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