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