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.krms.api.repository.term;
017    
018    import java.io.Serializable;
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.Collections;
022    import java.util.List;
023    
024    import javax.xml.bind.annotation.XmlAccessType;
025    import javax.xml.bind.annotation.XmlAccessorType;
026    import javax.xml.bind.annotation.XmlAnyElement;
027    import javax.xml.bind.annotation.XmlElement;
028    import javax.xml.bind.annotation.XmlElementWrapper;
029    import javax.xml.bind.annotation.XmlRootElement;
030    import javax.xml.bind.annotation.XmlType;
031    
032    import org.apache.commons.lang.StringUtils;
033    import org.kuali.rice.core.api.CoreConstants;
034    import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
035    import org.kuali.rice.core.api.mo.ModelBuilder;
036    import org.kuali.rice.krms.api.repository.BuilderUtils;
037    import org.kuali.rice.krms.api.repository.BuilderUtils.Transformer;
038    import org.kuali.rice.krms.api.repository.category.CategoryDefinition;
039    import org.kuali.rice.krms.api.repository.category.CategoryDefinitionContract;
040    
041    /**
042     * Immutable DTO for TermSpecifications.  Construction must be done via the {@link Builder} inner class.
043     * 
044     * @author Kuali Rice Team (rice.collab@kuali.org)
045     *
046     */
047    @XmlRootElement(name = TermSpecificationDefinition.Constants.ROOT_ELEMENT_NAME)
048    @XmlAccessorType(XmlAccessType.NONE)
049    @XmlType(name = TermSpecificationDefinition.Constants.TYPE_NAME, propOrder = {
050                    TermSpecificationDefinition.Elements.ID,
051                    TermSpecificationDefinition.Elements.NAME,
052            TermSpecificationDefinition.Elements.NAMESPACE,
053            TermSpecificationDefinition.Elements.TYPE,
054            TermSpecificationDefinition.Elements.DESCRIPTION,
055            TermSpecificationDefinition.Elements.ACTIVE,
056            CoreConstants.CommonElements.VERSION_NUMBER,
057            TermSpecificationDefinition.Elements.CATEGORIES,
058                    CoreConstants.CommonElements.FUTURE_ELEMENTS
059    })
060    public final class TermSpecificationDefinition extends AbstractDataTransferObject implements TermSpecificationDefinitionContract {
061            
062            private static final long serialVersionUID = 1L;
063            
064            @XmlElement(name = Elements.ID, required=false)
065            private final String id;
066        @XmlElement(name = Elements.NAME, required=true)
067        private final String name;
068        @XmlElement(name = Elements.NAMESPACE, required=true)
069        private final String namespace;
070            @XmlElement(name = Elements.TYPE, required=true)
071            private final String type;
072        @XmlElement(name = Elements.DESCRIPTION, required=false)
073        private final String description;
074        @XmlElement(name = Elements.ACTIVE, required = false)
075        private final boolean active;
076        @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
077        private final Long versionNumber;
078    
079        @XmlElementWrapper(name = Elements.CATEGORIES, required = false)
080        @XmlElement(name = Elements.CATEGORY, required = false)
081        private final List<CategoryDefinition> categories;
082    
083            
084            @SuppressWarnings("unused")
085        @XmlAnyElement
086        private final Collection<org.w3c.dom.Element> _futureElements = null;
087            
088            /**
089             * For JAXB use only, shouldn't ever be invoked directly
090             */
091            private TermSpecificationDefinition() {
092                    id = null;
093                    name = null;
094            namespace = null;
095                    type = null;
096            description = null;
097            active = true;
098            versionNumber = null;
099            this.categories = null;
100            }
101            
102            /**
103             * Private constructor enforces use of Builder
104             * 
105             * @param b the builder to use
106             */
107            private TermSpecificationDefinition(Builder b) {
108                    id = b.getId();
109                    name = b.getName();
110            namespace = b.getNamespace();
111                    type = b.getType();
112            description = b.getDescription();
113            active = b.isActive();
114                    versionNumber = b.getVersionNumber();
115            this.categories = constructCategories(b.getCategories());
116            }
117    
118        private static List<CategoryDefinition> constructCategories(List<CategoryDefinition.Builder> categoryBuilders) {
119            List<CategoryDefinition> categories = new ArrayList<CategoryDefinition>();
120            if (categoryBuilders != null) {
121                    for (CategoryDefinition.Builder categoryBuilder : categoryBuilders) {
122                            categories.add(categoryBuilder.build());
123                    }
124            }
125            return categories;
126        }
127    
128            /**
129             * Builder for the {@link TermSpecificationDefinition} immutable DTO.  Instantiate using static factory method(s).
130             * 
131             * @author Kuali Rice Team (rice.collab@kuali.org)
132             */
133            public static class Builder implements TermSpecificationDefinitionContract, ModelBuilder, Serializable {
134                    
135                    private static final long serialVersionUID = 1L;
136                    
137                    private String termSpecificationId;
138                    private String name;
139            private String namespace;
140                    private String type;
141            private String description;
142            private boolean active;
143            private Long versionNumber;
144            private List<CategoryDefinition.Builder> categories;
145    
146                    private static final String NON_NULL_NON_EMPTY_ERROR =  " must be non-null and must contain non-whitespace chars"; 
147    
148                    /**
149                     * {@link Transformer} to ease converting lists to Builder types
150                     */
151                    public static final Transformer<TermSpecificationDefinitionContract, TermSpecificationDefinition.Builder>
152                    toBuilder = new BuilderUtils.Transformer<TermSpecificationDefinitionContract, TermSpecificationDefinition.Builder>() {
153                            public TermSpecificationDefinition.Builder transform(TermSpecificationDefinitionContract input) {
154                                    return TermSpecificationDefinition.Builder.create(input);
155                            }
156                    };
157                    
158                    private Builder(String termSpecificationId, String name, String namespace, String type) {
159                            // weird to use setters in constructor .. oh well.
160                            setId(termSpecificationId);
161                            setNamespace(namespace);
162                            setName(name);
163                            setType(type);
164                setActive(true);
165                setCategories(new ArrayList<CategoryDefinition.Builder>());
166                    }
167                    
168                    /**
169                     * static factory for a {@link Builder} from a complete set of field values for this object.
170                     * 
171                     *
172             * @param termSpecificationId the primary key field.  Must be null for service methods that
173             * create {@link org.kuali.rice.krms.api.repository.term.TermSpecificationDefinitionContract}s, and must be non-null & contain non-whitespace
174             * chars otherwise.
175             * @param name the name for the {@link org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition}.  Must be non-null;.
176             * @param namespace the namespace for the {@link org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition}.  Must be non-null & contain non-whitespace.
177             *@param type the type for the {@link org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition}  @return a {@link Builder} object
178                     * @throws IllegalArgumentException if invalid parameters are supplied.
179                     */
180                    public static Builder create(String termSpecificationId, String name, String namespace, String type) {
181                            return new Builder(termSpecificationId, name, namespace, type);
182                    }
183                    
184                    /**
185                     * static factory for a {@link Builder} from a {@link TermSpecificationDefinitionContract}.
186                     * 
187                     * @param termSpecification may not be null;
188                     * @throws IllegalArgumentException if termSpecification is null, or violates the field invariants of the {@link Builder}.
189                     */
190                    public static Builder create(TermSpecificationDefinitionContract termSpecification) {
191                            if (termSpecification == null) throw new IllegalArgumentException("termSpecification must be non-null");
192                            Builder builder =new Builder(termSpecification.getId(), termSpecification.getName(), termSpecification.getNamespace(),
193                        termSpecification.getType());
194                builder.setDescription(termSpecification.getDescription());
195                builder.setActive(termSpecification.isActive());
196                            builder.setVersionNumber(termSpecification.getVersionNumber());
197                for (CategoryDefinitionContract category : termSpecification.getCategories()) {
198                    builder.getCategories().add(CategoryDefinition.Builder.create(category));
199                }
200    
201                            return builder;
202                    }
203    
204            public void setDescription(String description) {
205                this.description = description;
206            }
207    
208            // Setters
209                    
210                    /**
211                     * @param termSpecificationId the key for this {@link TermSpecificationDefinition}.  Must be null for
212                     * service methods that create {@link TermSpecificationDefinitionContract}s, and otherwise must be non-null & contain 
213                     * non-whitespace chars.
214                     */
215                    public void setId(String termSpecificationId) {
216                            if (termSpecificationId != null && StringUtils.isBlank(termSpecificationId))
217                                    throw new IllegalArgumentException("termSpecificationId must contain non-whitespace chars");
218                            this.termSpecificationId = termSpecificationId;
219                    }
220                    
221                    /**
222                     * @param namespace the namespace to set.  Must be non-null and contain non-whitespace chars;
223                     */
224                    public void setNamespace(String namespace) {
225                            if (StringUtils.isBlank(namespace)) {
226                                    throw new IllegalArgumentException("namespace" + NON_NULL_NON_EMPTY_ERROR);
227                            }
228                            this.namespace = namespace;
229                    }
230                    
231                    /**
232                     * @param name the name to set.  Must be non-null and contain non-whitespace chars;
233                     */
234                    public void setName(String name) {
235                            if (StringUtils.isBlank(name)) {
236                                    throw new IllegalArgumentException("name" + NON_NULL_NON_EMPTY_ERROR);
237                            }
238                            this.name = name;
239                    }
240                    /**
241                     * @param type the type to set. Must be non-null and contain non-whitespace chars;
242                     */
243                    public void setType(String type) {
244                            if (StringUtils.isBlank(type)) {
245                                    throw new IllegalArgumentException("type" + NON_NULL_NON_EMPTY_ERROR);
246                            }
247                            this.type = type;
248                    }
249                    
250                    /**
251                     * @param versionNumber the versionNumber to set.  May be null.
252                     */
253            public void setVersionNumber(Long versionNumber){
254                this.versionNumber = versionNumber;
255            }
256    
257            public void setActive(boolean active) {
258                this.active = active;
259            }
260    
261            /**
262             * @param categories the categories to set.  May not be null but can be an empty set.
263             */
264            public void setCategories(List<CategoryDefinition.Builder> categories) {
265                if (categories == null) {
266                    throw new IllegalArgumentException("categories was null");
267                }
268                this.categories = categories;
269            }
270            
271                    // Getters
272                    
273                    /**
274                     * @return the termSpecificationId
275                     */
276                    @Override
277                    public String getId() {
278                            return this.termSpecificationId;
279                    }
280    
281                    /**
282                     * @return the namespace
283                     */
284                    @Override
285                    public String getNamespace() {
286                            return this.namespace;
287                    }
288    
289                    /**
290                     * @return the name
291                     */
292                    @Override
293                    public String getName() {
294                            return this.name;
295                    }
296    
297                    /**
298                     * @return the type
299                     */
300                    @Override
301                    public String getType() {
302                            return this.type;
303                    }
304    
305            @Override
306            public String getDescription() {
307                return this.description;
308            }
309    
310            /**
311                     * @return the version number
312                     */
313            @Override
314            public Long getVersionNumber() {
315                return this.versionNumber;
316            }
317    
318            @Override
319            public boolean isActive() {
320                return active;
321            }
322    
323            /**
324             * @return the categories
325             */
326            @Override
327            public List<CategoryDefinition.Builder> getCategories() {
328                return this.categories;
329            }
330    
331    
332                    /**
333                     * Constructs a {@link TermSpecificationDefinition}
334                     * @see org.kuali.rice.core.api.mo.ModelBuilder#build()
335                     */
336                    @Override
337                    public TermSpecificationDefinition build() {
338                            return new TermSpecificationDefinition(this);
339                    }
340            }
341    
342            /**
343             * This value will be non-null for persisted  
344             * @see org.kuali.rice.krms.api.repository.term.TermSpecificationDefinitionContract#getId()
345             */
346            @Override
347            public String getId() {
348                    return id;
349            }
350    
351            /**
352             * @see org.kuali.rice.krms.api.repository.term.TermSpecificationDefinitionContract#getName()
353             */
354            @Override
355            public String getName() {
356                    return name;
357            }
358    
359        @Override
360        public String getNamespace() {
361            return namespace;
362        }
363    
364            /**
365             * @see org.kuali.rice.krms.api.repository.term.TermSpecificationDefinitionContract#getType()
366             */
367            @Override
368            public String getType() {
369                    return type;
370            }
371    
372        @Override
373        public String getDescription() {
374            return description;
375        }
376    
377        @Override
378        public boolean isActive() {
379            return active;
380        }
381    
382        /**
383             * @see org.kuali.rice.core.api.mo.common.Versioned#getVersionNumber()
384             */
385        @Override
386        public Long getVersionNumber() {
387            return versionNumber;
388        }
389    
390        /**
391         * @see TermSpecificationDefinitionContract#getCategories()
392         */
393        @Override
394        public List<CategoryDefinition> getCategories() {
395            return Collections.unmodifiableList(categories);
396        }
397            
398            /**
399             * Defines some internal constants used on this class.
400             */
401            static class Constants {
402                    final static String ROOT_ELEMENT_NAME = "termSpecification";
403                    final static String TYPE_NAME = "TermSpecificationType";
404            }
405            
406            static class Elements {
407                    public static final String ID = "id";
408                    public static final String NAME = "name";
409            public final static String NAMESPACE = "namespace";
410            public static final String TYPE = "type";
411            public static final String DESCRIPTION = "description";
412            public static final String ACTIVE = "active";
413            public final static String CATEGORIES = "categories";
414            public final static String CATEGORY = "category";
415        }
416            
417    
418    }