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