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 */ 016package org.kuali.rice.krms.api.repository.proposition; 017 018import java.io.Serializable; 019import java.util.Collection; 020 021import javax.xml.bind.annotation.XmlAccessType; 022import javax.xml.bind.annotation.XmlAccessorType; 023import javax.xml.bind.annotation.XmlAnyElement; 024import javax.xml.bind.annotation.XmlElement; 025import javax.xml.bind.annotation.XmlRootElement; 026import javax.xml.bind.annotation.XmlType; 027 028import org.apache.commons.lang.StringUtils; 029import org.kuali.rice.core.api.CoreConstants; 030import org.kuali.rice.core.api.mo.AbstractDataTransferObject; 031import org.kuali.rice.core.api.mo.ModelBuilder; 032import org.kuali.rice.krms.api.repository.term.TermDefinition; 033import org.kuali.rice.krms.impl.repository.PropositionParameterBo; 034 035/** 036 * Concrete model object implementation of KRMS Proposition Parameter 037 * immutable. 038 * Instances of PropositionParameter can be (un)marshalled to and from XML. 039 * 040 * @see PropositionParameterContract 041 */ 042@XmlRootElement(name = PropositionParameter.Constants.ROOT_ELEMENT_NAME) 043@XmlAccessorType(XmlAccessType.NONE) 044@XmlType(name = PropositionParameter.Constants.TYPE_NAME, propOrder = { 045 PropositionParameter.Elements.ID, 046 PropositionParameter.Elements.PROP_ID, 047 PropositionParameter.Elements.VALUE, 048 PropositionParameter.Elements.TERM_VALUE, 049 PropositionParameter.Elements.PARM_TYPE, 050 PropositionParameter.Elements.SEQUENCE, 051 CoreConstants.CommonElements.VERSION_NUMBER, 052 CoreConstants.CommonElements.FUTURE_ELEMENTS 053}) 054public final class PropositionParameter extends AbstractDataTransferObject implements PropositionParameterContract { 055 private static final long serialVersionUID = 2783959459503209577L; 056 057 @XmlElement(name = PropositionParameter.Elements.ID, required=true) 058 private String id; 059 @XmlElement(name = PropositionParameter.Elements.PROP_ID, required=true) 060 private String propId; 061 @XmlElement(name = PropositionParameter.Elements.VALUE, required=true) 062 private String value; 063 @XmlElement(name = PropositionParameter.Elements.TERM_VALUE, required=true) 064 private TermDefinition termValue; 065 @XmlElement(name = PropositionParameter.Elements.PARM_TYPE, required=true) 066 private String parameterType; 067 @XmlElement(name = PropositionParameter.Elements.SEQUENCE, required=true) 068 private Integer sequenceNumber; 069 @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false) 070 private final Long versionNumber; 071 072 @SuppressWarnings("unused") 073 @XmlAnyElement 074 private final Collection<org.w3c.dom.Element> _futureElements = null; 075 076 /** 077 * This constructor should never be called. 078 * It is only present for use during JAXB unmarshalling. 079 */ 080 private PropositionParameter() { 081 this.id = null; 082 this.propId = null; 083 this.value = null; 084 this.termValue = null; 085 this.parameterType = null; 086 this.sequenceNumber = null; 087 this.versionNumber = null; 088 } 089 090 /** 091 * Constructs a PropositionParameter from the given builder. 092 * This constructor is private and should only ever be invoked from the builder. 093 * 094 * @param builder the Builder from which to construct the PropositionParameter 095 */ 096 private PropositionParameter(PropositionParameter.Builder builder) { 097 this.id = builder.getId(); 098 this.propId = builder.getPropId(); 099 this.value = builder.getValue(); 100 this.termValue = builder.getTermValue(); 101 this.parameterType = builder.getParameterType(); 102 this.sequenceNumber = builder.getSequenceNumber(); 103 this.versionNumber = builder.getVersionNumber(); 104 } 105 106 @Override 107 public String getId() { 108 return this.id; 109 } 110 111 @Override 112 public String getPropId() { 113 return this.propId; 114 } 115 116 @Override 117 public String getValue() { 118 return this.value; 119 } 120 121 public TermDefinition getTermValue() { 122 return this.termValue; 123 } 124 125 @Override 126 public String getParameterType() { 127 return this.parameterType; 128 } 129 @Override 130 public Integer getSequenceNumber() { 131 return this.sequenceNumber; 132 } 133 134 @Override 135 public Long getVersionNumber() { 136 return versionNumber; 137 } 138 139 /** 140 * This builder is used to construct instances of PropositionParameter. 141 * It enforces the constraints of the {@link PropositionParameterContract}. 142 */ 143 public static class Builder implements PropositionParameterContract, ModelBuilder, Serializable { 144 private static final long serialVersionUID = -6889320709850568900L; 145 146 private String id; 147 private String propId; 148 private String value; 149 private TermDefinition termValue; 150 private String parameterType; 151 private Integer sequenceNumber; 152 private Long versionNumber; 153 private PropositionDefinition.Builder proposition; 154 155 /** 156 * Private constructor for creating a builder with all of it's required attributes. 157 * @param id the id value to set, must not be null or blank 158 * @param propId the propId value to set, must not be null or blank 159 * @param value the value value to set, must not be null or blank 160 * @param parameterType the value parameterType to set, must not be null or blank 161 * @param sequenceNumber the value sequenceNumber to set, must not be null or blank 162 */ 163 private Builder(String id, String propId, String value, String parameterType, Integer sequenceNumber) { 164 setId(id); 165 setPropId(propId); 166 this.value = value; 167 setTermValue(null); 168 setParameterType(parameterType); 169 setSequenceNumber(sequenceNumber); 170 } 171 172 /** 173 * Create a builder using the given values 174 * @param id the id value to set, must not be null or blank 175 * @param propId the propId value to set, must not be null or blank 176 * @param value the value value to set, must not be null or blank 177 * @param parameterType the value parameterType to set, must not be null or blank 178 * @param sequenceNumber the value sequenceNumber to set, must not be null or blank 179 * @return Builder with the given values set 180 */ 181 public static PropositionParameter.Builder create(String id, String propId, String value, String parameterType, Integer sequenceNumber) { 182 return new PropositionParameter.Builder(id, propId, value, parameterType, sequenceNumber); 183 } 184 185 /** 186 * Creates a builder by populating it with data from the given {@link PropositionParameterContract}. 187 * 188 * @param contract the contract from which to populate this builder 189 * @return an instance of the builder populated with data from the contract 190 */ 191 public static PropositionParameter.Builder create(PropositionParameterContract contract) { 192 if (contract == null) { 193 throw new IllegalArgumentException("contract is null"); 194 } 195 PropositionParameter.Builder builder = new PropositionParameter.Builder(contract.getId(), contract.getPropId(), contract.getValue(), contract.getParameterType(), contract.getSequenceNumber()); 196 builder.setVersionNumber(contract.getVersionNumber()); 197 198 //TODO: this if statement should be removed once propositionparameterbo also implements the new interface. 199 if (!(contract instanceof PropositionParameterBo)){ 200 builder.setTermValue(contract.getTermValue()); 201 } 202 return builder; 203 } 204 205 /** 206 * Creates a builder by populating it with data from the given {@link PropositionParameterContract}. 207 * 208 * @param propositionParameter the contract from which to populate this builder 209 * @return an instance of the builder populated with data from the contract 210 */ 211 public static PropositionParameter.Builder create(PropositionParameter propositionParameter) { 212 if (propositionParameter == null) { 213 throw new IllegalArgumentException("parameter is null"); 214 } 215 PropositionParameter.Builder builder = new PropositionParameter.Builder(propositionParameter.getId(), propositionParameter.getPropId(), propositionParameter.getValue(), propositionParameter.getParameterType(), propositionParameter.getSequenceNumber()); 216 builder.setVersionNumber(propositionParameter.getVersionNumber()); 217 builder.setTermValue(propositionParameter.getTermValue()); 218 return builder; 219 } 220 221 222 /** 223 * Creates a builder by populating it with data from the given {@link PropositionParameterContract}. 224 * 225 * @param inputBuilder the contract from which to populate this builder 226 * @return an instance of the builder populated with data from the contract 227 */ 228 public static PropositionParameter.Builder create(PropositionParameter.Builder inputBuilder) { 229 if (inputBuilder == null) { 230 throw new IllegalArgumentException("inputBuilder is null"); 231 } 232 PropositionParameter.Builder builder = new PropositionParameter.Builder(inputBuilder.getId(), inputBuilder.getPropId(), inputBuilder.getValue(), inputBuilder.getParameterType(), inputBuilder.getSequenceNumber()); 233 builder.setVersionNumber(inputBuilder.getVersionNumber()); 234 builder.setTermValue(inputBuilder.getTermValue()); 235 return builder; 236 } 237 238 /** 239 * Sets the value of the id on this builder to the given value. 240 * 241 * @param id the id value to set, must not be null or blank 242 * @throws IllegalArgumentException if the id is null or blank 243 */ 244 public void setId(String id) { 245 if (id != null && StringUtils.isBlank(id)) { 246 throw new IllegalArgumentException("id must not be null or blank"); 247 } 248 this.id = id; 249 } 250 251 /** 252 * Sets the value of the propId on this builder to the given value. 253 * 254 * @param propId the propId value to set, must not be null or blank 255 * @throws IllegalArgumentException if the propId is null or blank 256 */ 257 public void setPropId(String propId) { 258 // have to be able to create it with a null propId for chicken/egg reasons. 259 if (null != propId && StringUtils.isBlank(propId)) { 260 throw new IllegalArgumentException("propId must be not be null or blank"); 261 } 262 this.propId = propId; 263 } 264 265 /** 266 * Sets the value of the value on this builder to the given value. 267 * 268 * @param value the value value to set, may be null, otherwise must contain non-whitespace 269 */ 270 public void setValue(String value) { 271 if (value != null && "".equals(value.trim())) { 272 throw new IllegalArgumentException("value must contain non-whitespace characters"); 273 } 274 this.value = value; 275 } 276 277 /** 278 * Sets the value of the termValue on this builder to the given value. 279 * 280 * @param termValue the termValue value to set, may be null 281 */ 282 public void setTermValue(TermDefinition termValue) { 283 this.termValue = termValue; 284 } 285 286 /** 287 * Sets the value of the parameterType on this builder to the given value. 288 * 289 * @param parameterType the value parameterType to set, must not be null or blank 290 * @throws IllegalArgumentException if the parameterType is null, blank, or invalid 291 */ 292 public void setParameterType(String parameterType) { 293 if (StringUtils.isBlank(parameterType)){ 294 throw new IllegalArgumentException("parameter type is null or blank"); 295 } 296 if (!PropositionParameterType.VALID_TYPE_CODES.contains(parameterType)){ 297 throw new IllegalArgumentException("parameter type is invalid"); 298 } 299 // TODO: check against valid values 300 this.parameterType = parameterType; 301 } 302 303 /** 304 * Sets the value of the sequenceNumber on this builder to the given value. 305 * 306 * @param sequenceNumber the value sequenceNumber to set, must not be null or blank 307 * @throws IllegalArgumentException if the sequenceNumber is null, blank, or invalid 308 */ 309 public void setSequenceNumber(Integer sequenceNumber) { 310 if (sequenceNumber == null) { 311 throw new IllegalArgumentException("sequenceNumber type is blank"); 312 } 313 this.sequenceNumber = sequenceNumber; 314 } 315 316 /** 317 * Sets the value of the proposition on this builder to the given value. 318 * 319 * @param proposition the value proposition to set 320 */ 321 public void setProposition(PropositionDefinition.Builder proposition) { 322 if (proposition != null && !StringUtils.isBlank(proposition.getId())) { 323 setPropId(proposition.getId()); 324 } 325 this.proposition = proposition; 326 } 327 328 /** 329 * Sets the value of the versionNumber on this builder to the given value. 330 * 331 * @param versionNumber the value versionNumber to set 332 */ 333 public void setVersionNumber(Long versionNumber){ 334 this.versionNumber = versionNumber; 335 } 336 337 @Override 338 public String getId() { 339 return id; 340 } 341 342 @Override 343 public String getPropId() { 344 return propId; 345 } 346 347 @Override 348 public String getValue() { 349 return value; 350 } 351 352 @Override 353 public TermDefinition getTermValue() { 354 return termValue; 355 } 356 357 @Override 358 public String getParameterType() { 359 return parameterType; 360 } 361 362 @Override 363 public Integer getSequenceNumber() { 364 return sequenceNumber; 365 } 366 367 @Override 368 public Long getVersionNumber() { 369 return versionNumber; 370 } 371 372 /** 373 * Builds an instance of a PropositionParameter based on the current state of the builder. 374 * 375 * @return the fully-constructed PropositionParameter 376 */ 377 @Override 378 public PropositionParameter build() { 379 if (proposition == null && StringUtils.isBlank(propId)) { 380 throw new IllegalStateException("either proposition must be non-null or propId must be non-blank"); 381 } 382 return new PropositionParameter(this); 383 } 384 385 } 386 387 /** 388 * Defines some internal constants used on this class. 389 */ 390 static class Constants { 391 final static String ROOT_ELEMENT_NAME = "PropositionParameter"; 392 final static String TYPE_NAME = "PropositionParameterType"; 393 } 394 395 /** 396 * A private class which exposes constants which define the XML element names to use 397 * when this object is marshalled to XML. 398 */ 399 public static class Elements { 400 final static String ID = "id"; 401 final static String PROP_ID = "propId"; 402 final static String VALUE = "value"; 403 final static String TERM_VALUE = "termValue"; 404 final static String PARM_TYPE = "parameterType"; 405 final static String SEQUENCE = "sequenceNumber"; 406 } 407 408}