View Javadoc

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