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