Skip to content

Commit

Permalink
#21 implemented class and field transformations
Browse files Browse the repository at this point in the history
  • Loading branch information
doczir committed Dec 11, 2015
1 parent bb2ffd9 commit b333721
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: IncQueryLabs Ltd.
Export-Package: com.incquerylabs.evm.jdt.java.transformation,
com.incquerylabs.evm.jdt.java.transformation.queries,
com.incquerylabs.evm.jdt.java.transformation.queries.util,
com.incquerylabs.evm.jdt.java.transformation.util
com.incquerylabs.evm.jdt.java.transformation.queries.util
Require-Bundle: com.google.guava,
org.eclipse.xtext.xbase.lib,
org.eclipse.xtend.lib,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
package com.incquerylabs.evm.jdt.java.transformation

import com.google.common.base.Preconditions
import com.incquerylabs.evm.jdt.fqnutil.JDTQualifiedName
import com.incquerylabs.evm.jdt.fqnutil.UMLQualifiedName
import com.incquerylabs.evm.jdt.fqnutil.impl.JDTElementLocator
import com.incquerylabs.evm.jdt.java.transformation.queries.UmlQueries
import com.incquerylabs.evm.jdt.java.transformation.queries.util.AssociationOfClassQuerySpecification
import com.incquerylabs.evm.jdt.java.transformation.queries.util.UmlClassQuerySpecification
import com.incquerylabs.evm.jdt.java.transformation.util.PerJobFixedPriorityConflictResolver
import com.incquerylabs.evm.jdt.jdtmanipulator.IJDTManipulator
import com.incquerylabs.evm.jdt.java.transformation.rules.AssociationRules
import com.incquerylabs.evm.jdt.java.transformation.rules.ClassRules
import com.incquerylabs.evm.jdt.java.transformation.rules.RuleProvider
import com.incquerylabs.evm.jdt.jdtmanipulator.impl.JDTManipulator
import java.util.Map
import org.eclipse.incquery.runtime.api.GenericPatternGroup
import org.eclipse.incquery.runtime.api.IncQueryEngine
import org.eclipse.incquery.runtime.emf.EMFScope
import org.eclipse.incquery.runtime.evm.api.Scheduler.ISchedulerFactory
import org.eclipse.incquery.runtime.evm.specific.Schedulers
import org.eclipse.incquery.runtime.evm.specific.event.IncQueryActivationStateEnum
import org.eclipse.incquery.runtime.evm.specific.resolver.InvertedDisappearancePriorityConflictResolver
import org.eclipse.jdt.core.IJavaProject
import org.eclipse.uml2.uml.Element
import org.eclipse.uml2.uml.Model
import org.eclipse.viatra.emf.runtime.rules.eventdriven.EventDrivenTransformationRule
import org.eclipse.viatra.emf.runtime.rules.eventdriven.EventDrivenTransformationRuleFactory
import org.eclipse.viatra.emf.runtime.transformation.eventdriven.EventDrivenTransformation
import org.eclipse.viatra.emf.runtime.transformation.eventdriven.ExecutionSchemaBuilder
import org.eclipse.xtend.lib.annotations.Data

