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