org.jbpm.gd.common.editor.AbstractContentProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.jbpm.gd.common.editor.AbstractContentProvider.java

Source

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jbpm.gd.common.editor;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.part.FileEditorInput;
import org.jbpm.gd.common.model.NamedElement;
import org.jbpm.gd.common.model.SemanticElement;
import org.jbpm.gd.common.notation.AbstractNodeContainer;
import org.jbpm.gd.common.notation.BendPoint;
import org.jbpm.gd.common.notation.Edge;
import org.jbpm.gd.common.notation.Node;
import org.jbpm.gd.common.notation.NodeContainer;
import org.jbpm.gd.common.notation.NotationElement;
import org.jbpm.gd.common.notation.NotationMapping;
import org.jbpm.gd.common.notation.RootContainer;
import org.jbpm.gd.jpdl.Logger;

public abstract class AbstractContentProvider implements ContentProvider {

    protected abstract SemanticElement getEdgeSemanticElement(Node node, Element notationInfo, int index);

    protected abstract SemanticElement getNodeSemanticElement(NodeContainer node, Element notationInfo, int index);

    protected abstract void addNodes(NodeContainer nodeContainer, Element notationInfo);

    protected abstract void addEdges(Node node, Element notationInfo);

    protected abstract SemanticElement findDestination(Edge edge, Node source);

    protected String getRootNotationInfoElement() {
        return "<root-container/>";
    }

