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.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 }