001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.kim.impl.responsibility;
017
018import org.apache.commons.lang.StringUtils;
019import org.apache.commons.lang.exception.ExceptionUtils;
020import org.apache.commons.logging.Log;
021import org.apache.commons.logging.LogFactory;
022import org.kuali.rice.core.api.criteria.Predicate;
023import org.kuali.rice.core.api.criteria.QueryByCriteria;
024import org.kuali.rice.core.api.criteria.QueryResults;
025import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
026import org.kuali.rice.core.api.exception.RiceIllegalStateException;
027import org.kuali.rice.core.api.membership.MemberType;
028import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
029import org.kuali.rice.kim.api.common.delegate.DelegateType;
030import org.kuali.rice.kim.api.common.template.Template;
031import org.kuali.rice.kim.api.common.template.TemplateQueryResults;
032import org.kuali.rice.kim.api.responsibility.Responsibility;
033import org.kuali.rice.kim.api.responsibility.ResponsibilityAction;
034import org.kuali.rice.kim.api.responsibility.ResponsibilityQueryResults;
035import org.kuali.rice.kim.api.responsibility.ResponsibilityService;
036import org.kuali.rice.kim.api.role.RoleMembership;
037import org.kuali.rice.kim.api.role.RoleResponsibilityAction;
038import org.kuali.rice.kim.api.role.RoleService;
039import org.kuali.rice.kim.api.type.KimType;
040import org.kuali.rice.kim.api.type.KimTypeInfoService;
041import org.kuali.rice.kim.framework.responsibility.ResponsibilityTypeService;
042import org.kuali.rice.kim.impl.KIMPropertyConstants;
043import org.kuali.rice.kim.impl.common.attribute.AttributeTransform;
044import org.kuali.rice.kim.impl.common.attribute.KimAttributeDataBo;
045import org.kuali.rice.kim.impl.role.RoleResponsibilityActionBo;
046import org.kuali.rice.kim.impl.role.RoleResponsibilityBo;
047import org.kuali.rice.krad.data.DataObjectService;
048import org.springframework.util.CollectionUtils;
049
050import javax.xml.namespace.QName;
051import java.util.ArrayList;
052import java.util.Collection;
053import java.util.Collections;
054import java.util.HashMap;
055import java.util.Iterator;
056import java.util.List;
057import java.util.Map;
058
059import static org.kuali.rice.core.api.criteria.PredicateFactory.and;
060import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
061import static org.kuali.rice.core.api.criteria.PredicateFactory.in;
062import static org.kuali.rice.core.api.criteria.PredicateFactory.or;
063
064public class ResponsibilityServiceImpl implements ResponsibilityService {
065
066    private static final Integer DEFAULT_PRIORITY_NUMBER = Integer.valueOf(1);
067    private static final Log LOG = LogFactory.getLog(ResponsibilityServiceImpl.class);
068
069    private ResponsibilityTypeService defaultResponsibilityTypeService;
070    private KimTypeInfoService kimTypeInfoService;
071    private RoleService roleService;
072    private ResponsibilityDao responsibilityDao;
073
074    private DataObjectService dataObjectService;
075
076    @Override
077    public Responsibility createResponsibility(final Responsibility responsibility)
078            throws RiceIllegalArgumentException, RiceIllegalStateException {
079        incomingParamCheck(responsibility, "responsibility");
080
081        if (StringUtils.isNotBlank(responsibility.getId()) && getResponsibility(responsibility.getId()) != null) {
082            throw new RiceIllegalStateException("the responsibility to create already exists: " + responsibility);
083        }
084        List<ResponsibilityAttributeBo> attrBos = Collections.emptyList();
085        if (responsibility.getTemplate() != null) {
086            attrBos = KimAttributeDataBo.createFrom(ResponsibilityAttributeBo.class, responsibility.getAttributes(), responsibility.getTemplate().getKimTypeId());
087        }
088        ResponsibilityBo bo = ResponsibilityBo.from(responsibility);
089        bo.setAttributeDetails(attrBos);
090        return ResponsibilityBo.to(getDataObjectService().save(bo));
091    }
092
093    @Override
094    public Responsibility updateResponsibility(final Responsibility responsibility)
095            throws RiceIllegalArgumentException, RiceIllegalStateException {
096        incomingParamCheck(responsibility, "responsibility");
097
098        if (StringUtils.isBlank(responsibility.getId()) || getResponsibility(responsibility.getId()) == null) {
099            throw new RiceIllegalStateException("the responsibility does not exist: " + responsibility);
100        }
101
102       List<ResponsibilityAttributeBo> attrBos = Collections.emptyList();
103        if (responsibility.getTemplate() != null) {
104            attrBos = KimAttributeDataBo.createFrom(ResponsibilityAttributeBo.class, responsibility.getAttributes(), responsibility.getTemplate().getKimTypeId());
105        }
106        ResponsibilityBo bo = ResponsibilityBo.from(responsibility);
107
108        if (bo.getAttributeDetails() != null) {
109            bo.getAttributeDetails().clear();
110            bo.setAttributeDetails(attrBos);
111        }
112
113        return ResponsibilityBo.to(getDataObjectService().save(bo));
114    }
115
116    @Override
117    public Responsibility getResponsibility(final String id) throws RiceIllegalArgumentException {
118        incomingParamCheck(id, "id");
119
120        return ResponsibilityBo.to(getDataObjectService().find(ResponsibilityBo.class, id));
121    }
122
123    @Override
124    public Responsibility findRespByNamespaceCodeAndName(final String namespaceCode, final String name)
125            throws RiceIllegalArgumentException {
126        incomingParamCheck(namespaceCode, "namespaceCode");
127        incomingParamCheck(name, "name");
128
129        final Map<String, Object> criteria = new HashMap<String, Object>();
130        criteria.put("namespaceCode", namespaceCode);
131        criteria.put("name", name);
132        criteria.put("active", Boolean.TRUE);
133
134        QueryResults<ResponsibilityBo> bos =
135                getDataObjectService().findMatching(ResponsibilityBo.class,
136                        QueryByCriteria.Builder.andAttributes(criteria).build());
137
138        if (bos != null && bos.getResults() != null) {
139            if (bos.getResults().size() > 1) {
140                throw new RiceIllegalStateException("more than one Responsibility found with namespace code: " + namespaceCode + " and name: " + name);
141            }
142
143            final Iterator<ResponsibilityBo> i = bos.getResults().iterator();
144            return i.hasNext() ? ResponsibilityBo.to(i.next()) : null;
145        }
146        return null;
147    }
148
149    @Override
150    public Template getResponsibilityTemplate(final String id) throws RiceIllegalArgumentException {
151        incomingParamCheck(id, "id");
152
153        return ResponsibilityTemplateBo.to(getDataObjectService().find(ResponsibilityTemplateBo.class, id));
154    }
155
156    @Override
157    public Template findRespTemplateByNamespaceCodeAndName(final String namespaceCode, final String name) throws RiceIllegalArgumentException {
158        incomingParamCheck(namespaceCode, "namespaceCode");
159        incomingParamCheck(name, "name");
160
161        final Map<String, Object> criteria = new HashMap<String, Object>();
162        criteria.put("namespaceCode", namespaceCode);
163        criteria.put("name", name);
164        criteria.put("active", Boolean.TRUE);
165
166        QueryResults<ResponsibilityTemplateBo> bos =
167                getDataObjectService().findMatching(ResponsibilityTemplateBo.class,
168                        QueryByCriteria.Builder.andAttributes(criteria).build());
169        if (bos != null && bos.getResults() != null) {
170            if (bos.getResults().size() > 1) {
171                throw new RiceIllegalStateException("more than one Responsibility Template found with namespace code: " + namespaceCode + " and name: " + name);
172            }
173
174            final Iterator<ResponsibilityTemplateBo> i = bos.getResults().iterator();
175            return i.hasNext() ? ResponsibilityTemplateBo.to(i.next()) : null;
176        }
177        return null;
178    }
179
180    @Override
181    public boolean hasResponsibility(final String principalId, final String namespaceCode,
182            final String respName, final Map<String, String> qualification) throws RiceIllegalArgumentException {
183        incomingParamCheck(principalId, "principalId");
184        incomingParamCheck(namespaceCode, "namespaceCode");
185        incomingParamCheck(respName, "respName");
186        incomingParamCheck(qualification, "qualification");
187
188        // get all the responsibility objects whose name match that requested
189        final List<Responsibility> responsibilities = Collections.singletonList(findRespByNamespaceCodeAndName(namespaceCode, respName));
190        return hasResp(principalId, namespaceCode, responsibilities, qualification, null);
191    }
192
193    @Override
194    public boolean hasResponsibilityByTemplate(final String principalId, final String namespaceCode,
195            final String respTemplateName, final Map<String, String> qualification,
196            final Map<String, String> responsibilityDetails) throws RiceIllegalArgumentException {
197        incomingParamCheck(principalId, "principalId");
198        incomingParamCheck(namespaceCode, "namespaceCode");
199        incomingParamCheck(respTemplateName, "respTemplateName");
200        incomingParamCheck(qualification, "qualification");
201        incomingParamCheck(responsibilityDetails, "responsibilityDetails");
202
203
204        // get all the responsibility objects whose name match that requested
205        final List<Responsibility> responsibilities = findResponsibilitiesByTemplate(namespaceCode, respTemplateName);
206        return hasResp(principalId, namespaceCode, responsibilities, qualification, responsibilityDetails);
207    }
208
209    private boolean hasResp(final String principalId, final String namespaceCode,
210            final List<Responsibility> responsibilities,
211            final Map<String, String> qualification,
212            final Map<String, String> responsibilityDetails) throws RiceIllegalArgumentException {
213        // now, filter the full list by the detail passed
214        final List<String> ids = new ArrayList<String>();
215        for (Responsibility r : getMatchingResponsibilities(responsibilities, responsibilityDetails)) {
216            ids.add(r.getId());
217        }
218        final List<String> roleIds = getRoleIdsForResponsibilities(ids);
219        return roleService.principalHasRole(principalId, roleIds, qualification);
220    }
221
222    @Override
223    public List<ResponsibilityAction> getResponsibilityActions(final String namespaceCode,
224            final String responsibilityName, final Map<String, String> qualification) throws RiceIllegalArgumentException {
225        incomingParamCheck(namespaceCode, "namespaceCode");
226        incomingParamCheck(responsibilityName, "responsibilityName");
227        incomingParamCheck(qualification, "qualification");
228        
229        if ( LOG.isDebugEnabled() ) {
230            logResponsibilityCheck( namespaceCode, responsibilityName, qualification, Collections.<String, String>emptyMap() );
231        }
232
233        // get all the responsibility objects whose name match that requested
234        List<Responsibility> responsibilities = Collections.singletonList(findRespByNamespaceCodeAndName(namespaceCode, responsibilityName));
235        return getRespActions(namespaceCode, responsibilities, qualification, null);
236    }
237
238    @Override
239    public List<ResponsibilityAction> getResponsibilityActionsByTemplate(final String namespaceCode,
240            final String respTemplateName, final Map<String, String> qualification,
241            final Map<String, String> responsibilityDetails) throws RiceIllegalArgumentException {
242        incomingParamCheck(namespaceCode, "namespaceCode");
243        incomingParamCheck(respTemplateName, "respTemplateName");
244        incomingParamCheck(qualification, "qualification");
245        
246        if ( LOG.isDebugEnabled() ) {
247            logResponsibilityCheck( namespaceCode, respTemplateName, qualification, responsibilityDetails );
248        }
249
250        // get all the responsibility objects whose name match that requested
251        List<Responsibility> responsibilities = findResponsibilitiesByTemplate(namespaceCode, respTemplateName);
252        return getRespActions(namespaceCode, responsibilities, qualification, responsibilityDetails);
253    }
254
255    private List<ResponsibilityAction> getRespActions(final String namespaceCode,
256            final List<Responsibility> responsibilities,
257            final Map<String, String> qualification,
258            final Map<String, String> responsibilityDetails) {
259        // now, filter the full list by the detail passed
260        List<Responsibility> applicableResponsibilities = getMatchingResponsibilities(responsibilities, responsibilityDetails);
261        List<ResponsibilityAction> results = new ArrayList<ResponsibilityAction>();
262        for (Responsibility r : applicableResponsibilities) {
263            List<String> roleIds = getRoleIdsForResponsibility(r.getId());
264            results.addAll(getActionsForResponsibilityRoles(r, roleIds, qualification));
265        }
266        if ( LOG.isDebugEnabled() ) {
267            LOG.debug("Found " + results.size() + " matching ResponsibilityAction objects");
268            if ( LOG.isTraceEnabled() ) {
269                LOG.trace( results );
270            }
271        }
272        return results;
273    }
274
275    private List<ResponsibilityAction> getActionsForResponsibilityRoles(Responsibility responsibility, List<String> roleIds, Map<String, String> qualification) {
276        List<ResponsibilityAction> results = new ArrayList<ResponsibilityAction>();
277        Collection<RoleMembership> roleMembers = roleService.getRoleMembers(roleIds,qualification);
278        for (RoleMembership rm : roleMembers) {
279            // only add them to the list if the member ID has been populated
280            if (StringUtils.isNotBlank(rm.getMemberId())) {
281                List<RoleResponsibilityAction> roleResponsibilityActions
282                        = getResponsibilityActions(rm.getRoleId(), responsibility.getId(), rm.getId());
283                for (RoleResponsibilityAction roleResponsibilityAction : roleResponsibilityActions) {
284                    final ResponsibilityAction.Builder rai = ResponsibilityAction.Builder.create();
285                    rai.setMemberRoleId((rm.getEmbeddedRoleId() == null) ? rm.getRoleId() : rm.getEmbeddedRoleId());
286                    rai.setRoleId(rm.getRoleId());
287                    rai.setQualifier(rm.getQualifier());
288                    final List<DelegateType.Builder> bs = new ArrayList<DelegateType.Builder>();
289                    for (DelegateType d : rm.getDelegates()) {
290                        bs.add(DelegateType.Builder.create(d));
291                    }
292                    rai.setDelegates(bs);
293                    rai.setResponsibilityId(responsibility.getId());
294                    rai.setResponsibilityName(responsibility.getName());
295                    rai.setResponsibilityNamespaceCode(responsibility.getNamespaceCode());
296
297                    if (MemberType.PRINCIPAL.equals(rm.getType())) {
298                        rai.setPrincipalId(rm.getMemberId());
299                    } else {
300                        rai.setGroupId(rm.getMemberId());
301                    }
302                    // add the data to the ResponsibilityActionInfo objects
303                    rai.setActionTypeCode(roleResponsibilityAction.getActionTypeCode());
304                    rai.setActionPolicyCode(roleResponsibilityAction.getActionPolicyCode());
305                    rai.setPriorityNumber(roleResponsibilityAction.getPriorityNumber() == null ? DEFAULT_PRIORITY_NUMBER : roleResponsibilityAction.getPriorityNumber());
306                    rai.setForceAction(roleResponsibilityAction.isForceAction());
307                    rai.setParallelRoutingGroupingCode((rm.getRoleSortingCode() == null) ? "" : rm.getRoleSortingCode());
308                    rai.setRoleResponsibilityActionId(roleResponsibilityAction.getId());
309                    results.add(rai.build());
310                }
311            }
312        }
313        return Collections.unmodifiableList(results);
314    }
315
316    private List<RoleResponsibilityAction> getResponsibilityActions(String roleId, String responsibilityId, String roleMemberId) {
317        List<RoleResponsibilityAction> responsibilityActions = new ArrayList<RoleResponsibilityAction>();
318
319        // KULRICE-7459: Requisition, PO and its subtype documents are going to final status where they should not.
320        //
321        // need to do in 2 steps due to "*" wildcard convention in column data for role member id and role
322        // responsibility id.  Well, we could do in 1 step w/ straight SQL, but not w/ Criteria API due to the
323        // INNER JOIN automatically created between RoleResponsibility and RoleResponsibilityAction tables.
324
325        final Predicate roleResponsibilityPredicate =
326                and(
327                        equal("responsibilityId", responsibilityId),
328                        equal("roleId", roleId),
329                        equal("active", Boolean.TRUE)
330                );
331
332        // First get RoleResponsibilityBos
333        final QueryByCriteria.Builder roleResponsibilityQueryBuilder = QueryByCriteria.Builder.create();
334        roleResponsibilityQueryBuilder.setPredicates(roleResponsibilityPredicate);
335
336        final QueryResults<RoleResponsibilityBo> roleResponsibilityResults = getDataObjectService().
337                findMatching(RoleResponsibilityBo.class, roleResponsibilityQueryBuilder.build());
338        final List<RoleResponsibilityBo> roleResponsibilityBos = roleResponsibilityResults.getResults();
339
340        if (!CollectionUtils.isEmpty(roleResponsibilityBos)) { // if there are any...
341            // Then query RoleResponsibilityActionBos based on them
342
343            List<String> roleResponsibilityIds = new ArrayList<String>(roleResponsibilityBos.size());
344            for (RoleResponsibilityBo roleResponsibilityBo : roleResponsibilityBos) {
345                roleResponsibilityIds.add(roleResponsibilityBo.getRoleResponsibilityId());
346            }
347
348            final Predicate roleResponsibilityActionPredicate =
349                    or(
350                            and(
351                                    in("roleResponsibilityId", roleResponsibilityIds.toArray()),
352                                    or(
353                                            equal(KIMPropertyConstants.RoleMember.ROLE_MEMBER_ID, roleMemberId),
354                                            equal(KIMPropertyConstants.RoleMember.ROLE_MEMBER_ID, "*")
355                                    )
356                            ),
357                            and(
358                                    equal("roleResponsibilityId", "*"),
359                                    equal(KIMPropertyConstants.RoleMember.ROLE_MEMBER_ID, roleMemberId)
360                            )
361                    );
362
363            final QueryByCriteria.Builder roleResponsibilityActionQueryBuilder = QueryByCriteria.Builder.create();
364            roleResponsibilityActionQueryBuilder.setPredicates(roleResponsibilityActionPredicate);
365
366            final QueryResults<RoleResponsibilityActionBo> roleResponsibilityActionResults =
367                    getDataObjectService().findMatching(RoleResponsibilityActionBo.class,
368                            roleResponsibilityActionQueryBuilder.build());
369
370            final List<RoleResponsibilityActionBo> roleResponsibilityActionBos = roleResponsibilityActionResults.getResults();
371            for (RoleResponsibilityActionBo roleResponsibilityActionBo : roleResponsibilityActionBos) {
372                responsibilityActions.add(RoleResponsibilityActionBo.to(roleResponsibilityActionBo));
373            };
374        }
375
376        return Collections.unmodifiableList(responsibilityActions);
377    }
378
379    @Override
380    public List<String> getRoleIdsForResponsibility(String id) throws RiceIllegalArgumentException {
381        incomingParamCheck(id, "id");
382
383        final List<String> roleIds = getRoleIdsForPredicate(and(equal("responsibilityId", id), equal("active", Boolean.TRUE)));
384
385        return Collections.unmodifiableList(roleIds);
386    }
387
388    @Override
389    public ResponsibilityQueryResults findResponsibilities(final QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
390        incomingParamCheck(queryByCriteria, "queryByCriteria");
391
392        QueryResults<ResponsibilityBo> results = getDataObjectService().findMatching(ResponsibilityBo.class,
393                AttributeTransform.getInstance().apply(queryByCriteria));
394
395        ResponsibilityQueryResults.Builder builder = ResponsibilityQueryResults.Builder.create();
396        builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
397        builder.setTotalRowCount(results.getTotalRowCount());
398
399        final List<Responsibility.Builder> ims = new ArrayList<Responsibility.Builder>();
400        for (ResponsibilityBo bo : results.getResults()) {
401            ims.add(Responsibility.Builder.create(bo));
402        }
403
404        builder.setResults(ims);
405        return builder.build();
406    }
407
408    @Override
409    public TemplateQueryResults findResponsibilityTemplates(final QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
410        incomingParamCheck(queryByCriteria, "queryByCriteria");
411
412        QueryResults<ResponsibilityTemplateBo> results = getDataObjectService().
413                findMatching(ResponsibilityTemplateBo.class, queryByCriteria);
414
415        TemplateQueryResults.Builder builder = TemplateQueryResults.Builder.create();
416        builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
417        builder.setTotalRowCount(results.getTotalRowCount());
418
419        final List<Template.Builder> ims = new ArrayList<Template.Builder>();
420        for (ResponsibilityTemplateBo bo : results.getResults()) {
421            ims.add(Template.Builder.create(bo));
422        }
423
424        builder.setResults(ims);
425        return builder.build();
426    }
427
428    /**
429     * Compare each of the passed in responsibilities with the given responsibilityDetails.  Those that
430     * match are added to the result list.
431     */
432    private List<Responsibility> getMatchingResponsibilities(List<Responsibility> responsibilities, Map<String, String> responsibilityDetails) {
433        // if no details passed, assume that all match
434        if (responsibilityDetails == null || responsibilityDetails.isEmpty()) {
435            return responsibilities;
436        }
437
438        final List<Responsibility> applicableResponsibilities = new ArrayList<Responsibility>();
439        // otherwise, attempt to match the permission details
440        // build a map of the template IDs to the type services
441        Map<String, ResponsibilityTypeService> responsibilityTypeServices = getResponsibilityTypeServicesByTemplateId(responsibilities);
442        // build a map of permissions by template ID
443        Map<String, List<Responsibility>> responsibilityMap = groupResponsibilitiesByTemplate(responsibilities);
444        // loop over the different templates, matching all of the same template against the type
445        // service at once
446        for (Map.Entry<String, List<Responsibility>> respEntry : responsibilityMap.entrySet()) {
447            ResponsibilityTypeService responsibilityTypeService = responsibilityTypeServices.get(respEntry.getKey());
448            List<Responsibility> responsibilityInfos = respEntry.getValue();
449            if (responsibilityTypeService == null) {
450                responsibilityTypeService = defaultResponsibilityTypeService;
451            }
452            applicableResponsibilities.addAll(responsibilityTypeService.getMatchingResponsibilities(responsibilityDetails, responsibilityInfos));
453        }
454        return Collections.unmodifiableList(applicableResponsibilities);
455    }
456
457    private Map<String, ResponsibilityTypeService> getResponsibilityTypeServicesByTemplateId(Collection<Responsibility> responsibilities) {
458        Map<String, ResponsibilityTypeService> responsibilityTypeServices = new HashMap<String, ResponsibilityTypeService>(responsibilities.size());
459        for (Responsibility responsibility : responsibilities) {
460            final Template t = responsibility.getTemplate();
461            final KimType type = kimTypeInfoService.getKimType(t.getKimTypeId());
462
463            final String serviceName = type.getServiceName();
464            if (serviceName != null) {
465                ResponsibilityTypeService responsibiltyTypeService = GlobalResourceLoader.getService(QName.valueOf(serviceName));
466                if (responsibiltyTypeService != null) {
467                    responsibilityTypeServices.put(responsibility.getTemplate().getId(), responsibiltyTypeService);
468                } else {
469                    responsibilityTypeServices.put(responsibility.getTemplate().getId(), defaultResponsibilityTypeService);
470                }
471            }
472        }
473        return Collections.unmodifiableMap(responsibilityTypeServices);
474    }
475
476    private Map<String, List<Responsibility>> groupResponsibilitiesByTemplate(Collection<Responsibility> responsibilities) {
477        final Map<String, List<Responsibility>> results = new HashMap<String, List<Responsibility>>();
478        for (Responsibility responsibility : responsibilities) {
479            List<Responsibility> responsibilityInfos = results.get(responsibility.getTemplate().getId());
480            if (responsibilityInfos == null) {
481                responsibilityInfos = new ArrayList<Responsibility>();
482                results.put(responsibility.getTemplate().getId(), responsibilityInfos);
483            }
484            responsibilityInfos.add(responsibility);
485        }
486        return Collections.unmodifiableMap(results);
487    }
488
489    private List<String> getRoleIdsForResponsibilities(Collection<String> ids) {
490        final List<String> roleIds = getRoleIdsForPredicate(and(in("responsibilityId", ids.toArray()), equal("active", Boolean.TRUE)));
491
492        return Collections.unmodifiableList(roleIds);
493    }
494
495    private List<String> getRoleIdsForPredicate(Predicate p) {
496        QueryResults<RoleResponsibilityBo> qr =
497                getDataObjectService().findMatching(RoleResponsibilityBo.class,
498                        QueryByCriteria.Builder.fromPredicates(p));
499        final List<String> roleIds = new ArrayList<String>();
500        for (RoleResponsibilityBo bo : qr.getResults()) {
501            roleIds.add(bo.getRoleId());
502        }
503        return Collections.unmodifiableList(roleIds);
504    }
505
506
507    @Override
508    public List<Responsibility> findResponsibilitiesByTemplate(String namespaceCode, String templateName) {
509
510        final Map<String, Object> criteria = new HashMap<String, Object>();
511        criteria.put("template.namespaceCode", namespaceCode); 
512        criteria.put("template.name", templateName); 
513        criteria.put("active", Boolean.TRUE);
514
515        QueryResults<ResponsibilityBo> bos =
516                getDataObjectService().findMatching(ResponsibilityBo.class,
517                        QueryByCriteria.Builder.andAttributes(criteria).build());
518        final List<Responsibility> ims = new ArrayList<Responsibility>();
519        if (bos != null && bos.getResults() != null) {
520            for (ResponsibilityBo bo : bos.getResults()) {
521                if (bo != null) {
522                    ims.add(ResponsibilityBo.to(bo));
523                }
524            }
525        }
526
527        return Collections.unmodifiableList(ims);
528    }
529
530    @Override
531    public List<Responsibility> findWorkflowResponsibilities(String documentTypeName) {
532        incomingParamCheck(documentTypeName, "documentTypeName");
533        List<ResponsibilityBo> responsibilityBos = getResponsibilityDao().findWorkflowResponsibilities(documentTypeName);
534        List<Responsibility> responsibilities = new ArrayList<>();
535        for (ResponsibilityBo responsibilityBo : responsibilityBos) {
536            responsibilities.add(ResponsibilityBo.to(responsibilityBo));
537        }
538        return Collections.unmodifiableList(responsibilities);
539    }
540
541    @Override
542    public List<Responsibility> findWorkflowExceptionResponsibilities(String documentTypeName) {
543        incomingParamCheck(documentTypeName, "documentTypeName");
544        List<ResponsibilityBo> responsibilityBos = getResponsibilityDao().findWorkflowExceptionResponsibilities(documentTypeName);
545        List<Responsibility> responsibilities = new ArrayList<>();
546        for (ResponsibilityBo responsibilityBo : responsibilityBos) {
547            responsibilities.add(ResponsibilityBo.to(responsibilityBo));
548        }
549        return Collections.unmodifiableList(responsibilities);
550    }
551
552    public void setDefaultResponsibilityTypeService(final ResponsibilityTypeService defaultResponsibilityTypeService) {
553        this.defaultResponsibilityTypeService = defaultResponsibilityTypeService;
554    }
555
556    public void setKimTypeInfoService(final KimTypeInfoService kimTypeInfoService) {
557        this.kimTypeInfoService = kimTypeInfoService;
558    }
559
560    public void setRoleService(final RoleService roleService) {
561        this.roleService = roleService;
562    }
563
564    protected void logResponsibilityCheck(String namespaceCode, String responsibilityName, 
565                         Map<String, String> responsibilityDetails, Map<String, String> qualification ) {
566        StringBuilder sb = new StringBuilder();
567        sb.append(  '\n' );
568        sb.append( "Get Resp Actions: " ).append( namespaceCode ).append( "/" ).append( responsibilityName ).append( '\n' );
569        sb.append( "             Details:\n" );
570        if ( responsibilityDetails != null ) {
571            sb.append( responsibilityDetails );
572        } else {
573            sb.append( "                         [null]\n" );
574        }
575        sb.append( "             Qualifiers:\n" );
576        if ( qualification != null ) {
577            sb.append( qualification );
578        } else {
579            sb.append( "                         [null]\n" );
580        }
581        if (LOG.isTraceEnabled()) { 
582            LOG.trace( sb.append(ExceptionUtils.getStackTrace(new Throwable())));
583        } else {
584            LOG.debug(sb.toString());
585        }
586    }
587    
588    private void incomingParamCheck(Object object, String name) {
589        if (object == null) {
590            throw new RiceIllegalArgumentException(name + " was null");
591        } else if (object instanceof String
592                && StringUtils.isBlank((String) object)) {
593            throw new RiceIllegalArgumentException(name + " was blank");
594        }
595    }
596
597
598    public DataObjectService getDataObjectService() {
599        return dataObjectService;
600    }
601
602    public void setDataObjectService(DataObjectService dataObjectService) {
603        this.dataObjectService = dataObjectService;
604    }
605
606    public ResponsibilityDao getResponsibilityDao() {
607        return responsibilityDao;
608    }
609
610    public void setResponsibilityDao(ResponsibilityDao responsibilityDao) {
611        this.responsibilityDao = responsibilityDao;
612    }
613}