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