Coverage Report - org.kuali.rice.kim.document.rule.IdentityManagementRoleDocumentRule
 
Classes in this File Line Coverage Branch Coverage Complexity
IdentityManagementRoleDocumentRule
0%
0/298
0%
0/224
4.205
 
 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.document.rule;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.kuali.rice.core.api.uif.RemotableAttributeError;
 20  
 import org.kuali.rice.core.api.util.RiceKeyConstants;
 21  
 import org.kuali.rice.kim.api.KimConstants;
 22  
 import org.kuali.rice.kim.api.identity.IdentityService;
 23  
 import org.kuali.rice.kim.api.permission.Permission;
 24  
 import org.kuali.rice.kim.api.responsibility.Responsibility;
 25  
 import org.kuali.rice.kim.api.responsibility.ResponsibilityService;
 26  
 import org.kuali.rice.kim.api.role.Role;
 27  
 import org.kuali.rice.kim.api.role.RoleService;
 28  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 29  
 import org.kuali.rice.kim.api.type.KimAttributeField;
 30  
 import org.kuali.rice.kim.api.type.KimType;
 31  
 import org.kuali.rice.kim.bo.ui.KimDocumentRoleMember;
 32  
 import org.kuali.rice.kim.bo.ui.KimDocumentRolePermission;
 33  
 import org.kuali.rice.kim.bo.ui.KimDocumentRoleQualifier;
 34  
 import org.kuali.rice.kim.bo.ui.KimDocumentRoleResponsibility;
 35  
 import org.kuali.rice.kim.bo.ui.KimDocumentRoleResponsibilityAction;
 36  
 import org.kuali.rice.kim.bo.ui.RoleDocumentDelegationMember;
 37  
 import org.kuali.rice.kim.bo.ui.RoleDocumentDelegationMemberQualifier;
 38  
 import org.kuali.rice.kim.document.IdentityManagementRoleDocument;
 39  
 import org.kuali.rice.kim.framework.services.KimFrameworkServiceLocator;
 40  
 import org.kuali.rice.kim.framework.type.KimTypeService;
 41  
 import org.kuali.rice.kim.impl.responsibility.AddResponsibilityEvent;
 42  
 import org.kuali.rice.kim.impl.responsibility.AddResponsibilityRule;
 43  
 import org.kuali.rice.kim.impl.responsibility.KimDocumentResponsibilityRule;
 44  
 import org.kuali.rice.kim.impl.responsibility.ResponsibilityBo;
 45  
 import org.kuali.rice.kim.impl.responsibility.ResponsibilityInternalService;
 46  
 import org.kuali.rice.kim.impl.services.KimImplServiceLocator;
 47  
 import org.kuali.rice.kim.impl.type.KimTypeLookupableHelperServiceImpl;
 48  
 import org.kuali.rice.kim.rule.event.ui.AddDelegationEvent;
 49  
 import org.kuali.rice.kim.rule.event.ui.AddDelegationMemberEvent;
 50  
 import org.kuali.rice.kim.rule.event.ui.AddMemberEvent;
 51  
 import org.kuali.rice.kim.rule.event.ui.AddPermissionEvent;
 52  
 import org.kuali.rice.kim.rule.ui.AddDelegationMemberRule;
 53  
 import org.kuali.rice.kim.rule.ui.AddDelegationRule;
 54  
 import org.kuali.rice.kim.rule.ui.AddMemberRule;
 55  
 import org.kuali.rice.kim.rule.ui.AddPermissionRule;
 56  
 import org.kuali.rice.kim.rules.ui.KimDocumentMemberRule;
 57  
 import org.kuali.rice.kim.rules.ui.KimDocumentPermissionRule;
 58  
 import org.kuali.rice.kim.rules.ui.RoleDocumentDelegationMemberRule;
 59  
 import org.kuali.rice.kim.rules.ui.RoleDocumentDelegationRule;
 60  
 import org.kuali.rice.kns.kim.type.DataDictionaryTypeServiceHelper;
 61  
 import org.kuali.rice.krad.document.Document;
 62  
 import org.kuali.rice.krad.rules.TransactionalDocumentRuleBase;
 63  
 import org.kuali.rice.krad.service.BusinessObjectService;
 64  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 65  
 import org.kuali.rice.krad.util.GlobalVariables;
 66  
 import org.kuali.rice.krad.util.KRADConstants;
 67  
 import org.kuali.rice.krad.util.MessageMap;
 68  
 
 69  
 import java.sql.Timestamp;
 70  
 import java.util.ArrayList;
 71  
 import java.util.Collections;
 72  
 import java.util.HashMap;
 73  
 import java.util.HashSet;
 74  
 import java.util.List;
 75  
 import java.util.Map;
 76  
 import java.util.Set;
 77  
 
 78  
 /**
 79  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 80  
  */
 81  0
 public class IdentityManagementRoleDocumentRule extends TransactionalDocumentRuleBase implements AddPermissionRule, AddResponsibilityRule, AddMemberRule, AddDelegationRule, AddDelegationMemberRule {
 82  
 //        protected static final Logger LOG = Logger.getLogger( IdentityManagementRoleDocumentRule.class );
 83  
 
 84  
     public static final int PRIORITY_NUMBER_MIN_VALUE = 1;
 85  
     public static final int PRIORITY_NUMBER_MAX_VALUE = 11;
 86  
 
 87  
         protected AddResponsibilityRule addResponsibilityRule;
 88  
         protected AddPermissionRule  addPermissionRule;
 89  
         protected AddMemberRule  addMemberRule;
 90  
         protected AddDelegationRule addDelegationRule;
 91  
         protected AddDelegationMemberRule addDelegationMemberRule;
 92  
         protected BusinessObjectService businessObjectService;
 93  
         protected ResponsibilityService responsibilityService;
 94  0
         protected Class<? extends AddResponsibilityRule> addResponsibilityRuleClass = KimDocumentResponsibilityRule.class;
 95  0
         protected Class<? extends AddPermissionRule> addPermissionRuleClass = KimDocumentPermissionRule.class;
 96  0
         protected Class<? extends AddMemberRule> addMemberRuleClass = KimDocumentMemberRule.class;
 97  0
         protected Class<? extends AddDelegationRule> addDelegationRuleClass = RoleDocumentDelegationRule.class;
 98  0
         protected Class<? extends AddDelegationMemberRule> addDelegationMemberRuleClass = RoleDocumentDelegationMemberRule.class;
 99  
 
 100  
         protected IdentityService identityService;
 101  
         private static ResponsibilityInternalService responsibilityInternalService;
 102  
 
 103  0
         protected AttributeValidationHelper attributeValidationHelper = new AttributeValidationHelper();
 104  
 
 105  
         // KULRICE-4153
 106  0
         protected ActiveRoleMemberHelper activeRoleMemberHelper = new ActiveRoleMemberHelper();
 107  
 
 108  
     public IdentityService getIdentityService() {
 109  0
         if ( identityService == null) {
 110  0
             identityService = KimApiServiceLocator.getIdentityService();
 111  
         }
 112  0
         return identityService;
 113  
     }
 114  
 
 115  
     @Override
 116  
     protected boolean processCustomSaveDocumentBusinessRules(Document document) {
 117  0
         if (!(document instanceof IdentityManagementRoleDocument)) {
 118  0
             return false;
 119  
         }
 120  
 
 121  0
         IdentityManagementRoleDocument roleDoc = (IdentityManagementRoleDocument)document;
 122  
 
 123  0
         boolean valid = true;
 124  0
         boolean validateRoleAssigneesAndDelegations = !KimTypeLookupableHelperServiceImpl
 125  
                 .hasDerivedRoleTypeService(roleDoc.getKimType());
 126  0
         GlobalVariables.getMessageMap().addToErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
 127  0
         valid &= validDuplicateRoleName(roleDoc);
 128  0
         valid &= validPermissions(roleDoc);
 129  0
         valid &= validResponsibilities(roleDoc);
 130  0
         getDictionaryValidationService().validateDocumentAndUpdatableReferencesRecursively(document, getMaxDictionaryValidationDepth(), true, false);
 131  0
         validateRoleAssigneesAndDelegations &= validAssignRole(roleDoc);
 132  0
         if(validateRoleAssigneesAndDelegations){
 133  
                 //valid &= validAssignRole(roleDoc);
 134  
                 // KULRICE-4153 & KULRICE-4818
 135  
                 // Use the Active Role Member Helper to retrieve only those Role Members & Delegation member that are active
 136  
                 // If a member or delegation is active on a Role, and they have an inactive Role Qualifier, Role Qualifier validation will fail
 137  
                 // If a member or delegation is inactive on a Role, and they have an inactive Role Qualifier, Role Qualifier validation will pass
 138  0
                 List<KimDocumentRoleMember> activeRoleMembers = activeRoleMemberHelper.getActiveRoleMembers(roleDoc.getMembers());
 139  0
                 List<RoleDocumentDelegationMember> activeRoleDelegationMembers = activeRoleMemberHelper.getActiveDelegationRoleMembers(roleDoc.getDelegationMembers());
 140  
 
 141  0
                 valid &= validateRoleQualifier(activeRoleMembers, roleDoc.getKimType());
 142  0
                 valid &= validRoleMemberActiveDates(roleDoc.getMembers());
 143  0
                 valid &= validateDelegationMemberRoleQualifier(activeRoleMembers, activeRoleDelegationMembers, roleDoc.getKimType());
 144  0
                 valid &= validDelegationMemberActiveDates(roleDoc.getDelegationMembers());
 145  0
                 valid &= validRoleMembersResponsibilityActions(roleDoc.getMembers());
 146  
         }
 147  0
         valid &= validRoleResponsibilitiesActions(roleDoc.getResponsibilities());
 148  0
         GlobalVariables.getMessageMap().removeFromErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
 149  
 
 150  0
         return valid;
 151  
     }
 152  
 
 153  
         protected boolean validAssignRole(IdentityManagementRoleDocument document){
 154  0
         boolean rulePassed = true;
 155  0
         Map<String,String> additionalPermissionDetails = new HashMap<String,String>();
 156  0
         additionalPermissionDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, document.getRoleNamespace());
 157  0
         additionalPermissionDetails.put(KimConstants.AttributeConstants.ROLE_NAME, document.getRoleName());
 158  0
                 if((document.getMembers()!=null && document.getMembers().size()>0) ||
 159  
                                 (document.getDelegationMembers()!=null && document.getDelegationMembers().size()>0)){
 160  0
                         if(!getDocumentHelperService().getDocumentAuthorizer(document).isAuthorizedByTemplate(
 161  
                                         document, KimConstants.NAMESPACE_CODE, KimConstants.PermissionTemplateNames.ASSIGN_ROLE,
 162  
                                         GlobalVariables.getUserSession().getPrincipalId(), additionalPermissionDetails, null)){
 163  0
                     rulePassed = false;
 164  
                         }
 165  
                 }
 166  0
                 return rulePassed;
 167  
         }
 168  
 
 169  
     @SuppressWarnings("unchecked")
 170  
         protected boolean validDuplicateRoleName(IdentityManagementRoleDocument roleDoc){
 171  0
         Role role = KimApiServiceLocator.getRoleService().getRoleByNameAndNamespaceCode(roleDoc.getRoleNamespace(),
 172  
                 roleDoc.getRoleName());
 173  0
             boolean rulePassed = true;
 174  0
             if(role!=null){
 175  0
                     if(role.getId().equals(roleDoc.getRoleId())) {
 176  0
                 rulePassed = true;
 177  
             }
 178  
                     else{
 179  0
                             GlobalVariables.getMessageMap().putError("document.roleName",
 180  
                                             RiceKeyConstants.ERROR_DUPLICATE_ENTRY, new String[] {"Role Name"});
 181  0
                             rulePassed = false;
 182  
                     }
 183  
             }
 184  0
             return rulePassed;
 185  
     }
 186  
 
 187  
     protected boolean validRoleMemberActiveDates(List<KimDocumentRoleMember> roleMembers) {
 188  0
             boolean valid = true;
 189  0
                 int i = 0;
 190  0
             for(KimDocumentRoleMember roleMember: roleMembers) {
 191  0
                            valid &= validateActiveDate("document.members["+i+"].activeToDate", roleMember.getActiveFromDate(), roleMember.getActiveToDate());
 192  0
                     i++;
 193  
             }
 194  0
             return valid;
 195  
     }
 196  
 
 197  
     protected boolean validDelegationMemberActiveDates(List<RoleDocumentDelegationMember> delegationMembers) {
 198  0
             boolean valid = true;
 199  0
                 int i = 0;
 200  0
             for(RoleDocumentDelegationMember delegationMember: delegationMembers) {
 201  0
                            valid &= validateActiveDate("document.delegationMembers[" + i + "].activeToDate",
 202  
                        delegationMember.getActiveFromDate(), delegationMember.getActiveToDate());
 203  0
                     i++;
 204  
             }
 205  0
             return valid;
 206  
     }
 207  
 
 208  
     protected boolean validPermissions(IdentityManagementRoleDocument document){
 209  
             Permission kimPermissionInfo;
 210  0
             boolean valid = true;
 211  0
             int i = 0;
 212  0
             for(KimDocumentRolePermission permission: document.getPermissions()){
 213  0
                     kimPermissionInfo = permission.getPermission();
 214  0
                     if(!permission.isActive() && !hasPermissionToGrantPermission(permission.getPermission(), document)){
 215  0
                     GlobalVariables.getMessageMap().putError("permissions["+i+"].active", RiceKeyConstants.ERROR_ASSIGN_PERMISSION,
 216  
                                     new String[] {kimPermissionInfo.getNamespaceCode(), kimPermissionInfo.getTemplate().getName()});
 217  0
                     valid = false;
 218  
                     }
 219  0
                     i++;
 220  
             }
 221  0
             return valid;
 222  
     }
 223  
 
 224  
     protected boolean validResponsibilities(IdentityManagementRoleDocument document){
 225  
             ResponsibilityBo kimResponsibilityImpl;
 226  0
             boolean valid = true;
 227  0
             int i = 0;
 228  0
             for(KimDocumentRoleResponsibility responsibility: document.getResponsibilities()){
 229  0
                     kimResponsibilityImpl = responsibility.getKimResponsibility();
 230  0
                     if(!responsibility.isActive() && !hasPermissionToGrantResponsibility(ResponsibilityBo.to(responsibility.getKimResponsibility()), document)){
 231  0
                     GlobalVariables.getMessageMap().putError("responsibilities["+i+"].active", RiceKeyConstants.ERROR_ASSIGN_RESPONSIBILITY,
 232  
                                     new String[] {kimResponsibilityImpl.getNamespaceCode(), kimResponsibilityImpl.getTemplate().getName()});
 233  0
                     valid = false;
 234  
                     }
 235  0
                     i++;
 236  
             }
 237  0
             return valid;
 238  
     }
 239  
 
 240  
     protected boolean validRoleResponsibilitiesActions(List<KimDocumentRoleResponsibility> roleResponsibilities){
 241  0
         int i = 0;
 242  0
         boolean rulePassed = true;
 243  0
             for(KimDocumentRoleResponsibility roleResponsibility: roleResponsibilities){
 244  0
                     if(!getResponsibilityInternalService().areActionsAtAssignmentLevelById(roleResponsibility.getResponsibilityId())) {
 245  0
                             validateRoleResponsibilityAction("document.responsibilities["+i+"].roleRspActions[0].priorityNumber", roleResponsibility.getRoleRspActions().get(0));
 246  
             }
 247  0
                 i++;
 248  
             }
 249  0
             return rulePassed;
 250  
     }
 251  
 
 252  
     protected boolean validRoleMembersResponsibilityActions(List<KimDocumentRoleMember> roleMembers){
 253  0
         int i = 0;
 254  
         int j;
 255  0
         boolean rulePassed = true;
 256  0
             for(KimDocumentRoleMember roleMember: roleMembers){
 257  0
                     j = 0;
 258  0
                     if(roleMember.getRoleRspActions()!=null && !roleMember.getRoleRspActions().isEmpty()){
 259  0
                             for(KimDocumentRoleResponsibilityAction roleRspAction: roleMember.getRoleRspActions()){
 260  0
                                     validateRoleResponsibilityAction("document.members["+i+"].roleRspActions["+j+"].priorityNumber", roleRspAction);
 261  0
                                 j++;
 262  
                             }
 263  
                     }
 264  0
                     i++;
 265  
             }
 266  0
             return rulePassed;
 267  
     }
 268  
 
 269  
     protected boolean validateRoleResponsibilityAction(String errorPath, KimDocumentRoleResponsibilityAction roleRspAction){
 270  0
             boolean rulePassed = true;
 271  
             /*if(StringUtils.isBlank(roleRspAction.getActionPolicyCode())){
 272  
                     GlobalVariables.getErrorMap().putError(errorPath,
 273  
                                     RiceKeyConstants.ERROR_EMPTY_ENTRY, new String[] {"Action Policy Code"});
 274  
                     rulePassed = false;
 275  
             }
 276  
             if(roleRspAction.getPriorityNumber()==null){
 277  
                     GlobalVariables.getErrorMap().putError(errorPath,
 278  
                                     RiceKeyConstants.ERROR_EMPTY_ENTRY, new String[] {"Priority Number"});
 279  
                     rulePassed = false;
 280  
             }
 281  
             if(StringUtils.isBlank(roleRspAction.getActionTypeCode())){
 282  
                     GlobalVariables.getErrorMap().putError(errorPath,
 283  
                                     RiceKeyConstants.ERROR_EMPTY_ENTRY, new String[] {"Action Type Code"});
 284  
                     rulePassed = false;
 285  
             }*/
 286  0
             if(roleRspAction.getPriorityNumber()!=null &&
 287  
                             (roleRspAction.getPriorityNumber()<PRIORITY_NUMBER_MIN_VALUE
 288  
                                             || roleRspAction.getPriorityNumber()>PRIORITY_NUMBER_MAX_VALUE)){
 289  0
                     GlobalVariables.getMessageMap().putError(errorPath,
 290  
                                    RiceKeyConstants.ERROR_PRIORITY_NUMBER_RANGE, new String[] {PRIORITY_NUMBER_MIN_VALUE+"", PRIORITY_NUMBER_MAX_VALUE+""});
 291  0
                     rulePassed = false;
 292  
             }
 293  
 
 294  0
             return rulePassed;
 295  
     }
 296  
 
 297  
     protected boolean validateRoleQualifier(List<KimDocumentRoleMember> roleMembers, KimType kimType){
 298  0
                 List<RemotableAttributeError> validationErrors = new ArrayList<RemotableAttributeError>();
 299  
 
 300  0
                 int memberCounter = 0;
 301  0
                 int roleMemberCount = 0;
 302  
                 List<RemotableAttributeError> errorsTemp;
 303  
                 Map<String, String> mapToValidate;
 304  0
         KimTypeService kimTypeService = KimFrameworkServiceLocator.getKimTypeService(kimType);
 305  0
         GlobalVariables.getMessageMap().removeFromErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
 306  0
         final List<KimAttributeField> attributeDefinitions = kimTypeService.getAttributeDefinitions(kimType.getId());
 307  0
         final Set<String> uniqueAttributeNames = figureOutUniqueQualificationSet(roleMembers, attributeDefinitions);
 308  
 
 309  0
                 for(KimDocumentRoleMember roleMember: roleMembers) {
 310  0
                         errorsTemp = Collections.emptyList();
 311  0
                         mapToValidate = attributeValidationHelper.convertQualifiersToMap(roleMember.getQualifiers());
 312  0
                         if(!roleMember.isRole()){
 313  0
                                 errorsTemp = kimTypeService.validateAttributes(kimType.getId(), mapToValidate);
 314  0
                                 validationErrors.addAll(attributeValidationHelper.convertErrorsForMappedFields(
 315  
                         "document.members[" + memberCounter + "]", errorsTemp));
 316  0
                         memberCounter++;
 317  
                         }
 318  0
                         if (uniqueAttributeNames.size() > 0) {
 319  0
                                 validateUniquePersonRoleQualifiersUniqueForRoleMembership(roleMember, roleMemberCount, roleMembers, uniqueAttributeNames, validationErrors);
 320  
                         }
 321  
 
 322  0
                         roleMemberCount += 1;
 323  
             }
 324  
 
 325  0
                 GlobalVariables.getMessageMap().addToErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
 326  
 
 327  0
             if (validationErrors.isEmpty()) {
 328  0
                     return true;
 329  
             } 
 330  0
             attributeValidationHelper.moveValidationErrorsToErrorMap(validationErrors);
 331  0
             return false;
 332  
     }
 333  
 
 334  
     /**
 335  
      * Finds the names of the unique qualification attributes which this role should be checking against
 336  
      *
 337  
      * @param memberships the memberships (we take the qualification from the first)
 338  
      * @param attributeDefinitions information about the attributeDefinitions
 339  
      * @return a Set of unique attribute ids (with their indices, for error reporting)
 340  
      */
 341  
     protected Set<String> figureOutUniqueQualificationSet(List<KimDocumentRoleMember> memberships, List<KimAttributeField> attributeDefinitions) {
 342  0
             Set<String> uniqueAttributeIds = new HashSet<String>();
 343  
 
 344  0
             if (memberships != null && memberships.size() > 1) { // if there aren't two or more members, doing this whole check is kinda silly
 345  0
                     KimDocumentRoleMember membership = memberships.get(0);
 346  
 
 347  0
                     for (KimDocumentRoleQualifier qualifier : membership.getQualifiers()) {
 348  0
                         if (qualifier != null && qualifier.getKimAttribute() != null && !StringUtils.isBlank(qualifier.getKimAttribute().getAttributeName())) {
 349  0
                                 final KimAttributeField relatedDefinition = DataDictionaryTypeServiceHelper.findAttributeField(
 350  
                             qualifier.getKimAttribute().getAttributeName(), attributeDefinitions);
 351  
 
 352  0
                                 if (relatedDefinition != null && relatedDefinition.isUnique()) {
 353  0
                                         uniqueAttributeIds.add(qualifier.getKimAttrDefnId()); // it's unique - add it to the Set
 354  
                                 }
 355  0
                         }
 356  
                     }
 357  
             }
 358  
 
 359  0
             return uniqueAttributeIds;
 360  
     }
 361  
 
 362  
     /**
 363  
      * Checks all the qualifiers for the given membership, so that all qualifiers which should be unique are guaranteed to be unique
 364  
      *
 365  
      * @param membershipToCheck the membership to check
 366  
      * @param membershipToCheckIndex the index of the person's membership in the role (for error reporting purposes)
 367  
      * @param validationErrors Map<String, String> of errors to report
 368  
      * @return true if all unique values are indeed unique, false otherwise
 369  
      */
 370  
     protected boolean validateUniquePersonRoleQualifiersUniqueForRoleMembership(KimDocumentRoleMember membershipToCheck, int membershipToCheckIndex, List<KimDocumentRoleMember> memberships, Set<String> uniqueQualifierIds, List<RemotableAttributeError> validationErrors) {
 371  0
             boolean foundError = false;
 372  0
             int count = 0;
 373  
 
 374  0
             for (KimDocumentRoleMember membership : memberships) {
 375  0
                     if (membershipToCheckIndex != count) {
 376  0
                             if (sameMembership(membershipToCheck, membership)) {
 377  0
                                     if (sameUniqueMembershipQualifications(membershipToCheck, membership, uniqueQualifierIds)) {
 378  0
                                             foundError = true;
 379  
                                             // add error to each qualifier which is supposed to be unique
 380  0
                                             int qualifierCount = 0;
 381  
 
 382  0
                                             for (KimDocumentRoleQualifier qualifier : membership.getQualifiers()) {
 383  0
                                                     if (qualifier != null && uniqueQualifierIds.contains(qualifier.getKimAttrDefnId())) {
 384  0
                                                             validationErrors.add(RemotableAttributeError.Builder.create("document.members["+membershipToCheckIndex+"].qualifiers["+qualifierCount+"].attrVal", RiceKeyConstants.ERROR_DOCUMENT_IDENTITY_MANAGEMENT_PERSON_QUALIFIER_VALUE_NOT_UNIQUE+":"+qualifier.getKimAttribute().getAttributeName()+";"+qualifier.getAttrVal()).build());
 385  
                                                     }
 386  0
                                                     qualifierCount += 1;
 387  
                                             }
 388  
                                     }
 389  
                             }
 390  
                     }
 391  0
                     count += 1;
 392  
             }
 393  
 
 394  0
             return foundError;
 395  
     }
 396  
 
 397  
     /**
 398  
      * Determines if two memberships represent the same member being added: that is, the two memberships have the same type code and id
 399  
      *
 400  
      * @param membershipA the first membership to check
 401  
      * @param membershipB the second membership to check
 402  
      * @return true if the two memberships represent the same member; false if they do not, or if it could not be profitably determined if the members were the same
 403  
      */
 404  
     protected boolean sameMembership(KimDocumentRoleMember membershipA, KimDocumentRoleMember membershipB) {
 405  0
             if (!StringUtils.isBlank(membershipA.getMemberTypeCode()) && !StringUtils.isBlank(membershipB.getMemberTypeCode()) && !StringUtils.isBlank(membershipA.getMemberId()) && !StringUtils.isBlank(membershipB.getMemberId())) {
 406  0
                     return membershipA.getMemberTypeCode().equals(membershipB.getMemberTypeCode()) && membershipA.getMemberId().equals(membershipB.getMemberId());
 407  
             }
 408  0
             return false;
 409  
     }
 410  
 
 411  
     /**
 412  
      * Given two memberships which represent the same member, do they share qualifications?
 413  
      *
 414  
      * @param membershipA the first membership to check
 415  
      * @param membershipB the second membership to check
 416  
      * @param uniqueAttributeIds the Set of attribute definition ids which should be unique
 417  
      * @return
 418  
      */
 419  
     protected boolean sameUniqueMembershipQualifications(KimDocumentRoleMember membershipA, KimDocumentRoleMember membershipB, Set<String> uniqueAttributeIds) {
 420  0
             boolean equalSoFar = true;
 421  0
             for (String kimAttributeDefinitionId : uniqueAttributeIds) {
 422  0
                     final KimDocumentRoleQualifier qualifierA = membershipA.getQualifier(kimAttributeDefinitionId);
 423  0
                     final KimDocumentRoleQualifier qualifierB = membershipB.getQualifier(kimAttributeDefinitionId);
 424  
 
 425  0
                     if (qualifierA != null && qualifierB != null) {
 426  0
                             equalSoFar &= (qualifierA.getAttrVal() == null && qualifierB.getAttrVal() == null) || (qualifierA.getAttrVal() == null || qualifierA.getAttrVal().equals(qualifierB.getAttrVal()));
 427  
                     }
 428  0
             }
 429  0
             return equalSoFar;
 430  
     }
 431  
 
 432  
     protected KimDocumentRoleMember getRoleMemberForDelegation(
 433  
                     List<KimDocumentRoleMember> roleMembers, RoleDocumentDelegationMember delegationMember){
 434  0
             if(roleMembers==null || delegationMember==null || delegationMember.getRoleMemberId()==null) { return null; }
 435  0
             for(KimDocumentRoleMember roleMember: roleMembers){
 436  0
                     if(delegationMember.getRoleMemberId().equals(roleMember.getRoleMemberId())) {
 437  0
                 return roleMember;
 438  
             }
 439  
             }
 440  0
             return null;
 441  
     }
 442  
 
 443  
     protected boolean validateDelegationMemberRoleQualifier(List<KimDocumentRoleMember> roleMembers,
 444  
                     List<RoleDocumentDelegationMember> delegationMembers, KimType kimType){
 445  0
                 List<RemotableAttributeError> validationErrors = new ArrayList<RemotableAttributeError>();
 446  
                 boolean valid;
 447  0
                 int memberCounter = 0;
 448  
                 List<RemotableAttributeError> errorsTemp;
 449  
                 Map<String, String> mapToValidate;
 450  0
         KimTypeService kimTypeService = KimFrameworkServiceLocator.getKimTypeService(kimType);
 451  0
         GlobalVariables.getMessageMap().removeFromErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
 452  
         KimDocumentRoleMember roleMember;
 453  
         String errorPath;
 454  0
         final List<KimAttributeField> attributeDefinitions = kimTypeService.getAttributeDefinitions(kimType.getId());
 455  0
         final Set<String> uniqueQualifierAttributes = figureOutUniqueQualificationSetForDelegation(delegationMembers, attributeDefinitions);
 456  
 
 457  0
                 for(RoleDocumentDelegationMember delegationMember: delegationMembers) {
 458  0
                         errorPath = "delegationMembers["+memberCounter+"]";
 459  0
                         mapToValidate = attributeValidationHelper.convertQualifiersToMap(delegationMember.getQualifiers());
 460  0
                         if(!delegationMember.isRole()){
 461  0
                                 errorsTemp = kimTypeService.validateAttributes(kimType.getId(), mapToValidate);
 462  0
                                 validationErrors.addAll(
 463  
                                                 attributeValidationHelper.convertErrorsForMappedFields(errorPath, errorsTemp));
 464  
                         }
 465  0
                         roleMember = getRoleMemberForDelegation(roleMembers, delegationMember);
 466  0
                         if(roleMember==null){
 467  0
                                 valid = false;
 468  0
                                 GlobalVariables.getMessageMap().putError("document.delegationMembers["+memberCounter+"]", RiceKeyConstants.ERROR_DELEGATE_ROLE_MEMBER_ASSOCIATION, new String[]{});
 469  
                         } else{
 470  0
                                 errorsTemp = kimTypeService.validateAttributesAgainstExisting(
 471  
                                                                 kimType.getId(),
 472  
                                                                 attributeValidationHelper.convertQualifiersToMap(roleMember.getQualifiers()),
 473  
                                                                 mapToValidate);
 474  0
                                 validationErrors.addAll(
 475  
                                                 attributeValidationHelper.convertErrorsForMappedFields(errorPath, errorsTemp) );
 476  
                         }
 477  0
                         if (uniqueQualifierAttributes.size() > 0) {
 478  0
                                 validateUniquePersonRoleQualifiersUniqueForRoleDelegation(delegationMember, memberCounter, delegationMembers, uniqueQualifierAttributes, validationErrors);
 479  
                         }
 480  0
                 memberCounter++;
 481  
             }
 482  0
                 GlobalVariables.getMessageMap().addToErrorPath(KRADConstants.DOCUMENT_PROPERTY_NAME);
 483  0
             if (validationErrors.isEmpty()) {
 484  0
                     valid = true;
 485  
             } else {
 486  0
                     attributeValidationHelper.moveValidationErrorsToErrorMap(validationErrors);
 487  0
                     valid = false;
 488  
             }
 489  0
             return valid;
 490  
     }
 491  
 
 492  
     /**
 493  
      * Finds the names of the unique qualification attributes which this role should be checking against
 494  
      *
 495  
      * @param memberships the memberships (we take the qualification from the first)
 496  
      * @param attributeDefinitions information about the attributeDefinitions
 497  
      * @return a Set of unique attribute ids (with their indices, for error reporting)
 498  
      */
 499  
     protected Set<String> figureOutUniqueQualificationSetForDelegation(List<RoleDocumentDelegationMember> memberships, List<KimAttributeField> attributeDefinitions) {
 500  0
             Set<String> uniqueAttributeIds = new HashSet<String>();
 501  
 
 502  0
             if (memberships != null && memberships.size() > 1) { // if there aren't two or more members, doing this whole check is kinda silly
 503  0
                     RoleDocumentDelegationMember membership = memberships.get(0);
 504  
 
 505  0
                     for (RoleDocumentDelegationMemberQualifier qualifier : membership.getQualifiers()) {
 506  0
                         if (qualifier != null && qualifier.getKimAttribute() != null && !StringUtils.isBlank(qualifier.getKimAttribute().getAttributeName())) {
 507  0
                                 final KimAttributeField relatedDefinition = DataDictionaryTypeServiceHelper.findAttributeField(
 508  
                             qualifier.getKimAttribute().getAttributeName(), attributeDefinitions);
 509  
 
 510  0
                                 if (relatedDefinition.isUnique()) {
 511  0
                                         uniqueAttributeIds.add(qualifier.getKimAttrDefnId()); // it's unique - add it to the Set
 512  
                                 }
 513  0
                         }
 514  
                     }
 515  
             }
 516  
 
 517  0
             return uniqueAttributeIds;
 518  
     }
 519  
 
 520  
     /**
 521  
      * Checks all the qualifiers for the given membership, so that all qualifiers which should be unique are guaranteed to be unique
 522  
      *
 523  
      * @param delegationMembershipToCheck the membership to check
 524  
      * @param membershipToCheckIndex the index of the person's membership in the role (for error reporting purposes)
 525  
      * @param validationErrors Map<String, String> of errors to report
 526  
      * @return true if all unique values are indeed unique, false otherwise
 527  
      */
 528  
     protected boolean validateUniquePersonRoleQualifiersUniqueForRoleDelegation(RoleDocumentDelegationMember delegationMembershipToCheck, int membershipToCheckIndex, List<RoleDocumentDelegationMember> delegationMemberships, Set<String> uniqueQualifierIds, List<RemotableAttributeError> validationErrors) {
 529  0
             boolean foundError = false;
 530  0
             int count = 0;
 531  
 
 532  0
             for (RoleDocumentDelegationMember delegationMembership : delegationMemberships) {
 533  0
                     if (membershipToCheckIndex != count) {
 534  0
                             if (sameDelegationMembership(delegationMembershipToCheck, delegationMembership)) {
 535  0
                                     if (sameUniqueDelegationMembershipQualifications(delegationMembershipToCheck, delegationMembership, uniqueQualifierIds)) {
 536  0
                                             foundError = true;
 537  
                                             // add error to each qualifier which is supposed to be unique
 538  0
                                             int qualifierCount = 0;
 539  
 
 540  0
                                             for (RoleDocumentDelegationMemberQualifier qualifier : delegationMembership.getQualifiers()) {
 541  0
                                                     if (qualifier != null && uniqueQualifierIds.contains(qualifier.getKimAttrDefnId())) {
 542  0
                                                             validationErrors.add(RemotableAttributeError.Builder.create("document.delegationMembers["+membershipToCheckIndex+"].qualifiers["+qualifierCount+"].attrVal", RiceKeyConstants.ERROR_DOCUMENT_IDENTITY_MANAGEMENT_PERSON_QUALIFIER_VALUE_NOT_UNIQUE+":"+qualifier.getKimAttribute().getAttributeName()+";"+qualifier.getAttrVal()).build());
 543  
                                                     }
 544  0
                                                     qualifierCount += 1;
 545  
                                             }
 546  
                                     }
 547  
                             }
 548  
                     }
 549  0
                     count += 1;
 550  
             }
 551  
 
 552  0
             return foundError;
 553  
     }
 554  
 
 555  
     /**
 556  
      * Determines if two memberships represent the same member being added: that is, the two memberships have the same type code and id
 557  
      *
 558  
      * @param membershipA the first membership to check
 559  
      * @param membershipB the second membership to check
 560  
      * @return true if the two memberships represent the same member; false if they do not, or if it could not be profitably determined if the members were the same
 561  
      */
 562  
     protected boolean sameDelegationMembership(RoleDocumentDelegationMember membershipA, RoleDocumentDelegationMember membershipB) {
 563  0
             if (!StringUtils.isBlank(membershipA.getMemberTypeCode()) && !StringUtils.isBlank(membershipB.getMemberTypeCode()) && !StringUtils.isBlank(membershipA.getMemberId()) && !StringUtils.isBlank(membershipB.getMemberId())) {
 564  0
                     return membershipA.getMemberTypeCode().equals(membershipB.getMemberTypeCode()) && membershipA.getMemberId().equals(membershipB.getMemberId());
 565  
             }
 566  0
             return false;
 567  
     }
 568  
 
 569  
     /**
 570  
      * Given two memberships which represent the same member, do they share qualifications?
 571  
      *
 572  
      * @param membershipA the first membership to check
 573  
      * @param membershipB the second membership to check
 574  
      * @param uniqueAttributeIds the Set of attribute definition ids which should be unique
 575  
      * @return
 576  
      */
 577  
     protected boolean sameUniqueDelegationMembershipQualifications(RoleDocumentDelegationMember membershipA, RoleDocumentDelegationMember membershipB, Set<String> uniqueAttributeIds) {
 578  0
             boolean equalSoFar = true;
 579  0
             for (String kimAttributeDefinitionId : uniqueAttributeIds) {
 580  0
                     final RoleDocumentDelegationMemberQualifier qualifierA = membershipA.getQualifier(kimAttributeDefinitionId);
 581  0
                     final RoleDocumentDelegationMemberQualifier qualifierB = membershipB.getQualifier(kimAttributeDefinitionId);
 582  
 
 583  0
                     if (qualifierA != null && qualifierB != null) {
 584  0
                             equalSoFar &= (qualifierA.getAttrVal() == null && qualifierB.getAttrVal() == null) || (qualifierA.getAttrVal() == null || qualifierA.getAttrVal().equals(qualifierB.getAttrVal()));
 585  
                     }
 586  0
             }
 587  0
             return equalSoFar;
 588  
     }
 589  
 
 590  
         protected boolean validateActiveDate(String errorPath, Timestamp activeFromDate, Timestamp activeToDate) {
 591  
                 // TODO : do not have detail bus rule yet, so just check this for now.
 592  0
                 boolean valid = true;
 593  0
                 if (activeFromDate != null && activeToDate !=null && activeToDate.before(activeFromDate)) {
 594  0
                 MessageMap errorMap = GlobalVariables.getMessageMap();
 595  0
             errorMap.putError(errorPath, RiceKeyConstants.ERROR_ACTIVE_TO_DATE_BEFORE_FROM_DATE);
 596  0
             valid = false;
 597  
 
 598  
                 }
 599  0
                 return valid;
 600  
         }
 601  
 
 602  
         /**
 603  
          *
 604  
          * This method checks to see if adding a role to role membership
 605  
          * creates a circular reference.
 606  
          *
 607  
          * @param addMemberEvent
 608  
          * @return true  - ok to assign, no circular references
 609  
          *         false - do not make assignment, will create circular reference.
 610  
          */
 611  
         protected boolean checkForCircularRoleMembership(AddMemberEvent addMemberEvent)
 612  
         {
 613  0
                 KimDocumentRoleMember newMember = addMemberEvent.getMember();
 614  0
                 if (newMember == null || StringUtils.isBlank(newMember.getMemberId())){
 615  0
                         MessageMap errorMap = GlobalVariables.getMessageMap();
 616  0
                         errorMap.putError("member.memberId", RiceKeyConstants.ERROR_INVALID_ROLE, new String[] {""});
 617  0
                         return false;
 618  
                 }
 619  0
                 Set<String> roleMemberIds = null;
 620  
                 // if the role member is a role, check to make sure we won't be creating a circular reference.
 621  
                 // Verify that the new role is not already related to the role either directly or indirectly
 622  0
                 if (newMember.isRole()){
 623  
                         // get all nested role member ids that are of type role
 624  0
                         RoleService roleService = KimApiServiceLocator.getRoleService();
 625  0
                         roleMemberIds = roleService.getRoleTypeRoleMemberIds(newMember.getMemberId());
 626  
 
 627  
                         // check to see if the document role is not a member of the new member role
 628  0
                         IdentityManagementRoleDocument document = (IdentityManagementRoleDocument)addMemberEvent.getDocument();
 629  0
                         if (roleMemberIds.contains(document.getRoleId())){
 630  0
                                 MessageMap errorMap = GlobalVariables.getMessageMap();
 631  0
                                 errorMap.putError("member.memberId", RiceKeyConstants.ERROR_ASSIGN_ROLE_MEMBER_CIRCULAR, new String[] {newMember.getMemberId()});
 632  0
                                 return false;
 633  
                         }
 634  
                 }
 635  0
                 return true;
 636  
         }
 637  
 
 638  
         /**
 639  
          * @return the addResponsibilityRule
 640  
          */
 641  
         public AddResponsibilityRule getAddResponsibilityRule() {
 642  0
                 if(addResponsibilityRule == null){
 643  
                         try {
 644  0
                                 addResponsibilityRule = addResponsibilityRuleClass.newInstance();
 645  0
                         } catch ( Exception ex ) {
 646  0
                                 throw new RuntimeException( "Unable to create AddResponsibilityRule instance using class: " + addResponsibilityRuleClass, ex );
 647  0
                         }
 648  
                 }
 649  0
                 return addResponsibilityRule;
 650  
         }
 651  
 
 652  
         /**
 653  
          * @return the addPermissionRule
 654  
          */
 655  
         public AddPermissionRule getAddPermissionRule() {
 656  0
                 if(addPermissionRule == null){
 657  
                         try {
 658  0
                                 addPermissionRule = addPermissionRuleClass.newInstance();
 659  0
                         } catch ( Exception ex ) {
 660  0
                                 throw new RuntimeException( "Unable to create AddPermissionRule instance using class: " + addPermissionRuleClass, ex );
 661  0
                         }
 662  
                 }
 663  0
                 return addPermissionRule;
 664  
         }
 665  
 
 666  
         /**
 667  
          * @return the addMemberRule
 668  
          */
 669  
         public AddMemberRule getAddMemberRule() {
 670  0
                 if(addMemberRule == null){
 671  
                         try {
 672  0
                                 addMemberRule = addMemberRuleClass.newInstance();
 673  0
                         } catch ( Exception ex ) {
 674  0
                                 throw new RuntimeException( "Unable to create AddMemberRule instance using class: " + addMemberRuleClass, ex );
 675  0
                         }
 676  
                 }
 677  0
                 return addMemberRule;
 678  
         }
 679  
 
 680  
         /**
 681  
          * @return the addDelegationRule
 682  
          */
 683  
         public AddDelegationRule getAddDelegationRule() {
 684  0
                 if(addDelegationRule == null){
 685  
                         try {
 686  0
                                 addDelegationRule = addDelegationRuleClass.newInstance();
 687  0
                         } catch ( Exception ex ) {
 688  0
                                 throw new RuntimeException( "Unable to create AddDelegationRule instance using class: " + addDelegationRuleClass, ex );
 689  0
                         }
 690  
                 }
 691  0
                 return addDelegationRule;
 692  
         }
 693  
 
 694  
         /**
 695  
          * @return the addDelegationMemberRule
 696  
          */
 697  
         public AddDelegationMemberRule getAddDelegationMemberRule() {
 698  0
                 if(addDelegationMemberRule == null){
 699  
                         try {
 700  0
                                 addDelegationMemberRule = addDelegationMemberRuleClass.newInstance();
 701  0
                         } catch ( Exception ex ) {
 702  0
                                 throw new RuntimeException( "Unable to create AddDelegationMemberRule instance using class: " + addDelegationMemberRuleClass, ex );
 703  0
                         }
 704  
                 }
 705  0
                 return addDelegationMemberRule;
 706  
         }
 707  
 
 708  
     public boolean processAddPermission(AddPermissionEvent addPermissionEvent) {
 709  0
         return getAddPermissionRule().processAddPermission(addPermissionEvent);
 710  
     }
 711  
 
 712  
     public boolean hasPermissionToGrantPermission(Permission kimPermissionInfo , IdentityManagementRoleDocument document){
 713  0
         return getAddPermissionRule().hasPermissionToGrantPermission(kimPermissionInfo, document);
 714  
     }
 715  
 
 716  
     public boolean processAddResponsibility(AddResponsibilityEvent addResponsibilityEvent) {
 717  0
         return getAddResponsibilityRule().processAddResponsibility(addResponsibilityEvent);
 718  
     }
 719  
 
 720  
     public boolean hasPermissionToGrantResponsibility(Responsibility kimResponsibilityInfo, IdentityManagementRoleDocument document) {
 721  0
         return getAddResponsibilityRule().hasPermissionToGrantResponsibility(kimResponsibilityInfo, document);
 722  
     }
 723  
 
 724  
     public boolean processAddMember(AddMemberEvent addMemberEvent) {
 725  0
         boolean success = new KimDocumentMemberRule().processAddMember(addMemberEvent);
 726  0
         success &= validateActiveDate("member.activeFromDate", addMemberEvent.getMember().getActiveFromDate(), addMemberEvent.getMember().getActiveToDate());
 727  0
         success &= checkForCircularRoleMembership(addMemberEvent);
 728  0
         return success;
 729  
     }
 730  
 
 731  
     public boolean processAddDelegation(AddDelegationEvent addDelegationEvent) {
 732  0
         return getAddDelegationRule().processAddDelegation(addDelegationEvent);
 733  
     }
 734  
 
 735  
     public boolean processAddDelegationMember(AddDelegationMemberEvent addDelegationMemberEvent) {
 736  0
         boolean success = new RoleDocumentDelegationMemberRule().processAddDelegationMember(addDelegationMemberEvent);
 737  0
         RoleDocumentDelegationMember roleDocumentDelegationMember = addDelegationMemberEvent.getDelegationMember();
 738  0
         success &= validateActiveDate("delegationMember.activeFromDate", roleDocumentDelegationMember.getActiveFromDate(), roleDocumentDelegationMember.getActiveToDate());
 739  0
         return success;
 740  
     }
 741  
 
 742  
         public ResponsibilityService getResponsibilityService() {
 743  0
                 if(responsibilityService == null){
 744  0
                         responsibilityService = KimApiServiceLocator.getResponsibilityService();
 745  
                 }
 746  0
                 return responsibilityService;
 747  
         }
 748  
 
 749  
     public ResponsibilityInternalService getResponsibilityInternalService() {
 750  0
             if ( responsibilityInternalService == null ) {
 751  0
                     responsibilityInternalService = KimImplServiceLocator.getResponsibilityInternalService();
 752  
             }
 753  0
                 return responsibilityInternalService;
 754  
         }
 755  
 
 756  
 
 757  
         /**
 758  
          * @return the businessObjectService
 759  
          */
 760  
         public BusinessObjectService getBusinessObjectService() {
 761  0
                 if(businessObjectService == null){
 762  0
                         businessObjectService = KRADServiceLocator.getBusinessObjectService();
 763  
                 }
 764  0
                 return businessObjectService;
 765  
         }
 766  
 }