001 /** 002 * Copyright 2005-2014 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.function; 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.category.CategoryDefinition; 037 import org.kuali.rice.krms.api.repository.category.CategoryDefinitionContract; 038 import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition; 039 import org.w3c.dom.Element; 040 041 /** 042 * An immutable representation of a function definition. 043 * 044 * @see FunctionDefinitionContract 045 * 046 * @author Kuali Rice Team (rice.collab@kuali.org) 047 * 048 */ 049 @XmlRootElement(name = FunctionDefinition.Constants.ROOT_ELEMENT_NAME) 050 @XmlAccessorType(XmlAccessType.NONE) 051 @XmlType(name = FunctionDefinition.Constants.TYPE_NAME, propOrder = { 052 FunctionDefinition.Elements.ID, 053 FunctionDefinition.Elements.NAMESPACE, 054 FunctionDefinition.Elements.NAME, 055 FunctionParameterDefinition.Elements.DESCRIPTION, 056 FunctionDefinition.Elements.RETURN_TYPE, 057 FunctionDefinition.Elements.TYPE_ID, 058 FunctionDefinition.Elements.ACTIVE, 059 CoreConstants.CommonElements.VERSION_NUMBER, 060 FunctionDefinition.Elements.PARAMETERS, 061 FunctionDefinition.Elements.CATEGORIES, 062 CoreConstants.CommonElements.FUTURE_ELEMENTS 063 }) 064 public class FunctionDefinition extends AbstractDataTransferObject implements FunctionDefinitionContract { 065 066 private static final long serialVersionUID = 1391030685309770560L; 067 068 @XmlElement(name = Elements.ID, required = false) 069 private final String id; 070 071 @XmlElement(name = Elements.NAMESPACE, required = true) 072 private final String namespace; 073 074 @XmlElement(name = Elements.NAME, required = true) 075 private final String name; 076 077 @XmlElement(name = Elements.DESCRIPTION, required = false) 078 private final String description; 079 080 @XmlElement(name = Elements.RETURN_TYPE, required = true) 081 private final String returnType; 082 083 @XmlElement(name = Elements.TYPE_ID, required = true) 084 private final String typeId; 085 086 @XmlElement(name = Elements.ACTIVE, required = true) 087 private final boolean active; 088 089 @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false) 090 private final Long versionNumber; 091 092 @XmlElementWrapper(name = Elements.PARAMETERS, required = false) 093 @XmlElement(name = Elements.PARAMETER, required = false) 094 private final List<FunctionParameterDefinition> parameters; 095 096 @XmlElementWrapper(name = Elements.CATEGORIES, required = false) 097 @XmlElement(name = Elements.CATEGORY, required = false) 098 private final List<CategoryDefinition> categories; 099 100 @SuppressWarnings("unused") 101 @XmlAnyElement 102 private final Collection<Element> _futureElements = null; 103 104 /** 105 * Private constructor used only by JAXB. 106 */ 107 private FunctionDefinition() { 108 this.id = null; 109 this.namespace = null; 110 this.name = null; 111 this.description = null; 112 this.returnType = null; 113 this.typeId = null; 114 this.active = true; 115 this.versionNumber = null; 116 this.parameters = null; 117 this.categories = null; 118 } 119 120 /** 121 * Constructs a FunctionDefinition from the given builder. This constructor is private and should only 122 * ever be invoked from the builder. 123 * 124 * @param builder the Builder from which to construct the FunctionDefinition 125 */ 126 private FunctionDefinition(Builder builder) { 127 this.id = builder.getId(); 128 this.namespace = builder.getNamespace(); 129 this.name = builder.getName(); 130 this.description = builder.getDescription(); 131 this.returnType = builder.getReturnType(); 132 this.typeId = builder.getTypeId(); 133 this.active = builder.isActive(); 134 this.versionNumber = builder.getVersionNumber(); 135 this.parameters = new ArrayList<FunctionParameterDefinition>(); 136 for (FunctionParameterDefinition.Builder parameter : builder.getParameters()) { 137 this.parameters.add(parameter.build()); 138 } 139 this.categories = new ArrayList<CategoryDefinition>(); 140 for (CategoryDefinition.Builder category : builder.getCategories()) { 141 this.categories.add(category.build()); 142 } 143 } 144 145 @Override 146 public String getId() { 147 return id; 148 } 149 150 @Override 151 public String getNamespace() { 152 return namespace; 153 } 154 155 @Override 156 public String getName() { 157 return name; 158 } 159 160 @Override 161 public String getDescription() { 162 return description; 163 } 164 165 @Override 166 public String getReturnType() { 167 return returnType; 168 } 169 170 @Override 171 public String getTypeId() { 172 return typeId; 173 } 174 175 @Override 176 public boolean isActive() { 177 return active; 178 } 179 180 @Override 181 public Long getVersionNumber() { 182 return versionNumber; 183 } 184 185 @Override 186 public List<FunctionParameterDefinition> getParameters() { 187 return Collections.unmodifiableList(parameters); 188 } 189 190 @Override 191 public List<CategoryDefinition> getCategories() { 192 return Collections.unmodifiableList(categories); 193 } 194 195 /** 196 * A builder which can be used to construct {@link FunctionDefinition} 197 * instances. Enforces the constraints of the {@link FunctionDefinitionContract}. 198 * 199 * @author Kuali Rice Team (rice.collab@kuali.org) 200 * 201 */ 202 public static final class Builder implements FunctionDefinitionContract, ModelBuilder, Serializable { 203 204 private static final long serialVersionUID = -4470376239998290245L; 205 206 private String id; 207 private String namespace; 208 private String name; 209 private String description; 210 private String returnType; 211 private String typeId; 212 private boolean active; 213 private Long versionNumber; 214 private List<FunctionParameterDefinition.Builder> parameters; 215 private List<CategoryDefinition.Builder> categories; 216 217 /** 218 * Private constructor, use create method 219 * @param namespace to use when building 220 * @param name to use when building 221 * @param returnType to use when building 222 * @param typeId to use when building 223 */ 224 private Builder(String namespace, String name, String returnType, String typeId) { 225 setNamespace(namespace); 226 setName(name); 227 setReturnType(returnType); 228 setTypeId(typeId); 229 setActive(true); 230 setParameters(new ArrayList<FunctionParameterDefinition.Builder>()); 231 setCategories(new ArrayList<CategoryDefinition.Builder>()); 232 } 233 234 /** 235 * Creates a function definition builder with the given required values. This builder 236 * is the only means by which a {@link FunctionDefinition} object should be created. 237 * 238 * <p>Will default the active flag to true. 239 * 240 * @param namespace the namespace of the function definition to create, must not be null or blank 241 * @param name the name of the function definition to create, must not be null or blank 242 * @param returnType the return type of the function definition to create, must not be null or blank 243 * @param typeId the return type id of the function definition to create, must not be null or blank 244 * 245 * @return a builder with the required values already initialized 246 * 247 * @throws IllegalArgumentException if any of the given arguments is null or blank 248 */ 249 public static Builder create(String namespace, String name, String returnType, String typeId) { 250 return new Builder(namespace, name, returnType, typeId); 251 } 252 253 /** 254 * Creates and populates a builder with the data on the given {@link FunctionDefinitionContract}. 255 * This is similar in nature to a "copy constructor" for {@link FunctionDefinition}. 256 * 257 * @param contract an object implementing the {@link FunctionDefinitionContract} from which 258 * to copy property values 259 * 260 * @return a builder with the values from the contract already initialized 261 * 262 * @throws IllegalArgumentException if the given contract is null 263 */ 264 public static Builder create(FunctionDefinitionContract contract) { 265 if (contract == null) { 266 throw new IllegalArgumentException("contract was null"); 267 } 268 Builder builder = create(contract.getNamespace(), contract.getName(), contract.getReturnType(), contract.getTypeId()); 269 builder.setId(contract.getId()); 270 builder.setDescription(contract.getDescription()); 271 builder.setActive(contract.isActive()); 272 builder.setVersionNumber(contract.getVersionNumber()); 273 for (FunctionParameterDefinitionContract parameter : contract.getParameters()) { 274 builder.getParameters().add(FunctionParameterDefinition.Builder.create(parameter)); 275 } 276 for (CategoryDefinitionContract category : contract.getCategories()) { 277 builder.getCategories().add(CategoryDefinition.Builder.create(category)); 278 } 279 return builder; 280 } 281 282 @Override 283 public FunctionDefinition build() { 284 return new FunctionDefinition(this); 285 } 286 287 @Override 288 public String getId() { 289 return this.id; 290 } 291 292 /** 293 * Sets the id for the function definition that will be returned by this builder. 294 * 295 * @param id the function definition id to set 296 */ 297 public void setId(String id) { 298 this.id = id; 299 } 300 301 @Override 302 public String getNamespace() { 303 return this.namespace; 304 } 305 306 /** 307 * Sets the namespace code for the function definition that will be returned by this builder. 308 * The namespace must not be null or blank. 309 * 310 * @param namespace the namespace code to set on this builder, must not be null or blank 311 * 312 * @throws IllegalArgumentException if the given namespace is null or blank 313 */ 314 public void setNamespace(String namespace) { 315 if (StringUtils.isBlank(namespace)) { 316 throw new IllegalArgumentException("namespace was blank"); 317 } 318 this.namespace = namespace; 319 } 320 321 @Override 322 public String getName() { 323 return this.name; 324 } 325 326 /** 327 * Sets the name for the function definition that will be returned by this builder. 328 * The name must not be null or blank. 329 * 330 * @param name the name to set on this builder, must not be null or blank 331 * 332 * @throws IllegalArgumentException if the given name is null or blank 333 */ 334 public void setName(String name) { 335 if (StringUtils.isBlank(name)) { 336 throw new IllegalArgumentException("name was blank"); 337 } 338 this.name = name; 339 } 340 341 @Override 342 public String getDescription() { 343 return this.description; 344 } 345 346 /** 347 * Sets the description for the function definition that will be returned by this builder. 348 * 349 * @param description the description to set on this builder 350 */ 351 public void setDescription(String description) { 352 this.description = description; 353 } 354 355 @Override 356 public String getReturnType() { 357 return this.returnType; 358 } 359 360 /** 361 * Sets the return type for the function definition that will be 362 * returned by this builder. This can be one of a set of "built-in" 363 * data types or a custom datatype represented as a fully qualified 364 * java class name. The returnType must not be null or blank. 365 * 366 * @param returnType the returnType to set on this builder, must not be null or blank 367 * 368 * @throws IllegalArgumentException if the given returnType is null or blank 369 */ 370 public void setReturnType(String returnType) { 371 if (StringUtils.isBlank(returnType)) { 372 throw new IllegalArgumentException("returnType was blank"); 373 } 374 this.returnType = returnType; 375 } 376 377 @Override 378 public String getTypeId() { 379 return this.typeId; 380 } 381 382 /** 383 * Sets the id of the {@link KrmsTypeDefinition} which defines the 384 * actual implementation of this function. The typeId must not be 385 * null or blank. 386 * 387 * @param typeId the typeId to set on this builder, must not be null or blank 388 * 389 * @throws IllegalArgumentException if the given typeId is null or blank 390 */ 391 public void setTypeId(String typeId) { 392 if (StringUtils.isBlank(typeId)) { 393 throw new IllegalArgumentException("typeId was blank"); 394 } 395 this.typeId = typeId; 396 } 397 398 @Override 399 public boolean isActive() { 400 return this.active; 401 } 402 403 /** 404 * Sets the active flag for the function definition that will be 405 * returned by this builder. 406 * 407 * @param active the active flag to set 408 */ 409 public void setActive(boolean active) { 410 this.active = active; 411 } 412 413 @Override 414 public Long getVersionNumber() { 415 return this.versionNumber; 416 } 417 418 /** 419 * Sets the version number for the function definition that will be 420 * returned by this builder. 421 * 422 * <p>In general, this value should not be manually set on the builder, 423 * but rather copied from an existing {@link FunctionDefinitionContract} when 424 * invoking {@link Builder#create(FunctionDefinitionContract)}. 425 * 426 * @param versionNumber the version number to set 427 */ 428 public void setVersionNumber(Long versionNumber) { 429 this.versionNumber = versionNumber; 430 } 431 432 @Override 433 public List<FunctionParameterDefinition.Builder> getParameters() { 434 return this.parameters; 435 } 436 437 /** 438 * Sets the parameters for the function definition that will be returned by this builder. 439 * This list is a list of builders for each of the {@link FunctionParameterDefinition} 440 * instances that will form the parameters of this function definition. The given list 441 * must not be null. 442 * 443 * @param parameters a list of builders for the parameters which will be specified on this function definition 444 * 445 * @throws IllegalArgumentException if the given parameters list is null 446 */ 447 public void setParameters(List<FunctionParameterDefinition.Builder> parameters) { 448 if (parameters == null) { 449 throw new IllegalArgumentException("parameters was null"); 450 } 451 this.parameters = parameters; 452 } 453 454 @Override 455 public List<CategoryDefinition.Builder> getCategories() { 456 return this.categories; 457 } 458 459 /** 460 * Sets the category for the function definition that will be returned by this builder. 461 * This list is a list of builders for each of the {@link CategoryDefinition} 462 * instances that will form the categories of this function definition. The given list 463 * must not be null. 464 * 465 * @param categories a list of builders for the categories which will be specified on this function definition 466 * 467 * @throws IllegalArgumentException if the given categories list is null 468 */ 469 public void setCategories(List<CategoryDefinition.Builder> categories) { 470 if (categories == null) { 471 throw new IllegalArgumentException("categories was null"); 472 } 473 this.categories = categories; 474 } 475 476 } 477 478 /** 479 * Defines some internal constants used on this class. 480 */ 481 static class Constants { 482 final static String ROOT_ELEMENT_NAME = "function"; 483 final static String TYPE_NAME = "FunctionType"; 484 } 485 486 /** 487 * A private class which exposes constants which define the XML element names to use 488 * when this object is marshalled to XML. 489 */ 490 static class Elements { 491 final static String ID = "id"; 492 final static String NAMESPACE = "namespace"; 493 final static String NAME = "name"; 494 final static String DESCRIPTION = "description"; 495 final static String RETURN_TYPE = "returnType"; 496 final static String TYPE_ID = "typeId"; 497 final static String ACTIVE = "active"; 498 final static String PARAMETERS = "parameters"; 499 final static String PARAMETER = "parameter"; 500 final static String CATEGORIES = "categories"; 501 final static String CATEGORY = "category"; 502 } 503 504 }