View Javadoc

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