/* * 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; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import bpsim.impl.BpsimPackageImpl; import org.eclipse.bpmn2.Bpmn2Package; import org.eclipse.bpmn2.Definitions; import org.eclipse.bpmn2.DocumentRoot; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.jboss.drools.DroolsPackage; import org.jboss.drools.impl.DroolsPackageImpl; import org.kie.workbench.common.stunner.backend.service.XMLEncoderDiagramMetadataMarshaller; import org.kie.workbench.common.stunner.bpmn.backend.legacy.profile.impl.DefaultProfileImpl; import org.kie.workbench.common.stunner.bpmn.backend.legacy.resource.JBPMBpmn2ResourceFactoryImpl; import org.kie.workbench.common.stunner.bpmn.backend.legacy.resource.JBPMBpmn2ResourceImpl; import org.kie.workbench.common.stunner.bpmn.backend.marshall.json.Bpmn2Marshaller; import org.kie.workbench.common.stunner.bpmn.backend.marshall.json.Bpmn2UnMarshaller; import org.kie.workbench.common.stunner.bpmn.backend.marshall.json.builder.GraphObjectBuilderFactory; import org.kie.workbench.common.stunner.bpmn.backend.marshall.json.oryx.OryxManager; import org.kie.workbench.common.stunner.bpmn.definition.BPMNDiagram; import org.kie.workbench.common.stunner.core.api.DefinitionManager; import org.kie.workbench.common.stunner.core.api.FactoryManager; import org.kie.workbench.common.stunner.core.definition.service.DiagramMarshaller; import org.kie.workbench.common.stunner.core.definition.service.DiagramMetadataMarshaller; 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.Graph; import org.kie.workbench.common.stunner.core.graph.Node; import org.kie.workbench.common.stunner.core.graph.command.GraphCommandManager; import org.kie.workbench.common.stunner.core.graph.command.impl.GraphCommandFactory; import org.kie.workbench.common.stunner.core.graph.content.definition.Definition; import org.kie.workbench.common.stunner.core.graph.processing.index.GraphIndexBuilder; import org.kie.workbench.common.stunner.core.graph.util.GraphUtils; import org.kie.workbench.common.stunner.core.rule.RuleManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class BaseDiagramMarshaller<D> implements DiagramMarshaller<Graph, Metadata, Diagram<Graph, Metadata>> { private static final Logger LOG = LoggerFactory.getLogger(BaseDiagramMarshaller.class); private final XMLEncoderDiagramMetadataMarshaller diagramMetadataMarshaller; private final GraphObjectBuilderFactory bpmnGraphBuilderFactory; private final GraphIndexBuilder<?> indexBuilder; private final FactoryManager factoryManager; private final RuleManager rulesManager; private final GraphCommandManager graphCommandManager; private final GraphCommandFactory commandFactory; protected final DefinitionManager definitionManager; protected final OryxManager oryxManager; public BaseDiagramMarshaller(final XMLEncoderDiagramMetadataMarshaller diagramMetadataMarshaller, final GraphObjectBuilderFactory bpmnGraphBuilderFactory, final DefinitionManager definitionManager, final GraphIndexBuilder<?> indexBuilder, final OryxManager oryxManager, final FactoryManager factoryManager, final RuleManager rulesManager, final GraphCommandManager graphCommandManager, final GraphCommandFactory commandFactory) { this.diagramMetadataMarshaller = diagramMetadataMarshaller; this.bpmnGraphBuilderFactory = bpmnGraphBuilderFactory; this.definitionManager = definitionManager; this.indexBuilder = indexBuilder; this.oryxManager = oryxManager; this.factoryManager = factoryManager; this.rulesManager = rulesManager; this.graphCommandManager = graphCommandManager; this.commandFactory = commandFactory; } @Override @SuppressWarnings("unchecked") public String marshall(final Diagram diagram) throws IOException { LOG.debug("Starting diagram marshalling..."); final Bpmn2Marshaller marshaller = new Bpmn2Marshaller(definitionManager, oryxManager); String result = null; try { // Marshall the diagram definition result = marshaller.marshall(diagram); // Update diagram's settings. updateRootUUID(diagram.getMetadata(), diagram.getGraph()); } catch (IOException e) { LOG.error("Error marshalling file.", e); } LOG.debug("Diagram marshalling finished successfully."); return result; } @Override public Graph unmarshall(final Metadata metadata, final InputStream inputStream) throws IOException { LOG.debug("Starting diagram unmarshalling..."); // No rule checking for marshalling/unmarshalling, current jbpm designer marshallers should do it for us. final Bpmn2UnMarshaller parser = new Bpmn2UnMarshaller(bpmnGraphBuilderFactory, definitionManager, factoryManager, rulesManager, oryxManager, graphCommandManager, commandFactory, indexBuilder, getDiagramDefinitionSetClass(), getDiagramDefinitionClass()); Graph result = null; try { // Unmarshall the diagram definition final Definitions definitions = parseDefinitions(inputStream); parser.setProfile(new DefaultProfileImpl()); result = parser.unmarshall(definitions, null); // Update diagram's settings. updateRootUUID(metadata, result); } catch (IOException e) { LOG.error("Error unmarshalling file.", e); } LOG.debug("Diagram unmarshalling finished successfully."); return result; } public abstract Class<?> getDiagramDefinitionSetClass(); public abstract Class<? extends BPMNDiagram> getDiagramDefinitionClass(); public void updateRootUUID(final Metadata settings, final Graph graph) { // Update settings's root UUID. final String rootUUID = getRootUUID(graph); settings.setCanvasRootUUID(rootUUID); } public void updateTitle(final Metadata metadata, final Graph graph) { // Update metadata's title. final String title = getTitle(graph); metadata.setTitle(title); } private String getTitle(final Graph graph) { final Node<Definition<BPMNDiagram>, ?> diagramNode = getFirstDiagramNode(graph); final BPMNDiagram diagramBean = null != diagramNode ? (BPMNDiagram) ((Definition) diagramNode.getContent()).getDefinition() : null; return getTitle(diagramBean); } private String getTitle(final BPMNDiagram diagram) { final String title = diagram.getDiagramSet().getName().getValue(); return title != null && title.trim().length() > 0 ? title : "-- Untitled diagram --"; } @SuppressWarnings("unchecked") private Node<Definition<BPMNDiagram>, ?> getFirstDiagramNode(final Graph graph) { return GraphUtils.getFirstNode(graph, getDiagramDefinitionClass()); } private String getRootUUID(final Graph graph) { final Node diagramNode = getFirstDiagramNode(graph); return null != diagramNode ? diagramNode.getUUID() : null; } private Definitions parseDefinitions(final InputStream inputStream) throws IOException { try { DroolsPackageImpl.init(); BpsimPackageImpl.init(); final ResourceSet resourceSet = new ResourceSetImpl(); resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(Resource.Factory.Registry.DEFAULT_EXTENSION, new JBPMBpmn2ResourceFactoryImpl()); resourceSet.getPackageRegistry().put("http://www.omg.org/spec/BPMN/20100524/MODEL", Bpmn2Package.eINSTANCE); resourceSet.getPackageRegistry().put("http://www.jboss.org/drools", DroolsPackage.eINSTANCE); final JBPMBpmn2ResourceImpl resource = (JBPMBpmn2ResourceImpl) resourceSet.createResource(URI.createURI("inputStream://dummyUriWithValidSuffix.xml")); resource.getDefaultLoadOptions().put(JBPMBpmn2ResourceImpl.OPTION_ENCODING, "UTF-8"); resource.setEncoding("UTF-8"); final Map<String, Object> options = new HashMap<String, Object>(); options.put(JBPMBpmn2ResourceImpl.OPTION_ENCODING, "UTF-8"); options.put(JBPMBpmn2ResourceImpl.OPTION_DEFER_IDREF_RESOLUTION, true); options.put(JBPMBpmn2ResourceImpl.OPTION_DISABLE_NOTIFY, true); options.put(JBPMBpmn2ResourceImpl.OPTION_PROCESS_DANGLING_HREF, JBPMBpmn2ResourceImpl.OPTION_PROCESS_DANGLING_HREF_RECORD); resource.load(inputStream, options); final DocumentRoot root = (DocumentRoot) resource.getContents().get(0); return root.getDefinitions(); } catch (Exception e) { e.printStackTrace(); } finally { if (inputStream != null) { inputStream.close(); } } return null; } @Override public DiagramMetadataMarshaller<Metadata> getMetadataMarshaller() { return diagramMetadataMarshaller; } }