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.kew.actiontaken.service.impl;
017
018import org.kuali.rice.core.api.criteria.CountFlag;
019import org.kuali.rice.core.api.criteria.OrderByField;
020import org.kuali.rice.core.api.criteria.OrderDirection;
021import org.kuali.rice.core.api.criteria.QueryByCriteria;
022import org.kuali.rice.kew.actionrequest.ActionRequestValue;
023import org.kuali.rice.kew.actiontaken.ActionTakenValue;
024import org.kuali.rice.kew.actiontaken.dao.ActionTakenDao;
025import org.kuali.rice.kew.actiontaken.service.ActionTakenService;
026import org.kuali.rice.kew.api.action.ActionType;
027import org.kuali.rice.kim.api.group.GroupService;
028import org.kuali.rice.kim.api.services.KimApiServiceLocator;
029import org.kuali.rice.krad.data.DataObjectService;
030
031import java.sql.Timestamp;
032import java.util.ArrayList;
033import java.util.Collection;
034import java.util.List;
035
036import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
037
038/**
039 * Default implementation of the {@link ActionTakenService}.
040 *
041 * @author Kuali Rice Team (rice.collab@kuali.org)
042 */
043public class ActionTakenServiceImpl implements ActionTakenService {
044
045    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ActionTakenServiceImpl.class);
046
047    private static final String DOCUMENT_ID = "documentId";
048    private static final String PRINCIPAL_ID = "principalId";
049    private static final String CURRENT_INDICATOR = "currentIndicator";
050    private static final String ACTION_DATE = "actionDate";
051
052    private DataObjectService dataObjectService;
053    private ActionTakenDao actionTakenDao;
054
055    @Override
056    public ActionTakenValue findByActionTakenId(String actionTakenId) {
057        return getDataObjectService().find(ActionTakenValue.class, actionTakenId);
058    }
059
060    @Override
061    public ActionTakenValue getPreviousAction(ActionRequestValue actionRequest) {
062        return getPreviousAction(actionRequest, null);
063    }
064
065    @Override
066    public ActionTakenValue getPreviousAction(ActionRequestValue actionRequest, List<ActionTakenValue> simulatedActionsTaken) {
067        GroupService ims = KimApiServiceLocator.getGroupService();
068        ActionTakenValue foundActionTaken = null;
069        List<String> principalIds = new ArrayList<String>();
070        if (actionRequest.isGroupRequest()) {
071            principalIds.addAll( ims.getMemberPrincipalIds(actionRequest.getGroup().getId()));
072        } else if (actionRequest.isUserRequest()) {
073            principalIds.add(actionRequest.getPrincipalId());
074        }
075
076        for (String id : principalIds) {
077            List<ActionTakenValue> actionsTakenByUser =
078                new ArrayList<ActionTakenValue>(findByDocumentIdPrincipalId(actionRequest.getDocumentId(), id));
079            if (simulatedActionsTaken != null) {
080                for (ActionTakenValue simulatedAction : simulatedActionsTaken) {
081                    if (id.equals(simulatedAction.getPrincipalId())) {
082                        actionsTakenByUser.add(simulatedAction);
083                    }
084                }
085            }
086
087            for (ActionTakenValue actionTaken : actionsTakenByUser) {
088                if (ActionRequestValue.compareActionCode(actionTaken.getActionTaken(),
089                        actionRequest.getActionRequested(), true) >= 0) {
090                  foundActionTaken = actionTaken;
091                }
092            }
093        }
094
095        return foundActionTaken;
096    }
097
098    @Override
099    public Collection<ActionTakenValue> findByDocumentId(String documentId) {
100        LOG.debug("finding Action Takens by documentId " + documentId);
101        QueryByCriteria.Builder criteria = QueryByCriteria.Builder.create().setPredicates(equal(DOCUMENT_ID,
102                documentId), equal(CURRENT_INDICATOR, Boolean.TRUE));
103        criteria.setOrderByFields(OrderByField.Builder.create(ACTION_DATE, OrderDirection.ASCENDING).build());
104        return getDataObjectService().findMatching(ActionTakenValue.class, criteria.build()).getResults();
105    }
106
107    @Override
108    public List<ActionTakenValue> findByDocumentIdPrincipalId(String documentId, String principalId) {
109        LOG.debug("finding Action Takens by documentId " + documentId + " and principalId" + principalId);
110        QueryByCriteria.Builder criteria = QueryByCriteria.Builder.create().setPredicates(equal(DOCUMENT_ID,
111                documentId), equal(PRINCIPAL_ID, principalId), equal(CURRENT_INDICATOR, Boolean.TRUE));
112        return getDataObjectService().findMatching(ActionTakenValue.class, criteria.build()).getResults();
113    }
114
115    @Override
116    public List<ActionTakenValue> findByDocumentIdIgnoreCurrentInd(String documentId) {
117        LOG.debug("finding ActionsTaken ignoring currentInd by documentId:" + documentId);
118        QueryByCriteria.Builder criteria = QueryByCriteria.Builder.create().setPredicates(equal(DOCUMENT_ID,
119                documentId));
120        criteria.setOrderByFields(OrderByField.Builder.create(ACTION_DATE, OrderDirection.ASCENDING).build());
121        return getDataObjectService().findMatching(ActionTakenValue.class, criteria.build()).getResults();
122    }
123
124    @Override
125    public ActionTakenValue saveActionTaken(ActionTakenValue actionTaken) {
126        LOG.debug("saving ActionTaken");
127        checkNull(actionTaken.getDocumentId(), "Document ID");
128        checkNull(actionTaken.getActionTaken(), "action taken code");
129        checkNull(actionTaken.getDocVersion(), "doc version");
130        checkNull(actionTaken.getPrincipal(), "user principalId");
131
132        if (actionTaken.getActionDate() == null) {
133            actionTaken.setActionDate(new Timestamp(System.currentTimeMillis()));
134        }
135        if (actionTaken.getCurrentIndicator() == null) {
136            actionTaken.setCurrentIndicator(Boolean.TRUE);
137        }
138        LOG.debug("saving ActionTaken: routeHeader " + actionTaken.getDocumentId() +
139                ", actionTaken " + actionTaken.getActionTaken() + ", principalId " + actionTaken.getPrincipalId());
140        return getDataObjectService().save(actionTaken);
141    }
142
143    @Override
144    public void delete(ActionTakenValue actionTaken) {
145        LOG.debug("deleting ActionTaken " + actionTaken.getActionTakenId());
146        getDataObjectService().delete(actionTaken);
147    }
148
149    @Override
150    public boolean hasUserTakenAction(String principalId, String documentId) {
151        QueryByCriteria.Builder criteria = QueryByCriteria.Builder.create().setPredicates(
152                equal(DOCUMENT_ID, documentId),
153                equal(PRINCIPAL_ID, principalId),
154                equal(CURRENT_INDICATOR, Boolean.TRUE)
155        );
156        criteria.setCountFlag(CountFlag.ONLY);
157        return getDataObjectService().findMatching(ActionTakenValue.class, criteria.build()).getTotalRowCount() > 0;
158    }
159
160
161    @Override
162    public Timestamp getLastApprovedDate(String documentId)
163    {
164        return getActionTakenDao().getLastActionTakenDate(documentId, ActionType.APPROVE);
165    }
166
167    private void checkNull(Object value, String valueName) throws RuntimeException {
168        if (value == null) {
169            throw new IllegalArgumentException("Null value for " + valueName);
170        }
171    }
172
173
174    public ActionTakenDao getActionTakenDao() {
175        return actionTakenDao;
176    }
177
178    public void setActionTakenDao(ActionTakenDao actionTakenDao) {
179        this.actionTakenDao = actionTakenDao;
180    }
181
182
183    public DataObjectService getDataObjectService() {
184        return dataObjectService;
185    }
186
187    public void setDataObjectService(DataObjectService dataObjectService) {
188        this.dataObjectService = dataObjectService;
189    }
190}