Switch to side-by-side view

--- a/src/main/java/net/timbusproject/extractors/modules/tavernaextractor/TavernaExtractor.java
+++ b/src/main/java/net/timbusproject/extractors/modules/tavernaextractor/TavernaExtractor.java
@@ -29,12 +29,15 @@
 import net.sf.taverna.t2.activities.dataflow.DataflowActivity;
 import net.sf.taverna.t2.activities.externaltool.ExternalToolActivity;
 import net.sf.taverna.t2.activities.externaltool.ExternalToolActivityConfigurationBean;
+import net.sf.taverna.t2.activities.localworker.LocalworkerActivity;
 import net.sf.taverna.t2.activities.rest.RESTActivity;
 import net.sf.taverna.t2.activities.rshell.RshellActivity;
 import net.sf.taverna.t2.activities.rshell.RshellActivityConfigurationBean;
 import net.sf.taverna.t2.activities.wsdl.WSDLActivity;
 import net.sf.taverna.t2.activities.wsdl.xmlsplitter.XMLInputSplitterActivity;
 import net.sf.taverna.t2.activities.wsdl.xmlsplitter.XMLOutputSplitterActivity;
+import net.sf.taverna.t2.activities.xpath.XPathActivity;
+import net.sf.taverna.t2.activities.xpath.XPathActivityConfigurationBean;
 import net.sf.taverna.t2.commandline.CommandLineLauncher;
 import net.sf.taverna.t2.commandline.exceptions.DatabaseConfigurationException;
 import net.sf.taverna.t2.commandline.exceptions.InvalidOptionException;
@@ -179,6 +182,7 @@
     private IApplicationFunction callXMLSplitterApplicationFunction = null;
     private IApplicationFunction callWebServiceApplicationFunction = null;
     private IApplicationFunction callToolInvocationFunction = null;
+    private IApplicationFunction callXPathApplicationFunction = null;
 
     private Dataflow dataflow;
     private SSHManager sshManager;
@@ -206,52 +210,52 @@
     /*
      * // GETTER & SETTER ///////////////
      */
