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 }