/*
* Copyright 2016 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.
* You may obtain a copy of the License at
*
* 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.
*/
package org.kie.workbench.common.stunner.bpmn.backend.marshall.json.parser;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.codehaus.jackson.Base64Variant;
import org.codehaus.jackson.JsonLocation;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonStreamContext;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.ObjectCodec;
import org.codehaus.jackson.impl.JsonParserMinimalBase;
import org.kie.workbench.common.stunner.core.diagram.Diagram;
import org.kie.workbench.common.stunner.core.diagram.Metadata;
import org.kie.workbench.common.stunner.core.graph.Edge;
import org.kie.workbench.common.stunner.core.graph.Graph;
import org.kie.workbench.common.stunner.core.graph.Node;
import org.kie.workbench.common.stunner.core.graph.content.definition.DefinitionSet;
import org.kie.workbench.common.stunner.core.graph.content.relationship.Child;
import org.kie.workbench.common.stunner.core.graph.content.view.View;
import org.kie.workbench.common.stunner.core.graph.content.view.ViewConnector;
import org.kie.workbench.common.stunner.core.graph.processing.traverse.content.AbstractChildrenTraverseCallback;
import org.kie.workbench.common.stunner.core.graph.processing.traverse.content.ChildrenTraverseProcessorImpl;
import org.kie.workbench.common.stunner.core.graph.processing.traverse.tree.TreeWalkTraverseProcessorImpl;
// See org.codehaus.jackson.impl.ReaderBasedParser
public class BPMN2JsonParser extends JsonParserMinimalBase {
private Diagram<Graph, Metadata> diagram;
private NodeParser rootParser;
public BPMN2JsonParser(final Diagram<Graph, Metadata> diagram,
final ContextualParser.Context parsingContext) {
this.diagram = diagram;
initialize(parsingContext);
}
/*
****************************************************************
* Custom Stunner logic
****************************************************************
*/
@SuppressWarnings("unchecked")
private void initialize(final ContextualParser.Context parsingContext) {
Graph graph = diagram.getGraph();
final Map<String, EdgeParser> edgeParsers = new HashMap<>();
new ChildrenTraverseProcessorImpl(new TreeWalkTraverseProcessorImpl())
.traverse(graph,
new AbstractChildrenTraverseCallback<Node<View, Edge>, Edge<Child, Node>>() {
final Stack<NodeParser> parsers = new Stack<NodeParser>();
NodeParser currentParser = null;
@Override
public void startGraphTraversal(Graph<DefinitionSet, Node<View, Edge>> graph) {
super.startGraphTraversal(graph);
}
@Override
public boolean startNodeTraversal(final List<Node<View, Edge>> parents,
final Node<View, Edge> node) {
super.startNodeTraversal(parents,
node);
onNodeTraversal(node);
return true;
}
@Override
public void startNodeTraversal(final Node<View, Edge> node) {
super.startNodeTraversal(node);
onNodeTraversal(node);
}
private void onNodeTraversal(final Node node) {
NodeParser p = new NodeParser("",
node);
if (null != currentParser) {
parsers.peek().addChild(p);
} else {
BPMN2JsonParser.this.rootParser = p;
}
currentParser = p;
List<Edge> outEdges = node.getOutEdges();
if (null != outEdges && !outEdges.isEmpty()) {
for (Edge edge : outEdges) {
// Only add the edges with view connector types into the resulting structure to generate the bpmn definition.
if (edge.getContent() instanceof ViewConnector && !edgeParsers.containsKey(edge.getUUID())) {
edgeParsers.put(edge.getUUID(),
new EdgeParser("",
(Edge) edge));
}
}
}
}
@Override
public void startEdgeTraversal(Edge<Child, Node> edge) {
super.startEdgeTraversal(edge);
parsers.push(currentParser);
}
@Override
public void endEdgeTraversal(Edge<Child, Node> edge) {
super.endEdgeTraversal(edge);
currentParser = parsers.pop();
}
@Override
public void endGraphTraversal() {
super.endGraphTraversal();
}
});
// In oryx format, all edges are added into the main BPMNDiagram node.
if (null != rootParser && !edgeParsers.isEmpty()) {
for (EdgeParser edgeParser : edgeParsers.values()) {
rootParser.addChild(edgeParser);
}
}
// Initialize all the element parsers added in the tree.
BPMN2JsonParser.this.rootParser.initialize(parsingContext);
System.out.println("End of children and view traverse");
}
/*
****************************************************************
* JsonParser interface methods
****************************************************************
*/
@Override
public ObjectCodec getCodec() {
return null;
}
@Override
public void setCodec(final ObjectCodec c) {
}
@Override
public JsonToken nextToken() throws IOException, JsonParseException {
return rootParser.nextToken();
}
@Override
protected void _handleEOF() throws JsonParseException {
}
@Override
public String getCurrentName() throws IOException, JsonParseException {
return rootParser.getCurrentName();
}
@Override
public void close() throws IOException {
}
@Override
public boolean isClosed() {
return false;
}
@Override
public JsonStreamContext getParsingContext() {
return null;
}
@Override
public JsonLocation getTokenLocation() {
return null;
}
@Override
public JsonLocation getCurrentLocation() {
return null;
}
@Override
public String getText() throws IOException, JsonParseException {
return rootParser.getText();
}
@Override
public char[] getTextCharacters() throws IOException, JsonParseException {
return new char[0];
}
@Override
public boolean hasTextCharacters() {
return false;
}
@Override
public Number getNumberValue() throws IOException, JsonParseException {
return null;
}
@Override
public NumberType getNumberType() throws IOException, JsonParseException {
return null;
}
@Override
public int getIntValue() throws IOException, JsonParseException {
return rootParser.getIntValue();
}
@Override
public long getLongValue() throws IOException, JsonParseException {
return 0;
}
@Override
public BigInteger getBigIntegerValue() throws IOException, JsonParseException {
return null;
}
@Override
public float getFloatValue() throws IOException, JsonParseException {
return 0;
}
@Override
public double getDoubleValue() throws IOException, JsonParseException {
return 0;
}
@Override
public BigDecimal getDecimalValue() throws IOException, JsonParseException {
return null;
}
@Override
public int getTextLength() throws IOException, JsonParseException {
return 0;
}
@Override
public int getTextOffset() throws IOException, JsonParseException {
return 0;
}
@Override
public byte[] getBinaryValue(final Base64Variant b64variant) throws IOException, JsonParseException {
return new byte[0];
}
@Override
public JsonParser skipChildren() throws IOException, JsonParseException {
return null;
}
}