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.kew.api.peopleflow;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.kuali.rice.core.api.CoreConstants;
020    import org.kuali.rice.core.api.membership.MemberType;
021    import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
022    import org.kuali.rice.core.api.mo.ModelBuilder;
023    import org.kuali.rice.core.api.mo.ModelObjectUtils;
024    import org.kuali.rice.core.api.util.jaxb.MapStringStringAdapter;
025    import org.w3c.dom.Element;
026    
027    import javax.xml.bind.annotation.XmlAccessType;
028    import javax.xml.bind.annotation.XmlAccessorType;
029    import javax.xml.bind.annotation.XmlAnyElement;
030    import javax.xml.bind.annotation.XmlElement;
031    import javax.xml.bind.annotation.XmlElementWrapper;
032    import javax.xml.bind.annotation.XmlRootElement;
033    import javax.xml.bind.annotation.XmlType;
034    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
035    import java.io.Serializable;
036    import java.util.ArrayList;
037    import java.util.Collection;
038    import java.util.HashMap;
039    import java.util.List;
040    import java.util.Map;
041    
042    @XmlRootElement(name = PeopleFlowDefinition.Constants.ROOT_ELEMENT_NAME)
043    @XmlAccessorType(XmlAccessType.NONE)
044    @XmlType(name = PeopleFlowDefinition.Constants.TYPE_NAME, propOrder = {
045            PeopleFlowDefinition.Elements.ID,
046            PeopleFlowDefinition.Elements.NAMESPACE_CODE,
047            PeopleFlowDefinition.Elements.NAME,
048            PeopleFlowDefinition.Elements.TYPE_ID,
049            PeopleFlowDefinition.Elements.DESCRIPTION,
050            PeopleFlowDefinition.Elements.MEMBERS,
051            PeopleFlowDefinition.Elements.ATTRIBUTES,
052            PeopleFlowDefinition.Elements.ACTIVE,
053            CoreConstants.CommonElements.VERSION_NUMBER,
054            CoreConstants.CommonElements.FUTURE_ELEMENTS
055    })
056    public final class PeopleFlowDefinition extends AbstractDataTransferObject implements PeopleFlowContract {
057    
058        @XmlElement(name = Elements.NAME, required = true)
059        private final String name;
060    
061        @XmlElement(name = Elements.ATTRIBUTES, required = false)
062        @XmlJavaTypeAdapter(MapStringStringAdapter.class)
063        private final Map<String, String> attributes;
064    
065        @XmlElement(name = Elements.NAMESPACE_CODE, required = true)
066        private final String namespaceCode;
067    
068        @XmlElement(name = Elements.TYPE_ID, required = false)
069        private final String typeId;
070    
071        @XmlElement(name = Elements.DESCRIPTION, required = false)
072        private final String description;
073    
074        @XmlElementWrapper(name = Elements.MEMBERS, required = false)
075        @XmlElement(name = Elements.MEMBER, required = false)
076        private final List<PeopleFlowMember> members;
077        
078        @XmlElement(name = Elements.ID, required = false)
079        private final String id;
080    
081        @XmlElement(name = Elements.ACTIVE, required = false)
082        private final boolean active;
083    
084        @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
085        private final Long versionNumber;
086        
087        @SuppressWarnings("unused")
088        @XmlAnyElement
089        private final Collection<Element> _futureElements = null;
090    
091        /**
092         * Private constructor used only by JAXB.
093         * 
094         */
095        private PeopleFlowDefinition() {
096            this.name = null;
097            this.attributes = null;
098            this.namespaceCode = null;
099            this.typeId = null;
100            this.description = null;
101            this.members = null;
102            this.id = null;
103            this.active = false;
104            this.versionNumber = null;
105        }
106    
107        private PeopleFlowDefinition(Builder builder) {
108            this.name = builder.getName();
109            this.attributes = builder.getAttributes();
110            this.namespaceCode = builder.getNamespaceCode();
111            this.typeId = builder.getTypeId();
112            this.description = builder.getDescription();
113            this.members = ModelObjectUtils.buildImmutableCopy(builder.getMembers());
114            this.id = builder.getId();
115            this.active = builder.isActive();
116            this.versionNumber = builder.getVersionNumber();
117        }
118    
119        @Override
120        public String getName() {
121            return this.name;
122        }
123    
124        @Override
125        public Map<String, String> getAttributes() {
126            return this.attributes;
127        }
128    
129        @Override
130        public String getNamespaceCode() {
131            return this.namespaceCode;
132        }
133    
134        @Override
135        public String getTypeId() {
136            return this.typeId;
137        }
138    
139        @Override
140        public String getDescription() {
141            return this.description;
142        }
143    
144        @Override
145        public List<PeopleFlowMember> getMembers() {
146            return this.members;
147        }
148    
149        @Override
150        public String getId() {
151            return this.id;
152        }
153    
154        @Override
155        public boolean isActive() {
156            return this.active;
157        }
158    
159        @Override
160        public Long getVersionNumber() {
161            return this.versionNumber;
162        }
163    
164        /**
165         * A builder which can be used to construct {@link PeopleFlowDefinition} instances.  Enforces the constraints of the
166         * {@link PeopleFlowContract}.
167         */
168        public final static class Builder implements Serializable, ModelBuilder, PeopleFlowContract {
169    
170            private String name;
171            private Map<String, String> attributes;
172            private String namespaceCode;
173            private String typeId;
174            private String description;
175            private List<PeopleFlowMember.Builder> members;
176            private String id;
177            private boolean active;
178            private Long versionNumber;
179    
180            private Builder(String namespaceCode, String name) {
181                setNamespaceCode(namespaceCode);
182                setName(name);
183                setActive(true);
184                setAttributes(new HashMap<String, String>());
185                setMembers(new ArrayList<PeopleFlowMember.Builder>());
186            }
187    
188            public static Builder create(String namespaceCode, String name) {
189                return new Builder(namespaceCode, name);
190            }
191    
192            public static Builder create(PeopleFlowContract contract) {
193                Builder builder = createCopy(contract);
194                builder.setVersionNumber(contract.getVersionNumber());
195                if (contract.getMembers() != null) {
196                    for (PeopleFlowMemberContract member : contract.getMembers()) {
197                        builder.getMembers().add(PeopleFlowMember.Builder.create(member));
198                    }
199                }
200                return builder;
201            }
202    
203            private static Builder createCopy(PeopleFlowContract contract) {
204                if (contract == null) {
205                    throw new IllegalArgumentException("contract was null");
206                }
207                Builder builder = create(contract.getNamespaceCode(), contract.getName());
208                if (contract.getAttributes() != null) {
209                    builder.getAttributes().putAll(contract.getAttributes());
210                }
211                if (StringUtils.isEmpty(contract.getTypeId())) {
212                    // type_id is a foreign key, it needs to be either null or a real value, not empty String to avoid SQL Exception
213                    builder.setTypeId(null);
214                } else {
215                    builder.setTypeId(contract.getTypeId());
216                }
217                builder.setDescription(contract.getDescription());
218                builder.setId(contract.getId());
219                builder.setActive(contract.isActive());
220                return builder;
221            }
222    
223            public static Builder createMaintenanceCopy(PeopleFlowContract contract) {
224                Builder builder = createCopy(contract);
225                if (contract.getMembers() != null) {
226                    for (PeopleFlowMemberContract member : contract.getMembers()) {
227                        builder.getMembers().add(PeopleFlowMember.Builder.createCopy(member));
228                    }
229                }
230                return builder;
231            }
232    
233            public PeopleFlowDefinition build() {
234                return new PeopleFlowDefinition(this);
235            }
236    
237            @Override
238            public String getName() {
239                return this.name;
240            }
241    
242            @Override
243            public Map<String, String> getAttributes() {
244                return this.attributes;
245            }
246    
247            @Override
248            public String getNamespaceCode() {
249                return this.namespaceCode;
250            }
251    
252            @Override
253            public String getTypeId() {
254                return this.typeId;
255            }
256    
257            @Override
258            public String getDescription() {
259                return this.description;
260            }
261    
262            @Override
263            public List<PeopleFlowMember.Builder> getMembers() {
264                return this.members;
265            }
266    
267            @Override
268            public String getId() {
269                return this.id;
270            }
271    
272            @Override
273            public boolean isActive() {
274                return this.active;
275            }
276    
277            @Override
278            public Long getVersionNumber() {
279                return this.versionNumber;
280            }
281    
282            public void setName(String name) {
283                if (StringUtils.isBlank(name)) {
284                    throw new IllegalArgumentException("name was null or blank");
285                }
286                this.name = name;
287            }
288    
289            public void setAttributes(Map<String, String> attributes) {
290                this.attributes = attributes;
291            }
292    
293            public void setNamespaceCode(String namespaceCode) {
294                if (StringUtils.isBlank(namespaceCode)) {
295                    throw new IllegalArgumentException("namespaceCode was null or blank");
296                }
297                this.namespaceCode = namespaceCode;
298            }
299    
300            public void setTypeId(String typeId) {
301                this.typeId = typeId;
302            }
303    
304            public void setDescription(String description) {
305                this.description = description;
306            }
307    
308            public void setMembers(List<PeopleFlowMember.Builder> members) {
309                this.members = members;
310            }
311    
312            public void setId(String id) {
313                this.id = id;
314            }
315    
316            public void setActive(boolean active) {
317                this.active = active;
318            }
319    
320            public void setVersionNumber(Long versionNumber) {
321                this.versionNumber = versionNumber;
322            }
323    
324            public PeopleFlowMember.Builder addPrincipal(String principalId) {
325                PeopleFlowMember.Builder member = PeopleFlowMember.Builder.create(principalId, MemberType.PRINCIPAL);
326                getMembers().add(member);
327                return member;
328            }
329    
330            public PeopleFlowMember.Builder addGroup(String groupId) {
331                PeopleFlowMember.Builder member = PeopleFlowMember.Builder.create(groupId, MemberType.GROUP);
332                getMembers().add(member);
333                return member;
334            }
335    
336            public PeopleFlowMember.Builder addRole(String roleId) {
337                PeopleFlowMember.Builder member = PeopleFlowMember.Builder.create(roleId, MemberType.ROLE);
338                getMembers().add(member);
339                return member;
340            }
341    
342        }
343    
344        /**
345         * Defines some internal constants used on this class.
346         */
347        static class Constants {
348            final static String ROOT_ELEMENT_NAME = "peopleFlowDefinition";
349            final static String TYPE_NAME = "PeopleFlowDefinitionType";
350        }
351    
352        /**
353         * A private class which exposes constants which define the XML element names to use when this object is marshalled to XML.
354         */
355        static class Elements {
356            final static String NAME = "name";
357            final static String ATTRIBUTES = "attributes";
358            final static String NAMESPACE_CODE = "namespaceCode";
359            final static String TYPE_ID = "typeId";
360            final static String DESCRIPTION = "description";
361            final static String MEMBERS = "members";
362            final static String MEMBER = "member";
363            final static String ID = "id";
364            final static String ACTIVE = "active";
365        }
366    
367    }