org.jbpm.designer.server.RdfJsonTransformation.java Source code

Java tutorial

Introduction

Here is the source code for org.jbpm.designer.server.RdfJsonTransformation.java

Source

/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

/*
 * ATTENTION: Please synch these files with each other!
 * org.jbpm.designer.server.RdfJsonTransformation
 * org.b3mn.poem.util.RdfJsonTransformation
 */

package org.jbpm.designer.server;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

public class RdfJsonTransformation {

    private final static String[] reservedNodeNames = { "rdf:type", "type", "mode", "stencilset", "render",
            "bounds", "dockers", "outgoing", "target", "parent", "ssextension", "ssnamespace" };

    private static JSONObject canvas;
    private static Map<String, JSONObject> objects; // resourceId -> JSONObject
    private static Map<String, String> parents; // resourceId -> parent's resourceId

    private static String hostUrl;

    private static Logger log = LoggerFactory.getLogger("org.jbpm.designer.server.RdfJsonTransformation");

    public static JSONObject toJson(Document rdfDoc, String requestUrl) {

        canvas = new JSONObject();
        objects = new HashMap<String, JSONObject>();
        parents = new HashMap<String, String>();

        hostUrl = requestUrl;

        Node root = getRootNode(rdfDoc);
        if (root == null)
            return canvas;

        if (root.hasChildNodes()) {
            for (Node node = root.getFirstChild(); node != null; node = node.getNextSibling()) {

                if (node instanceof Text)
                    continue;

                // Does this make any sense??? it just don't parse xml docs with no new lines!!!
                //String type = getType(node);
                //if (type == null)
                //   continue;

                Node rdfTypeNode = getChild(node, "rdf:type");
                if (rdfTypeNode != null) {
                    String rdfType = getAttributeValue(rdfTypeNode, "rdf:resource");
                    if ((rdfType != null) && rdfType.equals("http://oryx-editor.org/canvas")) {
                        handleCanvas(node);
                        continue;
                    }
                }

                handleShape(node);

            }
        }

        setupParentRelationships();

        return canvas;
    }

