1 package org.kuali.rice.krms.api.repository.rule;
2
3 import java.io.Serializable;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.HashMap;
8 import java.util.List;
9 import java.util.Map;
10
11 import javax.xml.bind.annotation.XmlAccessType;
12 import javax.xml.bind.annotation.XmlAccessorType;
13 import javax.xml.bind.annotation.XmlAnyElement;
14 import javax.xml.bind.annotation.XmlElement;
15 import javax.xml.bind.annotation.XmlElementWrapper;
16 import javax.xml.bind.annotation.XmlRootElement;
17 import javax.xml.bind.annotation.XmlTransient;
18 import javax.xml.bind.annotation.XmlType;
19 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
20
21 import org.apache.commons.lang.StringUtils;
22 import org.apache.commons.lang.builder.EqualsBuilder;
23 import org.apache.commons.lang.builder.HashCodeBuilder;
24 import org.apache.commons.lang.builder.ToStringBuilder;
25 import org.kuali.rice.core.api.CoreConstants;
26 import org.kuali.rice.core.api.mo.ModelBuilder;
27 import org.kuali.rice.core.api.mo.ModelObjectComplete;
28 import org.kuali.rice.core.util.jaxb.MapStringStringAdapter;
29 import org.kuali.rice.krms.api.repository.action.ActionDefinition;
30 import org.kuali.rice.krms.api.repository.action.ActionDefinitionContract;
31 import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
32
33
34
35
36
37
38
39
40 @XmlRootElement(name = RuleDefinition.Constants.ROOT_ELEMENT_NAME)
41 @XmlAccessorType(XmlAccessType.NONE)
42 @XmlType(name = RuleDefinition.Constants.TYPE_NAME, propOrder = {
43 RuleDefinition.Elements.ID,
44 RuleDefinition.Elements.NAME,
45 RuleDefinition.Elements.NAMESPACE,
46 RuleDefinition.Elements.DESCRIPTION,
47 RuleDefinition.Elements.TYPE_ID,
48 RuleDefinition.Elements.PROPOSITION,
49 RuleDefinition.Elements.ACTIONS,
50 RuleDefinition.Elements.ATTRIBUTES,
51 CoreConstants.CommonElements.VERSION_NUMBER,
52 CoreConstants.CommonElements.FUTURE_ELEMENTS
53 })
54 public final class RuleDefinition implements RuleDefinitionContract, ModelObjectComplete{
55 private static final long serialVersionUID = 2783959459503209577L;
56
57 @XmlElement(name = Elements.ID, required=true)
58 private String id;
59 @XmlElement(name = Elements.NAME, required=true)
60 private String name;
61 @XmlElement(name = Elements.NAMESPACE, required=true)
62 private String namespace;
63 @XmlElement(name = Elements.DESCRIPTION, required=false)
64 private String description;
65 @XmlElement(name = Elements.TYPE_ID, required=true)
66 private String typeId;
67 @XmlElement(name = Elements.PROPOSITION, required=true)
68 private PropositionDefinition proposition;
69
70 @XmlElementWrapper(name = Elements.ACTIONS)
71 @XmlElement(name = Elements.ACTION, required=false)
72 private List<ActionDefinition> actions;
73
74 @XmlElement(name = Elements.ATTRIBUTES, required = false)
75 @XmlJavaTypeAdapter(value = MapStringStringAdapter.class)
76 private final Map<String, String> attributes;
77
78 @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
79 private final Long versionNumber;
80
81 @SuppressWarnings("unused")
82 @XmlAnyElement
83 private final Collection<org.w3c.dom.Element> _futureElements = null;
84
85 @XmlTransient
86 private String propId;
87
88
89
90
91
92 private RuleDefinition() {
93 this.id = null;
94 this.name = null;
95 this.namespace = null;
96 this.typeId = null;
97 this.propId = null;
98 this.proposition = null;
99 this.actions = null;
100 this.attributes = null;
101 this.versionNumber = null;
102 }
103
104
105
106
107
108
109
110 private RuleDefinition(Builder builder) {
111 this.id = builder.getId();
112 this.name = builder.getName();
113 this.namespace = builder.getNamespace();
114 this.typeId = builder.getTypeId();
115 this.propId = builder.getPropId();
116
117 if (builder.getProposition() != null) {
118 this.proposition = builder.getProposition().build();
119 }
120
121 List<ActionDefinition> actionList = new ArrayList<ActionDefinition> ();
122 if (builder.getActions() != null){
123 for (ActionDefinition.Builder b : builder.actions){
124 actionList.add(b.build());
125 }
126 this.actions = Collections.unmodifiableList(actionList);
127 }
128 if (builder.attributes != null){
129 this.attributes = Collections.unmodifiableMap(builder.getAttributes());
130 } else {
131 this.attributes = null;
132 }
133 this.versionNumber = builder.getVersionNumber();
134 }
135
136 @Override
137 public String getId() {
138 return this.id;
139 }
140
141 @Override
142 public String getName() {
143 return this.name;
144 }
145
146 public String getDescription() {
147 return this.description;
148 }
149
150 @Override
151 public String getNamespace() {
152 return this.namespace;
153 }
154
155 @Override
156 public String getTypeId() {
157 return this.typeId;
158 }
159
160 @Override
161 public String getPropId(){
162 return this.propId;
163 }
164
165 @Override
166 public PropositionDefinition getProposition(){
167 return this.proposition;
168 }
169
170 @Override
171 public List<ActionDefinition> getActions(){
172 return this.actions;
173 }
174
175 @Override
176 public Map<String, String> getAttributes() {
177 return this.attributes;
178 }
179
180 @Override
181 public Long getVersionNumber() {
182 return versionNumber;
183 }
184
185
186
187
188 public static class Builder implements RuleDefinitionContract, ModelBuilder, Serializable {
189 private static final long serialVersionUID = -7850514191699945347L;
190
191 private String id;
192 private String name;
193 private String description;
194 private String namespace;
195 private String typeId;
196 private String propId;
197 private PropositionDefinition.Builder proposition;
198 private List<ActionDefinition.Builder> actions;
199 private Map<String, String> attributes;
200 private Long versionNumber;
201
202
203
204
205 private Builder(String ruleId, String name, String namespace, String typeId, String propId) {
206 setId(ruleId);
207 setName(name);
208 setNamespace(namespace);
209 setTypeId(typeId);
210 setPropId(propId);
211 setAttributes(new HashMap<String, String>());
212 }
213
214 public static Builder create(String ruleId, String name, String namespace, String typeId, String propId){
215 return new Builder(ruleId, name, namespace, typeId, propId);
216 }
217
218
219
220
221
222
223
224 public static Builder create(RuleDefinitionContract contract) {
225 if (contract == null) {
226 throw new IllegalArgumentException("contract is null");
227 }
228
229 List <ActionDefinition.Builder> actionList = new ArrayList<ActionDefinition.Builder>();
230 if (contract.getActions() != null){
231 for (ActionDefinitionContract actionContract : contract.getActions()){
232 ActionDefinition.Builder actBuilder = ActionDefinition.Builder.create(actionContract);
233 actionList.add(actBuilder);
234 }
235 }
236
237 Builder builder = new Builder(contract.getId(), contract.getName(),
238 contract.getNamespace(), contract.getTypeId(), contract.getPropId());
239 if (contract.getProposition() != null) {
240 builder.setProposition(PropositionDefinition.Builder.create(contract.getProposition()));
241 }
242 if (contract.getAttributes() != null){
243 builder.setAttributes(new HashMap<String, String>(contract.getAttributes()));
244 }
245 builder.setActions(actionList);
246 builder.setVersionNumber(contract.getVersionNumber());
247 builder.setDescription(contract.getDescription());
248 return builder;
249 }
250
251
252
253
254
255
256
257
258 public void setId(String ruleId) {
259 if (ruleId != null && StringUtils.isBlank(ruleId)) {
260 throw new IllegalArgumentException("rule ID must be null or else non-blank");
261 }
262 this.id = ruleId;
263 }
264
265 public void setName(String name) {
266 if (StringUtils.isBlank(name)) {
267 throw new IllegalArgumentException("name is blank");
268 }
269 this.name = name;
270 }
271
272 public void setDescription(String description) {
273 if (description != null && StringUtils.isBlank(description)) {
274 throw new IllegalArgumentException("description is non-null but is blank");
275 }
276 this.description = description;
277 }
278
279 public void setNamespace(String namespace) {
280 if (StringUtils.isBlank(namespace)) {
281 throw new IllegalArgumentException("namespace is blank");
282 }
283 this.namespace = namespace;
284 }
285
286 public void setTypeId(String typeId) {
287 if (StringUtils.isBlank(typeId)) {
288 throw new IllegalArgumentException("KRMS type id is blank");
289 }
290 this.typeId = typeId;
291 }
292
293 public void setPropId(String propId) {
294 if (propId != null && StringUtils.isBlank(propId)) {
295 throw new IllegalArgumentException("propId must be null or non-blank");
296 }
297 this.propId = propId;
298 }
299
300 public void setProposition(PropositionDefinition.Builder prop) {
301 this.proposition = prop;
302 this.setPropId(prop.getId());
303 }
304
305 public void setActions(List<ActionDefinition.Builder> actions) {
306 if (actions == null){
307 this.actions = Collections.unmodifiableList(new ArrayList<ActionDefinition.Builder>());
308 return;
309 }
310 this.actions = Collections.unmodifiableList(actions);
311 }
312
313 public void setAttributes(Map<String, String> attributes){
314 if (attributes == null){
315 this.attributes = Collections.emptyMap();
316 }
317 this.attributes = Collections.unmodifiableMap(attributes);
318 }
319
320 public void setVersionNumber(Long versionNumber){
321 this.versionNumber = versionNumber;
322 }
323
324 @Override
325 public String getId() {
326 return id;
327 }
328
329 @Override
330 public String getName() {
331 return name;
332 }
333
334 @Override
335 public String getDescription() {
336 return description;
337 }
338
339 @Override
340 public String getNamespace() {
341 return namespace;
342 }
343
344 @Override
345 public String getTypeId() {
346 return typeId;
347 }
348
349 @Override
350 public String getPropId() {
351 return propId;
352 }
353
354 @Override
355 public PropositionDefinition.Builder getProposition() {
356 return proposition;
357 }
358
359 @Override
360 public List<ActionDefinition.Builder> getActions(){
361 return actions;
362 }
363 @Override
364 public Map<String, String> getAttributes() {
365 return attributes;
366 }
367
368 @Override
369 public Long getVersionNumber() {
370 return versionNumber;
371 }
372
373
374
375
376
377
378 @Override
379 public RuleDefinition build() {
380 return new RuleDefinition(this);
381 }
382
383 }
384 @Override
385 public int hashCode() {
386 return HashCodeBuilder.reflectionHashCode(this, Constants.HASH_CODE_EQUALS_EXCLUDE);
387 }
388
389 @Override
390 public boolean equals(Object obj) {
391 return EqualsBuilder.reflectionEquals(obj, this, Constants.HASH_CODE_EQUALS_EXCLUDE);
392 }
393
394 @Override
395 public String toString() {
396 return ToStringBuilder.reflectionToString(this);
397 }
398
399
400
401
402 public static class Constants {
403 final static String ROOT_ELEMENT_NAME = "rule";
404 final static String TYPE_NAME = "RuleType";
405 final static String[] HASH_CODE_EQUALS_EXCLUDE = { CoreConstants.CommonElements.FUTURE_ELEMENTS };
406 }
407
408
409
410
411
412 public static class Elements {
413 final static String ID = "id";
414 final static String NAME = "name";
415 final static String DESCRIPTION = "description";
416 final static String NAMESPACE = "namespace";
417 final static String TYPE_ID = "typeId";
418 final static String PROPOSITION = "proposition";
419 final static String ACTIONS = "actions";
420 final static String ACTION = "action";
421 final static String ATTRIBUTES = "attributes";
422 }
423
424 }