001    /**
002     * Copyright 2005-2012 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.kew.framework.document.search;
017    
018    import java.io.Serializable;
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.List;
022    import javax.xml.bind.annotation.XmlAccessType;
023    import javax.xml.bind.annotation.XmlAccessorType;
024    import javax.xml.bind.annotation.XmlAnyElement;
025    import javax.xml.bind.annotation.XmlElement;
026    import javax.xml.bind.annotation.XmlElementWrapper;
027    import javax.xml.bind.annotation.XmlRootElement;
028    import javax.xml.bind.annotation.XmlType;
029    
030    import org.apache.commons.lang.StringUtils;
031    import org.kuali.rice.core.api.CoreConstants;
032    import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
033    import org.kuali.rice.core.api.mo.ModelBuilder;
034    import org.kuali.rice.core.api.mo.ModelObjectUtils;
035    import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
036    import org.kuali.rice.kew.api.document.attribute.DocumentAttributeContract;
037    import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;
038    import org.w3c.dom.Element;
039    
040    /**
041     * An immutable data transfer object implementation of the {@link DocumentSearchResultValueContract}.
042     * Instances of this class should be constructed using the nested {@link Builder} class.
043     *
044     * @author Kuali Rice Team (rice.collab@kuali.org)
045     */
046    @XmlRootElement(name = DocumentSearchResultValue.Constants.ROOT_ELEMENT_NAME)
047    @XmlAccessorType(XmlAccessType.NONE)
048    @XmlType(name = DocumentSearchResultValue.Constants.TYPE_NAME, propOrder = {
049        DocumentSearchResultValue.Elements.DOCUMENT_ID,
050        DocumentSearchResultValue.Elements.DOCUMENT_ATTRIBUTES,
051        CoreConstants.CommonElements.FUTURE_ELEMENTS
052    })
053    public final class DocumentSearchResultValue extends AbstractDataTransferObject
054            implements DocumentSearchResultValueContract {
055    
056        @XmlElement(name = Elements.DOCUMENT_ID, required = true)
057        private final String documentId;
058    
059        @XmlElementWrapper(name = Elements.DOCUMENT_ATTRIBUTES, required = false)
060        @XmlElement(name = Elements.DOCUMENT_ATTRIBUTE, required = false)
061        private final List<DocumentAttribute> documentAttributes;
062        
063        @SuppressWarnings("unused")
064        @XmlAnyElement
065        private final Collection<Element> _futureElements = null;
066    
067        /**
068         * Private constructor used only by JAXB.
069         */
070        @SuppressWarnings("unused")
071        private DocumentSearchResultValue() {
072            this.documentId = null;
073            this.documentAttributes = null;
074        }
075    
076        private DocumentSearchResultValue(Builder builder) {
077            this.documentId = builder.getDocumentId();
078            this.documentAttributes = ModelObjectUtils.buildImmutableCopy(builder.getDocumentAttributes());
079        }
080    
081        @Override
082        public String getDocumentId() {
083            return this.documentId;
084        }
085    
086        @Override
087        public List<DocumentAttribute> getDocumentAttributes() {
088            return this.documentAttributes;
089        }
090    
091        /**
092         * A builder which can be used to construct {@link DocumentSearchResultValue} instances.  Enforces the constraints
093         * of the {@link DocumentSearchResultValueContract}.
094         */
095        public final static class Builder implements Serializable, ModelBuilder, DocumentSearchResultValueContract {
096    
097            private String documentId;
098            private List<DocumentAttribute.AbstractBuilder<?>> documentAttributes;
099    
100            private Builder(String documentId) {
101                setDocumentId(documentId);
102                setDocumentAttributes(new ArrayList<DocumentAttribute.AbstractBuilder<?>>());
103            }
104    
105            /**
106             * Creates a new builder instance initialized with the given document id.  The list of document attributes on
107             * this builder is initialized to an empty list.
108             *
109             * @param documentId the id of the document with which to initialize this builder, must not be a null or blank
110             * value
111             *
112             * @return a new builder instance initialized with the given document id
113             */
114            public static Builder create(String documentId) {
115                return new Builder(documentId);
116            }
117    
118            /**
119             * Creates a new builder instance initialized with copies of the properties from the given contract.
120             *
121             * @param contract the contract from which to copy properties
122             *
123             * @return a builder instance initialized with properties from the given contract
124             *
125             * @throws IllegalArgumentException if the given contract is null
126             */
127            public static Builder create(DocumentSearchResultValueContract contract) {
128                if (contract == null) {
129                    throw new IllegalArgumentException("contract was null");
130                }
131                Builder builder = create(contract.getDocumentId());
132                if (contract.getDocumentAttributes() != null) {
133                    for (DocumentAttributeContract documentAttribute : contract.getDocumentAttributes()) {
134                        builder.getDocumentAttributes().add(DocumentAttributeFactory.loadContractIntoBuilder(documentAttribute));
135                    }
136                }
137                return builder;
138            }
139    
140            @Override
141            public DocumentSearchResultValue build() {
142                return new DocumentSearchResultValue(this);
143            }
144    
145            @Override
146            public String getDocumentId() {
147                return this.documentId;
148            }
149    
150            @Override
151            public List<DocumentAttribute.AbstractBuilder<?>> getDocumentAttributes() {
152                return this.documentAttributes;
153            }
154    
155            /**
156             * Sets the document id on this builder to the given value.  The given document id must not be a null or blank
157             * value.
158             *
159             * @param documentId the id of the document to set on this builder, must not be a null or blank value
160             *
161             * @throws IllegalArgumentException if documentId is a null or blank value
162             */
163            public void setDocumentId(String documentId) {
164                if (StringUtils.isBlank(documentId)) {
165                    throw new IllegalArgumentException("documentId was null or blank");
166                }
167                this.documentId = documentId;
168            }
169    
170            /**
171             * Sets the list of document attribute builders on this builder to the given list.
172             *
173             * @param documentAttributes the list of document attribute builders to set on this builder
174             */
175            public void setDocumentAttributes(List<DocumentAttribute.AbstractBuilder<?>> documentAttributes) {
176                this.documentAttributes = documentAttributes;
177            }
178    
179        }
180    
181        /**
182         * Defines some internal constants used on this class.
183         */
184        static class Constants {
185            final static String ROOT_ELEMENT_NAME = "documentSearchResultValue";
186            final static String TYPE_NAME = "DocumentSearchResultValueType";
187        }
188    
189        /**
190         * A private class which exposes constants which define the XML element names to use when this object is marshalled
191         * to XML.
192         */
193        static class Elements {
194            final static String DOCUMENT_ID = "documentId";
195            final static String DOCUMENT_ATTRIBUTES = "documentAttributes";
196            final static String DOCUMENT_ATTRIBUTE = "documentAttribute";
197        }
198    
199    }