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