All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scroll.internal.formal.CROM.scala Maven / Gradle / Ivy

The newest version!
package scroll.internal.formal

import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.impl.DynamicEObjectImpl
import org.eclipse.emf.ecore.util.EcoreEList
import scroll.internal.ecore.ECoreImporter

import scala.collection.JavaConverters._
import scala.collection.mutable

/**
  * Representation of a Compartment Role Object Model (CROM).
  */
trait CROM extends ECoreImporter {
  private[this] val NATURALTYPE = "NaturalType"
  private[this] val ROLETYPE = "RoleType"
  private[this] val COMPARTMENTTYPE = "CompartmentType"
  private[this] val ROLEGROUP = "RoleGroup"
  private[this] val RELATIONSHIP = "Relationship"
  private[this] val FULFILLMENT = "Fulfillment"
  private[this] val PART = "Part"

  private[this] val validTypes = Set(NATURALTYPE, ROLEGROUP, ROLETYPE, COMPARTMENTTYPE, RELATIONSHIP, FULFILLMENT, PART)

  /**
    * Checks if the loaded CROM is wellformed.
    *
    * @param path the file path to load a CROM from
    * @return true if a model was loaded using `withModel()` and it is wellformed, false otherwise
    */
  def wellformed(path: String): Boolean = construct(path).wellformed

  private[this] def instanceName(of: EObject): String = of.eClass().getEAllAttributes.asScala.find(_.getName == "name") match {
    case Some(a) => of.eGet(a).toString
    case None => "-"
  }

  private[this] def constructNT[NT >: Null <: AnyRef](elem: EObject): NT = instanceName(elem).asInstanceOf[NT]

  private[this] def constructRT[RT >: Null <: AnyRef](elem: EObject): RT = instanceName(elem).asInstanceOf[RT]

  private[this] def constructCT[CT >: Null <: AnyRef](elem: EObject): CT = instanceName(elem).asInstanceOf[CT]

  private[this] def constructRST[RST >: Null <: AnyRef](elem: EObject): RST = instanceName(elem).asInstanceOf[RST]

  private[this] def constructFills[NT >: Null <: AnyRef, RT >: Null <: AnyRef](elem: EObject): List[(NT, RT)] = {
    val obj = elem.asInstanceOf[DynamicEObjectImpl]
    val filler = obj.dynamicGet(1).asInstanceOf[DynamicEObjectImpl].dynamicGet(0).asInstanceOf[NT]
    val filledObj = obj.dynamicGet(0).asInstanceOf[DynamicEObjectImpl]
    if (filledObj.eClass().getName == ROLEGROUP) {
      collectRoles(filledObj).map(r => (filler, instanceName(r).asInstanceOf[RT]))
    } else {
      val filled = obj.dynamicGet(0).asInstanceOf[DynamicEObjectImpl].dynamicGet(0).asInstanceOf[RT]
      List((filler, filled))
    }
  }

  private[this] def collectRoles(of: EObject): List[EObject] = of.eContents().asScala.toList.flatMap(e => e.eClass().getName match {
    case ROLEGROUP => collectRoles(e)
    case ROLETYPE => List(e)
    case PART => collectRoles(e)
    case _ => List()
  })

  private[this] def constructParts[CT >: Null <: AnyRef, RT >: Null <: AnyRef](elem: EObject): (CT, List[RT]) = {
    val ct = instanceName(elem.eContainer()).asInstanceOf[CT]
    val roles = collectRoles(elem).map(r => instanceName(r).asInstanceOf[RT])
    (ct, roles)
  }

  private[this] def constructRel[RST >: Null <: AnyRef, RT >: Null <: AnyRef](elem: EObject): (RST, List[RT]) = {
    val rstName = instanceName(elem).asInstanceOf[RST]
    val roles = collectRoles(elem.eContainer())
    // TODO: make sure order of roles (incoming/outgoing) is correct for the given relationship
    val rsts = roles.filter(role => {
      val incoming = role.asInstanceOf[DynamicEObjectImpl].dynamicGet(1).asInstanceOf[EcoreEList[DynamicEObjectImpl]].asScala
      val inCond = incoming match {
        case null => false
        case _ => incoming.exists(e => e.dynamicGet(0).asInstanceOf[String] == rstName)
      }
      val outgoing = role.asInstanceOf[DynamicEObjectImpl].dynamicGet(2).asInstanceOf[EcoreEList[DynamicEObjectImpl]].asScala
      val outCond = outgoing match {
        case null => false
        case _ => outgoing.exists(e => e.dynamicGet(0).asInstanceOf[String] == rstName)
      }
      inCond || outCond
    }).map(instanceName(_).asInstanceOf[RT])
    (rstName, rsts)
  }

  private[this] def addToMap(m: mutable.Map[String, List[String]], elem: (String, List[String])): Unit = {
    val key = elem._1
    val value = elem._2
    if (m.contains(key)) {
      m(key) = m(key) ++ value
    } else {
      val _ = m += elem
    }
  }

  protected[this] def construct[NT >: Null <: AnyRef, RT >: Null <: AnyRef, CT >: Null <: AnyRef, RST >: Null <: AnyRef](path: String): FormalCROM[NT, RT, CT, RST] = {
    val nt = mutable.ListBuffer[String]()
    val rt = mutable.ListBuffer[String]()
    val ct = mutable.ListBuffer[String]()
    val rst = mutable.ListBuffer[String]()
    val fills = mutable.ListBuffer[(String, String)]()
    val parts = mutable.Map[String, List[String]]()
    val rel = mutable.Map[String, List[String]]()

    loadModel(path).getAllContents.asScala.filter(e => validTypes.contains(e.eClass().getName)).foreach(curr => {
      curr.eClass().getName match {
        case NATURALTYPE => nt += constructNT(curr)
        case ROLETYPE => rt += constructRT(curr)
        case COMPARTMENTTYPE => ct += constructCT(curr)
        case RELATIONSHIP =>
          rst += constructRST[String](curr)
          addToMap(rel, constructRel[String, String](curr))
        case FULFILLMENT => fills ++= constructFills(curr)
        case PART => addToMap(parts, constructParts[String, String](curr))
        case _ =>
      }
    })
    FormalCROM(nt.result(), rt.result(), ct.result(), rst.result(), fills.result(), parts.toMap, rel.toMap).asInstanceOf[FormalCROM[NT, RT, CT, RST]]
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy