001/**
002 * Copyright 2005-2016 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 */
016package org.kuali.rice.kew.api.document.search;
017
018import org.apache.commons.collections.CollectionUtils;
019import org.kuali.rice.core.api.CoreConstants;
020import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
021import org.kuali.rice.core.api.mo.ModelBuilder;
022import org.kuali.rice.core.api.mo.ModelObjectUtils;
023import org.w3c.dom.Element;
024
025import javax.xml.bind.annotation.XmlAccessType;
026import javax.xml.bind.annotation.XmlAccessorType;
027import javax.xml.bind.annotation.XmlAnyElement;
028import javax.xml.bind.annotation.XmlElement;
029import javax.xml.bind.annotation.XmlElementWrapper;
030import javax.xml.bind.annotation.XmlRootElement;
031import javax.xml.bind.annotation.XmlType;
032import java.io.Serializable;
033import java.util.ArrayList;
034import java.util.Collection;
035import java.util.List;
036
037/**
038 * An immutable data transfer object implementation of the {@link DocumentSearchResultsContract}.  Instances of this
039 * class should be constructed using the nested {@link Builder} class.
040 *
041 * @author Kuali Rice Team (rice.collab@kuali.org)
042 */
043@XmlRootElement(name = DocumentSearchResults.Constants.ROOT_ELEMENT_NAME)
044@XmlAccessorType(XmlAccessType.NONE)
045@XmlType(name = DocumentSearchResults.Constants.TYPE_NAME, propOrder = {
046    DocumentSearchResults.Elements.SEARCH_RESULTS,
047    DocumentSearchResults.Elements.CRITERIA,
048    DocumentSearchResults.Elements.CRITERIA_MODIFIED,
049    DocumentSearchResults.Elements.OVER_THRESHOLD,
050    DocumentSearchResults.Elements.NUMBER_OF_SECURITY_FILTERED_RESULTS,
051    CoreConstants.CommonElements.FUTURE_ELEMENTS
052})
053public final class DocumentSearchResults extends AbstractDataTransferObject implements DocumentSearchResultsContract {
054
055    @XmlElementWrapper(name = Elements.SEARCH_RESULTS, required = true)
056    @XmlElement(name = Elements.SEARCH_RESULT, required = false)
057    private final List<DocumentSearchResult> searchResults;
058
059    @XmlElement(name = Elements.CRITERIA, required = true)
060    private final DocumentSearchCriteria criteria;
061
062    @XmlElement(name = Elements.CRITERIA_MODIFIED, required = true)
063    private final boolean criteriaModified;
064
065    @XmlElement(name = Elements.OVER_THRESHOLD, required = true)
066    private final boolean overThreshold;
067
068    @XmlElement(name = Elements.NUMBER_OF_SECURITY_FILTERED_RESULTS, required = true)
069    private final int numberOfSecurityFilteredResults;
070
071    @SuppressWarnings("unused")
072    @XmlAnyElement
073    private final Collection<Element> _futureElements = null;
074
075    /**
076     * Private constructor used only by JAXB.
077     */
078    @SuppressWarnings("unused")
079    private DocumentSearchResults() {
080        this.searchResults = null;
081        this.criteria = null;
082        this.criteriaModified = false;
083        this.overThreshold = false;
084        this.numberOfSecurityFilteredResults = 0;
085    }
086
087    private DocumentSearchResults(Builder builder) {
088        this.searchResults = ModelObjectUtils.buildImmutableCopy(builder.getSearchResults());
089        this.criteria = builder.getCriteria().build();
090        this.criteriaModified = builder.isCriteriaModified();
091        this.overThreshold = builder.isOverThreshold();
092        this.numberOfSecurityFilteredResults = builder.getNumberOfSecurityFilteredResults();
093    }
094
095    @Override
096    public List<DocumentSearchResult> getSearchResults() {
097        return this.searchResults;
098    }
099
100    @Override
101    public DocumentSearchCriteria getCriteria() {
102        return this.criteria;
103    }
104
105    @Override
106    public boolean isCriteriaModified() {
107        return this.criteriaModified;
108    }
109
110    @Override
111    public boolean isOverThreshold() {
112        return this.overThreshold;
113    }
114
115    @Override
116    public int getNumberOfSecurityFilteredResults() {
117        return this.numberOfSecurityFilteredResults;
118    }
119
120    /**
121     * A builder which can be used to construct {@link DocumentSearchResults} instances.  Enforces the constraints of
122     * the {@link DocumentSearchResultsContract}.
123     */
124    public final static class Builder implements Serializable, ModelBuilder, DocumentSearchResultsContract {
125
126        private List<DocumentSearchResult.Builder> searchResults;
127        private DocumentSearchCriteria.Builder criteria;
128        private boolean criteriaModified;
129        private boolean overThreshold;
130        private int numberOfSecurityFilteredResults;
131
132        private Builder(DocumentSearchCriteria.Builder criteria) {
133            setSearchResults(new ArrayList<DocumentSearchResult.Builder>());
134            setCriteria(criteria);
135            setCriteriaModified(false);
136            setOverThreshold(false);
137            setNumberOfSecurityFilteredResults(0);
138
139        }
140
141        /**
142         * Create a builder for the document search result and initialize it with the given document search criteria
143         * builder.  Additionally initializes {@code criteriaModified} to "false", {@code overThreshold} to "false",
144         * and {@code numberOfSecurityFilteredResults} to 0.
145         *
146         * @param criteria the document search criteria builder with which to initialize the returned builder instance
147         *
148         * @return a builder instance initialized with the given document search criteria builder
149         *
150         * @throws IllegalArgumentException if the given document search criteria builder is null
151         */
152        public static Builder create(DocumentSearchCriteria.Builder criteria) {
153            return new Builder(criteria);
154        }
155
156        /**
157         * Creates a new builder instance initialized with copies of the properties from the given contract.
158         *
159         * @param contract the contract from which to copy properties
160         *
161         * @return a builder instance initialized with properties from the given contract
162         *
163         * @throws IllegalArgumentException if the given contract is null
164         */
165        public static Builder create(DocumentSearchResultsContract contract) {
166            if (contract == null) {
167                throw new IllegalArgumentException("contract was null");
168            }
169            Builder builder = create(DocumentSearchCriteria.Builder.create(contract.getCriteria()));
170            if (!CollectionUtils.isEmpty(contract.getSearchResults())) {
171                for (DocumentSearchResultContract searchResultContract : contract.getSearchResults()) {
172                    builder.getSearchResults().add(DocumentSearchResult.Builder.create(searchResultContract));
173                }
174            }
175            builder.setCriteriaModified(contract.isCriteriaModified());
176            builder.setOverThreshold(contract.isOverThreshold());
177            builder.setNumberOfSecurityFilteredResults(contract.getNumberOfSecurityFilteredResults());
178            return builder;
179        }
180
181        public DocumentSearchResults build() {
182            return new DocumentSearchResults(this);
183        }
184
185        @Override
186        public List<DocumentSearchResult.Builder> getSearchResults() {
187            return this.searchResults;
188        }
189
190        @Override
191        public DocumentSearchCriteria.Builder getCriteria() {
192            return this.criteria;
193        }
194
195        @Override
196        public boolean isCriteriaModified() {
197            return this.criteriaModified;
198        }
199
200        @Override
201        public boolean isOverThreshold() {
202            return this.overThreshold;
203        }
204
205        @Override
206        public int getNumberOfSecurityFilteredResults() {
207            return this.numberOfSecurityFilteredResults;
208        }
209
210        public void setSearchResults(List<DocumentSearchResult.Builder> searchResults) {
211            this.searchResults = searchResults;
212        }
213
214        /**
215         * Sets the criteria builder on this builder to the given value.
216         *
217         * @param criteria the criteria builder to set, must not be null
218         *
219         * @throws IllegalArgumentException if criteria is null
220         */
221        public void setCriteria(DocumentSearchCriteria.Builder criteria) {
222            if (criteria == null) {
223                throw new IllegalArgumentException("criteria was null");
224            }
225            this.criteria = criteria;
226        }
227
228        public void setCriteriaModified(boolean criteriaModified) {
229            this.criteriaModified = criteriaModified;
230        }
231
232        public void setOverThreshold(boolean overThreshold) {
233            this.overThreshold = overThreshold;
234        }
235
236        public void setNumberOfSecurityFilteredResults(int numberOfSecurityFilteredResults) {
237            this.numberOfSecurityFilteredResults = numberOfSecurityFilteredResults;
238        }
239
240    }
241
242    /**
243     * Defines some internal constants used on this class.
244     */
245    static class Constants {
246        final static String ROOT_ELEMENT_NAME = "documentSearchResults";
247        final static String TYPE_NAME = "DocumentSearchResultsType";
248    }
249
250    /**
251     * A private class which exposes constants which define the XML element names to use when this object is marshalled to XML.
252     */
253    static class Elements {
254        final static String SEARCH_RESULTS = "searchResults";
255        final static String SEARCH_RESULT = "searchResult";
256        final static String CRITERIA = "criteria";
257        final static String CRITERIA_MODIFIED = "criteriaModified";
258        final static String OVER_THRESHOLD = "overThreshold";
259        final static String NUMBER_OF_SECURITY_FILTERED_RESULTS = "numberOfSecurityFilteredResults";
260    }
261
262}