class UMLToJavaTransformation {

static val umlQueries = UmlQueries::instance

// TODO: this is a temporary solution
Map<Element, String> elementNameRegistry = newHashMap

IncQueryEngine engine
val EventDrivenTransformationRuleFactory ruleFactory = new EventDrivenTransformationRuleFactory
ISchedulerFactory schedulerFactory
EventDrivenTransformation transformation

Expand All @@ -38,80 +36,50 @@ class UMLToJavaTransformation {
boolean initialized = false



new(IJavaProject project, Model model) {
manipulator = new JDTManipulator(new JDTElementLocator(project))
engine = IncQueryEngine::on(new EMFScope(model))
}


def initialize() {
def void initialize() {
Preconditions.checkArgument(engine != null, "Engine cannot be null!")
if(!initialized) {
if(schedulerFactory == null) {
schedulerFactory = Schedulers.getIQEngineSchedulerFactory(engine)
}
}

val ruleProviders = <RuleProvider>newArrayList
ruleProviders += new ClassRules
ruleProviders += new AssociationRules

ruleProviders.forEach[initialize(manipulator, elementNameRegistry)]

val queries = GenericPatternGroup::of(umlQueries)
queries.prepare(engine)

val transformationBuilder = EventDrivenTransformation::forEngine(engine)

val rules = initRules(manipulator)
val fixedPriorityResolver = new PerJobFixedPriorityConflictResolver
rules.forEach[fixedPriorityResolver.setPriority(rule.ruleSpecification, priority)]

val fixedPriorityResolver = new InvertedDisappearancePriorityConflictResolver
ruleProviders.forEach[registerRules(fixedPriorityResolver)]

val executionSchemaBuilder = new ExecutionSchemaBuilder
executionSchemaBuilder.engine = engine
executionSchemaBuilder.scheduler = schedulerFactory
executionSchemaBuilder.conflictResolver = fixedPriorityResolver
val executionSchema = executionSchemaBuilder.build

transformationBuilder.schema = executionSchema
rules.forEach[transformationBuilder.addRule(rule)]
ruleProviders.forEach[addRules(transformationBuilder)]
transformation = transformationBuilder.build


initialized = true
}

def initRules(IJDTManipulator manipulator) {
val list = newArrayList
list.add(new PrioritizedRule(ruleFactory.createRule.precondition(UmlClassQuerySpecification::instance)
.action(IncQueryActivationStateEnum.APPEARED) [
val qualifiedName = JDTQualifiedName::create(UMLQualifiedName::create(it.valueOfClass.qualifiedName))
manipulator.createClass(qualifiedName)
].action(IncQueryActivationStateEnum.UPDATED) [

].action(IncQueryActivationStateEnum.DISAPPEARED) [
val qualifiedName = JDTQualifiedName::create(UMLQualifiedName::create(it.valueOfClass.qualifiedName))
manipulator.deleteClass(qualifiedName)
].build, 0))
list.add(new PrioritizedRule(ruleFactory.createRule.precondition(AssociationOfClassQuerySpecification::instance)
.action(IncQueryActivationStateEnum.APPEARED) [
val containingClassQN = JDTQualifiedName::create(UMLQualifiedName::create(it.valueOfClass.qualifiedName))
val fieldName = it.association.name
val typeQN = JDTQualifiedName::create(UMLQualifiedName::create(it.endType.qualifiedName))
manipulator.createField(containingClassQN, fieldName, typeQN)
].action(IncQueryActivationStateEnum.UPDATED) [

].action(IncQueryActivationStateEnum.DISAPPEARED) [
val assocQN = JDTQualifiedName::create(UMLQualifiedName::create(it.association.qualifiedName))
manipulator.deleteField(assocQN)
].build, 1))
return list
}


def execute() {
transformation.executionSchema.startUnscheduledExecution
}

}

@Data
class PrioritizedRule {
EventDrivenTransformationRule<?, ?> rule
int priority
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,83 @@ package com.incquerylabs.evm.jdt.^java.transformation.queries

import "http://www.eclipse.org/uml2/5.0.0/UML"

pattern umlClass(class:Class) {
Class(class);
pattern umlClass(umlClass: Class) {
Class(umlClass);
// only accept "real" classes (in UML, it has lots of counterintuitive subclasses)
neg find umlAssociationClass(umlClass);
neg find behavior(umlClass);
neg find umlComponent(umlClass);
neg find node(umlClass);
neg find stereotype(umlClass);
neg find templateParameterClass(umlClass);
neg find templateBindingClass(umlClass);
}

pattern associationOfClass(class: Class, association: Association, endType: Class) {
find umlClass(class);
Association.ownedEnd.type(association, class);
Association.navigableOwnedEnd.type(association, endType);
class != endType;
pattern packageOfClass(umlClass, umlPackage) {
find umlClass(umlClass);
find umlPackage(umlPackage);
Package.packagedElement(umlPackage, umlClass);
}

private pattern umlAssociationClass(associationClass) {
AssociationClass(associationClass);
}

private pattern behavior(it) {
Behavior(it);
}

pattern umlComponent(component: Component) {
Component(component);
}

private pattern node(it) {
Node(it);
}

private pattern stereotype(it) {
Stereotype(it);
}

private pattern templateParameterClass(umlClass: Class){
TemplateSignature.ownedParameter(_, param);
ClassifierTemplateParameter.parameteredElement(param, umlClass);
}

private pattern templateBindingClass(umlClass: Class){
TemplateBinding.parameterSubstitution(_, param);
TemplateParameterSubstitution.actual(param, umlClass);
}

pattern umlClassInModel(model: Model, umlClass: Class) {
Model.packagedElement(model, umlClass);
find umlClass(umlClass);
}

pattern umlClassInPackage(umlPackage: Package, umlClass: Class) {
Package.packagedElement(umlPackage, umlClass);
find umlClass(umlClass);
find umlPackage(umlPackage);
}

pattern umlPackage(umlPackage) {
Package(umlPackage);
neg find model(umlPackage);
neg find profile(umlPackage);
}

private pattern model(model) {
Model(model);
}

private pattern profile(it) {
Profile(it);
}

pattern associationOfClass(trgType : Type, association: Association, srcEnd : Property, trgEnd : Property) {
Association.memberEnd(association, srcEnd);
Property.type(srcEnd, srcType);
Association.navigableOwnedEnd(association, trgEnd);
Property.type(trgEnd, trgType);
srcType != trgType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.incquerylabs.evm.jdt.java.transformation.rules

import com.incquerylabs.evm.jdt.java.transformation.queries.util.AssociationOfClassQuerySpecification
import com.incquerylabs.evm.jdt.jdtmanipulator.impl.JDTManipulator
import java.util.Map
import org.eclipse.incquery.runtime.evm.specific.Lifecycles
import org.eclipse.incquery.runtime.evm.specific.event.IncQueryActivationStateEnum
import org.eclipse.uml2.uml.Element

import static extension com.incquerylabs.evm.jdt.java.transformation.util.QualifiedNameUtil.*

class AssociationRules extends RuleProvider{

override initialize(JDTManipulator manipulator, Map<Element, String> elementNameRegistry) {
addRule(ruleFactory.createRule.precondition(AssociationOfClassQuerySpecification::instance)
.action(IncQueryActivationStateEnum.APPEARED) [
val containingClassQN = it.srcEnd.type.qualifiedName.toJDTQN
val fieldName = it.trgEnd.name
val typeQN = it.trgEnd.type.qualifiedName.toJDTQN
manipulator.createField(containingClassQN, fieldName, typeQN)
elementNameRegistry.put(it.trgEnd, it.trgEnd.name)
].action(IncQueryActivationStateEnum.UPDATED) [
val fieldName = elementNameRegistry.get(it.trgEnd)
manipulator.updateField((it.srcEnd.type.qualifiedName + "::" + fieldName).toJDTQN, it.trgEnd.type.qualifiedName.toJDTQN, it.trgEnd.name)
elementNameRegistry.put(it.trgEnd, it.trgEnd.name)
].action(IncQueryActivationStateEnum.DISAPPEARED) [
val fieldName = it.trgEnd.name
// TODO: if a type gets deleted and an association points at it, this event gets triggered and the it.srcEnd.type will be null -> not so good behavior
val fieldQN = (it.srcEnd.type.qualifiedName + "::" + fieldName).toJDTQN
manipulator.deleteField(fieldQN)
elementNameRegistry.remove(it.trgEnd.name)
].addLifeCycle(Lifecycles::getDefault(true, true)).build, 1)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.incquerylabs.evm.jdt.java.transformation.rules

import com.incquerylabs.evm.jdt.java.transformation.queries.util.UmlClassInModelQuerySpecification
import com.incquerylabs.evm.jdt.java.transformation.queries.util.UmlClassInPackageQuerySpecification
import com.incquerylabs.evm.jdt.jdtmanipulator.impl.JDTManipulator
import java.util.Map
import org.eclipse.incquery.runtime.evm.specific.Lifecycles
import org.eclipse.incquery.runtime.evm.specific.event.IncQueryActivationStateEnum
import org.eclipse.uml2.uml.Element

import static extension com.incquerylabs.evm.jdt.java.transformation.util.QualifiedNameUtil.*

class ClassRules extends RuleProvider {

override initialize(JDTManipulator manipulator, Map<Element, String> elementNameRegistry) {
addRule(ruleFactory.createRule.precondition(UmlClassInModelQuerySpecification::instance)
.action(IncQueryActivationStateEnum.APPEARED) [
val qualifiedName = it.umlClass.qualifiedName.toJDTQN
manipulator.createClass(qualifiedName)
elementNameRegistry.put(it.umlClass, it.umlClass.name)
].action(IncQueryActivationStateEnum.UPDATED) [
val clazzName = elementNameRegistry.get(it.umlClass)
manipulator.updateClass((it.model.qualifiedName + "::" + clazzName).toJDTQN, it.umlClass.name)
elementNameRegistry.put(it.umlClass, it.umlClass.name)
].action(IncQueryActivationStateEnum.DISAPPEARED) [
val qualifiedName = (it.model.qualifiedName + "::" + it.umlClass.name).toJDTQN
manipulator.deleteClass(qualifiedName)
elementNameRegistry.remove(it.umlClass.name)
].addLifeCycle(Lifecycles::getDefault(true, true)).build, 0)

addRule(ruleFactory.createRule.precondition(UmlClassInPackageQuerySpecification::instance)
.action(IncQueryActivationStateEnum.APPEARED) [
val qualifiedName = it.umlClass.qualifiedName.toJDTQN
manipulator.createClass(qualifiedName)
elementNameRegistry.put(it.umlClass, it.umlClass.name)
].action(IncQueryActivationStateEnum.UPDATED) [
val clazzName = elementNameRegistry.get(it.umlClass)
manipulator.updateClass((it.umlPackage.qualifiedName + "::" + clazzName).toJDTQN, it.umlClass.name)
elementNameRegistry.put(it.umlClass, it.umlClass.name)
].action(IncQueryActivationStateEnum.DISAPPEARED) [
val qualifiedName = (it.umlPackage.qualifiedName + "::" + it.umlClass.name).toJDTQN
manipulator.deleteClass(qualifiedName)
elementNameRegistry.remove(it.umlClass.name)
].addLifeCycle(Lifecycles::getDefault(true, true)).build, 0)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.incquerylabs.evm.jdt.java.transformation.rules

import com.incquerylabs.evm.jdt.jdtmanipulator.impl.JDTManipulator
import java.util.Map
import org.eclipse.incquery.runtime.evm.specific.resolver.InvertedDisappearancePriorityConflictResolver
import org.eclipse.uml2.uml.Element
import org.eclipse.viatra.emf.runtime.rules.eventdriven.EventDrivenTransformationRule
import org.eclipse.viatra.emf.runtime.rules.eventdriven.EventDrivenTransformationRuleFactory
import org.eclipse.viatra.emf.runtime.transformation.eventdriven.EventDrivenTransformation.EventDrivenTransformationBuilder
import org.eclipse.xtend.lib.annotations.Data

abstract class RuleProvider {

val rules = <PrioritizedRule>newArrayList
protected val ruleFactory = new EventDrivenTransformationRuleFactory

abstract def void initialize(JDTManipulator manipulator, Map<Element, String> elementNameRegistry)

protected def addRule(EventDrivenTransformationRule<?, ?> rule, int priority) {
rules.add(new PrioritizedRule(rule, priority))
}

final def void registerRules(InvertedDisappearancePriorityConflictResolver resolver) {
rules.forEach[resolver.setPriority(rule.ruleSpecification, priority)]
}

final def void addRules(EventDrivenTransformationBuilder builder) {
rules.forEach[builder.addRule(rule)]
}
}

@Data
class PrioritizedRule {
EventDrivenTransformationRule<?, ?> rule
int priority
}
Loading

0 comments on commit b333721

Please sign in to comment.