001/**
002 * Copyright 2005-2015 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.extension;
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.util.jaxb.MapStringStringAdapter;
023import org.kuali.rice.kew.api.KewApiConstants;
024import org.w3c.dom.Element;
025
026import javax.xml.bind.annotation.XmlAccessType;
027import javax.xml.bind.annotation.XmlAccessorType;
028import javax.xml.bind.annotation.XmlAnyElement;
029import javax.xml.bind.annotation.XmlElement;
030import javax.xml.bind.annotation.XmlRootElement;
031import javax.xml.bind.annotation.XmlType;
032import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
033import java.io.Serializable;
034import java.util.Collection;
035import java.util.Collections;
036import java.util.HashMap;
037import java.util.Map;
038
039/**
040 * Immutable implementation of the {@link ExtensionDefinitionContract}.  Defines an extension to some component of
041 * Kuali Enterprise Workflow.
042 *
043 * @author Kuali Rice Team (rice.collab@kuali.org)
044 */
045@XmlRootElement(name = ExtensionDefinition.Constants.ROOT_ELEMENT_NAME)
046@XmlAccessorType(XmlAccessType.NONE)
047@XmlType(name = ExtensionDefinition.Constants.TYPE_NAME, propOrder = {
048        ExtensionDefinition.Elements.ID,
049        ExtensionDefinition.Elements.NAME,
050        ExtensionDefinition.Elements.APPLICATION_ID,
051        ExtensionDefinition.Elements.LABEL,
052        ExtensionDefinition.Elements.DESCRIPTION,
053        ExtensionDefinition.Elements.TYPE,
054        ExtensionDefinition.Elements.RESOURCE_DESCRIPTOR,
055        ExtensionDefinition.Elements.CONFIGURATION,
056        CoreConstants.CommonElements.VERSION_NUMBER,
057        CoreConstants.CommonElements.FUTURE_ELEMENTS
058})
059public final class ExtensionDefinition extends AbstractDataTransferObject implements ExtensionDefinitionContract {
060
061    private static final long serialVersionUID = 6234968409006917945L;
062    
063    @XmlElement(name = Elements.ID, required = false)
064    private final String id;
065
066    @XmlElement(name = Elements.NAME, required = true)
067    private final String name;
068
069    @XmlElement(name = Elements.APPLICATION_ID, required = false)
070    private final String applicationId;
071
072    @XmlElement(name = Elements.LABEL, required = false)
073    private final String label;
074
075    @XmlElement(name = Elements.DESCRIPTION, required = false)
076    private final String description;
077
078    @XmlElement(name = Elements.TYPE, required = true)
079    private final String type;
080
081    @XmlElement(name = Elements.RESOURCE_DESCRIPTOR, required = true)
082    private final String resourceDescriptor;
083
084    @XmlElement(name = Elements.CONFIGURATION, required = false)
085    @XmlJavaTypeAdapter(MapStringStringAdapter.class)
086    private final Map<String, String> configuration;
087
088    @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
089    private final Long versionNumber;
090
091    @SuppressWarnings("unused")
092    @XmlAnyElement
093    private final Collection<Element> _futureElements = null;
094
095    /**
096     * Private constructor used only by JAXB.
097     */
098    @SuppressWarnings("unused")
099    private ExtensionDefinition() {
100        this.id = null;
101        this.name = null;
102        this.applicationId = null;
103        this.label = null;
104        this.description = null;
105        this.type = null;
106        this.resourceDescriptor = null;
107        this.configuration = null;
108        this.versionNumber = null;
109    }
110
111    private ExtensionDefinition(Builder builder) {
112        this.id = builder.getId();
113        this.name = builder.getName();
114        this.applicationId = builder.getApplicationId();
115        this.label = builder.getLabel();
116        this.description = builder.getDescription();
117        this.type = builder.getType();
118        this.resourceDescriptor = builder.getResourceDescriptor();
119        if (builder.getConfiguration() == null) {
120            this.configuration = Collections.emptyMap();
121        } else {
122            this.configuration = Collections.unmodifiableMap(new HashMap<String, String>(builder.getConfiguration()));
123        }
124        this.versionNumber = builder.getVersionNumber();
125    }
126
127    @Override
128    public String getId() {
129        return this.id;
130    }
131
132    @Override
133    public String getName() {
134        return this.name;
135    }
136
137    @Override
138    public String getApplicationId() {
139        return this.applicationId;
140    }
141
142    @Override
143    public String getLabel() {
144        return this.label;
145    }
146
147    @Override
148    public String getDescription() {
149        return this.description;
150    }
151
152    @Override
153    public String getType() {
154        return this.type;
155    }
156
157    @Override
158    public String getResourceDescriptor() {
159        return this.resourceDescriptor;
160    }
161
162    @Override
163    public Map<String, String> getConfiguration() {
164        return this.configuration;
165    }
166
167    @Override
168    public Long getVersionNumber() {
169        return this.versionNumber;
170    }
171
172    /**
173     * A builder which can be used to construct {@link ExtensionDefinition} instances.  Enforces the constraints of the
174     * {@link ExtensionDefinitionContract}.
175     */
176    public final static class Builder implements Serializable, ModelBuilder, ExtensionDefinitionContract {
177
178        private String id;
179        private String name;
180        private String applicationId;
181        private String label;
182        private String description;
183        private String type;
184        private String resourceDescriptor;
185        private Map<String, String> configuration;
186        private Long versionNumber;
187
188        private Builder(String name, String type, String resourceDescriptor) {
189            setName(name);
190            setType(type);
191            setResourceDescriptor(resourceDescriptor);
192            setConfiguration(new HashMap<String, String>());
193        }
194
195        public static Builder create(String name, String type, String resourceDescriptor) {
196            return new Builder(name, type, resourceDescriptor);
197        }
198
199        public static Builder create(ExtensionDefinitionContract contract) {
200            if (contract == null) {
201                throw new IllegalArgumentException("contract was null");
202            }
203            Builder builder = create(contract.getName(), contract.getType(), contract.getResourceDescriptor());
204            builder.setId(contract.getId());
205            builder.setApplicationId(contract.getApplicationId());
206            builder.setLabel(contract.getLabel());
207            builder.setDescription(contract.getDescription());
208            builder.setConfiguration(contract.getConfiguration());
209            builder.setVersionNumber(contract.getVersionNumber());
210            return builder;
211        }
212
213        public ExtensionDefinition build() {
214            return new ExtensionDefinition(this);
215        }
216
217        @Override
218        public String getId() {
219            return this.id;
220        }
221
222        @Override
223        public String getName() {
224            return this.name;
225        }
226
227        @Override
228        public String getApplicationId() {
229            return this.applicationId;
230        }
231
232        @Override
233        public String getLabel() {
234            return this.label;
235        }
236
237        @Override
238        public String getDescription() {
239            return this.description;
240        }
241
242        @Override
243        public String getType() {
244            return this.type;
245        }
246
247        @Override
248        public String getResourceDescriptor() {
249            return this.resourceDescriptor;
250        }
251
252        @Override
253        public Map<String, String> getConfiguration() {
254            return this.configuration;
255        }
256
257        @Override
258        public Long getVersionNumber() {
259            return this.versionNumber;
260        }
261
262        public void setId(String id) {
263            this.id = id;
264        }
265
266        public void setName(String name) {
267            if (StringUtils.isBlank(name)) {
268                throw new IllegalArgumentException("name was null or blank");
269            }
270            this.name = name;
271        }
272
273        public void setApplicationId(String applicationId) {
274            this.applicationId = applicationId;
275        }
276
277        public void setLabel(String label) {
278            this.label = label;
279        }
280
281        public void setDescription(String description) {
282            this.description = description;
283        }
284
285        public void setType(String type) {
286            if (StringUtils.isBlank(type)) {
287                throw new IllegalArgumentException("type was null or blank");
288            }
289
290            this.type = type;
291        }
292
293        public void setResourceDescriptor(String resourceDescriptor) {
294            if (StringUtils.isBlank(resourceDescriptor)) {
295                throw new IllegalArgumentException("descriptor was null or blank");
296            }
297            this.resourceDescriptor = resourceDescriptor;
298        }
299
300        public void setConfiguration(Map<String, String> configuration) {
301            this.configuration = configuration;
302        }
303
304        public void setVersionNumber(Long versionNumber) {
305            this.versionNumber = versionNumber;
306        }
307
308    }
309
310    /**
311     * Defines some internal constants used on this class.
312     */
313    static class Constants {
314        final static String ROOT_ELEMENT_NAME = "extensionDefinition";
315        final static String TYPE_NAME = "ExtensionDefinitionType";
316    }
317
318    /**
319     * A private class which exposes constants which define the XML element names to use when this object is marshalled to XML.
320     */
321    static class Elements {
322        final static String ID = "id";
323        final static String NAME = "name";
324        final static String APPLICATION_ID = "applicationId";
325        final static String LABEL = "label";
326        final static String DESCRIPTION = "description";
327        final static String TYPE = "type";
328        final static String RESOURCE_DESCRIPTOR = "resourceDescriptor";
329        final static String CONFIGURATION = "configuration";
330    }
331    
332    public static class Cache {
333        public static final String NAME = KewApiConstants.Namespaces.KEW_NAMESPACE_2_0 + "/" + ExtensionDefinition.Constants.TYPE_NAME;
334    }
335}