View Javadoc

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