View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.api.document.search;
17  
18  import org.kuali.rice.core.api.CoreConstants;
19  import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
20  import org.kuali.rice.core.api.mo.ModelBuilder;
21  import org.kuali.rice.kew.api.document.Document;
22  import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
23  import org.kuali.rice.kew.api.document.attribute.DocumentAttributeContract;
24  import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;
25  import org.w3c.dom.Element;
26  
27  import javax.xml.bind.annotation.XmlAccessType;
28  import javax.xml.bind.annotation.XmlAccessorType;
29  import javax.xml.bind.annotation.XmlAnyElement;
30  import javax.xml.bind.annotation.XmlElement;
31  import javax.xml.bind.annotation.XmlElementWrapper;
32  import javax.xml.bind.annotation.XmlRootElement;
33  import javax.xml.bind.annotation.XmlType;
34  import java.io.Serializable;
35  import java.util.ArrayList;
36  import java.util.Collection;
37  import java.util.Collections;
38  import java.util.List;
39  
40  /**
41   * An immutable data transfer object implementation of the {@link DocumentSearchResultContract}.  Instances of this
42   * class should be constructed using the nested {@link Builder} class.
43   *
44   * @author Kuali Rice Team (rice.collab@kuali.org)
45   */
46  @XmlRootElement(name = DocumentSearchResult.Constants.ROOT_ELEMENT_NAME)
47  @XmlAccessorType(XmlAccessType.NONE)
48  @XmlType(name = DocumentSearchResult.Constants.TYPE_NAME, propOrder = {
49      DocumentSearchResult.Elements.DOCUMENT,
50      DocumentSearchResult.Elements.DOCUMENT_ATTRIBUTES,
51      CoreConstants.CommonElements.FUTURE_ELEMENTS
52  })
53  public final class DocumentSearchResult extends AbstractDataTransferObject implements DocumentSearchResultContract {
54  
55      @XmlElement(name = Elements.DOCUMENT, required = false)
56      private final Document document;
57  
58      @XmlElementWrapper(name = Elements.DOCUMENT_ATTRIBUTES, required = true)
59      @XmlElement(name = Elements.DOCUMENT_ATTRIBUTE, required = false)
60      private final List<DocumentAttribute> documentAttributes;
61  
62      @SuppressWarnings("unused")
63      @XmlAnyElement
64      private final Collection<Element> _futureElements = null;
65  
66      /**
67       * Private constructor used only by JAXB.
68       */
69      @SuppressWarnings("unused")
70      private DocumentSearchResult() {
71          this.document = null;
72          this.documentAttributes = null;
73      }
74  
75      private DocumentSearchResult(Builder builder) {
76          this.document = builder.getDocument().build();
77          List<DocumentAttribute> documentAttributes = new ArrayList<DocumentAttribute>();
78          for (DocumentAttribute.AbstractBuilder<?> documentAttribute : builder.getDocumentAttributes()) {
79              documentAttributes.add(documentAttribute.build());
80          }
81          this.documentAttributes = Collections.unmodifiableList(documentAttributes);
82      }
83  
84      @Override
85      public Document getDocument() {
86          return this.document;
87      }
88  
89      @Override
90      public List<DocumentAttribute> getDocumentAttributes() {
91          return this.documentAttributes;
92      }
93  
94      /**
95       * Returns an unmodifiable list of all document attributes on this result which have the given name.  It is legal
96       * for a result to contain more than one attribute of the same name.  In these cases, this represents a document
97       * attribute which has more than one value.
98       *
99       * @param attributeName the attribute name of document attributes to retrieve
100      * @return an unmodifiable list of document attributes with the given name, will never be null but may be empty
101      */
102     public List<DocumentAttribute> getDocumentAttributeByName(String attributeName) {
103         List<DocumentAttribute> namedAttributes = new ArrayList<DocumentAttribute>();
104         for (DocumentAttribute attribute : getDocumentAttributes()) {
105             if (attribute.getName().equals(attributeName)) {
106                 namedAttributes.add(attribute);
107             }
108         }
109         return Collections.unmodifiableList(namedAttributes);
110     }
111 
112     /**
113      * Returns a single document attribute from this result which has the given name.  If there is more than one
114      * document attribute on this result with the given name, only a single one will be returned (though it is
115      * undeterministic which one will this will be).  If there are no attributes on this result with the given name
116      * then this method will return null.
117      *
118      * @param attributeName the attribute name of the document attribute to retrieve
119      * @return a single document attribute with the given name, or null if one does not exist
120      */
121     public DocumentAttribute getSingleDocumentAttributeByName(String attributeName) {
122         List<DocumentAttribute> namedAttributes = getDocumentAttributeByName(attributeName);
123         if (namedAttributes.isEmpty()) {
124             return null;
125         }
126         return namedAttributes.get(0);
127     }
128 
129     /**
130      * A builder which can be used to construct {@link DocumentSearchResult} instances.  Enforces the constraints of the
131      * {@link DocumentSearchResultContract}.
132      */
133     public final static class Builder implements Serializable, ModelBuilder, DocumentSearchResultContract {
134 
135         private Document.Builder document;
136         private List<DocumentAttribute.AbstractBuilder<?>> documentAttributes;
137 
138         private Builder(Document.Builder document) {
139             setDocument(document);
140             setDocumentAttributes(new ArrayList<DocumentAttribute.AbstractBuilder<?>>());
141         }
142 
143         /**
144          * Create a builder for the document search result and initialize it with the given document builder.
145          * Additionally initializes the list of document attribute builders on the new instance to an empty list.
146          *
147          * @param document the document builder with which to initialize the returned builder instance
148          *
149          * @return a builder instance initialized with the given document builder
150          *
151          * @throws IllegalArgumentException if the given document builder is null
152          */
153         public static Builder create(Document.Builder document) {
154             return new Builder(document);
155         }
156 
157         /**
158          * Creates a new builder instance initialized with copies of the properties from the given contract.
159          *
160          * @param contract the contract from which to copy properties
161          *
162          * @return a builder instance initialized with properties from the given contract
163          *
164          * @throws IllegalArgumentException if the given contract is null
165          */
166         public static Builder create(DocumentSearchResultContract contract) {
167             if (contract == null) {
168                 throw new IllegalArgumentException("contract was null");
169             }
170             Document.Builder documentBuilder = Document.Builder.create(contract.getDocument());
171             Builder builder = create(documentBuilder);
172             List<DocumentAttribute.AbstractBuilder<?>> documentAttributes = new ArrayList<DocumentAttribute.AbstractBuilder<?>>();
173             for (DocumentAttributeContract documentAttributeContract : contract.getDocumentAttributes()) {
174                 documentAttributes.add(DocumentAttributeFactory.loadContractIntoBuilder(documentAttributeContract));
175             }
176             builder.setDocumentAttributes(documentAttributes);
177             return builder;
178         }
179 
180         public DocumentSearchResult build() {
181             return new DocumentSearchResult(this);
182         }
183 
184         @Override
185         public Document.Builder getDocument() {
186             return this.document;
187         }
188 
189         @Override
190         public List<DocumentAttribute.AbstractBuilder<?>> getDocumentAttributes() {
191             return this.documentAttributes;
192         }
193 
194         public void setDocument(Document.Builder document) {
195             if (document == null) {
196                 throw new IllegalArgumentException("document was null");
197             }
198             this.document = document;
199         }
200 
201         public void setDocumentAttributes(List<DocumentAttribute.AbstractBuilder<?>> documentAttributes) {
202             this.documentAttributes = documentAttributes;
203         }
204 
205     }
206 
207     /**
208      * Defines some internal constants used on this class.
209      */
210     static class Constants {
211         final static String ROOT_ELEMENT_NAME = "documentSearchResult";
212         final static String TYPE_NAME = "DocumentSearchResultType";
213     }
214 
215     /**
216      * A private class which exposes constants which define the XML element names to use when this object is marshalled to XML.
217      */
218     static class Elements {
219         final static String DOCUMENT = "document";
220         final static String DOCUMENT_ATTRIBUTES = "documentAttributes";
221         final static String DOCUMENT_ATTRIBUTE = "documentAttribute";
222     }
223 
224 }