    protected String createInitialNotationInfo() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        buffer.append("\n\n");
        buffer.append(getRootNotationInfoElement());
        return buffer.toString();
    }

    public String getNotationInfoFileName(String semanticInfoFileName) {
        return ".gpd." + semanticInfoFileName;
    }

    public String getDiagramImageFileName(String semanticInfoFileName) {
        String result;
        int index = semanticInfoFileName.indexOf(".xml");
        result = index > -1 ? semanticInfoFileName.substring(0, index) : semanticInfoFileName;
        return result + ".jpg";
    }

    protected void processRootContainer(RootContainer rootContainer, Element notationInfo) {
        addDimension(rootContainer, notationInfo);
        addNodes(rootContainer, notationInfo);
        postProcess(rootContainer);
    }

    protected void addNodes(NodeContainer nodeContainer, SemanticElement[] semanticElements, Element notationInfo) {
        List notationInfoElements = notationInfo == null ? new ArrayList() : notationInfo.elements();
        for (int i = 0; i < semanticElements.length; i++) {
            Element notationInfoElement = null;
            String nodeName = ((NamedElement) semanticElements[i]).getName();
            for (int j = 0; j < notationInfoElements.size(); j++) {
                Element element = (Element) notationInfoElements.get(j);
                String elementName = element.attributeValue("name");
                if ((elementName != null && elementName.equals(nodeName))
                        || (elementName == null && nodeName == null)) {
                    notationInfoElement = element;
                }
            }
            //         if (notationInfoElements.size() >= i + 1) {
            //            notationInfoElement = (Element)notationInfoElements.get(i);
            //         }
            addNode(nodeContainer, semanticElements[i], notationInfoElement);
        }
    }

    protected void addEdges(Node node, SemanticElement[] semanticElements, Element notationInfo) {
        List notationInfoElements = notationInfo == null ? new ArrayList() : notationInfo.elements();
        for (int i = 0; i < semanticElements.length; i++) {
            Element notationInfoElement = null;
            if (notationInfoElements.size() >= i + 1) {
                notationInfoElement = (Element) notationInfoElements.get(i);
            }
            addEdge(node, semanticElements[i], notationInfoElement);
        }
    }

    protected void addNode(NodeContainer nodeContainer, SemanticElement semanticElement,
            Element notationInfoElement) {
        String notationElementId = NotationMapping.getNotationElementId(semanticElement.getElementId());
        Node notationElement = (Node) nodeContainer.getFactory().create(notationElementId);
        notationElement.setSemanticElement(semanticElement);
        notationElement.register();
        nodeContainer.addNode(notationElement);
        semanticElement.addPropertyChangeListener(notationElement);
        processNode(notationElement, notationInfoElement);
        if (notationElement instanceof NodeContainer) {
            addNodes((NodeContainer) notationElement, notationInfoElement);
        }
    }

    protected void addEdge(Node node, SemanticElement semanticElement, Element notationInfoElement) {
        NotationElement notationElement = node.getRegisteredNotationElementFor(semanticElement);
        if (notationElement == null) {
            String notationElementId = NotationMapping.getNotationElementId(semanticElement.getElementId());
            notationElement = (NotationElement) node.getFactory().create(notationElementId);
            notationElement.setSemanticElement(semanticElement);
            notationElement.register();
            node.addLeavingEdge((Edge) notationElement);
            semanticElement.addPropertyChangeListener(notationElement);
        }
        processEdge((Edge) notationElement, notationInfoElement);
    }

    protected void addDimension(RootContainer processDefinitionNotationElement, Element processDiagramInfo) {
        String width = processDiagramInfo.attributeValue("width");
        String height = processDiagramInfo.attributeValue("height");
        Dimension dimension = new Dimension(width == null ? 0 : Integer.valueOf(width).intValue(),
                height == null ? 0 : Integer.valueOf(height).intValue());
        processDefinitionNotationElement.setDimension(dimension);
    }

    protected void processNode(Node node, Element notationInfoElement) {
        addConstraint(node, notationInfoElement);
        addEdges(node, notationInfoElement);
    }

    protected void processEdge(Edge edge, Element edgeInfo) {
        processLabel(edge, edgeInfo);
        addBendpoints(edge, edgeInfo);
    }

    protected void addBendpoints(Edge edge, Element edgeInfo) {
        if (edgeInfo != null) {
            List list = edgeInfo.elements("bendpoint");
            for (int i = 0; i < list.size(); i++) {
                addBendpoint(edge, (Element) list.get(i), i);
            }
        }
    }

    protected BendPoint addBendpoint(Edge edge, Element bendpointInfo, int index) {
        BendPoint result = new BendPoint();
        processBendpoint(result, bendpointInfo);
        edge.addBendPoint(result);
        return result;
    }

    protected void processBendpoint(BendPoint bendPoint, Element bendpointInfo) {
        int w1 = Integer.valueOf(bendpointInfo.attributeValue("w1")).intValue();
        int h1 = Integer.valueOf(bendpointInfo.attributeValue("h1")).intValue();
        int w2 = Integer.valueOf(bendpointInfo.attributeValue("w2")).intValue();
        int h2 = Integer.valueOf(bendpointInfo.attributeValue("h2")).intValue();
        Dimension d1 = new Dimension(w1, h1);
        Dimension d2 = new Dimension(w2, h2);
        bendPoint.setRelativeDimensions(d1, d2);
    }

    private void processLabel(Edge edge, Element edgeInfo) {
        Element label = null;
        if (edgeInfo != null) {
            label = edgeInfo.element("label");
        }
        if (label != null) {
            Point offset = new Point();
            offset.x = Integer.valueOf(label.attributeValue("x")).intValue();
            offset.y = Integer.valueOf(label.attributeValue("y")).intValue();
            edge.getLabel().setOffset(offset);
        }
    }

    private void addConstraint(Node node, Element nodeInfo) {
        Rectangle constraint = node.getConstraint().getCopy();
        Dimension initialDimension = NotationMapping.getInitialDimension(node.getSemanticElement().getElementId());
        if (initialDimension != null) {
            constraint.setSize(initialDimension);
        }
        if (nodeInfo != null) {
            constraint.x = Integer.valueOf(nodeInfo.attributeValue("x")).intValue();
            constraint.y = Integer.valueOf(nodeInfo.attributeValue("y")).intValue();
            constraint.width = Integer.valueOf(nodeInfo.attributeValue("width")).intValue();
            constraint.height = Integer.valueOf(nodeInfo.attributeValue("height")).intValue();
        }
        node.setConstraint(constraint);
    }

    protected void postProcess(NodeContainer nodeContainer) {
        List nodes = nodeContainer.getNodes();
        for (int i = 0; i < nodes.size(); i++) {
            Node node = (Node) nodes.get(i);
            List edges = node.getLeavingEdges();
            for (int j = 0; j < edges.size(); j++) {
                Edge edge = (Edge) edges.get(j);
                SemanticElement destination = findDestination(edge, node);
                Node target = (Node) edge.getFactory().getRegisteredNotationElementFor(destination);
                if (target != null && edge.getTarget() == null) {
                    target.addArrivingEdge(edge);
                }
            }
            if (node instanceof NodeContainer) {
                postProcess((NodeContainer) node);
            }
        }
    }

    public boolean saveToInput(IEditorInput input, RootContainer rootContainer) {
        boolean result = true;
        try {
            IFile file = getNotationInfoFile(((IFileEditorInput) input).getFile());
            InputStreamReader reader = new InputStreamReader(file.getContents());
            Element notationInfo = new SAXReader().read(reader).getRootElement();
            if (upToDateCheck(notationInfo)) {
                getNotationInfoFile(((IFileEditorInput) input).getFile()).setContents(
                        new ByteArrayInputStream(toNotationInfoXml(rootContainer).getBytes()), true, true, null);
            } else {
                result = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    protected String toNotationInfoXml(RootContainer rootContainer) {
        StringWriter writer = new StringWriter();
        write(rootContainer, writer);
        return writer.toString();
    }

    protected void write(RootContainer rootContainer, Writer writer) {
        try {
            Document document = DocumentHelper.createDocument();
            Element root = document.addElement("root-container");
            write(rootContainer, root);
            XMLWriter xmlWriter = new XMLWriter(writer, OutputFormat.createPrettyPrint());
            xmlWriter.write(document);
        } catch (IOException e) {
            e.printStackTrace(new PrintWriter(writer));
        }
    }

    protected void write(RootContainer rootContainer, Element element) {
        addAttribute(element, "name", ((NamedElement) rootContainer.getSemanticElement()).getName());
        addAttribute(element, "width", Integer.toString(rootContainer.getDimension().width));
        addAttribute(element, "height", Integer.toString(rootContainer.getDimension().height));
        Iterator iter = rootContainer.getNodes().iterator();
        while (iter.hasNext()) {
            write((Node) iter.next(), element);
        }
    }

    protected void write(Node node, Element element) {
        Element newElement = null;
        if (node instanceof AbstractNodeContainer) {
            newElement = addElement(element, "node-container");
        } else {
            newElement = addElement(element, "node");
        }
        addAttribute(newElement, "name", ((NamedElement) node.getSemanticElement()).getName());
        addAttribute(newElement, "x", String.valueOf(node.getConstraint().x));
        addAttribute(newElement, "y", String.valueOf(node.getConstraint().y));
        addAttribute(newElement, "width", String.valueOf(node.getConstraint().width));
        addAttribute(newElement, "height", String.valueOf(node.getConstraint().height));
        if (node instanceof AbstractNodeContainer) {
            Iterator nodes = ((AbstractNodeContainer) node).getNodes().iterator();
            while (nodes.hasNext()) {
                write((Node) nodes.next(), newElement);
            }
        }
        Iterator edges = node.getLeavingEdges().iterator();
        while (edges.hasNext()) {
            Edge edge = (Edge) edges.next();
            write(edge, addElement(newElement, "edge"));
        }
    }

    protected void write(Edge edge, Element element) {
        Point offset = edge.getLabel().getOffset();
        if (offset != null) {
            Element label = addElement(element, "label");
            addAttribute(label, "x", String.valueOf(offset.x));
            addAttribute(label, "y", String.valueOf(offset.y));
        }
        Iterator bendpoints = edge.getBendPoints().iterator();
        while (bendpoints.hasNext()) {
            write((BendPoint) bendpoints.next(), addElement(element, "bendpoint"));
        }
    }

    protected void write(BendPoint bendpoint, Element bendpointElement) {
        addAttribute(bendpointElement, "w1", String.valueOf(bendpoint.getFirstRelativeDimension().width));
        addAttribute(bendpointElement, "h1", String.valueOf(bendpoint.getFirstRelativeDimension().height));
        addAttribute(bendpointElement, "w2", String.valueOf(bendpoint.getSecondRelativeDimension().width));
        addAttribute(bendpointElement, "h2", String.valueOf(bendpoint.getSecondRelativeDimension().height));
    }

    protected Element addElement(Element element, String elementName) {
        Element newElement = element.addElement(elementName);
        return newElement;
    }

    protected void addAttribute(Element e, String attributeName, String value) {
        if (value != null) {
            e.addAttribute(attributeName, value);
        }
    }

    private void createNotationInfoFile(IFile notationInfoFile) {
        try {
            notationInfoFile.create(new ByteArrayInputStream(createInitialNotationInfo().toString().getBytes()),
                    true, null);
        } catch (CoreException e) {
            Logger.logError(e);
        }
    }

    protected IFile getNotationInfoFile(IFile semanticInfoFile) {
        IProject project = semanticInfoFile.getProject();
        IPath semanticInfoPath = semanticInfoFile.getProjectRelativePath();
        IPath notationInfoPath = semanticInfoPath.removeLastSegments(1)
                .append(getNotationInfoFileName(semanticInfoFile.getName()));
        IFile notationInfoFile = project.getFile(notationInfoPath);
        if (!notationInfoFile.exists()) {
            createNotationInfoFile(notationInfoFile);
        }
        return notationInfoFile;
    }

    public void addNotationInfo(RootContainer rootContainer, IEditorInput input) {
        try {
            IFile file = getNotationInfoFile(((FileEditorInput) input).getFile());
            if (file.exists()) {
                InputStreamReader reader = new InputStreamReader(file.getContents());
                Element notationInfo = new SAXReader().read(reader).getRootElement();
                boolean changed = convertCheck(notationInfo);
                processRootContainer(rootContainer, notationInfo);
                if (changed) {
                    file.setContents(new ByteArrayInputStream(toNotationInfoXml(rootContainer).getBytes()), true,
                            true, null);
                }
            } else {
                file.create(new ByteArrayInputStream(createInitialNotationInfo().toString().getBytes()), true,
                        null);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (CoreException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private boolean convertCheck(Element notationInfo) {
        boolean changed = false;
        if ("process-diagram".equals(notationInfo.getName()) || "pageflow-diagram".equals(notationInfo.getName())) {
            MessageDialog dialog = new MessageDialog(null, "Convert To 3.1.x Format", null,
                    "A file created with an older GPD version was detected. "
                            + "If you open this file it will be converted to the 3.1.x "
                            + "format and overwritten.\n" + "Do you want to continue?",
                    MessageDialog.QUESTION, new String[] { "Convert And Open", "Continue Without Converting" }, 0);
            if (dialog.open() == 0) {
                convertToRootContainer(notationInfo);
                changed = true;
            }
        }
        return changed;
    }

    private boolean upToDateCheck(Element notationInfo) {
        if ("process-diagram".equals(notationInfo.getName()) || "pageflow-diagram".equals(notationInfo.getName())) {
            MessageDialog dialog = new MessageDialog(null, "GPD 3.0.x Format Detected", null,
                    "The file you are trying to save contains GPD 3.0.x information."
                            + "Saving the file will result in an automatic conversion into the 3.1.x format."
                            + "It will be impossible to open it with the old GPD.\n" + "Do you want to continue?",
                    MessageDialog.QUESTION, new String[] { "Save And Convert", "Cancel" }, 0);
            return dialog.open() == 0;
        }
        return true;
    }

    private void convertToRootContainer(Element notationInfo) {
        notationInfo.setName("root-container");
        convertChildrenToEdge(notationInfo);
    }

    private void convertChildrenToEdge(Element element) {
        List list = element.elements();
        for (int i = 0; i < list.size(); i++) {
            convertToEdge((Element) list.get(i));
        }
    }

    private void convertToEdge(Element element) {
        if ("transition".equals(element.getName())) {
            element.setName("edge");
        }
        convertChildrenToEdge(element);
    }

}