001    /**
002     * Copyright 2005-2014 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    
034    /**
035     * Concrete model object implementation of KRMS Proposition Parameter 
036     * immutable. 
037     * Instances of PropositionParameter can be (un)marshalled to and from XML.
038     *
039     * @see PropositionParameterContract
040     */
041    @XmlRootElement(name = PropositionParameter.Constants.ROOT_ELEMENT_NAME)
042    @XmlAccessorType(XmlAccessType.NONE)
043    @XmlType(name = PropositionParameter.Constants.TYPE_NAME, propOrder = {
044                    PropositionParameter.Elements.ID,
045                    PropositionParameter.Elements.PROP_ID,
046                    PropositionParameter.Elements.VALUE,
047                    PropositionParameter.Elements.PARM_TYPE,
048                    PropositionParameter.Elements.SEQUENCE,
049            CoreConstants.CommonElements.VERSION_NUMBER,
050            PropositionParameter.Elements.TERM_VALUE,
051                    CoreConstants.CommonElements.FUTURE_ELEMENTS
052    })
053    public final class PropositionParameter extends AbstractDataTransferObject implements PropositionParameterContract {
054            private static final long serialVersionUID = 2783959459503209577L;
055    
056            @XmlElement(name = Elements.ID, required=true)
057            private String id;
058            @XmlElement(name = Elements.PROP_ID, required=true)
059            private String propId;
060            @XmlElement(name = Elements.VALUE, required=true)
061            private String value;
062            @XmlElement(name = Elements.PARM_TYPE, required=true)
063            private String parameterType;
064            @XmlElement(name = Elements.SEQUENCE, required=true)
065            private Integer sequenceNumber;
066        @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
067        private final Long versionNumber;
068        @XmlElement(name = Elements.TERM_VALUE, required=false)
069        private TermDefinition termValue;
070    
071            @SuppressWarnings("unused")
072        @XmlAnyElement
073        private final Collection<org.w3c.dom.Element> _futureElements = null;
074            
075             /** 
076         * This constructor should never be called.  
077         * It is only present for use during JAXB unmarshalling. 
078         */
079        private PropositionParameter() {
080            this.id = null;
081            this.propId = null;
082            this.value = null;
083            this.termValue = null;
084            this.parameterType = null;
085            this.sequenceNumber = null;
086            this.versionNumber = null;
087        }
088        
089        /**
090             * Constructs a PropositionParameter from the given builder.  
091             * This constructor is private and should only ever be invoked from the builder.
092             * 
093             * @param builder the Builder from which to construct the PropositionParameter
094             */
095        private PropositionParameter(Builder builder) {
096            this.id = builder.getId();
097            this.propId = builder.getPropId();
098            this.value = builder.getValue();
099            this.termValue = builder.getTermValue();
100            this.parameterType = builder.getParameterType();
101            this.sequenceNumber = builder.getSequenceNumber();
102            this.versionNumber = builder.getVersionNumber();
103        }
104        
105            @Override
106            public String getId() {
107                    return this.id;
108            }
109            
110            @Override
111            public String getPropId() {
112                    return this.propId;
113            }
114    
115            @Override
116            public String getValue() {
117                    return this.value;
118            }
119            
120            @Override
121            public String getParameterType() {
122                    return this.parameterType;
123            }
124            @Override
125            public Integer getSequenceNumber() {
126                    return this.sequenceNumber; 
127            }
128    
129        @Override
130        public Long getVersionNumber() {
131            return versionNumber;
132        }
133    
134        @Override
135        public TermDefinition getTermValue() {
136            return this.termValue;
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                setValue(value);
167                setParameterType(parameterType);
168                            setSequenceNumber(sequenceNumber);
169            }
170    
171            /**
172             * Create a builder using the given values
173             * @param id the id value to set, must not be null or blank
174             * @param propId the propId value to set, must not be null or blank
175             * @param value the value value to set, must not be null or blank
176             * @param parameterType the value parameterType to set, must not be null or blank
177             * @param sequenceNumber the value sequenceNumber to set, must not be null or blank
178             * @return Builder with the given values set
179             */
180            public static Builder create(String id, String propId, String value, String parameterType, Integer sequenceNumber) {
181                    return new Builder(id, propId, value, parameterType, sequenceNumber);
182            }
183    
184            /**
185             * Creates a builder by populating it with data from the given {@link PropositionParameterContract}.
186             * 
187             * @param contract the contract from which to populate this builder
188             * @return an instance of the builder populated with data from the contract
189             */
190            public static Builder create(PropositionParameterContract contract) {
191                    if (contract == null) {
192                    throw new IllegalArgumentException("contract is null");
193                }
194    
195                Builder builder =  new Builder(contract.getId(), contract.getPropId(), contract.getValue(), contract.getParameterType(), contract.getSequenceNumber());
196                builder.setVersionNumber(contract.getVersionNumber());
197                builder.setTermValue(contract.getTermValue());
198    
199                return builder;
200            }
201    
202            /**
203             * Creates a builder by populating it with data from the given {@link PropositionParameterContract}.
204             * 
205             * @param propositionParameter the contract from which to populate this builder
206             * @return an instance of the builder populated with data from the contract
207             */
208            public static PropositionParameter.Builder create(PropositionParameter propositionParameter) {
209                    if (propositionParameter == null) {
210                    throw new IllegalArgumentException("parameter is null");
211                }
212    
213                Builder builder =  new Builder(propositionParameter.getId(), propositionParameter.getPropId(), propositionParameter.getValue(), propositionParameter.getParameterType(), propositionParameter.getSequenceNumber());
214                builder.setVersionNumber(propositionParameter.getVersionNumber());
215                builder.setTermValue(propositionParameter.getTermValue());
216    
217                return builder;
218            }
219    
220    
221            /**
222             * Creates a builder by populating it with data from the given {@link PropositionParameterContract}.
223             * 
224             * @param inputBuilder the contract from which to populate this builder
225             * @return an instance of the builder populated with data from the contract
226             */
227            public static PropositionParameter.Builder create(Builder inputBuilder) {
228                    if (inputBuilder == null) {
229                    throw new IllegalArgumentException("inputBuilder is null");
230                }
231                Builder builder =  new Builder(inputBuilder.getId(), inputBuilder.getPropId(), inputBuilder.getValue(), inputBuilder.getParameterType(), inputBuilder.getSequenceNumber());
232                builder.setVersionNumber(inputBuilder.getVersionNumber());
233                builder.setTermValue(inputBuilder.getTermValue());
234                return builder;
235            }
236    
237                    /**
238                     * Sets the value of the id on this builder to the given value.
239                     * 
240                     * @param id the id value to set, must not be null or blank
241                     * @throws IllegalArgumentException if the id is null or blank
242                     */
243            public void setId(String id) {
244                if (id != null && StringUtils.isBlank(id)) {
245                    throw new IllegalArgumentException("id must not be null or blank");
246                }
247                this.id = id;
248            }
249    
250            /**
251             * Sets the value of the propId on this builder to the given value.
252             *
253             * @param propId the propId value to set, must not be null or blank
254             * @throws IllegalArgumentException if the propId is null or blank
255             */
256                    public void setPropId(String propId) {
257                        // have to be able to create it with a null propId for chicken/egg reasons.
258                if (null != propId && StringUtils.isBlank(propId)) {
259                    throw new IllegalArgumentException("propId must be not be null or blank");
260                }
261                            this.propId = propId;
262                    }
263    
264            /**
265             * Sets the value of the value on this builder to the given value.
266             *
267             * @param value the value value to set, may be null, otherwise must contain non-whitespace
268             * @throws IllegalArgumentException if the value is all whitespace characters
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    }