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