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.type;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.core.api.CoreConstants;
020import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
021import org.kuali.rice.core.api.mo.ModelBuilder;
022import org.kuali.rice.core.api.mo.ModelObjectUtils;
023import org.kuali.rice.krms.api.KrmsConstants;
024
025import javax.xml.bind.annotation.XmlAccessType;
026import javax.xml.bind.annotation.XmlAccessorType;
027import javax.xml.bind.annotation.XmlAnyElement;
028import javax.xml.bind.annotation.XmlElement;
029import javax.xml.bind.annotation.XmlRootElement;
030import javax.xml.bind.annotation.XmlType;
031import java.io.Serializable;
032import java.util.ArrayList;
033import java.util.Collection;
034import java.util.List;
035
036/**
037 * An immutable, concrete model object implementation of a {@link KrmsTypeDefinitionContract}.
038 * <p>To construct an instance of a KrmsTypeDefinition, use the {@link KrmsTypeDefinition.Builder} class.
039 * Instances of KrmsType can be (un)marshalled to and from XML.<p/>
040 *
041 * @see KrmsTypeDefinitionContract
042 */
043@XmlRootElement(name = KrmsTypeDefinition.Constants.ROOT_ELEMENT_NAME)
044@XmlAccessorType(XmlAccessType.NONE)
045@XmlType(name = KrmsTypeDefinition.Constants.TYPE_NAME, propOrder = {
046                KrmsTypeDefinition.Elements.ID,
047                KrmsTypeDefinition.Elements.NAME,
048                KrmsTypeDefinition.Elements.NAMESPACE,
049                KrmsTypeDefinition.Elements.SERVICENAME,
050                KrmsTypeDefinition.Elements.ACTIVE,
051                KrmsTypeDefinition.Elements.ATTRIBUTES,
052        CoreConstants.CommonElements.VERSION_NUMBER,
053                CoreConstants.CommonElements.FUTURE_ELEMENTS
054})
055public final class KrmsTypeDefinition extends AbstractDataTransferObject implements KrmsTypeDefinitionContract{
056        private static final long serialVersionUID = -8314397393380856301L;
057
058        @XmlElement(name = Elements.ID, required = false)
059        private String id;
060        @XmlElement(name = Elements.NAME, required = true)
061        private String name;
062        @XmlElement(name = Elements.NAMESPACE, required = true)
063        private String namespace;
064        @XmlElement(name = Elements.SERVICENAME, required = false)
065        private String serviceName;
066        @XmlElement(name = Elements.ACTIVE, required = false)
067        private boolean active;
068        @XmlElement(name = Elements.ATTRIBUTE, required = false)
069        private List<KrmsTypeAttribute> attributes;
070    @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
071    private final Long versionNumber;
072
073        @SuppressWarnings("unused")
074    @XmlAnyElement
075    private final Collection<org.w3c.dom.Element> _futureElements = null;
076
077         /**
078     * This constructor should never be called.  It is only present for use during JAXB unmarshalling.
079     */
080    private KrmsTypeDefinition() {
081        this.id = null;
082        this.name = null;
083        this.namespace = null;
084        this.serviceName = null;
085        this.active = true;
086        this.attributes = null;
087        this.versionNumber = null;
088    }
089
090    /**
091         * Constructs a KRMS KrmsType from the given builder.  This constructor is private and should only
092         * ever be invoked from the builder.
093         *
094         * @param builder the Builder from which to construct the KRMS type
095         */
096    private KrmsTypeDefinition(Builder builder) {
097        this.id = builder.getId();
098        this.name = builder.getName();
099        this.namespace = builder.getNamespace();
100        this.serviceName = builder.getServiceName();
101        this.active = builder.isActive();
102        this.attributes = ModelObjectUtils.buildImmutableCopy(builder.attributes);
103        this.versionNumber = builder.getVersionNumber();
104    }
105
106        @Override
107        public String getId() {
108                return this.id;
109        }
110
111        @Override
112        public String getName() {
113                return this.name;
114        }
115
116        @Override
117        public String getNamespace() {
118                return this.namespace;
119        }
120
121        @Override
122        public String getServiceName() {
123                return this.serviceName;
124        }
125
126        @Override
127        public boolean isActive() {
128                return this.active;
129        }
130
131        @Override
132        public List<KrmsTypeAttribute> getAttributes() {
133                return this.attributes;
134        }
135
136    @Override
137    public Long getVersionNumber() {
138        return versionNumber;
139    }
140
141        /**
142     * This builder is used to construct instances of KrmsTypeDefinition.  It enforces the constraints of the {@link KrmsTypeDefinitionContract}.
143     */
144    public static class Builder implements KrmsTypeDefinitionContract, ModelBuilder, Serializable {
145                private static final long serialVersionUID = -3469525730879441547L;
146
147                private String id;
148        private String name;
149        private String namespace;
150        private String serviceName = "";
151        private boolean active;
152        private List<KrmsTypeAttribute.Builder> attributes;
153        private Long versionNumber;
154
155                /**
156                 * Private constructor for creating a builder with all of it's required attributes.
157                 */
158        private Builder(String name, String namespace) {
159            setName(name);
160            setNamespace(namespace);
161                        setActive(true);
162            setAttributes(new ArrayList<KrmsTypeAttribute.Builder>());
163        }
164
165        /**
166         * fluent interface that sets the serviceName field of the Builder.
167         *
168         * @param serviceName the service used to resolve attribute values
169         * @return a Builder object with the serviceName field set
170         */
171        public Builder serviceName(String serviceName){
172                this.serviceName = serviceName;
173                return this;
174        }
175
176        /**
177         * fluent interface that sets the attributes of KrmsTypeDefinition builder.
178         *
179         * @param attributes List of KrmsTypeAttribute builder objects. {@link KrmsTypeAttribute.Builder}
180         * @return a Builder object with the attributes collection set.
181         */
182        public Builder attributes(List<KrmsTypeAttribute.Builder> attributes){
183                setAttributes(attributes);
184                return this;
185        }
186
187        /**
188         * Creates a KrmsTypeDefinition builder from the given parameters.
189         *
190         * @param name of the KrmsTypeDefinition
191         * @param namespace to which the KrmsTypeDefinition belongs
192         * @return an instance of the builder with the fields already populated
193         * @throws IllegalArgumentException if the either the name or namespace is null or blank
194         */
195        public static Builder create(String name, String namespace) {
196            return new Builder(name, namespace);
197        }
198
199        /**
200         * Creates a builder by populating it with data from the given {@link KrmsTypeDefinitionContract}.
201         *
202         * @param contract the contract from which to populate this builder
203         * @return an instance of the builder populated with data from the contract
204         * @throws IllegalArgumentException if the contract is null
205         */
206        public static Builder create(KrmsTypeDefinitionContract contract) {
207                if (contract == null) {
208                throw new IllegalArgumentException("contract is null");
209            }
210            Builder builder =  new Builder(contract.getName(), contract.getNamespace());
211            builder.setId(contract.getId());
212            builder.setNamespace(contract.getNamespace());
213            builder.setActive(contract.isActive());
214            builder.setServiceName(contract.getServiceName());
215            List <KrmsTypeAttribute.Builder> attrBuilderList = new ArrayList<KrmsTypeAttribute.Builder>();
216            if (contract.getAttributes() != null) {
217                for(KrmsTypeAttributeContract attr : contract.getAttributes()){
218                        KrmsTypeAttribute.Builder myBuilder =
219                                KrmsTypeAttribute.Builder.create(attr);
220                        attrBuilderList.add(myBuilder);
221                }
222            }
223            builder.setAttributes(attrBuilderList);
224            builder.setVersionNumber(contract.getVersionNumber());
225            return builder;
226        }
227
228                /**
229                 * Sets the value of the id on this builder to the given value.
230                 *
231                 * @param id the id value to set; can be null; a null id is an indicator
232         * the this has not yet been persisted to the database.
233         * @throws IllegalArgumentException if the id is blank
234                 */
235        public void setId(String id) {
236            if (id != null && StringUtils.isBlank(id)) {
237                throw new IllegalArgumentException("ID must be non-blank");
238            }
239            this.id = id;
240        }
241
242        /**
243         * Sets the name of the KrmsTypeDefinition
244         * @param name string value to assign to the name; cannot be null or blank
245         * @throws IllegalArgumentException if the name is null or blank
246         */
247                public void setName(String name) {
248            if (StringUtils.isBlank(name)) {
249                throw new IllegalArgumentException("name is blank");
250            }
251                        this.name = name;
252                }
253
254        /**
255         * Sets the namespace of the KrmsTypeDefinition
256         * @param namespace string value to assign to the namespace; cannot be null or blank
257         * @throws IllegalArgumentException if the name is null or blank
258         */
259                public void setNamespace(String namespace) {
260            if (StringUtils.isBlank(namespace)) {
261                throw new IllegalArgumentException("namespace is blank");
262            }
263                        this.namespace = namespace;
264                }
265
266        /**
267         * Sets the name of the KRMS type service
268         * @param serviceName can be null.
269         */
270                public void setServiceName(String serviceName) {
271                        this.serviceName = serviceName;
272                }
273
274        /**
275         * sets the List of attributes related to this KrmsTypeDefinition.
276         *
277         * @param attributes list of {@link KrmsTypeAttribute.Builder} representing the
278         * attributes assigned to this KrmsTypeDefinition; List may be empty, but not null
279         */
280                public void setAttributes(List<KrmsTypeAttribute.Builder> attributes){
281                        this.attributes = attributes;
282                }
283
284        /**
285         * sets the active indicator value
286         * @param active boolean value to set
287         */
288                public void setActive(boolean active) {
289                        this.active = active;
290                }
291
292        /**
293         * Sets the version number for this object.  In general, this value should only
294         * be null if the object has not yet been stored to a persistent data store.
295         * This version number is generally used for the purposes of optimistic locking.
296         * @param versionNumber the version number, or null if one has not been assigned yet.
297         */
298        public void setVersionNumber(Long versionNumber){
299            this.versionNumber = versionNumber;
300        }
301
302                @Override
303                public String getId() {
304                        return id;
305                }
306
307                @Override
308                public String getName() {
309                        return name;
310                }
311
312                @Override
313                public String getNamespace() {
314                        return namespace;
315                }
316
317                @Override
318                public String getServiceName() {
319                        return serviceName;
320                }
321
322                @Override
323                public List<KrmsTypeAttribute.Builder> getAttributes(){
324                        return attributes;
325                }
326
327                @Override
328                public boolean isActive() {
329                        return active;
330                }
331
332        @Override
333        public Long getVersionNumber() {
334            return versionNumber;
335        }
336
337                /**
338                 * Builds an instance of a KrmsTypeDefinition based on the current state of the builder.
339                 *
340                 * @return the fully-constructed KrmsTypeDefinition
341                 */
342        @Override
343        public KrmsTypeDefinition build() {
344            return new KrmsTypeDefinition(this);
345        }
346
347    }
348
349        /**
350         * Defines some internal constants used on this class.
351         */
352        static class Constants {
353                final static String ROOT_ELEMENT_NAME = "KRMSType";
354                final static String TYPE_NAME = "KRMSTypeType";
355        }
356
357        /**
358         * A private class which exposes constants which define the XML element names to use
359         * when this object is marshalled to XML.
360         */
361        public static class Elements {
362                final static String ID = "id";
363                final static String NAME = "name";
364                final static String NAMESPACE = "namespace";
365                final static String SERVICENAME = "serviceName";
366                final static String ACTIVE = "active";
367                final static String ATTRIBUTE = "attribute";
368                final static String ATTRIBUTES = "attributes";
369        }
370
371    public static class Cache {
372        public static final String NAME = KrmsConstants.Namespaces.KRMS_NAMESPACE_2_0 + "/" + KrmsTypeDefinition.Constants.TYPE_NAME;
373    }
374}