Coverage Report - org.kuali.rice.krms.api.repository.proposition.PropositionDefinition
 
Classes in this File Line Coverage Branch Coverage Complexity
PropositionDefinition
90%
38/42
100%
6/6
1.692
PropositionDefinition$1
N/A
N/A
1.692
PropositionDefinition$Builder
87%
69/79
73%
25/34
1.692
PropositionDefinition$Constants
50%
1/2
N/A
1.692
PropositionDefinition$Elements
0%
0/1
N/A
1.692
 
 1  
 package org.kuali.rice.krms.api.repository.proposition;
 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.List;
 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.XmlElementWrapper;
 14  
 import javax.xml.bind.annotation.XmlRootElement;
 15  
 import javax.xml.bind.annotation.XmlType;
 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.krms.api.repository.LogicalOperator;
 25  
 import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
 26  
 import org.kuali.rice.krms.api.repository.rule.RuleDefinition.Elements;
 27  
 
 28  
 
 29  
 /**
 30  
  * Concrete model object implementation of KRMS Proposition. 
 31  
  * Immutable. 
 32  
  * Instances of Proposition can be (un)marshalled to and from XML.
 33  
  *
 34  
  * There are three main types of Propositions:
 35  
  *    1. Compound Propositions - a proposition consisting of other propositions
 36  
  *             and a boolean algebra operator (AND, OR) defining how to evaluate those propositions.
 37  
  *    2. Parameterized Propositions - a proposition which is parameterized by some set of values, 
 38  
  *             evaluation logic is implemented by hand and returns true or false
 39  
  *    3. Simple Propositions - a proposition of the form lhs op rhs where 
 40  
  *            lhs=left-hand side, rhs=right-hand side, and op=operator
 41  
  * Propositions are reference by a rule or another proposition (in the case of compound propositions).
 42  
  * Propositions are never re-used across multiple rules.
 43  
  * Each proposition can have zero or more parameters. The proposition parameter is the primary 
 44  
  * data element used to define the proposition.  (@see PropositionParameter)
 45  
  * 
 46  
  * @see PropositonContract
 47  
  * @see PropositionParameterContract
 48  
  */
 49  
 @XmlRootElement(name = PropositionDefinition.Constants.ROOT_ELEMENT_NAME)
 50  
 @XmlAccessorType(XmlAccessType.NONE)
 51  
 @XmlType(name = PropositionDefinition.Constants.TYPE_NAME, propOrder = {
 52  
                 PropositionDefinition.Elements.ID,
 53  
                 PropositionDefinition.Elements.DESC,
 54  
         PropositionDefinition.Elements.RULE_ID,
 55  
         PropositionDefinition.Elements.TYPE_ID,
 56  
                 PropositionDefinition.Elements.PROP_TYPE_CODE,
 57  
                 PropositionDefinition.Elements.PARAMETERS,                                                                        // xml element name differs from class property name
 58  
                 PropositionDefinition.Elements.CMPND_OP_CODE,
 59  
                 PropositionDefinition.Elements.CMPND_COMPONENTS,
 60  
         CoreConstants.CommonElements.VERSION_NUMBER,
 61  
                 CoreConstants.CommonElements.FUTURE_ELEMENTS
 62  
 })
 63  14
 public final class PropositionDefinition implements PropositionDefinitionContract, ModelObjectComplete{
 64  
         private static final long serialVersionUID = 2783959459503209577L;
 65  
 
 66  
         // TODO: change this to field name to id
 67  
         @XmlElement(name = Elements.ID, required=true)
 68  
         private String id;
 69  
         
 70  
         @XmlElement(name = Elements.DESC, required=true)
 71  
         private String description;
 72  
         
 73  
         @XmlElement(name = Elements.TYPE_ID, required=true)
 74  
         private String typeId;
 75  
         
 76  
     @XmlElement(name = Elements.RULE_ID, required=true)
 77  
     private String ruleId;
 78  
     
 79  
     @XmlElement(name = Elements.PROP_TYPE_CODE, required=true)
 80  
         private String propositionTypeCode;
 81  
 
 82  
         @XmlElementWrapper(name = Elements.PARAMETERS)
 83  
         @XmlElement(name = Elements.PARAMETER, required=false)
 84  
         private List<PropositionParameter> parameters;
 85  
         
 86  
         @XmlElement(name = Elements.CMPND_OP_CODE, required=false)
 87  
         private String compoundOpCode;
 88  
         
 89  
         @XmlElementWrapper(name = Elements.CMPND_COMPONENTS, required=false)
 90  
         @XmlElement(name = Elements.CMPND_COMPONENT, required=false)
 91  
         private List<PropositionDefinition> compoundComponents;
 92  
         
 93  
     @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
 94  
     private final Long versionNumber;
 95  
             
 96  35
         @SuppressWarnings("unused")
 97  
     @XmlAnyElement
 98  
     private final Collection<org.w3c.dom.Element> _futureElements = null;
 99  
         
 100  
         
 101  
          /** 
 102  
      * This constructor should never be called.  It is only present for use during JAXB unmarshalling. 
 103  
      */
 104  21
     private PropositionDefinition() {
 105  21
             this.id = null;
 106  21
             this.description = null;
 107  21
             this.typeId = null;
 108  21
             this.propositionTypeCode = null;
 109  21
             this.parameters = null;
 110  21
             this.compoundOpCode = null;
 111  21
             this.compoundComponents = null;
 112  21
         this.versionNumber = null;
 113  21
     }
 114  
     
 115  
     /**
 116  
          * Constructs a KRMS Proposition from the given builder.  
 117  
          * This constructor is private and should only ever be invoked from the builder.
 118  
          * 
 119  
          * @param builder the Builder from which to construct the KRMS Proposition
 120  
          */
 121  14
     private PropositionDefinition(Builder builder) {
 122  14
         this.id = builder.getId();
 123  14
         this.description = builder.getDescription();
 124  14
         this.ruleId = builder.getRuleId();
 125  14
         this.typeId = builder.getTypeId();
 126  14
         this.propositionTypeCode = builder.getPropositionTypeCode();
 127  
         
 128  
         // Build parameter list
 129  14
         List<PropositionParameter> paramList = new ArrayList<PropositionParameter>();
 130  14
         for (PropositionParameter.Builder b : builder.parameters){
 131  36
                 paramList.add(b.build());
 132  
         }
 133  14
         this.parameters = Collections.unmodifiableList(paramList);
 134  
         
 135  
         // Build Compound Proposition properties
 136  14
         this.compoundOpCode = builder.getCompoundOpCode();
 137  14
         List <PropositionDefinition> componentList = new ArrayList<PropositionDefinition>();
 138  14
         if (builder.compoundComponents != null){
 139  8
                 for (PropositionDefinition.Builder b : builder.compoundComponents){
 140  4
                         componentList.add(b.build());
 141  
                 }
 142  8
             this.compoundComponents = Collections.unmodifiableList(componentList);
 143  
         }
 144  14
         this.versionNumber = builder.getVersionNumber();
 145  14
     }
 146  
     
 147  
         @Override
 148  
         public String getId() {
 149  6
                 return this.id;
 150  
         }
 151  
 
 152  
         @Override
 153  
         public String getDescription() {
 154  9
                 return this.description;
 155  
         }
 156  
 
 157  
     /**
 158  
      * @return the ruleId
 159  
      */
 160  
     public String getRuleId() {
 161  0
         return this.ruleId;
 162  
     }
 163  
 
 164  
         @Override
 165  
         public String getTypeId() {
 166  6
                 return this.typeId;
 167  
         }
 168  
 
 169  
         @Override
 170  
         public String getPropositionTypeCode() {
 171  6
                 return this.propositionTypeCode; 
 172  
         }
 173  
 
 174  
         @Override
 175  
         public List<PropositionParameter> getParameters() {
 176  5
                 return this.parameters; 
 177  
         }
 178  
 
 179  
         @Override
 180  
         public String getCompoundOpCode() {
 181  1
                 return this.compoundOpCode; 
 182  
         }
 183  
 
 184  
         @Override
 185  
         public List<PropositionDefinition> getCompoundComponents() {
 186  11
                 return this.compoundComponents; 
 187  
         }
 188  
 
 189  
     @Override
 190  
     public Long getVersionNumber() {
 191  0
         return versionNumber;
 192  
     }
 193  
         
 194  
         /**
 195  
      * This builder is used to construct instances of KRMS Proposition.  It enforces the constraints of the {@link PropositionDefinitionContract}.
 196  
      */
 197  42
     public static class Builder implements PropositionDefinitionContract, ModelBuilder, Serializable {
 198  
             private static final long serialVersionUID = -6889320709850568900L;
 199  
                 
 200  
         private String id;
 201  
         private String description;
 202  
         private String ruleId;
 203  
         private String typeId;
 204  
         private String propositionTypeCode;
 205  
         private List<PropositionParameter.Builder> parameters;
 206  
         private String compoundOpCode;
 207  
         private List<PropositionDefinition.Builder> compoundComponents;
 208  
         private RuleDefinition.Builder rule;
 209  
         private Long versionNumber;
 210  
 
 211  
                 /**
 212  
                  * Private constructor for creating a builder with all of it's required attributes.
 213  
                  * @param typeId TODO
 214  
                  */
 215  27
         private Builder(String propId, String propTypeCode, String ruleId, String typeId, List<PropositionParameter.Builder> parameters) {
 216  27
                 setId(propId);
 217  25
                         setPropositionTypeCode(propTypeCode);
 218  20
                         setRuleId(ruleId);
 219  20
                         setTypeId(typeId);
 220  20
                         setParameters(parameters);
 221  20
         }
 222  
         
 223  
         public Builder compoundOpCode(String opCode){
 224  0
                 setCompoundOpCode(opCode);
 225  0
                 return this;
 226  
         }
 227  
         
 228  
         public Builder compoundComponents (List<PropositionDefinition.Builder> components){
 229  0
                 setCompoundComponents(components);
 230  0
                 return this;
 231  
         }
 232  
  
 233  
         public static Builder create(String propId, String propTypeCode, String ruleId, String typeId, List<PropositionParameter.Builder> parameters){
 234  16
                 return new Builder(propId, propTypeCode, ruleId, typeId, parameters);
 235  
         }
 236  
         
 237  
         /**
 238  
          * Creates a builder by populating it with data from the given {@link PropositionDefinitionContract}.
 239  
          * 
 240  
          * @param contract the contract from which to populate this builder
 241  
          * @return an instance of the builder populated with data from the contract
 242  
          */
 243  
         public static Builder create(PropositionDefinitionContract contract) {
 244  11
                 if (contract == null) {
 245  0
                 throw new IllegalArgumentException("contract is null");
 246  
             }
 247  11
                 List <PropositionParameter.Builder> paramBuilderList = new ArrayList<PropositionParameter.Builder>();
 248  11
                 if (contract.getParameters() != null){
 249  11
                         for (PropositionParameterContract paramContract : contract.getParameters()){
 250  24
                                 PropositionParameter.Builder myBuilder = PropositionParameter.Builder.create(paramContract);
 251  24
                                 paramBuilderList.add(myBuilder);
 252  24
                         }
 253  
                 }
 254  11
             Builder builder =  new Builder(contract.getId(), contract.getPropositionTypeCode(), contract.getRuleId(), contract.getTypeId(), paramBuilderList);
 255  
             
 256  11
                 List <PropositionDefinition.Builder> componentBuilderList = new ArrayList<PropositionDefinition.Builder>();
 257  11
                 if (contract.getCompoundComponents() != null) {
 258  11
                         for (PropositionDefinitionContract cContract : contract.getCompoundComponents()){
 259  6
                                 PropositionDefinition.Builder pBuilder = PropositionDefinition.Builder.create(cContract);
 260  6
                                 componentBuilderList.add(pBuilder);
 261  6
                         }
 262  11
                 builder.setCompoundComponents(componentBuilderList);
 263  
                 }
 264  11
                 builder.setCompoundOpCode(contract.getCompoundOpCode());
 265  11
             builder.setDescription(contract.getDescription());
 266  11
             builder.setVersionNumber(contract.getVersionNumber());
 267  11
             return builder;
 268  
         }
 269  
 
 270  
                 /**
 271  
                  * Sets the value of the id on this builder to the given value.
 272  
                  * 
 273  
                  * @param id the id value to set
 274  
                  */
 275  
 
 276  
         public void setId(String propId) {
 277  27
             if (propId != null && StringUtils.isBlank(propId)) {
 278  2
                 throw new IllegalArgumentException("proposition id must not be blank");                    
 279  
             }
 280  25
                         this.id = propId;
 281  25
                 }
 282  
 
 283  
                 public void setDescription(String desc) {
 284  16
                         this.description = desc;
 285  16
                 }
 286  
                 
 287  
         public void setTypeId(String typeId) {
 288  21
             this.typeId = typeId;
 289  21
         }
 290  
         
 291  
         public void setRuleId(String ruleId) {
 292  20
             this.ruleId = ruleId;
 293  20
         }
 294  
         
 295  
         public void setRule(RuleDefinition.Builder rule) {
 296  0
             if (rule != null && !StringUtils.isBlank(rule.getId())) {
 297  0
                 setRuleId(rule.getId());
 298  
             }
 299  0
             this.rule = rule;
 300  0
         }
 301  
         
 302  
                 public void setPropositionTypeCode(String propTypeCode) {
 303  25
                         if (StringUtils.isBlank(propTypeCode)) {
 304  4
                 throw new IllegalArgumentException("proposition type code is blank");
 305  
                         }
 306  21
                         if (!PropositionType.VALID_TYPE_CODES.contains(propTypeCode)) {
 307  1
                 throw new IllegalArgumentException("invalid proposition type code");
 308  
                         }
 309  20
                         this.propositionTypeCode = propTypeCode;
 310  20
                 }
 311  
                 
 312  
                 public void setParameters(List<PropositionParameter.Builder> parameters) {
 313  
                         // compound propositions have empty parameter lists
 314  
                         // Simple propositions must have a non-empty parameter list
 315  20
                         if (parameters == null || parameters.isEmpty()){
 316  5
                                 this.parameters = Collections.unmodifiableList(new ArrayList<PropositionParameter.Builder>());
 317  
                         } else {
 318  15
                             this.parameters = Collections.unmodifiableList(parameters);
 319  
                         }
 320  20
                 }
 321  
                 
 322  
                 public void setCompoundOpCode(String opCode){
 323  11
                         if (StringUtils.isBlank(opCode)){ return; }
 324  3
                         if (!LogicalOperator.OP_CODES.contains(opCode)){
 325  0
                                 throw new IllegalArgumentException("invalid opCode value");
 326  
                         }
 327  3
                         this.compoundOpCode = opCode;
 328  3
                 }
 329  
 
 330  
                 public void setCompoundComponents(List<PropositionDefinition.Builder> components){
 331  11
                         if (components == null || components.isEmpty()){
 332  8
                                 this.compoundComponents = Collections.unmodifiableList(new ArrayList<PropositionDefinition.Builder>());
 333  8
                                 return;
 334  
                         }
 335  3
                         this.compoundComponents = Collections.unmodifiableList(components);
 336  3
                 }
 337  
                 
 338  
         public void setVersionNumber(Long versionNumber){
 339  12
             this.versionNumber = versionNumber;
 340  12
         }
 341  
         
 342  
                 @Override
 343  
                 public String getId() {
 344  24
                         return id;
 345  
                 }
 346  
 
 347  
                 @Override
 348  
                 public String getDescription() {
 349  20
                         return description;
 350  
                 }
 351  
                 
 352  
                 @Override
 353  
                 public String getRuleId() {
 354  20
                     return ruleId;
 355  
                 }
 356  
 
 357  
                 @Override
 358  
                 public String getTypeId() {
 359  20
                         return typeId;
 360  
                 }
 361  
 
 362  
                 @Override
 363  
                 public String getPropositionTypeCode() {
 364  20
                         return propositionTypeCode;
 365  
                 }
 366  
                 
 367  
                 @Override
 368  
                 public List<PropositionParameter.Builder> getParameters() {
 369  12
                         return parameters;
 370  
                 }
 371  
 
 372  
                 @Override
 373  
                 public String getCompoundOpCode() {
 374  20
                         return compoundOpCode;
 375  
                 }
 376  
                 
 377  
                 @Override
 378  
                 public List<PropositionDefinition.Builder> getCompoundComponents() {
 379  12
                         return compoundComponents;
 380  
                 }
 381  
 
 382  
         @Override
 383  
         public Long getVersionNumber() {
 384  20
             return versionNumber;
 385  
         }
 386  
 
 387  
                 /**
 388  
                  * Builds an instance of a Proposition based on the current state of the builder.
 389  
                  * 
 390  
                  * @return the fully-constructed Proposition
 391  
                  */
 392  
         @Override
 393  
         public PropositionDefinition build() {
 394  14
             return new PropositionDefinition(this);
 395  
         }
 396  
                 
 397  
     }
 398  
     
 399  
     
 400  
         @Override
 401  
         public int hashCode() {
 402  0
                 return HashCodeBuilder.reflectionHashCode(this, Constants.HASH_CODE_EQUALS_EXCLUDE);
 403  
         }
 404  
 
 405  
         @Override
 406  
         public boolean equals(Object obj) {
 407  7
                 return EqualsBuilder.reflectionEquals(obj, this, Constants.HASH_CODE_EQUALS_EXCLUDE);
 408  
         }
 409  
 
 410  
         @Override
 411  
         public String toString() {
 412  0
                 return ToStringBuilder.reflectionToString(this);
 413  
         }
 414  
         
 415  
         /**
 416  
          * Defines some internal constants used on this class.
 417  
          */
 418  0
         static class Constants {
 419  
                 final static String ROOT_ELEMENT_NAME = "proposition";
 420  
                 final static String TYPE_NAME = "PropositionType";
 421  1
                 final static String[] HASH_CODE_EQUALS_EXCLUDE = { CoreConstants.CommonElements.FUTURE_ELEMENTS };
 422  
         }
 423  
         
 424  
         /**
 425  
          * A private class which exposes constants which define the XML element names to use
 426  
          * when this object is marshalled to XML.
 427  
          */
 428  0
         public static class Elements {
 429  
                 final static String ID = "id";
 430  
                 final static String DESC = "description";
 431  
         final static String RULE_ID = "ruleId";
 432  
                 final static String TYPE_ID = "typeId";
 433  
                 final static String PROP_TYPE_CODE = "propositionTypeCode";
 434  
                 final static String PARAMETER = "parameter";
 435  
                 final static String PARAMETERS = "parameters";
 436  
                 final static String CMPND_OP_CODE = "compoundOpCode";
 437  
                 final static String CMPND_COMPONENTS = "compoundComponents";
 438  
                 final static String CMPND_COMPONENT = "proposition";
 439  
         }
 440  
 
 441  
         
 442  
 }