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 }