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}