View Javadoc

1   /*
2    * Copyright 2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 1.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/ecl1.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.apache.commons.lang.builder.EqualsBuilder;
34  import org.apache.commons.lang.builder.HashCodeBuilder;
35  import org.apache.commons.lang.builder.ToStringBuilder;
36  import org.kuali.rice.core.api.CoreConstants;
37  import org.kuali.rice.core.api.mo.ModelBuilder;
38  import org.kuali.rice.core.api.mo.ModelObjectComplete;
39  import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
40  import org.w3c.dom.Element;
41  
42  /**
43   * An immutable representation of a function definition.
44   * 
45   * @see FunctionDefinitionContract
46   * 
47   * @author Kuali Rice Team (rice.collab@kuali.org)
48   *
49   */
50  @XmlRootElement(name = FunctionDefinition.Constants.ROOT_ELEMENT_NAME)
51  @XmlAccessorType(XmlAccessType.NONE)
52  @XmlType(name = FunctionDefinition.Constants.TYPE_NAME, propOrder = {
53  		FunctionDefinition.Elements.ID,
54  		FunctionDefinition.Elements.NAMESPACE,
55  		FunctionDefinition.Elements.NAME,
56  		FunctionParameterDefinition.Elements.DESCRIPTION,
57  		FunctionDefinition.Elements.RETURN_TYPE,
58  		FunctionDefinition.Elements.TYPE_ID,
59  		FunctionDefinition.Elements.ACTIVE,
60          CoreConstants.CommonElements.VERSION_NUMBER,
61          FunctionDefinition.Elements.PARAMETERS,
62          CoreConstants.CommonElements.FUTURE_ELEMENTS
63  })
64  public class FunctionDefinition implements FunctionDefinitionContract, ModelObjectComplete {
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  	@SuppressWarnings("unused")
97      @XmlAnyElement
98      private final Collection<Element> _futureElements = null;
99  	
100 	/**
101      * Private constructor used only by JAXB.
102      */
103     private FunctionDefinition() {
104     	this.id = null;
105     	this.namespace = null;
106     	this.name = null;
107     	this.description = null;
108     	this.returnType = null;
109     	this.typeId = null;
110     	this.active = false;
111     	this.versionNumber = null;
112     	this.parameters = null;
113     }
114     
115     private FunctionDefinition(Builder builder) {
116     	this.id = builder.getId();
117     	this.namespace = builder.getNamespace();
118     	this.name = builder.getName();
119     	this.description = builder.getDescription();
120     	this.returnType = builder.getReturnType();
121     	this.typeId = builder.getTypeId();
122     	this.active = builder.isActive();
123     	this.versionNumber = builder.getVersionNumber();
124     	this.parameters = new ArrayList<FunctionParameterDefinition>();
125     	for (FunctionParameterDefinition.Builder parameter : builder.getParameters()) {
126     		this.parameters.add(parameter.build());
127     	}
128     }
129     
130 	@Override
131 	public String getId() {
132 		return id;
133 	}
134 
135 	@Override
136 	public String getNamespace() {
137 		return namespace;
138 	}
139 
140 	@Override
141 	public String getName() {
142 		return name;
143 	}
144 
145 	@Override
146 	public String getDescription() {
147 		return description;
148 	}
149 	
150 	@Override
151 	public String getReturnType() {
152 		return returnType;
153 	}
154 
155 	@Override
156 	public String getTypeId() {
157 		return typeId;
158 	}
159 
160 	@Override
161 	public boolean isActive() {
162 		return active;
163 	}
164 	
165 	@Override
166 	public Long getVersionNumber() {
167 		return versionNumber;
168 	}
169 	
170 	@Override
171 	public List<FunctionParameterDefinition> getParameters() {
172 		return Collections.unmodifiableList(parameters);
173 	}
174 
175 	/**
176 	 * A builder which can be used to construct {@link FunctionDefinition}
177 	 * instances.  Enforces the constraints of the {@link FunctionDefinitionContract}.
178 	 * 
179 	 * @author Kuali Rice Team (rice.collab@kuali.org)
180 	 *
181 	 */
182 	public static final class Builder implements FunctionDefinitionContract, ModelBuilder, Serializable  {
183     	    	
184     	private static final long serialVersionUID = -4470376239998290245L;
185     	
186 		private String id;
187     	private String namespace;
188     	private String name;
189     	private String description;
190     	private String returnType;
191     	private String typeId;
192     	private boolean active;
193     	private Long versionNumber;
194     	private List<FunctionParameterDefinition.Builder> parameters;
195     	
196         private Builder(String namespace, String name, String returnType, String typeId) {
197         	setNamespace(namespace);
198         	setName(name);
199         	setReturnType(returnType);
200         	setTypeId(typeId);
201         	setActive(true);
202         	setParameters(new ArrayList<FunctionParameterDefinition.Builder>());
203         }
204         
205         /**
206          * Creates a function definition builder with the given required values.  This builder
207          * is the only means by which a {@link FunctionDefinition} object should be created.
208          * 
209          * <p>Will default the active flag to true.
210          * 
211          * @param namespace the namespace of the function definition to create, must not be null or blank
212          * @param name the name of the function definition to create, must not be null or blank
213          * @param returnType the return type of the function definition to create, must not be null or blank
214          * @param typeId the return type id of the function definition to create, must not be null or blank
215          * 
216          * @return a builder with the required values already initialized
217          * 
218          * @throws IllegalArgumentException if any of the given arguments is null or blank
219          */
220         public static Builder create(String namespace, String name, String returnType, String typeId) {
221         	return new Builder(namespace, name, returnType, typeId);
222         }
223         
224         /**
225          * Creates and populates a builder with the data on the given {@link FunctionDefinitionContract}.
226          * This is similar in nature to a "copy constructor" for {@link FunctionDefinition}.
227          * 
228          * @param contract an object implementing the {@link FunctionDefinitionContract} from which
229          * to copy property values
230          *  
231          * @return a builder with the values from the contract already initialized
232          * 
233          * @throws IllegalArgumentException if the given contract is null
234          */
235         public static Builder create(FunctionDefinitionContract contract) {
236         	if (contract == null) {
237         		throw new IllegalArgumentException("contract was null");
238         	}
239         	Builder builder = create(contract.getNamespace(), contract.getName(), contract.getReturnType(), contract.getTypeId());
240         	builder.setId(contract.getId());
241         	builder.setDescription(contract.getDescription());
242         	builder.setActive(contract.isActive());
243         	builder.setVersionNumber(contract.getVersionNumber());
244         	for (FunctionParameterDefinitionContract parameter : contract.getParameters()) {
245         		builder.getParameters().add(FunctionParameterDefinition.Builder.create(parameter));
246         	}
247         	return builder;
248         }
249 
250         @Override
251         public FunctionDefinition build() {
252         	return new FunctionDefinition(this);
253         }
254         
255         @Override
256 		public String getId() {
257 			return this.id;
258 		}
259 
260         /**
261          * Sets the id for the function definition that will be returned by this builder.
262          * 
263          * @param id the function definition id to set
264          */
265 		public void setId(String id) {
266 			this.id = id;
267 		}
268 
269 		@Override
270 		public String getNamespace() {
271 			return this.namespace;
272 		}
273 
274         /**
275          * Sets the namespace code for the function definition that will be returned by this builder.
276          * The namespace must not be null or blank.
277          * 
278          * @param namespace the namespace code to set on this builder, must not be null or blank
279          * 
280          * @throws IllegalArgumentException if the given namespace is null or blank
281          */
282 		public void setNamespace(String namespace) {
283 			if (StringUtils.isBlank(namespace)) {
284 				throw new IllegalArgumentException("namespace was blank");
285 			}
286 			this.namespace = namespace;
287 		}
288 
289 		@Override
290 		public String getName() {
291 			return this.name;
292 		}
293 
294 		/**
295          * Sets the name for the function definition that will be returned by this builder.
296          * The name must not be null or blank.
297          * 
298          * @param name the name to set on this builder, must not be null or blank
299          * 
300          * @throws IllegalArgumentException if the given name is null or blank
301          */
302 		public void setName(String name) {
303 			if (StringUtils.isBlank(name)) {
304 				throw new IllegalArgumentException("name was blank");
305 			}
306 			this.name = name;
307 		}
308 		
309 		@Override
310 		public String getDescription() {
311 			return this.description;
312 		}
313 
314         /**
315          * Sets the description for the function definition that will be returned by this builder.
316          * 
317          * @param description the description to set on this builder
318          */
319 		public void setDescription(String description) {
320 			this.description = description;
321 		}
322 
323 		@Override
324 		public String getReturnType() {
325 			return this.returnType;
326 		}
327 
328 		/**
329          * Sets the return type for the function definition that will be
330          * returned by this builder.  This can be one of a set of "built-in"
331          * data types or a custom datatype represented as a fully qualified
332          * java class name.  The returnType must not be null or blank.
333          * 
334          * @param returnType the returnType to set on this builder, must not be null or blank
335          * 
336          * @throws IllegalArgumentException if the given returnType is null or blank
337          */
338 		public void setReturnType(String returnType) {
339 			if (StringUtils.isBlank(returnType)) {
340 				throw new IllegalArgumentException("returnType was blank");
341 			}
342 			this.returnType = returnType;
343 		}
344 
345 		@Override
346 		public String getTypeId() {
347 			return this.typeId;
348 		}
349 
350 		/**
351          * Sets the id of the {@link KrmsTypeDefinition} which defines the
352          * actual implementation of this function.  The typeId must not be
353          * null or blank.
354          * 
355          * @param typeId the typeId to set on this builder, must not be null or blank
356          * 
357          * @throws IllegalArgumentException if the given typeId is null or blank
358          */
359 		public void setTypeId(String typeId) {
360 			if (StringUtils.isBlank(typeId)) {
361 				throw new IllegalArgumentException("typeId was blank");
362 			}
363 			this.typeId = typeId;
364 		}
365 
366 		@Override
367 		public boolean isActive() {
368 			return this.active;
369 		}
370 
371 		/**
372          * Sets the active flag for the function definition that will be
373          * returned by this builder.
374          * 
375          * @param active the active flag to set
376          */
377 		public void setActive(boolean active) {
378 			this.active = active;
379 		}
380 
381 		@Override
382 		public Long getVersionNumber() {
383 			return this.versionNumber;
384 		}
385 
386 		/**
387          * Sets the version number for the function definition that will be
388          * returned by this builder.
389          * 
390          * <p>In general, this value should not be manually set on the builder,
391          * but rather copied from an existing {@link FunctionDefinitionContract} when
392          * invoking {@link Builder#create(FunctionDefinitionContract)}.
393          * 
394          * @param versionNumber the version number to set
395          */
396 		public void setVersionNumber(Long versionNumber) {
397 			this.versionNumber = versionNumber;
398 		}
399 		
400 		@Override
401 		public List<FunctionParameterDefinition.Builder> getParameters() {
402 			return this.parameters;
403 		}
404 		
405 		/**
406          * Sets the parameters for the function definition that will be returned by this builder.
407          * This list is a list of builders for each of the {@link FunctionParameterDefinition}
408          * instances that will form the parameters of this function definition.  The given list
409          * must not be null.
410          * 
411          * @param parameters a list of builders for the parameters which will be specified on this function definition
412          * 
413          * @throws IllegalArgumentException if the given parameters list is null 
414          */
415 		public void setParameters(List<FunctionParameterDefinition.Builder> parameters) {
416 			if (parameters == null) {
417 				throw new IllegalArgumentException("parameters was null");
418 			}
419 			this.parameters = parameters;
420 		}
421 
422 	}
423 	
424 	@Override
425     public int hashCode() {
426         return HashCodeBuilder.reflectionHashCode(this, Constants.HASH_CODE_EQUALS_EXCLUDE);
427     }
428 
429     @Override
430     public boolean equals(Object obj) {
431         return EqualsBuilder.reflectionEquals(obj, this, Constants.HASH_CODE_EQUALS_EXCLUDE);
432     }
433 
434     @Override
435     public String toString() {
436         return ToStringBuilder.reflectionToString(this);
437     }
438 	
439 	/**
440      * Defines some internal constants used on this class.
441      */
442     static class Constants {
443         final static String ROOT_ELEMENT_NAME = "function";
444         final static String TYPE_NAME = "FunctionType";
445         final static String[] HASH_CODE_EQUALS_EXCLUDE = {CoreConstants.CommonElements.FUTURE_ELEMENTS};
446     }
447 
448     /**
449      * A private class which exposes constants which define the XML element names to use
450      * when this object is marshalled to XML.
451      */
452     static class Elements {
453         final static String ID = "id";
454         final static String NAMESPACE = "namespace";
455         final static String NAME = "name";
456         final static String DESCRIPTION = "description";
457         final static String RETURN_TYPE = "returnType";
458         final static String TYPE_ID = "typeId";
459         final static String ACTIVE = "active";
460         final static String PARAMETERS = "parameters";
461         final static String PARAMETER = "parameter";
462     }
463     
464 }