Support TOSCA in verigraph (gRPC service) 51/56651/2
authorserena.spinoso <serena.spinoso@polito.it>
Thu, 26 Apr 2018 12:19:16 +0000 (14:19 +0200)
committerserena.spinoso <serena.spinoso@polito.it>
Thu, 26 Apr 2018 12:39:01 +0000 (14:39 +0200)
JIRA: PARSER-179

Add TOSCA service description in gRPC server.
Add a TOSCA-based client to use the new functionality.
Add a JUnit class for testing gRPC service with TOSCA descriptor

Change-Id: Id3217a674f076714cd48e3b7e4236e7445d89cd2
Signed-off-by: serena.spinoso <serena.spinoso@polito.it>
15 files changed:
verigraph/build.xml
verigraph/gRPC-build.xml
verigraph/pom.xml
verigraph/schema/README.rst [new file with mode: 0644]
verigraph/schema/tosca/TOSCA-v1.0.xsd [new file with mode: 0644]
verigraph/schema/tosca/ToscaTypes_XMLconfig.xsd [new file with mode: 0644]
verigraph/schema/tosca/ToscaVerigraphDefinitions.xml [new file with mode: 0644]
verigraph/schema/tosca/yamlToscaDefinitions.yaml [new file with mode: 0644]
verigraph/src/it/polito/verigraph/grpc/client/ToscaClient.java [new file with mode: 0644]
verigraph/src/it/polito/verigraph/grpc/server/GrpcUtils.java
verigraph/src/it/polito/verigraph/grpc/server/Service.java
verigraph/src/it/polito/verigraph/grpc/tosca/test/GrpcToscaTest.java [new file with mode: 0644]
verigraph/src/it/polito/verigraph/tosca/converter/grpc/GraphToGrpc.java [new file with mode: 0644]
verigraph/src/it/polito/verigraph/tosca/converter/grpc/GrpcToGraph.java [new file with mode: 0644]
verigraph/src/main/proto/verigraph.proto

index dae4678..ba576a7 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
- Copyright (c) 2017 Politecnico di Torino and others.
+ Copyright (c) 2017/18 Politecnico di Torino and others.
 
  All rights reserved. This program and the accompanying materials
  are made available under the terms of the Apache License, Version 2.0
@@ -14,6 +14,9 @@
 
   <property name="root.location" location="." />
   <!-- The location to be used for class files -->
+  <property name="docker-grpc.dir" value="${root.location}/docker/gRPC" />
+  <property name="docker-rest.dir" value="${root.location}/docker/REST" />
+  <property name="cli.dir" value="${root.location}/VerigraphCLI" />
   <property name="src.dir" location="${root.location}/src" />
   <property name="gen.dir" location="${root.location}/gen-src" />
   <property name="war.dir" location="${root.location}/war" />
@@ -23,6 +26,9 @@
   <property name="lib.dir" location="${root.location}/lib" />
   <property name="schemadir" location="${root.location}/schema" />
   <property name="schemafile" value="xml_components.xsd" />
+  <property name="toscaschemadir" location="${root.location}/schema/tosca" />
+  <property name="toscaschemafile" value="TOSCA-v1.0.xsd" />
+  <property name="toscaverigraphschemafile" value="ToscaTypes_XMLconfig.xsd" />
   <property name="testfile" value="test.py" />
   <property name="target" value="1.8" />
   <property name="source" value="1.8" />
     <delete file="${lib.dir}/z3-4.5.0-x86-win.zip" />
   </target>
 
-       
-  <target name="-chk-bindings">
-    <uptodate property="generate-bindings.notRequired" targetfile="${src.dir}/.flagfile">
-      <srcfiles dir="${schemadir}" includes="${schemafile}" />
+
+  <target name="chk-bindings">
+    <uptodate property="generate-bindings.notRequired" targetfile="${gen.dir}/.flagfile">
+      <srcresources>
+        <fileset dir="${schemadir}" includes="${schemafile}" />
+        <fileset dir="${toscaschemadir}" includes="${toscaschemafile}" />
+        <fileset dir="${toscaschemadir}" includes="${toscaverigraphschemafile}" />
+      </srcresources>
     </uptodate>
   </target>
 
-       
-  <target name="generate-bindings" unless="generate-bindings.notRequired" depends="init" description="Create the value classes">
+  <target name="generate-bindings" unless="generate-bindings.notRequired" depends="init, chk-bindings" description="Create the value classes">
     <exec executable="xjc" failonerror="true">
       <arg line="-d ${gen.dir} -p it.polito.neo4j.jaxb ${schemadir}/${schemafile}" />
     </exec>
-    <touch file="${src.dir}/.flagfile" />
+    <exec executable="xjc" failonerror="true">
+      <arg line="-d ${gen.dir} -p it.polito.tosca.jaxb ${toscaschemadir}/${toscaschemafile}" />
+    </exec>
+    <mkdir dir="${root.location}/temp-gen" />
+    <exec executable="xjc" failonerror="true">
+      <arg line="-d ${root.location}/temp-gen -p it.polito.tosca.jaxb ${toscaschemadir}/${toscaverigraphschemafile}" />
+    </exec>
+
+    <copy toDir="${gen.dir}/it/polito/tosca/jaxb" overwrite="true">
+      <file name="${root.location}/temp-gen/it/polito/tosca/jaxb/Configuration.java" />
+    </copy>
+    <delete dir="${root.location}/temp-gen" />
+
+    <touch file="${gen.dir}/.flagfile" />
   </target>
 
-       
+
   <!-- The target for compiling the Verigraph application -->
   <target name="build-service" depends="init, generate-bindings, mvn-init">
     <echo>Building verigraph (if needed)...</echo>
     </sequential>
   </macrodef>
 
-       
   <target name="war-exploded" depends="build-service">
     <war-exploded />
   </target>
 
-       
   <target name="generate-war" depends="war-exploded">
     <war destfile="${gen-war.dir}/${serviceName}.war" basedir="${gen-tomcat-service.dir}">
       <exclude name="protoc-dependencies/" />
     </war>
   </target>
 
-       
+  <target name="docker-rest-build" depends="generate-war">
+    <delete file="${docker-rest.dir}/verigraph.war" />
+
+    <copy file="${gen-war.dir}/verigraph.war" toDir="${docker-rest.dir}" />
+  </target>
+
+  <target name="docker-grpc-build" depends="build-service">
+    <delete dir="${docker-grpc.dir}/service_lib" />
+    <mkdir dir="${docker-grpc.dir}/service_lib" />
+
+    <copy toDir="${docker-grpc.dir}/service_lib" flatten="true" overwrite="true">
+      <fileset refid="runtime.fileset" />
+    </copy>
+    <copy file="${lib.dir}/com.microsoft.z3.jar" todir="${docker-grpc.dir}/service_lib" />
+
+    <delete file="${docker-grpc.dir}/server.properties" />
+    <delete dir="${docker-grpc.dir}/jsonschema" />
+    <copy file="${root.location}/server.properties" todir="${docker-grpc.dir}" />
+    <copydir src="${root.location}/jsonschema" dest="${docker-grpc.dir}/jsonschema" />
+
+    <path id="jars.path">
+      <fileset dir="${docker-grpc.dir}">
+        <include name="service_lib/*.jar" />
+      </fileset>
+    </path>
+
+    <pathconvert property="jars.mf" pathsep=" ">
+      <path refid="jars.path" />
+      <flattenmapper />
+      <map from="" to="service_lib/" />
+    </pathconvert>
+
+    <delete file="${docker-grpc.dir}/service.jar"/>
+    <jar destfile="${docker-grpc.dir}/service.jar">
+      <manifest>
+        <attribute name="Main-Class" value="it.polito.verigraph.grpc.server.Service"/>
+        <attribute name="Class-Path" value="${jars.mf}"/>
+      </manifest>
+      <fileset dir="${root.location}/build"/>
+    </jar>
+  </target>
+
+
+  <target name="build-cli-jar" depends="build-service">
+    <delete dir="${cli.dir}" />
+    <mkdir dir="${cli.dir}" />
+
+    <copy toDir="${cli.dir}/service_lib" flatten="true" overwrite="true">
+      <fileset refid="runtime.fileset" />
+    </copy>
+    <copy file="${src.dir}/it/polito/verigraph/tosca/README_CLI.txt" todir="${cli.dir}" />
+
+    <path id="jars.path">
+      <fileset dir="${cli.dir}">
+        <include name="service_lib/*.jar" />
+      </fileset>
+    </path>
+
+    <pathconvert property="jars.mf" pathsep=" ">
+      <path refid="jars.path" />
+      <flattenmapper />
+      <map from="" to="service_lib/" />
+    </pathconvert>
+
+    <delete file="${cli.dir}/VerigraphCLI.jar"/>
+    <jar destfile="${cli.dir}/VerigraphCLI.jar">
+      <manifest>
+        <attribute name="Main-Class" value="it.polito.verigraph.tosca.ToscaCLI"/>
+        <attribute name="Class-Path" value="${jars.mf}"/>
+      </manifest>
+      <fileset dir="${root.location}/build"/>
+    </jar>
+  </target>
+
   <!-- launch test python test -->
   <target name="run-test">
     <exec dir="${test.dir}" executable="python">
     </exec>
   </target>
 
-
-
   <!-- target for cleaning -->
   <target name="clean">
     <delete dir="${build.dir}" />
     <delete dir="${gen-tomcat-service.dir}" />
     <delete dir="${war.dir}" />
     <delete dir="${lib.dir}" />
+    <delete dir="${docker-grpc.dir}/service_lib" />
+    <delete dir="${docker-grpc.dir}/jsonschema" />
+    <delete file="${docker-grpc.dir}/server.properties" />
+    <delete file="${docker-grpc.dir}/service.jar" />
+    <delete file="${docker-rest.dir}/verigraph.war" />
+    <delete dir="${cli.dir}" />
   </target>
 
-
 </project>
\ No newline at end of file
index 7ff5549..50483c8 100644 (file)
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
  Copyright (c) 2017 Politecnico di Torino and others.
-
  All rights reserved. This program and the accompanying materials
  are made available under the terms of the Apache License, Version 2.0
  which accompanies this distribution, and is available at
@@ -31,6 +30,8 @@
   <property name="test2.class" value="it.polito.verigraph.grpc.test.GrpcTest" />
   <property name="test3.class" value="it.polito.verigraph.grpc.test.MultiThreadTest" />
   <property name="test4.class" value="it.polito.verigraph.grpc.test.ReachabilityTest" />
+  <!-- Tosca grpc test class -->
+  <property name="testToscaGrpc.class" value="it.polito.verigraph.grpc.tosca.test.GrpcToscaTest" />
   <!-- The name to be given to the final zip -->
   <property name="sol.zip" value="grpc.zip" />
   <!-- Java compiler settings -->
@@ -43,7 +44,7 @@
   <path id="test.classpath">
     <pathelement path="${build.dir}" />
     <fileset dir="${grpc.location}/lib">
-        <include name="com.microsoft.z3.jar" />
+      <include name="com.microsoft.z3.jar" />
     </fileset>
     <fileset refid="mvn-dependencies" />
   </path>
@@ -65,7 +66,7 @@
   </artifact:dependencies>-->
 
   <path id="build.classpath">
-      <fileset refid="mvn-dependencies" />
+    <fileset refid="mvn-dependencies" />
   </path>
 
   <!-- target name="init">
@@ -77,7 +78,7 @@
   <!--target name="gRPC-build" depends="init" description="Build the sources"-->
   <target name="gRPC-build" description="Build the sources">
     <echo>Building gRPC (if needed)...</echo>
-      <javac
+    <javac
         debug="${debug}"
         debuglevel="${debuglevel}"
         source="${source}"
         destdir="${build.dir}"
         classpathref="build.classpath"
         includeantruntime="false">
-        <src path="${generated.dir}" />
-        <src path="${src.dir}" />
-        <src path="${grpc.location}/gen-src"/>
-        <compilerarg value="-Xlint:unchecked"/>
-        <classpath>
-          <pathelement path="${grpc.location}/lib/com.microsoft.z3.jar"/>
-        </classpath>
-        <include name="$it/polito/**/**/*.java"/>
-        <!-- classpath>
+      <src path="${generated.dir}" />
+      <src path="${src.dir}" />
+      <src path="${grpc.location}/gen-src"/>
+      <compilerarg value="-Xlint:unchecked"/>
+      <classpath>
+        <pathelement path="${grpc.location}/lib/com.microsoft.z3.jar"/>
+      </classpath>
+      <include name="$it/polito/**/**/*.java"/>
+      <!-- classpath>
           <pathelement path="${other_lib.dir}/qjutils.jar"/>
         </classpath-->
-      </javac>
+    </javac>
     <echo>Done.</echo>
   </target>
 
   <!-- The target for running the gRPC application -->
   <target name="gRPC-run" depends="gRPC-build" description="Run gRPC">
     <parallel>
-       <sequential>
-          <java classname="it.polito.verigraph.grpc.Service" failonerror="true" classpathref="build.classpath" fork="yes">
-            <classpath>
-              <pathelement path="${build.dir}"/>
-            </classpath>
-            </java>
-        </sequential>
-        <sequential>
-          <sleep milliseconds="500"/>
-            <java classname="it.polito.verigraph.grpc.Client" failonerror="true" classpathref="build.classpath" fork="yes">
-           <classpath>
-          <pathelement path="${build.dir}"/>
-        </classpath>
-           </java>
+      <sequential>
+        <java classname="it.polito.verigraph.grpc.Service" failonerror="true" classpathref="build.classpath" fork="yes">
+          <classpath>
+            <pathelement path="${build.dir}"/>
+            <path refid="test.classpath" />
+          </classpath>
+        </java>
+      </sequential>
+      <sequential>
+        <sleep milliseconds="500"/>
+        <java classname="it.polito.verigraph.grpc.Client" failonerror="true" classpathref="build.classpath" fork="yes">
+          <classpath>
+            <pathelement path="${build.dir}"/>
+          </classpath>
+        </java>
       </sequential>
     </parallel>
   </target>
     <java classname="it.polito.verigraph.grpc.server.Service" failonerror="true" classpathref="build.classpath" fork="yes">
       <classpath>
         <pathelement path="${build.dir}"/>
+        <path refid="test.classpath" />
       </classpath>
     </java>
   </target>
     </antcall>
   </target>
 
+  <!-- Run Tosca Grpc Tests -->
+  <target name="gRPC-tosca-run-tests" description="Run tests for Tosca implementation of gRPC">
+    <echo>Running grpc tests...</echo>
+    <junit printsummary="yes" dir="." fork="yes" haltonfailure="no" showoutput="yes" filtertrace="true" timeout="120000">
+      <jvmarg value="-Djava.awt.headless=true" />
+      <formatter type="brief" usefile="false" />
+      <test haltonfailure="no" failureproperty="test_failed" name="${testToscaGrpc.class}" />
+      <classpath>
+        <path refid="test.classpath" />
+      </classpath>
+    </junit>
+    <fail if="test_failed" message="*** JUnit tests for gRPC Tosca completed: some Tests FAILED ***" />
+  </target>
 
   <!-- Target runFuncTest.real  -->
   <target name="runFuncTest.real" depends="gRPC-build">
   <!-- target name="clean">
     <delete dir="${build.dir}" />
   </target-->
