001 /**
002 * Copyright 2005-2013 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.KrmsConstants;
037 import org.kuali.rice.krms.api.repository.BuilderUtils;
038 import org.kuali.rice.krms.api.repository.BuilderUtils.Transformer;
039 import org.kuali.rice.krms.api.repository.category.CategoryDefinition;
040 import org.kuali.rice.krms.api.repository.category.CategoryDefinitionContract;
041
042 /**
043 * Immutable DTO for TermSpecifications. Construction must be done via the {@link Builder} inner class.
044 *
045 * @author Kuali Rice Team (rice.collab@kuali.org)
046 *
047 */
048 @XmlRootElement(name = TermSpecificationDefinition.Constants.ROOT_ELEMENT_NAME)
049 @XmlAccessorType(XmlAccessType.NONE)
050 @XmlType(name = TermSpecificationDefinition.Constants.TYPE_NAME, propOrder = {
051 TermSpecificationDefinition.Elements.ID,
052 TermSpecificationDefinition.Elements.NAME,
053 TermSpecificationDefinition.Elements.NAMESPACE,
054 TermSpecificationDefinition.Elements.TYPE,
055 TermSpecificationDefinition.Elements.DESCRIPTION,
056 TermSpecificationDefinition.Elements.ACTIVE,
057 CoreConstants.CommonElements.VERSION_NUMBER,
058 TermSpecificationDefinition.Elements.CATEGORIES,
059 CoreConstants.CommonElements.FUTURE_ELEMENTS
060 })
061 public final class TermSpecificationDefinition extends AbstractDataTransferObject implements TermSpecificationDefinitionContract {
062
063 private static final long serialVersionUID = 1L;
064
065 @XmlElement(name = Elements.ID, required=false)
066 private final String id;
067 @XmlElement(name = Elements.NAME, required=true)
068 private final String name;
069 @XmlElement(name = Elements.NAMESPACE, required=true)
070 private final String namespace;
071 @XmlElement(name = Elements.TYPE, required=true)
072 private final String type;
073 @XmlElement(name = Elements.DESCRIPTION, required=false)
074 private final String description;
075 @XmlElement(name = Elements.ACTIVE, required = false)
076 private final boolean active;
077 @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
078 private final Long versionNumber;
079
080 @XmlElementWrapper(name = Elements.CATEGORIES, required = false)
081 @XmlElement(name = Elements.CATEGORY, required = false)
082 private final List<CategoryDefinition> categories;
083
084
085 @SuppressWarnings("unused")
086 @XmlAnyElement
087 private final Collection<org.w3c.dom.Element> _futureElements = null;
088
089 /**
090 * For JAXB use only, shouldn't ever be invoked directly
091 */
092 private TermSpecificationDefinition() {
093 id = null;
094 name = null;
095 namespace = null;
096 type = null;
097 description = null;
098 active = true;
099 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 }