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