-</project>
\ No newline at end of file
+</project>
index cfa21e9..9684667 100755 (executable)
@@ -37,8 +37,8 @@
                 <version>3.0</version>\r
                 <inherited>true</inherited>\r
                 <configuration>\r
-                    <source>1.7</source>\r
-                    <target>1.7</target>\r
+                    <source>1.8</source>\r
+                    <target>1.8</target>\r
                 </configuration>\r
             </plugin>\r
             <plugin>\r
             <artifactId>slf4j-log4j12</artifactId>\r
             <version>1.6.4</version>\r
         </dependency>\r
+        <dependency>\r
+            <groupId>com.fasterxml.jackson.dataformat</groupId>\r
+            <artifactId>jackson-dataformat-yaml</artifactId>\r
+            <version>2.9.2</version>\r
+        </dependency>\r
+        <!-- Trying to make jaxb work -->\r
+        <dependency>\r
+            <groupId>org.eclipse.persistence</groupId>\r
+            <artifactId>org.eclipse.persistence.core</artifactId>\r
+            <version>2.6.0</version>\r
+        </dependency>\r
     </dependencies>\r
-\r
 </project>
\ No newline at end of file
diff --git a/verigraph/schema/README.rst b/verigraph/schema/README.rst
new file mode 100644 (file)
index 0000000..c3e7a22
--- /dev/null
@@ -0,0 +1,4 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+The XML Schema files in this folder are used by VeriGraph to
+automatically generate Java XML Bindings (JAXB)
diff --git a/verigraph/schema/tosca/TOSCA-v1.0.xsd b/verigraph/schema/tosca/TOSCA-v1.0.xsd
new file mode 100644 (file)
index 0000000..ebfcaa6
--- /dev/null
@@ -0,0 +1,790 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Topology and Orchestration Specification for Cloud Applications Version 1.0
+    OASIS Standard
+    25 November 2013
+    Copyright (c) OASIS Open 2013. All rights reserved.
+    Source: http://docs.oasis-open.org/tosca/TOSCA/v1.0/os/schemas/
+-->
+<xs:schema targetNamespace="http://docs.oasis-open.org/tosca/ns/2011/12" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns="http://docs.oasis-open.org/tosca/ns/2011/12" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+ <xs:element name="documentation" type="tDocumentation"/>
+ <xs:complexType name="tDocumentation" mixed="true">
+  <xs:sequence>
+   <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+  </xs:sequence>
+  <xs:attribute name="source" type="xs:anyURI"/>
+  <xs:attribute ref="xml:lang"/>
+ </xs:complexType>
+ <xs:complexType name="tExtensibleElements">
+  <xs:sequence>
+   <xs:element ref="documentation" minOccurs="0" maxOccurs="unbounded"/>
+   <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+  </xs:sequence>
+  <xs:anyAttribute namespace="##other" processContents="lax"/>
+ </xs:complexType>
+ <xs:complexType name="tImport">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:attribute name="namespace" type="xs:anyURI"/>
+    <xs:attribute name="location" type="xs:anyURI"/>
+    <xs:attribute name="importType" type="importedURI" use="required"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:element name="Definitions">
+  <xs:complexType>
+   <xs:complexContent>
+    <xs:extension base="tDefinitions"/>
+   </xs:complexContent>
+  </xs:complexType>
+ </xs:element>
+ <xs:complexType name="tDefinitions">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="Extensions" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="Extension" type="tExtension" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="Import" type="tImport" minOccurs="0" maxOccurs="unbounded"/>
+     <xs:element name="Types" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:choice maxOccurs="unbounded">
+      <xs:element name="ServiceTemplate" type="tServiceTemplate"/>
+      <xs:element name="NodeType" type="tNodeType"/>
+      <xs:element name="NodeTypeImplementation" type="tNodeTypeImplementation"/>
+      <xs:element name="RelationshipType" type="tRelationshipType"/>
+      <xs:element name="RelationshipTypeImplementation" type="tRelationshipTypeImplementation"/>
+      <xs:element name="RequirementType" type="tRequirementType"/>
+      <xs:element name="CapabilityType" type="tCapabilityType"/>
+      <xs:element name="ArtifactType" type="tArtifactType"/>
+      <xs:element name="ArtifactTemplate" type="tArtifactTemplate"/>
+      <xs:element name="PolicyType" type="tPolicyType"/>
+      <xs:element name="PolicyTemplate" type="tPolicyTemplate"/>
+     </xs:choice>
+    </xs:sequence>
+    <xs:attribute name="id" type="xs:ID" use="required"/>
+    <xs:attribute name="name" type="xs:string" use="optional"/>
+    <xs:attribute name="targetNamespace" type="xs:anyURI" use="required"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tServiceTemplate">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="Tags" type="tTags" minOccurs="0"/>
+     <xs:element name="BoundaryDefinitions" type="tBoundaryDefinitions" minOccurs="0"/>
+     <xs:element name="TopologyTemplate" type="tTopologyTemplate"/>
+     <xs:element name="Plans" type="tPlans" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="id" type="xs:ID" use="required"/>
+    <xs:attribute name="name" type="xs:string" use="optional"/>
+    <xs:attribute name="targetNamespace" type="xs:anyURI"/>
+    <xs:attribute name="substitutableNodeType" type="xs:QName" use="optional"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tTags">
+  <xs:sequence>
+   <xs:element name="Tag" type="tTag" maxOccurs="unbounded"/>
+  </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tTag">
+  <xs:attribute name="name" type="xs:string" use="required"/>
+  <xs:attribute name="value" type="xs:string" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tBoundaryDefinitions">
+  <xs:sequence>
+   <xs:element name="Properties" minOccurs="0">
+    <xs:complexType>
+     <xs:sequence>
+      <xs:any namespace="##other"/>
+      <xs:element name="PropertyMappings" minOccurs="0">
+       <xs:complexType>
+        <xs:sequence>
+         <xs:element name="PropertyMapping" type="tPropertyMapping" maxOccurs="unbounded"/>
+        </xs:sequence>
+       </xs:complexType>
+      </xs:element>
+     </xs:sequence>
+    </xs:complexType>
+   </xs:element>
+   <xs:element name="PropertyConstraints" minOccurs="0">
+    <xs:complexType>
+     <xs:sequence>
+      <xs:element name="PropertyConstraint" type="tPropertyConstraint" maxOccurs="unbounded"/>
+     </xs:sequence>
+    </xs:complexType>
+   </xs:element>
+   <xs:element name="Requirements" minOccurs="0">
+    <xs:complexType>
+     <xs:sequence>
+      <xs:element name="Requirement" type="tRequirementRef" maxOccurs="unbounded"/>
+     </xs:sequence>
+    </xs:complexType>
+   </xs:element>
+   <xs:element name="Capabilities" minOccurs="0">
+    <xs:complexType>
+     <xs:sequence>
+      <xs:element name="Capability" type="tCapabilityRef" maxOccurs="unbounded"/>
+     </xs:sequence>
+    </xs:complexType>
+   </xs:element>
+   <xs:element name="Policies" minOccurs="0">
+    <xs:complexType>
+     <xs:sequence>
+      <xs:element name="Policy" type="tPolicy" maxOccurs="unbounded"/>
+     </xs:sequence>
+    </xs:complexType>
+   </xs:element>
+   <xs:element name="Interfaces" minOccurs="0">
+    <xs:complexType>
+     <xs:sequence>
+      <xs:element name="Interface" type="tExportedInterface" maxOccurs="unbounded"/>
+     </xs:sequence>
+    </xs:complexType>
+   </xs:element>
+  </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tPropertyMapping">
+  <xs:attribute name="serviceTemplatePropertyRef" type="xs:string" use="required"/>
+  <xs:attribute name="targetObjectRef" type="xs:IDREF" use="required"/>
+  <xs:attribute name="targetPropertyRef" type="xs:string" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tRequirementRef">
+  <xs:attribute name="name" type="xs:string" use="optional"/>
+  <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tCapabilityRef">
+  <xs:attribute name="name" type="xs:string" use="optional"/>
+  <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tEntityType" abstract="true">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="Tags" type="tTags" minOccurs="0"/>
+     <xs:element name="DerivedFrom" minOccurs="0">
+      <xs:complexType>
+       <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="PropertiesDefinition" minOccurs="0">
+      <xs:complexType>
+       <xs:attribute name="element" type="xs:QName"/>
+       <xs:attribute name="type" type="xs:QName"/>
+      </xs:complexType>
+     </xs:element>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:NCName" use="required"/>
+    <xs:attribute name="abstract" type="tBoolean" default="no"/>
+    <xs:attribute name="final" type="tBoolean" default="no"/>
+    <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tEntityTemplate" abstract="true">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="Properties" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:any namespace="##other" processContents="lax"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="PropertyConstraints" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="PropertyConstraint" type="tPropertyConstraint" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+    </xs:sequence>
+    <xs:attribute name="id" type="xs:ID" use="required"/>
+    <xs:attribute name="type" type="xs:QName" use="required"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tNodeTemplate">
+  <xs:complexContent>
+   <xs:extension base="tEntityTemplate">
+    <xs:sequence>
+     <xs:element name="Requirements" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="Requirement" type="tRequirement" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="Capabilities" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="Capability" type="tCapability" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="Policies" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="Policy" type="tPolicy" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="DeploymentArtifacts" type="tDeploymentArtifacts" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:string" use="optional"/>
+    <xs:attribute name="minInstances" type="xs:int" use="optional" default="1"/>
+    <xs:attribute name="maxInstances" use="optional" default="1">
+     <xs:simpleType>
+      <xs:union>
+       <xs:simpleType>
+        <xs:restriction base="xs:nonNegativeInteger">
+         <xs:pattern value="([1-9]+[0-9]*)"/>
+        </xs:restriction>
+       </xs:simpleType>
+       <xs:simpleType>
+        <xs:restriction base="xs:string">
+         <xs:enumeration value="unbounded"/>
+        </xs:restriction>
+       </xs:simpleType>
+      </xs:union>
+     </xs:simpleType>
+    </xs:attribute>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tTopologyTemplate">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:choice maxOccurs="unbounded">
+     <xs:element name="NodeTemplate" type="tNodeTemplate"/>
+     <xs:element name="RelationshipTemplate" type="tRelationshipTemplate"/>
+    </xs:choice>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRelationshipType">
+  <xs:complexContent>
+   <xs:extension base="tEntityType">
+    <xs:sequence>
+     <xs:element name="InstanceStates" type="tTopologyElementInstanceStates" minOccurs="0"/>
+     <xs:element name="SourceInterfaces" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="Interface" type="tInterface" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="TargetInterfaces" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="Interface" type="tInterface" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="ValidSource" minOccurs="0">
+      <xs:complexType>
+       <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="ValidTarget" minOccurs="0">
+      <xs:complexType>
+       <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+      </xs:complexType>
+     </xs:element>
+    </xs:sequence>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRelationshipTypeImplementation">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="Tags" type="tTags" minOccurs="0"/>
+     <xs:element name="DerivedFrom" minOccurs="0">
+      <xs:complexType>
+       <xs:attribute name="relationshipTypeImplementationRef" type="xs:QName" use="required"/>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="RequiredContainerFeatures" type="tRequiredContainerFeatures" minOccurs="0"/>
+     <xs:element name="ImplementationArtifacts" type="tImplementationArtifacts" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:NCName" use="required"/>
+    <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+    <xs:attribute name="relationshipType" type="xs:QName" use="required"/>
+    <xs:attribute name="abstract" type="tBoolean" use="optional" default="no"/>
+    <xs:attribute name="final" type="tBoolean" use="optional" default="no"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRelationshipTemplate">
+  <xs:complexContent>
+   <xs:extension base="tEntityTemplate">
+    <xs:sequence>
+     <xs:element name="SourceElement">
+      <xs:complexType>
+       <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="TargetElement">
+      <xs:complexType>
+       <xs:attribute name="ref" type="xs:IDREF" use="required"/>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="RelationshipConstraints" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="RelationshipConstraint" maxOccurs="unbounded">
+         <xs:complexType>
+          <xs:sequence>
+           <xs:any namespace="##other" processContents="lax" minOccurs="0"/>
+          </xs:sequence>
+          <xs:attribute name="constraintType" type="xs:anyURI" use="required"/>
+         </xs:complexType>
+        </xs:element>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:string" use="optional"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tNodeType">
+  <xs:complexContent>
+   <xs:extension base="tEntityType">
+    <xs:sequence>
+     <xs:element name="RequirementDefinitions" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="RequirementDefinition" type="tRequirementDefinition" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="CapabilityDefinitions" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="CapabilityDefinition" type="tCapabilityDefinition" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="InstanceStates" type="tTopologyElementInstanceStates" minOccurs="0"/>
+     <xs:element name="Interfaces" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="Interface" type="tInterface" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+    </xs:sequence>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tNodeTypeImplementation">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="Tags" type="tTags" minOccurs="0"/>
+     <xs:element name="DerivedFrom" minOccurs="0">
+      <xs:complexType>
+       <xs:attribute name="nodeTypeImplementationRef" type="xs:QName" use="required"/>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="RequiredContainerFeatures" type="tRequiredContainerFeatures" minOccurs="0"/>
+     <xs:element name="ImplementationArtifacts" type="tImplementationArtifacts" minOccurs="0"/>
+     <xs:element name="DeploymentArtifacts" type="tDeploymentArtifacts" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:NCName" use="required"/>
+    <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+    <xs:attribute name="nodeType" type="xs:QName" use="required"/>
+    <xs:attribute name="abstract" type="tBoolean" use="optional" default="no"/>
+    <xs:attribute name="final" type="tBoolean" use="optional" default="no"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRequirementType">
+  <xs:complexContent>
+   <xs:extension base="tEntityType">
+    <xs:attribute name="requiredCapabilityType" type="xs:QName" use="optional"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRequirementDefinition">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="Constraints" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="Constraint" type="tConstraint" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:string" use="required"/>
+    <xs:attribute name="requirementType" type="xs:QName" use="required"/>
+    <xs:attribute name="lowerBound" type="xs:int" use="optional" default="1"/>
+    <xs:attribute name="upperBound" use="optional" default="1">
+     <xs:simpleType>
+      <xs:union>
+       <xs:simpleType>
+        <xs:restriction base="xs:nonNegativeInteger">
+         <xs:pattern value="([1-9]+[0-9]*)"/>
+        </xs:restriction>
+       </xs:simpleType>
+       <xs:simpleType>
+        <xs:restriction base="xs:string">
+         <xs:enumeration value="unbounded"/>
+        </xs:restriction>
+       </xs:simpleType>
+      </xs:union>
+     </xs:simpleType>
+    </xs:attribute>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tRequirement">
+  <xs:complexContent>
+   <xs:extension base="tEntityTemplate">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tCapabilityType">
+  <xs:complexContent>
+   <xs:extension base="tEntityType"/>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tCapabilityDefinition">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="Constraints" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="Constraint" type="tConstraint" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:string" use="required"/>
+    <xs:attribute name="capabilityType" type="xs:QName" use="required"/>
+    <xs:attribute name="lowerBound" type="xs:int" use="optional" default="1"/>
+    <xs:attribute name="upperBound" use="optional" default="1">
+     <xs:simpleType>
+      <xs:union>
+       <xs:simpleType>
+        <xs:restriction base="xs:nonNegativeInteger">
+         <xs:pattern value="([1-9]+[0-9]*)"/>
+        </xs:restriction>
+       </xs:simpleType>
+       <xs:simpleType>
+        <xs:restriction base="xs:string">
+         <xs:enumeration value="unbounded"/>
+        </xs:restriction>
+       </xs:simpleType>
+      </xs:union>
+     </xs:simpleType>
+    </xs:attribute>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tCapability">
+  <xs:complexContent>
+   <xs:extension base="tEntityTemplate">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tArtifactType">
+  <xs:complexContent>
+   <xs:extension base="tEntityType"/>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tArtifactTemplate">
+  <xs:complexContent>
+   <xs:extension base="tEntityTemplate">
+    <xs:sequence>
+     <xs:element name="ArtifactReferences" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="ArtifactReference" type="tArtifactReference" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:string" use="optional"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tDeploymentArtifacts">
+  <xs:sequence>
+   <xs:element name="DeploymentArtifact" type="tDeploymentArtifact" maxOccurs="unbounded"/>
+  </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tDeploymentArtifact">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+    <xs:attribute name="artifactType" type="xs:QName" use="required"/>
+    <xs:attribute name="artifactRef" type="xs:QName" use="optional"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tImplementationArtifacts">
+  <xs:sequence>
+   <xs:element name="ImplementationArtifact" maxOccurs="unbounded">
+    <xs:complexType>
+     <xs:complexContent>
+      <xs:extension base="tImplementationArtifact"/>
+     </xs:complexContent>
+    </xs:complexType>
+   </xs:element>
+  </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tImplementationArtifact">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:attribute name="interfaceName" type="xs:anyURI" use="optional"/>
+    <xs:attribute name="operationName" type="xs:NCName" use="optional"/>
+    <xs:attribute name="artifactType" type="xs:QName" use="required"/>
+    <xs:attribute name="artifactRef" type="xs:QName" use="optional"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tPlans">
+  <xs:sequence>
+   <xs:element name="Plan" type="tPlan" maxOccurs="unbounded"/>
+  </xs:sequence>
+  <xs:attribute name="targetNamespace" type="xs:anyURI" use="optional"/>
+ </xs:complexType>
+ <xs:complexType name="tPlan">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="Precondition" type="tCondition" minOccurs="0"/>
+     <xs:element name="InputParameters" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="InputParameter" type="tParameter" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="OutputParameters" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="OutputParameter" type="tParameter" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:choice>
+      <xs:element name="PlanModel">
+       <xs:complexType>
+        <xs:sequence>
+         <xs:any namespace="##other" processContents="lax"/>
+        </xs:sequence>
+       </xs:complexType>
+      </xs:element>
+      <xs:element name="PlanModelReference">
+       <xs:complexType>
+        <xs:attribute name="reference" type="xs:anyURI" use="required"/>
+       </xs:complexType>
+      </xs:element>
+     </xs:choice>
+    </xs:sequence>
+    <xs:attribute name="id" type="xs:ID" use="required"/>
+    <xs:attribute name="name" type="xs:string" use="optional"/>
+    <xs:attribute name="planType" type="xs:anyURI" use="required"/>
+    <xs:attribute name="planLanguage" type="xs:anyURI" use="required"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tPolicyType">
+  <xs:complexContent>
+   <xs:extension base="tEntityType">
+    <xs:sequence>
+     <xs:element name="AppliesTo" type="tAppliesTo" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="policyLanguage" type="xs:anyURI" use="optional"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tPolicyTemplate">
+  <xs:complexContent>
+   <xs:extension base="tEntityTemplate">
+    <xs:attribute name="name" type="xs:string" use="optional"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tAppliesTo">
+  <xs:sequence>
+   <xs:element name="NodeTypeReference" maxOccurs="unbounded">
+    <xs:complexType>
+     <xs:attribute name="typeRef" type="xs:QName" use="required"/>
+    </xs:complexType>
+   </xs:element>
+  </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tPolicy">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:attribute name="name" type="xs:string" use="optional"/>
+    <xs:attribute name="policyType" type="xs:QName" use="required"/>
+    <xs:attribute name="policyRef" type="xs:QName" use="optional"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tConstraint">
+  <xs:sequence>
+   <xs:any namespace="##other" processContents="lax"/>
+  </xs:sequence>
+  <xs:attribute name="constraintType" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tPropertyConstraint">
+  <xs:complexContent>
+   <xs:extension base="tConstraint">
+    <xs:attribute name="property" type="xs:string" use="required"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tExtensions">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="Extension" type="tExtension" maxOccurs="unbounded"/>
+    </xs:sequence>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tExtension">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:attribute name="namespace" type="xs:anyURI" use="required"/>
+    <xs:attribute name="mustUnderstand" type="tBoolean" use="optional" default="yes"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tParameter">
+  <xs:attribute name="name" type="xs:string" use="required"/>
+  <xs:attribute name="type" type="xs:string" use="required"/>
+  <xs:attribute name="required" type="tBoolean" use="optional" default="yes"/>
+ </xs:complexType>
+ <xs:complexType name="tInterface">
+  <xs:sequence>
+   <xs:element name="Operation" type="tOperation" maxOccurs="unbounded"/>
+  </xs:sequence>
+  <xs:attribute name="name" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tExportedInterface">
+  <xs:sequence>
+   <xs:element name="Operation" type="tExportedOperation" maxOccurs="unbounded"/>
+  </xs:sequence>
+  <xs:attribute name="name" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tOperation">
+  <xs:complexContent>
+   <xs:extension base="tExtensibleElements">
+    <xs:sequence>
+     <xs:element name="InputParameters" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="InputParameter" type="tParameter" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+     <xs:element name="OutputParameters" minOccurs="0">
+      <xs:complexType>
+       <xs:sequence>
+        <xs:element name="OutputParameter" type="tParameter" maxOccurs="unbounded"/>
+       </xs:sequence>
+      </xs:complexType>
+     </xs:element>
+    </xs:sequence>
+    <xs:attribute name="name" type="xs:NCName" use="required"/>
+   </xs:extension>
+  </xs:complexContent>
+ </xs:complexType>
+ <xs:complexType name="tExportedOperation">
+  <xs:choice>
+   <xs:element name="NodeOperation">
+    <xs:complexType>
+     <xs:attribute name="nodeRef" type="xs:IDREF" use="required"/>
+     <xs:attribute name="interfaceName" type="xs:anyURI" use="required"/>
+     <xs:attribute name="operationName" type="xs:NCName" use="required"/>
+    </xs:complexType>
+   </xs:element>
+   <xs:element name="RelationshipOperation">
+    <xs:complexType>
+     <xs:attribute name="relationshipRef" type="xs:IDREF" use="required"/>
+     <xs:attribute name="interfaceName" type="xs:anyURI" use="required"/>
+     <xs:attribute name="operationName" type="xs:NCName" use="required"/>
+    </xs:complexType>
+   </xs:element>
+   <xs:element name="Plan">
+    <xs:complexType>
+     <xs:attribute name="planRef" type="xs:IDREF" use="required"/>
+    </xs:complexType>
+   </xs:element>
+  </xs:choice>
+  <xs:attribute name="name" type="xs:NCName" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tCondition">
+  <xs:sequence>
+   <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+  </xs:sequence>
+  <xs:attribute name="expressionLanguage" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tTopologyElementInstanceStates">
+  <xs:sequence>
+   <xs:element name="InstanceState" maxOccurs="unbounded">
+    <xs:complexType>
+     <xs:attribute name="state" type="xs:anyURI" use="required"/>
+    </xs:complexType>
+   </xs:element>
+  </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tArtifactReference">
+  <xs:choice minOccurs="0" maxOccurs="unbounded">
+   <xs:element name="Include">
+    <xs:complexType>
+     <xs:attribute name="pattern" type="xs:string" use="required"/>
+    </xs:complexType>
+   </xs:element>
+   <xs:element name="Exclude">
+    <xs:complexType>
+     <xs:attribute name="pattern" type="xs:string" use="required"/>
+    </xs:complexType>
+   </xs:element>
+  </xs:choice>
+  <xs:attribute name="reference" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="tRequiredContainerFeatures">
+  <xs:sequence>
+   <xs:element name="RequiredContainerFeature" type="tRequiredContainerFeature" maxOccurs="unbounded"/>
+  </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="tRequiredContainerFeature">
+  <xs:attribute name="feature" type="xs:anyURI" use="required"/>
+ </xs:complexType>
+ <xs:simpleType name="tBoolean">
+  <xs:restriction base="xs:string">
+   <xs:enumeration value="yes"/>
+   <xs:enumeration value="no"/>
+  </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="importedURI">
+  <xs:restriction base="xs:anyURI"/>
+ </xs:simpleType>
+</xs:schema>
diff --git a/verigraph/schema/tosca/ToscaTypes_XMLconfig.xsd b/verigraph/schema/tosca/ToscaTypes_XMLconfig.xsd
new file mode 100644 (file)
index 0000000..98751b4
--- /dev/null
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2018 Politecnico di Torino and others.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Apache License, Version 2.0
+ which accompanies this distribution, and is available at
+ http://www.apache.org/licenses/LICENSE-2.0
+-->
+
+
+<xsd:schema  xmlns="http://docs.oasis-open.org/tosca/ns/2011/12/ToscaVerigraphDefinition"
+      xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+      targetNamespace="http://docs.oasis-open.org/tosca/ns/2011/12/ToscaVerigraphDefinition">
+
+  <!-- Generic Configuration type, contains a single configuration element -->
+  <xsd:element name="Configuration">
+    <xsd:complexType>
+      <xsd:choice>
+        <xsd:element name="antispamConfiguration">
+          <xsd:complexType>
+            <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+              <xsd:element name="source" type="xsd:string" />
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="cacheConfiguration">
+          <xsd:complexType>
+            <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+              <xsd:element name="resource" type="xsd:string" />
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="dpiConfiguration">
+          <xsd:complexType>
+            <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+              <xsd:element name="notAllowed" type="xsd:string" />
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="endhostConfiguration">
+          <xsd:complexType>
+            <xsd:attribute name="body" type="xsd:string" />
+            <xsd:attribute name="sequence" type="xsd:integer" />
+            <xsd:attribute name="protocol">
+            <xsd:simpleType>
+              <xsd:restriction base="xsd:string">
+                <xsd:enumeration value="HTTP_REQUEST" />
+                <xsd:enumeration value="HTTP_RESPONSE" />
+                <xsd:enumeration value="POP3_REQUEST" />
+                <xsd:enumeration value="POP3_RESPONSE" />
+              </xsd:restriction>
+            </xsd:simpleType>
+            </xsd:attribute>
+            <xsd:attribute name="email_from" type="xsd:string" />
+            <xsd:attribute name="url" type="xsd:string" />
+            <xsd:attribute name="options" type="xsd:string" />
+            <xsd:attribute name="destination" type="xsd:string" />
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="endpointConfiguration">
+          <xsd:complexType>
+            <xsd:sequence>
+              <xsd:element name="name" type="xsd:string" nillable="true" />
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="fieldmodifierConfiguration">
+          <xsd:complexType>
+            <xsd:sequence>
+              <xsd:element name="name" type="xsd:string" nillable="true" />
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="firewallConfiguration">
+          <xsd:complexType>
+            <xsd:sequence>
+              <xsd:element name="elements" maxOccurs="unbounded">
+                <xsd:complexType>
+                  <xsd:sequence>
+                    <xsd:element name="source" type="xsd:string" />
+                    <xsd:element name="destination" type="xsd:string" />
+                  </xsd:sequence>
+                </xsd:complexType>
+              </xsd:element>
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="mailclientConfiguration">
+          <xsd:complexType>
+            <xsd:attribute name="mailserver" type="xsd:string"
+              use="required" />
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="mailserverConfiguration">
+          <xsd:complexType>
+            <xsd:sequence>
+              <xsd:element name="name" type="xsd:string" nillable="true" />
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="natConfiguration">
+          <xsd:complexType>
+            <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+              <xsd:element name="source" type="xsd:string" />
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="vpnaccessConfiguration">
+          <xsd:complexType>
+            <xsd:attribute name="vpnexit" type="xsd:string" use="required" />
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="vpnexitConfiguration">
+          <xsd:complexType>
+            <xsd:attribute name="vpnaccess" type="xsd:string"
+              use="required" />
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="webclientConfiguration">
+          <xsd:complexType>
+            <xsd:attribute name="nameWebServer" type="xsd:string"
+              use="required" />
+          </xsd:complexType>
+        </xsd:element>
+        <xsd:element name="webserverConfiguration">
+          <xsd:complexType>
+            <xsd:sequence>
+              <xsd:element name="name" type="xsd:string" nillable="true" />
+            </xsd:sequence>
+          </xsd:complexType>
+        </xsd:element>
+      </xsd:choice>
+      <xsd:attribute name="confID" type="xsd:string" />
+      <xsd:attribute name="confDescr" type="xsd:string" />
+    </xsd:complexType>
+  </xsd:element>
+
+
+   <!--   <xsd:element name="firewallConfiguration">
+        <xsd:complexType >
+            <xsd:sequence>
+                <xsd:element ref="elements" maxOccurs="unbounded" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="elements">
+        <xsd:complexType>
+            <xsd:sequence>
+                <xsd:element name="source" type="xsd:string" />
+                <xsd:element name="destination" type="xsd:string" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="endhostConfiguration">
+        <xsd:complexType>
+            <xsd:attribute name="body" type="xsd:string" />
+            <xsd:attribute name="sequence" type="xsd:integer" />
+            <xsd:attribute name="protocol" type="protocolTypes" />
+            <xsd:attribute name="email_from" type="xsd:string" />
+            <xsd:attribute name="url" type="xsd:string" />
+            <xsd:attribute name="options" type="xsd:string" />
+            <xsd:attribute name="destination" type="xsd:string" />
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="endpointConfiguration">
+        <xsd:complexType>
+            <xsd:sequence>
+                <xsd:element name="name" type="xsd:string"
+                    nillable="true" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+  <xsd:element name="antispamConfiguration">
+        <xsd:complexType>
+            <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+                <xsd:element name="source" type="xsd:string" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="cacheConfiguration">
+        <xsd:complexType>
+            <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+                <xsd:element name="resource" type="xsd:string" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="dpiConfiguration">
+        <xsd:complexType>
+            <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+                <xsd:element name="notAllowed" type="xsd:string" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="mailclientConfiguration">
+        <xsd:complexType>
+            <xsd:attribute name="mailserver" type="xsd:string"
+                use="required" />
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="mailserverConfiguration">
+        <xsd:complexType>
+            <xsd:sequence>
+                <xsd:element name="name" type="xsd:string"
+                    nillable="true" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="natConfiguration">
+        <xsd:complexType>
+            <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+                <xsd:element name="source" type="xsd:string" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="vpnaccessConfiguration">
+        <xsd:complexType>
+            <xsd:attribute name="vpnexit" type="xsd:string"
+                use="required" />
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="vpnexitConfiguration">
+        <xsd:complexType>
+            <xsd:attribute name="vpnaccess" type="xsd:string"
+                use="required" />
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="webclientConfiguration">
+        <xsd:complexType>
+            <xsd:attribute name="nameWebServer" type="xsd:string"
+                use="required" />
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="webserverConfiguration">
+        <xsd:complexType>
+            <xsd:sequence>
+                <xsd:element name="name" type="xsd:string"
+                    nillable="true" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+    <xsd:element name="fieldmodifierConfiguration">
+        <xsd:complexType>
+            <xsd:sequence>
+                <xsd:element name="name" type="xsd:string"
+                    nillable="true" />
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+
+  <xsd:simpleType name="functionalTypes">
+        <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="FIREWALL" />
+            <xsd:enumeration value="ENDHOST" />
+            <xsd:enumeration value="ENDPOINT" />
+            <xsd:enumeration value="ANTISPAM" />
+            <xsd:enumeration value="CACHE" />
+            <xsd:enumeration value="DPI" />
+            <xsd:enumeration value="MAILCLIENT" />
+            <xsd:enumeration value="MAILSERVER" />
+            <xsd:enumeration value="NAT" />
+            <xsd:enumeration value="VPNACCESS" />
+            <xsd:enumeration value="VPNEXIT" />
+            <xsd:enumeration value="WEBCLIENT" />
+            <xsd:enumeration value="WEBSERVER" />
+            <xsd:enumeration value="FIELDMODIFIER" />
+        </xsd:restriction>
+    </xsd:simpleType>
+    <xsd:simpleType name="protocolTypes">
+        <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="HTTP_REQUEST" />
+            <xsd:enumeration value="HTTP_RESPONSE" />
+            <xsd:enumeration value="POP3_REQUEST" />
+            <xsd:enumeration value="POP3_RESPONSE" />
+        </xsd:restriction>
+    </xsd:simpleType>
+
+  -->
+
+</xsd:schema>
\ No newline at end of file
diff --git a/verigraph/schema/tosca/ToscaVerigraphDefinitions.xml b/verigraph/schema/tosca/ToscaVerigraphDefinitions.xml
new file mode 100644 (file)
index 0000000..4f49037
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2018 Politecnico di Torino and others.
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Apache License, Version 2.0
+ which accompanies this distribution, and is available at
+ http://www.apache.org/licenses/LICENSE-2.0
+-->
+
+<Definitions id="Verigraph_Definitions" name="Verigraph Type Definition"
+  xmlns="http://docs.oasis-open.org/tosca/ns/2011/12"
+  targetNamespace="http://docs.oasis-open.org/tosca/ns/2011/12/ToscaVerigraphDefinition">
+
+  <import importType="http://www.w3.org/2001/XMLSchema"
+    namespace="http://docs.oasis-open.org/tosca/ns/2011/12/ToscaVerigraphDefinition"
+    location="./ToscaTypes_XMLconfig.xsd" />
+
+  <NodeType name="AntispamType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="CacheType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="DpiType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="EndhostType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="EndpointType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="FieldModifierType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="FirewallType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="MailclientType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="MailserverType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="NatType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="VpnAccessType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="VpnExitType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="WebclientType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <NodeType name="WebserverType">
+    <PropertiesDefinition element="Configuration" />
+  </NodeType>
+
+  <RelationshipType name="linkedTo" />
+
+</Definitions>
\ No newline at end of file
diff --git a/verigraph/schema/tosca/yamlToscaDefinitions.yaml b/verigraph/schema/tosca/yamlToscaDefinitions.yaml
new file mode 100644 (file)
index 0000000..e72a5da
--- /dev/null
@@ -0,0 +1,157 @@
+##############################################################################
+# Copyright (c) 2018 Politecnico di Torino and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+#Tosca definitions for Verigraph extension in Tosca Yaml simple profile
+
+tosca_definitions_version: http://docs.oasis-open.org/tosca/ns/simple/yaml/1.0
+
+description: node type definitions exetending tosca types for support to Verigraph verification system
+
+node_types:
+  verigraph.types.Antispam:
+    derived_from: tosca.nodes.Root
+    description: verigraph Antispam node
+    properties:
+      sources:
+        type: list
+        entry_schema:
+          type: string
+
+  verigraph.types.Cache:
+    derived_from: tosca.nodes.Root
+    description: verigraph Cache node
+    properties:
+      resources:
+        type: list
+        entry_schema:
+          type: string
+
+  verigraph.types.Dpi:
+    derived_from: tosca.nodes.Root
+    description: verigraph Dpi node
+    properties:
+      notAllowedList:
+        type: list
+        entry_schema:
+          type: string
+
+  verigraph.types.Endhost:
+    derived_from: tosca.nodes.Root
+    description: verigraph endhost node
+    attributes:
+      body:
+        type: string
+      sequence:
+        type: integer
+      protocol:
+        type: string
+        constraints:
+          - valid_values: [ HTTP_REQUEST, HTTP_RESPONSE, POP3_REQUEST, POP3_RESOPONSE ]
+      email_from:
+        type: string
+      url:
+        type: string
+      options:
+        type: string
+      destination:
+        type: string
+
+  verigraph.types.Endpoint:
+    derived_from: tosca.nodes.Root
+    description: verigraph Endpoint node
+    properties:
+      names:
+        type: list
+        entry_schema:
+          type: string
+
+  verigraph.types.FieldModifier:
+    derived_from: tosca.nodes.Root
+    description: verigraph Field Modifier node
+    properties:
+      names:
+        type: list
+        entry_schema:
+          type: string
+
+  verigraph.types.Firewall:
+    derived_from: tosca.nodes.Root
+    description: verigraph Firewall node
+    properties:
+      elements:
+        type: map
+        entry_schema:
+          description: "source : destination" firewall mapping
+          type: string
+
+  verigraph.types.MailClient:
+    derived_from: tosca.nodes.Root
+    description: verigraph Mail Client node
+    attributes:
+      mailserver:
+        type: string
+
+  verigraph.types.MailServer:
+    derived_from: tosca.nodes.Root
+    descrtiption: verigraph Mail Server node
+    properties:
+      names:
+        type: list
+        entry_schema:
+          type: string
+
+  verigraph.types.Nat:
+    derived_from: tosca.nodes.Root
+    descrtiption: verigraph Nat node
+    properties:
+      sources:
+        type: list
+        entry_schema:
+          type: string
+
+  verigraph.types.VpnAccess:
+    deriver_from: tosca.nodes.Root
+    descrtiption: verigraph Vpn Access node
+    attributes:
+      vpnexit:
+        type: string
+
+  verigraph.types.VpnExit:
+    derived_from: tosca.nodes.Root
+    descrtiption: verigraph Vpn Exit node
+    attributes:
+      vpnaccess:
+        type: string
+
+  verigraph.types.WebClient:
+    derived_from: tosca.nodes.Root
+    descrtiption: verigraph web Client node
+    attributes:
+      nameWebServer:
+        type: string
+
+  verigraph.types.WebServer:
+    derived_from: tosca.nodes.Root
+    descrtiption: verigraph web Server node
+    properties:
+      names:
+        type: list
+        entry_schema:
+          type: string
+
+relationship_types:
+  verigraph.relationshipType.generic:
+    derived_from: tosca.relationships.Root
+    properties:
+      name:
+        type: string
+      source_id:
+        type: string
+      target_id:
+        type: string
diff --git a/verigraph/src/it/polito/verigraph/grpc/client/ToscaClient.java b/verigraph/src/it/polito/verigraph/grpc/client/ToscaClient.java
new file mode 100644 (file)
index 0000000..dbf8442
--- /dev/null
@@ -0,0 +1,299 @@
+/*******************************************************************************\r
+ * Copyright (c) 2018 Politecnico di Torino and others.\r
+ *\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Apache License, Version 2.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *******************************************************************************/\r
+package it.polito.verigraph.grpc.client;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.concurrent.TimeUnit;\r
+\r
+import io.grpc.ManagedChannel;\r
+import io.grpc.ManagedChannelBuilder;\r
+import io.grpc.StatusRuntimeException;\r
+import it.polito.verigraph.grpc.GetRequest;\r
+import it.polito.verigraph.grpc.GraphGrpc;\r
+import it.polito.verigraph.grpc.NewGraph;\r
+import it.polito.verigraph.grpc.NewTopologyTemplate;\r
+import it.polito.verigraph.grpc.NodeTemplateGrpc;\r
+import it.polito.verigraph.grpc.RequestID;\r
+import it.polito.verigraph.grpc.Status;\r
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;\r
+import it.polito.verigraph.grpc.ToscaPolicy;\r
+import it.polito.verigraph.grpc.ToscaRequestID;\r
+import it.polito.verigraph.grpc.ToscaTestGrpc;\r
+import it.polito.verigraph.grpc.ToscaVerificationGrpc;\r
+import it.polito.verigraph.grpc.VerigraphGrpc;\r
+\r
+public class ToscaClient {\r
+\r
+  private final ManagedChannel channel;\r
+  private final VerigraphGrpc.VerigraphBlockingStub blockingStub;\r
+\r
+  public ToscaClient(String host, int port) {\r
+    this(ManagedChannelBuilder.forAddress(host, port).usePlaintext(true));\r
+  }\r
+\r
+  /** Construct client for accessing toscaVerigraph server using the existing channel. */\r
+  public ToscaClient(ManagedChannelBuilder<?> channelBuilder) {\r
+    channel = channelBuilder.build();\r
+    blockingStub = VerigraphGrpc.newBlockingStub(channel);\r
+  }\r
+\r
+  /** Close the channel */\r
+  public void shutdown() throws InterruptedException {\r
+    channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);\r
+  }\r
+\r
+  /** Obtain a list of the available TopologyTemplates*/\r
+  public List<TopologyTemplateGrpc> getTopologyTemplates(){\r
+    List<TopologyTemplateGrpc> templates = new ArrayList<TopologyTemplateGrpc>();\r
+    GetRequest request = GetRequest.newBuilder().build();\r
+    boolean response_ok = true;\r
+\r
+    /*Iterates on received topology templates, prints on log file in case of errors*/\r
+    Iterator<TopologyTemplateGrpc> receivedTemplates;\r
+    try {\r
+      receivedTemplates = blockingStub.getTopologyTemplates(request);\r
+      System.out.println("++ Receiving TopologyTemplates...");\r
+      while(receivedTemplates.hasNext()) {\r
+        TopologyTemplateGrpc received = receivedTemplates.next();\r
+        if(received.getErrorMessage().equals("")) {\r
+          System.out.println("++ Correctly received TopologyTemplate --> id:" + received.getId());\r
+          templates.add(received);\r
+        } else\r
+          System.out.println("-- Received a TopologyTemplate with error: " + received.getErrorMessage());\r
+      }\r
+    } catch (StatusRuntimeException ex) {\r
+      System.out.println("-- RPC failed: " + ex.getMessage());\r
+      response_ok = false;\r
+    }\r
+    if(response_ok) {\r
+      System.out.println("++ All TopologyTemplates correctly received.");\r
+      return templates;\r
+    } else {\r
+      return null; //Function returns null in case of error to differentiate from empty list case.\r
+    }\r
+  }\r
+\r
+\r
+  /** Obtain a TopologyTemplate by ID */\r
+  public TopologyTemplateGrpc getTopologyTemplate(String id) {\r
+    ToscaRequestID request = ToscaRequestID.newBuilder().setIdTopologyTemplate(id).build();\r
+    TopologyTemplateGrpc response = TopologyTemplateGrpc.newBuilder().build();\r
+    try {\r
+      System.out.println("++ Receiving TopologyTemplate...");\r
+      response = blockingStub.getTopologyTemplate(request);\r
+      if(response.getErrorMessage().equals("")){\r
+        System.out.println("++ Received TopologyTemplate --> id:" + response.getId());\r
+        return response;\r
+      } else {\r
+        System.out.println("-- Error: " + response.getErrorMessage());\r
+        return response;\r
+      }\r
+    } catch (StatusRuntimeException ex) {\r
+      System.out.println("-- RPC failed: " + ex.getStatus());\r
+      return TopologyTemplateGrpc.newBuilder().setErrorMessage(ex.getStatus().getDescription()).build();\r
+    }\r
+  }\r
+\r
+\r
+  /** Creates a new TopologyTemplate, takes in input a TopologyTemplateGrpc  */\r
+  public NewTopologyTemplate createTopologyTemplate(TopologyTemplateGrpc topol) {\r
+    try {\r
+      //Sending new Topology and analyzing response\r
+      System.out.println("++ Sending the new TopologyTemplate...");\r
+      NewTopologyTemplate response = blockingStub.createTopologyTemplate(topol);\r
+      if(response.getSuccess())\r
+        System.out.println("++ TopologyTemplate successfully created with id: "+ response.getTopologyTemplate().getId());\r
+      else\r
+        System.out.println("-- TopologyTemplate creation failed: " + response.getErrorMessage());\r
+      return response;\r
+\r
+    } catch (StatusRuntimeException ex) {\r
+      System.out.println("-- RPC failed: " + ex.getStatus());\r
+      return NewTopologyTemplate.newBuilder().setSuccess(false).setErrorMessage(ex.getStatus().getDescription()).build();\r
+      //getDescription may be empty\r
+    }\r
+  }\r
+\r
+\r
+  /** Update a TopologyTemplate, takes in input a TopologyTemplateGrpc and the Topology's ID to be updated*/\r
+  public NewTopologyTemplate updateTopologyTemplate(TopologyTemplateGrpc topol, String id) {\r
+    //Checking if the inserted string is an object\r
+    try {\r
+      Long.valueOf(id);\r
+    } catch (NumberFormatException ex) {\r
+      System.out.println("-- The ID must a number according to Verigraph implementation.");\r
+      return NewTopologyTemplate.newBuilder().setSuccess(false)\r
+              .setErrorMessage("The ID must a number according to Verigraph implementation.").build();\r
+    }\r
+\r
+    //Update the topology ID\r
+    TopologyTemplateGrpc.Builder updTopol = TopologyTemplateGrpc.newBuilder();\r
+    try {\r
+      updTopol.setId(id)\r
+      .addAllNodeTemplate(topol.getNodeTemplateList())\r
+      .addAllRelationshipTemplate(topol.getRelationshipTemplateList());\r
+    } catch (Exception ex) {\r
+      System.out.println("-- Error: Incorrect fields implementation.");\r
+      return NewTopologyTemplate.newBuilder().setSuccess(false).setErrorMessage("Error: Incorrect fields implementation.").build();\r
+    }\r
+\r
+    //Sending updated Topology and analyzing response\r
+    try {\r
+\r
+      System.out.println("++ Sending the updated TopologyTemplate...");\r
+      NewTopologyTemplate response = blockingStub.updateTopologyTemplate(updTopol.build());\r
+      if(response.getSuccess())\r
+        System.out.println("++ TopologyTemplate successfully updated.");\r
+      else\r
+        System.out.println("-- TopologyTemplate not updated: " + response.getErrorMessage());\r
+      return response;\r
+\r
+    } catch (StatusRuntimeException ex) {\r
+      System.out.println("-- RPC failed: " + ex.getStatus());\r
+      return NewTopologyTemplate.newBuilder().setSuccess(false).setErrorMessage(ex.getStatus().getDescription()).build();\r
+    }\r
+  }\r
+\r
+\r
+  /** Delete a TopologyTemplate by ID */\r
+  public Status deleteTopologyTemplate(String id) {\r
+    try {\r
+      Long.valueOf(id);\r
+    } catch (NumberFormatException ex) {\r
+      System.out.println("-- The ID must a number according to Verigraph implementation.");\r
+      return Status.newBuilder().setSuccess(false)\r
+              .setErrorMessage("The ID must a number according to Verigraph implementation.").build();\r
+    }\r
+    ToscaRequestID request = ToscaRequestID.newBuilder().setIdTopologyTemplate(id).build();\r
+    try {\r
+      System.out.println("++ Sending delete request...");\r
+      Status response = blockingStub.deleteTopologyTemplate(request);\r
+      if(response.getSuccess())\r
+        System.out.println("++ TopologyTemplate successfully deleted.");\r
+      else\r
+        System.out.println("-- Error deleting TopologyTemplate : " + response.getErrorMessage());\r
+      return response;\r
+\r
+    } catch (StatusRuntimeException ex) {\r
+      System.out.println("-- RPC failed: " + ex.getStatus());\r
+      return Status.newBuilder().setSuccess(false).setErrorMessage(ex.getStatus().getDescription()).build();\r
+    }\r
+  }\r
+\r
+\r
+  /** VerifyPolicy */\r
+  public ToscaVerificationGrpc verifyPolicy(ToscaPolicy policy){\r
+    ToscaVerificationGrpc response;\r
+    try {\r
+      System.out.println("++ Sending ToscaPolicy...");\r
+      response = blockingStub.verifyToscaPolicy(policy);\r
+      if(!response.getErrorMessage().equals("")){\r
+        System.out.println("-- Error in operation: " + response.getErrorMessage());\r
+      }\r
+      else {\r
+        System.out.println("++ Result: " + response.getResult());\r
+        System.out.println("++ Comment: " + response.getComment());\r
+\r
+        for(ToscaTestGrpc test : response.getTestList()){\r
+          System.out.println("++ Traversed nodes:");\r
+          for(NodeTemplateGrpc node : test.getNodeTemplateList()){\r
+            System.out.println("\t Node "+node.getName());\r
+          }\r
+        }\r
+      }\r
+      return response;\r
+    } catch (StatusRuntimeException e) {\r
+      System.out.println("-- RPC failed: " + e.getStatus());\r
+      return ToscaVerificationGrpc.newBuilder().setSuccessOfOperation(false)\r
+              .setErrorMessage(e.getStackTrace().toString()).build();\r
+    }\r
+  }\r
+\r
+\r
+  //Methods added for backward compatibility with JSON grpc, only create and update methods need to be redefined\r
+  //The reason is that the tosca Grpc converter requires a coherent numbering of IDs while the previous\r
+  //implementations exploits names to identify nodes and can considers IDs as not strictly required attributes.\r
+\r
+  public NewGraph createGraph(GraphGrpc gr) {\r
+    NewGraph response;\r
+    try {\r
+      response = blockingStub.createGraph(gr);\r
+      if(response.getSuccess())\r
+        System.out.println("++ TopologyTemplate successfully created with id: "+ response.getGraph().getId());\r
+      else\r
+        System.out.println("-- TopologyTemplate creation failed: " + response.getErrorMessage());\r
+      return response;\r
+    } catch (StatusRuntimeException e) {\r
+      System.err.println("-- RPC failed: " + e.getStatus());\r
+      return NewGraph.newBuilder().setSuccess(false).setErrorMessage(e.getStatus().getDescription()).build();\r
+    }\r
+\r
+  }\r
+\r
+  public NewGraph updateGraph(long idGraph, GraphGrpc newGraph) {\r
+\r
+    GraphGrpc gr = GraphGrpc.newBuilder(newGraph).setId(idGraph).build();\r
+    NewGraph response;\r
+    try {\r
+      response = blockingStub.updateGraph(gr);\r
+      if(response.getSuccess())\r
+        System.out.println("++ TopologyTemplate successfully created with id: "+ response.getGraph().getId());\r
+      else\r
+        System.out.println("-- TopologyTemplate creation failed: " + response.getErrorMessage());\r
+      return response;\r
+    } catch (StatusRuntimeException e) {\r
+      System.err.println("-- RPC failed: " + e.getStatus());\r
+      return NewGraph.newBuilder().setSuccess(false).setErrorMessage(e.getStatus().getDescription()).build();\r
+    }\r
+  }\r
+\r
+  public GraphGrpc getGraph(long idGraph) {\r
+\r
+    RequestID request = RequestID.newBuilder().setIdGraph(idGraph).build() ;\r
+    try {\r
+      System.out.println("++ Receiving TopologyTemplate...");\r
+      GraphGrpc graph = blockingStub.getGraph(request);\r
+      System.out.println("++ Received TopologyTemplate --> id:" + graph.getId());\r
+      if(!graph.getErrorMessage().equals("")){\r
+        System.out.println("-- Error : " + graph.getErrorMessage());\r
+        return graph;\r
+      }\r
+      return graph;\r
+    } catch (StatusRuntimeException ex) {\r
+      System.err.println("-- RPC failed: " + ex.getStatus());\r
+      return null;\r
+    }\r
+  }\r
+\r
+\r
+  public List<GraphGrpc> getGraphs() {\r
+    List<GraphGrpc> graphsReceived = new ArrayList<GraphGrpc>();\r
+    GetRequest request = GetRequest.newBuilder().build();\r
+    Iterator<GraphGrpc> graphs;\r
+    try {\r
+      graphs = blockingStub.getGraphs(request);\r
+      System.out.println("++ Receiving TopologyTemplates...");\r
+      while (graphs.hasNext()) {\r
+        GraphGrpc graph = graphs.next();\r
+        if(graph.getErrorMessage().equals("")){\r
+          System.out.println("++ Correctly received graph --> id:" + graph.getId());\r
+          graphsReceived.add(graph);\r
+        }else{\r
+          System.out.println("-- Received a graph with error : " + graph.getErrorMessage());\r
+        }\r
+      }\r
+    } catch (StatusRuntimeException ex) {\r
+      System.err.println("-- RPC failed : " + ex.getStatus());\r
+      return null;\r
+    }\r
+    return graphsReceived;\r
+  }\r
+}\r
index 43859db..96c52a5 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2017 Politecnico di Torino and others.
+ * Copyright (c) 2017/18 Politecnico di Torino and others.
  *
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Apache License, Version 2.0
@@ -12,16 +12,18 @@ import java.io.IOException;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.base.Splitter;
+
 import it.polito.verigraph.grpc.ConfigurationGrpc;
 import it.polito.verigraph.grpc.GraphGrpc;
 import it.polito.verigraph.grpc.NeighbourGrpc;
 import it.polito.verigraph.grpc.NodeGrpc;
