Switch to side-by-side view

--- a
+++ b/src/net/timbusproject/context/converter/OWLExport.java
@@ -0,0 +1,347 @@
+/**
+ * Copyright (c) 2013/2014 Verein zur Foerderung der IT-Sicherheit in Oesterreich (SBA).
+ * The work has been developed in the TIMBUS Project and the above-mentioned are Members of the TIMBUS Consortium.
+ * TIMBUS is supported by the European Union under the 7th Framework Programme for research and technological
+ * development and demonstration activities (FP7/2007-2013) under grant agreement no. 269940.
+ *
+ * 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, including without
+ * limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTIBITLY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise,
+ * unless required by applicable law or agreed to in writing, shall any Contributor be liable for damages, including
+ * any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this
+ * License or out of the use or inability to use the Work.
+ * See the License for the specific language governing permissions and limitation under the License.
+ */
+
+package net.timbusproject.context.converter;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.semanticweb.owlapi.apibinding.OWLManager;
+import org.semanticweb.owlapi.io.FileDocumentTarget;
+import org.semanticweb.owlapi.io.OWLXMLOntologyFormat;
+import org.semanticweb.owlapi.model.AddAxiom;
+import org.semanticweb.owlapi.model.AddImport;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLAnnotation;
+import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLDataFactory;
+import org.semanticweb.owlapi.model.OWLDataProperty;
+import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLDeclarationAxiom;
+import org.semanticweb.owlapi.model.OWLImportsDeclaration;
+import org.semanticweb.owlapi.model.OWLLiteral;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.model.OWLObjectProperty;
+import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLOntologyCreationException;
+import org.semanticweb.owlapi.model.OWLOntologyManager;
+import org.semanticweb.owlapi.model.OWLOntologyStorageException;
+import org.semanticweb.owlapi.vocab.OWL2Datatype;
+
+import uk.ac.bolton.archimate.editor.model.viewpoints.IViewpoint;
+import uk.ac.bolton.archimate.model.FolderType;
+import uk.ac.bolton.archimate.model.IAccessRelationship;
+import uk.ac.bolton.archimate.model.IArchimateElement;
+import uk.ac.bolton.archimate.model.IArchimateModel;
+import uk.ac.bolton.archimate.model.IDiagramModelObject;
+import uk.ac.bolton.archimate.model.IFolder;
+import uk.ac.bolton.archimate.model.IProperty;
+import uk.ac.bolton.archimate.model.IRelationship;
+import uk.ac.bolton.archimate.model.impl.ArchimateDiagramModel;
+import uk.ac.bolton.archimate.model.impl.DiagramModelArchimateObject;
+import uk.ac.bolton.archimate.model.impl.DiagramModelGroup;
+import uk.ac.manchester.cs.owl.owlapi.OWL2DatatypeImpl;
+
+/**
+ * Methods to export an Archimate Model to OWL (Web Ontology Language)
+ * 
+ * @author Rudolf Mayer (rmayer@sba-research.org)
+ */
+public class OWLExport {
+
+    private static final String SCENARIOS_URL = "ScenariosURL";
+
+    private static final String DIOURL = "DIOURL";
+
+    public static final Properties owlExportProperties = new Properties();
+
+    static {
+        String propertiesFileName = "owlExport.properties";
+        URL resource = OWLExportPlugin.class.getResource(propertiesFileName);
+
+        try {
+            owlExportProperties.load(resource.openStream());
+            System.out.println();
+            System.out.println("\nLoaded OWL Export properties from " + resource);
+            System.out.println("Properties:");
+            System.out.println(owlExportProperties);
+            System.out.println("------------------------------\n");
+        } catch (Exception e) {
+            System.err.println("\nCould not load OWL Export properties, tried file with name '" + propertiesFileName
+                    + "'.");
+            e.printStackTrace();
+
+            // default: using the TIMBUS scenarios URL
+            owlExportProperties.put(SCENARIOS_URL, "http://timbus.teco.edu/ontologies/Scenarios/");
+            owlExportProperties.put(DIOURL, "http://timbus.teco.edu/ontologies/DIO.owl");
+            System.out.println("==> Using default properties:");
+            System.out.println("\t" + owlExportProperties);
+            System.out.println();
+        }
+
+    }
+
+    /** a mapping of some Archimate relation names to the OWL names */
+    public static final HashMap<String, String> propertyNamesMap = new HashMap<String, String>();
+    static {
+        propertyNamesMap.put("access", "accesses");
+        propertyNamesMap.put("aggregation", "aggregates");
+        propertyNamesMap.put("assignment", "assignment");
+        propertyNamesMap.put("composition", "composedOf");
+        propertyNamesMap.put("flow", "flowTo");
+        propertyNamesMap.put("influence", "influencedBy");
+        propertyNamesMap.put("realisation", "realizes");
+        propertyNamesMap.put("specialisation", "specialization");
+        propertyNamesMap.put("triggering", "triggers");
+        propertyNamesMap.put("usedby", "usedBy");
+    }
+
+    /** subtypes of the relation "access" */
+    public static final String[] relationAccessTypes = { "hasAccessTypeWrite", "hasAccessTypeRead",
+            "hasAccessTypeAccess", "hasAccessTypeRead_Write" };
+
+    /** the default property names */
+    public static final String DEFAULT_PROPERTY = "association";
+
+    /** The URL of the TIMBUS DIO */
+    public static final String TIMBUS_DIO_URL = owlExportProperties.getProperty(DIOURL);
+
+    /** The IRI for the TIMBUS DIO, see {@link #TIMBUS_DIO_URL} */
+    public static final IRI TIMBUS_DIO_IRI = IRI.create(TIMBUS_DIO_URL);
+
+    /** Prefix on the OWL name */
+    public static final String SCENARIOS_PREFIX = owlExportProperties.getProperty(SCENARIOS_URL);
+
+    /** The types of folders in Archi */
+    public static final FolderType[] FOLDER_TYPES = { FolderType.BUSINESS, FolderType.APPLICATION,
+            FolderType.TECHNOLOGY, FolderType.MOTIVATION, FolderType.IMPLEMENTATION_MIGRATION, FolderType.CONNECTORS,
+            FolderType.RELATIONS };
+
+    public static void exportToOwl(IArchimateModel model, File file) throws IOException {
+
+        // create Ontology manager
+        OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
+        OWLDataFactory df = OWLManager.getOWLDataFactory();
+
+        String iriThisOntology = getDefaultIRI(file);
+        OWLOntology ontology;
+        try {
+            ontology = manager.createOntology(IRI.create(iriThisOntology));
+        } catch (OWLOntologyCreationException e) {
+            e.printStackTrace();
+            throw new IOException(e);
+        }
+
+        // import the DIO
+        OWLImportsDeclaration importDeclaraton = df.getOWLImportsDeclaration(TIMBUS_DIO_IRI);
+        manager.applyChange(new AddImport(ontology, importDeclaraton));
+
+        Set<OWLAnnotation> emptyAnnotations = Collections.<OWLAnnotation> emptySet();
+
+        for (FolderType folderType : FOLDER_TYPES) {
+            IFolder folder = model.getFolder(folderType);
+
+            List<EObject> elements = new ArrayList<EObject>((int) (folder.getElements().size() * 1.2));
+            Util.getElements(folder, elements);
+            for (EObject eObject : elements) {
+
+                if (eObject instanceof IArchimateElement) {
+                    IArchimateElement element = (IArchimateElement) eObject;
+
+                    String elementName = element.getId();
+                    String elementClassName = element.eClass().getName();
+
+                    if (eObject instanceof IRelationship) { // write relationships
+                        IRelationship relationship = (IRelationship) eObject;
+
+                        String sourceName = relationship.getSource().getId();
+                        String tagetName = relationship.getTarget().getId();
+
+                        OWLNamedIndividual source = df.getOWLNamedIndividual(IRI.create("#" + sourceName));
+                        OWLNamedIndividual object = df.getOWLNamedIndividual(IRI.create("#" + tagetName));
+
+                        // derive the name of the relation from the class name
+                        String propertyName = relationship.eClass().getName().replace("Relationship", "");
+                        if (propertyNamesMap.containsKey(propertyName.toLowerCase())) {
+                            // some relations have a mapping to a better name
+                            propertyName = propertyNamesMap.get(propertyName.toLowerCase());
+                        } else {
+                            propertyName = DEFAULT_PROPERTY;
+                        }
+
+                        if (eObject instanceof IAccessRelationship) {
+                            // access relations have several subtypes, we add the correct name here
+                            IAccessRelationship accessRelationship = (IAccessRelationship) eObject;
+                            int accesstype = accessRelationship.getAccessType();
+                            propertyName = relationAccessTypes[accesstype];
+                        }
+
+                        OWLObjectProperty property = df.getOWLObjectProperty(IRI.create(TIMBUS_DIO_URL + "#"
+                                + propertyName));
+
+                        OWLObjectPropertyAssertionAxiom objectPropertyAssertion = df
+                                .getOWLObjectPropertyAssertionAxiom(property, source, object);
+                        manager.applyChange(new AddAxiom(ontology, objectPropertyAssertion));
+
+                    } else { // write individuals (and data properties)
+
+                        // writes the indiv with the ID as name
+                        OWLNamedIndividual indiv = df.getOWLNamedIndividual(IRI.create("#" + elementName));
+                        OWLDeclarationAxiom indivDeclaration = df.getOWLDeclarationAxiom(indiv);
+                        manager.applyChange(new AddAxiom(ontology, indivDeclaration));
+
+                        // add an rdfs:label property as annotation
+                        String labelName = formatString(Util.replaceSpecialWhiteSpace(element.getName()));
+                        OWLAnnotation annotation = df.getOWLAnnotation(df.getRDFSLabel(), df.getOWLLiteral(labelName));
+                        OWLAnnotationAssertionAxiom annotationAssertionAxiom = df.getOWLAnnotationAssertionAxiom(
+                                indiv.getIRI(), annotation);
+                        manager.applyChange(new AddAxiom(ontology, annotationAssertionAxiom));
+
+                        // add a class expression
+                        OWLClass classExpression = df.getOWLClass(IRI.create(TIMBUS_DIO_URL + "#" + elementClassName));
+                        OWLClassAssertionAxiom classAssertion = df.getOWLClassAssertionAxiom(classExpression, indiv);
+                        manager.applyChange(new AddAxiom(ontology, classAssertion));
+
+                        if (!element.getProperties().isEmpty()) { // add data properties
+                            for (IProperty eProperty : element.getProperties()) {
+                                OWLDataProperty property = df.getOWLDataProperty(IRI.create(TIMBUS_DIO_URL + "#"
+                                        + eProperty.getKey()));
+                                OWLLiteral owlLiteral = df.getOWLLiteral(eProperty.getValue(),
+                                        OWL2DatatypeImpl.getDatatype(OWL2Datatype.RDF_PLAIN_LITERAL));
+                                OWLDataPropertyAssertionAxiom dataPropertyAssertion = df
+                                        .getOWLDataPropertyAssertionAxiom(property, indiv, owlLiteral, emptyAnnotations);
+                                manager.applyChange(new AddAxiom(ontology, dataPropertyAssertion));
+                            }
+                        }
+                    }
+                }
+
+            }
+
+        }
+
+        FileDocumentTarget fileTarget = new FileDocumentTarget(file);
+        try {
+            manager.saveOntology(ontology, new OWLXMLOntologyFormat(), fileTarget);
+        } catch (OWLOntologyStorageException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public static String getDefaultIRI(File file) {
+        return SCENARIOS_PREFIX + file.getName();
+    }
+
+    public static void exportLayout(IArchimateModel model, File layoutFile, File owlFile) throws FileNotFoundException {
+        exportLayout(layoutFile, getDefaultIRI(owlFile), getLayeredView(model));
+    }
+
+    /** Exports the layout of the layered view ({@link IViewpoint#LAYERED_VIEWPOINT}) of a model to a CSV separated file */
+    public static void exportLayout(IArchimateModel model, File layoutFile, String defaultIRI)
+            throws FileNotFoundException {
+        exportLayout(layoutFile, defaultIRI, getLayeredView(model));
+    }
+
+    /** Exports the layout of a model to a CSV separated file */
+    public static void exportLayout(File layoutFile, String defaultIRI, ArchimateDiagramModel layeredView)
+            throws FileNotFoundException {
+        if (layeredView != null) {
+            EList<IDiagramModelObject> children = layeredView.getChildren();
+
+            ArrayList<String> export = new ArrayList<String>();
+            exportChildrenLayout(children, 0, 0, export, defaultIRI);
+            Collections.sort(export);
+
+            PrintWriter pw = new PrintWriter(layoutFile);
+            for (String string : export) {
+                pw.println(string);
+            }
+
+            pw.flush();
+            pw.close();
+        }
+    }
+
+    public static ArchimateDiagramModel getLayeredView(IArchimateModel model) {
+        IFolder diagramFolder = model.getFolder(FolderType.DIAGRAMS);
+        ArchimateDiagramModel layeredView = null;
+
+        for (EObject eObject : diagramFolder.getElements()) {
+            if (eObject instanceof ArchimateDiagramModel) {
+                ArchimateDiagramModel diagramModel = (ArchimateDiagramModel) eObject;
+                if (diagramModel.getViewpoint() == IViewpoint.LAYERED_VIEWPOINT) {
+                    layeredView = diagramModel;
+                }
+            }
+        }
+        return layeredView;
+    }
+
+    public static File getDefaultLayoutFile(File file) {
+        return new File(file.getAbsolutePath() + ".layout.csv");
+    }
+
+    private static void exportChildrenLayout(EList<IDiagramModelObject> children, int x, int y,
+            ArrayList<String> export, String iriPrefix) {
+        for (IDiagramModelObject diagramModelObject : children) {
+
+            int coordX = x + diagramModelObject.getBounds().getX();
+            int coordY = y + diagramModelObject.getBounds().getY();
+            if (diagramModelObject instanceof DiagramModelGroup) {
+                exportChildrenLayout(((DiagramModelGroup) diagramModelObject).getChildren(), coordX, coordY, export,
+                        iriPrefix);
+            } else {
+                String elementName = diagramModelObject.getId();
+                if (diagramModelObject instanceof DiagramModelArchimateObject) {
+                    elementName = ((DiagramModelArchimateObject) diagramModelObject).getArchimateElement().getId();
+                }
+                StringBuilder sb = new StringBuilder(iriPrefix).append("#").append(elementName).append("\t")
+                        .append(coordX).append("\t").append(coordY);
+
+                if (diagramModelObject instanceof DiagramModelArchimateObject
+                        && ((DiagramModelArchimateObject) diagramModelObject).getChildren() != null
+                        && ((DiagramModelArchimateObject) diagramModelObject).getChildren().size() > 0) {
+                    sb.append("\t").append(diagramModelObject.getBounds().getWidth()).append("\t")
+                            .append(diagramModelObject.getBounds().getHeight());
+                    exportChildrenLayout(((DiagramModelArchimateObject) diagramModelObject).getChildren(), coordX,
+                            coordY, export, iriPrefix);
+                }
+                export.add(sb.toString());
+            }
+        }
+    }
+
+    public static String formatString(String s) {
+        return s.replace(" ", "_").replace("(", "-").replace(")", "-").replace("/", "_");
+    }
+}