View Javadoc

1   package org.kuali.rice.krms.api.repository.action;
2   
3   import java.io.Serializable;
4   import java.util.Collection;
5   import java.util.Collections;
6   import java.util.HashMap;
7   import java.util.Map;
8   
9   import javax.xml.bind.annotation.XmlAccessType;
10  import javax.xml.bind.annotation.XmlAccessorType;
11  import javax.xml.bind.annotation.XmlAnyElement;
12  import javax.xml.bind.annotation.XmlElement;
13  import javax.xml.bind.annotation.XmlRootElement;
14  import javax.xml.bind.annotation.XmlType;
15  import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
16  
17  import org.apache.commons.lang.StringUtils;
18  import org.apache.commons.lang.builder.EqualsBuilder;
19  import org.apache.commons.lang.builder.HashCodeBuilder;
20  import org.apache.commons.lang.builder.ToStringBuilder;
21  import org.kuali.rice.core.api.CoreConstants;
22  import org.kuali.rice.core.api.mo.ModelBuilder;
23  import org.kuali.rice.core.api.mo.ModelObjectComplete;
24  import org.kuali.rice.core.util.jaxb.MapStringStringAdapter;
25  
26  /**
27   * Concrete model object implementation of KRMS Repository Action 
28   * immutable. 
29   * Instances of Action can be (un)marshalled to and from XML.
30   *
31   * @see ActionDefinitionContract
32   */
33  @XmlRootElement(name = ActionDefinition.Constants.ROOT_ELEMENT_NAME)
34  @XmlAccessorType(XmlAccessType.NONE)
35  @XmlType(name = ActionDefinition.Constants.TYPE_NAME, propOrder = {
36  		ActionDefinition.Elements.ID,
37  		ActionDefinition.Elements.NAME,
38  		ActionDefinition.Elements.NAMESPACE,
39  		ActionDefinition.Elements.DESC,
40  		ActionDefinition.Elements.TYPE_ID,
41  		ActionDefinition.Elements.RULE_ID,
42  		ActionDefinition.Elements.SEQUENCE_NUMBER,
43  		ActionDefinition.Elements.ATTRIBUTES,
44          CoreConstants.CommonElements.VERSION_NUMBER,
45  		CoreConstants.CommonElements.FUTURE_ELEMENTS
46  })
47  public final class ActionDefinition implements ActionDefinitionContract, ModelObjectComplete{
48  	private static final long serialVersionUID = 2783959459503209577L;
49  
50  	@XmlElement(name = Elements.ID, required=true)
51  	private String id;
52  	@XmlElement(name = Elements.NAME, required=true)
53  	private String name;
54  	@XmlElement(name = Elements.NAMESPACE, required=true)
55  	private String namespace;
56  	@XmlElement(name = Elements.DESC, required=true)
57  	private String description;
58  	@XmlElement(name = Elements.TYPE_ID, required=true)
59  	private String typeId;
60  	@XmlElement(name = Elements.RULE_ID, required=true)
61  	private String ruleId;
62  	@XmlElement(name = Elements.SEQUENCE_NUMBER, required=true)
63  	private Integer sequenceNumber;
64  	
65  	@XmlElement(name = Elements.ATTRIBUTES, required = false)
66  	@XmlJavaTypeAdapter(value = MapStringStringAdapter.class)
67  	private final Map<String, String> attributes;
68  	
69      @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
70      private final Long versionNumber;
71      	
72  	@SuppressWarnings("unused")
73      @XmlAnyElement
74      private final Collection<org.w3c.dom.Element> _futureElements = null;
75  	
76  	
77  	 /** 
78       * This constructor should never be called.  
79       * It is only present for use during JAXB unmarshalling. 
80       */
81      private ActionDefinition() {
82      	this.id = null;
83      	this.name = null;
84      	this.namespace = null;
85      	this.description = null;
86      	this.typeId = null;
87      	this.ruleId = null;
88      	this.sequenceNumber = null;
89      	this.attributes = null;
90          this.versionNumber = null;
91      }
92      
93      /**
94  	 * Constructs a KRMS Repository Action object from the given builder.  
95  	 * This constructor is private and should only ever be invoked from the builder.
96  	 * 
97  	 * @param builder the Builder from which to construct the Action
98  	 */
99      private ActionDefinition(Builder builder) {
100         this.id = builder.getId();
101         this.name = builder.getName();
102         this.namespace = builder.getNamespace();
103         this.description = builder.getDescription();
104         this.typeId = builder.getTypeId();
105         this.ruleId = builder.getRuleId();
106         this.sequenceNumber = builder.getSequenceNumber();
107         if (builder.attributes != null){
108         	this.attributes = Collections.unmodifiableMap(builder.getAttributes());
109         } else {
110         	this.attributes = null;
111         }
112         this.versionNumber = builder.getVersionNumber();
113     }
114     
115 	@Override
116 	public String getId() {
117 		return this.id;
118 	}
119 
120 	@Override
121 	public String getName() {
122 		return this.name;
123 	}
124 
125 	@Override
126 	public String getNamespace() {
127 		return this.namespace;
128 	}
129 
130 	@Override
131 	public String getDescription() {
132 		return this.description;
133 	}
134 
135 	@Override
136 	public String getTypeId() {
137 		return this.typeId;
138 	}
139 
140 	@Override
141 	public String getRuleId() {
142 		return this.ruleId;
143 	}
144 
145 	@Override
146 	public Integer getSequenceNumber() {
147 		return this.sequenceNumber;
148 	}
149 
150 	@Override
151 	public Map<String, String> getAttributes() {
152 		return this.attributes; 
153 	}
154 
155     @Override
156     public Long getVersionNumber() {
157         return versionNumber;
158     }
159         
160 	/**
161      * This builder is used to construct instances of KRMS Repository Action.  It enforces the constraints of the {@link ActionDefinitionContract}.
162      */
163     public static class Builder implements ActionDefinitionContract, ModelBuilder, Serializable {
164         private static final long serialVersionUID = -6773634512570180267L;
165 
166         private String id;
167         private String name;
168         private String namespace;
169         private String description;
170         private String typeId;
171         private String ruleId;
172         private Integer sequenceNumber;
173         private Map<String, String> attributes;
174         private Long versionNumber;
175 
176 		/**
177 		 * Private constructor for creating a builder with all of it's required attributes.
178 		 */
179         private Builder(String actionId, String name, String namespace, String typeId, String ruleId, Integer sequenceNumber) {
180             setId(actionId);
181             setName(name);
182             setNamespace(namespace);
183             setTypeId(typeId);
184             setRuleId(ruleId);
185             setSequenceNumber(sequenceNumber);
186             setAttributes(new HashMap<String, String>());
187         }
188         
189         public static Builder create(String actionId, String name, String namespace, String typeId, String ruleId, Integer sequenceNumber){
190         	return new Builder(actionId, name, namespace, typeId, ruleId, sequenceNumber);
191         }
192         /**
193          * Creates a builder by populating it with data from the given {@link ActionDefinitionContract}.
194          * 
195          * @param contract the contract from which to populate this builder
196          * @return an instance of the builder populated with data from the contract
197          */
198         public static Builder create(ActionDefinitionContract contract) {
199         	if (contract == null) {
200                 throw new IllegalArgumentException("contract is null");
201             }
202             Builder builder =  new Builder(contract.getId(), contract.getName(),
203             		contract.getNamespace(), contract.getTypeId(), contract.getRuleId(),
204             		contract.getSequenceNumber());
205             builder.setDescription(contract.getDescription());
206         	if (contract.getAttributes() != null){
207                 builder.setAttributes(new HashMap<String, String>(contract.getAttributes()));
208         	}
209             builder.setVersionNumber(contract.getVersionNumber());
210             return builder;
211         }
212 
213 		/**
214 		 * Sets the value of the id on this builder to the given value.
215 		 * 
216 		 * @param id the id value to set, must be null or non-blank
217 		 * @throws IllegalArgumentException if the id is non-null and blank
218 		 */
219 
220         public void setId(String actionId) {
221             if (actionId != null && StringUtils.isBlank(actionId)) {
222                 throw new IllegalArgumentException("action ID must be null or non-blank");
223             }
224 			this.id = actionId;
225 		}
226 
227      
228         public void setName(String name) {
229             if (StringUtils.isBlank(name)) {
230                 throw new IllegalArgumentException("name is blank");
231             }
232 			this.name = name;
233 		}
234      
235         public void setNamespace(String namespace) {
236             if (StringUtils.isBlank(namespace)) {
237                 throw new IllegalArgumentException("namespace is blank");
238             }
239 			this.namespace = namespace;
240 		}
241      
242 		public void setDescription(String desc) {
243 			this.description = desc;
244 		}
245 		
246 		public void setTypeId(String typeId) {
247 			if (StringUtils.isBlank(typeId)) {
248 	                throw new IllegalArgumentException("KRMS type id is blank");
249 			}
250 			this.typeId = typeId;
251 		}
252 		
253 		public void setRuleId(String ruleId) {
254 			if (StringUtils.isBlank(ruleId)) {
255 	                throw new IllegalArgumentException("rule id is blank");
256 			}
257 			this.ruleId = ruleId;
258 		}
259 		
260 		public void setSequenceNumber(Integer sequenceNumber) {
261 			if (sequenceNumber == null) {
262 	                throw new IllegalArgumentException("sequence number is null");
263 			}
264 			this.sequenceNumber = sequenceNumber;
265 		}
266 		
267 		public void setAttributes(Map<String, String> attributes){
268 			if (attributes == null){
269 				this.attributes = Collections.emptyMap();
270 			}
271 			this.attributes = Collections.unmodifiableMap(attributes);
272 		}
273 		
274         public void setVersionNumber(Long versionNumber){
275             this.versionNumber = versionNumber;
276         }
277         
278 		@Override
279 		public String getId() {
280 			return id;
281 		}
282 
283 		@Override
284 		public String getName() {
285 			return name;
286 		}
287 
288 		@Override
289 		public String getNamespace() {
290 			return namespace;
291 		}
292 
293 		@Override
294 		public String getDescription() {
295 			return description;
296 		}
297 
298 		@Override
299 		public String getTypeId() {
300 			return typeId;
301 		}
302 
303 		@Override
304 		public String getRuleId() {
305 			return ruleId;
306 		}
307 
308 		@Override
309 		public Integer getSequenceNumber() {
310 			return sequenceNumber;
311 		}
312 
313 		@Override
314 		public Map<String, String> getAttributes() {
315 			return attributes;
316 		}
317 
318         @Override
319         public Long getVersionNumber() {
320             return versionNumber;
321         }
322 
323 		/**
324 		 * Builds an instance of a Action based on the current state of the builder.
325 		 * 
326 		 * @return the fully-constructed Action
327 		 */
328         @Override
329         public ActionDefinition build() {
330             return new ActionDefinition(this);
331         }
332 		
333     }
334 	@Override
335 	public int hashCode() {
336 		return HashCodeBuilder.reflectionHashCode(this, Constants.HASH_CODE_EQUALS_EXCLUDE);
337 	}
338 
339 	@Override
340 	public boolean equals(Object obj) {
341 		return EqualsBuilder.reflectionEquals(obj, this, Constants.HASH_CODE_EQUALS_EXCLUDE);
342 	}
343 
344 	@Override
345 	public String toString() {
346 		return ToStringBuilder.reflectionToString(this);
347 	}
348 	
349 	/**
350 	 * Defines some internal constants used on this class.
351 	 */
352 	static class Constants {
353 		final static String ROOT_ELEMENT_NAME = "action";
354 		final static String TYPE_NAME = "ActionType";
355 		final static String[] HASH_CODE_EQUALS_EXCLUDE = { CoreConstants.CommonElements.FUTURE_ELEMENTS };
356 	}
357 	
358 	/**
359 	 * A private class which exposes constants which define the XML element names to use
360 	 * when this object is marshalled to XML.
361 	 */
362 	public static class Elements {
363 		final static String ID = "id";
364 		final static String NAME = "name";
365 		final static String NAMESPACE = "namespace";
366 		final static String DESC = "description";
367 		final static String TYPE_ID = "typeId";
368 		final static String RULE_ID = "ruleId";
369 		final static String SEQUENCE_NUMBER = "sequenceNumber";
370 		final static String ATTRIBUTES = "attributes";
371 	}
372 
373 }