-    public static void setDotLocation(Path dotLocation) {
+    public void setDotLocation(Path dotLocation) {
         TavernaExtractor.dotLocation = dotLocation;
     }
 
-    public static Path getDotLocation() {
+    public Path getDotLocation() {
         return dotLocation;
     }
 
-    public static Path getArchimateOutputPath() {
+    public Path getArchimateOutputPath() {
         return archimateOutputPath;
     }
 
-    public static void setArchimateOutputPath(Path archimateOutputPath) {
+    public void setArchimateOutputPath(Path archimateOutputPath) {
         TavernaExtractor.archimateOutputPath = archimateOutputPath;
     }
 
-    public static Path getInputFileName() {
+    public Path getInputFileName() {
         return inputFileName;
     }
 
-    public static void setInputFileName(Path inputFileName) {
+    public void setInputFileName(Path inputFileName) {
         TavernaExtractor.inputFileName = inputFileName;
     }
 
-    public static Path getTavernaHome() {
+    public Path getTavernaHome() {
         return tavernaHome;
     }
 
-    public static void setTavernaHome(Path tavernaHome) {
+    public void setTavernaHome(Path tavernaHome) {
 
         TavernaExtractor.tavernaHome = tavernaHome;
     }
 
-    public static Path getTavernaHomeLib() {
+    public Path getTavernaHomeLib() {
         return tavernaHomeLib;
     }
 
-    public static void setTavernaHomeLib(Path tavernaHomeLib) {
+    public void setTavernaHomeLib(Path tavernaHomeLib) {
         TavernaExtractor.tavernaHomeLib = tavernaHomeLib;
     }
 
-    public static Path getTavernaHomeRepo() {
+    public Path getTavernaHomeRepo() {
         return tavernaHomeRepo;
     }
 
-    public static void setTavernaHomeRepo(Path tavernaHomeRepo) {
+    public void setTavernaHomeRepo(Path tavernaHomeRepo) {
         TavernaExtractor.tavernaHomeRepo = tavernaHomeRepo;
     }
 
@@ -281,19 +285,19 @@
         LOGGER.info("Start Taverna Extractor ...");
 
         //setup
-        TavernaExtractor.setTavernaHomeLib(TavernaExtractor.getTavernaHome().resolve("lib"));
-        TavernaExtractor.setTavernaHomeRepo(TavernaExtractor.getTavernaHome().resolve("repository"));
+        this.setTavernaHomeLib(this.getTavernaHome().resolve("lib"));
+        this.setTavernaHomeRepo(this.getTavernaHome().resolve("repository"));
 
         if (remote)
-            validateRemoteDirectories(TavernaExtractor.getTavernaHome(), TavernaExtractor.getTavernaHomeLib(), TavernaExtractor.getTavernaHomeRepo());
+            validateRemoteDirectories(this.getTavernaHome(), this.getTavernaHomeLib(), this.getTavernaHomeRepo());
         else
-            validateDirectories(TavernaExtractor.getTavernaHome(), TavernaExtractor.getTavernaHomeLib(), TavernaExtractor.getTavernaHomeRepo());
-
-        LOGGER.info("TavernaHome is set to [" + TavernaExtractor.getTavernaHome() + "].");
-        LOGGER.info("TavernaHomeLib is set to [" + TavernaExtractor.getTavernaHomeLib() + "].");
-        LOGGER.info("TavernaHomeRepo is set to [" + TavernaExtractor.getTavernaHomeRepo() + "].");
-        LOGGER.info("Workflow input file is [" + TavernaExtractor.getInputFileName() + "].");
-        LOGGER.info("Archimate output file is [" + TavernaExtractor.getArchimateOutputPath() + "].");
+            validateDirectories(this.getTavernaHome(), this.getTavernaHomeLib(), this.getTavernaHomeRepo());
+
+        LOGGER.info("TavernaHome is set to [" + this.getTavernaHome() + "].");
+        LOGGER.info("TavernaHomeLib is set to [" + this.getTavernaHomeLib() + "].");
+        LOGGER.info("TavernaHomeRepo is set to [" + this.getTavernaHomeRepo() + "].");
+        LOGGER.info("Workflow input file is [" + this.getInputFileName() + "].");
+        LOGGER.info("Archimate output file is [" + this.getArchimateOutputPath() + "].");
 
         inputPorts = new Container(Orientation.VERTICAL);
         outputPorts = new Container(Orientation.VERTICAL);
@@ -397,7 +401,7 @@
         ArchiUtils.initRelation(factory.createCompositionRelationship(), desktop, workflowFile, relationsFolder,
                 relations);
 
-        workflowFile.getProperties().add(createDepProperties(TavernaExtractor.getInputFileName().toString()));
+        workflowFile.getProperties().add(createDepProperties(this.getInputFileName().toString()));
 
         // Orchestration Service
         parentProcessWorkflow = ArchiUtils.initElement(factory.createBusinessProcess(), dataflow.getLocalName()
@@ -421,12 +425,12 @@
         ArchiUtils.initRelation(factory.createCompositionRelationship(), desktop, repoBundle,
                 relationsFolder, relations);
 
-        if (TavernaExtractor.getTavernaHomeRepo().toFile().isDirectory()) {
+        if (this.getTavernaHomeRepo().toFile().isDirectory()) {
 
             final List<File> jarFiles = new ArrayList<>();
             final PathMatcher matcher = FileSystems.getDefault()
                     .getPathMatcher("glob:*.jar");
-            Files.walkFileTree(TavernaExtractor.getTavernaHomeRepo(), new FileVisitor<Path>() {
+            Files.walkFileTree(this.getTavernaHomeRepo(), new FileVisitor<Path>() {
                 @Override
                 public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
                     return CONTINUE;
@@ -457,7 +461,7 @@
                 repoBundle.getProperties().add(createDepProperties(jarLocation));
             }
         } else {
-            LOGGER.error("ERROR: " + TavernaExtractor.getTavernaHomeRepo().toFile() + " is not a directory. No further dependecies processing.");
+            LOGGER.error("ERROR: " + this.getTavernaHomeRepo().toFile() + " is not a directory. No further dependecies processing.");
         }
         // --- END Taverna ---
 
@@ -930,7 +934,7 @@
         if (callXMLSplitterApplicationFunction == null) {
 
             callXMLSplitterApplicationFunction = ArchiUtils.initElement(factory.createApplicationFunction(),
-                    "XML Splitter", applicationFolder, applicationComponents);
+                    "XML Splitter Built-In Service", applicationFolder, applicationComponents);
 
             ArchiUtils.initRelation(factory.createAssignmentRelationship(), callXMLSplitterApplicationFunction,
                     workflowApplicationComponent, relationsFolder, relations);
@@ -950,14 +954,112 @@
         ArchiUtils.initRelation(factory.createUsedByRelationship(), callXMLSplitterApplicationFunction,
                 processorProcessMap.get(processor), relationsFolder, relations);
 
-//        IArtifact script = (IArtifact) ArchiUtils.initElement(factory.createArtifact(), processor.getLocalName()
-//                + "Script", infrastructureFolder, nodeElements);
-
-//        ArchiUtils.initRelation(factory.createCompositionRelationship(), workflowFile, script, relationsFolder,
-//                relations);
-
-//        ArchiUtils
-//                .initRelation(factory.createRealisationRelationship(), script, appService, relationsFolder, relations);
+        LOGGER.debug("Get input elements of process "+ArchiUtils.getInputElementsOfProcess(processorProcessMap.get(processor),
+                relations).size());
+        // creating request response data objects
+        for (IArchimateElement inputElement : ArchiUtils.getInputElementsOfProcess(processorProcessMap.get(processor),
+                relations)) {
+
+            LOGGER.debug("inputElement = "+inputElement.getName());
+
+            if (!business2dataMap.containsKey(inputElement)) {
+
+                IDataObject requestObject = ArchiUtils.initElement(factory.createDataObject(), inputElement.getName(),
+                        applicationFolder, applicationComponents);
+
+                business2dataMap.put((IBusinessObject) inputElement, requestObject);
+
+                ArchiUtils.initRelation(factory.createRealisationRelationship(), requestObject, inputElement,
+                        relationsFolder, relations);
+            }
+            ArchiUtils.initAccessRelation(factory.createAccessRelationship(), appService,
+                    business2dataMap.get(inputElement), applicationFolder, relations, IAccessRelationship.READ_ACCESS);
+
+        }
+
+        LOGGER.debug("Get output elements of process "+ArchiUtils.getInputElementsOfProcess(processorProcessMap.get(processor),
+                relations).size());
+        for (IArchimateElement outputElement : ArchiUtils.getOutputElementsOfProcess(
+                processorProcessMap.get(processor), relations)) {
+
+            LOGGER.debug("inputElement = "+outputElement.getName());
+
+            if (!business2dataMap.containsKey(outputElement)) {
+
+                IDataObject responseObject = ArchiUtils.initElement(factory.createDataObject(),
+                        outputElement.getName(), applicationFolder, applicationComponents);
+
+                ArchiUtils.initRelation(factory.createRealisationRelationship(), responseObject, outputElement,
+                        relationsFolder, relations);
+
+                business2dataMap.put((IBusinessObject) outputElement, responseObject);
+            }
+
+            ArchiUtils
+                    .initAccessRelation(factory.createAccessRelationship(), appService,
+                            business2dataMap.get(outputElement), applicationFolder, relations,
+                            IAccessRelationship.WRITE_ACCESS);
+
+        }
+    }
+
+    public void processXPathActivity(IFolder infrastructureFolder, IFolder motivationFolder,
+                                         IFolder applicationFolder, IFolder relationsFolder, IApplicationComponent workflowApplicationComponent,
+                                         HashMap<Processor, IBusinessProcess> processorProcessMap, Processor processor, Activity<?> a)
+            throws IOException {
+
+        //beanshellScripts.add((BeanshellActivity) a);
+
+        LOGGER.debug("XPath script found = " + processor.getLocalName());
+
+        //XPathActivity xPathActivity = (XPathActivity) a;
+
+        // create external application service for each business process/function
+        if (callXPathApplicationFunction == null) {
+
+            callXPathApplicationFunction = ArchiUtils.initElement(factory.createApplicationFunction(),
+                    "XPath Built-In Service", applicationFolder, applicationComponents);
+
+            ArchiUtils.initRelation(factory.createAssignmentRelationship(), callXPathApplicationFunction,
+                    workflowApplicationComponent, relationsFolder, relations);
+
+            ArchiUtils.initRelation(factory.createRealisationRelationship(), taverna, callXPathApplicationFunction,
+                    relationsFolder, relations);
+        }
+
+        IApplicationService appService = ArchiUtils.initElement(factory.createApplicationService(),
+                processor.getLocalName(), applicationFolder, externalApplicationServices);
+
+        appService.getProperties().add(createDepProperties(BeanshellActivity.class));
+
+        ArchiUtils.initRelation(factory.createUsedByRelationship(), appService, processorProcessMap.get(processor),
+                relationsFolder, relations);
+
+        ArchiUtils.initRelation(factory.createUsedByRelationship(), callXPathApplicationFunction,
+                processorProcessMap.get(processor), relationsFolder, relations);
+
+        IArtifact script = (IArtifact) ArchiUtils.initElement(factory.createArtifact(), processor.getLocalName()
+                , infrastructureFolder, nodeElements);
+
+       XPathActivityConfigurationBean c =  (XPathActivityConfigurationBean) a.getConfiguration();
+       String ex = c.getXpathExpression() != null ? c.getXpathExpression() : "NO_EXPRESSION_AVAILABLE";
+       String doc = c.getXmlDocument() != null ? c.getXmlDocument() : "NO_XML_DOCUMENT_AVAILABLE";
+
+       IProperty property = factory.createProperty();
+       property.setKey("expression");
+       property.setValue(ex);
+       script.getProperties().add(property);
+
+       IProperty property_document = factory.createProperty();
+       property_document.setKey("document");
+       property_document.setValue(doc);
+       script.getProperties().add(property_document);
+
+       ArchiUtils.initRelation(factory.createCompositionRelationship(), workflowFile, script, relationsFolder,
+                relations);
+
+       ArchiUtils
+                .initRelation(factory.createRealisationRelationship(), script, appService, relationsFolder, relations);
 
         // creating request response data objects
         for (IArchimateElement inputElement : ArchiUtils.getInputElementsOfProcess(processorProcessMap.get(processor),
@@ -1097,14 +1199,14 @@
                 IArtifact beanshellScriptDep = (IArtifact) ArchiUtils.initElement(factory.createArtifact(), item,
                         infrastructureFolder, nodeElements);
 
-                ArchiUtils.initRelationNodeElement(factory.createAssociationRelationship(), script, beanshellScriptDep,
-                        relationsFolder, nodeElements);
-
-                ArchiUtils.initRelationNodeElement(factory.createCompositionRelationship(), beanshellScriptDep, desktop,
-                        relationsFolder, nodeElements);
+                ArchiUtils.initRelation(factory.createAssociationRelationship(), script, beanshellScriptDep,
+                        relationsFolder);
+
+                ArchiUtils.initRelation(factory.createCompositionRelationship(), beanshellScriptDep, desktop,
+                        relationsFolder);
 
                 // Do the license checking
-                String fileName = TavernaExtractor.getTavernaHomeLib() + File.separator + item;
+                String fileName = this.getTavernaHomeLib() + File.separator + item;
 
                 IProperty jarLocation = factory.createProperty();
                 jarLocation.setKey("hasSourceLocation");
@@ -1759,10 +1861,23 @@
             }
         }
 
+        //TODO: needs improvements -> hasNoPrecedentProcessor not working if only one non-constant value processor exists!!
         List<Processor> startingProcessors = new ArrayList<Processor>();
         for (Processor processor : dataflow.getProcessors()) {
 
-            // detect if first step processor
+            if (ArchiUtils.isValueProcessor(processor)) {
+                break;
+            }
+            else{
+                startingProcessors.add(processor);
+            }
+        }
+        if(startingProcessors.size() == 1){
+            return startingProcessors;
+        }
+
+        startingProcessors = new ArrayList<Processor>();
+        for (Processor processor : dataflow.getProcessors()) {
 
             if (ArchiUtils.isValueProcessor(processor)) {
                 break;
@@ -1844,7 +1959,7 @@
             // Dot to SVG
             File svgTmp = new File(tmpDirPath + File.separator + "tavernaExtractorToArchimate.dot.svg");
 
-            String[] COMMAND = {TavernaExtractor.getDotLocation().toString(), "-Tsvg", dotTmp.getAbsolutePath(), "-o", svgTmp.getAbsolutePath()};
+            String[] COMMAND = {this.getDotLocation().toString(), "-Tsvg", dotTmp.getAbsolutePath(), "-o", svgTmp.getAbsolutePath()};
 
             LOGGER.debug("Running command '" + StringUtils.join(COMMAND, " ") + "'.");
 
@@ -1967,13 +2082,13 @@
 
                 // TODO UnrecognizedActivity detected !!
                 if (a instanceof UnrecognizedActivity) {
-                    LOGGER.error("PROBLEM: UnrecognizedActivity detected! ");
+                    LOGGER.error("\tPROBLEM: UnrecognizedActivity detected! ");
                 }
                 // TODO DisabledActivity detected !!
                 // From the javadoc: A disabled activity is a wrapper for an Activity that is offline or similarly
                 // disabled
                 else if (a instanceof DisabledActivity) {
-                    LOGGER.error("PROBLEM: DisabledActivity detected! ");
+                    LOGGER.error("\tPROBLEM: DisabledActivity detected! ");
                     // TODO: create a note element with information
                 }
 
@@ -2036,6 +2151,19 @@
                 }
                 else if (a instanceof XMLInputSplitterActivity || a instanceof XMLOutputSplitterActivity) {
                     processXMLSplitterActivity(infrastructureFolder, motivationFolder, applicationFolder,
+                            relationsFolder, workflowApplicationComponent, processorProcessMap, processor, a);
+                }
+                else if (a instanceof XPathActivity){
+                    LOGGER.info("XPathActivity has to be done");
+                    processXPathActivity(infrastructureFolder, motivationFolder, applicationFolder,
+                            relationsFolder, workflowApplicationComponent, processorProcessMap, processor, a);
+                }
+                else if (a instanceof LocalworkerActivity){
+
+                    /*
+                          Localworker Activity equals BeanshellActivity ?!
+                     */
+                    processBeanshellActivity(infrastructureFolder, motivationFolder, applicationFolder,
                             relationsFolder, workflowApplicationComponent, processorProcessMap, processor, a);
                 }
                 else{
@@ -2302,7 +2430,6 @@
                 }
             }
         }
-
     }
 
     private Dataflow getDataflowRemote() throws TavernaExtractorException {
@@ -2355,7 +2482,7 @@
     private void saveRemote(IArchimateModel model) throws TavernaExtractorException {
 
         // Set new file
-        File outFile = TavernaExtractor.getArchimateOutputPath().toFile();
+        File outFile = this.getArchimateOutputPath().toFile();
         model.setFile(outFile);
 
         // Set model version
@@ -2404,7 +2531,7 @@
     private void saveLocal(IArchimateModel model) throws IOException {
 
         // Set new file
-        File outFile = TavernaExtractor.getArchimateOutputPath().toFile();
+        File outFile = this.getArchimateOutputPath().toFile();
         model.setFile(outFile);
 
         // Set model version