001/*
002 * Copyright 2010 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community License, Version 1.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/ecl1.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 */
016package org.kuali.ole.coa.service.impl;
017
018import java.util.ArrayList;
019import java.util.Collections;
020import java.util.HashMap;
021import java.util.HashSet;
022import java.util.List;
023import java.util.Map;
024import java.util.Set;
025
026import org.apache.commons.lang.StringUtils;
027import org.joda.time.DateTime;
028import org.kuali.ole.coa.identity.OleKimDocDelegateMember;
029import org.kuali.ole.coa.identity.OleKimDocRoleMember;
030import org.kuali.ole.coa.identity.OleKimDocumentAttributeData;
031import org.kuali.ole.coa.identity.OrgReviewRole;
032import org.kuali.ole.coa.service.OrgReviewRoleService;
033import org.kuali.ole.sys.OLEConstants;
034import org.kuali.ole.sys.identity.OleKimAttributes;
035import org.kuali.rice.core.api.criteria.PredicateUtils;
036import org.kuali.rice.core.api.criteria.QueryByCriteria;
037import org.kuali.rice.core.api.delegation.DelegationType;
038import org.kuali.rice.core.api.membership.MemberType;
039import org.kuali.rice.kew.api.KewApiServiceLocator;
040import org.kuali.rice.kew.api.doctype.DocumentTypeService;
041import org.kuali.rice.kim.api.KimConstants;
042import org.kuali.rice.kim.api.common.attribute.KimAttribute;
043import org.kuali.rice.kim.api.common.delegate.DelegateMember;
044import org.kuali.rice.kim.api.common.delegate.DelegateType;
045import org.kuali.rice.kim.api.group.Group;
046import org.kuali.rice.kim.api.identity.principal.Principal;
047import org.kuali.rice.kim.api.role.Role;
048import org.kuali.rice.kim.api.role.RoleMember;
049import org.kuali.rice.kim.api.role.RoleMemberContract;
050import org.kuali.rice.kim.api.role.RoleMemberQueryResults;
051import org.kuali.rice.kim.api.role.RoleResponsibilityAction;
052import org.kuali.rice.kim.api.role.RoleService;
053import org.kuali.rice.kim.api.services.KimApiServiceLocator;
054import org.kuali.rice.kim.api.type.KimType;
055import org.kuali.rice.kim.api.type.KimTypeAttribute;
056import org.kuali.rice.kim.util.KimCommonUtils;
057import org.kuali.rice.krad.exception.ValidationException;
058import org.kuali.rice.krad.util.GlobalVariables;
059import org.springframework.cache.annotation.Cacheable;
060
061public class OrgReviewRoleServiceImpl implements OrgReviewRoleService {
062    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OrgReviewRoleServiceImpl.class);
063
064    // note: this assumes that all use the OLE-SYS namespace
065    protected static final Map<String,Role> ROLE_CACHE = new HashMap<String, Role>();
066    protected static final Map<String,Map<String,KimAttribute>> ATTRIBUTE_CACHE = new HashMap<String, Map<String,KimAttribute>>();
067
068    protected Set<String> potentialParentDocumentTypeNames = new HashSet<String>();
069    {
070        potentialParentDocumentTypeNames.add(OLEConstants.COAConstants.FINANCIAL_SYSTEM_TRANSACTIONAL_DOCUMENT);
071        potentialParentDocumentTypeNames.add(OLEConstants.COAConstants.FINANCIAL_SYSTEM_COMPLEX_MAINTENANCE_DOCUMENT);
072        potentialParentDocumentTypeNames.add(OLEConstants.COAConstants.FINANCIAL_SYSTEM_SIMPLE_MAINTENANCE_DOCUMENT);
073        potentialParentDocumentTypeNames = Collections.unmodifiableSet(potentialParentDocumentTypeNames);
074    }
075    protected DocumentTypeService documentTypeService;
076
077    @Override
078    public RoleMember getRoleMemberFromKimRoleService( String roleMemberId ) {
079        if ( StringUtils.isEmpty(roleMemberId) ) {
080            throw new IllegalArgumentException( "Role member ID may not be blank." );
081        }
082        RoleMemberQueryResults roleMembers = KimApiServiceLocator.getRoleService().findRoleMembers(QueryByCriteria.Builder.fromPredicates( PredicateUtils.convertMapToPredicate(Collections.singletonMap(KimConstants.PrimaryKeyConstants.ID, roleMemberId))));
083        if ( roleMembers == null || roleMembers.getResults() == null || roleMembers.getResults().isEmpty() ) {
084            throw new IllegalArgumentException( "Unknown role member ID passed in - nothing returned from KIM RoleService: " + roleMemberId );
085        }
086        return roleMembers.getResults().get(0);
087    }
088
089    @Override
090    public void populateOrgReviewRoleFromRoleMember(OrgReviewRole orr, String roleMemberId) {
091        if ( StringUtils.isBlank(roleMemberId) ) {
092            throw new IllegalArgumentException( "Role member ID may not be blank" );
093        }
094        RoleMember roleMember = getRoleMemberFromKimRoleService(roleMemberId);
095        orr.setRoleMember(roleMember);
096
097        populateObjectExtras(orr);
098    }
099
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}