+import it.polito.verigraph.grpc.NodeGrpc.FunctionalType;
 import it.polito.verigraph.grpc.TestGrpc;
 import it.polito.verigraph.grpc.VerificationGrpc;
-import it.polito.verigraph.grpc.NodeGrpc.FunctionalType;
 import it.polito.verigraph.model.Configuration;
 import it.polito.verigraph.model.Graph;
 import it.polito.verigraph.model.Neighbour;
@@ -29,6 +31,7 @@ import it.polito.verigraph.model.Node;
 import it.polito.verigraph.model.Test;
 import it.polito.verigraph.model.Verification;
 
+
 public class GrpcUtils {
     private static final Logger logger = Logger.getLogger(GrpcUtils.class.getName());
 
@@ -43,6 +46,7 @@ public class GrpcUtils {
         //id is not present
         Neighbour ne = new Neighbour();
         ne.setName(request.getName());
+        ne.setId(request.getId());
         return ne;
     }
 
@@ -86,13 +90,17 @@ public class GrpcUtils {
     }
 
     public static Node deriveNode(NodeGrpc request) {
-        //id is not present
+       //id is not present
         Node node = new Node();
         node.setName(request.getName());
         node.setFunctional_type(request.getFunctionalType().toString());
         Configuration conf = deriveConfiguration(request.getConfiguration());
         node.setConfiguration(conf);
 
+        //Modification for Tosca CLI
+        Long id = request.getId();
+        if( id != null) node.setId(request.getId());
+
         Map<Long,Neighbour> neighours = node.getNeighbours();
         long i = 1;
         for(NeighbourGrpc neighbour:request.getNeighbourList()){
@@ -106,7 +114,7 @@ public class GrpcUtils {
     public static GraphGrpc obtainGraph(Graph graph){
         GraphGrpc.Builder gr = GraphGrpc.newBuilder();
         gr.setId(graph.getId());
-        for(Node node:graph.getNodes().values()){
+        for(Node node : graph.getNodes().values()){
             NodeGrpc ng = obtainNode(node);
             gr.addNode(ng);
         }
@@ -116,14 +124,16 @@ public class GrpcUtils {
     public static Graph deriveGraph(GraphGrpc request) {
         //id is not present
         Graph graph = new Graph();
-
+        //Modification for Tosca CLI
+        Long id = request.getId();
+        if( id != null) graph.setId(request.getId());
+        
         long i=1;
         Map<Long, Node> nodes= graph.getNodes();
         for(NodeGrpc node:request.getNodeList()){
             Node ng = deriveNode(node);
-            nodes.put(i++, ng);  
+            nodes.put(i++, ng);
         }
-
         return graph;
     }
 
@@ -142,12 +152,13 @@ public class GrpcUtils {
         return ver.build();
     }
 
-    /**Intended for string that begins with "?"
-     * */
+
+    /** Intended for string that begins with "?" */
     public static Map<String,String> getParamGivenString(String str){
         String string = str.substring(1);
         final Map<String, String> map = Splitter.on('&').trimResults().withKeyValueSeparator("=").
                 split(string);
         return map;
     }
+
 }
index 1839b7e..c6b69b0 100644 (file)
@@ -15,9 +15,13 @@ import java.util.logging.FileHandler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.SimpleFormatter;
+
 import io.grpc.Server;
 import io.grpc.ServerBuilder;
 import io.grpc.stub.StreamObserver;
+import it.polito.verigraph.exception.BadRequestException;
+import it.polito.verigraph.exception.DataNotFoundException;
+import it.polito.verigraph.exception.ForbiddenException;
 import it.polito.verigraph.grpc.ConfigurationGrpc;
 import it.polito.verigraph.grpc.GetRequest;
 import it.polito.verigraph.grpc.GraphGrpc;
@@ -25,15 +29,17 @@ import it.polito.verigraph.grpc.NeighbourGrpc;
 import it.polito.verigraph.grpc.NewGraph;
 import it.polito.verigraph.grpc.NewNeighbour;
 import it.polito.verigraph.grpc.NewNode;
+import it.polito.verigraph.grpc.NewTopologyTemplate;
 import it.polito.verigraph.grpc.NodeGrpc;
 import it.polito.verigraph.grpc.Policy;
 import it.polito.verigraph.grpc.RequestID;
 import it.polito.verigraph.grpc.Status;
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;
+import it.polito.verigraph.grpc.ToscaPolicy;
+import it.polito.verigraph.grpc.ToscaRequestID;
+import it.polito.verigraph.grpc.ToscaVerificationGrpc;
 import it.polito.verigraph.grpc.VerificationGrpc;
 import it.polito.verigraph.grpc.VerigraphGrpc;
-import it.polito.verigraph.exception.BadRequestException;
-import it.polito.verigraph.exception.DataNotFoundException;
-import it.polito.verigraph.exception.ForbiddenException;
 import it.polito.verigraph.model.Configuration;
 import it.polito.verigraph.model.Graph;
 import it.polito.verigraph.model.Neighbour;
@@ -44,6 +50,8 @@ import it.polito.verigraph.service.GraphService;
 import it.polito.verigraph.service.NeighbourService;
 import it.polito.verigraph.service.NodeService;
 import it.polito.verigraph.service.VerificationService;
+import it.polito.verigraph.tosca.converter.grpc.GraphToGrpc;
+import it.polito.verigraph.tosca.converter.grpc.GrpcToGraph;
 
 public class Service {
     /** Port on which the server should run. */
@@ -107,7 +115,7 @@ public class Service {
         }
     }
 
-    /**Here start method of my implementation*/
+    /** Here start methods */
     private class VerigraphImpl extends VerigraphGrpc.VerigraphImplBase{
 
         /** Here start methods of GraphResource*/
@@ -307,8 +315,7 @@ public class Service {
 
         @Override
         public void updateNode(NodeGrpc request, StreamObserver<NewNode> responseObserver) {
-            NewNode.Builder response = NewNode.newBuilder(); 
-            try{
+            NewNode.Builder response = NewNode.newBuilder();            try{
                 Node node = GrpcUtils.deriveNode(request);
                 node.setId(request.getId());
                 Node newNode = nodeService.updateNode(request.getIdGraph(), node);
@@ -340,7 +347,8 @@ public class Service {
                 }
                 Node node = nodeService.getNode(request.getIdGraph(), request.getIdNode());
                 if (node == null){
-                    throw new BadRequestException("Node with id " + request.getIdNode() + " not found in graph with id " + request.getIdGraph());
+                    throw new BadRequestException("Node with id " + request.getIdNode() +
+                            " not found in graph with id " + request.getIdGraph());
                 }
                 Configuration nodeConfiguration = GrpcUtils.deriveConfiguration(request);
                 Node nodeCopy = new Node();
@@ -386,8 +394,7 @@ public class Service {
                 NeighbourGrpc nr = NeighbourGrpc.newBuilder().setErrorMessage(internalError).build();
                 responseObserver.onNext(nr);
                 logger.log(Level.WARNING, ex.getMessage());
-            }           
-            responseObserver.onCompleted();
+            }                      responseObserver.onCompleted();
         }
 
         @Override
@@ -462,5 +469,149 @@ public class Service {
             responseObserver.onNext(response.build());
             responseObserver.onCompleted();
         }
+
+        /** Here start methods of TOSCA gRPC server */             @Override
+        public void getTopologyTemplates (GetRequest request, StreamObserver<TopologyTemplateGrpc> responseObserver) {
+            boolean not_correct = false;
+            try {
+                for(Graph item : graphService.getAllGraphs()) {
+                    TopologyTemplateGrpc topol = GraphToGrpc.obtainTopologyTemplate(item);
+                    responseObserver.onNext(topol);
+                }
+            } catch(Exception ex){
+                logger.log(Level.WARNING, ex.getMessage());
+                not_correct = true;
+            }
+            if(not_correct)
+                responseObserver.onNext(TopologyTemplateGrpc.newBuilder()
+                        .setErrorMessage("Internal Server Error while retrieving TopologyTemplate").build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getTopologyTemplate (ToscaRequestID request, StreamObserver<TopologyTemplateGrpc> responseObserver) {
+            try {
+                Long graphID = Long.valueOf(request.getIdTopologyTemplate());
+                //this method will throw a NumberFormatException in case the ID is not representable as a long
+                Graph graph = graphService.getGraph(graphID);
+                TopologyTemplateGrpc topol = GraphToGrpc.obtainTopologyTemplate(graph);
+                responseObserver.onNext(topol);
+            } catch(ForbiddenException | DataNotFoundException ex) {
+                TopologyTemplateGrpc topolError = TopologyTemplateGrpc.newBuilder().setErrorMessage(ex.getMessage()).build();
+                responseObserver.onNext(topolError);
+                logger.log(Level.WARNING, ex.getMessage());
+            } catch(NumberFormatException ex) {
+                TopologyTemplateGrpc topolError = TopologyTemplateGrpc.newBuilder()
+                        .setErrorMessage("The TopologyTemplate ID must be a long value.").build();
+                responseObserver.onNext(topolError);
+                logger.log(Level.WARNING, ex.getMessage());
+            } catch(Exception ex) {
+                TopologyTemplateGrpc topolError = TopologyTemplateGrpc.newBuilder().setErrorMessage(internalError).build();
+                responseObserver.onNext(topolError);
+                logger.log(Level.WARNING, ex.getMessage());
+            }
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void createTopologyTemplate (TopologyTemplateGrpc request, StreamObserver<NewTopologyTemplate> responseObserver) {
+            NewTopologyTemplate.Builder response = NewTopologyTemplate.newBuilder();
+            try{
+                Graph graph = GrpcToGraph.deriveGraph(request);
+                Graph newGraph = graphService.addGraph(graph);
+                response.setSuccess(true).setTopologyTemplate(GraphToGrpc.obtainTopologyTemplate(newGraph));
+                } catch(BadRequestException ex) {
+                ex.printStackTrace();
+                response.setSuccess(false).setErrorMessage("Provided invalid request to the service.");
+                logger.log(Level.WARNING, ex.getClass().toString());
+                logger.log(Level.WARNING, ex.getMessage());
+            } catch(Exception ex) {
+                ex.printStackTrace();
+                response.setSuccess(false).setErrorMessage(internalError);
+                logger.log(Level.WARNING, ex.getClass().toString());
+                logger.log(Level.WARNING, ex.getMessage());
+            }
+            responseObserver.onNext(response.build());
+            responseObserver.onCompleted();
+        }
+
+
+        @Override
+        public void updateTopologyTemplate (TopologyTemplateGrpc request, StreamObserver<NewTopologyTemplate> responseObserver) {
+            NewTopologyTemplate.Builder response = NewTopologyTemplate.newBuilder();
+            try{
+                Graph graph = GrpcToGraph.deriveGraph(request);
+                Graph newGraph = graphService.updateGraph(graph);
+                response.setSuccess(true).setTopologyTemplate(GraphToGrpc.obtainTopologyTemplate(newGraph));
+            } catch(ForbiddenException | DataNotFoundException | BadRequestException ex){
+                response.setSuccess(false).setErrorMessage(ex.getMessage());
+                logger.log(Level.WARNING, ex.getMessage());
+            } catch(Exception ex){
+                response.setSuccess(false).setErrorMessage(internalError);
+                logger.log(Level.WARNING, ex.getMessage());
+            }
+            responseObserver.onNext(response.build());
+            responseObserver.onCompleted();
+        }
+
+
+        @Override
+        public void deleteTopologyTemplate (ToscaRequestID request, StreamObserver<Status> responseObserver) {
+            Status.Builder response = Status.newBuilder();
+            Long graphID = null;
+            try{
+                graphID = Long.valueOf(request.getIdTopologyTemplate());
+                //this method will throw a NumberFormatException in case the ID is not representable as a long
+                graphService.removeGraph(graphID);
+                response.setSuccess(true);
+            } catch(ForbiddenException | DataNotFoundException ex) {
+                response.setSuccess(false).setErrorMessage(ex.getMessage());
+                logger.log(Level.WARNING, ex.getMessage());
+            } catch(NumberFormatException ex) {
+                response.setSuccess(false).setErrorMessage("The TopologyTemplate ID must be a long value.");
+                logger.log(Level.WARNING, ex.getMessage());
+            } catch(Exception ex) {
+                response.setSuccess(false).setErrorMessage(internalError);
+                logger.log(Level.WARNING, ex.getMessage());
+            }
+            responseObserver.onNext(response.build());
+            responseObserver.onCompleted();
+        }
+
+
+        @Override
+        public void verifyToscaPolicy(ToscaPolicy request, StreamObserver<ToscaVerificationGrpc> responseObserver) {
+            try{
+                //Convert request
+                VerificationBean verify = new VerificationBean();
+                verify.setDestination(request.getDestination());
+                verify.setSource(request.getSource());
+                verify.setType(request.getType().toString());
+                verify.setMiddlebox(request.getMiddlebox());
+
+                //Convert Response
+                Long graphID = Long.valueOf(request.getIdTopologyTemplate());
+                //this method will throw a NumberFormatException in case the ID is not representable as a long
+                Verification ver = verificationService.verify(graphID, verify);
+                responseObserver.onNext(GraphToGrpc.obtainToscaVerification(ver));
+            } catch(ForbiddenException | DataNotFoundException | BadRequestException ex) {
+                ToscaVerificationGrpc verError = ToscaVerificationGrpc.newBuilder().setSuccessOfOperation(false)
+                        .setErrorMessage(ex.getMessage()).build();
+                responseObserver.onNext(verError);
+                logger.log(Level.WARNING, ex.getMessage());
+            } catch(NumberFormatException ex) {
+                ToscaVerificationGrpc verError = ToscaVerificationGrpc.newBuilder().setSuccessOfOperation(false)
+                        .setErrorMessage("The TopologyTemplate ID must be a long value.").build();
+                responseObserver.onNext(verError);
+                logger.log(Level.WARNING, ex.getMessage());
+            } catch(Exception ex) {
+                ToscaVerificationGrpc verError = ToscaVerificationGrpc.newBuilder().setSuccessOfOperation(false)
+                        .setErrorMessage(internalError).build();
+                responseObserver.onNext(verError);
+                logger.log(Level.WARNING, ex.getMessage());
+            }                     responseObserver.onCompleted();
+        }
+
+
     }
 }
diff --git a/verigraph/src/it/polito/verigraph/grpc/tosca/test/GrpcToscaTest.java b/verigraph/src/it/polito/verigraph/grpc/tosca/test/GrpcToscaTest.java
new file mode 100644 (file)
index 0000000..5771406
--- /dev/null
@@ -0,0 +1,425 @@
+/*******************************************************************************\r
+ * Copyright (c) 2018 Politecnico di Torino and others.\r
+ *\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Apache License, Version 2.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *******************************************************************************/\r
+package it.polito.verigraph.grpc.tosca.test;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertNotNull;\r
+import static org.junit.Assert.fail;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.junit.After;\r
+import org.junit.Before;\r
+import org.junit.FixMethodOrder;\r
+import org.junit.Test;\r
+import org.junit.runner.RunWith;\r
+import org.junit.runners.JUnit4;\r
+import org.junit.runners.MethodSorters;\r
+\r
+import it.polito.verigraph.grpc.NewTopologyTemplate;\r
+import it.polito.verigraph.grpc.NodeTemplateGrpc;\r
+import it.polito.verigraph.grpc.NodeTemplateGrpc.Type;\r
+import it.polito.verigraph.grpc.RelationshipTemplateGrpc;\r
+import it.polito.verigraph.grpc.Status;\r
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;\r
+import it.polito.verigraph.grpc.ToscaConfigurationGrpc;\r
+import it.polito.verigraph.grpc.ToscaPolicy;\r
+import it.polito.verigraph.grpc.ToscaPolicy.PolicyType;\r
+import it.polito.verigraph.grpc.ToscaVerificationGrpc;\r
+import it.polito.verigraph.grpc.client.ToscaClient;\r
+import it.polito.verigraph.grpc.server.Service;\r
+\r
+@RunWith(JUnit4.class)\r
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)\r
+public class GrpcToscaTest {\r
+    private Service server;\r
+    private ToscaClient client;\r
+    private TopologyTemplateGrpc testTemplate, simpleTestTemplate;\r
+\r
+    public GrpcToscaTest() {\r
+        this.generateTestTemplate();\r
+    }\r
+\r
+    @Before\r
+    public void setUpBeforeClass() throws Exception {\r
+        client = new ToscaClient("localhost" , 50051);\r
+        server = new Service(50051);\r
+        server.start();\r
+    }\r
+\r
+    @After\r
+    public void tearDown() throws Exception {\r
+        server.stop();\r
+        client.shutdown();\r
+    }\r
+\r
+\r
+    @Test\r
+    public void test0Creation() {\r
+        System.out.println("\nTest A: Graph Creation.");\r
+\r
+        NewTopologyTemplate response = client.createTopologyTemplate(testTemplate);\r
+        assertNotNull("Returned a NULL graph", response);\r
+        assertEquals(response.getSuccess(), true);\r
+        assertEquals("Error report: " + response.getErrorMessage(), "", response.getErrorMessage());\r
+\r
+        Status resp = client.deleteTopologyTemplate(response.getTopologyTemplate().getId());\r
+        assertEquals("Error while deleting testTemplate.", true, resp.getSuccess());\r
+\r
+        System.out.println("Test A completed\n");\r
+\r
+        return;\r
+    }\r
+\r
+\r
+    @Test\r
+    public void test1Reading() {\r
+        System.out.println("\nTest B: Graph Reading.");\r
+\r
+        //Creating a test graph on remote repository\r
+        System.out.println("Phase B.1 -- Creating a test graph.");\r
+        NewTopologyTemplate response = client.createTopologyTemplate(simpleTestTemplate);\r
+        assertNotNull("Returned a NULL graph", response);\r
+        assertEquals(true, response.getSuccess());\r
+        assertEquals("Error report: " + response.getErrorMessage(), "", response.getErrorMessage());\r
+\r
+        //Reading remote graph.\r
+        System.out.println("Phase B.2 -- Reading remote graph.");\r
+        TopologyTemplateGrpc retrieved = client.getTopologyTemplate(response.getTopologyTemplate().getId());\r
+        assertNotNull("Retrieved a NULL graph", retrieved);\r
+        assertEquals(retrieved.getId(), response.getTopologyTemplate().getId());\r
+\r
+        //Nodes checking\r
+        System.out.println("Phase B.3 -- Checking graph's nodes.");\r
+        assertEquals(retrieved.getNodeTemplateCount(), 3);\r
+        assertEquals("Node1 name error", response.getTopologyTemplate().getNodeTemplateList().get(0).getName(),\r
+                retrieved.getNodeTemplateList().get(0).getName());\r
+        assertEquals("Node2 name error", response.getTopologyTemplate().getNodeTemplateList().get(1).getName(),\r
+                retrieved.getNodeTemplateList().get(1).getName());\r
+        assertEquals("Node3 name error", response.getTopologyTemplate().getNodeTemplateList().get(2).getName(),\r
+                retrieved.getNodeTemplateList().get(2).getName());\r
+\r
+        //Relationships checking\r
+        System.out.println("Phase B.4 -- Checking graph's relationships.");\r
+        assertEquals(retrieved.getRelationshipTemplateCount(), 4);\r
+        String source1=null, target1=null;\r
+        String source2=null, target2=null;\r
+        String source3=null, target3=null;\r
+        String source4=null, target4=null;\r
+        for (NodeTemplateGrpc node : retrieved.getNodeTemplateList()){\r
+            if(node.getId().equals(retrieved.getRelationshipTemplateList().get(0).getIdSourceNodeTemplate()))\r
+                source1=node.getName();\r
+            if(node.getId().equals(retrieved.getRelationshipTemplateList().get(0).getIdTargetNodeTemplate()))\r
+                target1=node.getName();\r
+            if(node.getId().equals(retrieved.getRelationshipTemplateList().get(1).getIdSourceNodeTemplate()))\r
+                source2=node.getName();\r
+            if(node.getId().equals(retrieved.getRelationshipTemplateList().get(1).getIdTargetNodeTemplate()))\r
+                target2=node.getName();\r
+            if(node.getId().equals(retrieved.getRelationshipTemplateList().get(2).getIdSourceNodeTemplate()))\r
+                source3=node.getName();\r
+            if(node.getId().equals(retrieved.getRelationshipTemplateList().get(2).getIdTargetNodeTemplate()))\r
+                target3=node.getName();\r
+            if(node.getId().equals(retrieved.getRelationshipTemplateList().get(3).getIdSourceNodeTemplate()))\r
+                source4=node.getName();\r
+            if(node.getId().equals(retrieved.getRelationshipTemplateList().get(3).getIdTargetNodeTemplate()))\r
+                target4=node.getName();\r
+        }\r
+\r
+        assertEquals("Relat1 name error", retrieved.getRelationshipTemplateList().get(0).getName(), source1+"to"+target1);\r
+        assertEquals("Relat2 name error", retrieved.getRelationshipTemplateList().get(1).getName(), source2+"to"+target2);\r
+        assertEquals("Relat3 name error", retrieved.getRelationshipTemplateList().get(2).getName(), source3+"to"+target3);\r
+        assertEquals("Relat4 name error", retrieved.getRelationshipTemplateList().get(3).getName(), source4+"to"+target4);\r
+\r
+        System.out.println("Phase B.5 -- Deleting graph.");\r
+        Status resp = client.deleteTopologyTemplate(response.getTopologyTemplate().getId());\r
+        assertEquals("Error while deleting simpleTestTemplate", true, resp.getSuccess());\r
+\r
+\r
+        System.out.println("Test B completed.\n");\r
+        return;\r
+    }\r
+\r
+    @Test\r
+    public void test2Update() {\r
+        System.out.println("\nTest C: Update.");\r
+\r
+        //Creating a test graph on remote repository\r
+        System.out.println("Phase C.1 -- Creating a test graph.");\r
+        NewTopologyTemplate response = client.createTopologyTemplate(simpleTestTemplate);\r
+        assertNotNull("Returned a NULL graph", response);\r
+        assertEquals(true, response.getSuccess());\r
+        assertEquals("Error report: " + response.getErrorMessage(), "", response.getErrorMessage());\r
+\r
+        //Reading remote graph.\r
+        System.out.println("Phase C.2 -- Reading remote graph.");\r
+        TopologyTemplateGrpc retrieved = client.getTopologyTemplate(response.getTopologyTemplate().getId());\r
+        assertNotNull("Retrieved a NULL graph", retrieved);\r
+        assertEquals(retrieved.getId(), response.getTopologyTemplate().getId());\r
+\r
+        //Updating a TopologyTemplateGrpc\r
+        System.out.println("Phase C.3 -- Updating a test graph.");\r
+        TopologyTemplateGrpc.Builder templ = TopologyTemplateGrpc.newBuilder();\r
+        List<NodeTemplateGrpc> nodes = new ArrayList<NodeTemplateGrpc>();\r
+        List<RelationshipTemplateGrpc> relats = new ArrayList<RelationshipTemplateGrpc>();\r
+\r
+        ToscaConfigurationGrpc node1conf = ToscaConfigurationGrpc.newBuilder().setDescription("node1configuration")\r
+                .setId("15").setConfiguration("[]").build();\r
+        NodeTemplateGrpc node1 = NodeTemplateGrpc.newBuilder().setConfiguration(node1conf).setId("999")\r
+                .setName("webserver1").setType(Type.webserver).build();\r
+        nodes.add(node1);\r
+\r
+        ToscaConfigurationGrpc node2conf = ToscaConfigurationGrpc.newBuilder().setDescription("node2configuration")\r
+                .setId("16").setConfiguration("[{\r\n\"protocol\":\"HTTP_REQUEST\",\r\n \"url\":\"www.facebook.com\"\r\n }]").build();\r
+        NodeTemplateGrpc node2 = NodeTemplateGrpc.newBuilder().setConfiguration(node2conf).setId("888")\r
+                .setName("host2").setType(Type.endhost).build();\r
+        nodes.add(node2);\r
+\r
+        RelationshipTemplateGrpc rel0 = RelationshipTemplateGrpc.newBuilder().setId("1001")\r
+                .setIdSourceNodeTemplate("999").setIdTargetNodeTemplate("888").setName("webserver1tohost2").build();\r
+        relats.add(rel0);\r
+\r
+        RelationshipTemplateGrpc rel1 = RelationshipTemplateGrpc.newBuilder().setId("1002")\r
+                .setIdSourceNodeTemplate("888").setIdTargetNodeTemplate("999").setName("host2towebserver1").build();\r
+        relats.add(rel1);\r
+\r
+        TopologyTemplateGrpc newTestTemplate = templ.addAllNodeTemplate(nodes).addAllRelationshipTemplate(relats).setId("9").build();\r
+        NewTopologyTemplate updated = client.updateTopologyTemplate(newTestTemplate, response.getTopologyTemplate().getId());\r
+        assertNotNull("Returned a NULL graph", updated);\r
+        assertEquals(true, updated.getSuccess());\r
+        assertEquals("Error report: " + updated.getErrorMessage(), "", updated.getErrorMessage());\r
+\r
+        //Reading remote graph.\r
+        System.out.println("Phase C.4 -- Reading remote graph.");\r
+        TopologyTemplateGrpc retrieved2 = client.getTopologyTemplate(response.getTopologyTemplate().getId());\r
+        assertNotNull("Retrieved a NULL graph", retrieved2);\r
+        assertEquals(retrieved2.getId(), response.getTopologyTemplate().getId());\r
+\r
+        //Nodes checking\r
+        System.out.println("Phase C.5 -- Checking updated graph's nodes.");\r
+        assertEquals(retrieved2.getNodeTemplateCount(), 2);\r
+        assertEquals("Node1 name error", updated.getTopologyTemplate().getNodeTemplateList().get(0).getName(),\r
+                retrieved2.getNodeTemplateList().get(0).getName());\r
+        assertEquals("Node2 name error", updated.getTopologyTemplate().getNodeTemplateList().get(1).getName(),\r
+                retrieved2.getNodeTemplateList().get(1).getName());\r
+\r
+        //Relationships checking\r
+        System.out.println("Phase C.6 -- Checking updated graph's relationships.");\r
+        assertEquals(retrieved2.getRelationshipTemplateCount(), 2);\r
+        String source1=null, target1=null;\r
+        String source2=null, target2=null;\r
+        for (NodeTemplateGrpc node : retrieved2.getNodeTemplateList()){\r
+            if(node.getId().equals(retrieved2.getRelationshipTemplateList().get(0).getIdSourceNodeTemplate()))\r
+                source1=node.getName();\r
+            if(node.getId().equals(retrieved2.getRelationshipTemplateList().get(0).getIdTargetNodeTemplate()))\r
+                target1=node.getName();\r
+            if(node.getId().equals(retrieved2.getRelationshipTemplateList().get(1).getIdSourceNodeTemplate()))\r
+                source2=node.getName();\r
+            if(node.getId().equals(retrieved2.getRelationshipTemplateList().get(1).getIdTargetNodeTemplate()))\r
+                target2=node.getName();\r
+        }\r
+\r
+        assertEquals("Relat1 name error", retrieved2.getRelationshipTemplateList().get(0).getName(), source1+"to"+target1);\r
+        assertEquals("Relat2 name error", retrieved2.getRelationshipTemplateList().get(1).getName(), source2+"to"+target2);\r
+\r
+        System.out.println("Phase C.6 -- Deleting graph.");\r
+        Status resp = client.deleteTopologyTemplate(updated.getTopologyTemplate().getId());\r
+        assertEquals("Error while deleting simpleTestTemplate", true, resp.getSuccess());\r
+\r
+        System.out.println("Test C completed.\n");\r
+        return;\r
+    }\r
+\r
+\r
+    @Test\r
+    public void test3Verification() {\r
+        System.out.println("\nTest D: Verification.");\r
+        NewTopologyTemplate response = client.createTopologyTemplate(testTemplate);\r
+        if(response == null | response.getSuccess() != true) {\r
+            fail("Test failed, unable to load the graph.");\r
+            return;\r
+        }\r
+\r
+        //The Id of the graph on which we are going to perform tests\r
+        String testTemplateId = response.getTopologyTemplate().getId();\r
+\r
+        //REACHABILITY test\r
+        System.out.println("Phase 1.1 - Reachability SAT.");\r
+        ToscaPolicy policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)\r
+                .setType(PolicyType.reachability).setSource("host2").setDestination("host1").build();\r
+        ToscaVerificationGrpc result = client.verifyPolicy(policy);\r
+        assertNotNull("There was no response", result);\r
+        assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "SAT", result.getResult());\r
+        assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());\r
+\r
+        result = null;\r
+        System.out.println("Phase 1.2 - Reachability UNSAT.");\r
+        policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)\r
+                .setType(PolicyType.reachability).setSource("host1").setDestination("antispamNode1").build();\r
+        result = client.verifyPolicy(policy);\r
+        assertNotNull("There was no response", result);\r
+        assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "UNSAT", result.getResult());\r
+        assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());\r
+\r
+        //ISOLATION test\r
+        result = null;\r
+        System.out.println("Phase 2.1 - Isolation SAT.");\r
+        policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)\r
+                .setType(PolicyType.isolation).setSource("host2").setDestination("host1").setMiddlebox("webserver1").build();\r
+        result = client.verifyPolicy(policy);\r
+        assertNotNull("There was no response", result);\r
+        assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "SAT", result.getResult());\r
+        assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());\r
+\r
+        System.out.println("Phase 2.2 - Isolation UNSAT.");\r
+        policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)\r
+                .setType(PolicyType.isolation).setSource("host2").setDestination("host1").setMiddlebox("fw").build();\r
+        result = client.verifyPolicy(policy);\r
+        assertNotNull("There was no response", result);\r
+        assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "UNSAT", result.getResult());\r
+        assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());\r
+\r
+        //TRAVERSAL test\r
+        result = null;\r
+        System.out.println("Phase 3.1 - Traversal SAT.");\r
+        policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)\r
+                .setType(PolicyType.traversal).setSource("host2").setDestination("host1").setMiddlebox("fw").build();\r
+        result = client.verifyPolicy(policy);\r
+        assertNotNull("There was no response", result);\r
+        assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "SAT", result.getResult());\r
+        assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());\r
+\r
+        System.out.println("Phase 3.2 - Traversal UNSAT.");\r
+        policy = ToscaPolicy.newBuilder().setIdTopologyTemplate(testTemplateId)\r
+                .setType(PolicyType.traversal).setSource("host2").setDestination("webserver1").setMiddlebox("fw").build();\r
+        result = client.verifyPolicy(policy);\r
+        assertNotNull("There was no response", result);\r
+        assertEquals("Unexpected result : " + result.getResult() + " - " + result.getComment(), "UNSAT", result.getResult());\r
+        assertEquals("Error report: " + result.getErrorMessage(), "", result.getErrorMessage());\r
+\r
+        Status resp = client.deleteTopologyTemplate(testTemplateId);\r
+        assertEquals("Error while deleting testTemplate", true, resp.getSuccess());\r
+\r
+        System.out.println("Test D completed.\n");\r
+        return;\r
+    }\r
+\r
+\r
+    @Test\r
+    public void test4Deletion() {\r
+        System.out.println("\nTest E: Deletion");\r
+        NewTopologyTemplate templ = client.createTopologyTemplate(testTemplate);\r
+\r
+        if(templ.getSuccess() != true) {\r
+            fail("Unable to create the graph.");\r
+            return;\r
+        }else {\r
+            Status resp = client.deleteTopologyTemplate(templ.getTopologyTemplate().getId());\r
+            assertEquals("Error while deleting testTemplate", true, resp.getSuccess());\r
+        }\r
+\r
+        System.out.println("Test E completed.\n");\r
+        return;\r
+    }\r
+\r
+\r
+    //Generates a correct instance of a TopologyTemplateGrpc to be used in tests\r
+    public void generateTestTemplate() {\r
+        TopologyTemplateGrpc.Builder templ = TopologyTemplateGrpc.newBuilder();\r
+        List<NodeTemplateGrpc> nodes = new ArrayList<NodeTemplateGrpc>();\r
+        List<RelationshipTemplateGrpc> relats = new ArrayList<RelationshipTemplateGrpc>();\r
+\r
+        //Definition of nodes\r
+        ToscaConfigurationGrpc node0conf = ToscaConfigurationGrpc.newBuilder().setDescription("node0configuration")\r
+                .setId("100").setConfiguration("[{\r\n\"webserver1\":\"host2\"\r\n}]").build();\r
+        NodeTemplateGrpc node0 = NodeTemplateGrpc.newBuilder().setConfiguration(node0conf).setId("100")\r
+                .setName("fw").setType(Type.firewall).build();\r
+        nodes.add(node0);\r
+\r
+        ToscaConfigurationGrpc node1conf = ToscaConfigurationGrpc.newBuilder().setDescription("node1configuration")\r
+                .setId("101").setConfiguration("[]").build();\r
+        NodeTemplateGrpc node1 = NodeTemplateGrpc.newBuilder().setConfiguration(node1conf).setId("101")\r
+                .setName("webserver1").setType(Type.webserver).build();\r
+        nodes.add(node1);\r
+\r
+        ToscaConfigurationGrpc node2conf = ToscaConfigurationGrpc.newBuilder().setDescription("node2configuration")\r
+                .setId("102").setConfiguration("[{\r\n\"protocol\":\"HTTP_REQUEST\",\r\n \"url\":\"www.facebook.com\"\r\n }]").build();\r
+        NodeTemplateGrpc node2 = NodeTemplateGrpc.newBuilder().setConfiguration(node2conf).setId("102")\r
+                .setName("host2").setType(Type.endhost).build();\r
+        nodes.add(node2);\r
+\r
+        ToscaConfigurationGrpc node3conf = ToscaConfigurationGrpc.newBuilder().setDescription("node3configuration")\r
+                .setId("103").setConfiguration("[ {\r\n\"protocol\":\"HTTP_REQUEST\",\r\n\"url\":\"www.google.com\",\r\n\"destination\":\"server1\"\r\n}]").build();\r
+        NodeTemplateGrpc node3 = NodeTemplateGrpc.newBuilder().setConfiguration(node3conf).setId("103")\r
+                .setName("host1").setType(Type.endhost).build();\r
+        nodes.add(node3);\r
+\r
+        ToscaConfigurationGrpc node4conf = ToscaConfigurationGrpc.newBuilder().setDescription("node4configuration")\r
+                .setId("104").setConfiguration("[\"host1\",\"host2\"]").build();\r
+        NodeTemplateGrpc node4 = NodeTemplateGrpc.newBuilder().setConfiguration(node4conf).setId("104")\r
+                .setName("antispamNode1").setType(Type.antispam).build();\r
+        nodes.add(node4);\r
+\r
+        //Building relationships\r
+        RelationshipTemplateGrpc rel0 = RelationshipTemplateGrpc.newBuilder().setId("1001")\r
+                .setIdSourceNodeTemplate("100").setIdTargetNodeTemplate("101").setName("fwToServ1").build();\r
+        relats.add(rel0);\r
+\r
+        RelationshipTemplateGrpc rel1 = RelationshipTemplateGrpc.newBuilder().setId("1002")\r
+                .setIdSourceNodeTemplate("101").setIdTargetNodeTemplate("100").setName("serv1ToFw").build();\r
+        relats.add(rel1);\r
+\r
+        RelationshipTemplateGrpc rel2 = RelationshipTemplateGrpc.newBuilder().setId("1003")\r
+                .setIdSourceNodeTemplate("100").setIdTargetNodeTemplate("103").setName("fwToHost1").build();\r
+        relats.add(rel2);\r
+\r
+        RelationshipTemplateGrpc rel3 = RelationshipTemplateGrpc.newBuilder().setId("1004")\r
+                .setIdSourceNodeTemplate("100").setIdTargetNodeTemplate("102").setName("fwToHost2").build();\r
+        relats.add(rel3);\r
+\r
+        RelationshipTemplateGrpc rel4 = RelationshipTemplateGrpc.newBuilder().setId("1005")\r
+                .setIdSourceNodeTemplate("102").setIdTargetNodeTemplate("100").setName("Host2Tofw").build();\r
+        relats.add(rel4);\r
+\r
+        RelationshipTemplateGrpc rel5 = RelationshipTemplateGrpc.newBuilder().setId("1006")\r
+                .setIdSourceNodeTemplate("103").setIdTargetNodeTemplate("100").setName("Host1Tofw").build();\r
+        relats.add(rel5);\r
+\r
+        this.testTemplate = templ.addAllNodeTemplate(nodes).addAllRelationshipTemplate(relats).setId("0").build();\r
+\r
+        TopologyTemplateGrpc.Builder templ2 = TopologyTemplateGrpc.newBuilder();\r
+        List<NodeTemplateGrpc> nodes2 = new ArrayList<NodeTemplateGrpc>();\r
+        List<RelationshipTemplateGrpc> relats2 = new ArrayList<RelationshipTemplateGrpc>();\r
+        nodes2.add(node0);\r
+        nodes2.add(node1);\r
+        nodes2.add(node2);\r
+        relats2.add(rel0);\r
+        relats2.add(rel1);\r
+        relats2.add(rel3);\r
+        relats2.add(rel4);\r
+\r
+        this.simpleTestTemplate = templ2.addAllNodeTemplate(nodes2).addAllRelationshipTemplate(relats2).setId("1").build();\r
+\r
+    }\r
+\r
+    /*class NodeTemplateGrpcComparator implements Comparator<NodeTemplateGrpc> {\r
+        public int compare(NodeTemplateGrpc n0, NodeTemplateGrpc n1) {\r
+            return n0.getName().compareTo(n1.getName());\r
+        }\r
+    }\r
+\r
+    class RelationshipTemplateGrpcComparator implements Comparator<RelationshipTemplateGrpc> {\r
+        public int compare(RelationshipTemplateGrpc n0, RelationshipTemplateGrpc n1) {\r
+            int source = n0.getIdSourceNodeTemplate().compareTo(n1.getIdSourceNodeTemplate());\r
+            int target = n0.getIdTargetNodeTemplate().compareTo(n1.getIdTargetNodeTemplate());\r
+            return source + target;\r
+        }\r
+    }*/\r
+\r
+}\r
diff --git a/verigraph/src/it/polito/verigraph/tosca/converter/grpc/GraphToGrpc.java b/verigraph/src/it/polito/verigraph/tosca/converter/grpc/GraphToGrpc.java
new file mode 100644 (file)
index 0000000..fb52c7b
--- /dev/null
@@ -0,0 +1,101 @@
+/*******************************************************************************\r
+ * Copyright (c) 2018 Politecnico di Torino and others.\r
+ *\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Apache License, Version 2.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *******************************************************************************/\r
+package it.polito.verigraph.tosca.converter.grpc;\r
+\r
+import java.util.Map;\r
+\r
+import it.polito.verigraph.grpc.NodeTemplateGrpc;\r
+import it.polito.verigraph.grpc.RelationshipTemplateGrpc;\r
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;\r
+import it.polito.verigraph.grpc.ToscaConfigurationGrpc;\r
+import it.polito.verigraph.grpc.ToscaTestGrpc;\r
+import it.polito.verigraph.grpc.ToscaVerificationGrpc;\r
+import it.polito.verigraph.model.Configuration;\r
+import it.polito.verigraph.model.Graph;\r
+import it.polito.verigraph.model.Neighbour;\r
+import it.polito.verigraph.model.Node;\r
+import it.polito.verigraph.model.Test;\r
+import it.polito.verigraph.model.Verification;\r
+\r
+public class GraphToGrpc {\r
+\r
+    /** Mapping method --> from model Graph to grpc TopologyTemplate */\r
+    public static TopologyTemplateGrpc obtainTopologyTemplate(Graph graph) {\r
+        TopologyTemplateGrpc.Builder topol = TopologyTemplateGrpc.newBuilder();\r
+        topol.setId(String.valueOf(graph.getId()));\r
+\r
+        //NodeTemplate\r
+        for(Node node : graph.getNodes().values()) {\r
+            NodeTemplateGrpc nt = obtainNodeTemplate(node);\r
+            topol.addNodeTemplate(nt);\r
+            //RelationshipTemplate\r
+            Map<Long,Neighbour> neighMap = node.getNeighbours();\r
+            for (Map.Entry<Long, Neighbour> myentry : neighMap.entrySet()) {\r
+                Neighbour neigh = myentry.getValue();\r
+                RelationshipTemplateGrpc relat = obtainRelationshipTemplate(neigh, node);\r
+                topol.addRelationshipTemplate(relat);\r
+            }\r
+        }\r
+        return topol.build();\r
+    }\r
+\r
+\r
+    /** Mapping method --> from model Node to grpc NodeTemplate */\r
+    private static NodeTemplateGrpc obtainNodeTemplate(Node node){\r
+        NodeTemplateGrpc.Builder nodegrpc = NodeTemplateGrpc.newBuilder();\r
+\r
+        nodegrpc.setId(String.valueOf(node.getId()));\r
+        nodegrpc.setName(node.getName());\r
+        nodegrpc.setType(NodeTemplateGrpc.Type.valueOf(node.getFunctional_type().toLowerCase()));\r
+\r
+        ToscaConfigurationGrpc config = obtainToscaConfiguration(node.getConfiguration());\r
+        nodegrpc.setConfiguration(config);\r
+\r
+        return nodegrpc.build();\r
+    }\r
+\r
+\r
+    /** Mapping method --> from model Neighbour to grpc RelationshipTemplate */\r
+    private static RelationshipTemplateGrpc obtainRelationshipTemplate(Neighbour neigh, Node sourceNode) {\r
+        RelationshipTemplateGrpc.Builder relat = RelationshipTemplateGrpc.newBuilder();\r
+        relat.setId(String.valueOf(sourceNode.getId()));\r
+        //Neighbour does not have a neighbourID! RelationshipTemplate does, so it is set to sourceNodeID\r
+        relat.setIdSourceNodeTemplate(String.valueOf(sourceNode.getId()));\r
+        relat.setIdTargetNodeTemplate(String.valueOf(neigh.getId()));\r
+        relat.setName(sourceNode.getName()+"to"+neigh.getName());\r
+        return relat.build();\r
+    }\r
+\r
+\r
+    /** Mapping method --> from model Configuration to grpc ToscaConfigurationGrpc */\r
+    private static ToscaConfigurationGrpc obtainToscaConfiguration(Configuration conf) {\r
+        return ToscaConfigurationGrpc.newBuilder()\r
+                .setId(conf.getId())\r
+                .setDescription(conf.getDescription())\r
+                .setConfiguration(conf.getConfiguration().toString())\r
+                .build();\r
+    }\r
+\r
+    /** Mapping method --> from model Verification to grpc ToscaVerificationGrpc */\r
+    public static ToscaVerificationGrpc obtainToscaVerification(Verification verify){\r
+        ToscaVerificationGrpc.Builder ver = ToscaVerificationGrpc.newBuilder();\r
+        ver.setComment(verify.getComment());\r
+        ver.setResult(verify.getResult());\r
+        for(Test test:verify.getTests()){\r
+            ToscaTestGrpc.Builder tst = ToscaTestGrpc.newBuilder().setResult(test.getResult());\r
+            for(Node node:test.getPath()){\r
+                NodeTemplateGrpc nodetempl = obtainNodeTemplate(node);\r
+                tst.addNodeTemplate(nodetempl);\r
+            }\r
+            ver.addTest(tst);\r
+        }\r
+        return ver.build();\r
+    }\r
+\r
+}\r
diff --git a/verigraph/src/it/polito/verigraph/tosca/converter/grpc/GrpcToGraph.java b/verigraph/src/it/polito/verigraph/tosca/converter/grpc/GrpcToGraph.java
new file mode 100644 (file)
index 0000000..76906b3
--- /dev/null
@@ -0,0 +1,150 @@
+/*******************************************************************************\r
+ * Copyright (c) 2018 Politecnico di Torino and others.\r
+ *\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Apache License, Version 2.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *******************************************************************************/\r
+package it.polito.verigraph.tosca.converter.grpc;\r
+\r
+import java.io.IOException;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import com.fasterxml.jackson.core.JsonProcessingException;\r
+import com.fasterxml.jackson.databind.JsonNode;\r
+import com.fasterxml.jackson.databind.ObjectMapper;\r
+\r
+import it.polito.verigraph.exception.BadRequestException;\r
+import it.polito.verigraph.grpc.NodeTemplateGrpc;\r
+import it.polito.verigraph.grpc.RelationshipTemplateGrpc;\r
+import it.polito.verigraph.grpc.TopologyTemplateGrpc;\r
+import it.polito.verigraph.grpc.ToscaConfigurationGrpc;\r
+import it.polito.verigraph.model.Configuration;\r
+import it.polito.verigraph.model.Graph;\r
+import it.polito.verigraph.model.Neighbour;\r
+import it.polito.verigraph.model.Node;\r
+\r
+public class GrpcToGraph {\r
+\r
+    /** Mapping method --> from grpc TopologyTemplateGrpc to model Graph */\r
+    public static Graph deriveGraph(TopologyTemplateGrpc request) throws BadRequestException, JsonProcessingException, IOException {\r
+        Graph graph = new Graph();\r
+        Map<Long, Node> nodes = new HashMap<>();\r
+\r
+        try {\r
+            //Create a list of Node without Neighbour\r
+            for(NodeTemplateGrpc nodetempl : request.getNodeTemplateList()){\r
+                Node node = deriveNode(nodetempl);\r
+              //It necessary to check uniqueness here otherwise a .put with the same key will overwrite the old node\r
+                if(nodes.containsKey(node.getId()))\r
+                    throw new BadRequestException("The NodeTemplate ID must be unique.");\r
+                else\r
+                    nodes.put(node.getId(), node);\r
+            }\r
+\r
+            //Add Neighbour to the Node of the list\r
+            List<RelationshipTemplateGrpc> relatList = request.getRelationshipTemplateList();\r
+            nodes = deriveNeighboursNode(nodes, relatList);\r
+\r
+            //Add Node and ID to the graph\r
+            graph.setNodes(nodes);\r
+            try {\r
+                graph.setId(Long.valueOf(request.getId()));\r
+            } catch(NumberFormatException ex) {\r
+                throw new BadRequestException("If you want to store your TopologyTemplate on this server,"\r
+                        + "the TopologyTemplate ID must be a number.");\r
+            }\r
+\r
+            return graph;\r
+\r
+        } catch (NullPointerException e) {\r
+            throw new BadRequestException("The TopologyTemplate received has invalid fields.");\r
+        }\r
+\r
+    }\r
+\r
+\r
+    /** Mapping method --> from grpc NodeTemplate to model Node (with no Neighbour) */\r
+    private static Node deriveNode(NodeTemplateGrpc nodegrpc) throws BadRequestException, JsonProcessingException, IOException {\r
+        Node node = new Node();\r
+        try {\r
+            try {\r
+                node.setId(Long.valueOf(nodegrpc.getId()));\r
+            } catch(NumberFormatException ex) {\r
+                throw new BadRequestException("The NodeTemplate ID must be a number.");\r
+            }\r
+\r
+            node.setName(nodegrpc.getName());\r
+            Configuration conf = deriveConfiguration(nodegrpc.getConfiguration());\r
+            node.setConfiguration(conf);\r
+            node.setFunctional_type(nodegrpc.getType().toString());\r
+\r
+        } catch(NullPointerException ex) {\r
+            throw new BadRequestException("A NodeTemplate has wrong fields representation.");\r
+        }\r
+\r
+        return node;\r
+    }\r
+\r
+\r
+\r
+    /** Mapping method --> from a list of model Node to a list of model Node with their Neighbour */\r
+    private static Map<Long,Node> deriveNeighboursNode(Map<Long,Node> nodes, List<RelationshipTemplateGrpc> relatList)\r
+            throws BadRequestException{\r
+        Map<Long,Node> updNodes = nodes; //new list to be filled with updated Node (update = Node + its Neighbour)\r
+        for(RelationshipTemplateGrpc relat : relatList) {\r
+            try {\r
+                //Retrieve the target Node name and generate a new Neighbour\r
+                String neighName = updNodes.get(Long.valueOf(relat.getIdTargetNodeTemplate())).getName();\r
+                Neighbour neigh = new Neighbour();\r
+                neigh.setName(neighName);\r
+                neigh.setId(Long.valueOf(relat.getId()));\r
+\r
+                //Retrieve the Neighbour map of the source Node and add the Neighbour\r
+                Node source = updNodes.get(Long.valueOf(relat.getIdSourceNodeTemplate()));\r
+                Map<Long,Neighbour> sourceNodeNeighMap = source.getNeighbours();\r
+                if(sourceNodeNeighMap.containsKey(neigh.getId()))\r
+                    throw new BadRequestException("The RelationshipTemplate ID must be unique.");\r
+                else\r
+                    sourceNodeNeighMap.put(neigh.getId(), neigh);\r
+                source.setNeighbours(sourceNodeNeighMap);\r
+\r
+                //Update the Node list\r
+                updNodes.put(Long.valueOf(relat.getIdSourceNodeTemplate()), source);\r
+            } catch(NullPointerException | NumberFormatException ex) {\r
+                throw new BadRequestException("A RelationshipTemplate has wrong fields representation.");\r
+            }\r
+        }\r
+        return updNodes;\r
+    }\r
+\r
+    /** Mapping method --> from ToscaConfiguration to model Configuration */\r
+    private static Configuration deriveConfiguration(ToscaConfigurationGrpc request)\r
+            throws BadRequestException, JsonProcessingException, IOException {\r
+        Configuration conf = new Configuration();\r
+        ObjectMapper mapper = new ObjectMapper();\r
+        JsonNode rootNode = null;\r
+\r
+        try {\r
+            conf.setId(request.getId());\r
+        } catch (NullPointerException e) {}\r
+\r
+        try {\r
+            conf.setDescription(request.getDescription());\r
+        } catch (NullPointerException e) {}\r
+\r
+        try {\r
+            if ("".equals(request.getConfiguration()))\r
+                rootNode=mapper.readTree("[]");\r
+            else\r
+                rootNode = mapper.readTree(request.getConfiguration());\r
+        } catch (NullPointerException e) {\r
+            rootNode=mapper.readTree("[]");\r
+        }\r
+        conf.setConfiguration(rootNode);\r
+        return conf;\r
+    }\r
+}\r
index feb8ff0..e8e9ccc 100644 (file)
@@ -1,3 +1,13 @@
+/* This Protocol Buffer has been updated for supporting TOSCA-based objects.
+ * The only granularity for executing CRUD operations is at the TopologyTemplate level.
+ *
+ * The names of the objects are assigned according to the TOSCA standard, and can be
+ * mapped as follows in the Verigraph domain:
+ * TopologyTemplate -> Graph
+ * NodeTemplate -> Node
+ * RelationshipTemplate -> Neighbour (partial)
+*/
+
 syntax = "proto3";
 
 package verigraph;
