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.action;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.kuali.rice.core.api.CoreConstants;
020 import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
021 import org.kuali.rice.core.api.mo.ModelBuilder;
022 import org.kuali.rice.core.api.util.jaxb.MapStringStringAdapter;
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.XmlRootElement;
029 import javax.xml.bind.annotation.XmlType;
030 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
031 import java.io.Serializable;
032 import java.util.Collection;
033 import java.util.Collections;
034 import java.util.HashMap;
035 import java.util.Map;
036
037 /**
038 * Concrete model object implementation of KRMS Repository Action
039 * immutable.
040 * Instances of Action can be (un)marshalled to and from XML.
041 *
042 * @see org.kuali.rice.krms.framework.engine.Action
043 * @see ActionDefinitionContract
044 *
045 * @author Kuali Rice Team (rice.collab@kuali.org)
046 */
047 @XmlRootElement(name = ActionDefinition.Constants.ROOT_ELEMENT_NAME)
048 @XmlAccessorType(XmlAccessType.NONE)
049 @XmlType(name = ActionDefinition.Constants.TYPE_NAME, propOrder = {
050 ActionDefinition.Elements.ID,
051 ActionDefinition.Elements.NAME,
052 ActionDefinition.Elements.NAMESPACE,
053 ActionDefinition.Elements.DESC,
054 ActionDefinition.Elements.TYPE_ID,
055 ActionDefinition.Elements.RULE_ID,
056 ActionDefinition.Elements.SEQUENCE_NUMBER,
057 ActionDefinition.Elements.ATTRIBUTES,
058 CoreConstants.CommonElements.VERSION_NUMBER,
059 CoreConstants.CommonElements.FUTURE_ELEMENTS
060 })
061 public final class ActionDefinition extends AbstractDataTransferObject implements ActionDefinitionContract {
062 private static final long serialVersionUID = 2783959459503209577L;
063
064 @XmlElement(name = Elements.ID, required=true)
065 private String id;
066 @XmlElement(name = Elements.NAME, required=true)
067 private String name;
068 @XmlElement(name = Elements.NAMESPACE, required=true)
069 private String namespace;
070 @XmlElement(name = Elements.DESC, required=true)
071 private String description;
072 @XmlElement(name = Elements.TYPE_ID, required=true)
073 private String typeId;
074 @XmlElement(name = Elements.RULE_ID, required=true)
075 private String ruleId;
076 @XmlElement(name = Elements.SEQUENCE_NUMBER, required=true)
077 private Integer sequenceNumber;
078
079 @XmlElement(name = Elements.ATTRIBUTES, required = false)
080 @XmlJavaTypeAdapter(value = MapStringStringAdapter.class)
081 private final Map<String, String> attributes;
082
083 @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
084 private final Long versionNumber;
085
086 @SuppressWarnings("unused")
087 @XmlAnyElement
088 private final Collection<org.w3c.dom.Element> _futureElements = null;
089
090
091 /**
092 * This constructor should never be called.
093 * It is only present for use during JAXB unmarshalling.
094 */
095 private ActionDefinition() {
096 this.id = null;
097 this.name = null;
098 this.namespace = null;
099 this.description = null;
100 this.typeId = null;
101 this.ruleId = null;
102 this.sequenceNumber = null;
103 this.attributes = null;
104 this.versionNumber = null;
105 }
106
107 /**
108 * Constructs a KRMS Repository Action object from the given builder.
109 * This constructor is private and should only ever be invoked from the builder.
110 *
111 * @param builder the Builder from which to construct the Action
112 */
113 private ActionDefinition(Builder builder) {
114 this.id = builder.getId();
115 this.name = builder.getName();
116 this.namespace = builder.getNamespace();
117 this.description = builder.getDescription();
118 this.typeId = builder.getTypeId();
119 this.ruleId = builder.getRuleId();
120 this.sequenceNumber = builder.getSequenceNumber();
121 if (builder.attributes != null){
122 this.attributes = Collections.unmodifiableMap(builder.getAttributes());
123 } else {
124 this.attributes = null;
125 }
126 this.versionNumber = builder.getVersionNumber();
127 }
128
129 @Override
130 public String getId() {
131 return this.id;
132 }
133
134 @Override
135 public String getName() {
136 return this.name;
137 }
138
139 @Override
140 public String getNamespace() {
141 return this.namespace;
142 }
143
144 @Override
145 public String getDescription() {
146 return this.description;
147 }
148
149 @Override
150 public String getTypeId() {
151 return this.typeId;
152 }
153
154 @Override
155 public String getRuleId() {
156 return this.ruleId;
157 }
158
159 @Override
160 public Integer getSequenceNumber() {
161 return this.sequenceNumber;
162 }
163
164 /**
165 * Returns the internal representation of the set of attributes associated with the
166 * Action. The attributes are represented as name/value pairs.
167 *
168 * @return internal representation of the set of ActionAttribute objects.
169 */
170 @Override
171 public Map<String, String> getAttributes() {
172 return this.attributes;
173 }
174
175 @Override
176 public Long getVersionNumber() {
177 return versionNumber;
178 }
179
180 /**
181 * This builder is used to construct instances of KRMS Repository Action. It enforces the constraints of the {@link ActionDefinitionContract}.
182 */
183 public static class Builder implements ActionDefinitionContract, ModelBuilder, Serializable {
184 private static final long serialVersionUID = -6773634512570180267L;
185
186 private String id;
187 private String name;
188 private String namespace;
189 private String description;
190 private String typeId;
191 private String ruleId;
192 private Integer sequenceNumber;
193 private Map<String, String> attributes;
194 private Long versionNumber;
195
196 /**
197 * Private constructor for creating a builder with all of it's required attributes.
198 *
199 * @param actionId the actionId value to set, must no tbe null or blank
200 * @param name the name value to set, must not be null or blank
201 * @param namespace the namespace value to set, must not be null or blank
202 * @param typeId the typeId value to set
203 * @param ruleId the ruleId value to set, must not be null or blank
204 * @param sequenceNumber the sequenceNumber value to set, must not be null or blank
205 */
206 private Builder(String actionId, String name, String namespace, String typeId, String ruleId, Integer sequenceNumber) {
207 setId(actionId);
208 setName(name);
209 setNamespace(namespace);
210 setTypeId(typeId);
211 setRuleId(ruleId);
212 setSequenceNumber(sequenceNumber);
213 setAttributes(new HashMap<String, String>());
214 }
215
216 /**
217 * Create a builder with the given parameters
218 *
219 * @param actionId the actionId value to set, must no tbe null or blank
220 * @param name the name value to set, must not be null or blank
221 * @param namespace the namespace value to set, must not be null or blank
222 * @param typeId the typeId value to set
223 * @param ruleId the ruleId value to set, must not be null or blank
224 * @param sequenceNumber the sequenceNumber value to set, must not be null or blank
225 * @return an instance of the builder populated with given data
226 */
227 public static Builder create(String actionId, String name, String namespace, String typeId, String ruleId, Integer sequenceNumber){
228 return new Builder(actionId, name, namespace, typeId, ruleId, sequenceNumber);
229 }
230 /**
231 * Creates a builder by populating it with data from the given {@link ActionDefinitionContract}.
232 *
233 * @param contract the contract from which to populate this builder
234 * @return an instance of the builder populated with data from the contract
235 * @throws IllegalArgumentException if the contract is null
236 */
237 public static Builder create(ActionDefinitionContract contract) {
238 if (contract == null) {
239 throw new IllegalArgumentException("contract is null");
240 }
241 Builder builder = new Builder(contract.getId(), contract.getName(),
242 contract.getNamespace(), contract.getTypeId(), contract.getRuleId(),
243 contract.getSequenceNumber());
244 builder.setDescription(contract.getDescription());
245 if (contract.getAttributes() != null){
246 builder.setAttributes(new HashMap<String, String>(contract.getAttributes()));
247 }
248 builder.setVersionNumber(contract.getVersionNumber());
249 return builder;
250 }
251
252 /**
253 * Sets the value of the id on this builder to the given value.
254 *
255 * @param actionId the actionId value to set, must no tbe null or blank
256 * @throws IllegalArgumentException if the actionId is non-null and blank
257 */
258 public void setId(String actionId) {
259 if (actionId != null && StringUtils.isBlank(actionId)) {
260 throw new IllegalArgumentException("action ID must be null or non-blank");
261 }
262 this.id = actionId;
263 }
264
265
266 /**
267 * Sets the value of the name on this builder to the given value.
268 *
269 * @param name the name value to set, must not be null or blank
270 * @throws IllegalArgumentException if the name is non-null and blank
271 */
272 public void setName(String name) {
273 if (StringUtils.isBlank(name)) {
274 throw new IllegalArgumentException("name is blank");
275 }
276 this.name = name;
277 }
278
279 /**
280 * Sets the value of the namespace on this builder to the given value.
281 *
282 * @param namespace the namespace value to set, must not be null or blank
283 * @throws IllegalArgumentException if the namespace is non-null and blank
284 */
285 public void setNamespace(String namespace) {
286 if (StringUtils.isBlank(namespace)) {
287 throw new IllegalArgumentException("namespace is blank");
288 }
289 this.namespace = namespace;
290 }
291
292 /**
293 * Sets the value of the description on this builder to the given value.
294 *
295 * @param desc the description value to set
296 */
297 public void setDescription(String desc) {
298 this.description = desc;
299 }
300
301 /**
302 * Sets the value of the typeId on this builder to the given value.
303 *
304 * @param typeId the typeId value to set, must not be null or blank.
305 * @throws IllegalArgumentException if the typeId is null or blank
306 */
307 public void setTypeId(String typeId) {
308 if (StringUtils.isBlank(typeId)) {
309 throw new IllegalArgumentException("KRMS type id is blank");
310 }
311 this.typeId = typeId;
312 }
313
314 /**
315 * Sets the value of the ruleId on this builder to the given value.
316 *
317 * @param ruleId the ruleId value to set, must not be null or blank
318 * @throws IllegalArgumentException if the ruleId is null or blank
319 */
320 public void setRuleId(String ruleId) {
321 if (StringUtils.isBlank(ruleId)) {
322 throw new IllegalArgumentException("rule id is blank");
323 }
324 this.ruleId = ruleId;
325 }
326
327 /**
328 * Sets the value of the sequenceNumber on this builder to the given value.
329 *
330 * @param sequenceNumber the sequenceNumber value to set, must not be null or blank
331 * @throws IllegalArgumentException if the sequenceNumber is null or blank
332 */
333 public void setSequenceNumber(Integer sequenceNumber) {
334 if (sequenceNumber == null) {
335 throw new IllegalArgumentException("sequence number is null");
336 }
337 this.sequenceNumber = sequenceNumber;
338 }
339
340 /**
341 * Sets the value of the attributes on this builder to the given value.
342 *
343 * @param attributes the attributes value to set, can be null
344 */
345 public void setAttributes(Map<String, String> attributes){
346 if (attributes == null){
347 this.attributes = Collections.emptyMap();
348 }
349 this.attributes = Collections.unmodifiableMap(attributes);
350 }
351
352 /**
353 * Sets the value of the versionNumber on this builder to the given value.
354 *
355 * @param versionNumber the versionNumber value to set
356 */
357 public void setVersionNumber(Long versionNumber){
358 this.versionNumber = versionNumber;
359 }
360
361 @Override
362 public String getId() {
363 return id;
364 }
365
366 @Override
367 public String getName() {
368 return name;
369 }
370
371 @Override
372 public String getNamespace() {
373 return namespace;
374 }
375
376 @Override
377 public String getDescription() {
378 return description;
379 }
380
381 @Override
382 public String getTypeId() {
383 return typeId;
384 }
385
386 @Override
387 public String getRuleId() {
388 return ruleId;
389 }
390
391 @Override
392 public Integer getSequenceNumber() {
393 return sequenceNumber;
394 }
395
396 @Override
397 public Map<String, String> getAttributes() {
398 return attributes;
399 }
400
401 @Override
402 public Long getVersionNumber() {
403 return versionNumber;
404 }
405
406 /**
407 * Builds an instance of a Action based on the current state of the builder.
408 *
409 * @return the fully-constructed Action
410 */
411 @Override
412 public ActionDefinition build() {
413 return new ActionDefinition(this);
414 }
415
416 }
417
418 /**
419 * Defines some internal constants used on this class.
420 */
421 static class Constants {
422 final static String ROOT_ELEMENT_NAME = "action";
423 final static String TYPE_NAME = "ActionType";
424 }
425
426 /**
427 * A private class which exposes constants which define the XML element names to use
428 * when this object is marshalled to XML.
429 */
430 public static class Elements {
431 final static String ID = "id";
432 final static String NAME = "name";
433 final static String NAMESPACE = "namespace";
434 final static String DESC = "description";
435 final static String TYPE_ID = "typeId";
436 final static String RULE_ID = "ruleId";
437 final static String SEQUENCE_NUMBER = "sequenceNumber";
438 final static String ATTRIBUTES = "attributes";
439 }
440
441 }