View Javadoc

1   /**
2    * Copyright 2005-2013 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.krms.api.repository.term;
17  
18  import java.io.Serializable;
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.List;
23  
24  import javax.xml.bind.annotation.XmlAccessType;
25  import javax.xml.bind.annotation.XmlAccessorType;
26  import javax.xml.bind.annotation.XmlAnyElement;
27  import javax.xml.bind.annotation.XmlElement;
28  import javax.xml.bind.annotation.XmlElementWrapper;
29  import javax.xml.bind.annotation.XmlRootElement;
30  import javax.xml.bind.annotation.XmlType;
31  
32  import org.apache.commons.lang.StringUtils;
33  import org.kuali.rice.core.api.CoreConstants;
34  import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
35  import org.kuali.rice.core.api.mo.ModelBuilder;
36  import org.kuali.rice.krms.api.KrmsConstants;
37  import org.kuali.rice.krms.api.repository.BuilderUtils;
38  import org.kuali.rice.krms.api.repository.BuilderUtils.Transformer;
39  import org.kuali.rice.krms.api.repository.category.CategoryDefinition;
40  import org.kuali.rice.krms.api.repository.category.CategoryDefinitionContract;
41  
42  /**
43   * Immutable DTO for TermSpecifications.  Construction must be done via the {@link Builder} inner class.
44   * 
45   * @author Kuali Rice Team (rice.collab@kuali.org)
46   *
47   */
48  @XmlRootElement(name = TermSpecificationDefinition.Constants.ROOT_ELEMENT_NAME)
49  @XmlAccessorType(XmlAccessType.NONE)
50  @XmlType(name = TermSpecificationDefinition.Constants.TYPE_NAME, propOrder = {
51  		TermSpecificationDefinition.Elements.ID,
52  		TermSpecificationDefinition.Elements.NAME,
53          TermSpecificationDefinition.Elements.NAMESPACE,
54          TermSpecificationDefinition.Elements.TYPE,
55          TermSpecificationDefinition.Elements.DESCRIPTION,
56          TermSpecificationDefinition.Elements.ACTIVE,
57          CoreConstants.CommonElements.VERSION_NUMBER,
58          TermSpecificationDefinition.Elements.CATEGORIES,
59          "contextIds", // has to match the field name -- the element wrapper name does not
60          CoreConstants.CommonElements.FUTURE_ELEMENTS
61  })
62  public final class TermSpecificationDefinition extends AbstractDataTransferObject implements TermSpecificationDefinitionContract {
63  	
64  	private static final long serialVersionUID = 1L;
65  	
66  	@XmlElement(name = Elements.ID, required=false)
67  	private final String id;
68      @XmlElement(name = Elements.NAME, required=true)
69      private final String name;
70      @XmlElement(name = Elements.NAMESPACE, required=true)
71      private final String namespace;
72  	@XmlElement(name = Elements.TYPE, required=true)
73  	private final String type;
74      @XmlElement(name = Elements.DESCRIPTION, required=false)
75      private final String description;
76      @XmlElement(name = Elements.ACTIVE, required = false)
77      private final boolean active;
78      @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
79      private final Long versionNumber;
80  
81      @XmlElementWrapper(name = Elements.CATEGORIES, required = false)
82      @XmlElement(name = Elements.CATEGORY, required = false)
83      private final List<CategoryDefinition> categories;
84  
85  
86      @XmlElementWrapper(name = Elements.CONTEXTS, required = false)
87      @XmlElement(name = Elements.CONTEXT_ID, required = false)
88      private final List<String> contextIds;
89  
90  	@SuppressWarnings("unused")
91      @XmlAnyElement
92      private final Collection<org.w3c.dom.Element> _futureElements = null;
93  	
94  	/**
95  	 * For JAXB use only, shouldn't ever be invoked directly
96  	 */
97  	private TermSpecificationDefinition() {
98  		id = null;
99  		name = null;
100         namespace = null;
101 		type = null;
102         description = null;
103         active = true;
104         versionNumber = null;
105         this.categories = null;
106         this.contextIds = null;
107 	}
108 	
109 	/**
110 	 * Private constructor enforces use of Builder
111 	 * 
112 	 * @param b the builder to use
113 	 */
114 	private TermSpecificationDefinition(Builder b) {
115 		id = b.getId();
116 		name = b.getName();
117         namespace = b.getNamespace();
118 		type = b.getType();
119         description = b.getDescription();
120         active = b.isActive();
121 		versionNumber = b.getVersionNumber();
122         this.categories = constructCategories(b.getCategories());
123         this.contextIds = Collections.unmodifiableList(new ArrayList(b.getContextIds()));
124 	}
125 
126     private static List<CategoryDefinition> constructCategories(List<CategoryDefinition.Builder> categoryBuilders) {
127     	List<CategoryDefinition> categories = new ArrayList<CategoryDefinition>();
128     	if (categoryBuilders != null) {
129     		for (CategoryDefinition.Builder categoryBuilder : categoryBuilders) {
130     			categories.add(categoryBuilder.build());
131     		}
132     	}
133     	return categories;
134     }
135 
136 	/**
137 	 * Builder for the {@link TermSpecificationDefinition} immutable DTO.  Instantiate using static factory method(s).
138 	 * 
139 	 * @author Kuali Rice Team (rice.collab@kuali.org)
140 	 */
141 	public static class Builder implements TermSpecificationDefinitionContract, ModelBuilder, Serializable {
142 		
143 		private static final long serialVersionUID = 1L;
144 		
145 		private String termSpecificationId;
146 		private String name;
147         private String namespace;
148 		private String type;
149         private String description;
150         private boolean active;
151         private Long versionNumber;
152         private List<CategoryDefinition.Builder> categories;
153         private List<String> contextIds;
154 
155 		private static final String NON_NULL_NON_EMPTY_ERROR =  " must be non-null and must contain non-whitespace chars"; 
156 
157 		/**
158 		 * {@link Transformer} to ease converting lists to Builder types
159 		 */
160 		public static final Transformer<TermSpecificationDefinitionContract, TermSpecificationDefinition.Builder>
161 		toBuilder = new BuilderUtils.Transformer<TermSpecificationDefinitionContract, TermSpecificationDefinition.Builder>() {
162 			public TermSpecificationDefinition.Builder transform(TermSpecificationDefinitionContract input) {
163 				return TermSpecificationDefinition.Builder.create(input);
164 			}
165 		};
166 		
167 		private Builder(String termSpecificationId, String name, String namespace, String type) {
168 			// weird to use setters in constructor .. oh well.
169 			setId(termSpecificationId);
170 			setNamespace(namespace);
171 			setName(name);
172 			setType(type);
173             setActive(true);
174             setCategories(new ArrayList<CategoryDefinition.Builder>());
175             setContextIds(new ArrayList<String>());
176 		}
177 		
178 		/**
179 		 * static factory for a {@link Builder} from a complete set of field values for this object.
180 		 * 
181 		 *
182          * @param termSpecificationId the primary key field.  Must be null for service methods that
183          * create {@link org.kuali.rice.krms.api.repository.term.TermSpecificationDefinitionContract}s, and must be non-null & contain non-whitespace
184          * chars otherwise.
185          * @param name the name for the {@link org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition}.  Must be non-null;.
186          * @param namespace the namespace for the {@link org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition}.  Must be non-null & contain non-whitespace.
187          *@param type the type for the {@link org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition}  @return a {@link Builder} object
188 		 * @throws IllegalArgumentException if invalid parameters are supplied.
189 		 */
190 		public static Builder create(String termSpecificationId, String name, String namespace, String type) {
191 			return new Builder(termSpecificationId, name, namespace, type);
192 		}
193 		
194 		/**
195 		 * static factory for a {@link Builder} from a {@link TermSpecificationDefinitionContract}.
196 		 * 
197 		 * @param termSpecification may not be null;
198 		 * @throws IllegalArgumentException if termSpecification is null, or violates the field invariants of the {@link Builder}.
199 		 */
200 		public static Builder create(TermSpecificationDefinitionContract termSpecification) {
201 			if (termSpecification == null) throw new IllegalArgumentException("termSpecification must be non-null");
202 			Builder builder = new Builder(termSpecification.getId(), termSpecification.getName(), termSpecification.getNamespace(),
203                     termSpecification.getType());
204             builder.setDescription(termSpecification.getDescription());
205             builder.setActive(termSpecification.isActive());
206 			builder.setVersionNumber(termSpecification.getVersionNumber());
207             for (CategoryDefinitionContract category : termSpecification.getCategories()) {
208                 builder.getCategories().add(CategoryDefinition.Builder.create(category));
209             }
210             if (termSpecification.getContextIds() != null) {
211                 builder.getContextIds().addAll(termSpecification.getContextIds());
212             }
213 
214 			return builder;
215 		}
216 
217         public void setDescription(String description) {
218             this.description = description;
219         }
220 
221         // Setters
222 		
223 		/**
224 		 * @param termSpecificationId the key for this {@link TermSpecificationDefinition}.  Must be null for
225 		 * service methods that create {@link TermSpecificationDefinitionContract}s, and otherwise must be non-null & contain 
226 		 * non-whitespace chars.
227 		 */
228 		public void setId(String termSpecificationId) {
229 			if (termSpecificationId != null && StringUtils.isBlank(termSpecificationId))
230 				throw new IllegalArgumentException("termSpecificationId must contain non-whitespace chars");
231 			this.termSpecificationId = termSpecificationId;
232 		}
233 		
234 		/**
235 		 * @param namespace the namespace to set.  Must be non-null and contain non-whitespace chars;
236 		 */
237 		public void setNamespace(String namespace) {
238 			if (StringUtils.isBlank(namespace)) {
239 				throw new IllegalArgumentException("namespace" + NON_NULL_NON_EMPTY_ERROR);
240 			}
241 			this.namespace = namespace;
242 		}
243 		
244 		/**
245 		 * @param name the name to set.  Must be non-null and contain non-whitespace chars;
246 		 */
247 		public void setName(String name) {
248 			if (StringUtils.isBlank(name)) {
249 				throw new IllegalArgumentException("name" + NON_NULL_NON_EMPTY_ERROR);
250 			}
251 			this.name = name;
252 		}
253 		/**
254 		 * @param type the type to set. Must be non-null and contain non-whitespace chars;
255 		 */
256 		public void setType(String type) {
257 			if (StringUtils.isBlank(type)) {
258 				throw new IllegalArgumentException("type" + NON_NULL_NON_EMPTY_ERROR);
259 			}
260 			this.type = type;
261 		}
262 		
263 		/**
264 		 * @param versionNumber the versionNumber to set.  May be null.
265 		 */
266         public void setVersionNumber(Long versionNumber){
267             this.versionNumber = versionNumber;
268         }
269 
270         public void setActive(boolean active) {
271             this.active = active;
272         }
273 
274         /**
275          * @param categories the categories to set.  May not be null but can be an empty set.
276          */
277         public void setCategories(List<CategoryDefinition.Builder> categories) {
278             if (categories == null) {
279                 throw new IllegalArgumentException("categories was null");
280             }
281             this.categories = categories;
282         }
283 
284         /**
285          * @param contextIds the contextIds to set.  May not be null but may be empty.
286          */
287         public void setContextIds(List<String> contextIds) {
288             if (contextIds == null) {
289                 throw new IllegalArgumentException("contextIds was null");
290             }
291             this.contextIds = contextIds;
292         }
293 
294         // Getters
295 		
296 		/**
297 		 * @return the termSpecificationId
298 		 */
299 		@Override
300 		public String getId() {
301 			return this.termSpecificationId;
302 		}
303 
304 		/**
305 		 * @return the namespace
306 		 */
307 		@Override
308 		public String getNamespace() {
309 			return this.namespace;
310 		}
311 
312 		/**
313 		 * @return the name
314 		 */
315 		@Override
316 		public String getName() {
317 			return this.name;
318 		}
319 
320 		/**
321 		 * @return the type
322 		 */
323 		@Override
324 		public String getType() {
325 			return this.type;
326 		}
327 
328         @Override
329         public String getDescription() {
330             return this.description;
331         }
332 
333         /**
334 		 * @return the version number
335 		 */
336         @Override
337         public Long getVersionNumber() {
338             return this.versionNumber;
339         }
340 
341         @Override
342         public boolean isActive() {
343             return active;
344         }
345 
346         /**
347          * @return the categories
348          */
349         @Override
350         public List<CategoryDefinition.Builder> getCategories() {
351             return this.categories;
352         }
353 
354         @Override
355         public List<String> getContextIds() {
356             return contextIds;
357         }
358 
359         /**
360 		 * Constructs a {@link TermSpecificationDefinition}
361 		 * @see org.kuali.rice.core.api.mo.ModelBuilder#build()
362 		 */
363 		@Override
364 		public TermSpecificationDefinition build() {
365 			return new TermSpecificationDefinition(this);
366 		}
367 	}
368 
369 	/**
370 	 * This value will be non-null for persisted  
371 	 * @see org.kuali.rice.krms.api.repository.term.TermSpecificationDefinitionContract#getId()
372 	 */
373 	@Override
374 	public String getId() {
375 		return id;
376 	}
377 
378 	/**
379 	 * @see org.kuali.rice.krms.api.repository.term.TermSpecificationDefinitionContract#getName()
380 	 */
381 	@Override
382 	public String getName() {
383 		return name;
384 	}
385 
386     @Override
387     public String getNamespace() {
388         return namespace;
389     }
390 
391 	/**
392 	 * @see org.kuali.rice.krms.api.repository.term.TermSpecificationDefinitionContract#getType()
393 	 */
394 	@Override
395 	public String getType() {
396 		return type;
397 	}
398 
399     @Override
400     public String getDescription() {
401         return description;
402     }
403 
404     @Override
405     public boolean isActive() {
406         return active;
407     }
408 
409     /**
410 	 * @see org.kuali.rice.core.api.mo.common.Versioned#getVersionNumber()
411 	 */
412     @Override
413     public Long getVersionNumber() {
414         return versionNumber;
415     }
416 
417     /**
418      * @see TermSpecificationDefinitionContract#getCategories()
419      */
420     @Override
421     public List<CategoryDefinition> getCategories() {
422         return Collections.unmodifiableList(categories);
423     }
424 
425     @Override
426     public List<String> getContextIds() {
427         return contextIds;
428     }
429 
430     /**
431 	 * Defines some internal constants used on this class.
432 	 */
433 	static class Constants {
434 		final static String ROOT_ELEMENT_NAME = "termSpecification";
435 		final static String TYPE_NAME = "TermSpecificationType";
436 	}
437 	
438 	static class Elements {
439 		public static final String ID = "id";
440 		public static final String NAME = "name";
441         public final static String NAMESPACE = "namespace";
442         public static final String TYPE = "type";
443         public static final String DESCRIPTION = "description";
444         public static final String ACTIVE = "active";
445         public final static String CATEGORIES = "categories";
446         public final static String CATEGORY = "category";
447         public final static String CONTEXTS = "contexts";
448         public final static String CONTEXT_ID = "contextId";
449     }
450 
451     public static class Cache {
452         public static final String NAME = KrmsConstants.Namespaces.KRMS_NAMESPACE_2_0 + "/" + TermSpecificationDefinition.Constants.TYPE_NAME;
453     }
454 }