@@ -6,7 +16,7 @@ option java_multiple_files = true;
 option java_package = "it.polito.verigraph.grpc";
 option java_outer_classname = "VerigraphProto";
 
-// The service definition.
+/** gRPC */
 service Verigraph {
   // Obtains a list of graphs
   rpc GetGraphs (GetRequest) returns (stream GraphGrpc) {}
@@ -45,8 +55,24 @@ service Verigraph {
   rpc DeleteNeighbour (RequestID) returns (Status) {}
   // Updates a neighbour
   rpc UpdateNeighbour (NeighbourGrpc) returns (NewNeighbour) {}
+
+  /** TOSCA gRPC */
+  // Obtain a list of topology templates
+  rpc GetTopologyTemplates (GetRequest) returns (stream TopologyTemplateGrpc) {}
+  // Obtain a topology template
+  rpc GetTopologyTemplate (ToscaRequestID) returns (TopologyTemplateGrpc) {}
+  // Create a TopologyTemplate
+  rpc CreateTopologyTemplate (TopologyTemplateGrpc) returns (NewTopologyTemplate) {}
+  // Delete a TopologyTemplate
+  rpc DeleteTopologyTemplate (ToscaRequestID) returns (Status) {}
+  // Update a TopologyTemplate
+  rpc UpdateTopologyTemplate (TopologyTemplateGrpc) returns (NewTopologyTemplate) {}
+  // Verify a ToscaPolicy
+  rpc VerifyToscaPolicy (ToscaPolicy) returns (ToscaVerificationGrpc) {}
 }
 
+
+/** Messages */
 message GetRequest {
 }
 
@@ -151,4 +177,87 @@ string errorMessage = 5;
 message Status{
 bool success = 1;
 string errorMessage = 2;
-}
\ No newline at end of file
+}
+
+/** TOSCA Messages */
+message ToscaRequestID {
+  string idTopologyTemplate = 1;
+}
+
+message TopologyTemplateGrpc{
+  string id = 1;
+  string name = 2;
+  repeated NodeTemplateGrpc nodeTemplate = 3;
+  repeated RelationshipTemplateGrpc relationshipTemplate = 4;
+  string errorMessage = 5;
+}
+
+message NewTopologyTemplate{
+  bool success = 1;
+  TopologyTemplateGrpc topologyTemplate = 2;
+  string errorMessage = 3;
+}
+
+message NodeTemplateGrpc{
+  string id = 1;
+  string name = 2;
+  enum Type {
+    antispam = 0;
+    cache = 1;
+    dpi = 2;
+    endhost = 3;
+    endpoint = 4;
+    fieldmodifier = 5;
+    firewall = 6;
+    mailclient = 7;
+    mailserver = 8;
+    nat = 9;
+    vpnaccess = 10;
+    vpnexit = 11;
+    webclient = 12;
+    webserver = 13;
+  }
+  Type type = 3;
+  ToscaConfigurationGrpc configuration = 4;
+  string errorMessage = 5;
+}
+
+message RelationshipTemplateGrpc{
+  string idSourceNodeTemplate = 1;
+  string idTargetNodeTemplate = 2;
+  string id = 3;
+  string name = 4;
+  string errorMessage = 5;
+}
+
+message ToscaPolicy{
+  string idTopologyTemplate = 1;
+  string source = 2;
+  string destination = 3;
+  enum PolicyType {
+    reachability = 0;
+    isolation = 1;
+    traversal = 2;
+  }
+  PolicyType type = 4;
+  string middlebox = 5;
+}
+
+message ToscaConfigurationGrpc{
+  string id = 1;
+  string description = 2;
+  string configuration = 3;
+}
+
+message ToscaTestGrpc {
+  repeated NodeTemplateGrpc nodeTemplate = 1;
+  string result = 2;
+}
+
+message ToscaVerificationGrpc{
+  bool successOfOperation = 1;
+  string result = 2;
+  string comment = 3;
+  repeated ToscaTestGrpc test = 4;
+  string errorMessage = 5;
+}