    private static void handleCanvas(Node n) {
        try {
            canvas.put("resourceId", getResourceId(n));
            canvas.put("childShapes", new JSONArray());
            handleProperties(n, canvas);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private static void handleShape(Node n) {
        try {
            if (!isValidShapeNode(n))
                return;

            String resourceId = getResourceId(n);
            JSONObject shape = new JSONObject();
            shape.put("resourceId", resourceId);
            objects.put(resourceId, shape);
            parents.put(resourceId, getParentResourceId(n));
            shape.put("outgoing", new JSONArray());
            shape.put("childShapes", new JSONArray());
            handleProperties(n, shape);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * Evaluates if given node can be a shape. E.g., it looks for an resource id, if there are any
     * children and if it have a node named generatorAgent (which provides only meta info about the rdf) 
     * @param n Node
     * @return true if given node seems to be a shape
     */
    private static boolean isValidShapeNode(Node n) {
        if (getResourceId(n).length() == 0) //if there isn't a resource id
            return false;
        if (n.hasChildNodes()) {
            //if there is the generatorAgent node
            if (n.getFirstChild().getLocalName() != null
                    && n.getFirstChild().getLocalName().equals("generatorAgent"))
                return false;
        } else {
            //if there isn't any child node
            return false;
        }
        return true;
    }

    private static void setupParentRelationships() {
        for (String resourceId : parents.keySet()) {
            JSONObject child = objects.get(resourceId);
            JSONObject parent = objects.get(parents.get(resourceId));
            if (parent == null)
                parent = canvas;
            try {
                parent.getJSONArray("childShapes").put(child);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    private static void handleProperties(Node n, JSONObject object) throws JSONException {
        JSONObject properties = new JSONObject();
        object.put("properties", properties);
        if (n.hasChildNodes()) {
            for (Node child = n.getFirstChild(); child != null; child = child.getNextSibling()) {
                if (!isReservedNodeName(child.getNodeName())) {
                    String content = getContent(child);
                    if (content == null) {
                        properties.put(child.getNodeName(), content);
                    } else {
                        try {
                            // try to parse property value to JSON object (for complex properties)
                            JSONObject jsonObj = new JSONObject(content);
                            properties.put(child.getNodeName(), jsonObj);
                        } catch (JSONException e) {
                            // non-JSON content
                            log.info("conversion error");
                            log.info(content);
                            log.info(e.toString());
                            properties.put(child.getNodeName(), content);
                        }
                    }
                } else {
                    handleReservedNodeName(child, object);
                }
            }
        }
        //      if((!object.has("target")||"{}".equals(object.getString("target"))||"".equals(object.getString("target")))&& object.has("outgoing")){
        //         if(object.getJSONArray("outgoing").length()>0)
        //            object.put("target", object.getJSONArray("outgoing").get(0));
        //      }
    }

    private static void handleReservedNodeName(Node n, JSONObject object) throws JSONException {

        if (n.getNodeName().equals("bounds")) {
            object.put("bounds", getBounds(n));

        } else if (n.getNodeName().equals("dockers")) {
            object.put("dockers", getDockers(n));
        } else if (n.getNodeName().equals("ssextension")) {
            // There can be several extensions so put them all in an array
            if (!object.has("ssextensions")) {
                object.put("ssextensions", new JSONArray());
            }
            JSONArray extensions = (JSONArray) object.get("ssextensions");
            extensions.put(getContent(n));
        } else if (n.getNodeName().equals("type")) {
            object.put("stencil", (new JSONObject()).put("id", getType(n)));

        } else if (n.getNodeName().equals("outgoing")) {
            JSONObject outgoingObject = new JSONObject();
            outgoingObject.put("resourceId", getResourceId(getAttributeValue(n, "rdf:resource")));
            object.getJSONArray("outgoing").put(outgoingObject);

        } else if (n.getNodeName().equals("target")) {
            JSONObject target = new JSONObject();
            target.put("resourceId", getResourceId(getAttributeValue(n, "rdf:resource")));
            object.put("target", target);

        } else if (n.getNodeName().equals("stencilset")) {
            JSONObject stencilset;
            if (object.has("stencilset")) {
                stencilset = object.getJSONObject("stencilset");
            } else {
                stencilset = new JSONObject();
                object.put("stencilset", stencilset);
            }

            String stencilsetUrl = getAttributeValue(n, "rdf:resource");
            if (!stencilsetUrl.startsWith(hostUrl))
                stencilsetUrl = hostUrl + stencilsetUrl;

            //hack for reverse proxies:
            if (stencilsetUrl.lastIndexOf("http://") > 0)
                stencilsetUrl = stencilsetUrl.substring(stencilsetUrl.lastIndexOf("http://"));

            stencilset.put("url", stencilsetUrl);

        } else if (n.getNodeName().equals("ssnamespace")) {
            JSONObject stencilset;
            if (object.has("stencilset")) {
                stencilset = object.getJSONObject("stencilset");
            } else {
                stencilset = new JSONObject();
                object.put("stencilset", stencilset);
            }

            String namespace = getAttributeValue(n, "rdf:resource");

            stencilset.put("namespace", namespace);

        }

    }

    private static JSONObject getBounds(Node n) throws JSONException {
        String boundsString = getContent(n);
        if (boundsString == null)
            return null;
        String[] boundStringArr = boundsString.split(",");

        JSONObject upperLeft = new JSONObject();
        upperLeft.put("x", Double.parseDouble(boundStringArr[0]));
        upperLeft.put("y", Double.parseDouble(boundStringArr[1]));

        JSONObject lowerRight = new JSONObject();
        lowerRight.put("x", Double.parseDouble(boundStringArr[2]));
        lowerRight.put("y", Double.parseDouble(boundStringArr[3]));

        JSONObject bounds = new JSONObject();
        bounds.put("upperLeft", upperLeft);
        bounds.put("lowerRight", lowerRight);
        return bounds;
    }

    /**
     * Transforms a docker representation like {@code '50 60 20 60 #' ]} to {@code [{x: 50, y: 60}, {x: 20, y: 60}]}
     * @param n The node which contains a docker
     * @return A json array of dockers
     * @throws org.json.JSONException
     */
    private static JSONArray getDockers(Node n) throws JSONException {
        String dockersString = getContent(n);
        if (dockersString == null)
            return null;

        String[] dockerPoints = dockersString.replaceAll("#|\\s+", " ").trim().split(" ");
        JSONArray dockers = new JSONArray();

        JSONObject currentDocker = null;
        for (int i = 0; i < dockerPoints.length; i++) {
            Double point = Double.parseDouble(dockerPoints[i]);

            if ((i % 2) == 0) { // if it is a x coordinate
                currentDocker = new JSONObject();
                currentDocker.put("x", point);
            } else { // else it is a y coordinate
                currentDocker.put("y", point);
                dockers.put(currentDocker);
            }
        }

        return dockers;
    }

    private static String getParentResourceId(Node n) {
        Node parentNode = getChild(n, "parent");
        if (parentNode == null)
            return null;
        String parentResourceId = getResourceId(getAttributeValue(parentNode, "rdf:resource"));
        if (parentResourceId != null)
            return getResourceId(parentResourceId);
        else
            return null;
    }

    private static String getContent(Node node) {
        if (node != null && node.hasChildNodes())
            return node.getFirstChild().getNodeValue();
        return null;
    }

    private static String getAttributeValue(Node node, String attribute) {
        Node item = node.getAttributes().getNamedItem(attribute);
        if (item != null)
            return item.getNodeValue();
        else
            return null;
    }

    private static String getType(Node node) {
        String type = getContent(node);
        if (type != null)
            return type.substring(type.indexOf('#') + 1);
        else
            return null;
    }

    private static String getResourceId(Node node) {
        String attributeValue = getAttributeValue(node, "rdf:about");
        if (attributeValue != null)
            return getResourceId(attributeValue);
        else
            return null;
    }

    private static String getResourceId(String id) {
        if (id == null)
            return null;
        return id.substring(id.indexOf('#') + 1);
    }

    private static Node getChild(Node n, String name) {
        if (n == null)
            return null;
        for (Node node = n.getFirstChild(); node != null; node = node.getNextSibling())
            if (node.getNodeName().equals(name))
                return node;
        return null;
    }

    private static Node getRootNode(Document doc) {
        Node node = doc.getDocumentElement();
        if (node == null || !node.getNodeName().equals("rdf:RDF"))
            return null;
        return node;
    }

    private static boolean isReservedNodeName(String nodeName) {
        for (String n : reservedNodeNames) {
            if (n.equals(nodeName))
                return true;
        }
        return false;
    }

}