001/**
002 * Copyright 2005-2015 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.edl.impl.components;
017
018import org.apache.logging.log4j.Logger;
019import org.apache.logging.log4j.LogManager;
020import org.kuali.rice.core.api.util.xml.XmlJotter;
021import org.kuali.rice.edl.impl.EDLContext;
022import org.kuali.rice.edl.impl.EDLModelComponent;
023import org.kuali.rice.edl.impl.EDLXmlUtils;
024import org.kuali.rice.edl.impl.RequestParser;
025import org.kuali.rice.edl.impl.UserAction;
026import org.kuali.rice.kew.api.WorkflowDocument;
027import org.kuali.rice.kew.api.WorkflowDocumentFactory;
028import org.kuali.rice.kew.api.WorkflowRuntimeException;
029import org.kuali.rice.kew.api.document.DocumentStatus;
030import org.kuali.rice.kew.api.exception.WorkflowException;
031import org.w3c.dom.Document;
032import org.w3c.dom.Element;
033
034/**
035 * Used as a pre processor and post processor. As a pre processor this creates/fetches the workflow
036 * document and sets it on request. As a post processor this takes appropriate user action on the
037 * document if the document is not in error.
038 * 
039 * @author Kuali Rice Team (rice.collab@kuali.org)
040 * 
041 */
042public class WorkflowDocumentActions implements EDLModelComponent {
043
044    private static final Logger LOG = LogManager.getLogger(WorkflowDocumentActions.class);
045
046    public static final String ACTION_TAKEN = "actionTaken";
047
048    boolean isPreProcessor;
049
050    public void updateDOM(Document dom, Element configElement, EDLContext edlContext) {
051
052        try {
053            isPreProcessor = configElement.getTagName().equals("preProcessor");
054            if (isPreProcessor) {
055                doPreProcessWork(edlContext);
056            } else {
057                doPostProcessWork(dom, edlContext);
058            }
059        } catch (Exception e) {
060            throw new WorkflowRuntimeException(e);
061        }
062
063    }
064
065    private void doPreProcessWork(EDLContext edlContext) throws Exception {
066        RequestParser requestParser = edlContext.getRequestParser();
067
068        UserAction userAction = edlContext.getUserAction();
069        WorkflowDocument document = null;
070        if (UserAction.ACTION_CREATE.equals(userAction.getAction())) {
071            document = WorkflowDocumentFactory.createDocument(edlContext.getUserSession().getPrincipalId(), edlContext
072                    .getEdocLiteAssociation().getEdlName());
073            document.setTitle("Routing Document Type '" + document.getDocumentTypeName() + "'");
074            document.getDocumentId();
075            LOG.info("Created document " + document.getDocumentId());
076        } else {
077            document = (WorkflowDocument) requestParser.getAttribute(RequestParser.WORKFLOW_DOCUMENT_SESSION_KEY);
078            if (document == null) {
079                String docId = (String) requestParser.getAttribute("docId");
080                if (docId == null) {
081                    LOG.info("no document found for edl " + edlContext.getEdocLiteAssociation().getEdlName());
082                    return;
083                } else {
084                    document = WorkflowDocumentFactory
085                            .loadDocument(edlContext.getUserSession().getPrincipalId(), docId);
086                }
087            }
088        }
089
090        requestParser.setAttribute(RequestParser.WORKFLOW_DOCUMENT_SESSION_KEY, document);
091    }
092
093    private void doPostProcessWork(Document dom, EDLContext edlContext) throws Exception {
094        RequestParser requestParser = edlContext.getRequestParser();
095        // if the document is in error then we don't want to execute the action!
096        if (edlContext.isInError()) {
097            return;
098        }
099        WorkflowDocument document = (WorkflowDocument) edlContext.getRequestParser().getAttribute(
100                RequestParser.WORKFLOW_DOCUMENT_SESSION_KEY);
101        if (document == null) {
102            return;
103        }
104        //strip out the data element
105        Element dataElement = (Element) dom.getElementsByTagName(EDLXmlUtils.DATA_E).item(0);
106        String docContent = XmlJotter.jotNode(dataElement);//use the transformer on edlcontext
107        document.setApplicationContent(docContent);
108        takeAction(document, dom, edlContext);
109    }
110
111    public static void takeAction(WorkflowDocument document, Document dom, EDLContext edlContext)
112            throws WorkflowException {
113        RequestParser requestParser = edlContext.getRequestParser();
114        UserAction userAction = edlContext.getUserAction();
115        String annotation = requestParser.getParameterValue("annotation");
116        String action = userAction.getAction();
117        String previousNodeName = requestParser.getParameterValue("previousNode");
118
119        if (!userAction.isValidatableAction()) {
120            // if the action's not validatable, clear the attribute definitions because we don't want to end up executing validateClientRoutingData()
121            // TODO the problem here is that the XML is still updated on a cancel so we end up without any attribute content in the document content
122            document.clearAttributeDefinitions();
123        }
124
125        boolean actionTaken = true;
126
127        if (UserAction.ACTION_ROUTE.equals(action)) {
128            document.route(annotation);
129        }else if(UserAction.ACTION_CREATE.equals(action)){
130               document.saveDocumentData();
131        }
132        else if (UserAction.ACTION_APPROVE.equals(action)) {
133            document.approve(annotation);
134        } else if (UserAction.ACTION_DISAPPROVE.equals(action)) {
135            document.disapprove(annotation);
136        } else if (UserAction.ACTION_CANCEL.equals(action)) {
137            document.cancel(annotation);
138        } else if (UserAction.ACTION_BLANKETAPPROVE.equals(action)) {
139            document.blanketApprove(annotation);
140        } else if (UserAction.ACTION_FYI.equals(action)) {
141            document.fyi();
142        } else if (UserAction.ACTION_ACKNOWLEDGE.equals(action)) {
143            document.acknowledge(annotation);
144        } else if (UserAction.ACTION_SAVE.equals(action)) {
145            if (document.getStatus().equals(DocumentStatus.INITIATED)) {
146                document.saveDocument(annotation);
147            } else {
148                document.saveDocumentData();
149            }
150        } else if (UserAction.ACTION_COMPLETE.equals(action)) {
151            document.complete(annotation);
152        } else if (UserAction.ACTION_DELETE.equals(action)) {
153            document.delete();
154        } else if (UserAction.ACTION_RETURN_TO_PREVIOUS.equals(action)) {
155            document.returnToPreviousNode(annotation, previousNodeName);
156        } else {
157            actionTaken = false;
158        }
159
160        if (actionTaken) {
161            Element actionTakenElement = EDLXmlUtils.getOrCreateChildElement(dom.getDocumentElement(), ACTION_TAKEN,
162                    true);
163            actionTakenElement.appendChild(dom.createTextNode(action));
164        }
165    }
166
167}