From ffbb17e9d36784a4f9ffbf2203a0385a2f230154 Mon Sep 17 00:00:00 2001
From: Chrissi <christopher@hbsc-werner.de>
Date: Tue, 4 Jun 2019 10:06:05 +0200
Subject: [PATCH] add generation of instances for combination of rsum and rsync
 can be used for rsum

---
 .../model_sync/generator/Generator.scala      |  12 ++
 .../SModelCombiInstanceService.scala          |  22 +++
 .../SModelSUMCorePreparationService.scala     |   2 -
 .../generator/SModelSUMRemoveRefService.scala |  22 +++
 .../generator/acr_model/SClass.scala          |  14 ++
 .../generator/acr_model/STypedElement.scala   |   5 +
 .../sync/InstanceCombiGenerator.scala         | 134 ++++++++++++++++++
 .../generator/sync/InstanceGenerator.scala    |  13 +-
 .../generator/util/InstanceLine.scala         |   7 +-
 9 files changed, 217 insertions(+), 14 deletions(-)
 create mode 100644 src/main/scala/org/rosi_project/model_sync/generator/SModelCombiInstanceService.scala
 create mode 100644 src/main/scala/org/rosi_project/model_sync/generator/SModelSUMRemoveRefService.scala
 create mode 100644 src/main/scala/org/rosi_project/model_sync/generator/sync/InstanceCombiGenerator.scala

