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.framework.workflow;
017
018import org.apache.commons.lang.StringUtils;
019import org.jdom2.Attribute;
020import org.jdom2.Element;
021import org.kuali.rice.core.api.util.xml.XmlHelper;
022import org.kuali.rice.core.api.util.xml.XmlJotter;
023import org.kuali.rice.edl.framework.extract.DumpDTO;
024import org.kuali.rice.edl.framework.extract.ExtractService;
025import org.kuali.rice.edl.framework.extract.FieldDTO;
026import org.kuali.rice.edl.framework.services.EdlFrameworkServiceLocator;
027import org.kuali.rice.kew.api.KewApiConstants;
028import org.kuali.rice.kew.api.KewApiServiceLocator;
029import org.kuali.rice.kew.api.doctype.DocumentType;
030import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
031import org.kuali.rice.kew.framework.postprocessor.ActionTakenEvent;
032import org.kuali.rice.kew.framework.postprocessor.DeleteEvent;
033import org.kuali.rice.kew.framework.postprocessor.DocumentRouteLevelChange;
034import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
035import org.kuali.rice.kew.framework.postprocessor.ProcessDocReport;
036import org.w3c.dom.Document;
037
038import java.rmi.RemoteException;
039import java.sql.Timestamp;
040import java.util.ArrayList;
041import java.util.Collection;
042import java.util.Iterator;
043import java.util.List;
044
045public class EDocLiteDatabasePostProcessor extends EDocLitePostProcessor {
046
047    private static final org.apache.logging.log4j.Logger LOG = org.apache.logging.log4j.LogManager
048            .getLogger(EDocLiteDatabasePostProcessor.class);
049
050    @Override
051    public ProcessDocReport doRouteStatusChange(DocumentRouteStatusChange event) throws RemoteException {
052        LOG.debug("doRouteStatusChange: " + event);
053        String documentId = event.getDocumentId();
054        super.postEvent(documentId, event, "statusChange");
055        Document doc = getEDLContent(documentId);
056        if (LOG.isDebugEnabled()) {
057            LOG.debug("Submitting doc: " + XmlJotter.jotNode(doc));
058        }
059        extractEDLData(documentId, getNodeNames(event.getDocumentId()), doc);
060        return super.doRouteStatusChange(event);
061    }
062
063    @Override
064    public ProcessDocReport doActionTaken(ActionTakenEvent event) throws RemoteException {
065        LOG.debug("doActionTaken: " + event);
066        String documentId = event.getDocumentId();
067        super.postEvent(documentId, event, "actionTaken");
068
069        // if the action requested is a save, go ahead and update the database with the most current information. -grpatter
070        if (KewApiConstants.ACTION_TAKEN_SAVED_CD.equals(event.getActionTaken().getActionTaken())) {
071            Document doc = getEDLContent(documentId);
072            extractEDLData(documentId, getNodeNames(event.getDocumentId()), doc);
073        }
074
075        return super.doActionTaken(event);
076    }
077
078    @Override
079    public ProcessDocReport doDeleteRouteHeader(DeleteEvent event) throws RemoteException {
080        LOG.debug("doDeleteRouteHeader: " + event);
081        super.postEvent(event.getDocumentId(), event, "deleteRouteHeader");
082        return super.doDeleteRouteHeader(event);
083    }
084
085    @Override
086    public ProcessDocReport doRouteLevelChange(DocumentRouteLevelChange event) throws RemoteException {
087        LOG.debug("doRouteLevelChange: " + event);
088        String documentId = event.getDocumentId();
089        super.postEvent(documentId, event, "routeLevelChange");
090        Document doc = getEDLContent(documentId);
091        if (LOG.isDebugEnabled()) {
092            LOG.debug("Submitting doc: " + XmlJotter.jotNode(doc));
093        }
094        extractEDLData(documentId, new String[]{event.getNewNodeName()}, doc);
095        return super.doRouteLevelChange(event);
096    }
097
098    //      public static Document getEDLContent(DocumentRouteHeaderValue routeHeader) throws Exception {
099    //          String content = routeHeader.getDocContent();
100    //          Document doc =  DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(content)));
101    //          return doc;
102    //      }
103
104    private String[] getNodeNames(String documentId) {
105        List<String> activeNodeInstances = KewApiServiceLocator.getWorkflowDocumentService().getActiveRouteNodeNames(documentId);
106        if (activeNodeInstances == null || activeNodeInstances.isEmpty()) {
107            activeNodeInstances = KewApiServiceLocator.getWorkflowDocumentService().getTerminalRouteNodeNames(documentId);
108        }
109
110        return activeNodeInstances != null ? activeNodeInstances.toArray(new String[] {}) : new String[] {};
111    }
112
113    private void extractEDLData(String documentId, String[] nodeNames, Document documentContent) {
114        try {
115            org.kuali.rice.kew.api.document.Document document = KewApiServiceLocator.getWorkflowDocumentService().getDocument(documentId);
116            DocumentType documentType = KewApiServiceLocator.getDocumentTypeService().getDocumentTypeById(
117                    document.getDocumentTypeId());
118            DumpDTO dump = getExtractService().getDumpByDocumentId(documentId);
119            if (dump == null) {
120                dump = new DumpDTO();
121            }
122            dump.setDocId(documentId);
123            dump.setDocCreationDate(new Timestamp(document.getDateCreated().getMillis()));
124            dump.setDocCurrentNodeName(StringUtils.join(nodeNames, ","));
125            dump.setDocDescription(documentType.getDescription());
126            if (document.getDateLastModified() != null) {
127                dump.setDocModificationDate(new Timestamp(document.getDateLastModified().getMillis()));
128            }
129            dump.setDocInitiatorId(document.getInitiatorPrincipalId());
130            dump.setDocRouteStatusCode(document.getStatus().getCode());
131            dump.setDocTypeName(documentType.getName());
132
133            List<FieldDTO> fields = dump.getFields();
134            fields.clear();
135
136            List fieldElements = setExtractFields(documentContent);
137            for (Iterator iter = fieldElements.iterator(); iter.hasNext();) {
138                FieldDTO field = new FieldDTO();
139                field.setDocId(dump.getDocId());
140                Element element = (Element) iter.next();
141                Attribute attribute = element.getAttribute("name");
142                field.setFieldName(attribute.getValue());
143                field.setFieldValue(element.getChildText("value"));
144                fields.add(field);
145            }
146            dump.setFields(fields);
147            getExtractService().saveDump(dump);
148        } catch (Exception e) {
149            if (e instanceof RuntimeException) {
150                throw (RuntimeException) e;
151            }
152            throw new RuntimeException(e);
153        }
154    }
155
156    private ExtractService getExtractService() {
157        return EdlFrameworkServiceLocator.getExtractService();
158    }
159
160    private static Element getRootElement(Document docContent) {
161        return XmlHelper.buildJDocument(docContent).getRootElement();
162    }
163
164    private List setExtractFields(Document documentContent) {
165        Element rootElement = getRootElement(documentContent);
166        List<Element> fields = new ArrayList<Element>();
167        Collection<Element> fieldElements = XmlHelper.findElements(rootElement, "field");
168        Iterator<Element> elementIter = fieldElements.iterator();
169        while (elementIter.hasNext()) {
170            Element field = elementIter.next();
171            Element version = field.getParentElement();
172            if (version.getAttribute("current").getValue().equals("true")) {
173                if (field.getAttribute("name") != null) {
174                    fields.add(field);
175                }
176            }
177        }
178        return fields;
179    }
180
181}