001/**
002 * Copyright 2005-2016 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.term;
017
018import java.io.Serializable;
019import java.util.Collection;
020import java.util.List;
021
022import javax.xml.bind.annotation.XmlAccessType;
023import javax.xml.bind.annotation.XmlAccessorType;
024import javax.xml.bind.annotation.XmlAnyElement;
025import javax.xml.bind.annotation.XmlElement;
026import javax.xml.bind.annotation.XmlElementWrapper;
027import javax.xml.bind.annotation.XmlRootElement;
028import javax.xml.bind.annotation.XmlType;
029
030import org.apache.commons.lang.StringUtils;
031import org.jdom.IllegalAddException;
032import org.kuali.rice.core.api.CoreConstants;
033import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
034import org.kuali.rice.core.api.mo.ModelBuilder;
035import org.kuali.rice.krms.api.KrmsConstants;
036import org.kuali.rice.krms.api.repository.BuilderUtils;
037
038/**
039 * Immutable DTO for Terms.  Construction must be done via the {@link Builder} inner class.
040 * 
041 * @author Kuali Rice Team (rice.collab@kuali.org)
042 *
043 */
044@XmlRootElement(name = TermDefinition.Constants.ROOT_ELEMENT_NAME)
045@XmlAccessorType(XmlAccessType.NONE)
046@XmlType(name = TermDefinition.Constants.TYPE_NAME, propOrder = {
047                TermDefinition.Elements.ID,
048        TermDefinition.Elements.SPECIFICATION,
049        TermDefinition.Elements.DESCRIPTION,
050                TermDefinition.Elements.PARAMETERS,
051        CoreConstants.CommonElements.VERSION_NUMBER,
052                CoreConstants.CommonElements.FUTURE_ELEMENTS
053})
054public final class TermDefinition extends AbstractDataTransferObject implements TermDefinitionContract {
055        
056        private static final long serialVersionUID = 1L;
057        
058        @XmlElement(name = Elements.ID, required=false)
059        private final String id;
060        @XmlElement(name = Elements.SPECIFICATION, required=true)
061        private final TermSpecificationDefinition specification;
062    @XmlElement(name = Elements.DESCRIPTION, required=false)
063    private final String description;
064        @XmlElementWrapper(name = Elements.PARAMETERS, required=false)
065        @XmlElement(name = "parameter", required=false)
066        private final List<TermParameterDefinition> parameters;
067    @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
068    private final Long versionNumber;
069        
070        @SuppressWarnings("unused")
071    @XmlAnyElement
072    private final Collection<org.w3c.dom.Element> _futureElements = null;
073        
074        /**
075         * This constructor is for JAXB only.  Do not invoke directly.
076         */
077        private TermDefinition() {
078                id = null;
079                specification = null;
080        description = null;
081                parameters = null;
082        versionNumber = null;
083        }
084        
085        private TermDefinition(Builder builder) {
086                id = builder.getId();
087                specification = builder.getSpecification().build();
088        description = builder.getDescription();
089                parameters = BuilderUtils.convertFromBuilderList(builder.getParameters());
090                versionNumber = builder.getVersionNumber();
091        }
092        
093        /**
094         * {@link ModelBuilder} for {@link TermDefinition}s.
095         * 
096         * @author Kuali Rice Team (rice.collab@kuali.org)
097         *
098         */
099        public static class Builder implements TermDefinitionContract, ModelBuilder, Serializable {
100                
101                private static final long serialVersionUID = 1L;
102                
103                private String id;
104        private String description;
105                private TermSpecificationDefinition.Builder specification;
106                private List<TermParameterDefinition.Builder> parameters;
107        private Long versionNumber;
108                
109                private Builder(String id, TermSpecificationDefinition.Builder termSpecificationDefinition, 
110                                List<TermParameterDefinition.Builder> termParameters) {
111                        setId(id);
112                        setSpecification(termSpecificationDefinition);
113                        setParameters(termParameters);
114                }
115
116                /**
117                 * static factory for creating a {@link Builder}.
118                 * 
119                 * @param id may be null.
120                 * @param termSpecification must not be null.
121                 * @param termParameters may be null.
122                 */
123                public static Builder create(String id, TermSpecificationDefinition.Builder termSpecification, 
124                                List<TermParameterDefinition.Builder> termParameters) {
125                        return new Builder(id, termSpecification, termParameters);
126                }
127                
128                /**
129                 * static factory for creating a {@link Builder} from a {@link TermDefinitionContract}.
130                 * 
131                 * @param term must be non-null.
132                 */
133                public static Builder create(TermDefinitionContract term) {
134                        if (term == null) throw new IllegalAddException("term may not be null");
135                        
136                        // Convert TermParameterDefinitionContract to TermParameterDefinition:
137                        List<TermParameterDefinition.Builder> outParams =
138                                BuilderUtils.transform(term.getParameters(), TermParameterDefinition.Builder.toBuilder);
139
140                        Builder builder = create(term.getId(), 
141                                        // doing my TermSpecificationDefinitionContract conversion inline:
142                                        TermSpecificationDefinition.Builder.create(term.getSpecification()),
143                                        // this is made immutable in the setter
144                                        outParams 
145                                        );
146            builder.setDescription(term.getDescription());
147                        builder.setVersionNumber(term.getVersionNumber());
148                        return builder;
149                }
150
151        public void setDescription(String description) {
152            this.description = description;
153        }
154
155        // Builder setters:
156                
157                /**
158                 * @param id the id to set.  Should be null to build {@link TermDefinition}s for creation operations.
159                 * @throws IllegalArgumentException if the id is non-null and only contains whitespace
160                 */
161                public void setId(String id) {
162                        if (id != null && StringUtils.isBlank(id)) {
163                                throw new IllegalArgumentException("id must contain non-whitespace chars");
164                        }
165                        this.id = id;
166                }
167                
168                /**
169                 * @param termSpecification the termSpecification to set
170                 * @throws IllegalArgumentException if termSpecification is null
171                 */
172                public void setSpecification(TermSpecificationDefinition.Builder termSpecification) {
173                        if (termSpecification == null) {
174                                throw new IllegalArgumentException("termSpecification must not be null");
175                        }
176                        this.specification = termSpecification;
177                }
178                
179                /**
180                 * @param parameters the termParameters to set.  May be null, or empty.
181                 */
182                public void setParameters(List<TermParameterDefinition.Builder> parameters) {
183                        this.parameters = parameters;
184                }
185
186                /**
187                 * @param versionNumber the versionNumber to set.  May be null.
188                 */
189        public void setVersionNumber(Long versionNumber){
190            this.versionNumber = versionNumber;
191        }
192        
193                // Builder getters:
194                
195                /**
196                 * @return the id
197                 */
198                @Override
199                public String getId() {
200                        return id;
201                }
202
203                /**
204                 * @return the termSpecification
205                 */
206                @Override
207                public TermSpecificationDefinition.Builder getSpecification() {
208                        return specification;
209                }
210
211        @Override
212        public String getDescription() {
213            return description;
214        }
215
216        /**
217                 * @return the termParameters
218                 */
219                @Override
220                public List<TermParameterDefinition.Builder> getParameters() {
221                        return parameters;
222                }
223                
224                /**
225                 * @return the version number
226                 */
227        @Override
228        public Long getVersionNumber() {
229            return this.versionNumber;
230        }
231        
232                /**
233                 * Builds the {@link TermDefinition}, or dies trying.
234                 * 
235                 * @see org.kuali.rice.core.api.mo.ModelBuilder#build()
236                 * @throws IllegalStateException if builder validation fails
237                 */
238                @Override
239                public TermDefinition build() {
240                        return new TermDefinition(this);
241                }
242        }
243        
244        /**
245         * @return the termId.  May be null if this {@link TermDefinition} hasn't been persisted.
246         */
247        @Override
248        public String getId() {
249                return this.id;
250        }
251        /**
252         * @return the specification.  Will never be null.
253         */
254        @Override
255        public TermSpecificationDefinition getSpecification() {
256                return this.specification;
257        }
258
259    @Override
260    public String getDescription() {
261        return description;
262    }
263
264    /**
265         * @return the parameters.  May be empty, but will never be null.
266         */
267        @Override
268        public List<TermParameterDefinition> getParameters() {
269                return this.parameters;
270        }
271        
272        /**
273         * @see org.kuali.rice.core.api.mo.common.Versioned#getVersionNumber()
274         */
275    @Override
276    public Long getVersionNumber() {
277        return versionNumber;
278    }
279
280        static class Constants {
281                public static final String ROOT_ELEMENT_NAME = "termDefinition";
282                public static final String TYPE_NAME = "termDefinitionType";
283        }
284
285        static class Elements {
286                public static final String ID = "id";
287                public static final String SPECIFICATION = "specification";
288                public static final String PARAMETERS = "parameters";
289        public static final String DESCRIPTION = "description";
290    }
291
292    public static class Cache {
293        public static final String NAME = KrmsConstants.Namespaces.KRMS_NAMESPACE_2_0 + "/" + TermDefinition.Constants.TYPE_NAME;
294    }
295}