Skip to content
Snippets Groups Projects
Commit e2311567 authored by Chrissi's avatar Chrissi
Browse files

Merge branch 'develop'

parents 0cf8f28c f0cedcbe
No related branches found
No related tags found
No related merge requests found
Showing
with 752 additions and 144 deletions
package org.rosi_project.model_sync.generator
import org.rosi_project.model_sync.provider.DisplayableModel
import org.rosi_project.model_sync.provider.ModelSyncProvider
/** Representation of a model configuration (i.e. a number of corresponding models). It tells the
* generator how the model looks like, which types are needed, etc.
*
......
package org.rosi_project.model_sync.generator
object PackageNames {
val multiInhertitanceWithTraits = false
var sourcePkgPrefix: String = "" //sync. , sum.
val viewPkgName: String = "view"
val viewPostName: String = "View"
val viewRolePostName: String = "Role"
val queryPkgName: String = "query"
val queryPostName: String = "Query"
val queryRolePostName: String = "Role"
val queryHelperPrefix: String = "Helper"
val joinPkgName: String = "join"
val examplePkgName: String = "example"
val creationPkgName: String = "creation"
}
\ No newline at end of file
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
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.ReferenceMethodCreationVisitor
/**
* Add a method to get all references in the RSUM case.
* Sync functions necessary because we need compartment functions in the naturals.
*
* @author Christopher Werner
*/
class SModelCombiRefMethodService {
/**
* Remove reference from model classes.
*
* @param sModel the model to augment
*/
def prepareModel(sModel: SModel): Unit = {
val refMethodVisitor = new ReferenceMethodCreationVisitor
sModel.accept(refMethodVisitor)
}
}
\ No newline at end of file
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.GetterSetterGeneratingVisitor
/** Simple service that adds getter and setter for Attributes and References.
*
* @author Christopher Werner
*/
class SModelGetterSetterAllPreparationService {
/** Adds getter and setter for Attributes and References.
*
* @param sModel the model to augment
*/
def prepareModel(sModel: SModel): Unit = {
val getterSetterVisitor = new GetterSetterGeneratingVisitor
sModel.accept(getterSetterVisitor)
}
}
package org.rosi_project.model_sync.generator
import org.rosi_project.model_sync.generator.sync.BasicTypeGetterSetterGeneratingVisitor
import org.rosi_project.model_sync.generator.acr_model.SModel
class SModelGetterSetterAttrPreparationService {
/** Adds getter and setter for Attributes.
*
* @param sModel the model to augment
*/
def prepareModel(sModel: SModel): Unit = {
val getterSetterVisitor = new BasicTypeGetterSetterGeneratingVisitor
sModel.accept(getterSetterVisitor)
}
}
\ No newline at end of file
package org.rosi_project.model_sync.generator
import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression
import org.rosi_project.model_sync.generator.acr_model.SModel
import org.rosi_project.model_sync.generator.sync.JoinGeneratingVisitor
import org.rosi_project.model_sync.generator.sync.ModelJoinViewGeneratingVisitor
/** Simple service to create join classes and objects for ModelJoin.
*
* @author Christopher Werner
*/
class SModelJoinPreparationService {
/** Augments a [[SModel]] with new JoinClasses and JoinObjects.
*
* @param sModel the model to augment
* modelJoin input
*/
def prepareModel(sModel: SModel, joinExpression: ModelJoinExpression): Unit = {
val joinVisitor = new JoinGeneratingVisitor(joinExpression)
val modelJoinVisitor = new ModelJoinViewGeneratingVisitor(joinExpression)
//order is important !!!!
sModel.accept(joinVisitor)
sModel.accept(modelJoinVisitor)
}
}
\ No newline at end of file
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.{GetterSetterGeneratingVisitor, SyncEnhancingVisitor}
import org.rosi_project.model_sync.generator.sync.SyncEnhancingVisitor
/** Simple service to perform all the necessary adaptions of an [[SModel]] to make applicable for
* synchronization.
/** Simple service to perform only extension and method statement add.
*
* @author Rico Bergmann
* @author Christopher Werner
*/
class SModelSyncPreparationService {
class SModelOnlySyncService {
/** Augments a [[SModel]] with the necessary methods and statements to make it usable in a
* synchronization context.
*
* @param sModel the model to augment
*/
def prepareModel(sModel: SModel, modelCfg: ModelConfig): Unit = {
val getterSetterVisitor = new GetterSetterGeneratingVisitor
val syncNotificationVisitor = new SyncEnhancingVisitor(modelCfg)
sModel.accept(getterSetterVisitor)
def prepareModel(sModel: SModel): Unit = {
val syncNotificationVisitor = new SyncEnhancingVisitor
sModel.accept(syncNotificationVisitor)
}
}
\ No newline at end of file
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._
/** Simple service to create relational compartments for each relation.
*
* @author Christopher Werner
*/
class SModelRelationalCompartmentPreparationService {
/** Create relational compartments for each relation.
*
* @param sModel the model to augment
*/
def prepareModel(sModel: SModel): Unit = {
val relationCompartmentVisitor = new RelationCompartmentGeneratingVisitor
sModel.accept(relationCompartmentVisitor)
}
}
\ No newline at end of file
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._
/** Add functionality for Queries and Views to the RSUM.
*
* @author Christopher Werner
*/
class SModelSUMPreparationService {
/** Add functionality for Queries and Views to the RSUM.
*
* @param sModel the model to augment
*/
def prepareModel(sModel: SModel): Unit = {
val queryHelperVisitor = new GenerateQueryHelperVisitor
val viewGenerationVisitor = new ViewGeneratingVisitor
val queryGenerationVisitor = new QueryGeneratingVisitor
//order is important !!!!
sModel.accept(viewGenerationVisitor)
sModel.accept(queryHelperVisitor)
sModel.accept(queryGenerationVisitor)
}
}
\ No newline at end of file
package org.rosi_project.model_sync.generator
import org.rosi_project.model_sync.generator.sync.SumModelReadingVisitor
import org.rosi_project.model_sync.generator.acr_model.SModel
/** Simple service to create the new emf ecore model instances.
*
* @author Christopher Werner
*/
class SModelSUMReadEMFService {
/** Add classes to read emf and ecore models.
*
* @param sModel the model to augment
*/
def prepareModel(sModel: SModel, config: GeneratorConfig): Unit = {
val sumModelReadingVisitor = new SumModelReadingVisitor(config)
sModel.accept(sumModelReadingVisitor)
}
}
\ No newline at end of file
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
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.InstanceGenerator
/** Simple service to create instances.
*
* @author Christopher Werner
*/
class SModelSyncInstanceService {
/** 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 InstanceGenerator(clsAins)
sModel.accept(insgenerator)
}
}
\ No newline at end of file
package org.rosi_project.model_sync.generator
import org.rosi_project.model_sync.generator.acr_model.SModel
import org.rosi_project.model_sync.generator.ui.SyncUiVisitor
/** Simple service to add all the necessary adaption classes of an [[SModel]] to make applicable for
* synchronization user interface.
*
* @author Christopher Werner
*/
class SModelSyncUiPreparationService {
/** Add UI provider functionality too a [[SModel]] with the necessary methods and statements to make it usable
* in the user interface.
*
* @param sModel the model to augment
*/
def prepareModel(sModel: SModel, modelCfg: ModelConfig): Unit = {
if (modelCfg != null) {
val syncUiVisitor = new SyncUiVisitor(modelCfg)
sModel.accept(syncUiVisitor)
}
}
}
\ No newline at end of file
package org.rosi_project.model_sync.generator.acr_model
import org.rosi_project.model_sync.generator.support.Assert
/**
* Complex implementation of the [[SModel]].
*
* @author Christopher Werner
*/
class ComplexSModel(name: String, sourceName: String, nsUri: String) extends SModel(name, sourceName, nsUri) {
private var modelClasses: Set[SClass] = Set.empty
private var providerClasses: Set[SClass] = Set.empty
private var relationalCompartments: Set[SClass] = Set.empty
private var viewCompartments: Set[SClass] = Set.empty
private var joinClasses: Set[SClass] = Set.empty
private var sEnums: Set[SEnum] = Set.empty
/** Provides all model classes in `this` model. */
override def getModelClasses: Set[SClass] = modelClasses
/** Provides all provider classes in `this` model. */
override def getProviderClasses: Set[SClass] = providerClasses
/** Provides all relational compartments in `this` model. */
override def getRelationalCompartments: Set[SClass] = relationalCompartments
/** Provides all view compartments in `this` model. */
override def getViewCompartments: Set[SClass] = viewCompartments
/** Provides all the classes in `this` model. */
override def getAllClasses: Set[SClass] = modelClasses ++ providerClasses ++ relationalCompartments ++ viewCompartments
/** Provides all join classes in `this` model. */
override def getJoinClasses: Set[SClass] = joinClasses
/** Provides all model enums in `this` model. */
override def getModelEnums: Set[SEnum] = sEnums
/**
* Extends the model by a new provder class.
*
* @param mClass the class to add. May never `null`.
*/
override def addProviderClass(mClass: SClass): Unit = {
Assert.notNull(mClass, "Class may not be null")
providerClasses += mClass
}
/**
* Extends the model by a new relational compartment.
*
* @param mClass the class to add. May never `null`.
*/
override def addRelationalCompartment(mClass: SClass): Unit = {
Assert.notNull(mClass, "Class may not be null")
relationalCompartments += mClass
}
/**
* Extends the model by a new view compartment.
*
* @param mClass the class to add. May never `null`.
*/
override def addViewCompartment(mClass: SClass): Unit = {
Assert.notNull(mClass, "Class may not be null")
viewCompartments += mClass
}
/**
* Extends the model by a new class.
*
* @param mClass the class to add. May never `null`.
*/
override def addModelClass(mClass: SClass): Unit = {
Assert.notNull(mClass, "Class may not be null")
modelClasses += mClass
}
/**
* Extends the model by a new join class.
*
* @param mClass the class to add. May never `null`.
*/
override def addJoinClass(mClass: SClass): Unit = {
Assert.notNull(mClass, "Class may not be null")
joinClasses += mClass
}
/**
* Extends the model by a new enum.
*
* @param mEnum the enum to add. May never `null`.
*/
override def addModelEnums(mEnum: SEnum): Unit = {
Assert.notNull(mEnum, "Enum may not be null")
sEnums += mEnum
}
override def accept(visitor: SModelVisitor): Unit = {
getAllClasses.foreach(_.accept(visitor))
visitor.visit(this)
}
def canEqual(other: Any): Boolean = other.isInstanceOf[SimpleSModel]
override def equals(other: Any): Boolean = other match {
case that: ComplexSModel =>
(that canEqual this) &&
modelClasses == that.modelClasses &&
providerClasses == that.providerClasses &&
relationalCompartments == that.relationalCompartments &&
viewCompartments == that.viewCompartments &&
joinClasses == that.joinClasses &&
sEnums == that.sEnums
case _ => false
}
override def addOtherModel(model: SModel): SModel = {
modelClasses = modelClasses ++ model.getModelClasses
providerClasses = providerClasses ++ model.getProviderClasses
relationalCompartments = relationalCompartments ++ model.getRelationalCompartments
viewCompartments = viewCompartments ++ model.getViewCompartments
joinClasses = joinClasses ++ model.getJoinClasses
sEnums = sEnums ++ model.getModelEnums
return this
}
override def hashCode(): Int = {
val state = Seq(getAllClasses)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
}
}
\ No newline at end of file
......@@ -12,6 +12,8 @@ class GenericSType(name: String, sPackage: String = "", val typeParam: STypedEle
override def getName: String = s"$name[${typeParam.getName}]"
override def getDeepName: String = s"$name[${typeParam.getDeepName}]"
override def getNecessaryImports: Set[SImport] = if (typeParam.getPackage.isEmpty || typeParam.getPackage == sPackage)
typeParam.getNecessaryImports + SImport(typeParam.getPackage, typeParam.getName) else typeParam.getNecessaryImports
}
......@@ -20,6 +22,6 @@ class GenericSType(name: String, sPackage: String = "", val typeParam: STypedEle
*/
object GenericSType {
def unapply(arg: GenericSType): Option[(String, String, STypedElement)] = Some((arg.name, arg.sPackage, arg.typeParam))
def unapply(arg: GenericSType): Option[(String, String, STypedElement)] = Some((arg.getName, arg.sPackage, arg.typeParam))
}
package org.rosi_project.model_sync.generator.acr_model
object MethodVisibility extends Enumeration {
val privateVis, protectedVis, publicVis, privateExternalClass = Value
}
\ No newline at end of file
......@@ -6,16 +6,10 @@ package org.rosi_project.model_sync.generator.acr_model
*
* @author Rico Bergmann
*/
case class SAttribute(name: String, attrType: STypedElement) extends SModelElement {
/** Provides the type of `this` attribute as a `String`.
*
* @return the type. Will never be `null` nor empty.
*/
def getType: String = attrType.getName
case class SAttribute(_name: String, _type: STypedElement, val unique: Boolean = false) extends SStructuralFeature(_name, _type) {
override def accept(visitor: SModelVisitor): Unit = visitor.visit(this)
override def toString: String = s"$name: $getType"
override def toString: String = s"$getName: ${getTypeElement.getName} $unique"
}
package org.rosi_project.model_sync.generator.acr_model
import java.util.Objects
import org.rosi_project.model_sync.generator.acr_model.types.SSeq
import org.rosi_project.model_sync.generator.acr_model.types.GenericSequence
import org.rosi_project.model_sync.generator.acr_model.types.PredefTypes
import org.rosi_project.model_sync.generator.sync.ToStringMethods
/** Representation of Scala classes. Attributes, methods, etc. have their own wrappers which should
/**
* Representation of Scala classes. Attributes, methods, etc. have their own wrappers which should
* be used to modify these individual parts of the class.
*
* @see [[SType]]
* @author Rico Bergmann
*/
class SClass(val name: String,
val sPackage: String = "",
var attributes: Seq[SAttribute] = Seq.empty,
var parent: STypedElement = null,
protected var methods: Seq[SMethod] = Seq.empty)
extends STypedElement {
class SClass(_name: String,
_sPackage: String = "",
_sClassType: SClassType.Value = SClassType.normalClass) extends STypedElement(_name, _sPackage, _sClassType) {
protected var parentClass: STypedElement = null
protected var parentInterfaces: Seq[STypedElement] = Seq.empty
protected var internalClasses: Seq[SInnerClass] = Seq.empty
protected var attributes: Seq[SAttribute] = Seq.empty
protected var references: Seq[SReference] = Seq.empty
protected var methods: Seq[SMethod] = Seq.empty
protected var constructorStatements: Seq[SMethodStatement] = Seq.empty
/** Provides code that should be executed when invoking the constructor.
*/
def getAdditionalConstructorStatements: Seq[SMethodStatement] = constructorStatements
def getClassParent: STypedElement = parentClass
/** Checks, whether `this` is part of the default package
*/
def isDefaultPackage: Boolean = sPackage == ""
def getInterfaceParents: Seq[STypedElement] = parentInterfaces
/** Checks, whether `this` extends any other classes. If this is the case, it is '''not'''
* considered a ''root class'', otherwise it is.
*/
def isRootClass: Boolean = parent == null
def getStructuralFeatures: Seq[SStructuralFeature] = attributes ++ references
/** Provides the set of all symbols that have to be imported in order to use `this` complete
* class.
*/
def collectImports: Set[String] = getNecessaryImports.map(imp => s"${imp.pckg}.${imp.name}")
def getInternalClasses: Seq[SInnerClass] = internalClasses
def getDeepStructuralFeatures: Seq[SStructuralFeature] = {
val cls = getClassParent
if (cls == null) {
attributes ++ references
} else {
cls match {
case parentAsSClass: SClass =>
attributes ++ references ++ parentAsSClass.getDeepStructuralFeatures
case _ =>
attributes ++ references
}
}
}
def getOnlyDeepAttributes: Seq[SAttribute] = {
val cls = getClassParent
if (cls == null) {
attributes
} else {
cls match {
case parentAsSClass: SClass =>
attributes ++ parentAsSClass.getOnlyDeepAttributes
case _ =>
attributes
}
}
}
def getOnlyDeepReferences: Seq[SReference] = {
val cls = getClassParent
if (cls == null) {
references
} else {
cls match {
case parentAsSClass: SClass =>
references ++ parentAsSClass.getOnlyDeepReferences
case _ =>
references
}
}
}
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.
/**
* Augments `this` class with another method.
*
* @param m the additional method. May not be `null`
*/
......@@ -47,45 +104,93 @@ class SClass(val name: String,
methods = methods :+ m
}
/**
* Gets the methods of `this` class.
* And adds a to String if not exists.
*/
def getMethods: Seq[SMethod] = {
if (methods.exists(_.name == "toString")) {
if (methods.exists(_.getName == "toString")) {
methods
} else {
methods :+ new SMethod(
name = "toString",
result = SType.String,
params = Seq.empty,
implementation = Seq(SMethodStatement((List(s""" "$name: " """) ++ attributes.map(attr => s""" "${attr.name}=" + ${attr.name} + " " """)).mkString(" + "))),
overrides = true
)
methods :+ ToStringMethods.normalToStringMethod(this)
}
}
/** Augments the constructor by another statement. The statement will be executed lastly (though
* this may change due to further modifications of the constructor).
/** Gets the parents of `this` class. */
def getAllParents(): Seq[STypedElement] = {
if (parentInterfaces.isEmpty && parentClass == null) {
return Seq.empty
}
if (parentInterfaces.isEmpty) {
return Seq(parentClass)
}
if (parentClass == null) {
return parentInterfaces
}
parentInterfaces :+ parentClass
}
/**
* Adds a internal class to `this` class.
*
* @param statement the new statement. May not be `null`
* If `parent == this or null` nothing will happen.
*/
def augmentConstructor(statement: SMethodStatement): Unit = {
Objects.requireNonNull(statement, "Statement to add may not be null")
constructorStatements = constructorStatements :+ statement
def addInternalClass(internal: SInnerClass): Unit = {
if (internal == null || internal == this) {
return
}
if (internalClasses.contains(internal)) {
return
}
internalClasses = internalClasses :+ internal
}
/** Makes `this` class a subclass of `parent`.
/**
* Makes `this` class a subclass of `parent`.
*
* If `parent == this` nothing will happen.
*
* @param parent the superclass. May be `null` to indicate that there is no superclass (other
* than `AnyRef`)
*/
def setParent(parent: STypedElement): Unit = {
if (parent == this) {
def addParent(parent: STypedElement): Unit = {
if (parent == null || parent == this || parentClass == parent || parentInterfaces.contains(parent)) {
return
}
this.parent = parent
if (parent.isInterface) {
parentInterfaces = parentInterfaces :+ parent
} else {
if (parentClass == null) {
parentClass = parent
} else {
//print error message here
println("!!!Cannot add parent because their is one parent that is no interface!!!")
}
}
/** Sets the attributes of `this` class.
}
/** Gets the references of `this` class. */
def getReferences(): Seq[SReference] = references
/**
* Sets the references of `this` class.
*
* @param refs the references. May be `null` to remove all current references.
*/
def setReferences(refs: Seq[SReference]): Unit = {
if (refs == null) {
this.references = Seq.empty
} else {
this.references = refs
}
}
/** Gets the attributes of `this` class. */
def getAttributes(): Seq[SAttribute] = attributes
/**
* Sets the attributes of `this` class.
*
* @param attrs the attributes. May be `null` to remove all current attributes.
*/
......@@ -97,99 +202,172 @@ class SClass(val name: String,
}
}
/** Provides all types `this` classes accesses in some way.
/** Provides code that should be executed when invoking the constructor. */
def getAdditionalConstructorStatements: Seq[SMethodStatement] = constructorStatements
/**
* Checks, whether `this` extends any other classes. If this is the case, it is '''not'''
* considered a ''root class'', otherwise it is.
* Interfaces are not checked.
*/
def getUsedTypes: Set[STypedElement] = {
val parentImport: Seq[STypedElement] = if (isRootClass) List() else List(parent)
def isRootClass: Boolean = parentClass == null
def isAbsoluteRootClassOrInterface: Boolean = parentClass == null && parentInterfaces.isEmpty
def getRootClassWithNameAndPackage(n: String, p: String): SClass = {
var parent = this
while (!parent.isRootClass) {
if (parent.getClassParent.isInstanceOf[SClass]) {
parent = parent.getClassParent.asInstanceOf[SClass]
if (parent.getName == n && parent.getPackage == p) {
return parent
}
}
}
return null
}
/**
* Provides the set of all symbols that have to be imported in order to use `this` complete
* class.
*/
def collectImports: Set[String] = getNecessaryImports.map(imp => s"${imp.pckg}.${imp.name}")
/**
* Augments the constructor by another statement. The statement will be executed lastly (though
* this may change due to further modifications of the constructor).
*
* @param statement the new statement. May not be `null`
*/
def augmentConstructor(statement: SMethodStatement): Unit = {
Objects.requireNonNull(statement, "Statement to add may not be null")
constructorStatements = constructorStatements :+ statement
}
override def getAllConstructorParameters: Seq[SMethodParameter] = {
val ownParams = getStructuralFeatures.map(attr => SMethodParameter(attr.getName, attr.getTypeElement))
val parentParams = if (isRootClass) List() else getClassParent.getAllConstructorParameters
ownParams ++ parentParams
}
val parentConstructorParamImports: Seq[STypedElement] = if (isRootClass) List() else parent match {
case parent: SClass => parent.attributes.map(_.attrType)
override def getAttributeConstructorParameters: Seq[SMethodParameter] = {
val ownParams = getAttributes.map(attr => SMethodParameter(attr.getName, attr.getTypeElement))
val parentParams = if (isRootClass) List() else getClassParent.getAttributeConstructorParameters
ownParams ++ parentParams
}
override def getInheritanceHierarchy: Seq[STypedElement] = if (isRootClass) List(this) else this +: getClassParent.getInheritanceHierarchy
/** Provides all types `this` classes accesses in some way. */
def getUsedTypes: Set[STypedElement] = {
//iterate over construction features of parent types
val parentConstructorParamImports: Seq[STypedElement] = if (isRootClass) List() else getClassParent match {
case parent: SClass =>
parent.getDeepStructuralFeatures.map(_.getTypeElement)
case _ => List()
}
val attrTypeImports: Seq[STypedElement] = attributes.map(_.attrType)
//attribute types
val attrTypeImports: Seq[STypedElement] = attributes.map(_.getTypeElement)
//reference types
val refTypeImports: Seq[STypedElement] = references.map(_.getTypeElement)
//method types
val methodResultImports: Seq[STypedElement] = methods.map(_.result)
val methodParamImports: Seq[STypedElement] = methods.flatMap(_.params).map(_.paramType)
val methodParamImports: Seq[STypedElement] = methods.flatMap(_.params).map(_.getType)
val methodImplImports: Seq[STypedElement] = methods.flatMap(_.getUsedTypes.toList)
// create a set to eliminate duplicates
(parentImport
val allImports: Seq[STypedElement] = (getAllParents
++ parentConstructorParamImports
++ attrTypeImports
++ refTypeImports
++ methodResultImports
++ methodParamImports
++ methodImplImports).toSet
}
++ methodImplImports)
override def getName: String = name
var allCleanImports: Seq[STypedElement] = Seq.empty
override def getPackage: String = sPackage
override def getConstructorParameters: Seq[SMethodParameter] = {
val ownParams = attributes.map(attr => SMethodParameter(attr.name, attr.attrType))
val parentParams = if (isRootClass) List() else parent.getConstructorParameters
ownParams ++ parentParams
allImports.foreach(i => {
i match {
case seq: GenericSequence =>
allCleanImports = allCleanImports :+ seq.typeParam
case t: STypedElement =>
allCleanImports = allCleanImports :+ t
//case _ =>
}
})
override def getInheritanceHierarchy: Seq[STypedElement] = if (isRootClass) List(this) else this +: parent.getInheritanceHierarchy
// create a set to eliminate duplicates
allCleanImports.toSet
}
override def getNecessaryImports: Set[SImport] = {
val parentImport: List[SImport] = if (isRootClass) List() else includeImportIfNecessary(parent.getPackage, parent.getName)
val parentConstructorParamImports: List[SImport] = if (isRootClass) List() else parent match {
var allImports: List[SImport] = List.empty
//iterate over all parent types
getAllParents().foreach(p => {
allImports = includeImportIfNecessary(p, allImports)
})
//iterate over construction features of parent types
if (!isRootClass) {
getClassParent match {
case parent: SClass =>
parent.attributes
.map(attr => includeImportIfNecessary(attr.attrType.getPackage, attr.attrType.getName))
.fold(List())((l1, l2) => l1 ++ l2)
case _ => List()
parent.getDeepStructuralFeatures.foreach(p => {
allImports = includeImportIfNecessary(p.getTypeElement, allImports)
})
case _ =>
}
}
val attrTypeImports: List[SImport] =
attributes
.map(attr => includeImportIfNecessary(attr.attrType.getPackage, attr.getType))
.fold(List())((l1, l2) => l1 ++ l2)
val methodResultImports: List[SImport] =
methods
.map(_.result)
.map(res => includeImportIfNecessary(res.getPackage, res.getName))
.fold(List())((l1, l2) => l1 ++ l2)
val methodParamImports: List[SImport] =
methods
.map(_.params)
.fold(List())((l1, l2) => l1 ++ l2)
.map(param => includeImportIfNecessary(param.paramType.getPackage, param.paramType.getName))
.fold(List())((l1, l2) => l1 ++ l2)
val methodImplImports: List[SImport] =
methods
.map(_.getUsedTypes.toList)
.fold(List())((l1, l2) => l1 ++ l2)
.map(typ => includeImportIfNecessary(typ.getPackage, typ.getName))
.fold(List())((l1, l2) => l1 ++ l2)
//iterate over all attributes
attributes.foreach(a => {
allImports = includeImportIfNecessary(a.getTypeElement, allImports)
})
//iterate over all references
references.foreach(r => {
allImports = includeImportIfNecessary(r.getTypeElement, allImports)
})
//iterated over all methods
methods.foreach(m => {
//iterate over result types
allImports = includeImportIfNecessary(m.result, allImports)
//iterate over parameter types
m.params.foreach(p => {
allImports = includeImportIfNecessary(p.getType, allImports)
})
//iterate over used types in the method
m.getUsedTypes.foreach(t => {
allImports = includeImportIfNecessary(t, allImports)
})
})
//iterate over all construction statements
constructorStatements.foreach(s => {
s.usedTypes.foreach(t => {
allImports = includeImportIfNecessary(t, allImports)
})
})
// create a set to eliminate duplicates
(parentImport
++ parentConstructorParamImports
++ attrTypeImports
++ methodResultImports
++ methodParamImports
++ methodImplImports).toSet
(allImports).toSet
}
override def accept(visitor: SModelVisitor): Unit = {
attributes.foreach(_.accept(visitor))
references.foreach(_.accept(visitor))
methods.foreach(_.accept(visitor))
visitor.visit(this)
}
protected def canEqual(other: Any): Boolean = other.isInstanceOf[SClass]
/** Checks if some class has to be imported in order to be usable from `this` class. If this
/**
* Checks if some class has to be imported in order to be usable from `this` class. If this
* is the case it will wrap the necessary import in a `List` for further usage.
*
* @param sPackage the package of the class
......@@ -197,23 +375,31 @@ class SClass(val name: String,
* @return an empty list if the class does not need to be imported, or the necessary import
* otherwise
*/
private def includeImportIfNecessary(sPackage: String, sClass: String): List[SImport] = {
if (sPackage != this.sPackage && sPackage != "") List(SImport(sPackage, sClass)) else List()
private def includeImportIfNecessary(sTypeElement: STypedElement, list: List[SImport]): List[SImport] = {
//catch GenericSequence types and there use internal type param
var t = sTypeElement
sTypeElement match {
case seq: GenericSequence =>
t = seq.typeParam
case _ =>
}
//return only if new package
if (t.sPackage != this.sPackage && t.sPackage != "") list :+ SImport(t.sPackage, t.getName) else list
}
override def equals(other: Any): Boolean = other match {
case that: SClass =>
(that canEqual this) &&
name == that.name &&
getName == that.getName &&
sPackage == that.sPackage
case _ => false
}
override def hashCode(): Int = {
val state = Seq(name, sPackage)
val state = Seq(getName, sPackage)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
}
override def toString: String = s"$name(${attributes.map(_.name).mkString(", ")})"
override def toString: String = s"SC: $getName($sPackage, ${attributes.map(_.getName).mkString(", ")} ## ${getOnlyDeepAttributes.map(_.getName).mkString(", ")} || $isAbstract, $isInterface)"
}
package org.rosi_project.model_sync.generator.acr_model
object SClassType extends Enumeration {
val normalClass, caseClass, abstactClass, normalTrait, normalObject = Value
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment