View Javadoc
1   /*
2    * Copyright 2010 The Kuali Foundation.
3    *
4    * Licensed under the Educational Community License, Version 1.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/ecl1.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.ole.coa.service.impl;
17  
18  import java.util.ArrayList;
19  import java.util.Collections;
20  import java.util.HashMap;
21  import java.util.HashSet;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Set;
25  
26  import org.apache.commons.lang.StringUtils;
27  import org.joda.time.DateTime;
28  import org.kuali.ole.coa.identity.OleKimDocDelegateMember;
29  import org.kuali.ole.coa.identity.OleKimDocRoleMember;
30  import org.kuali.ole.coa.identity.OleKimDocumentAttributeData;
31  import org.kuali.ole.coa.identity.OrgReviewRole;
32  import org.kuali.ole.coa.service.OrgReviewRoleService;
33  import org.kuali.ole.sys.OLEConstants;
34  import org.kuali.ole.sys.identity.OleKimAttributes;
35  import org.kuali.rice.core.api.criteria.PredicateUtils;
36  import org.kuali.rice.core.api.criteria.QueryByCriteria;
37  import org.kuali.rice.core.api.delegation.DelegationType;
38  import org.kuali.rice.core.api.membership.MemberType;
39  import org.kuali.rice.kew.api.KewApiServiceLocator;
40  import org.kuali.rice.kew.api.doctype.DocumentTypeService;
41  import org.kuali.rice.kim.api.KimConstants;
42  import org.kuali.rice.kim.api.common.attribute.KimAttribute;
43  import org.kuali.rice.kim.api.common.delegate.DelegateMember;
44  import org.kuali.rice.kim.api.common.delegate.DelegateType;
45  import org.kuali.rice.kim.api.group.Group;
46  import org.kuali.rice.kim.api.identity.principal.Principal;
47  import org.kuali.rice.kim.api.role.Role;
48  import org.kuali.rice.kim.api.role.RoleMember;
49  import org.kuali.rice.kim.api.role.RoleMemberContract;
50  import org.kuali.rice.kim.api.role.RoleMemberQueryResults;
51  import org.kuali.rice.kim.api.role.RoleResponsibilityAction;
52  import org.kuali.rice.kim.api.role.RoleService;
53  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
54  import org.kuali.rice.kim.api.type.KimType;
55  import org.kuali.rice.kim.api.type.KimTypeAttribute;
56  import org.kuali.rice.kim.util.KimCommonUtils;
57  import org.kuali.rice.krad.exception.ValidationException;
58  import org.kuali.rice.krad.util.GlobalVariables;
59  import org.springframework.cache.annotation.Cacheable;
60  
61  public class OrgReviewRoleServiceImpl implements OrgReviewRoleService {
62      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OrgReviewRoleServiceImpl.class);
63  
64      // note: this assumes that all use the OLE-SYS namespace
65      protected static final Map<String,Role> ROLE_CACHE = new HashMap<String, Role>();
66      protected static final Map<String,Map<String,KimAttribute>> ATTRIBUTE_CACHE = new HashMap<String, Map<String,KimAttribute>>();
67  
68      protected Set<String> potentialParentDocumentTypeNames = new HashSet<String>();
69      {
70          potentialParentDocumentTypeNames.add(OLEConstants.COAConstants.FINANCIAL_SYSTEM_TRANSACTIONAL_DOCUMENT);
71          potentialParentDocumentTypeNames.add(OLEConstants.COAConstants.FINANCIAL_SYSTEM_COMPLEX_MAINTENANCE_DOCUMENT);
72          potentialParentDocumentTypeNames.add(OLEConstants.COAConstants.FINANCIAL_SYSTEM_SIMPLE_MAINTENANCE_DOCUMENT);
73          potentialParentDocumentTypeNames = Collections.unmodifiableSet(potentialParentDocumentTypeNames);
74      }
75      protected DocumentTypeService documentTypeService;
76  
77      @Override
78      public RoleMember getRoleMemberFromKimRoleService( String roleMemberId ) {
79          if ( StringUtils.isEmpty(roleMemberId) ) {
80              throw new IllegalArgumentException( "Role member ID may not be blank." );
81          }
82          RoleMemberQueryResults roleMembers = KimApiServiceLocator.getRoleService().findRoleMembers(QueryByCriteria.Builder.fromPredicates( PredicateUtils.convertMapToPredicate(Collections.singletonMap(KimConstants.PrimaryKeyConstants.ID, roleMemberId))));
83          if ( roleMembers == null || roleMembers.getResults() == null || roleMembers.getResults().isEmpty() ) {
84              throw new IllegalArgumentException( "Unknown role member ID passed in - nothing returned from KIM RoleService: " + roleMemberId );
85          }
86          return roleMembers.getResults().get(0);
87      }
88  
89      @Override
90      public void populateOrgReviewRoleFromRoleMember(OrgReviewRole orr, String roleMemberId) {
91          if ( StringUtils.isBlank(roleMemberId) ) {
92              throw new IllegalArgumentException( "Role member ID may not be blank" );
93          }
94          RoleMember roleMember = getRoleMemberFromKimRoleService(roleMemberId);
95          orr.setRoleMember(roleMember);
96  
97          populateObjectExtras(orr);
98      }
99  
100     @Override
101     public void populateOrgReviewRoleFromDelegationMember(OrgReviewRole orr, String roleMemberId, String delegationMemberId) {
102         RoleMember roleMember = null;
103         if ( StringUtils.isNotBlank(roleMemberId) ) {
104             roleMember = getRoleMemberFromKimRoleService(roleMemberId);
105         }
106         RoleService roleService = KimApiServiceLocator.getRoleService();
107         DelegateMember delegationMember = roleService.getDelegationMemberById(delegationMemberId);
108         DelegateType delegation = roleService.getDelegateTypeByDelegationId(delegationMember.getDelegationId());
109 
110         orr.setDelegationTypeCode(delegation.getDelegationType().getCode());
111         //orr.setRoleMember(roleMember);
112         orr.setDelegateMember(roleMember,delegationMember);
113 
114         orr.setRoleRspActions(roleService.getRoleMemberResponsibilityActions(delegationMember.getRoleMemberId()));
115 
116         populateObjectExtras(orr);
117     }
118 
119     protected void populateObjectExtras( OrgReviewRole orr ) {
120         if( !orr.getRoleRspActions().isEmpty() ){
121             orr.setActionTypeCode(orr.getRoleRspActions().get(0).getActionTypeCode());
122             orr.setPriorityNumber(orr.getRoleRspActions().get(0).getPriorityNumber()==null?"":String.valueOf(orr.getRoleRspActions().get(0).getPriorityNumber()));
123             orr.setActionPolicyCode(orr.getRoleRspActions().get(0).getActionPolicyCode());
124             orr.setForceAction(orr.getRoleRspActions().get(0).isForceAction());
125         }
126     }
127 
128     @Override
129     @Cacheable(value=OrgReviewRole.CACHE_NAME,key="'{ValidDocumentTypeForOrgReview}'+#p0")
130     public boolean isValidDocumentTypeForOrgReview(String documentTypeName){
131         if(StringUtils.isEmpty(documentTypeName)){
132             return false;
133         }
134 
135         return !getRolesToConsider(documentTypeName).isEmpty();
136     }
137 
138     @Override
139     public void validateDocumentType(String documentTypeName) throws ValidationException {
140         if ( getRolesToConsider(documentTypeName).isEmpty() ) {
141             GlobalVariables.getMessageMap().putError(OrgReviewRole.DOC_TYPE_NAME_FIELD_NAME, "error.document.orgReview.invalidDocumentType", documentTypeName);
142         }
143     }
144 
145     @Override
146     @Cacheable(value=OrgReviewRole.CACHE_NAME,key="'{hasOrganizationHierarchy}'+#p0")
147     public boolean hasOrganizationHierarchy(String documentTypeName) {
148         if(StringUtils.isBlank(documentTypeName)) {
149             return false;
150         }
151         return getDocumentTypeService().hasRouteNodeForDocumentTypeName(OLEConstants.RouteLevelNames.ORGANIZATION_HIERARCHY, documentTypeName);
152     }
153 
154     @Override
155     @Cacheable(value=OrgReviewRole.CACHE_NAME,key="'{hasAccountingOrganizationHierarchy}'+#p0")
156     public boolean hasAccountingOrganizationHierarchy(String documentTypeName) {
157         if(StringUtils.isBlank(documentTypeName)) {
158             return false;
159         }
160         return getDocumentTypeService().hasRouteNodeForDocumentTypeName(OLEConstants.RouteLevelNames.ACCOUNTING_ORGANIZATION_HIERARCHY, documentTypeName);
161     }
162 
163     @Override
164     @Cacheable(value=OrgReviewRole.CACHE_NAME,key="'{ClosestOrgReviewRoleParentDocumentTypeName}'+#p0")
165     public String getClosestOrgReviewRoleParentDocumentTypeName(final String documentTypeName){
166         if(StringUtils.isBlank(documentTypeName)) {
167             return null;
168         }
169         return KimCommonUtils.getClosestParentDocumentTypeName(getDocumentTypeService().getDocumentTypeByName(documentTypeName), potentialParentDocumentTypeNames);
170     }
171 
172     /**
173      *  1. Check WorkflowInfo.hasNode(documentTypeName, nodeName) to see if the document type selected has
174      *  OrganizationHierarchy and/or AccountingOrganizationHierarchy - if it has either or both,
175      *  set the Review Types radio group appropriately and make it read only.
176      *  2. Else, if OLE is the document type selected, set the Review Types radio group to both and leave it editable.
177      *  3. Else, if FinancialSystemTransactionalDocument is the closest parent (per KimCommonUtils.getClosestParent),
178      *  set the Review Types radio group to Organization Accounting Only and leave it editable.
179      *  4. Else, if FinancialSystemComplexMaintenanceDocument is the closest parent (per KimCommonUtils.getClosestParent),
180      *  set the Review Types radio group to Organization Only and make read-only.
181      *  5. Else, if FinancialSystemSimpleMaintenanceDocument is the closest parent (per KimCommonUtils.getClosestParent),
182      *  this makes no sense and should generate an error.
183      * @param documentTypeName
184      * @param hasOrganizationHierarchy
185      * @param hasAccountingOrganizationHierarchy
186      * @param closestParentDocumentTypeName
187      * @return
188      */
189     @Override
190     @Cacheable(value=OrgReviewRole.CACHE_NAME,key="'{getRolesToConsider}'+#p0")
191     public List<String> getRolesToConsider(String documentTypeName) throws ValidationException {
192         List<String> rolesToConsider = new ArrayList<String>(2);
193         if(StringUtils.isBlank(documentTypeName) || OLEConstants.ROOT_DOCUMENT_TYPE.equals(documentTypeName) ){
194             rolesToConsider.add(OLEConstants.SysKimApiConstants.ORGANIZATION_REVIEWER_ROLE_NAME);
195             rolesToConsider.add(OLEConstants.SysKimApiConstants.ACCOUNTING_REVIEWER_ROLE_NAME);
196         } else {
197             String closestParentDocumentTypeName = getClosestOrgReviewRoleParentDocumentTypeName(documentTypeName);
198             if(documentTypeName.equals(OLEConstants.COAConstants.FINANCIAL_SYSTEM_TRANSACTIONAL_DOCUMENT)
199                     || OLEConstants.COAConstants.FINANCIAL_SYSTEM_TRANSACTIONAL_DOCUMENT.equals(closestParentDocumentTypeName)) {
200                 rolesToConsider.add(OLEConstants.SysKimApiConstants.ACCOUNTING_REVIEWER_ROLE_NAME);
201             } else {
202                 boolean hasOrganizationHierarchy = hasOrganizationHierarchy(documentTypeName);
203                 boolean hasAccountingOrganizationHierarchy = hasAccountingOrganizationHierarchy(documentTypeName);
204                 if(hasOrganizationHierarchy || documentTypeName.equals(OLEConstants.COAConstants.FINANCIAL_SYSTEM_COMPLEX_MAINTENANCE_DOCUMENT)
205                         || OLEConstants.COAConstants.FINANCIAL_SYSTEM_COMPLEX_MAINTENANCE_DOCUMENT.equals(closestParentDocumentTypeName) ) {
206                     rolesToConsider.add(OLEConstants.SysKimApiConstants.ORGANIZATION_REVIEWER_ROLE_NAME);
207                 }
208                 if(hasAccountingOrganizationHierarchy) {
209                     rolesToConsider.add(OLEConstants.SysKimApiConstants.ACCOUNTING_REVIEWER_ROLE_NAME);
210                 }
211             }
212         }
213         return rolesToConsider;
214     }
215 
216     @Override
217     public void saveOrgReviewRoleToKim( OrgReviewRole orr ) {
218         if(orr.isDelegate() || orr.isCreateDelegation()){
219             saveDelegateMemberToKim(orr);
220         } else{
221             saveRoleMemberToKim(orr);
222         }
223     }
224 
225     protected void updateDelegateMemberFromDocDelegateMember( DelegateMember.Builder member, OleKimDocDelegateMember dm ) {
226         member.setMemberId(dm.getMemberId());
227         member.setType(dm.getType());
228         member.setRoleMemberId(dm.getRoleMemberId());
229         member.setAttributes(dm.getAttributes());
230         member.setActiveFromDate(dm.getActiveFromDate());
231         member.setActiveToDate(dm.getActiveToDate());
232     }
233 
234     protected void saveDelegateMemberToKim( OrgReviewRole orr ) {
235         if ( LOG.isDebugEnabled() ) {
236             LOG.debug( "Saving delegate member from OrgReviewRole: " + orr );
237         }
238         RoleService roleService = KimApiServiceLocator.getRoleService();
239         // Save delegation(s)
240         List<OleKimDocDelegateMember> delegationMembers = getDelegationMembersToSave(orr);
241 
242         for( OleKimDocDelegateMember dm : delegationMembers ) {
243             // retrieve the delegate type so it can be updated
244             DelegationType delegationType = dm.getDelegationType();
245             DelegateType delegateType = roleService.getDelegateTypeByRoleIdAndDelegateTypeCode(orr.getRoleId(), delegationType);
246             // KIM always returns a non-null value even if it has never been persisted
247             if ( delegateType == null || delegateType.getDelegationId() == null ) {
248                 DelegateType.Builder newDelegateType = DelegateType.Builder.create(orr.getRoleId(), delegationType, new ArrayList<DelegateMember.Builder>(1));
249                 // ensure this is set (for new delegation types)
250                 newDelegateType.setKimTypeId( orr.getKimTypeId());
251                 delegateType = roleService.createDelegateType(newDelegateType.build());
252                 if ( LOG.isDebugEnabled() ) {
253                     LOG.debug("No DelegateType in KIM.  Created new one: " + delegateType);
254                 }
255             } else {
256                 if ( LOG.isDebugEnabled() ) {
257                     LOG.debug("Pulled DelegateType from KIM: " + delegateType);
258                 }
259             }
260 
261             boolean foundExistingMember = false;
262             DelegateMember addedMember = null;
263 
264             // check for an existing delegation member given its unique ID
265             // if found, update that record
266             if ( StringUtils.isNotBlank(dm.getDelegationMemberId()) ) {
267                 DelegateMember member = roleService.getDelegationMemberById(dm.getDelegationMemberId());
268                 if ( member != null ) {
269                     foundExistingMember = true;
270                     if ( LOG.isDebugEnabled() ) {
271                         LOG.debug("Found existing delegate member - updating existing record. " + member);
272                     }
273                     DelegateMember.Builder updatedMember = DelegateMember.Builder.create(member);
274                     // OLEMI-9628 : fixing issue with the delegate switch from primary to secondary
275                     // IN this case, we need to delete the member from the "other" delegate type
276 
277                     // need to determine what the "existing" type was
278                     DelegateType originalDelegateType = roleService.getDelegateTypeByDelegationId(member.getDelegationId());
279                     // if they are the same, we can just update the existing record
280                     if ( originalDelegateType.getDelegationType().equals(dm.getDelegationType()) ) {
281                         updateDelegateMemberFromDocDelegateMember(updatedMember, dm);
282                         addedMember = roleService.updateDelegateMember(updatedMember.build());
283                     } else {
284                         // Otherwise, we need to remove the old one and add a new one
285                         // Remove old
286                         roleService.removeDelegateMembers(Collections.singletonList(member));
287                         // add new
288                         DelegateMember.Builder newMember = DelegateMember.Builder.create();
289                         newMember.setDelegationId(delegateType.getDelegationId());
290                         updateDelegateMemberFromDocDelegateMember(newMember, dm);
291                         addedMember = roleService.createDelegateMember(newMember.build());
292                     }
293                 }
294             }
295             // if we did not find one, then we need to create a new member
296             if ( !foundExistingMember ) {
297                 if ( LOG.isDebugEnabled() ) {
298                     LOG.debug("No existing delegate member found, adding as a new delegate: " + dm);
299                 }
300                 DelegateMember.Builder newMember = DelegateMember.Builder.create();
301                 newMember.setDelegationId(delegateType.getDelegationId());
302                 updateDelegateMemberFromDocDelegateMember(newMember, dm);
303                 addedMember = roleService.createDelegateMember(newMember.build());
304             }
305 
306             if ( addedMember != null ) {
307                 orr.setDelegationMemberId(addedMember.getDelegationMemberId());
308             }
309         }
310     }
311 
312     protected void saveRoleMemberToKim( OrgReviewRole orr ) {
313         if ( LOG.isDebugEnabled() ) {
314             LOG.debug( "Saving role member from OrgReviewRole: " + orr );
315         }
316         RoleService roleService = KimApiServiceLocator.getRoleService();
317         // Save role member(s)
318         for( RoleMemberContract roleMember : getRoleMembers(orr) ) {
319             List<RoleResponsibilityAction.Builder> roleRspActionsToSave = getRoleResponsibilityActions(orr, roleMember);
320             RoleMemberQueryResults roleMembers = roleService.findRoleMembers(QueryByCriteria.Builder.fromPredicates( PredicateUtils.convertMapToPredicate(Collections.singletonMap(KimConstants.PrimaryKeyConstants.ID, roleMember.getId()))));
321             if ( orr.isEdit() && roleMembers != null && roleMembers.getResults() != null && !roleMembers.getResults().isEmpty() ) {
322                 RoleMember existingRoleMember = roleMembers.getResults().get(0);
323                 RoleMember.Builder updatedRoleMember = RoleMember.Builder.create(roleMember);
324                 updatedRoleMember.setVersionNumber(existingRoleMember.getVersionNumber());
325                 updatedRoleMember.setObjectId(existingRoleMember.getObjectId());
326                 roleMember = roleService.updateRoleMember( updatedRoleMember.build() );
327             } else {
328                 RoleMember.Builder newRoleMember = RoleMember.Builder.create(roleMember);
329                 roleMember = roleService.createRoleMember( newRoleMember.build() );
330             }
331             for ( RoleResponsibilityAction.Builder rra : roleRspActionsToSave ) {
332                 // ensure linked to the right record
333                 rra.setRoleMemberId(roleMember.getId());
334                 if ( StringUtils.isBlank( rra.getId() ) ) {
335                     roleService.createRoleResponsibilityAction(rra.build());
336                 } else {
337                     roleService.updateRoleResponsibilityAction(rra.build());
338                 }
339             }
340             orr.setRoleMemberId(roleMember.getId());
341             orr.setORMId(roleMember.getId());
342         }
343     }
344 
345     protected Role getRoleInfo( String roleName ) {
346         if ( roleName == null ) {
347             return null;
348         }
349         Role role = ROLE_CACHE.get(roleName);
350         if ( role == null ) {
351             role = KimApiServiceLocator.getRoleService().getRoleByNamespaceCodeAndName( OLEConstants.SysKimApiConstants.ORGANIZATION_REVIEWER_ROLE_NAMESPACECODE, roleName);
352             synchronized ( ROLE_CACHE ) {
353                 ROLE_CACHE.put(roleName, role);
354             }
355         }
356         return role;
357     }
358 
359     protected List<OleKimDocDelegateMember> getDelegationMembersToSave(OrgReviewRole orr){
360         OleKimDocDelegateMember delegationMember = null;
361         if(orr.isEdit() && StringUtils.isNotBlank(orr.getDelegationMemberId())){
362             delegationMember = new OleKimDocDelegateMember( KimApiServiceLocator.getRoleService().getDelegationMemberById(orr.getDelegationMemberId()) );
363         }
364 
365         if(delegationMember==null){
366             delegationMember = new OleKimDocDelegateMember();
367             if(StringUtils.isNotEmpty(orr.getRoleMemberRoleNamespaceCode()) && StringUtils.isNotEmpty(orr.getRoleMemberRoleName())){
368                 String roleId = KimApiServiceLocator.getRoleService().getRoleIdByNamespaceCodeAndName(orr.getRoleMemberRoleNamespaceCode(), orr.getRoleMemberRoleName());
369                 delegationMember.setMemberId(roleId);
370                 delegationMember.setType(MemberType.ROLE);
371             } else if(StringUtils.isNotEmpty(orr.getGroupMemberGroupNamespaceCode()) && StringUtils.isNotEmpty(orr.getGroupMemberGroupName())){
372                 Group groupInfo = KimApiServiceLocator.getGroupService().getGroupByNamespaceCodeAndName(orr.getGroupMemberGroupNamespaceCode(), orr.getGroupMemberGroupName());
373                 delegationMember.setMemberId(groupInfo.getId());
374                 delegationMember.setType(MemberType.GROUP);
375             } else if(StringUtils.isNotEmpty(orr.getPrincipalMemberPrincipalName())){
376                 Principal principal = KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(orr.getPrincipalMemberPrincipalName());
377                 delegationMember.setMemberId(principal.getPrincipalId());
378                 delegationMember.setType(MemberType.PRINCIPAL);
379             }
380         }
381         delegationMember.setDelegationType(DelegationType.fromCode( orr.getDelegationTypeCode() ));
382         delegationMember.setAttributes(getAttributes(orr, orr.getKimTypeId()));
383         if ( orr.getActiveFromDate() != null ) {
384             delegationMember.setActiveFromDate( new DateTime( orr.getActiveFromDate() ) );
385         }
386         if ( orr.getActiveToDate() != null ) {
387             delegationMember.setActiveToDate( new DateTime( orr.getActiveToDate() ) );
388         }
389         delegationMember.setRoleMemberId(orr.getRoleMemberId());
390         return Collections.singletonList(delegationMember);
391     }
392 
393     protected OleKimDocRoleMember getRoleMemberToSave(Role role, OrgReviewRole orr){
394         OleKimDocRoleMember roleMember = null;
395         if ( orr.getPerson() != null ) {
396             roleMember = new OleKimDocRoleMember(role.getId(), MemberType.PRINCIPAL, orr.getPerson().getPrincipalId());
397         } else if ( orr.getGroup() != null ) {
398             roleMember = new OleKimDocRoleMember(role.getId(), MemberType.GROUP, orr.getGroup().getId() );
399         } else if( orr.getRole() != null ){
400             roleMember = new OleKimDocRoleMember(role.getId(), MemberType.ROLE, orr.getRole().getId() );
401         }
402         if ( roleMember != null ) {
403             if(orr.isEdit()){
404                 roleMember.setId(orr.getRoleMemberId());
405             }
406             roleMember.setAttributes(getAttributes(orr, role.getKimTypeId()));
407             if ( orr.getActiveFromDate() != null ) {
408                 roleMember.setActiveFromDate( new DateTime( orr.getActiveFromDate().getTime() ) );
409             }
410             if ( orr.getActiveToDate() != null ) {
411                 roleMember.setActiveToDate( new DateTime( orr.getActiveToDate().getTime() ) );
412             }
413         }
414         return roleMember;
415     }
416 
417     protected List<String> getRolesToSaveFor(List<String> roleNamesToConsider, String reviewRolesIndicator){
418         if(roleNamesToConsider!=null){
419             List<String> roleToSaveFor = new ArrayList<String>();
420             if(OLEConstants.COAConstants.ORG_REVIEW_ROLE_ORG_ACC_ONLY_CODE.equals(reviewRolesIndicator)){
421                 roleToSaveFor.add(OLEConstants.SysKimApiConstants.ACCOUNTING_REVIEWER_ROLE_NAME);
422             } else if(OLEConstants.COAConstants.ORG_REVIEW_ROLE_ORG_ONLY_CODE.equals(reviewRolesIndicator)){
423                 roleToSaveFor.add(OLEConstants.SysKimApiConstants.ORGANIZATION_REVIEWER_ROLE_NAME);
424             } else{
425                 roleToSaveFor.addAll(roleNamesToConsider);
426             }
427             return roleToSaveFor;
428         } else {
429             return Collections.emptyList();
430         }
431     }
432 
433     protected List<OleKimDocRoleMember> getRoleMembers(OrgReviewRole orr){
434         List<OleKimDocRoleMember> objectsToSave = new ArrayList<OleKimDocRoleMember>();
435         List<String> roleNamesToSaveFor = getRolesToSaveFor(orr.getRoleNamesToConsider(), orr.getReviewRolesIndicator());
436         for(String roleName: roleNamesToSaveFor){
437             Role roleInfo = getRoleInfo(roleName);
438             OleKimDocRoleMember roleMemberToSave = getRoleMemberToSave(roleInfo, orr);
439             if ( roleMemberToSave != null ) {
440                 objectsToSave.add(roleMemberToSave);
441             }
442         }
443         return objectsToSave;
444     }
445 
446     protected Map<String,String> getAttributes(OrgReviewRole orr, String kimTypeId){
447         if( StringUtils.isBlank(kimTypeId) ) {
448             return Collections.emptyMap();
449         }
450 
451         List<OleKimDocumentAttributeData> attributeDataList = new ArrayList<OleKimDocumentAttributeData>();
452         OleKimDocumentAttributeData attributeData = getAttribute(kimTypeId, OleKimAttributes.CHART_OF_ACCOUNTS_CODE, orr.getChartOfAccountsCode());
453         if ( attributeData != null ) {
454             attributeDataList.add(attributeData);
455         }
456 
457         attributeData = getAttribute(kimTypeId, OleKimAttributes.ORGANIZATION_CODE, orr.getOrganizationCode());
458         if ( attributeData != null ) {
459             attributeDataList.add(attributeData);
460         }
461 
462         attributeData = getAttribute(kimTypeId, KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, orr.getFinancialSystemDocumentTypeCode());
463         if ( attributeData != null ) {
464             attributeDataList.add(attributeData);
465         }
466 
467         attributeData = getAttribute(kimTypeId, OleKimAttributes.ACCOUNTING_LINE_OVERRIDE_CODE, orr.getOverrideCode());
468         if ( attributeData != null ) {
469             attributeDataList.add(attributeData);
470         }
471 
472         attributeData = getAttribute(kimTypeId, OleKimAttributes.FROM_AMOUNT, orr.getFromAmountStr());
473         if ( attributeData != null ) {
474             attributeDataList.add(attributeData);
475         }
476 
477         attributeData = getAttribute(kimTypeId, OleKimAttributes.TO_AMOUNT, orr.getToAmountStr());
478         if ( attributeData != null ) {
479             attributeDataList.add(attributeData);
480         }
481 
482         return orr.getQualifierAsAttributeSet(attributeDataList);
483     }
484 
485 // JHK: Commented out as it is not needed at the moment.  If we decide that we need to link these to the
486 // exact responsibilities in the future, I didn't want anyone to have to re-invent the wheel.
487 //    protected List<RoleResponsibility> getResponsibilitiesWithRoleMemberLevelActions( String roleId ) {
488 //        List<RoleResponsibility> roleResponsibilities = KimApiServiceLocator.getRoleService().getRoleResponsibilities(roleId);
489 //        //Assuming that there is only 1 responsibility for both the org review roles
490 //        if ( roleResponsibilities == null || roleResponsibilities.isEmpty() ) {
491 //            throw new IllegalStateException("The Org Review Role id: " + roleId + " does not have any responsibilities associated with it");
492 //        }
493 //        List<RoleResponsibility> respWithRoleMemberActions = new ArrayList<RoleResponsibility>( roleResponsibilities.size() );
494 //        for ( RoleResponsibility rr : roleResponsibilities ) {
495 //            Responsibility r = KimApiServiceLocator.getResponsibilityService().getResponsibility(rr.getResponsibilityId());
496 //            if ( Boolean.parseBoolean( r.getAttributes().get(KimConstants.AttributeConstants.ACTION_DETAILS_AT_ROLE_MEMBER_LEVEL) ) ) {
497 //                respWithRoleMemberActions.add(rr);
498 //            }
499 //        }
500 //        return respWithRoleMemberActions;
501 //    }
502 
503     protected List<RoleResponsibilityAction.Builder> getRoleResponsibilityActions(OrgReviewRole orr, RoleMemberContract roleMember){
504         List<RoleResponsibilityAction.Builder> roleResponsibilityActions = new ArrayList<RoleResponsibilityAction.Builder>(1);
505 
506         RoleResponsibilityAction.Builder rra = RoleResponsibilityAction.Builder.create();
507         // if this is an existing role member, pull matching role resp action record (and set ID in object) so it can be updated
508         // otherwise, it will be left blank and a new one will be created
509         if ( StringUtils.isNotBlank( roleMember.getId() ) ) {
510             List<RoleResponsibilityAction> origRoleRspActions = KimApiServiceLocator.getRoleService().getRoleMemberResponsibilityActions(roleMember.getId());
511             if ( origRoleRspActions!=null && !origRoleRspActions.isEmpty() ) {
512                 rra.setId(origRoleRspActions.get(0).getId());
513                 rra.setVersionNumber(origRoleRspActions.get(0).getVersionNumber());
514             }
515         }
516 
517         rra.setRoleMemberId(roleMember.getId());
518         rra.setRoleResponsibilityId("*");
519         rra.setActionTypeCode(orr.getActionTypeCode());
520         rra.setActionPolicyCode(orr.getActionPolicyCode());
521 
522         if(StringUtils.isNotBlank(orr.getPriorityNumber())){
523             try{
524                 rra.setPriorityNumber(Integer.valueOf(orr.getPriorityNumber()));
525             } catch(Exception nfx){
526                 rra.setPriorityNumber(null);
527             }
528         }
529         rra.setForceAction(orr.isForceAction());
530         roleResponsibilityActions.add(rra);
531         return roleResponsibilityActions;
532     }
533 
534     protected OleKimDocumentAttributeData getAttribute( String kimTypeId, String attributeName, String attributeValue ) {
535         if ( StringUtils.isNotBlank(attributeValue) ) {
536             KimAttribute attribute = getAttributeDefinition(kimTypeId, attributeName);
537             if( attribute != null ){
538                 OleKimDocumentAttributeData attributeData = new OleKimDocumentAttributeData();
539                 attributeData.setKimTypId(kimTypeId);
540                 attributeData.setAttrVal(attributeValue);
541                 attributeData.setKimAttrDefnId(attribute.getId());
542                 attributeData.setKimAttribute(attribute);
543                 return attributeData;
544             }
545         }
546         return null;
547     }
548 
549     protected KimAttribute getAttributeDefinition( String kimTypeId, String attributeName ) {
550         // attempt to pull from cache
551         Map<String,KimAttribute> typeAttributes = ATTRIBUTE_CACHE.get(kimTypeId);
552         // if type has not been loaded, init
553         if ( typeAttributes == null ) {
554             KimType kimType = KimApiServiceLocator.getKimTypeInfoService().getKimType(kimTypeId);
555             if ( kimType != null ) {
556                 List<KimTypeAttribute> attributes = kimType.getAttributeDefinitions();
557                 typeAttributes = new HashMap<String, KimAttribute>();
558                 if ( attributes != null ) {
559                     // build the map and put it into the cache
560                     for ( KimTypeAttribute att : attributes ) {
561                         typeAttributes.put( att.getKimAttribute().getAttributeName(), att.getKimAttribute() );
562                     }
563                 }
564                 synchronized ( ATTRIBUTE_CACHE ) {
565                     ATTRIBUTE_CACHE.put(kimTypeId, typeAttributes);
566                 }
567             }
568         }
569         // now, see if the attribute is in there
570         if ( typeAttributes != null ) {
571             return typeAttributes.get(attributeName);
572         }
573         return null;
574     }
575 
576 
577     protected DocumentTypeService getDocumentTypeService() {
578         if ( documentTypeService == null ) {
579             documentTypeService = KewApiServiceLocator.getDocumentTypeService();
580         }
581         return documentTypeService;
582     }
583 
584 }