diff --git a/src/main/scala/org/rosi_project/model_sync/generator/Generator.scala b/src/main/scala/org/rosi_project/model_sync/generator/Generator.scala
index 9d594c7..c81f258 100644
--- a/src/main/scala/org/rosi_project/model_sync/generator/Generator.scala
+++ b/src/main/scala/org/rosi_project/model_sync/generator/Generator.scala
@@ -51,6 +51,7 @@ class Generator(config: GeneratorConfig) {
       //create the new classes for rsum and rsync
       if (config.getCreate == Creation.rolesync) {
         sModels.foreach(sm => {
+          //instance generation for rsync
           if (sm._2.obj != null) {
             new SModelSyncInstanceService prepareModel(sm._1, sm._2)
           }
@@ -63,6 +64,8 @@ class Generator(config: GeneratorConfig) {
         sModels.foreach(sm => {
           //create core stuff
           new SModelSUMCorePreparationService prepareModel (sm._1)
+          //remove references
+          new SModelSUMRemoveRefService prepareModel (sm._1)
           //create view and query stuff
           new SModelSUMPreparationService prepareModel (sm._1)
         })
@@ -73,6 +76,15 @@ class Generator(config: GeneratorConfig) {
           new SModelSUMCorePreparationService prepareModel (sm._1)
           //add sync stuff
           new SModelOnlySyncService prepareModel (sm._1)
+          //instance generation for combi means rsum
+          if (sm._2.obj != null) {
+            new SModelCombiInstanceService prepareModel(sm._1, sm._2)
+          }
+          else
+          {
+            //remove references
+            new SModelSUMRemoveRefService prepareModel (sm._1)
+          }
           //create view and query stuff
           new SModelSUMPreparationService prepareModel (sm._1)
         })
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/SModelCombiInstanceService.scala b/src/main/scala/org/rosi_project/model_sync/generator/SModelCombiInstanceService.scala
new file mode 100644
index 0000000..348b2e3
--- /dev/null
+++ b/src/main/scala/org/rosi_project/model_sync/generator/SModelCombiInstanceService.scala
@@ -0,0 +1,22 @@
+package org.rosi_project.model_sync.generator
+
+import org.rosi_project.model_sync.generator.acr_model.SModel
+import org.rosi_project.model_sync.generator.util.ClassAndInstance
+import org.rosi_project.model_sync.generator.sync.InstanceCombiGenerator
+
+/** Simple service to create instances.
+  * For the combination of sum and sync.
+  * 
+  * @author Christopher Werner
+  */
+class SModelCombiInstanceService {
+  
+  /** Add a new class to the [[SModel]] to instantiate it.
+    *
+    * @param sModel the model to augment
+    */
+  def prepareModel(sModel: SModel, clsAins: ClassAndInstance): Unit = {
+    val insgenerator = new InstanceCombiGenerator(clsAins)
+    sModel.accept(insgenerator)   
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/SModelSUMCorePreparationService.scala b/src/main/scala/org/rosi_project/model_sync/generator/SModelSUMCorePreparationService.scala
index 4debc8d..eb2d80c 100644
--- a/src/main/scala/org/rosi_project/model_sync/generator/SModelSUMCorePreparationService.scala
+++ b/src/main/scala/org/rosi_project/model_sync/generator/SModelSUMCorePreparationService.scala
@@ -18,11 +18,9 @@ class SModelSUMCorePreparationService {
   def prepareModel(sModel: SModel): Unit = {
     val getterSetterVisitor = new BasicTypeGetterSetterGeneratingVisitor
     val relationCompartmentVisitor = new RelationCompartmentGeneratingVisitor
-    val removeReferencesVisitor = new ReferenceRemoveVisitor
 
     //order is important !!!!    
     sModel.accept(getterSetterVisitor)
     sModel.accept(relationCompartmentVisitor)
-    sModel.accept(removeReferencesVisitor)
   }
 }
\ No newline at end of file
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/SModelSUMRemoveRefService.scala b/src/main/scala/org/rosi_project/model_sync/generator/SModelSUMRemoveRefService.scala
new file mode 100644
index 0000000..b389f9f
--- /dev/null
+++ b/src/main/scala/org/rosi_project/model_sync/generator/SModelSUMRemoveRefService.scala
@@ -0,0 +1,22 @@
+package org.rosi_project.model_sync.generator
+
+import org.rosi_project.model_sync.generator.acr_model.SModel
+import org.rosi_project.model_sync.generator.sync.ReferenceRemoveVisitor
+
+/** Remove references from model classes.
+  *
+  * @author Christopher Werner
+  */
+class SModelSUMRemoveRefService {
+  
+  /** Remove reference from model classes.
+    *
+    * @param sModel the model to augment
+    */
+  def prepareModel(sModel: SModel): Unit = {
+    val removeReferencesVisitor = new ReferenceRemoveVisitor
+
+    //order is important !!!!    
+    sModel.accept(removeReferencesVisitor)
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/acr_model/SClass.scala b/src/main/scala/org/rosi_project/model_sync/generator/acr_model/SClass.scala
index 08cc586..a69d98e 100644
--- a/src/main/scala/org/rosi_project/model_sync/generator/acr_model/SClass.scala
+++ b/src/main/scala/org/rosi_project/model_sync/generator/acr_model/SClass.scala
@@ -77,6 +77,20 @@ class SClass(_name: String,
       }
     }
   }
+  
+  override def proofHierarchicalEquality(sType: STypedElement): Boolean = {
+    if (sType == this) {
+      return true
+    } else {
+      this.getAllParents().foreach(p => {
+        if (p.proofHierarchicalEquality(sType)) {
+          return true
+        }
+      })
+      return false
+    }
+    
+  }
 
   /**
    * Augments `this` class with another method.
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/acr_model/STypedElement.scala b/src/main/scala/org/rosi_project/model_sync/generator/acr_model/STypedElement.scala
index d3de6f2..b57f9e3 100644
--- a/src/main/scala/org/rosi_project/model_sync/generator/acr_model/STypedElement.scala
+++ b/src/main/scala/org/rosi_project/model_sync/generator/acr_model/STypedElement.scala
@@ -34,6 +34,11 @@ abstract class STypedElement (_name: String,
     * will be ignored however.
     */
   def getInheritanceHierarchy: Seq[STypedElement] = Seq.empty
+  
+  /**
+   * Proof the hierarchical equality between two STypedElement
+   */
+  def proofHierarchicalEquality(sType: STypedElement): Boolean = sType == this
 
   /** Provides all classes that need to be imported for `this` type.
     */
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/sync/InstanceCombiGenerator.scala b/src/main/scala/org/rosi_project/model_sync/generator/sync/InstanceCombiGenerator.scala
new file mode 100644
index 0000000..4cefc3e
--- /dev/null
+++ b/src/main/scala/org/rosi_project/model_sync/generator/sync/InstanceCombiGenerator.scala
@@ -0,0 +1,134 @@
+package org.rosi_project.model_sync.generator.sync
+
+import scala.collection.JavaConverters._
+import org.rosi_project.model_sync.generator.acr_model._
+import org.rosi_project.model_sync.generator.util.ClassAndInstance
+import org.eclipse.emf.ecore.EObject
+import org.rosi_project.model_sync.generator.util.InstanceLine
+import org.rosi_project.model_sync.generator.acr_model.types.PredefTypes
+import org.eclipse.emf.ecore.EStructuralFeature
+import org.eclipse.emf.common.util.EList
+import org.rosi_project.model_sync.util.EMFUtilForGenerator
+import java.util.List
+
+class InstanceCombiGenerator(val clsins: ClassAndInstance) extends SModelVisitor {
+
+  override def visit(sModel: SModel): Unit = {
+    //println("++++++++++++++++++++++++++++++++++++++++++++++")
+    val example = new SClass("ExampleCombiCase", "example")
+    val contents = clsins.obj.eAllContents().asScala
+    var counter = 0
+    var lines: Seq[InstanceLine] = Seq.empty
+    var generationLines: Seq[InstanceLine] = Seq.empty
+    var sType = STypeRegistry.getFromClass(clsins.obj.eClass())
+    if (sType != null) {
+      lines = lines :+ new InstanceLine(counter, clsins.obj, sType)
+      counter += 1
+    }
+    contents.foreach(o => {
+      sType = STypeRegistry.getFromClass(o.eClass())
+      if (sType != null) {
+        lines = lines :+ new InstanceLine(counter, o, sType)
+        counter += 1
+      }
+    })    
+    //add values for instances
+    lines.foreach(l => {
+      l.usedType.getAllConstructorParameters.foreach(cp => {
+        if (!STypeRegistry.isDefaultType(cp.getType.getName)) {
+          val structs: Seq[EStructuralFeature] = l.obj.eClass().getEAllStructuralFeatures.asScala
+          structs.foreach(att => {
+            if (att.getName == cp.getName) {
+              val obj = l.obj.eGet(att)
+              if (obj.isInstanceOf[EObject]) {
+                lines.foreach(lnow => {
+                  if (lnow.obj == obj.asInstanceOf[EObject]) {
+                    //println("Found: " + lnow.counter) .filter(_.isInstanceOf[SRelationalCompartmentClass])
+                    sModel.getRelationalCompartments.foreach(rc => {
+                      val realRc = rc.asInstanceOf[SRelationalCompartmentClass]
+                      //println(" AN: " + att.getName + " l1: " + l.usedType.getName + " l2: " + lnow.usedType.getName + " RC: " + realRc.connectedRef.getName + " SN: " + realRc.sClass.getName + " TN: " + realRc.tClass.getName)
+                      if (realRc.connectedRef.getName == att.getName && l.usedType.proofHierarchicalEquality(realRc.sClass) && lnow.usedType.proofHierarchicalEquality(realRc.tClass)) {
+                        val s = s"new ${realRc.getName}(${l.getName()}, ${lnow.getName()})"
+                        generationLines = generationLines :+ new InstanceLine(0, null, realRc, s)
+                      }
+                    })
+                  }
+                })
+              } else {
+                val listi: List[EObject] = EMFUtilForGenerator.getList(obj)
+                val liste = listi.asScala
+                liste.foreach(eo => {
+                  lines.foreach(lnow => {
+                    if (lnow.obj == eo) {
+                      sModel.getRelationalCompartments.foreach(rc => {
+                        val realRc = rc.asInstanceOf[SRelationalCompartmentClass]
+                        //println(" AN: " + att.getName + " l1: " + l.usedType.getName + " l2: " + lnow.usedType.getName + " RC: " + realRc.connectedRef.getName + " SN: " + realRc.sClass.getName + " TN: " + realRc.tClass.getName)
+                        if (realRc.connectedRef.getName == att.getName && l.usedType.proofHierarchicalEquality(realRc.sClass) && lnow.usedType.proofHierarchicalEquality(realRc.tClass)) {
+                          val s = s"new ${realRc.getName}(${l.getName()}, ${lnow.getName()})"
+                          generationLines = generationLines :+ new InstanceLine(0, null, realRc, s)
+                        }
+                      })
+                    }
+                  })
+                })
+              }
+            }
+          })
+        }
+      })
+    })
+    
+    //remove references
+    sModel.getModelClasses.foreach(cls => {      
+      //remove all references from the class
+      cls.setReferences(null)
+    })
+    
+    //construction of instances
+    lines.foreach(l => {
+      example.augmentConstructor(new SMethodStatement(l.getLine(), Set(l.usedType)))
+    })
+    
+    //construction of connections
+    generationLines.foreach(l => {
+      example.augmentConstructor(new SMethodStatement(l.getLine(), Set(l.usedType)))
+    })
+    
+    
+    example.addParent(PredefTypes.App)
+    sModel.addJoinObject(example)
+    //println("++++++++++++++++++++++++++++++++++++++++++++++")
+    // pass
+
+  }
+
+  def setValues(eo: EObject, lines: Seq[InstanceLine]): String = {
+    lines.foreach(lnow => {
+      if (lnow.obj == eo) {
+        return lnow.getName()
+      }
+    })
+    ""
+  }
+
+  override def visit(sClass: SClass): Unit = {
+    // pass
+  }
+
+  override def visit(sAttr: SAttribute): Unit = {
+    // pass
+  }
+
+  override def visit(sRef: SReference): Unit = {
+    // pass
+  }
+
+  override def visit(sMethod: SMethod): Unit = {
+    // pass
+  }
+
+  override def visit(sType: SType): Unit = {
+    // pass
+  }
+
+}
\ No newline at end of file
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/sync/InstanceGenerator.scala b/src/main/scala/org/rosi_project/model_sync/generator/sync/InstanceGenerator.scala
index 066cc6e..224714e 100644
--- a/src/main/scala/org/rosi_project/model_sync/generator/sync/InstanceGenerator.scala
+++ b/src/main/scala/org/rosi_project/model_sync/generator/sync/InstanceGenerator.scala
@@ -19,7 +19,7 @@ import java.util.List
 class InstanceGenerator(val clsins: ClassAndInstance) extends SModelVisitor {
 
   override def visit(sModel: SModel): Unit = {
-    println("++++++++++++++++++++++++++++++++++++++++++++++")
+    //println("++++++++++++++++++++++++++++++++++++++++++++++")
     val example = new SClass("ExampleCase", "example")
     val contents = clsins.obj.eAllContents().asScala
     var counter = 0
@@ -48,9 +48,8 @@ class InstanceGenerator(val clsins: ClassAndInstance) extends SModelVisitor {
           structs.foreach(att => {
             if (att.getName == cp.getName) {
               val obj = l.obj.eGet(att)
-              println("### " + att.getName + " T: " + obj.isTraversableAgain + " Si: " + obj.size + " C: " + obj.getClass + " " + obj.getClass.getSimpleName)
+              //println("### " + att.getName)
               if (obj.isInstanceOf[EObject]) {
-                //println("Obj")
                 lines.foreach(lnow => {
                   if (lnow.obj == obj.asInstanceOf[EObject]) {
                     //println("Found: " + lnow.counter)
@@ -68,16 +67,10 @@ class InstanceGenerator(val clsins: ClassAndInstance) extends SModelVisitor {
           })
         }
       })
-
-      /*var structs: Seq[EStructuralFeature] = l.obj.eClass().getEAllStructuralFeatures.asScala
-      structs.foreach(att => {
-        println(att.getName + " " + l.obj.eGet(att))
-      })*/
-      //println(l.obj.eGet(l.obj.eClass().getEAllAttributes.get(0)))
     })
     example.addParent(PredefTypes.App)
     sModel.addJoinObject(example)
-    println("++++++++++++++++++++++++++++++++++++++++++++++")
+    //println("++++++++++++++++++++++++++++++++++++++++++++++")
     // pass
 
   }
diff --git a/src/main/scala/org/rosi_project/model_sync/generator/util/InstanceLine.scala b/src/main/scala/org/rosi_project/model_sync/generator/util/InstanceLine.scala
index d7a3624..56bd013 100644
--- a/src/main/scala/org/rosi_project/model_sync/generator/util/InstanceLine.scala
+++ b/src/main/scala/org/rosi_project/model_sync/generator/util/InstanceLine.scala
@@ -9,10 +9,13 @@ import org.rosi_project.model_sync.generator.acr_model.SMethodParameter
 import org.rosi_project.model_sync.generator.acr_model.STypeRegistry
 import org.eclipse.emf.ecore.EStructuralFeature
 
-class InstanceLine(val counter: Int, val obj: EObject, val usedType: STypedElement) {
+class InstanceLine(val counter: Int, val obj: EObject, val usedType: STypedElement, val lineString: String = "") {
   
   def getLine(): String = {
-    s"val i${counter} = new ${usedType.getName} (${usedType.getAllConstructorParameters.map(classEmptyConstructorParameterCreation(_)).mkString(", ")})"
+    if (obj != null) {
+      return s"val i${counter} = new ${usedType.getName} (${usedType.getAllConstructorParameters.map(classEmptyConstructorParameterCreation(_)).mkString(", ")})"
+    }
+    return lineString
   }
   
   def getName(): String = "i" + counter
-- 
GitLab