001 /**
002 * Copyright 2005-2011 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 */
016 package org.kuali.rice.kim.impl.jaxb;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.jacorb.idl.Member;
020 import org.joda.time.DateTime;
021 import org.kuali.rice.core.api.membership.MemberType;
022 import org.kuali.rice.core.api.util.jaxb.DateTimeAdapter;
023 import org.kuali.rice.core.util.jaxb.NameAndNamespacePair;
024 import org.kuali.rice.core.util.jaxb.NameAndNamespacePairValidatingAdapter;
025 import org.kuali.rice.kim.api.KimConstants.KimUIConstants;
026 import org.kuali.rice.kim.api.group.GroupContract;
027 import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
028 import org.kuali.rice.kim.api.jaxb.QualificationListAdapter;
029 import org.kuali.rice.kim.api.role.RoleContract;
030 import org.kuali.rice.kim.api.role.RoleMember;
031 import org.kuali.rice.kim.api.role.RoleMemberContract;
032 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
033
034 import javax.xml.bind.Unmarshaller;
035 import javax.xml.bind.annotation.XmlAccessType;
036 import javax.xml.bind.annotation.XmlAccessorType;
037 import javax.xml.bind.annotation.XmlElement;
038 import javax.xml.bind.annotation.XmlTransient;
039 import javax.xml.bind.annotation.XmlType;
040 import javax.xml.bind.annotation.adapters.NormalizedStringAdapter;
041 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
042 import java.io.Serializable;
043 import java.util.HashMap;
044 import java.util.Map;
045
046 /**
047 * Base class representing an unmarshalled <roleMember> element.
048 * Refer to the static inner classes for more information about the specific contexts.
049 *
050 * @author Kuali Rice Team (rice.collab@kuali.org)
051 */
052 @XmlTransient
053 public abstract class RoleMemberXmlDTO implements Serializable {
054
055 private static final long serialVersionUID = 1L;
056
057 @XmlElement(name="principalId")
058 @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
059 private String principalId;
060
061 @XmlElement(name="principalName")
062 @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
063 private String principalName;
064
065 @XmlElement(name="groupId")
066 @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
067 private String groupId;
068
069 @XmlElement(name="groupName")
070 @XmlJavaTypeAdapter(NameAndNamespacePairValidatingAdapter.class)
071 private NameAndNamespacePair groupName;
072
073 @XmlElement(name="roleIdAsMember")
074 @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
075 private String roleIdAsMember;
076
077 @XmlElement(name="roleNameAsMember")
078 @XmlJavaTypeAdapter(NameAndNamespacePairValidatingAdapter.class)
079 private NameAndNamespacePair roleNameAsMember;
080
081 @XmlElement(name="activeFromDate")
082 @XmlJavaTypeAdapter(DateTimeAdapter.class)
083 private DateTime activeFromDate;
084
085 @XmlElement(name="activeToDate")
086 @XmlJavaTypeAdapter(DateTimeAdapter.class)
087 private DateTime activeToDate;
088
089 @XmlElement(name="qualifications")
090 @XmlJavaTypeAdapter(QualificationListAdapter.class)
091 private Map<String, String> qualifications;
092
093 @XmlTransient
094 private MemberType memberType;
095
096 /**
097 * Constructs an empty RoleMemberXmlDTO instance.
098 */
099 public RoleMemberXmlDTO() {}
100
101 /**
102 * Constructs a RoleMemberXmlDTO instance that is populated with the info from the given role member.
103 *
104 * @param roleMember The role member that this DTO should populate its data from.
105 * @param populateMemberId If true, the member principal/group/role ID will get populated; otherwise, only
106 * the member principal/group/role name and (if applicable) namespace will get populated.
107 * @throws IllegalArgumentException if roleMember is null, has an invalid member type, or refers to a nonexistent principal/group/role.
108 */
109 public RoleMemberXmlDTO(RoleMember roleMember, boolean populateMemberId) {
110 if (roleMember == null) {
111 throw new IllegalArgumentException("roleMember cannot be null");
112 }
113 this.memberType = roleMember.getMemberType();
114 this.activeFromDate = roleMember.getActiveFromDate();
115 this.activeToDate = roleMember.getActiveToDate();
116 this.qualifications = (roleMember.getAttributes() != null) ? roleMember.getAttributes() : new HashMap<String, String>();
117
118 if (MemberType.PRINCIPAL.equals(memberType)) {
119 if (populateMemberId) {
120 this.principalId = roleMember.getMemberId();
121 }
122 PrincipalContract principal = KimApiServiceLocator.getIdentityService().getPrincipal(
123 roleMember.getMemberId());
124 if (principal == null) {
125 throw new IllegalArgumentException("Cannot find principal with ID \"" + roleMember.getMemberId() + "\"");
126 }
127 this.principalName = principal.getPrincipalName();
128 } else if (MemberType.GROUP.equals(memberType)) {
129 if (populateMemberId) {
130 this.groupId = roleMember.getMemberId();
131 }
132 GroupContract group = KimApiServiceLocator.getGroupService().getGroup(roleMember.getMemberId());
133 if (group == null) {
134 throw new IllegalArgumentException("Cannot find group with ID \"" + roleMember.getMemberId() + "\"");
135 }
136 this.groupName = new NameAndNamespacePair(group.getNamespaceCode(), group.getName());
137 } else if (MemberType.ROLE.equals(memberType)) {
138 if (populateMemberId) {
139 this.roleIdAsMember = roleMember.getMemberId();
140 }
141 RoleContract role = KimApiServiceLocator.getRoleService().getRole(roleMember.getMemberId());
142 if (role == null) {
143 throw new IllegalArgumentException("Cannot find role with ID \"" + roleMember.getMemberId() + "\"");
144 }
145 this.roleNameAsMember = new NameAndNamespacePair(role.getNamespaceCode(), role.getName());
146 } else {
147 throw new IllegalArgumentException("Cannot construct a RoleMemberXmlDTO from a role member with an unrecognized member type code of \"" +
148 memberType + "\"");
149 }
150 }
151
152 /**
153 * @return the principalId
154 */
155 public String getPrincipalId() {
156 return this.principalId;
157 }
158
159 /**
160 * @param principalId the principalId to set
161 */
162 public void setPrincipalId(String principalId) {
163 this.principalId = principalId;
164 }
165
166 /**
167 * @return the principalName
168 */
169 public String getPrincipalName() {
170 return this.principalName;
171 }
172
173 /**
174 * @param principalName the principalName to set
175 */
176 public void setPrincipalName(String principalName) {
177 this.principalName = principalName;
178 }
179
180 /**
181 * @return the groupId
182 */
183 public String getGroupId() {
184 return this.groupId;
185 }
186
187 /**
188 * @param groupId the groupId to set
189 */
190 public void setGroupId(String groupId) {
191 this.groupId = groupId;
192 }
193
194 /**
195 * @return the groupName
196 */
197 public NameAndNamespacePair getGroupName() {
198 return this.groupName;
199 }
200
201 /**
202 * @param groupName the groupName to set
203 */
204 public void setGroupName(NameAndNamespacePair groupName) {
205 this.groupName = groupName;
206 }
207
208 /**
209 * @return the roleIdAsMember
210 */
211 public String getRoleIdAsMember() {
212 return this.roleIdAsMember;
213 }
214
215 /**
216 * @param roleIdAsMember the roleIdAsMember to set
217 */
218 public void setRoleIdAsMember(String roleIdAsMember) {
219 this.roleIdAsMember = roleIdAsMember;
220 }
221
222 /**
223 * @return the roleNameAsMember
224 */
225 public NameAndNamespacePair getRoleNameAsMember() {
226 return this.roleNameAsMember;
227 }
228
229 /**
230 * @param roleNameAsMember the roleNameAsMember to set
231 */
232 public void setRoleNameAsMember(NameAndNamespacePair roleNameAsMember) {
233 this.roleNameAsMember = roleNameAsMember;
234 }
235
236 /**
237 * @return the activeFromDate
238 */
239 public DateTime getActiveFromDate() {
240 return this.activeFromDate;
241 }
242
243 /**
244 * @param activeFromDate the activeFromDate to set
245 */
246 public void setActiveFromDate(DateTime activeFromDate) {
247 this.activeFromDate = activeFromDate;
248 }
249
250 /**
251 * @return the activeToDate
252 */
253 public DateTime getActiveToDate() {
254 return this.activeToDate;
255 }
256
257 /**
258 * @param activeToDate the activeToDate to set
259 */
260 public void setActiveToDate(DateTime activeToDate) {
261 this.activeToDate = activeToDate;
262 }
263
264 /**
265 * @return the qualifications
266 */
267 public Map<String, String> getQualifications() {
268 return this.qualifications;
269 }
270
271 /**
272 * @param qualifications the qualifications to set
273 */
274 public void setQualifications(Map<String, String> qualifications) {
275 this.qualifications = qualifications;
276 }
277
278 /**
279 * Retrieves the member type.
280 *
281 * <p>If the member type is null at the time that this method is invoked, an attempt will be made to set its
282 * value based on any populated member principal/group/role ID/name information.
283 *
284 * @return the member type, or null if no membership identification information has been set on this member.
285 * @throws IllegalStateException if the role member is populated simultaneously with multiple member ID/name information
286 */
287 public MemberType getMemberType() {
288 if (memberType == null) {
289 boolean foundMemberInfo = false;
290
291 if (StringUtils.isNotBlank(principalId) || StringUtils.isNotBlank(principalName)) {
292 memberType = MemberType.PRINCIPAL;
293 foundMemberInfo = true;
294 }
295
296 if (StringUtils.isNotBlank(groupId) || groupName != null) {
297 if (foundMemberInfo) {
298 memberType = null;
299 throw new IllegalStateException("Cannot have a role member that is simultaneously populated with member principal, member group, and/or member role information");
300 }
301 memberType = MemberType.GROUP;
302 foundMemberInfo = true;
303 }
304
305 if (StringUtils.isNotBlank(roleIdAsMember) || roleNameAsMember != null) {
306 if (foundMemberInfo) {
307 memberType = null;
308 throw new IllegalStateException("Cannot have a role member that is simultaneously populated with member principal, member group, and/or member role information");
309 }
310 memberType = MemberType.ROLE;
311 foundMemberInfo = true;
312 }
313 }
314 return this.memberType;
315 }
316
317 /**
318 * Retrieves the role member's ID, based on the member type and any populated member principal/group/role IDs.
319 *
320 * <p>If the member type is null at the time that this method is invoked, an attempt will be made to set its
321 * value based on any populated member principal/group/role ID/name information.
322 *
323 * @return The member's ID, or null if the member type is null or the associated member ID information is null.
324 */
325 public String getMemberId() {
326 if (MemberType.PRINCIPAL.equals(getMemberType())) {
327 return principalId;
328 } else if (MemberType.GROUP.equals(getMemberType())) {
329 return groupId;
330 } else if (MemberType.ROLE.equals(getMemberType())) {
331 return roleIdAsMember;
332 }
333 return null;
334 }
335
336 /**
337 * Retrieves the role member's name, based on the member type and any populated member principal/group/role names.
338 *
339 * <p>If the member type is null at the time that this method is invoked, an attempt will be made to set its
340 * value based on any populated member principal/group/role ID/name information.
341 *
342 * @return The member's name, or null if the member type is null or the associated member name information is null.
343 */
344 public String getMemberName() {
345 if (MemberType.PRINCIPAL.equals(getMemberType())) {
346 return principalName;
347 } else if (MemberType.GROUP.equals(getMemberType())) {
348 return (groupName != null) ? groupName.getName() : null;
349 } else if (MemberType.ROLE.equals(getMemberType())) {
350 return (roleNameAsMember != null) ? roleNameAsMember.getName() : null;
351 }
352 return null;
353 }
354
355 /**
356 * Retrieves the role member's namespace code, based on the member type and any populated member principal/group/role names.
357 *
358 * <p>If the member type is null at the time that this method is invoked, an attempt will be made to set its
359 * value based on any populated member principal/group/role ID/name information.
360 *
361 * @return The member's namespace code, or null if the member type is null, the associated member name information is null,
362 * or the role member is a principal.
363 */
364 public String getMemberNamespaceCode() {
365 if (MemberType.PRINCIPAL.equals(getMemberType())) {
366 return null;
367 } else if (MemberType.GROUP.equals(getMemberType())) {
368 return (groupName != null) ? groupName.getName() : null;
369 } else if (MemberType.ROLE.equals(getMemberType())) {
370 return (roleNameAsMember != null) ? roleNameAsMember.getName() : null;
371 }
372 return null;
373 }
374
375 /**
376 * Retrieves the ID of the role that this member belongs to.
377 * Subclasses are responsible for implementing this method so that it does so.
378 *
379 * @return The role ID of the role that this member belongs to.
380 */
381 public abstract String getRoleId();
382
383 // =======================================================================================================
384
385 /**
386 * This class represents a <roleMember> element that is not a descendant of a <role> element.
387 *
388 * @author Kuali Rice Team (rice.collab@kuali.org)
389 */
390 @XmlAccessorType(XmlAccessType.FIELD)
391 @XmlType(name="StandaloneRoleMemberType", propOrder={
392 "roleId", "roleNameAndNamespace", "principalId", "principalName", "groupId", "groupName", "roleIdAsMember",
393 "roleNameAsMember", "activeFromDate", "activeToDate", "qualifications"
394 })
395 public static class OutsideOfRole extends RoleMemberXmlDTO {
396
397 private static final long serialVersionUID = 1L;
398
399 @XmlElement(name="roleId")
400 @XmlJavaTypeAdapter(NormalizedStringAdapter.class)
401 private String roleId;
402
403 @XmlElement(name="roleName")
404 @XmlJavaTypeAdapter(NameAndNamespacePairValidatingAdapter.class)
405 private NameAndNamespacePair roleNameAndNamespace;
406
407 public OutsideOfRole() {
408 super();
409 }
410
411 public OutsideOfRole(RoleMember roleMember, boolean populateMemberId) {
412 super(roleMember, populateMemberId);
413 this.roleId = roleMember.getRoleId();
414 RoleContract tempRole = KimApiServiceLocator.getRoleService().getRole(roleId);
415 if (tempRole == null) {
416 throw new IllegalArgumentException("Cannot find role with ID \"" + roleId + "\"");
417 }
418 this.roleNameAndNamespace = new NameAndNamespacePair(tempRole.getNamespaceCode(), tempRole.getName());
419 }
420
421 /**
422 * @see org.kuali.rice.kim.impl.jaxb.RoleMemberXmlDTO#getRoleId()
423 */
424 @Override
425 public String getRoleId() {
426 return roleId;
427 }
428
429 /**
430 * @param roleId the roleId to set
431 */
432 public void setRoleId(String roleId) {
433 this.roleId = roleId;
434 }
435
436 /**
437 * @return the roleNameAndNamespace
438 */
439 public NameAndNamespacePair getRoleNameAndNamespace() {
440 return this.roleNameAndNamespace;
441 }
442
443 /**
444 * @param roleNameAndNamespace the roleNameAndNamespace to set
445 */
446 public void setRoleNameAndNamespace(NameAndNamespacePair roleNameAndNamespace) {
447 this.roleNameAndNamespace = roleNameAndNamespace;
448 }
449
450 /**
451 * Retrieves the role name from the role-name-and-namespace combo.
452 *
453 * @return The name of the role that this member belongs to, or null if the role-name-and-namespace combo is null.
454 */
455 public String getRoleName() {
456 return (roleNameAndNamespace != null) ? roleNameAndNamespace.getName() : null;
457 }
458
459 /**
460 * Retrieves the role namespace code from the role-name-and-namespace combo.
461 *
462 * @return The namespace code of the role that this member belongs to, or null if the role-name-and-namespace combo is null.
463 */
464 public String getRoleNamespaceCode() {
465 return (roleNameAndNamespace != null) ? roleNameAndNamespace.getNamespaceCode() : null;
466 }
467 }
468
469 // =======================================================================================================
470
471 /**
472 * This class represents a <roleMember> element that is a descendant of a <role> element.
473 *
474 * @author Kuali Rice Team (rice.collab@kuali.org)
475 */
476 @XmlAccessorType(XmlAccessType.FIELD)
477 @XmlType(name="RoleMemberType", propOrder={
478 "principalId", "principalName", "groupId", "groupName", "roleIdAsMember",
479 "roleNameAsMember", "activeFromDate", "activeToDate", "qualifications"
480 })
481 public static class WithinRole extends RoleMemberXmlDTO {
482
483 private static final long serialVersionUID = 1L;
484
485 @XmlTransient
486 private String roleId;
487
488 public WithinRole() {
489 super();
490 }
491
492 public WithinRole(RoleMember roleMember, boolean populateMemberId) {
493 super(roleMember, populateMemberId);
494 this.roleId = roleMember.getRoleId();
495 }
496
497 void beforeUnmarshal(Unmarshaller unmarshaller, Object parent) {
498 if (parent instanceof RoleMembersXmlDTO.WithinRole) {
499 this.roleId = ((RoleMembersXmlDTO.WithinRole)parent).getRoleId();
500 }
501 }
502
503 /**
504 * @see org.kuali.rice.kim.impl.jaxb.RoleMemberXmlDTO#getRoleId()
505 */
506 @Override
507 public String getRoleId() {
508 return roleId;
509 }
510
511 }
512 }