View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krms.api.repository.function;
17  
18  import java.io.Serializable;
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.Collections;
22  import java.util.List;
23  
24  import javax.xml.bind.annotation.XmlAccessType;
25  import javax.xml.bind.annotation.XmlAccessorType;
26  import javax.xml.bind.annotation.XmlAnyElement;
27  import javax.xml.bind.annotation.XmlElement;
28  import javax.xml.bind.annotation.XmlElementWrapper;
29  import javax.xml.bind.annotation.XmlRootElement;
30  import javax.xml.bind.annotation.XmlType;
31  
32  import org.apache.commons.lang.StringUtils;
33  import org.kuali.rice.core.api.CoreConstants;
34  import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
35  import org.kuali.rice.core.api.mo.ModelBuilder;
36  import org.kuali.rice.krms.api.repository.category.CategoryDefinition;
37  import org.kuali.rice.krms.api.repository.category.CategoryDefinitionContract;
38  import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
39  import org.w3c.dom.Element;
40  
41  /**
42   * An immutable representation of a function definition.
43   * 
44   * @see FunctionDefinitionContract
45   * 
46   * @author Kuali Rice Team (rice.collab@kuali.org)
47   *
48   */
49  @XmlRootElement(name = FunctionDefinition.Constants.ROOT_ELEMENT_NAME)
50  @XmlAccessorType(XmlAccessType.NONE)
51  @XmlType(name = FunctionDefinition.Constants.TYPE_NAME, propOrder = {
52  		FunctionDefinition.Elements.ID,
53  		FunctionDefinition.Elements.NAMESPACE,
54  		FunctionDefinition.Elements.NAME,
55  		FunctionParameterDefinition.Elements.DESCRIPTION,
56  		FunctionDefinition.Elements.RETURN_TYPE,
57  		FunctionDefinition.Elements.TYPE_ID,
58  		FunctionDefinition.Elements.ACTIVE,
59          CoreConstants.CommonElements.VERSION_NUMBER,
60          FunctionDefinition.Elements.PARAMETERS,
61          FunctionDefinition.Elements.CATEGORIES,
62          CoreConstants.CommonElements.FUTURE_ELEMENTS
63  })
64  public class FunctionDefinition extends AbstractDataTransferObject implements FunctionDefinitionContract {
65  
66  	private static final long serialVersionUID = 1391030685309770560L;
67  
68  	@XmlElement(name = Elements.ID, required = false)
69  	private final String id;
70  	
71  	@XmlElement(name = Elements.NAMESPACE, required = true)
72  	private final String namespace;
73  	
74  	@XmlElement(name = Elements.NAME, required = true)
75  	private final String name;
76  	
77  	@XmlElement(name = Elements.DESCRIPTION, required = false)
78  	private final String description;
79  	
80  	@XmlElement(name = Elements.RETURN_TYPE, required = true)
81  	private final String returnType;
82  	
83  	@XmlElement(name = Elements.TYPE_ID, required = true)
84  	private final String typeId;
85  	
86  	@XmlElement(name = Elements.ACTIVE, required = true)
87  	private final boolean active;
88  	
89  	@XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
90  	private final Long versionNumber;
91  	
92  	@XmlElementWrapper(name = Elements.PARAMETERS, required = false)
93  	@XmlElement(name = Elements.PARAMETER, required = false)
94  	private final List<FunctionParameterDefinition> parameters;
95  
96      @XmlElementWrapper(name = Elements.CATEGORIES, required = false)
97      @XmlElement(name = Elements.CATEGORY, required = false)
98      private final List<CategoryDefinition> categories;
99  	
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 }