View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    * 
4    * Copyright 2005-2014 The Kuali Foundation
5    * 
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   * 
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.rice.kim.impl.jaxb;
20  
21  import java.io.Serializable;
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import javax.xml.bind.Unmarshaller;
26  import javax.xml.bind.annotation.XmlAccessType;
27  import javax.xml.bind.annotation.XmlAccessorType;
28  import javax.xml.bind.annotation.XmlElement;
29  import javax.xml.bind.annotation.XmlTransient;
30  import javax.xml.bind.annotation.XmlType;
31  import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
32  import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
33  
34  import org.apache.commons.lang.StringUtils;
35  import org.joda.time.DateTime;
36  import org.kuali.rice.core.api.membership.MemberType;
37  import org.kuali.rice.core.api.util.jaxb.DateTimeAdapter;
38  import org.kuali.rice.core.util.jaxb.NameAndNamespacePair;
39  import org.kuali.rice.core.util.jaxb.NameAndNamespacePairValidatingAdapter;
40  import org.kuali.rice.kim.api.group.GroupContract;
41  import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
42  import org.kuali.rice.kim.api.jaxb.QualificationListAdapter;
43  import org.kuali.rice.kim.api.role.RoleContract;
44  import org.kuali.rice.kim.api.role.RoleMember;
45  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
46  
47  /**
48   * Base class representing an unmarshalled &lt;roleMember&gt; element.
49   * Refer to the static inner classes for more information about the specific contexts.
50   *
51   * @author Kuali Rice Team (rice.collab@kuali.org)
52   */
53  @XmlTransient
54  public abstract class RoleMemberXmlDTO implements Serializable {
55  
56      private static final long serialVersionUID = 1L;
57  
58      @XmlElement(name="principalId")
59      @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
60      private String principalId;
61  
62      @XmlElement(name="principalName")
63      @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
64      private String principalName;
65  
66      @XmlElement(name="groupId")
67      @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
68      private String groupId;
69  
70      @XmlElement(name="groupName")
71      @XmlJavaTypeAdapter(NameAndNamespacePairValidatingAdapter.class)
72      private NameAndNamespacePair groupName;
73  
74      @XmlElement(name="roleIdAsMember")
75      @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
76      private String roleIdAsMember;
77  
78      @XmlElement(name="roleNameAsMember")
79      @XmlJavaTypeAdapter(NameAndNamespacePairValidatingAdapter.class)
80      private NameAndNamespacePair roleNameAsMember;
81  
82      @XmlElement(name="activeFromDate")
83      @XmlJavaTypeAdapter(DateTimeAdapter.class)
84      private DateTime activeFromDate;
85  
86      @XmlElement(name="activeToDate")
87      @XmlJavaTypeAdapter(DateTimeAdapter.class)
88      private DateTime activeToDate;
89  
90      @XmlElement(name="qualifications")
91      @XmlJavaTypeAdapter(QualificationListAdapter.class)
92      private Map<String, String> qualifications;
93  
94      @XmlTransient
95      private MemberType memberType;
96  
97      /**
98       * Constructs an empty RoleMemberXmlDTO instance.
99       */
100     public RoleMemberXmlDTO() {}
101 
102     /**
103      * Constructs a RoleMemberXmlDTO instance that is populated with the info from the given role member.
104      *
105      * @param roleMember The role member that this DTO should populate its data from.
106      * @param populateMemberId If true, the member principal/group/role ID will get populated; otherwise, only
107      * the member principal/group/role name and (if applicable) namespace will get populated.
108      * @throws IllegalArgumentException if roleMember is null, has an invalid member type, or refers to a nonexistent principal/group/role.
109      */
110     public RoleMemberXmlDTO(RoleMember roleMember, boolean populateMemberId) {
111         if (roleMember == null) {
112             throw new IllegalArgumentException("roleMember cannot be null");
113         }
114         this.memberType = roleMember.getType();
115         this.activeFromDate = roleMember.getActiveFromDate();
116         this.activeToDate = roleMember.getActiveToDate();
117         this.qualifications = (roleMember.getAttributes() != null) ? roleMember.getAttributes() : new HashMap<String, String>();
118 
119         if (MemberType.PRINCIPAL.equals(memberType)) {
120             if (populateMemberId) {
121                 this.principalId = roleMember.getMemberId();
122             }
123             PrincipalContract principal = KimApiServiceLocator.getIdentityService().getPrincipal(
124                     roleMember.getMemberId());
125             if (principal == null) {
126                 throw new IllegalArgumentException("Cannot find principal with ID \"" +  roleMember.getMemberId() + "\"");
127             }
128             this.principalName = principal.getPrincipalName();
129         } else if (MemberType.GROUP.equals(memberType)) {
130             if (populateMemberId) {
131                 this.groupId = roleMember.getMemberId();
132             }
133             GroupContract group = KimApiServiceLocator.getGroupService().getGroup(roleMember.getMemberId());
134             if (group == null) {
135                 throw new IllegalArgumentException("Cannot find group with ID \"" + roleMember.getMemberId() + "\"");
136             }
137             this.groupName = new NameAndNamespacePair(group.getNamespaceCode(), group.getName());
138         } else if (MemberType.ROLE.equals(memberType)) {
139             if (populateMemberId) {
140                 this.roleIdAsMember = roleMember.getMemberId();
141             }
142             RoleContract role = KimApiServiceLocator.getRoleService().getRole(roleMember.getMemberId());
143             if (role == null) {
144                 throw new IllegalArgumentException("Cannot find role with ID \"" + roleMember.getMemberId() + "\"");
145             }
146             this.roleNameAsMember = new NameAndNamespacePair(role.getNamespaceCode(), role.getName());
147         } else {
148             throw new IllegalArgumentException("Cannot construct a RoleMemberXmlDTO from a role member with an unrecognized member type code of \"" +
149                     memberType + "\"");
150         }
151     }
152 
153     /**
154      * @return the principalId
155      */
156     public String getPrincipalId() {
157         return this.principalId;
158     }
159 
160     /**
161      * @param principalId the principalId to set
162      */
163     public void setPrincipalId(String principalId) {
164         this.principalId = principalId;
165     }
166 
167     /**
168      * @return the principalName
169      */
170     public String getPrincipalName() {
171         return this.principalName;
172     }
173 
174     /**
175      * @param principalName the principalName to set
176      */
177     public void setPrincipalName(String principalName) {
178         this.principalName = principalName;
179     }
180 
181     /**
182      * @return the groupId
183      */
184     public String getGroupId() {
185         return this.groupId;
186     }
187 
188     /**
189      * @param groupId the groupId to set
190      */
191     public void setGroupId(String groupId) {
192         this.groupId = groupId;
193     }
194 
195     /**
196      * @return the groupName
197      */
198     public NameAndNamespacePair getGroupName() {
199         return this.groupName;
200     }
201 
202     /**
203      * @param groupName the groupName to set
204      */
205     public void setGroupName(NameAndNamespacePair groupName) {
206         this.groupName = groupName;
207     }
208 
209     /**
210      * @return the roleIdAsMember
211      */
212     public String getRoleIdAsMember() {
213         return this.roleIdAsMember;
214     }
215 
216     /**
217      * @param roleIdAsMember the roleIdAsMember to set
218      */
219     public void setRoleIdAsMember(String roleIdAsMember) {
220         this.roleIdAsMember = roleIdAsMember;
221     }
222 
223     /**
224      * @return the roleNameAsMember
225      */
226     public NameAndNamespacePair getRoleNameAsMember() {
227         return this.roleNameAsMember;
228     }
229 
230     /**
231      * @param roleNameAsMember the roleNameAsMember to set
232      */
233     public void setRoleNameAsMember(NameAndNamespacePair roleNameAsMember) {
234         this.roleNameAsMember = roleNameAsMember;
235     }
236 
237     /**
238      * @return the activeFromDate
239      */
240     public DateTime getActiveFromDate() {
241         return this.activeFromDate;
242     }
243 
244     /**
245      * @param activeFromDate the activeFromDate to set
246      */
247     public void setActiveFromDate(DateTime activeFromDate) {
248         this.activeFromDate = activeFromDate;
249     }
250 
251     /**
252      * @return the activeToDate
253      */
254     public DateTime getActiveToDate() {
255         return this.activeToDate;
256     }
257 
258     /**
259      * @param activeToDate the activeToDate to set
260      */
261     public void setActiveToDate(DateTime activeToDate) {
262         this.activeToDate = activeToDate;
263     }
264 
265     /**
266      * @return the qualifications
267      */
268     public Map<String, String> getQualifications() {
269         return this.qualifications;
270     }
271 
272     /**
273      * @param qualifications the qualifications to set
274      */
275     public void setQualifications(Map<String, String> qualifications) {
276         this.qualifications = qualifications;
277     }
278 
279     /**
280      * Retrieves the member type.
281      *
282      * <p>If the member type is null at the time that this method is invoked, an attempt will be made to set its
283      * value based on any populated member principal/group/role ID/name information.
284      *
285      * @return the member type, or null if no membership identification information has been set on this member.
286      * @throws IllegalStateException if the role member is populated simultaneously with multiple member ID/name information
287      */
288     public MemberType getMemberType() {
289         if (memberType == null) {
290             boolean foundMemberInfo = false;
291 
292             if (StringUtils.isNotBlank(principalId) || StringUtils.isNotBlank(principalName)) {
293                 memberType = MemberType.PRINCIPAL;
294                 foundMemberInfo = true;
295             }
296 
297             if (StringUtils.isNotBlank(groupId) || groupName != null) {
298                 if (foundMemberInfo) {
299                     memberType = null;
300                     throw new IllegalStateException("Cannot have a role member that is simultaneously populated with member principal, member group, and/or member role information");
301                 }
302                 memberType = MemberType.GROUP;
303                 foundMemberInfo = true;
304             }
305 
306             if (StringUtils.isNotBlank(roleIdAsMember) || roleNameAsMember != null) {
307                 if (foundMemberInfo) {
308                     memberType = null;
309                     throw new IllegalStateException("Cannot have a role member that is simultaneously populated with member principal, member group, and/or member role information");
310                 }
311                 memberType = MemberType.ROLE;
312                 foundMemberInfo = true;
313             }
314         }
315         return this.memberType;
316     }
317 
318     /**
319      * Retrieves the role member's ID, based on the member type and any populated member principal/group/role IDs.
320      *
321      * <p>If the member type is null at the time that this method is invoked, an attempt will be made to set its
322      * value based on any populated member principal/group/role ID/name information.
323      *
324      * @return The member's ID, or null if the member type is null or the associated member ID information is null.
325      */
326     public String getMemberId() {
327         if (MemberType.PRINCIPAL.equals(getMemberType())) {
328             return principalId;
329         } else if (MemberType.GROUP.equals(getMemberType())) {
330             return groupId;
331         } else if (MemberType.ROLE.equals(getMemberType())) {
332             return roleIdAsMember;
333         }
334         return null;
335     }
336 
337     /**
338      * Retrieves the role member's name, based on the member type and any populated member principal/group/role names.
339      *
340      * <p>If the member type is null at the time that this method is invoked, an attempt will be made to set its
341      * value based on any populated member principal/group/role ID/name information.
342      *
343      * @return The member's name, or null if the member type is null or the associated member name information is null.
344      */
345     public String getMemberName() {
346         if (MemberType.PRINCIPAL.equals(getMemberType())) {
347             return principalName;
348         } else if (MemberType.GROUP.equals(getMemberType())) {
349             return (groupName != null) ? groupName.getName() : null;
350         } else if (MemberType.ROLE.equals(getMemberType())) {
351             return (roleNameAsMember != null) ? roleNameAsMember.getName() : null;
352         }
353         return null;
354     }
355 
356     /**
357      * Retrieves the role member's namespace code, based on the member type and any populated member principal/group/role names.
358      *
359      * <p>If the member type is null at the time that this method is invoked, an attempt will be made to set its
360      * value based on any populated member principal/group/role ID/name information.
361      *
362      * @return The member's namespace code, or null if the member type is null, the associated member name information is null,
363      * or the role member is a principal.
364      */
365     public String getMemberNamespaceCode() {
366         if (MemberType.PRINCIPAL.equals(getMemberType())) {
367             return null;
368         } else if (MemberType.GROUP.equals(getMemberType())) {
369             return (groupName != null) ? groupName.getName() : null;
370         } else if (MemberType.ROLE.equals(getMemberType())) {
371             return (roleNameAsMember != null) ? roleNameAsMember.getName() : null;
372         }
373         return null;
374     }
375 
376     /**
377      * Retrieves the ID of the role that this member belongs to.
378      * Subclasses are responsible for implementing this method so that it does so.
379      *
380      * @return The role ID of the role that this member belongs to.
381      */
382     public abstract String getRoleId();
383 
384     // =======================================================================================================
385 
386     /**
387      * This class represents a &lt;roleMember&gt; element that is not a descendant of a &lt;role&gt; element.
388      *
389      * @author Kuali Rice Team (rice.collab@kuali.org)
390      */
391     @XmlAccessorType(XmlAccessType.FIELD)
392     @XmlType(name="StandaloneRoleMemberType", propOrder={
393             "roleId", "roleNameAndNamespace", "principalId", "principalName", "groupId", "groupName", "roleIdAsMember",
394                     "roleNameAsMember", "activeFromDate", "activeToDate", "qualifications"
395     })
396     public static class OutsideOfRole extends RoleMemberXmlDTO {
397 
398         private static final long serialVersionUID = 1L;
399 
400         @XmlElement(name="roleId")
401         @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
402         private String roleId;
403 
404         @XmlElement(name="roleName")
405         @XmlJavaTypeAdapter(NameAndNamespacePairValidatingAdapter.class)
406         private NameAndNamespacePair roleNameAndNamespace;
407 
408         public OutsideOfRole() {
409             super();
410         }
411 
412         public OutsideOfRole(RoleMember roleMember, boolean populateMemberId) {
413             super(roleMember, populateMemberId);
414             this.roleId = roleMember.getRoleId();
415             RoleContract tempRole = KimApiServiceLocator.getRoleService().getRole(roleId);
416             if (tempRole == null) {
417                 throw new IllegalArgumentException("Cannot find role with ID \"" + roleId + "\"");
418             }
419             this.roleNameAndNamespace = new NameAndNamespacePair(tempRole.getNamespaceCode(), tempRole.getName());
420         }
421 
422         /**
423          * @see org.kuali.rice.kim.impl.jaxb.RoleMemberXmlDTO#getRoleId()
424          */
425         @Override
426         public String getRoleId() {
427             return roleId;
428         }
429 
430         /**
431          * @param roleId the roleId to set
432          */
433         public void setRoleId(String roleId) {
434             this.roleId = roleId;
435         }
436 
437         /**
438          * @return the roleNameAndNamespace
439          */
440         public NameAndNamespacePair getRoleNameAndNamespace() {
441             return this.roleNameAndNamespace;
442         }
443 
444         /**
445          * @param roleNameAndNamespace the roleNameAndNamespace to set
446          */
447         public void setRoleNameAndNamespace(NameAndNamespacePair roleNameAndNamespace) {
448             this.roleNameAndNamespace = roleNameAndNamespace;
449         }
450 
451         /**
452          * Retrieves the role name from the role-name-and-namespace combo.
453          *
454          * @return The name of the role that this member belongs to, or null if the role-name-and-namespace combo is null.
455          */
456         public String getRoleName() {
457             return (roleNameAndNamespace != null) ? roleNameAndNamespace.getName() : null;
458         }
459 
460         /**
461          * Retrieves the role namespace code from the role-name-and-namespace combo.
462          *
463          * @return The namespace code of the role that this member belongs to, or null if the role-name-and-namespace combo is null.
464          */
465         public String getRoleNamespaceCode() {
466             return (roleNameAndNamespace != null) ? roleNameAndNamespace.getNamespaceCode() : null;
467         }
468     }
469 
470     // =======================================================================================================
471 
472     /**
473      * This class represents a &lt;roleMember&gt; element that is a descendant of a &lt;role&gt; element.
474      *
475      * @author Kuali Rice Team (rice.collab@kuali.org)
476      */
477     @XmlAccessorType(XmlAccessType.FIELD)
478     @XmlType(name="RoleMemberType", propOrder={
479             "principalId", "principalName", "groupId", "groupName", "roleIdAsMember",
480                     "roleNameAsMember", "activeFromDate", "activeToDate", "qualifications"
481     })
482     public static class WithinRole extends RoleMemberXmlDTO {
483 
484         private static final long serialVersionUID = 1L;
485 
486         @XmlTransient
487         private String roleId;
488 
489         public WithinRole() {
490             super();
491         }
492 
493         public WithinRole(RoleMember roleMember, boolean populateMemberId) {
494             super(roleMember, populateMemberId);
495             this.roleId = roleMember.getRoleId();
496         }
497 
498         void beforeUnmarshal(Unmarshaller unmarshaller, Object parent) {
499             if (parent instanceof RoleMembersXmlDTO.WithinRole) {
500                 this.roleId = ((RoleMembersXmlDTO.WithinRole)parent).getRoleId();
501             }
502         }
503 
504         /**
505          * @see org.kuali.rice.kim.impl.jaxb.RoleMemberXmlDTO#getRoleId()
506          */
507         @Override
508         public String getRoleId() {
509             return roleId;
510         }
511 
512     }
513 }