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     */
016    package org.kuali.rice.krms.api.repository.proposition;
017    
018    import java.io.Serializable;
019    import java.util.Collection;
020    
021    import javax.xml.bind.annotation.XmlAccessType;
022    import javax.xml.bind.annotation.XmlAccessorType;
023    import javax.xml.bind.annotation.XmlAnyElement;
024    import javax.xml.bind.annotation.XmlElement;
025    import javax.xml.bind.annotation.XmlRootElement;
026    import javax.xml.bind.annotation.XmlType;
027    
028    import org.apache.commons.lang.StringUtils;
029    import org.kuali.rice.core.api.CoreConstants;
030    import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
031    import org.kuali.rice.core.api.mo.ModelBuilder;
032    import org.kuali.rice.krms.api.repository.term.TermDefinition;
033    import 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    })
054    public 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    }