1    /*
2     * Copyright 2006 :torweg free software group
3     * 
4     * This program is free software: you can redistribute it and/or modify
5     * it under the terms of the GNU General Public License as published by
6     * the Free Software Foundation, either version 3 of the License, or
7     * (at your option) any later version.
8     * 
9     * This program is distributed in the hope that it will be useful,
10    * but WITHOUT ANY WARRANTY; without even the implied warranty of
11    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    * GNU General Public License for more details.
13    * 
14    * You should have received a copy of the GNU General Public License
15    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16    *
17    */
18   package org.torweg.pulse.accesscontrol;
19   
20   import java.util.HashSet;
21   import java.util.List;
22   import java.util.Set;
23   
24   import javax.persistence.CascadeType;
25   import javax.persistence.Column;
26   import javax.persistence.Entity;
27   import javax.persistence.Lob;
28   import javax.persistence.ManyToMany;
29   import javax.persistence.Table;
30   import javax.xml.bind.annotation.XmlAccessOrder;
31   import javax.xml.bind.annotation.XmlAccessType;
32   import javax.xml.bind.annotation.XmlAccessorOrder;
33   import javax.xml.bind.annotation.XmlAccessorType;
34   import javax.xml.bind.annotation.XmlElement;
35   import javax.xml.bind.annotation.XmlElementWrapper;
36   import javax.xml.bind.annotation.XmlRootElement;
37   import javax.xml.bind.annotation.XmlTransient;
38   
39   import net.sf.json.JSONObject;
40   
41   import org.hibernate.LazyInitializationException;
42   import org.hibernate.Session;
43   import org.hibernate.criterion.Projections;
44   import org.jdom.Element;
45   import org.slf4j.Logger;
46   import org.slf4j.LoggerFactory;
47   import org.torweg.pulse.util.INameable;
48   
49   /**
50    * A {@code Group} is an entity used to group {@code Permission}s and {@code
51    * User}s.
52    * 
53    * @author Christian Schatt, Daniel Dietz
54    * @version $Revision: 1479 $
55    */
56   @Entity
57   @Table(name = "`Group`")
58   @XmlRootElement(name = "group")
59   @XmlAccessorOrder(XmlAccessOrder.UNDEFINED)
60   @XmlAccessorType(XmlAccessType.FIELD)
61   public class Group extends AbstractAccessControlObject implements INameable {
62   
63       /**
64        * The serialVersionUID of the {@code Group}.
65        */
66       private static final long serialVersionUID = -6429942011690281961L;
67   
68       /**
69        * the logger.
70        */
71       private static final Logger LOGGER = LoggerFactory.getLogger(Group.class);
72   
73       /**
74        * The description of the {@code Group}.
75        */
76       @Lob
77       @Column(length = 4096, nullable = false)
78       @XmlElement(name = "description")
79       private String description = "";
80   
81       /**
82        * The {@code Permission}s associated with the {@code Group}.
83        */
84       @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE,
85               CascadeType.REFRESH })
86       @XmlTransient
87       // getter JAXB-annotated
88       private final Set<Permission> permissions = new HashSet<Permission>();
89   
90       /**
91        * used for Hibernate<sup>TM</sup>.
92        */
93       @Deprecated
94       protected Group() {
95           super();
96       }
97   
98       /**
99        * The {@code Constructor} that sets the name of the {@code Group} .
100       * 
101       * @param newName
102       *            the name of the {@code Group}
103       */
104      public Group(final String newName) {
105          super();
106          this.setName(newName);
107      }
108  
109      /**
110       * returns the description.
111       * 
112       * @return the description.
113       */
114      public final String getDescription() {
115          return this.description;
116      }
117  
118      /**
119       * sets the description.
120       * 
121       * @param d
122       *            the description to set
123       */
124      public final void setDescription(final String d) {
125          this.description = d;
126      }
127  
128      /**
129       * Returns a shallow copy of the {@code Group}'s {@code Collection} of
130       * {@code Permission}s.
131       * 
132       * <p>
133       * Attention: Since the returned {@code Set} is not a reference to the
134       * {@code Group}'s internal {@code Collection}, any modifications to its
135       * state will get lost. However, modifications to the state of the {@code
136       * Set}'s elements will be consistent.
137       * </p>
138       * 
139       * <p>
140       * For example: Adding/Deleting a {@code Permission} to/from the {@code Set}
141       * will not have any effect, when the {@code Group} is saved. On the other
142       * hand, modifications to a {@code Permission} in the {@code Set} will be
143       * made persistent, when the {@code Permission} is saved.
144       * </p>
145       * 
146       * @return the {@code Permission}s associated with the {@code Group}
147       */
148      public final Set<Permission> getPermissions() {
149          return new HashSet<Permission>(this.permissions);
150      }
151  
152      /**
153       * For JAXB only.
154       * 
155       * @return this.getPermissions()
156       */
157      @XmlElementWrapper(name = "permissions")
158      @XmlElement(name = "permission")
159      @SuppressWarnings("unused")
160      @Deprecated
161      private HashSet<Permission> getPermissionsJAXB() { // NOPMD
162          try {
163              return new HashSet<Permission>(getPermissions());
164          } catch (LazyInitializationException e) {
165              LOGGER.debug("ignored: {}", e.getLocalizedMessage());
166              return null;
167          }
168      }
169  
170      /**
171       * Adds a {@code Permission} to the {@code Group}'s {@code Set} of {@code
172       * Permission}s. If it already is part of the {@code Set}, it will not be
173       * added.
174       * 
175       * @param perm
176       *            the {@code Permission} to be added
177       * @return true if the {@code Set} changed as a result of the call
178       */
179      public final boolean addPermission(final Permission perm) {
180          if (perm == null) {
181              return false;
182          }
183          return this.permissions.add(perm);
184      }
185  
186      /**
187       * Determines if a {@code Permission} is part of the {@code Group} 's
188       * {@code Set} of {@code Permission}s.
189       * 
190       * @param perm
191       *            the {@code Permission} to be sought-after
192       * @return true if the {@code Permission} is part of the {@code Set}
193       */
194      public final boolean containsPermission(final Permission perm) {
195          return this.permissions.contains(perm);
196      }
197  
198      /**
199       * Removes a {@code Permission} from the {@code Group}'s {@code Set} of
200       * {@code Permission}s if it is part of it.
201       * 
202       * @param perm
203       *            the {@code Permission} to be removed
204       * @return true if the {@code Set} changed as a result of the call
205       */
206      public final boolean removePermission(final Permission perm) {
207          if (perm == null) {
208              return false;
209          }
210          return this.permissions.remove(perm);
211      }
212  
213      /**
214       * Returns the {@code Role}s associated with the {@code Group} ordered by
215       * name.
216       * 
217       * @param s
218       *            the hibernate<sup>TM</sup>-{@code Session}
219       * 
220       * @return the {@code Role}s associated with the {@code Group}
221       */
222      @SuppressWarnings("unchecked")
223      public final List<Role> getRoles(final Session s) {
224          return (List<Role>) getAssociatedAbstractAccessControlObjects(s,
225                  Role.class, "groups", getId());
226      }
227  
228      /**
229       * Returns the {@code User}s associated with the {@code Group} ordered by
230       * name.
231       * 
232       * @param s
233       *            the hibernate<sup>TM</sup>-{@code Session}
234       * 
235       * @return the {@code User}s associated with the {@code Group}
236       */
237      @SuppressWarnings("unchecked")
238      public final List<User> getUsers(final Session s) {
239          return (List<User>) getAssociatedAbstractAccessControlObjects(s,
240                  User.class, "groups", getId());
241      }
242  
243      /**
244       * Serializes the state of the {@code Group} as a JDOM {@code Element}.
245       * 
246       * @return the state of the {@code Group} as a JDOM {@code Element}
247       */
248      public final Element deserializeToJDOM() {
249          Element element = new Element(getClass().getSimpleName()).setAttribute(
250                  "class", getClass().getCanonicalName());
251          if (this.getId() != null) {
252              element.setAttribute("id", getId().toString());
253          }
254          element.setAttribute("name", getName());
255          element
256                  .addContent(new Element("description")
257                          .setText(getDescription()));
258          try {
259              for (Permission permission : getPermissions()) {
260                  element.addContent(permission.deserializeToJDOM());
261              }
262          } catch (LazyInitializationException exception) {
263              element.removeChildren(Permission.class.getSimpleName());
264          }
265  
266          return element;
267      }
268  
269      /**
270       * Serializes the state of the {@code Group} as a {@code JSONObject}.
271       * 
272       * @return the state of the {@code Group} as a {@code JSONObject}
273       */
274      @Override
275      public final JSONObject toJSON() {
276          return toJSON(null);
277      }
278  
279      /**
280       * Serializes the state of the {@code Group} as a {@code JSONObject}.
281       * <p>
282       * If a {@code Session} is given the number of {@code User}s and {@code
283       * Role}s associated with the {@code Group} will be added to the JSON.
284       * </p>
285       * 
286       * @param s
287       *            the hibernate<sup>TM</sup>-{@code Session}
288       * 
289       * @return the state of the {@code Group} as a {@code JSONObject}
290       */
291      public final JSONObject toJSON(final Session s) {
292  
293          JSONObject json = super.toJSON();
294  
295          json.put("name", getName());
296          json.put("description", getDescription());
297  
298          // adds info for ext-tree
299          json.put("uiProvider", "AccessControlTreeNodeUI");
300          json.put("leaf", true);
301          json.put("expandable", false);
302          json.put("allowChildren", false);
303          json.put("text", getName());
304  
305          // adds info for overview-grid
306          json.put("noPermissions", getPermissions().size());
307          if (s != null) {
308              json.put("noRoles", (Long) getLoadCriteriaForClassWithAlias(s,
309                      Role.class, "groups", getId()).setProjection(
310                      Projections.rowCount()).uniqueResult());
311              json.put("noUsers", (Long) getLoadCriteriaForClassWithAlias(s,
312                      User.class, "groups", getId()).setProjection(
313                      Projections.rowCount()).uniqueResult());
314          }
315  
316          return json;
317      }
318  
319  }
320