/* Copyright 1999-2008 Acelet.org. All rights reserved. GPL v2 license */
/** @author Wei Jiang */
package com.acelet.s.workflow;
import java.io.*;
import java.util.*;
import javax.swing.tree.*;
import com.acelet.lib.*;
import com.acelet.s.job.*;
import com.jgraph.editor.JGraphEditorFile;
import com.jgraph.editor.JGraphEditorModel;
import com.jgraph.pad.JGraphpadDiagram;
import com.jgraph.pad.graph.JGraphpadBusinessObject;
import com.jgraph.pad.graph.JGraphpadGraphModel;
import org.jgraph.graph.DefaultEdge;
import org.jgraph.graph.DefaultGraphCell;
import org.jgraph.graph.DefaultPort;
import org.jgraph.graph.GraphLayoutCache;
public class Spirit implements WorkflowConstants {
public static String SPIRIT_FILE_NAME = "spirit";
String xmlText;
JGraphEditorFile graphEditorFile;
JGraphpadDiagram graphpadDiagram;
GraphLayoutCache graphLayoutCache;
JGraphpadGraphModel graphpadGraphModel;
JGraphEditorModel graphEditorModel;
Hashtable cellToSourceHashtable = new Hashtable();
Vector cellVector = new Vector();
Vector edgeVector = new Vector();
public Spirit(JGraphEditorFile graphEditorFile) throws Exception {
this.graphEditorFile = graphEditorFile;
}
public Spirit(String xmlText) throws Exception {
this.xmlText = xmlText;
graphEditorFile = makeGraphEditorFile(xmlText);
}
public String checkError() throws Exception {
StringBuffer buffer = new StringBuffer();
Vector orphanCellVector = getOrphanCellVector();
if (orphanCellVector.size() > 0)
buffer.append(Phrase.get("ER_THERE_ARE_ORPHAN_ACTIONS") + ": " +
orphanCellVector.size() + "\n\n");
Vector loneEdgeVector = getLoneEdgeVector();
if (loneEdgeVector.size() > 0)
buffer.append(Phrase.get("ER_THERE_ARE_LONE_TRANSITION") + ": " +
loneEdgeVector.size() + "\n\n");
int numberOfNoNameCells = getNumberOfNoNameCells();
if (numberOfNoNameCells > 0)
buffer.append(Phrase.get("ER_SOME_ACTION_DOES_NOT_HAVE_NAME") + ": " +
numberOfNoNameCells + "\n\n");
Vector duplicatedNameVector = getDuplicatedNameVector();
if (duplicatedNameVector.size() > 0) {
buffer.append(Phrase.get("ER_DUPLICATED_ACTION_ID") + ":\n");
for (int i = 0; i < duplicatedNameVector.size(); i++)
buffer.append(duplicatedNameVector.get(i) + "\n");
buffer.append("\n");
}
Vector emptyTaskVector = getEmptyTaskVector();
if (emptyTaskVector.size() > 0) {
buffer.append(Phrase.get("ER_SOME_ACTION_DOES_NOT_HAVE_TASK_NAME") + ":\n");
for (int i = 0; i < emptyTaskVector.size(); i++)
buffer.append(emptyTaskVector.get(i) + "\n");
}
int numberOfStartCells = getNumberOfStartCells();
if (numberOfStartCells != 1)
buffer.append(Phrase.get("ER_NUMBER_OF_START_ACTION_IS_NOT_ONE") + ": " +
numberOfStartCells + "\n\n");
return buffer.toString();
}
public String extract() {
StringBuffer buffer = new StringBuffer();
findDiagram();
graphLayoutCache = graphpadDiagram.getGraphLayoutCache();
graphpadGraphModel = (JGraphpadGraphModel) graphLayoutCache.getModel();
Object[] all = JGraphpadGraphModel.getAll(graphpadGraphModel);
for (int i = 0; i < all.length; i++) {
Object object = all[i];
if (object instanceof DefaultEdge) {
edgeVector.add(object);
} else if (object instanceof DefaultPort) {
continue;
} else if (object instanceof DefaultGraphCell) {
cellVector.add(object);
}
}
Vector duplicatedNameVector = new Vector();
for (int i = 0; i < cellVector.size(); i++) {
DefaultGraphCell defaultGraphCell = (DefaultGraphCell) cellVector.get(i);
Hashtable userObjectHashtable = null;
Object userObject = graphpadGraphModel.getValue(defaultGraphCell);
if (userObject instanceof JGraphpadBusinessObject) {
JGraphpadBusinessObject graphpadBusinessObject = (JGraphpadBusinessObject) userObject;
userObjectHashtable = (Hashtable) graphpadBusinessObject.getProperties();
} else
continue;
Vector incomingCellVector = new Vector();
Object[] incomingEdges =
JGraphpadGraphModel.getIncomingEdges(graphpadGraphModel, defaultGraphCell);
for (int index = 0; index < incomingEdges.length; index++) {
DefaultEdge edge = (DefaultEdge) incomingEdges[index];
Object vertex = graphpadGraphModel.getSourceVertex(graphpadGraphModel, edge);
if (CellType.isCellActionCell(vertex)) {
DefaultGraphCell cell = (DefaultGraphCell) vertex;
JGraphpadBusinessObject businessObject =
(JGraphpadBusinessObject) graphpadGraphModel.getValue(cell);
Hashtable businessProperties = (Hashtable) businessObject.getProperties();
incomingCellVector.add(businessProperties);
} else
continue;
}
Object existing = null;
if (CellType.isCellActionCell(defaultGraphCell))
cellToSourceHashtable.put(userObjectHashtable, incomingCellVector);
if (existing != null)
duplicatedNameVector.add(userObjectHashtable.get(KEY_ID));
}
if (duplicatedNameVector.size() > 0) {
buffer.append(Phrase.get("ER_DUPLICATED_ACTION_ID") + ":\n");
for (int i = 0; i < duplicatedNameVector.size(); i++)
buffer.append(duplicatedNameVector.get(i) + "\n");
buffer.append("\n");
}
return buffer.toString();
}
JGraphpadDiagram findDiagram() {
return graphpadDiagram = findDiagram(graphEditorFile);
}
static JGraphpadDiagram findDiagram(JGraphEditorFile file) {
Enumeration children = file.children();
while (children.hasMoreElements()) {
Object object = children.nextElement();
if (object instanceof JGraphpadDiagram)
return (JGraphpadDiagram) object;
}
return null;
}
public Hashtable getCellToSourceHashtable() {
return (Hashtable) cellToSourceHashtable.clone();
}
public Vector getCellVector() {
return (Vector) cellVector.clone();
}
Vector getDuplicatedNameVector() {
Vector allNameVector = new Vector();
Vector duplicatedNameVector = new Vector();
Enumeration enumeration = cellToSourceHashtable.keys();
while (enumeration.hasMoreElements()) {
Map userObjectProperties = (Map) enumeration.nextElement();
String id = null;
Object object = userObjectProperties.get(KEY_ID);
if (object != null)
id = object.toString();
else
continue;
if (allNameVector.contains(id))
duplicatedNameVector.add(id);
else
allNameVector.add(id);
}
return duplicatedNameVector;
}
Vector getEmptyTaskVector() {
Vector vector = new Vector();
Enumeration enumeration = cellToSourceHashtable.keys();
while (enumeration.hasMoreElements()) {
Map userObjectProperties = (Map) enumeration.nextElement();
String id = null;
Object object = userObjectProperties.get(KEY_ID);
if (object != null)
id = object.toString();
else
continue;
String taskName = (String) userObjectProperties.get(KEY_TASK_NAME);
if (taskName == null || taskName.trim().length() == 0)
vector.add(id);
}
return vector;
}
Vector getEndCellVector() {
Vector vector = new Vector();
for (int i = 0; i < cellVector.size(); i++) {
DefaultGraphCell defaultGraphCell = (DefaultGraphCell) cellVector.get(i);
Object[] outgoingEdges =
JGraphpadGraphModel.getOutgoingEdges(graphpadGraphModel, defaultGraphCell);
if (outgoingEdges.length == 0)
vector.add(defaultGraphCell);
}
return vector;
}
public JGraphEditorFile getGraphEditorFile() {
return graphEditorFile;
}
public JGraphEditorModel getGraphEditorModel() {
return graphEditorModel;
}
Vector getLoneEdgeVector() {
Vector vector = new Vector();
for (int i = 0; i < edgeVector.size(); i++) {
DefaultEdge edge = (DefaultEdge) edgeVector.get(i);
Object vertex = graphpadGraphModel.getSourceVertex(graphpadGraphModel, edge);
if (vertex == null || (CellType.isCellActionCell(vertex)) == false) {
vector.add(edge);
continue;
}
Object targetObject = graphpadGraphModel.getTargetVertex(graphpadGraphModel, edge);
if (targetObject == null || (CellType.isCellActionCell(targetObject)) == false) {
vector.add(edge);
continue;
}
}
return vector;
}
Vector getOrphanCellVector() {
Vector vector = new Vector();
for (int i = 0; i < cellVector.size(); i++) {
DefaultGraphCell defaultGraphCell = (DefaultGraphCell) cellVector.get(i);
if (CellType.isCellActionCell(defaultGraphCell) == false)
continue;
Object[] incomingEdges =
JGraphpadGraphModel.getIncomingEdges(graphpadGraphModel, defaultGraphCell);
Object[] outgoingEdges =
JGraphpadGraphModel.getOutgoingEdges(graphpadGraphModel, defaultGraphCell);
if (incomingEdges.length == 0 && outgoingEdges.length == 0)
vector.add(defaultGraphCell);
}
return vector;
}
int getNumberOfNoNameCells() {
int numberOfNoNameCells = 0;
Enumeration enumeration = cellToSourceHashtable.keys();
while (enumeration.hasMoreElements()) {
Map userObjectProperties = (Map) enumeration.nextElement();
String id = null;
Object object = userObjectProperties.get(KEY_ID);
String name = object.toString();
if (name.trim().length() == 0)
numberOfNoNameCells++;
}
return numberOfNoNameCells;
}
int getNumberOfStartCells() {
int numberOfStartCells = 0;
Enumeration enumeration = cellToSourceHashtable.keys();
while (enumeration.hasMoreElements()) {
Hashtable keyHashtable = (Hashtable) enumeration.nextElement();
Vector sourceEdgeHashtable = (Vector) cellToSourceHashtable.get(keyHashtable);
if (sourceEdgeHashtable.size() == 0)
numberOfStartCells++;
}
return numberOfStartCells;
}
JGraphEditorFile makeGraphEditorFile(String xmlText) throws Exception {
graphEditorModel = new JGraphEditorModel();
ByteArrayInputStream inputStream = null;
try {
inputStream = new ByteArrayInputStream(xmlText.getBytes(ENCODING));
graphEditorFile = (JGraphEditorFile) graphEditorModel.readObject(inputStream);
graphEditorFile.setFilename(SPIRIT_FILE_NAME);
graphEditorModel.addRoot(graphEditorFile);
return graphEditorFile;
} finally {
try {
if (inputStream != null)
inputStream.close();
} catch (Exception ex) {
ex.printStackTrace();
throw new Exception(Phrase.get("ER_INVALID_WORKFLOW_DATA"));
}
}
}
}