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.kim.api.permission;
017
018import com.google.common.collect.Maps;
019import org.apache.commons.lang.StringUtils;
020import org.kuali.rice.core.api.CoreConstants;
021import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
022import org.kuali.rice.core.api.mo.ModelBuilder;
023import org.kuali.rice.core.api.util.jaxb.MapStringStringAdapter;
024import org.kuali.rice.kim.api.KimConstants;
025import org.kuali.rice.kim.api.common.template.Template;
026import org.w3c.dom.Element;
027
028import javax.xml.bind.annotation.XmlAccessType;
029import javax.xml.bind.annotation.XmlAccessorType;
030import javax.xml.bind.annotation.XmlAnyElement;
031import javax.xml.bind.annotation.XmlElement;
032import javax.xml.bind.annotation.XmlRootElement;
033import javax.xml.bind.annotation.XmlType;
034import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
035import java.io.Serializable;
036import java.util.Collection;
037import java.util.Collections;
038import java.util.Map;
039
040/**
041 * An immutable representation of a {@link PermissionContract}.
042 *
043 * <p>To construct an instance of a Permission, use the {@link Permission.Builder} class.<p/>
044 *
045 * @see PermissionContract
046 */
047@XmlRootElement(name = Permission.Constants.ROOT_ELEMENT_NAME)
048@XmlAccessorType(XmlAccessType.NONE)
049@XmlType(name = Permission.Constants.TYPE_NAME, propOrder = {
050                Permission.Elements.ID,
051                Permission.Elements.NAMESPACE_CODE,
052                Permission.Elements.NAME,
053                Permission.Elements.DESCRIPTION,
054                Permission.Elements.TEMPLATE,
055        Permission.Elements.ACTIVE,
056        Permission.Elements.ATTRIBUTES,
057        CoreConstants.CommonElements.VERSION_NUMBER,
058        CoreConstants.CommonElements.OBJECT_ID,
059        CoreConstants.CommonElements.FUTURE_ELEMENTS
060})
061public final class Permission extends AbstractDataTransferObject implements PermissionContract{
062
063        private static final long serialVersionUID = 1L;
064
065    @XmlElement(name = Permission.Elements.ID, required = true)
066    private final String id;
067
068    @XmlElement(name = Permission.Elements.NAMESPACE_CODE, required = true)
069    private final String namespaceCode;
070
071    @XmlElement(name = Permission.Elements.NAME, required = true)
072    private final String name;
073
074    @XmlElement(name = Permission.Elements.DESCRIPTION, required = false)
075    private final String description;
076
077    @XmlElement(name = Permission.Elements.TEMPLATE, required = true)
078    private final Template template;
079
080    @XmlElement(name = Permission.Elements.ATTRIBUTES, required = false)
081    @XmlJavaTypeAdapter(value = MapStringStringAdapter.class)
082    private final Map<String, String> attributes;
083
084    @XmlElement(name = Permission.Elements.ACTIVE, required = false)
085    private boolean active;
086
087    @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
088    private final Long versionNumber;
089
090    @XmlElement(name = CoreConstants.CommonElements.OBJECT_ID, required = false)
091    private final String objectId;
092
093    @SuppressWarnings("unused")
094    @XmlAnyElement
095    private final Collection<Element> _futureElements = null;
096
097    /**
098         *  A constructor to be used only by JAXB unmarshalling.
099         *
100         */
101    @SuppressWarnings("unused")
102        private Permission() {
103                this.id = null;
104        this.namespaceCode = null;
105        this.name = null;
106        this.description = null;
107        this.template = null;
108        this.attributes = null;
109        this.active = false;
110        this.versionNumber = Long.valueOf(1L);
111        this.objectId = null;
112        }
113
114    /**
115         * A constructor using the Builder.
116         *
117         * @param builder
118         */
119        private Permission(Builder builder) {
120                this.id = builder.getId();
121        this.namespaceCode = builder.getNamespaceCode();
122        this.name = builder.getName();
123        this.description = builder.getDescription();
124        this.template = builder.getTemplate() != null ? builder.getTemplate().build() : null;
125        this.attributes = builder.getAttributes() != null ? builder.getAttributes() : Collections.<String, String>emptyMap();
126        this.active = builder.isActive();
127        this.versionNumber = builder.getVersionNumber();
128        this.objectId = builder.getObjectId();
129        }
130
131        /**
132         * @see org.kuali.rice.kim.api.permission.PermissionContract#getId()
133         */
134        @Override
135        public String getId() {
136                return id;
137        }
138
139        /**
140         * @see org.kuali.rice.kim.api.permission.PermissionContract#getNamespaceCode()
141         */
142        @Override
143        public String getNamespaceCode() {
144                return namespaceCode;
145        }
146
147        /**
148         * @see org.kuali.rice.kim.api.permission.PermissionContract#getName()
149         */
150        @Override
151        public String getName() {
152                return name;
153        }
154
155        /**
156         * @see org.kuali.rice.kim.api.permission.PermissionContract#getDescription()
157         */
158        @Override
159        public String getDescription() {
160                return description;
161        }
162
163        /**
164         * @see org.kuali.rice.kim.api.permission.PermissionContract#getTemplate()
165         */
166        @Override
167        public Template getTemplate() {
168                return template;
169        }
170
171        /**
172         * @see org.kuali.rice.core.api.mo.common.active.Inactivatable#isActive()
173         */
174        @Override
175        public boolean isActive() {
176                return active;
177        }
178
179        /**
180         *
181         * @see org.kuali.rice.kim.api.permission.PermissionContract#getAttributes()
182         */
183        @Override
184        public Map<String, String> getAttributes() {
185                return this.attributes;
186        }
187
188        /**
189         * @see org.kuali.rice.core.api.mo.common.Versioned#getVersionNumber()
190         */
191        @Override
192        public Long getVersionNumber() {
193                return versionNumber;
194        }
195
196        /**
197         * @see org.kuali.rice.core.api.mo.common.GloballyUnique#getObjectId()
198         */
199        @Override
200        public String getObjectId() {
201                return objectId;
202        }
203
204    /**
205     * This builder constructs a Permission enforcing the constraints of the {@link PermissionContract}.
206     */
207    public static final class Builder implements PermissionContract, ModelBuilder, Serializable {
208        private String id;
209        private String namespaceCode;
210        private String name;
211        private String description;
212        private Template.Builder template;
213        private Map<String, String> attributes;
214        private Long versionNumber = 1L;
215        private String objectId;
216        private boolean active;
217
218        private Builder(String namespaceCode, String name) {
219            setNamespaceCode(namespaceCode);
220            setName(name);
221        }
222
223        /**
224         * Creates a Permission with the required fields.
225         */
226        public static Builder create(String namespaceCode, String name) {
227            return new Builder(namespaceCode, name);
228        }
229
230        /**
231         * Creates a Permission from an existing {@link PermissionContract}.
232         */
233        public static Builder create(PermissionContract contract) {
234            Builder builder = new Builder(contract.getNamespaceCode(), contract.getName());
235            builder.setId(contract.getId());
236            builder.setDescription(contract.getDescription());
237            if (contract.getAttributes() != null) {
238                builder.setAttributes(contract.getAttributes());
239            }
240            builder.setActive(contract.isActive());
241            builder.setVersionNumber(contract.getVersionNumber());
242            builder.setObjectId(contract.getObjectId());
243            if (contract.getTemplate() != null
244                    && contract.getTemplate().getName() != null
245                    && contract.getTemplate().getNamespaceCode() != null) {
246                builder.setTemplate(Template.Builder.create(contract.getTemplate()));
247            }            
248
249            return builder;
250        }
251
252        @Override
253        public String getId() {
254            return id;
255        }
256
257        public void setId(final String id) {
258                this.id = id;
259        }
260        
261        @Override
262        public String getNamespaceCode() {
263            return namespaceCode;
264        }
265
266        public void setNamespaceCode(final String namespaceCode) {
267                if (StringUtils.isBlank(namespaceCode)) {
268                throw new IllegalArgumentException("namespaceCode is blank");
269            }
270                this.namespaceCode = namespaceCode;
271        }
272
273        @Override
274        public String getName() {
275            return name;
276        }
277
278        public void setName(final String name) {
279                if (StringUtils.isBlank(name)) {
280                throw new IllegalArgumentException("name is blank");
281            }
282                this.name = name;
283        }
284
285                @Override
286                public String getDescription() {
287                        return description;
288                }
289                
290                public void setDescription(final String description) {
291                        this.description = description;
292                }
293
294                @Override
295                public Template.Builder getTemplate() {
296                        return template;
297                }
298                
299                public void setTemplate(final Template.Builder template) {
300                        if (template == null) {
301                throw new IllegalArgumentException("template is null");
302            }
303            if (StringUtils.isNotBlank(template.getName())
304                    && StringUtils.isNotBlank(template.getNamespaceCode())) {
305                            this.template = template;
306            } else {
307                this.template = null;
308            }
309                }
310                
311                @Override
312                public boolean isActive() {
313                        return active;
314                }
315                
316                public void setActive(final boolean active) {
317            this.active = active;
318        }
319
320                @Override
321                public Long getVersionNumber() {
322                        return versionNumber;
323                }
324
325                public void setVersionNumber(final Long versionNumber) {
326
327                        if (versionNumber != null && versionNumber <= 0) {
328                    throw new IllegalArgumentException("versionNumber is invalid");
329                }
330                        this.versionNumber = versionNumber;
331            }
332                 
333                @Override
334                public String getObjectId() {
335                        return objectId;
336                }
337
338        public void setObjectId(final String objectId) {
339            this.objectId = objectId;
340        }
341
342                @Override
343                public Map<String, String> getAttributes() {
344                        return attributes;
345                }
346                
347                public void setAttributes(Map<String, String> attributes) {
348            this.attributes = Collections.unmodifiableMap(Maps.newHashMap(attributes));
349        }
350                
351        @Override
352        public Permission build() {
353            return new Permission(this);
354        }
355    }
356    
357    /**
358     * Defines some internal constants used on this class.
359     */
360    static class Constants {
361        static final String ROOT_ELEMENT_NAME = "permission";
362        static final String TYPE_NAME = "PermissionType";
363    }
364
365    /**
366     * A private class which exposes constants which define the XML element names to use
367     * when this object is marshalled to XML.
368     */
369    static class Elements {
370        static final String ID = "id";
371        static final String NAMESPACE_CODE = "namespaceCode";
372        static final String NAME = "name";
373        static final String DESCRIPTION = "description";
374        static final String TEMPLATE = "template";
375        static final String ATTRIBUTES = "attributes";
376        static final String ACTIVE = "active";
377    }
378
379    public static class Cache {
380        public static final String NAME = KimConstants.Namespaces.KIM_NAMESPACE_2_0 + "/" + Permission.Constants.TYPE_NAME;
381    }
382}