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 }