From 00671142d8e01938898965f78e2a62ed159fd9df Mon Sep 17 00:00:00 2001 From: Chrissi <christopher@hbsc-werner.de> Date: Wed, 7 Aug 2019 14:24:14 +0200 Subject: [PATCH] remove model join stuff from this project + adapt to naming changes in model management provider --- build.sbt | 7 +- project/sbt-antlr4.sbt | 2 - src/main/antlr4/ModelJoin.g4 | 152 --------- .../representation/core/AttributePath.java | 147 --------- .../representation/core/ClassResource.java | 86 ----- .../representation/core/OCLConstraint.java | 32 -- .../representation/core/OCLStatement.java | 64 ---- .../core/RelativeAttribute.java | 78 ----- .../representation/core/ResourcePath.java | 154 --------- .../core/TypedAttributePath.java | 95 ------ .../grammar/CompoundKeepExpression.java | 20 -- .../grammar/JoinExpression.java | 204 ------------ .../grammar/KeepAggregateExpression.java | 261 --------------- .../grammar/KeepAttributesExpression.java | 82 ----- .../grammar/KeepCalculatedExpression.java | 125 ------- .../grammar/KeepExpression.java | 60 ---- .../grammar/KeepReferenceExpression.java | 223 ------------- .../grammar/KeepSubTypeExpression.java | 167 ---------- .../grammar/KeepSuperTypeExpression.java | 166 ---------- .../grammar/ModelJoinExpression.java | 102 ------ .../grammar/NaturalJoinExpression.java | 96 ------ .../grammar/OuterJoinExpression.java | 150 --------- .../grammar/ThetaJoinExpression.java | 77 ----- .../parser/ModelJoinParser.java | 32 -- .../parser/ModelJoinParsingException.java | 31 -- .../antlr/AntlrBackedModelJoinParser.java | 104 ------ .../parser/antlr/JoinStatementVisitor.java | 183 ----------- .../parser/antlr/KeepStatementVisitor.java | 307 ------------------ .../parser/antlr/ModelJoinVisitor.java | 28 -- .../parser/legacy/DefaultModelJoinParser.java | 187 ----------- .../parser/legacy/JoinParser.java | 254 --------------- .../parser/legacy/KeepParser.java | 98 ------ .../representation/util/Assert.java | 36 -- .../representation/util/Functional.java | 235 -------------- .../representation/util/JoinFactory.java | 302 ----------------- .../representation/util/ModelJoinBuilder.java | 79 ----- .../representation/util/Nothing.java | 11 - .../model_join/representation/util/Pair.java | 48 --- .../writer/FileBasedModelJoinWriter.java | 51 --- .../writer/ModelJoinWriter.java | 42 --- .../writer/ModelJoinWritingService.java | 20 -- .../writer/StringBasedModelJoinWriter.java | 160 --------- .../ModelJoinCreation.java | 131 -------- .../generator/sync/PredefRsumTypes.scala | 4 +- ...leBasedModelJoinWriterAcceptanceTests.java | 64 ---- ...ngBasedModelJoinWriterAcceptanceTests.java | 39 --- .../representation/writer/TestedModels.java | 69 ---- 47 files changed, 3 insertions(+), 5062 deletions(-) delete mode 100644 project/sbt-antlr4.sbt delete mode 100644 src/main/antlr4/ModelJoin.g4 delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/core/AttributePath.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/core/ClassResource.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLConstraint.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLStatement.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/core/RelativeAttribute.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/core/ResourcePath.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/core/TypedAttributePath.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/CompoundKeepExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/JoinExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAggregateExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAttributesExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepCalculatedExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepReferenceExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSubTypeExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSuperTypeExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ModelJoinExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/NaturalJoinExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/OuterJoinExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ThetaJoinExpression.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParser.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParsingException.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/AntlrBackedModelJoinParser.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/JoinStatementVisitor.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/KeepStatementVisitor.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/ModelJoinVisitor.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/DefaultModelJoinParser.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/JoinParser.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/KeepParser.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/util/Assert.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/util/Functional.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/util/JoinFactory.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/util/ModelJoinBuilder.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/util/Nothing.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/util/Pair.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriter.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWriter.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWritingService.java delete mode 100644 src/main/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriter.java delete mode 100644 src/main/java/org/rosi_project/model_sync/modelrepresentation/ModelJoinCreation.java delete mode 100644 src/test/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriterAcceptanceTests.java delete mode 100644 src/test/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriterAcceptanceTests.java delete mode 100644 src/test/java/org/rosi_project/model_sync/model_join/representation/writer/TestedModels.java diff --git a/build.sbt b/build.sbt index 13a20cc..429b551 100644 --- a/build.sbt +++ b/build.sbt @@ -1,4 +1,3 @@ -import com.simplytyped.Antlr4Plugin.autoImport.antlr4PackageName import sbt.Keys.{libraryDependencies, scalacOptions, version} val emfcommonVersion = "2.12.0" @@ -55,8 +54,4 @@ lazy val generator = (project in file(".")) ).dependsOn( modelmanagementprovider, uiProvider - ).enablePlugins(Antlr4Plugin) - -antlr4PackageName in Antlr4 := Some("org.rosi_project.model_sync.model_join.representation.parser.antlr.generated") -antlr4GenVisitor in Antlr4 := true -antlr4GenListener in Antlr4 := false + ) diff --git a/project/sbt-antlr4.sbt b/project/sbt-antlr4.sbt deleted file mode 100644 index 7b26d1f..0000000 --- a/project/sbt-antlr4.sbt +++ /dev/null @@ -1,2 +0,0 @@ - -addSbtPlugin("com.simplytyped" % "sbt-antlr4" % "0.8.2") diff --git a/src/main/antlr4/ModelJoin.g4 b/src/main/antlr4/ModelJoin.g4 deleted file mode 100644 index 70817b5..0000000 --- a/src/main/antlr4/ModelJoin.g4 +++ /dev/null @@ -1,152 +0,0 @@ -/* - * ModelJoin.g4 - * - * Defines the structure of our ModelJoin grammar - * - * Author: Rico Bergmann - */ -grammar ModelJoin; - -/* - * Parser - */ -modeljoin : join+ EOF ; -join : (naturaljoin | thetajoin | outerjoin) AS classres - ( OPENCURLYBRAKET - keepattributesexpr* - keepaggregatesexpr* - keepcalculatedexpr* - keepexpr* - CLOSEDCURLYBRAKET )? ; -naturaljoin : NATURAL JOIN classres WITH classres ; -thetajoin : THETA JOIN classres WITH classres WHERE oclcond; -outerjoin : (leftouterjoin | rightouterjoin) OUTER JOIN classres WITH classres; -leftouterjoin : LEFT ; -rightouterjoin : RIGHT ; - -keepattributesexpr : KEEP ATTRIBUTES attrres (COMMA attrres)* ; -keepaggregatesexpr : KEEP AGGREGATE aggrtype - OPENBRAKET relattr CLOSEDBRAKET - OVER classres AS attrres ; -keepcalculatedexpr : KEEP CALCULATED ATTRIBUTE oclcond AS (typedattrres | attrres) ; -keepexpr : (keeptypeexpr | keepoutgoingexpr | keepincomingexpr) - ( OPENCURLYBRAKET - keepattributesexpr* - keepaggregatesexpr* - keepcalculatedexpr* - keepexpr* - CLOSEDCURLYBRAKET)? ; -keeptypeexpr : keepsupertypeexpr | keepsubtypeexpr ; -keepsupertypeexpr : KEEP SUPERTYPE classres ( AS TYPE classres )? ; -keepsubtypeexpr : KEEP SUBTYPE classres ( AS TYPE classres )? ; -keepoutgoingexpr : KEEP OUTGOING attrres ( AS TYPE classres )? ; -keepincomingexpr : KEEP INCOMING attrres (AS TYPE classres )? ; - -classres : WORD (DOT WORD)* ; -attrres : WORD (DOT WORD)+ ; -typedattrres : attrres COLON WORD ; -relattr : WORD ; -oclcond : (WORD | NUMBER | specialchar | anytoken | WHITESPACE | NEWLINE)+; -aggrtype : SUM | AVG | MIN | MAX | SIZE ; - -specialchar : DOT - | OPENBRAKET - | CLOSEDBRAKET - | OPENCURLYBRAKET - | CLOSEDCURLYBRAKET - | COMMA - | UNDERSCORE - | SPECIALCHAR ; - -// anytoken matches all possible tokens in case their content may appear as part of some regular -// text as well -anytoken : OPENBRAKET - | CLOSEDBRAKET - | OPENCURLYBRAKET - | CLOSEDCURLYBRAKET - | DOT - | COLON - | COMMA - | UNDERSCORE - | SPECIALCHAR - - | JOIN - | NATURAL - | THETA - | WHERE - | OUTER - | RIGHT - | LEFT - | WITH - | AS - - | KEEP - | ATTRIBUTES - | ATTRIBUTE - | AGGREGATE - | CALCULATED - | SUPERTYPE - | SUBTYPE - | OUTGOING - | INCOMING - | TYPE - | OVER - - | SUM - | AVG - | MIN - | MAX - | SIZE ; - -/* - * Lexer - */ - -fragment LOWERCASE : [a-z] ; -fragment UPPERCASE : [A-Z] ; -fragment ANYCASE : LOWERCASE | UPPERCASE ; -fragment DIGIT : [0-9] ; - -OPENBRAKET : '(' ; -CLOSEDBRAKET : ')' ; -OPENCURLYBRAKET : '{' ; -CLOSEDCURLYBRAKET : '}' ; -DOT : '.' ; -COLON : ':' ; -COMMA : ',' ; -UNDERSCORE : '_' ; -SPECIALCHAR : [-><!="'|] ; - -JOIN : 'join' ; -NATURAL : 'natural' ; -THETA : 'theta' ; -WHERE : 'where' ; -OUTER : 'outer' ; -RIGHT : 'right' ; -LEFT : 'left' ; -WITH : 'with' ; -AS : 'as' ; - -KEEP : 'keep' ; -ATTRIBUTES : 'attributes' ; -ATTRIBUTE : 'attribute' ; -AGGREGATE : 'aggregate' ; -CALCULATED : 'calculated' ; -SUPERTYPE : 'supertype' ; -SUBTYPE : 'subtype' ; -OUTGOING : 'outgoing' ; -INCOMING : 'incoming' ; -TYPE : 'type' ; -OVER : 'over' ; - -SUM : 'sum' ; -AVG : 'avg' ; -MIN : 'min' ; -MAX : 'max' ; -SIZE : 'size' ; - -WORD : ANYCASE (ANYCASE | DIGIT | UNDERSCORE)* ; -NUMBER : [+-]? DIGIT+ DOT? DIGIT* ; - -WHITESPACE : ' ' -> skip ; -NEWLINE : ('\r'? '\n' | '\r')+ -> skip ; diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/AttributePath.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/AttributePath.java deleted file mode 100644 index 2f28ca2..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/AttributePath.java +++ /dev/null @@ -1,147 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.core; - -import java.util.Objects; -import javax.annotation.Nonnull; - -/** - * An {@code AttributePath} represents a single attribute of some model class. - * <p> - * As <em>ModelJoin</em> does not care about types at a conceptual level, no type information is - * stored. - * - * @author Rico Bergmann - */ -public class AttributePath { - - private static final String CLASS_ATTRIBUTE_DELIMITER = "."; - - /** - * Generates a new {@code path} given the owning class as well as the attribute's name. - */ - @Nonnull - public static AttributePath from( - @Nonnull ClassResource containingClass, - @Nonnull String attributeName) { - return new AttributePath(containingClass, attributeName); - } - - /** - * Generates a new {@code path} given the owning class as well as the attribute. - */ - @Nonnull - public static AttributePath from( - @Nonnull ClassResource containingClass, - @Nonnull RelativeAttribute attribute) { - return new AttributePath(containingClass, attribute); - } - - public static AttributePath from(String containingClass, String attributeName) { - return new AttributePath(containingClass, attributeName); - } - - /** - * Generates a new {@code AttributePath} by splitting up the {@code qualifiedPath} into the - * {@link ClassResource} and attribute portion. Therefore the {@code qualifiedPath} is expected - * to adhere to the following scheme: {@code [package].class.attribute}. - */ - @Nonnull - public static AttributePath fromQualifiedPath(@Nonnull String qualifiedPath) { - final int splitPos = qualifiedPath.lastIndexOf(CLASS_ATTRIBUTE_DELIMITER); - - if (splitPos < 0) { - throw new IllegalArgumentException("Missing class portion on '" + qualifiedPath + "'"); - } - - String classResourcePortion = qualifiedPath.substring(0, splitPos); - String attributePortion = qualifiedPath.substring(splitPos + 1); - return new AttributePath(ClassResource.fromQualifiedName(classResourcePortion), attributePortion); - } - - @Nonnull - private final ClassResource containingClass; - - @Nonnull - private final RelativeAttribute attribute; - - public AttributePath(String containingClass, String attributeName) { - this.containingClass = ClassResource.fromQualifiedName(containingClass); - this.attribute = RelativeAttribute.of(attributeName); - } - - /** - * Full constructor, parsing the attribute's name into a valid {@link RelativeAttribute}. - * - * @param containingClass the class which owns the attribute - * @param attributeName the attribute's name - */ - public AttributePath(@Nonnull ClassResource containingClass, @Nonnull String attributeName) { - this.containingClass = containingClass; - this.attribute = RelativeAttribute.of(attributeName); - } - - /** - * Full constructor. - * - * @param containingClass the class which owns the attribute - * @param attribute the attribute's name - */ - public AttributePath(@Nonnull ClassResource containingClass, @Nonnull RelativeAttribute attribute) { - this.containingClass = containingClass; - this.attribute = attribute; - } - - /** - * Creates a new {@code AttributePath} by copying another path. - */ - protected AttributePath(@Nonnull AttributePath other) { - this.containingClass = other.getContainingClass(); - this.attribute = other.getAttribute(); - } - - /** - * Provides the class which owns {@code this} attribute. - */ - @Nonnull - public ClassResource getContainingClass() { - return containingClass; - } - - /** - * Provides {@code this} attribute as a {@link RelativeAttribute}. - */ - @Nonnull - public RelativeAttribute getAttribute() { - return attribute; - } - - /** - * Provides the name of {@code this} attribute. - */ - @Nonnull - public String getAttributeName() { - return attribute.getAttributeName(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof AttributePath)) { - return false; - } - AttributePath that = (AttributePath) o; - return containingClass.equals(that.containingClass) && - attribute.equals(that.attribute); - } - - @Override - public int hashCode() { - return Objects.hash(containingClass, attribute); - } - - @Override - public String toString() { - return containingClass.toString() + "." + attribute; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ClassResource.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ClassResource.java deleted file mode 100644 index 7143ad7..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ClassResource.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.core; - -import javax.annotation.Nonnull; - -/** - * A {@code ClassResource} represents a fully-qualified reference to some class to be used in a - * join. This class merely exist to emphasize that some resource actually represents a class and - * thus provides a nicer (i.e. better named) interface to query for the resource's fields. - * <p> - * In difference to a {@link ResourcePath}, instances of this class will drop the {@code .java} - * ending of the file name if referenced from the file system. - * - * @author Rico Bergmann - */ -public class ClassResource extends ResourcePath { - - /** - * Generates a new {@code path} given the path to its containing <em>package</em> and the name of - * the class which should be referenced. - */ - @Nonnull - public static ClassResource from(@Nonnull String packagePath, @Nonnull String className) { - return new ClassResource(packagePath, className); - } - - /** - * @see ResourcePath#parse(String) - */ - @Nonnull - public static ClassResource fromQualifiedName(@Nonnull String qualifiedClass) { - /* - * A class resource is just a better representation of a class (in difference to just _some_ - * kind of resource) but works just the same - thus we will re-use all the parsing logic from - * the ResourcePath - */ - ResourcePath parsedResource = ResourcePath.parse(qualifiedClass); - return new ClassResource(parsedResource.resourcePath, parsedResource.resourceName); - } - - /** - * @see ResourcePath#parseAsFileSystemPath(String) - */ - @Nonnull - public static ClassResource fromFileSystem(@Nonnull String fullPath) { - /* - * A class resource is just a better representation of a class (in difference to just _some_ - * kind of resource) but works just the same - thus we will re-use all the parsing logic from - * the ResourcePath - */ - ResourcePath parsedResource = ResourcePath.parseAsFileSystemPath(dropFileTypeEnding(fullPath)); - return new ClassResource(parsedResource.resourcePath, parsedResource.resourceName); - } - - /** - * Deletes the {@code .java} ending from a resource name. - */ - private static String dropFileTypeEnding(String fullPath) { - return fullPath.replaceAll("\\.java$", ""); - } - - /** - * Full constructor. - * - * @param containingPackage the path to the package to which the class belongs - * @param className the name of the class - */ - public ClassResource(@Nonnull String containingPackage, @Nonnull String className) { - super(containingPackage, className); - } - - /** - * Provides the name of the class represented by {@code this} resource. - */ - @Nonnull - public String getClassName() { - return resourceName; - } - - /** - * Provides the package that contains the class represented by {@code this} resource. - */ - @Nonnull - public String getPackage() { - return resourcePath; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLConstraint.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLConstraint.java deleted file mode 100644 index 6f8afef..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLConstraint.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.core; - -import javax.annotation.Nonnull; - -/** - * An {@code OCLConstraint} specifies some predicate on (possibly multiple) models that have to hold - * under certain conditions. - * <p> - * This class is a specialization of an arbitrary {@link OCLStatement} for statements, that - * evaluate to a boolean values. - * - * @author Rico Bergmann - */ -public class OCLConstraint extends OCLStatement { - - /** - * Generates a new constraint with the given content. - */ - @Nonnull - public static OCLConstraint of(@Nonnull String content) { - return new OCLConstraint(content); - } - - /** - * Full constructor. - * - * @param content the actual constraint - */ - public OCLConstraint(@Nonnull String content) { - super(content); - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLStatement.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLStatement.java deleted file mode 100644 index 5acfc57..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/OCLStatement.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.core; - -import java.util.Objects; -import javax.annotation.Nonnull; - -/** - * An {@code OCLStatement} is a simple expression written in the {@code Object Constraint Language}. - * <p> - * This class simply wraps an arbitrary OCL expression. No further checks or the like are performed. - * - * @author Rico Bergmann - * @see <a href="https://www.omg.org/spec/OCL/">OMG OCL specification</a> - */ -public class OCLStatement { - - /** - * Creates a new statement with the given {@code content}. - */ - @Nonnull - public static OCLStatement of(@Nonnull String content) { - return new OCLStatement(content); - } - - @Nonnull - protected final String content; - - /** - * Full constructor. - * - * @param content the actual expression - */ - public OCLStatement(@Nonnull String content) { - this.content = content; - } - - /** - * Provides the actual statement as a {@code String}. - */ - public String get() { - return content; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - OCLStatement that = (OCLStatement) o; - return content.equals(that.content); - } - - @Override - public int hashCode() { - return Objects.hash(content); - } - - @Override - public String toString() { - return content; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/RelativeAttribute.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/RelativeAttribute.java deleted file mode 100644 index d3e002c..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/RelativeAttribute.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.core; - -import java.util.Objects; -import javax.annotation.Nonnull; - -/** - * A {@code RelativeAttribute} represents a member of some class. - * <p> - * In difference to the {@link AttributePath} this class does not retain any information about the - * class to which it belongs. - * - * @author Rico Bergmann - */ -public class RelativeAttribute { - - /** - * Extracts the attribute from a qualified {@link AttributePath}. - */ - @Nonnull - public static RelativeAttribute from(@Nonnull AttributePath attributePath) { - return new RelativeAttribute(attributePath.getAttributeName()); - } - - /** - * Generates a new {@code RelativeAttribute} with the given name. - */ - @Nonnull - public static RelativeAttribute of(@Nonnull String attributeName) { - if (!attributeName.matches(ATTRIBUTE_NAME_REGEX)) { - throw new IllegalArgumentException("Not a valid attribute name: " + attributeName); - } - return new RelativeAttribute(attributeName); - } - - private static final String ATTRIBUTE_NAME_REGEX = "^[a-zA-Z_]\\w*$"; - - @Nonnull - private final String attributeName; - - /** - * Full constructor. - * - * @param attributeName the name of the attribute to generate - */ - public RelativeAttribute(@Nonnull String attributeName) { - this.attributeName = attributeName; - } - - /** - * Provides the name of the represented attribute. - */ - @Nonnull - public String getAttributeName() { - return attributeName; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - RelativeAttribute that = (RelativeAttribute) o; - return attributeName.equals(that.attributeName); - } - - @Override - public int hashCode() { - return Objects.hash(attributeName); - } - - @Override - public String toString() { - return attributeName; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ResourcePath.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ResourcePath.java deleted file mode 100644 index d4f9985..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/ResourcePath.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.core; - -import java.io.File; -import java.util.Objects; -import javax.annotation.Nonnull; - -/** - * A {@code ResourcePath} represents a fully-qualified name of some model element to be used in a - * join. - * - * @author Rico Bergmann - */ -public class ResourcePath { - - /** - * Generates a new {@code path} given the path to its containing <em>package</em> and the name of - * the resource which should be referenced. - */ - @Nonnull - public static ResourcePath from(@Nonnull String packagePath, @Nonnull String resourceName) { - return new ResourcePath(packagePath, resourceName); - } - - /** - * Generates a new {@code path} given its fully-qualified name. - * - * @param qualifiedResourcePath the path. It is expected to conform to the format {@code - * pathToResource.resourceName} - */ - @Nonnull - public static ResourcePath parse(@Nonnull String qualifiedResourcePath) { - if (qualifiedResourcePath.equals(".")) { - throw new IllegalArgumentException( - "Not a valid resource path: '" + qualifiedResourcePath + "'"); - } - - int splitPos = qualifiedResourcePath.lastIndexOf("."); - - String packagePath; - if (splitPos == -1) { - packagePath = ""; - } else { - packagePath = qualifiedResourcePath.substring(0, splitPos); - } - - String resourceName = qualifiedResourcePath.substring(splitPos + 1); - return new ResourcePath(packagePath, resourceName); - } - - /** - * Generates a new {@code path} given its fully-qualified name. - * <p> - * The name will be interpreted as some location on the file system (that is as {@code - * /path/to/resource}). However, both {@code \} as well as {@code /} will be accepted as path - * separators. - * - * @param qualifiedResourcePath the path. It is expected to conform to the format {@code - * pathToResource/resourceName} - */ - public static ResourcePath parseAsFileSystemPath(@Nonnull String qualifiedResourcePath) { - return parse(toPackageStylePath(qualifiedResourcePath)); - } - - /** - * Converts a path as used by the file system to the corresponding path as used in a Java package. - */ - protected static String toPackageStylePath(@Nonnull String fileSystemResourcePath) { - return fileSystemResourcePath.replaceAll("[\\\\/]", "."); - } - - @Nonnull - protected final String resourcePath; - - @Nonnull - protected final String resourceName; - - /** - * Full constructor. - * - * @param resourcePath the path to the directory/package in which the resource resides - * @param resourceName the name of the class (or other resource) - */ - public ResourcePath(@Nonnull String resourcePath, @Nonnull String resourceName) { - if (resourceName.isEmpty()) { - throw new IllegalArgumentException("Resource name may not be empty"); - } - this.resourcePath = resourcePath; - this.resourceName = resourceName; - } - - /** - * Provides the path to the directory/package in which {@code this} resource resides. The path - * will be in "Java-package style", i.e. its components will be separated by {@code .}. - */ - @Nonnull - public String getResourcePath() { - return resourcePath; - } - - /** - * Provides the name of the resource which is represented by {@code this} path. - * <p> - * The name is relative to the containing directory/package. - */ - @Nonnull - public String getResourceName() { - return resourceName; - } - - /** - * Converts {@code this} path to {@code String}. It will match the format {@code package.name}. - */ - @Nonnull - public String get() { - return this.toString(); - } - - /** - * Converts {@code this} path to a {@code String}, treating it as some path on the file system. - * <p> - * The components of the path will be separated by the platform-dependent separator for the - * current platform. That is, its result may vary depending on the OS on which it is run. - */ - @Nonnull - public String getAsFileSystemPath() { - return this.toString().replaceAll("\\.", File.pathSeparator); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ResourcePath that = (ResourcePath) o; - return this.resourcePath.equals(that.resourcePath) && - this.resourceName.equals(that.resourceName); - } - - @Override - public int hashCode() { - return Objects.hash(resourcePath, resourceName); - } - - @Override - public String toString() { - if (resourcePath.isEmpty()) { - return resourceName; - } - return resourcePath + "." + resourceName; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/TypedAttributePath.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/core/TypedAttributePath.java deleted file mode 100644 index 0384a2a..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/core/TypedAttributePath.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.core; - -import java.util.Objects; -import javax.annotation.Nonnull; - -/** - * A {@code TypedAttributePath} extends a default {@link AttributePath} by adding type information, - * i.e. adding information about the type of the object the path references. - * <p> - * As we do not have any knowledge about the actual classes that are represented by paths we may - * not validate, whether the given type indeed matches the attribute's type. - * - * @author Rico Bergmann - */ -public class TypedAttributePath extends AttributePath { - - private static final String PATH_TYPE_SEPARATOR = ":"; - - /** - * Creates a new {@code TypedAttributePath} by combining the provided path and type information. - */ - @Nonnull - public static TypedAttributePath of(@Nonnull AttributePath path, @Nonnull ClassResource type) { - return new TypedAttributePath(path, type); - } - - /** - * Generates a new {@code TypedAttributePath} by splitting up the given path into its path and - * type portion. The {@code qualifiedTypedPath} is expected to match the format {@code path:type}, - * where {@code path} may be parsed using {@link AttributePath#fromQualifiedPath(String)} and type - * may be parsed using {@link ClassResource#fromQualifiedName(String)}. - */ - @Nonnull - public static TypedAttributePath fromQualifiedTypedPath(@Nonnull String qualifiedTypedPath) { - final int pathTypeSplitPos = qualifiedTypedPath.lastIndexOf(PATH_TYPE_SEPARATOR); - - if (pathTypeSplitPos < 0) { - throw new IllegalArgumentException("Missing type portion on '" + qualifiedTypedPath + "'"); - } - - final String qualifiedPath = qualifiedTypedPath.substring(0, pathTypeSplitPos); - final String type = qualifiedTypedPath.substring(pathTypeSplitPos + 1); - return new TypedAttributePath(AttributePath.fromQualifiedPath(qualifiedPath), ClassResource.fromQualifiedName(type)); - } - - @Nonnull - private final ClassResource type; - - /** - * Full constructor. - * - * @param path the attribute - * @param type the attribute's type - */ - public TypedAttributePath( - @Nonnull AttributePath path, - @Nonnull ClassResource type) { - super(path); - this.type = type; - } - - /** - * Provides the type of {@code this} attribute. - */ - @Nonnull - public ClassResource getType() { - return type; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof TypedAttributePath)) { - return false; - } - if (!super.equals(o)) { - return false; - } - TypedAttributePath that = (TypedAttributePath) o; - return type.equals(that.type); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), type); - } - - @Override - public String toString() { - return super.toString() + PATH_TYPE_SEPARATOR + type.toString(); - } - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/CompoundKeepExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/CompoundKeepExpression.java deleted file mode 100644 index 1e253da..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/CompoundKeepExpression.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.List; -import javax.annotation.Nonnull; - -/** - * A {@code CompoundKeepExpression} is a special kind of {@code KeepExpression} which in turn may - * contain a number of other {@code KeepExpression}s. - * - * @author Rico Bergmann - */ -public abstract class CompoundKeepExpression extends KeepExpression { - - /** - * Provides all the keep expressions that this expression is build of. - */ - @Nonnull - public abstract List<KeepExpression> getKeeps(); - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/JoinExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/JoinExpression.java deleted file mode 100644 index ecdccf9..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/JoinExpression.java +++ /dev/null @@ -1,204 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; - -/** - * A {@code JoinExpression} combines two classes of the source models and - * generates a new view derived from them. - * <p> - * At a conceptual level, these classes are referred to as the {@code left} and - * {@code right} class. - * <p> - * Other than the classes to combine, each join also consists of a number of - * {@link KeepExpression}s which contain the fields which should form the - * resulting class as well as information on how to set their values. - * <p> - * As there are a number of different joins available, this class is left - * {@code abstract} with subclasses to represent the specific joins. - * - * @author Rico Bergmann - * @see NaturalJoinExpression - * @see OuterJoinExpression - * @see ThetaJoinExpression - */ -public abstract class JoinExpression implements Iterable<KeepExpression> { - - /** - * The {@code JoinType} defines which rules should be applied when - * performing the join. - */ - public enum JoinType { - - /** - * The {@code natural join} combines two classes based on attributes - * with equal name and type. - * - * @see NaturalJoinExpression - */ - NATURAL, - - /** - * The {@code outer join} works like the {@link #NATURAL} one, but - * leaves instances from one class with no corresponding instance in the - * other class according to the {@code outer join - * type}. See the subclass for details. - * - * @see OuterJoinExpression - */ - OUTER, - - /** - * The {@code theta join} is more general than the {@link #NATURAL} and - * {@link #OUTER} one as it enables an arbitrary criteria to define - * whether two instances are "joinable" or not. - * - * @see ThetaJoinExpression - */ - THETA - } - - @Nonnull - protected final ClassResource left; - - @Nonnull - protected final ClassResource right; - - @Nonnull - protected final ClassResource target; - - @Nonnull - protected final List<KeepExpression> keeps; - - /** - * Full constructor. - * - * @param left - * the left class to use in the join - * @param right - * the right class to use in the join - * @param target - * the name of the resulting view - * @param keeps - * the keep statements in the join - */ - protected JoinExpression(@Nonnull ClassResource left, @Nonnull ClassResource right, @Nonnull ClassResource target, - @Nonnull List<KeepExpression> keeps) { - - this.left = left; - this.right = right; - this.target = target; - this.keeps = keeps; - } - - /** - * Proof if the right and the left class path are equals. - * @return result value - */ - public boolean isSameElement() { - if (left.getResourceName().equals(right.getResourceName()) - && left.getResourcePath().equals(right.getResourcePath())) { - return true; - } - return false; - } - - /** - * Provides the based class used in {@code this} join. Only important for - * outer join in other cases always Left. - */ - @Nonnull - public ClassResource getBaseModel() { - return this.getLeft(); - } - - /** - * Provides the other class used in {@code this} join. Only important for - * outer join in other cases always Right. - */ - @Nonnull - public ClassResource getOtherModel() { - return this.getRight(); - } - - /** - * Provides the left class used in {@code this} join. - */ - @Nonnull - public ClassResource getLeft() { - return left; - } - - /** - * Provides the right class used in {@code this} join. - */ - @Nonnull - public ClassResource getRight() { - return right; - } - - /** - * Provides the name of the class resulting from {@code this} join. - */ - @Nonnull - public ClassResource getTarget() { - return target; - } - - /** - * Provides the {@code keep} statements that should be used to build the - * resulting class. - */ - @Nonnull - public Iterable<KeepExpression> getKeeps() { - return keeps; - } - - public List<KeepExpression> getKeepsList() { - return Collections.unmodifiableList(keeps); - } - - /** - * Provides the type of {@code this} join. - */ - @Nonnull - public abstract JoinType getType(); - - /** - * Provides the type of {@code this} join as a non-technical {@code String}. - */ - @Nonnull - abstract String getJoinTypeAsString(); - - @Nonnull - @Override - public Iterator<KeepExpression> iterator() { - return keeps.iterator(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - JoinExpression that = (JoinExpression) o; - return this.target.equals(that.target); - } - - @Override - public int hashCode() { - return Objects.hash(target); - } - - @Override - public String toString() { - return getJoinTypeAsString() + " " + left.toString() + " with " + right.toString() + " as " + target.toString(); - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAggregateExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAggregateExpression.java deleted file mode 100644 index d0da5aa..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAggregateExpression.java +++ /dev/null @@ -1,261 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.Objects; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.AttributePath; -import org.rosi_project.model_sync.model_join.representation.core.RelativeAttribute; - -/** - * A {@code KeepAggregateExpression} adds an attribute to some join by calculating an aggregation on - * the referenced collection of numerical values. The possible aggregation operations are equal to - * those provided by the SQL programming language. - * <p> - * The aggregate's result will in turn be some numerical value. - * - * @author Rico Bergmann - */ -public class KeepAggregateExpression extends KeepExpression { - - /** - * The {@code AggregationType} defines what aggregation should be performed. - */ - public enum AggregationType { - - /** - * The attribute's value should be the sum of all the referenced values. - */ - SUM, - - /** - * The attribute's value should be the average value of all the referenced values. - */ - AVG, - - /** - * The attribute's value should be the minimum value of all the referenced values. - */ - MIN, - - /** - * The attribute's value should be the maximum value of all the referenced values. - */ - MAX, - - /** - * The attribute's value should be the number of referenced elements. - */ - SIZE - } - - /** - * The {@code AggregateBuilder} enables the construction of new {@link KeepAggregateExpression}s - * through a nice and fluent interface. - * - * @author Rico Bergmann - */ - public static class AggregateBuilder { - - @Nonnull - private final AggregationType aggregationType; - - @Nonnull - private final RelativeAttribute aggregatedAttribute; - - @Nonnull - private AttributePath source; - - /** - * Full constructor. - * - * @param aggregationType the aggregation operation that should be performed - * @param aggregatedAttribute the attribute on which the aggregation should be performed - */ - AggregateBuilder(@Nonnull AggregationType aggregationType, - @Nonnull RelativeAttribute aggregatedAttribute) { - this.aggregationType = aggregationType; - this.aggregatedAttribute = aggregatedAttribute; - } - - /** - * Specifies the reference destination that provides the attribute to join. - * <p> - * Suppose the following example: - * <pre> - * {@code - * class City { - * List<Street> streets; - * } - * - * class Street { - * int length; - * } - * } - * </pre> - * If one was to calculate the average length of all streets per city, the following aggregation - * could be used: {@code keep aggregate avg(length) over City.streets as avgStreetLength}. In - * this case, {@code City.streets} is the wanted reference destination as it provides the {@code - * length} attribute which should be used for the aggregation. - */ - @Nonnull - public AggregateBuilder over(@Nonnull AttributePath source) { - this.source = source; - return this; - } - - /** - * Specifies the name of the aggregation attribute in the target join. - */ - @Nonnull - public KeepAggregateExpression as(@Nonnull AttributePath target) { - return new KeepAggregateExpression(aggregationType, aggregatedAttribute, source, target); - } - } - - /** - * Generates a new {@code keep aggregate} expression that sums up the referenced values. - */ - @Nonnull - public static AggregateBuilder sum(@Nonnull RelativeAttribute attribute) { - return new AggregateBuilder(AggregationType.SUM, attribute); - } - - /** - * Generates a new {@code keep aggregate} expression that calculates the average value of the - * referenced values. - */ - @Nonnull - public static AggregateBuilder avg(@Nonnull RelativeAttribute attribute) { - return new AggregateBuilder(AggregationType.AVG, attribute); - } - - /** - * Generates a new {@code keep aggregate} expression that provides the minimum value of the - * referenced values. - */ - @Nonnull - public static AggregateBuilder min(@Nonnull RelativeAttribute attribute) { - return new AggregateBuilder(AggregationType.MIN, attribute); - } - - /** - * Generates a new {@code keep aggregate} expression that provides the maximum value of the - * referenced values. - */ - @Nonnull - public static AggregateBuilder max(@Nonnull RelativeAttribute attribute) { - return new AggregateBuilder(AggregationType.MAX, attribute); - } - - /** - * Generates a new {@code keep aggregate} expression that counts the number of values that are - * referenced. - */ - @Nonnull - public static AggregateBuilder size(@Nonnull RelativeAttribute attribute) { - return new AggregateBuilder(AggregationType.SIZE, attribute); - } - - @Nonnull - private final AggregationType aggregation; - - @Nonnull - private final RelativeAttribute aggregatedAttribute; - - @Nonnull - private final AttributePath source; - - @Nonnull - private final AttributePath target; - - /** - * Full constructor. - * - * @param aggregation the aggregation operation that should be performed - * @param aggregatedAttribute the attribute on which the aggregation should be performed - * @param source the field which provides the {@code aggregatedAttribute}. Therefore this - * attribute has to be multi-valued. - * @param target the name of the attribute under which the aggregation result should be - * available in the join - */ - public KeepAggregateExpression( - @Nonnull AggregationType aggregation, - @Nonnull RelativeAttribute aggregatedAttribute, - @Nonnull AttributePath source, - @Nonnull AttributePath target) { - this.aggregation = aggregation; - this.aggregatedAttribute = aggregatedAttribute; - this.source = source; - this.target = target; - } - - /** - * Provides the aggregation operation {@code this} expression will perform. - */ - @Nonnull - public AggregationType getAggregation() { - return aggregation; - } - - /** - * Provides the attribute that will be aggregated. As all {@link AggregationType aggregation - * operations} are defined on numerical values, this attribute in turn has to be of numerical - * type. - */ - @Nonnull - public RelativeAttribute getAggregatedAttribute() { - return aggregatedAttribute; - } - - /** - * Provides the field which contains the {@link #getAggregatedAttribute() aggregated attribute}. - * As an aggregation will - by definition - be performed upon an arbitrary number of values, this - * attribute has to be some kind of collection. - */ - @Nonnull - public AttributePath getSource() { - return source; - } - - /** - * Provides the attribute under which the result of {@code this} aggregation should be made - * available. - */ - @Nonnull - public AttributePath getTarget() { - return target; - } - - @Override - public void accept(@Nonnull KeepExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - KeepAggregateExpression that = (KeepAggregateExpression) o; - return aggregation == that.aggregation && - aggregatedAttribute.equals(that.aggregatedAttribute) && - source.equals(that.source) && - target.equals(that.target); - } - - @Override - public int hashCode() { - return Objects.hash(aggregation, aggregatedAttribute, source, target); - } - - @Override - public String toString() { - String aggregationOperation = aggregation.toString().toLowerCase(); - return "keep aggregate " // - + aggregationOperation + "(" + aggregatedAttribute + ") " // - + "over" + source // - + " as " + target; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAttributesExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAttributesExpression.java deleted file mode 100644 index 99cdb81..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepAttributesExpression.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import com.google.common.collect.Lists; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.AttributePath; - -/** - * A {@code KeepAttributesExpression} simply retains a number of attributes from arbitrary source - * classes and includes them in the target join. The attributes' name and type will be left - * unchanged. - * - * @author Rico Bergmann - */ -public class KeepAttributesExpression extends KeepExpression { - - /** - * Generates a new keep expression for a number of attributes. - */ - @Nonnull - public static KeepAttributesExpression keepAttributes(@Nonnull AttributePath firstAttribute, - @Nonnull AttributePath... moreAttributes) { - List<AttributePath> attributes = Lists.newArrayList(moreAttributes); - attributes.add(0, firstAttribute); - return new KeepAttributesExpression(attributes); - } - - @Nonnull - private final List<AttributePath> attributes; - - /** - * Full constructor. - * - * @param attributes the attributes for which the expression should be created - */ - public KeepAttributesExpression(@Nonnull List<AttributePath> attributes) { - this.attributes = attributes; - } - - /** - * Provides the attributes that should be retained in the join. - * <p> - * The returned {@code List} is a shallow copy of the attributes in {@code this} expression. - */ - @Nonnull - public List<AttributePath> getAttributes() { - return new ArrayList<>(attributes); - } - - @Override - public void accept(@Nonnull KeepExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - KeepAttributesExpression that = (KeepAttributesExpression) o; - return this.attributes.equals(that.attributes); - } - - @Override - public int hashCode() { - return Objects.hash(attributes); - } - - @Override - public String toString() { - return "keep attributes " + attributes.stream() // - .map(AttributePath::toString) // - .reduce((firstAttribute, secondAttribute) -> firstAttribute + ", " + secondAttribute) // - .orElseThrow(() -> new IllegalStateException( - "A keep attribute expression has to keep at least one attribute")); - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepCalculatedExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepCalculatedExpression.java deleted file mode 100644 index 19a1a22..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepCalculatedExpression.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.Objects; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.AttributePath; -import org.rosi_project.model_sync.model_join.representation.core.OCLStatement; -import org.rosi_project.model_sync.model_join.representation.core.TypedAttributePath; - -/** - * A {@code KeepCalculatedExpression} adds an attribute to some join by evaluating an arbitrary - * {@link OCLStatement OCL statement}. - * <p> - * This is the most general kind of {@link KeepExpression} as all other expressions may be expressed - * in OCL as well. - * - * @author Rico Bergmann - * @see OCLStatement - */ -public class KeepCalculatedExpression extends KeepExpression { - - /** - * The {@code KeepCalculatedBuilder} enables the construction of new {@link - * KeepCalculatedExpression}s through a nice and fluent interface. - * - * @author Rico Bergmann - */ - public static class KeepCalculatedBuilder { - - @Nonnull - private final OCLStatement calculationRule; - - /** - * Full constructor. - * - * @param calculationRule the OCL statement that should be used to calculate the attribute's - * value. - */ - KeepCalculatedBuilder(@Nonnull OCLStatement calculationRule) { - this.calculationRule = calculationRule; - } - - /** - * Specifies the name of the attribute in the target join. - */ - @Nonnull - public KeepCalculatedExpression as(@Nonnull TypedAttributePath target) { - return new KeepCalculatedExpression(calculationRule, target); - } - } - - /** - * Generates a new {@code keep calculated} expression. - */ - @Nonnull - public static KeepCalculatedBuilder keepCalculatedAttribute( - @Nonnull OCLStatement calculationRule) { - return new KeepCalculatedBuilder(calculationRule); - } - - @Nonnull - private final OCLStatement calculationRule; - - @Nonnull - private final TypedAttributePath target; - - /** - * Full constructor. - * - * @param calculationRule the OCL statement that should be used to calculate the attribute's - * value - * @param target the name of the attribute under which the aggregation result should be - * available in the join - */ - public KeepCalculatedExpression( - @Nonnull OCLStatement calculationRule, - @Nonnull TypedAttributePath target) { - this.calculationRule = calculationRule; - this.target = target; - } - - /** - * Provides the OCL expression that is used to determine the value of {@code this} attribute. - */ - @Nonnull - public OCLStatement getCalculationRule() { - return calculationRule; - } - - /** - * Provides the attribute under which the result of {@code this} calculation should be made - * available. - */ - @Nonnull - public TypedAttributePath getTarget() { - return target; - } - - @Override - public void accept(@Nonnull KeepExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - KeepCalculatedExpression that = (KeepCalculatedExpression) o; - return calculationRule.equals(that.calculationRule) && - target.equals(that.target); - } - - @Override - public int hashCode() { - return Objects.hash(calculationRule, target); - } - - @Override - public String toString() { - return "keep calculated attribute " + calculationRule + " as " + target; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepExpression.java deleted file mode 100644 index bd87900..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepExpression.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import javax.annotation.Nonnull; - -/** - * A {@code KeepExpression} configures the resulting model of a join. - * <p> - * This mostly means retaining some attributes or calculating their value but may also include - * maintaining references to other classes. - * - * @author Rico Bergmann - */ -public abstract class KeepExpression { - - /** - * The {@code visitor} enables the execution of arbitrary algorithms on {@code KeepExpression}s - * without taking care of the actual traversal of the expression tree. - */ - public interface KeepExpressionVisitor { - - /** - * Runs the algorithm as appropriate for {@link KeepAggregateExpression}s. - */ - void visit(@Nonnull KeepAggregateExpression expression); - - /** - * Runs the algorithm as appropriate for {@link KeepAttributesExpression}s. - */ - void visit(@Nonnull KeepAttributesExpression expression); - - /** - * Runs the algorithm as appropriate for {@link KeepCalculatedExpression}s. - */ - void visit(@Nonnull KeepCalculatedExpression expression); - - /** - * Runs the algorithm as appropriate for {@link KeepReferenceExpression}s. - */ - void visit(@Nonnull KeepReferenceExpression expression); - - /** - * Runs the algorithm as appropriate for {@link KeepSubTypeExpression}s. - */ - void visit(@Nonnull KeepSubTypeExpression expression); - - /** - * Runs the algorithm as appropriate for {@link KeepSuperTypeExpression}s. - */ - void visit(@Nonnull KeepSuperTypeExpression expression); - - } - - // TODO `as` statements may be omitted !?!? ... (╯°□°)╯︵ ┻━┻ - - /** - * Applies a {@code visitor} to {@code this} expression structure. - */ - public abstract void accept(@Nonnull KeepExpressionVisitor visitor); - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepReferenceExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepReferenceExpression.java deleted file mode 100644 index 5d6f0f3..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepReferenceExpression.java +++ /dev/null @@ -1,223 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.AttributePath; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.util.Assert; - -// TODO the Xtext grammar also specifies an optional `as reference` part - what does that part do? -// most likely `as reference` will refer to another type that was already defined in its dedicated -// join statement. - -/** - * A {@code KeepReferenceExpression} retains links to other instances in the original models. All - * objects that are referenced in the base models will also be available in the resulting ModelJoin - * views. - * <p> - * As references are directional, each expression also distinguishes between {@code outgoing} and - * {@code incoming} references - depending on whether the model class of {@code this} expression - * owns the reference ({@code outgoing}) or instances of this model class are being referenced - * ({@code incoming}). - * <p> - * The referenced instances will be made available according to a number of keep statements which - * specify the attributes to include. This boils down to the creation of a nested ModelJoin view for - * these instances. - * - * @author Rico Bergmann - */ -public class KeepReferenceExpression extends CompoundKeepExpression { - - /** - * The {@code ReferenceDirection} defines whether a reference is owned by the containing model - * class or whether it is the class being referenced. - */ - public enum ReferenceDirection { - - /** - * Indicates that the containing model class owns the reference. - */ - OUTGOING, - - /** - * Indicates that the containing model class is referenced by some other class. - */ - INCOMING - } - - /** - * The {@code KeepReferenceBuilder} enables the construction of new {@code - * KeepReferenceExpression} instances through a nice and fluent interface. - * - * @author Rico Bergmann - */ - public static class KeepReferenceBuilder { - - private ReferenceDirection referenceDirection; - private AttributePath attribute; - private ClassResource target; - - @Nonnull - private List<KeepExpression> keeps; - - /** - * Default constructor. - */ - private KeepReferenceBuilder() { - this.keeps = new ArrayList<>(); - } - - /** - * Creates an outgoing reference for the given attribute. - */ - @Nonnull - public KeepReferenceBuilder outgoing(@Nonnull AttributePath attribute) { - this.referenceDirection = ReferenceDirection.OUTGOING; - this.attribute = attribute; - return this; - } - - /** - * Creates an incoming reference for the given attribute. - */ - @Nonnull - public KeepReferenceBuilder incoming(@Nonnull AttributePath attribute) { - this.referenceDirection = ReferenceDirection.INCOMING; - this.attribute = attribute; - return this; - } - - /** - * Specifies the name of the attribute in the target join. - */ - @Nonnull - public KeepReferenceBuilder as(@Nonnull ClassResource target) { - this.target = target; - return this; - } - - /** - * Adds an attribute to the view for the referenced instances. - */ - @Nonnull - public KeepReferenceBuilder keep(@Nonnull KeepExpression keepExpression) { - this.keeps.add(keepExpression); - return this; - } - - /** - * Finishes the construction process. - */ - @Nonnull - public KeepReferenceExpression buildExpression() { - Assert.noNullArguments("All components must be specified", attribute, referenceDirection, target, keeps); - return new KeepReferenceExpression(attribute, referenceDirection, target, keeps); - } - } - - /** - * Starts the creation process for a new {@code KeepReferenceExpression}. - */ - @Nonnull - public static KeepReferenceBuilder keep() { - return new KeepReferenceBuilder(); - } - - @Nonnull - private final AttributePath attribute; - - @Nonnull - private final ReferenceDirection referenceDirection; - - @Nonnull - private final ClassResource target; - - @Nonnull - private final List<KeepExpression> keeps; - - /** - * Full constructor. - * - * @param attribute the attribute of the source model which contains the references - * @param referenceDirection whether the source model owns the reference or is being - * referenced - * @param target the name of the class which enca - * @param keeps the statements which should be build the "nested" view for the references - */ - public KeepReferenceExpression( - @Nonnull AttributePath attribute, - @Nonnull ReferenceDirection referenceDirection, - @Nonnull ClassResource target, - @Nonnull List<KeepExpression> keeps) { - this.attribute = attribute; - this.referenceDirection = referenceDirection; - this.target = target; - this.keeps = keeps; - } - - /** - * Provides the attribute of the source model which contains the references. - */ - @Nonnull - public AttributePath getAttribute() { - return attribute; - } - - /** - * Provides the kind of reference, that is whether the containing Join owns the reference or is - * being referenced by another model class or Join. - */ - @Nonnull - public ReferenceDirection getReferenceDirection() { - return referenceDirection; - } - - /** - * Provides the name of the attribute under which the referenced instances should be made - * available. - */ - @Nonnull - public ClassResource getTarget() { - return target; - } - - /** - * Provides all {@code KeepExpression keep expressions} that should be used to build the Join for - * the referenced instances. - */ - @Nonnull - @Override - public List<KeepExpression> getKeeps() { - return new ArrayList<>(keeps); - } - - @Override - public void accept(@Nonnull KeepExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - KeepReferenceExpression that = (KeepReferenceExpression) o; - return attribute.equals(that.attribute) && target.equals(that.target); - } - - @Override - public int hashCode() { - return Objects.hash(attribute, target); - } - - @Override - public String toString() { - String directionString = referenceDirection.toString().toLowerCase(); - return "keep " + directionString + " " + attribute + " as type " + target; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSubTypeExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSubTypeExpression.java deleted file mode 100644 index 76e8d60..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSubTypeExpression.java +++ /dev/null @@ -1,167 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.util.Assert; - -/** - * A {@code KeepSubTypeExpression} instructs the {@code ModelJoin} runtime to instantiate the most - * specific type that inherits from this type as well. The additional instance will be built - * according to the {@code KeepExpression keep statements} that it is constructed of. - * <p> - * In order to prevent ambiguities a {@code KeepSubTypeExpression} may only be specified on joins - * that do not participate in another {@link JoinExpression join statement}. - * - * @author Rico Bergmann - */ -public class KeepSubTypeExpression extends CompoundKeepExpression { - - /** - * The {@code KeepSubTypeBuilder} enables the construction of new {@code KeepSubTypeExpression} - * instances through a nice and fluent interface. - * - * @author Rico Bergmann - */ - public static class KeepSubTypeBuilder { - - private ClassResource typeToKeep; - private ClassResource target; - private List<KeepExpression> keeps; - - /** - * Default constructor. - */ - private KeepSubTypeBuilder() { - this.keeps = new ArrayList<>(); - } - - /** - * Specifies the subtype that should be instantiated. - */ - @Nonnull - public KeepSubTypeBuilder subtype(@Nonnull ClassResource type) { - this.typeToKeep = type; - return this; - } - - /** - * Specifies the name of the class that should be generated for the subtype instances. - */ - @Nonnull - public KeepSubTypeBuilder as(@Nonnull ClassResource target) { - this.target = target; - return this; - } - - /** - * Adds a {@link KeepExpression keep statement} for the subtype-class. The described attribute - * will be initialized for each instantiated subtype element. - */ - @Nonnull - public KeepSubTypeBuilder keep(@Nonnull KeepExpression keep) { - this.keeps.add(keep); - return this; - } - - /** - * Finishes the construction process. - */ - @Nonnull - public KeepSubTypeExpression buildExpression() { - Assert.noNullArguments("All components must be specified", typeToKeep, target, keeps); - return new KeepSubTypeExpression(typeToKeep, target, keeps); - } - - } - - /** - * Starts the creation process for a new {@code KeepSubTypeExpression}. - */ - @Nonnull - public static KeepSubTypeBuilder keep() { - return new KeepSubTypeBuilder(); - } - - @Nonnull - private final ClassResource typeToKeep; - - @Nonnull - private final ClassResource target; - - @Nonnull - private final List<KeepExpression> keeps; - - /** - * Full constructor. - * - * @param typeToKeep the subtype that should be instantiated. - * @param target the name of the view that should be generated for all matching instances - * @param keeps the keep statements that should form the attributes of the generated view - * instances - */ - public KeepSubTypeExpression( - @Nonnull ClassResource typeToKeep, - @Nonnull ClassResource target, - @Nonnull List<KeepExpression> keeps) { - this.typeToKeep = typeToKeep; - this.target = target; - this.keeps = keeps; - } - - /** - * Provides the subtype that should be instantiated. - */ - @Nonnull - public ClassResource getType() { - return typeToKeep; - } - - /** - * Provides the name of the view that should be generated for all matching instances. - */ - @Nonnull - public ClassResource getTarget() { - return target; - } - - /** - * Provides all {@code KeepExpression keep expressions} that should be used to build the Join for - * the instances of the subclass instances. - */ - @Nonnull - @Override - public List<KeepExpression> getKeeps() { - return new ArrayList<>(keeps); - } - - @Override - public void accept(@Nonnull KeepExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - KeepSubTypeExpression that = (KeepSubTypeExpression) o; - return typeToKeep.equals(that.typeToKeep) && - target.equals(that.target); - } - - @Override - public int hashCode() { - return Objects.hash(typeToKeep, target); - } - - @Override - public String toString() { - return "keep subtype " + typeToKeep + " as " + target; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSuperTypeExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSuperTypeExpression.java deleted file mode 100644 index 6c72a3d..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/KeepSuperTypeExpression.java +++ /dev/null @@ -1,166 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.util.Assert; - -// TODO add doc - -/** - * A {@code KeepSuperTypeExpression} instructs the {@code ModelJoin} runtime to instantiate the a - * supertype of some class in a join along an instance of that class. The additional instance will - * be built according to the {@code KeepExpression keep statements} that it is constructed of. - * - * @author Rico Bergmann - */ -public class KeepSuperTypeExpression extends CompoundKeepExpression { - - /** - * The {@code KeepSuperTypeBuilder} enables the construction of new {@code KeepSuperTypeExpression} - * instances through a nice and fluent interface. - * - * @author Rico Bergmann - */ - public static class KeepSuperTypeBuilder { - - private ClassResource typeToKeep; - private ClassResource target; - private List<KeepExpression> keeps; - - /** - * Default constructor. - */ - private KeepSuperTypeBuilder() { - this.keeps = new ArrayList<>(); - } - - /** - * Specifies the supertype that should be instantiated. - */ - @Nonnull - public KeepSuperTypeBuilder supertype(@Nonnull ClassResource type) { - this.typeToKeep = type; - return this; - } - - /** - * Specifies the name of the class that should be generated for the subtype instances. - */ - @Nonnull - public KeepSuperTypeBuilder as(@Nonnull ClassResource target) { - this.target = target; - return this; - } - - /** - * Adds a {@link KeepExpression keep statement} for the subtype-class. The described attribute - * will be initialized for each instantiated subtype element. - */ - @Nonnull - public KeepSuperTypeBuilder keep(@Nonnull KeepExpression keep) { - this.keeps.add(keep); - return this; - } - - /** - * Finishes the construction process. - */ - @Nonnull - public KeepSuperTypeExpression buildExpression() { - Assert.noNullArguments("All components must be specified", typeToKeep, target, keeps); - return new KeepSuperTypeExpression(typeToKeep, target, keeps); - } - - } - - /** - * Starts the creation process for a new {@code KeepSuperTypeExpression}. - */ - @Nonnull - public static KeepSuperTypeBuilder keep() { - return new KeepSuperTypeBuilder(); - } - - @Nonnull - private final ClassResource typeToKeep; - - @Nonnull - private final ClassResource target; - - @Nonnull - private final List<KeepExpression> keeps; - - /** - * Full constructor. - * - * @param typeToKeep the supertype that should be instantiated. - * @param target the name of the view that should be generated for all matching instances - * @param keeps the keep statements that should form the attributes of the generated view - * instances - */ - public KeepSuperTypeExpression( - @Nonnull ClassResource typeToKeep, - @Nonnull ClassResource target, - @Nonnull List<KeepExpression> keeps) { - this.typeToKeep = typeToKeep; - this.target = target; - this.keeps = keeps; - } - - /** - * Provides the supertype that should be instantiated. - */ - @Nonnull - public ClassResource getType() { - return typeToKeep; - } - - /** - * Provides the name of the view that should be generated for all matching instances. - */ - @Nonnull - public ClassResource getTarget() { - return target; - } - - /** - * Provides all {@code KeepExpression keep expressions} that should be used to build the Join for - * the instances of the superclass instances. - */ - @Nonnull - @Override - public List<KeepExpression> getKeeps() { - return new ArrayList<>(keeps); - } - - @Override - public void accept(@Nonnull KeepExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - KeepSuperTypeExpression that = (KeepSuperTypeExpression) o; - return typeToKeep.equals(that.typeToKeep) && - target.equals(that.target); - } - - @Override - public int hashCode() { - return Objects.hash(typeToKeep, target); - } - - @Override - public String toString() { - return "keep supertype " + typeToKeep + " as " + target; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ModelJoinExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ModelJoinExpression.java deleted file mode 100644 index 30382b5..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ModelJoinExpression.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import javax.annotation.Nonnull; - -/** - * The {@code ModelJoinExpression} represents an actual ModelJoin, i.e. a specification of which - * joins to use and how they should be built. - * - * @author Rico Bergmann - */ -public class ModelJoinExpression implements Iterable<JoinExpression> { - - private String name = ""; - - public String getName() { - return name; - } - - public void setName(String n) { - name = n; - } - - /** - * Creates a new {@code ModelJoin}. - * - * @param joins the joins that should be included. - */ - @Nonnull - public static ModelJoinExpression with(@Nonnull List<JoinExpression> joins) { - return new ModelJoinExpression(joins); - } - - /** - * Ensures that all joins specify distinct join targets and throws an {@code - * IllegalArgumentException} otherwise. - */ - private static void assertDifferentTargetsForAllJoins(Collection<JoinExpression> joinsToCheck) { - final long totalNumberOfJoins = joinsToCheck.size(); - final long numberOfDistinctTargetsSpecified = joinsToCheck.stream()// - .map(JoinExpression::getTarget) // - .distinct() // - .count(); - - if (numberOfDistinctTargetsSpecified < totalNumberOfJoins) { - throw new IllegalArgumentException("Some joins share the same target"); - } - } - - @Nonnull - private final List<JoinExpression> joins; - - /** - * Full constructor. - * - * @param joins the joins that this ModelJoin consists of - */ - public ModelJoinExpression(List<JoinExpression> joins) { - assertDifferentTargetsForAllJoins(joins); - this.joins = joins; - } - - /** - * Provides all joins {@code this} model specifies. - */ - @Nonnull - public Collection<JoinExpression> getJoins() { - return new ArrayList<>(joins); - } - - @Nonnull - @Override - public Iterator<JoinExpression> iterator() { - return joins.iterator(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ModelJoinExpression that = (ModelJoinExpression) o; - return joins.equals(that.joins); - } - - @Override - public int hashCode() { - return Objects.hash(joins); - } - - @Override - public String toString() { - return joins.toString(); - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/NaturalJoinExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/NaturalJoinExpression.java deleted file mode 100644 index 7c3d7b4..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/NaturalJoinExpression.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.List; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; - -/** - * The {@code natural join} combines model classes based on attributes of the - * same name and type. - * <p> - * As an example, consider the following two classes: - * - * <pre> - * { - * @code - * class Person { - * String firstname; - * String lastname; - * Date dateOfBirth; - * Char gender; - * // ... other code omitted - * } - * - * class Employee { - * int id; - * String firstname; - * String lastname; - * Date dateOfBirth; - * int salary; - * // ... other code omitted - * } - * } - * </pre> - * <p> - * Performing a natural join on {@code Person} and {@code Employee} will combine - * instances only if they share the same first name, last name and date of - * birth. All other fields will not be considered during the comparison. - * - * <pre> - * ┌───────────────────┐ ┌───────────────────┐ - * │ Person │ │ Employee │ - * ├───────────────────┤ ├───────────────────┤ - * │firstname: String │ ┄┄┄┄┄┄┄╮ │id: int │ - * │lastname: String │ ┄┄┄┄┄╮ ╰┄┄┄ │firstname: String │ - * │dateOfBirth: Date │ ┄┄┄╮ ╰┄┄┄┄┄ │lastname: String │ - * │gender: Char │ ╰┄┄┄┄┄┄┄ │dateOfBirth: Date │ - * ├───────────────────┤ │salary: int │ - * │ ... │ ├───────────────────┤ - * └───────────────────┘ │ ... │ - * └───────────────────┘ - * </pre> - * <p> - * The resulting class will by default only contain the attributes that where - * used in comparison (first name, last name and date of birth in the example). - * - * @author Rico Bergmann - */ -public class NaturalJoinExpression extends JoinExpression { - - /* - * TODO: discuss should the natural join extend theta join instead (from a - * theoretical view more appropriate. However this would also mean that the - * natural join has to derive the join condition as well. This in turn would - * also meant that class resources would have to know which attributes are - * defined on them. - */ - - /** - * Full constructor. - * - * @param left - * the left class to use in the join - * @param right - * the right class to use in the join - * @param target - * the name of the resulting view - * @param keeps - * the keep statements in the join - */ - public NaturalJoinExpression(@Nonnull ClassResource left, @Nonnull ClassResource right, - @Nonnull ClassResource target, @Nonnull List<KeepExpression> keeps) { - super(left, right, target, keeps); - } - - @Nonnull - @Override - public JoinType getType() { - return JoinType.NATURAL; - } - - @Nonnull - @Override - String getJoinTypeAsString() { - return "natural join"; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/OuterJoinExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/OuterJoinExpression.java deleted file mode 100644 index 376dad0..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/OuterJoinExpression.java +++ /dev/null @@ -1,150 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.List; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; - -/** - * The {@code outer join} is a special kind of {@code natural join}: depending - * on its specific type, all elements of one source will definitely be included - * - potentially being joined with matching instances of the other source. - * <p> - * Matches will be determined the same way as with a normal - * {@code natural join}. However, depending on the kind of join, the result will - * include all instances of the {@code left} or {@code right} source model, no - * matter whether they have a matching instance in the other model or not. In - * case that some instance has no corresponding instance in the other model, all - * fields that belong to the other model will be set to {@code null}. - * <p> - * Consider the following example (derived from the model shown in the - * {@link NaturalJoinExpression} documentation) - * - * <pre> - * Person: - * ┌───────────┬──────────┬─────────────┬────────┐ - * │ firstname │ lastname │ dateOfBirth │ gender │ - * ├───────────┼──────────┼─────────────┼────────┤ - * │ Jane │ Doe │ 1999-01-01 │ f │ - * │ John │ Doe │ 1998-02-03 │ m │ - * │ Maria │ Miller │ 1990-12-31 │ f │ - * └───────────┴──────────┴─────────────┴────────┘ - * - * Employee: - * ┌────┬───────────┬──────────┬─────────────┬────────┐ - * │ id │ firstname │ lastname │ dateOfBirth │ salary │ - * ├────┼───────────┼──────────┼─────────────┼────────┤ - * │ 1 │ Jane │ Doe │ 1999-01-01 │ 20000 │ - * │ 2 │ John │ Doe │ 1997-03-04 │ 15000 │ - * │ 3 │ Maria │ Miller │ 1990-12-31 │ 17500 │ - * └────┴───────────┴──────────┴─────────────┴────────┘ - * </pre> - * - * Performing an left outer join as described in the - * {@link NaturalJoinExpression natural join} documentation will lead to the - * following result (again written in relational style): - * - * <pre> - * ┌───────────┬──────────┬─────────────┬────────┬──────┬────────┐ - * │ firstname │ lastname │ dateOfBirth │ gender │ id │ salary │ - * ├───────────┼──────────┼─────────────┼────────┼──────┼────────┤ - * │ Jane │ Doe │ 1999-01-01 │ f │ 1 │ 20000 │ - * │ John │ Doe │ 1998-02-03 │ m │ NULL │ NULL │ - * │ Maria │ Miller │ 1990-12-31 │ f │ 3 │ 17500 │ - * └───────────┴──────────┴─────────────┴────────┴──────┴────────┘ - * </pre> - * - * @author Rico Bergmann - */ -public class OuterJoinExpression extends NaturalJoinExpression { - - /** - * The {@code JoinDirection} denotes which side of the source models should - * keep all of its instances - no matter whether they have a matching - * instances in the other model or not. - */ - public enum JoinDirection { - LEFT, RIGHT - } - - @Nonnull - private final JoinDirection direction; - - /** - * Full constructor. - * - * @param left - * the left class to use in the join - * @param right - * the right class to use in the join - * @param target - * the name of the resulting view - * @param direction - * the source model which should definitely be kept - * @param keeps - * the keep statements in the join - */ - public OuterJoinExpression(@Nonnull ClassResource left, @Nonnull ClassResource right, @Nonnull ClassResource target, - @Nonnull JoinDirection direction, @Nonnull List<KeepExpression> keeps) { - super(left, right, target, keeps); - this.direction = direction; - } - - /** - * Provides the position of the source model on which the join should be - * based. - */ - @Nonnull - public JoinDirection getDirection() { - return direction; - } - - /** - * Provides the source model on which the join should be based. - */ - @Override - public ClassResource getBaseModel() { - switch (direction) { - case LEFT: - return left; - case RIGHT: - return right; - default: - throw new AssertionError(direction); - } - } - - @Override - public ClassResource getOtherModel() { - switch (direction) { - case LEFT: - return right; - case RIGHT: - return left; - default: - throw new AssertionError(direction); - } - } - - @Nonnull - @Override - public JoinType getType() { - return JoinType.OUTER; - } - - @Nonnull - @Override - String getJoinTypeAsString() { - String directionString; - switch (this.direction) { - case LEFT: - directionString = "left"; - break; - case RIGHT: - directionString = "right"; - break; - default: - throw new AssertionError(this.direction); - } - return directionString + " outer join"; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ThetaJoinExpression.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ThetaJoinExpression.java deleted file mode 100644 index 39f777b..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/grammar/ThetaJoinExpression.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.grammar; - -import java.util.List; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.core.OCLConstraint; - -/** - * A {@code theta join} is the most general type of join. It will determine join-compatibility - * based on an arbitrary predicate which may evaluate to {@code true} or {@code false}, denoting - * whether two instances are to be joined or not. - * <p> - * To specify this condition, {@link OCLConstraint OCL} is used. - * <p> - * As a simple example, consider the following two classes: - * <pre> - * ┌───────────────────┐ ┌───────────────────┐ - * │ Person │ │ Employee │ - * ├───────────────────┤ ├───────────────────┤ - * │firstname: String │ │id: int │ - * │lastname: String │ │fullname: String │ - * │dateOfBirth: Date │ │dateOfBirth: Date │ - * │gender: Char │ │salary: int │ - * ├───────────────────┤ ├───────────────────┤ - * │ ... │ │ ... │ - * └───────────────────┘ └───────────────────┘ - * </pre> - * <p> - * The expression {@code person.firstname + ' ' + person.lastname = employee.fullname} would than - * match all persons with employee instances if they have the same name. - * - * @author Rico Bergmann - */ -public class ThetaJoinExpression extends JoinExpression { - - @Nonnull - private final OCLConstraint condition; - - /** - * Full constructor. - * - * @param left the left class to use in the join - * @param right the right class to use in the join - * @param target the name of the resulting view - * @param condition the condition which should be used to determine join-compatibility - */ - public ThetaJoinExpression( - @Nonnull ClassResource left, - @Nonnull ClassResource right, - @Nonnull ClassResource target, - @Nonnull OCLConstraint condition, - @Nonnull List<KeepExpression> keeps) { - super(left, right, target, keeps); - this.condition = condition; - } - - /** - * Provides the condition which should be used to determine whether two instances are join - * compatible or not. - */ - @Nonnull - public OCLConstraint getCondition() { - return condition; - } - - @Nonnull - @Override - public JoinType getType() { - return JoinType.THETA; - } - - @Nonnull - @Override - String getJoinTypeAsString() { - return "theta join"; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParser.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParser.java deleted file mode 100644 index 87c6f0c..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParser.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.parser; - -import java.io.File; -import java.util.Optional; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; - -/** - * The {@code ModelJoinParser} reads a {@code ModelJoin} file from disk and creates a matching - * logical representation for it. - * - * @author Rico Bergmann - */ -public interface ModelJoinParser { - - /** - * Converts the {@code ModelJoin} file into a {@link ModelJoinExpression}, wrapped into an {@code - * Optional}. If parsing fails, an empty {@code Optional} will be returned. - */ - @Nonnull - Optional<ModelJoinExpression> read(@Nonnull File modelFile); - - /** - * Converts the {@code ModelJoin} file into a {@link ModelJoinExpression}. If parsing fails, a - * {@link ModelJoinParsingException} will be thrown. - * - * @throws ModelJoinParsingException if the model may not be parsed for some reason. - */ - @Nonnull - ModelJoinExpression readOrThrow(@Nonnull File modelFile); - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParsingException.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParsingException.java deleted file mode 100644 index 6b72c01..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/ModelJoinParsingException.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.parser; - -/** - * The {@code ModelJoinParsingException} indicates that a {@code ModelJoin} file could not be read - * correctly, e.g. because of missing values or a malformed structure. - * - * @author Rico Bergmann - */ -public class ModelJoinParsingException extends RuntimeException { - - /** - * @see RuntimeException#RuntimeException(String) - */ - public ModelJoinParsingException(String message) { - super(message); - } - - /** - * @see RuntimeException#RuntimeException(String, Throwable) - */ - public ModelJoinParsingException(String message, Throwable cause) { - super(message, cause); - } - - /** - * @see RuntimeException#RuntimeException(Throwable) - */ - public ModelJoinParsingException(Throwable cause) { - super(cause); - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/AntlrBackedModelJoinParser.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/AntlrBackedModelJoinParser.java deleted file mode 100644 index 8677378..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/AntlrBackedModelJoinParser.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.parser.antlr; - -import java.io.File; -import java.io.IOException; -import java.util.Optional; -import javax.annotation.Nonnull; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.CommonTokenStream; -import org.antlr.v4.runtime.TokenStream; -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; -import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParser; -import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinLexer; - -/** - * The {@code AntlrBackedModelJoinParser} reads a {@code ModelJoin} file according to a compiled - * {@code ANTLR} grammar and generates the matching {@link ModelJoinExpression} for the file. - * - * @author Rico Bergmann - * @see <a href="https://www.antlr.org/">ANTLR project</a> - */ -public class AntlrBackedModelJoinParser implements ModelJoinParser { - - @Nonnull - @Override - public Optional<ModelJoinExpression> read(@Nonnull File modelFile) { - try { - return Optional.of(invokeAntlr(modelFile)); - } catch (ModelJoinParsingException e) { - return Optional.empty(); - } - } - - @Nonnull - @Override - public ModelJoinExpression readOrThrow(@Nonnull File modelFile) { - return invokeAntlr(modelFile); - } - - /** - * Executes the whole ANTLR workflow. - * - * @throws ModelJoinParsingException if the workflow fails. Details on the error will be added - * to the exception. - */ - protected ModelJoinExpression invokeAntlr(@Nonnull File modelFile) { - CharStream modelStream = consumeCompleteModelFileContent(modelFile); - ModelJoinLexer lexer = initializeLexerBasedOn(modelStream); - TokenStream tokenStream = tokenize(lexer); - - org.rosi_project.model_sync.model_join.representation.parser.antlr.generated. // - ModelJoinParser modelJoinParser = initializeParserBasedOn(tokenStream); - - org.rosi_project.model_sync.model_join.representation.parser.antlr.generated. // - ModelJoinParser.ModeljoinContext modelJoinContext = modelJoinParser.modeljoin(); - - ModelJoinVisitor modelJoinVisitor = new ModelJoinVisitor(); - - return modelJoinVisitor.visitModeljoin(modelJoinContext); - } - - /** - * Converts the content of a {@code ModelJoin} file into an ANTLR input stream. - * - * @throws ModelJoinParsingException if the file may not be read - */ - @Nonnull - protected CharStream consumeCompleteModelFileContent(@Nonnull File modelFile) { - try { - return CharStreams.fromPath(modelFile.toPath()); - } catch (IOException e) { - throw new ModelJoinParsingException(e); - } - } - - /** - * Sets up a lexer for the given {@code ModelJoin} file. - */ - @Nonnull - protected ModelJoinLexer initializeLexerBasedOn(@Nonnull CharStream modelFile) { - return new ModelJoinLexer(modelFile); - } - - /** - * Executes the lexing step. - */ - @Nonnull - protected TokenStream tokenize(@Nonnull ModelJoinLexer lexer) { - return new CommonTokenStream(lexer); - } - - /** - * Sets up the parser. - */ - @Nonnull - protected org.rosi_project.model_sync.model_join.representation.parser.antlr.generated. // - ModelJoinParser initializeParserBasedOn(@Nonnull TokenStream tokens) { - return new org.rosi_project.model_sync.model_join.representation.parser.antlr.generated. // - ModelJoinParser(tokens); - } - -} - diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/JoinStatementVisitor.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/JoinStatementVisitor.java deleted file mode 100644 index 3fe1c7b..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/JoinStatementVisitor.java +++ /dev/null @@ -1,183 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.parser.antlr; - -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.core.OCLConstraint; -import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression.JoinType; -import org.rosi_project.model_sync.model_join.representation.grammar.NaturalJoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.OuterJoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.ThetaJoinExpression; -import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinBaseVisitor; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.JoinContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.NaturaljoinContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.OuterjoinContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.ThetajoinContext; -import org.rosi_project.model_sync.model_join.representation.util.JoinFactory; -import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.NaturalJoinBuilder; -import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.OuterJoinBuilder; -import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.ThetaJoinBuilder; - -/** - * The {@code JoinStatementVisitor} creates {@link JoinExpression} instances for a parsed {@code - * ModelJoin} file. - * - * @author Rico Bergmann - */ -public class JoinStatementVisitor extends ModelJoinBaseVisitor<JoinExpression> { - - private final KeepStatementVisitor keepStatementVisitor; - - /** - * Default constructor. Nothing special about it. - */ - JoinStatementVisitor() { - this.keepStatementVisitor = new KeepStatementVisitor(); - } - - @Override - public JoinExpression visitJoin(JoinContext ctx) { - JoinType joinType = determineJoinType(ctx); - return invokeJoinBuilderAccordingTo(joinType, ctx); - } - - /** - * Checks, which kind of join is specified in a specific {@code JoinContext}. - */ - private JoinType determineJoinType(@Nonnull JoinContext ctx) { - if (ctx.thetajoin() != null) { - return JoinType.THETA; - } else if (ctx.naturaljoin() != null) { - return JoinType.NATURAL; - } else if (ctx.outerjoin() != null) { - return JoinType.OUTER; - } else { - throw new ModelJoinParsingException("Unkown join type in join " + ctx); - } - } - - /** - * Generates a {@link JoinExpression} according to the {@link JoinType} of the given {@code - * JoinContext}. - */ - private JoinExpression invokeJoinBuilderAccordingTo(@Nonnull JoinType type, - @Nonnull JoinContext ctx) { - switch (type) { - case THETA: - return generateThetaJoin(ctx); - case NATURAL: - return generateNaturalJoin(ctx); - case OUTER: - return generateOuterJoin(ctx); - default: - throw new AssertionError(type); - } - } - - /** - * Creates the {@link ThetaJoinExpression} instance contained in a {@code JoinContext}. This - * method assumes that the provided {@code ctx} indeed contains a theta join. - */ - private ThetaJoinExpression generateThetaJoin(@Nonnull JoinContext ctx) { - ThetajoinContext thetajoinContext = ctx.thetajoin(); - - ClassResource left = ClassResource.fromQualifiedName(thetajoinContext.classres(0).getText()); - ClassResource right = ClassResource.fromQualifiedName(thetajoinContext.classres(1).getText()); - - ThetaJoinBuilder joinBuilder = JoinFactory.createNew() - .theta() - .join(left) - .with(right) - .as(ClassResource.fromQualifiedName(ctx.classres().getText())) - .where(OCLConstraint.of(thetajoinContext.oclcond().getText())); - - ctx.keepaggregatesexpr().stream() - .map(keepStatementVisitor::visitKeepaggregatesexpr) - .forEach(joinBuilder::keep); - ctx.keepattributesexpr().stream() - .map(keepStatementVisitor::visitKeepattributesexpr) - .forEach(joinBuilder::keep); - ctx.keepcalculatedexpr().stream() - .map(keepStatementVisitor::visitKeepcalculatedexpr) - .forEach(joinBuilder::keep); - ctx.keepexpr().stream() - .map(keepStatementVisitor::visitKeepexpr) - .forEach(joinBuilder::keep); - - return joinBuilder.done(); - } - - /** - * Creates the {@link NaturalJoinExpression} instance contained in a {@code JoinContext}. This - * method assumes that the provided {@code ctx} indeed contains a natural join. - */ - private NaturalJoinExpression generateNaturalJoin(@Nonnull JoinContext ctx) { - NaturaljoinContext naturalJoinContext = ctx.naturaljoin(); - - ClassResource left = ClassResource.fromQualifiedName(naturalJoinContext.classres(0).getText()); - ClassResource right = ClassResource.fromQualifiedName(naturalJoinContext.classres(1).getText()); - - NaturalJoinBuilder joinBuilder = JoinFactory.createNew() - .natural() - .join(left) - .with(right) - .as(ClassResource.fromQualifiedName(ctx.classres().getText())); - - ctx.keepaggregatesexpr().stream() - .map(keepStatementVisitor::visitKeepaggregatesexpr) - .forEach(joinBuilder::keep); - ctx.keepattributesexpr().stream() - .map(keepStatementVisitor::visitKeepattributesexpr) - .forEach(joinBuilder::keep); - ctx.keepcalculatedexpr().stream() - .map(keepStatementVisitor::visitKeepcalculatedexpr) - .forEach(joinBuilder::keep); - ctx.keepexpr().stream() - .map(keepStatementVisitor::visitKeepexpr) - .forEach(joinBuilder::keep); - - return joinBuilder.done(); - } - - /** - * Creates the {@link OuterJoinExpression} instance contained in a {@code JoinContext}. This - * method assumes that the provided {@code ctx} indeed contains an outer join. - */ - private OuterJoinExpression generateOuterJoin(@Nonnull JoinContext ctx) { - OuterjoinContext outerJoinContext = ctx.outerjoin(); - - ClassResource left = ClassResource.fromQualifiedName(outerJoinContext.classres(0).getText()); - ClassResource right = ClassResource.fromQualifiedName(outerJoinContext.classres(1).getText()); - - OuterJoinBuilder joinBuilder = JoinFactory.createNew() - .outer() - .join(left) - .with(right) - .as(ClassResource.fromQualifiedName(ctx.classres().getText())); - - if (outerJoinContext.leftouterjoin() != null) { - joinBuilder.leftOuter(); - } else if (outerJoinContext.rightouterjoin() != null) { - joinBuilder.rightOuter(); - } else { - throw new ModelJoinParsingException("Expected either 'left' or 'right' 'outer join'"); - } - - ctx.keepaggregatesexpr().stream() - .map(keepStatementVisitor::visitKeepaggregatesexpr) - .forEach(joinBuilder::keep); - ctx.keepattributesexpr().stream() - .map(keepStatementVisitor::visitKeepattributesexpr) - .forEach(joinBuilder::keep); - ctx.keepcalculatedexpr().stream() - .map(keepStatementVisitor::visitKeepcalculatedexpr) - .forEach(joinBuilder::keep); - ctx.keepexpr().stream() - .map(keepStatementVisitor::visitKeepexpr) - .forEach(joinBuilder::keep); - - return joinBuilder.done(); - } - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/KeepStatementVisitor.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/KeepStatementVisitor.java deleted file mode 100644 index 2e9789d..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/KeepStatementVisitor.java +++ /dev/null @@ -1,307 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.parser.antlr; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import org.rosi_project.model_sync.model_join.representation.core.AttributePath; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.core.OCLStatement; -import org.rosi_project.model_sync.model_join.representation.core.RelativeAttribute; -import org.rosi_project.model_sync.model_join.representation.core.TypedAttributePath; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepAggregateExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepAggregateExpression.AggregationType; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepAttributesExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepCalculatedExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepReferenceExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepSubTypeExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepSuperTypeExpression; -import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinBaseVisitor; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.AttrresContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepaggregatesexprContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepattributesexprContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepcalculatedexprContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepexprContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepincomingexprContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepoutgoingexprContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepsubtypeexprContext; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.KeepsupertypeexprContext; - -/** - * The {@code KeepStatementVisitor} creates {@link KeepExpression} instances from a parsed {@code - * ModelJoin} file. - * - * @author Rico Bergmann - */ -public class KeepStatementVisitor extends ModelJoinBaseVisitor<KeepExpression> { - - /** - * A simple enumeration of the possible keep statements for compound statements as defined in the - * {@code ModelJoin} ANTLR grammar. - */ - private enum KeepExprType { - - /** - * The {@code KEEP_TYPE_EXPR} subsumes both {@code keep subtype} as well as {@code keep - * supertype} expressions. - */ - KEEP_TYPE_EXPR, - - /** - * The {@code KEEP_INCOMING_EXPR} corresponds to a {@code keep incoming reference} statement. - */ - KEEP_INCOMING_EXPR, - - /** - * The {@code KEEP_OUTGOING_EXPR} corresponds to a {@code keep outgoing reference} statement. - */ - KEEP_OUTGOING_EXPR - - } - - @Override - public KeepExpression visitKeepattributesexpr(KeepattributesexprContext ctx) { - return new KeepAttributesExpression( - ctx.attrres().stream() - .map(AttrresContext::getText) - .map(AttributePath::fromQualifiedPath) - .collect(ArrayList::new, ArrayList::add, ArrayList::addAll) - ); - - } - - @Override - public KeepExpression visitKeepaggregatesexpr(KeepaggregatesexprContext ctx) { - String rawAggregationType = ctx.aggrtype().getText(); - AggregationType aggregationType = AggregationType.valueOf(rawAggregationType.toUpperCase()); - - return new KeepAggregateExpression( - aggregationType /* SUM / MAX / MIN etc */, - RelativeAttribute.of(ctx.relattr().getText()) /* the attribute in the target relation */, - AttributePath.fromQualifiedPath(ctx.classres().getText()) /* the source attribute */, - AttributePath.fromQualifiedPath(ctx.attrres().getText()) /* name in the new ModelJoin */ - ); - } - - @Override - public KeepExpression visitKeepcalculatedexpr(KeepcalculatedexprContext ctx) { - OCLStatement oclExpr = OCLStatement.of(ctx.oclcond().getText()); - - return KeepCalculatedExpression // - .keepCalculatedAttribute(oclExpr) // - .as(TypedAttributePath.fromQualifiedTypedPath(ctx.typedattrres().getText()) - ); - } - - @Override - public KeepExpression visitKeepexpr(KeepexprContext ctx) { - KeepExprType keepExprType = determineExpressionTypeFor(ctx); - - switch (keepExprType) { - case KEEP_TYPE_EXPR: - return buildKeepTypeExpressionFor(ctx); - case KEEP_INCOMING_EXPR: - return buildKeepIncomingReferenceExpressionFor(ctx); - case KEEP_OUTGOING_EXPR: - return buildKeepOutgoingReferenceExpressionFor(ctx); - default: - throw new AssertionError(keepExprType); - } - } - - /** - * Checks, which kind of expression is specified in a specific {@code KeepexprContext}. - */ - private KeepExprType determineExpressionTypeFor(KeepexprContext ctx) { - - /* - * From the ANTLR grammar we know that exactly one of the IF cases has to hold - */ - if (ctx.keeptypeexpr() != null) { - return KeepExprType.KEEP_TYPE_EXPR; - } else if (ctx.keepincomingexpr() != null) { - return KeepExprType.KEEP_INCOMING_EXPR; - } else if (ctx.keepoutgoingexpr() != null) { - return KeepExprType.KEEP_OUTGOING_EXPR; - } else { - throw new ModelJoinParsingException( - "Expected either 'keep reference' or 'keep type' expression: " + ctx); - } - } - - /** - * Creates the appropriate {@link KeepExpression} for a {@code KeepexprContext}. - */ - private KeepExpression buildKeepTypeExpressionFor(KeepexprContext ctx) { - if (ctx.keeptypeexpr().keepsubtypeexpr() != null) { - return buildKeepSubtypeExpressionFor(ctx); - } else if (ctx.keeptypeexpr().keepsupertypeexpr() != null) { - return buildKeepSupertypeExpressionFor(ctx); - } else { - throw new ModelJoinParsingException( - "Expected either 'keep supertype' or 'keep subtype' expression: " + ctx); - } - } - - /** - * Creates the {@link KeepReferenceExpression} instance contained in a {@code KeepexprContext}. - * This method assumes that the provided {@code ctx} indeed contains a keep incoming reference - * statement. - */ - private KeepReferenceExpression buildKeepIncomingReferenceExpressionFor(KeepexprContext ctx) { - KeepincomingexprContext incomingCtx = ctx.keepincomingexpr(); - - AttributePath attributeToKeep = AttributePath - .fromQualifiedPath(incomingCtx.attrres().getText()); - - List<KeepExpression> nestedExpressions = ctx.keepattributesexpr().stream() - .map(this::visitKeepattributesexpr) - .collect(Collectors.toList()); - - nestedExpressions.addAll(ctx.keepaggregatesexpr().stream() - .map(this::visitKeepaggregatesexpr) - .collect(Collectors.toList()) - ); - - nestedExpressions.addAll(ctx.keepexpr().stream() - .map(this::visitKeepexpr) - .collect(Collectors.toList()) - ); - - KeepReferenceExpression.KeepReferenceBuilder expressionBuilder = KeepReferenceExpression.keep() - .incoming(attributeToKeep); - - ClassResource targetClass; - if (incomingCtx.classres() != null) { - targetClass = ClassResource.fromQualifiedName(incomingCtx.classres().getText()); - } else { - targetClass = attributeToKeep.getContainingClass(); - } - - expressionBuilder.as(targetClass); - nestedExpressions.forEach(expressionBuilder::keep); - - return expressionBuilder.buildExpression(); - } - - /** - * Creates the {@link KeepReferenceExpression} instance contained in a {@code KeepexprContext}. - * This method assumes that the provided {@code ctx} indeed contains a keep outgoing reference - * statement. - */ - private KeepReferenceExpression buildKeepOutgoingReferenceExpressionFor(KeepexprContext ctx) { - KeepoutgoingexprContext outgoingCtx = ctx.keepoutgoingexpr(); - - AttributePath attributeToKeep = AttributePath - .fromQualifiedPath(outgoingCtx.attrres().getText()); - - List<KeepExpression> nestedExpressions = ctx.keepattributesexpr().stream() - .map(this::visitKeepattributesexpr) - .collect(Collectors.toList()); - - nestedExpressions.addAll(ctx.keepaggregatesexpr().stream() - .map(this::visitKeepaggregatesexpr) - .collect(Collectors.toList()) - ); - - nestedExpressions.addAll(ctx.keepexpr().stream() - .map(this::visitKeepexpr) - .collect(Collectors.toList()) - ); - - KeepReferenceExpression.KeepReferenceBuilder expressionBuilder = KeepReferenceExpression.keep() - .outgoing(attributeToKeep); - - ClassResource targetClass; - if (outgoingCtx.classres() != null) { - targetClass = ClassResource.fromQualifiedName(outgoingCtx.classres().getText()); - } else { - targetClass = attributeToKeep.getContainingClass(); - } - - expressionBuilder.as(targetClass); - nestedExpressions.forEach(expressionBuilder::keep); - - return expressionBuilder.buildExpression(); - } - - /** - * Creates the {@link KeepSubTypeExpression} instance contained in a {@code KeepexprContext}. This - * method assumes that the provided {@code ctx} indeed contains a keep subtype statement. - */ - private KeepSubTypeExpression buildKeepSubtypeExpressionFor(KeepexprContext ctx) { - KeepsubtypeexprContext subtypeCtx = ctx.keeptypeexpr().keepsubtypeexpr(); - - ClassResource typeToKeep = ClassResource.fromQualifiedName(subtypeCtx.classres(0).getText()); - - List<KeepExpression> nestedExpressions = ctx.keepattributesexpr().stream() - .map(this::visitKeepattributesexpr) - .collect(Collectors.toList()); - - nestedExpressions.addAll(ctx.keepaggregatesexpr().stream() - .map(this::visitKeepaggregatesexpr) - .collect(Collectors.toList()) - ); - - nestedExpressions.addAll(ctx.keepexpr().stream() - .map(this::visitKeepexpr) - .collect(Collectors.toList()) - ); - - KeepSubTypeExpression.KeepSubTypeBuilder expressionBuilder = KeepSubTypeExpression.keep() - .subtype(typeToKeep); - - ClassResource targetClass; - if (subtypeCtx.classres() != null) { - targetClass = ClassResource.fromQualifiedName(subtypeCtx.classres(1).getText()); - } else { - targetClass = typeToKeep; - } - - expressionBuilder.as(targetClass); - nestedExpressions.forEach(expressionBuilder::keep); - - return expressionBuilder.buildExpression(); - } - - /** - * Creates the {@link KeepSuperTypeExpression} instance contained in a {@code KeepexprContext}. - * This method assumes that the provided {@code ctx} indeed contains a keep supertype statement. - */ - private KeepSuperTypeExpression buildKeepSupertypeExpressionFor(KeepexprContext ctx) { - KeepsupertypeexprContext supertypeCtx = ctx.keeptypeexpr().keepsupertypeexpr(); - - ClassResource typeToKeep = ClassResource.fromQualifiedName(supertypeCtx.classres(0).getText()); - - List<KeepExpression> nestedExpressions = ctx.keepattributesexpr().stream() - .map(this::visitKeepattributesexpr) - .collect(Collectors.toList()); - - nestedExpressions.addAll(ctx.keepaggregatesexpr().stream() - .map(this::visitKeepaggregatesexpr) - .collect(Collectors.toList()) - ); - - nestedExpressions.addAll(ctx.keepexpr().stream() - .map(this::visitKeepexpr) - .collect(Collectors.toList()) - ); - - KeepSuperTypeExpression.KeepSuperTypeBuilder expressionBuilder = KeepSuperTypeExpression.keep() - .supertype(typeToKeep); - - ClassResource targetClass; - if (supertypeCtx.classres() != null) { - targetClass = ClassResource.fromQualifiedName(supertypeCtx.classres(1).getText()); - } else { - targetClass = typeToKeep; - } - - expressionBuilder.as(targetClass); - nestedExpressions.forEach(expressionBuilder::keep); - - return expressionBuilder.buildExpression(); - } - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/ModelJoinVisitor.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/ModelJoinVisitor.java deleted file mode 100644 index f1883fa..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/antlr/ModelJoinVisitor.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.parser.antlr; - -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinBaseVisitor; -import org.rosi_project.model_sync.model_join.representation.parser.antlr.generated.ModelJoinParser.ModeljoinContext; -import org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder; - -/** - * The {@code ModelJoinVisitor} creates a {@link ModelJoinExpression} instances from a parsed {@code - * ModelJoin} file. - * - * @author Rico Bergmann - */ -public class ModelJoinVisitor extends ModelJoinBaseVisitor<ModelJoinExpression> { - - @Override - public ModelJoinExpression visitModeljoin(ModeljoinContext ctx) { - JoinStatementVisitor joinVisitor = new JoinStatementVisitor(); - ModelJoinBuilder modelJoinBuilder = ModelJoinBuilder.createNewModelJoin(); - - ctx.join().stream() // - .map(joinVisitor::visitJoin) // - .forEach(modelJoinBuilder::add); - - return modelJoinBuilder.build(); - } - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/DefaultModelJoinParser.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/DefaultModelJoinParser.java deleted file mode 100644 index 25f4b9c..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/DefaultModelJoinParser.java +++ /dev/null @@ -1,187 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.parser.legacy; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Optional; -import java.util.regex.Pattern; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; -import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParser; -import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException; -import org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder; - -/** - * The {@code DefaultModelJoinParser} reads a {@code ModelJoin} file from disk and creates matching - * representation for it. - * - * @author Rico Bergmann - */ -@Deprecated -public class DefaultModelJoinParser { - - /** - * Converts the {@code ModelJoin} file into a {@link ModelJoinExpression}, wrapped into an {@code - * Optional}. If parsing fails, an empty {@code Optional} will be returned. - */ - @Nonnull - public static Optional<ModelJoinExpression> read(@Nonnull File modelFile) { - DefaultModelJoinParser parser = new DefaultModelJoinParser(modelFile, ErrorReportingStrategy.OPTIONAL); - return parser.run(); - } - - /** - * Converts the {@code ModelJoin} file into a {@link ModelJoinExpression}. If parsing fails, a - * {@link ModelJoinParsingException} will be thrown. - * - * @throws ModelJoinParsingException if the model may not be parsed for some reason. - */ - @Nonnull - public static ModelJoinExpression readOrThrow(@Nonnull File modelFile) { - DefaultModelJoinParser parser = new DefaultModelJoinParser(modelFile, ErrorReportingStrategy.EXCEPTION); - Optional<ModelJoinExpression> result = parser.run(); - - if (result.isPresent()) { - return result.get(); - } else { - /* - * Theoretically, the parser should throw the exception by itself, so this code should never - * actually run. It is merely here for safety purposes (unchecked access of Optional.get()) - */ - throw new ModelJoinParsingException("Result not present but no exception was thrown either"); - } - } - - /** - * Indicates what should happen if parsing fails. - */ - enum ErrorReportingStrategy { - - /** - * On failure an empty {@code Optional} should be returned. - */ - OPTIONAL, - - /** - * On failure an {@link ModelJoinParsingException} should be thrown. - */ - EXCEPTION - } - - private static final Pattern EMPTY_LINE = Pattern.compile("^\\s*$"); - private static final Pattern IMPORT_STATEMENT = Pattern.compile("^import .*"); - private static final Pattern TARGET_STATEMENT = Pattern.compile("^target .*"); - private static final Pattern JOIN_STATEMENT = Pattern - .compile("^(((left|right) outer)|theta|natural) join .*"); - - @Nonnull - private final File modelFile; - - @Nonnull - private final ErrorReportingStrategy errorReportingStrategy; - - /** - * Full constructor. - * - * @param modelFile the file to parse - * @param errorReportingStrategy what to do in case an error occurs. - */ - private DefaultModelJoinParser(@Nonnull File modelFile, - @Nonnull ErrorReportingStrategy errorReportingStrategy) { - this.modelFile = modelFile; - this.errorReportingStrategy = errorReportingStrategy; - } - - /** - * Creates the {@code ModelJoin} representation from the {@code modelFile}. - * <p> - * Depending on the selected {@code errorReportingStrategy} either an Exception will be thrown, or - * an empty {@code Optional} will be returned if something goes wrong. - */ - private Optional<ModelJoinExpression> run() { - ModelJoinExpression resultingModel; - try (FileInputStream modelInputStream = new FileInputStream(modelFile); - InputStreamReader modelInputReader = new InputStreamReader(modelInputStream); - BufferedReader bufferedModelReader = new BufferedReader(modelInputReader)) { - - ModelJoinBuilder modelJoinBuilder = ModelJoinBuilder.createNewModelJoin(); - readModelFileAndPopulateBuilder(bufferedModelReader, modelJoinBuilder); - resultingModel = modelJoinBuilder.build(); - - } catch (ModelJoinParsingException e) { - switch (errorReportingStrategy) { - case OPTIONAL: - return Optional.empty(); - case EXCEPTION: - throw e; - default: - throw new AssertionError(errorReportingStrategy); - } - } catch (IOException e) { - switch (errorReportingStrategy) { - case OPTIONAL: - return Optional.empty(); - case EXCEPTION: - throw new ModelJoinParsingException(e); - default: - throw new AssertionError(errorReportingStrategy); - } - } - return Optional.of(resultingModel); - } - - /** - * Reads the {@code modelFile} and constructs the corresponding {@code ModelJoin} on the fly. - * <p> - * On error, an {@code IOException} or an {@link ModelJoinParsingException} will be thrown. - * - * @throws ModelJoinParsingException if the model file's content are malformed or another - * component failed - * @throws IOException if the model file might not be read any further - */ - private void readModelFileAndPopulateBuilder(BufferedReader modelReader, - ModelJoinBuilder modelBuilder) throws IOException { - String currentLine; - while ((currentLine = modelReader.readLine()) != null) { - if (lineShouldBeSkipped(currentLine)) { - // the line should be skipped. So we do nothing. - continue; - } else if (lineStartsJoinDeclaration(currentLine)) { - // a new join is being declared. Delegate to the join parser to handle the rest. - JoinParser joinParser = new JoinParser(currentLine, modelReader); - modelBuilder.add(joinParser.run()); - } else { - // we do not know what to do with the current line. Should abort. - throw new ModelJoinParsingException("Unexpected line: '" + currentLine + "'"); - } - } - } - - /** - * Checks, whether the parser should consider the given {@code line} any further, or just ignore - * it. - * <p> - * A line should be skipped, iff. - * <ul> - * <li>It only consists of whitespace characters</li> - * <li>It is an {@code import statement} (as those are not yet considered in the current {@code - * ModelJoin} abstraction)</li> - * <li>It is a {@code target statement} (as those are not yet considered in the current {@code - * ModelJoin} abstraction)</li> - * </ul> - */ - private boolean lineShouldBeSkipped(String line) { - return EMPTY_LINE.matcher(line).matches() // - || IMPORT_STATEMENT.matcher(line).matches() // - || TARGET_STATEMENT.matcher(line).matches(); - } - - /** - * Checks, whether the given {@code line} is the beginning of a {@code join statement}. - */ - private boolean lineStartsJoinDeclaration(String line) { - return JOIN_STATEMENT.matcher(line).matches(); - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/JoinParser.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/JoinParser.java deleted file mode 100644 index ee32b61..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/JoinParser.java +++ /dev/null @@ -1,254 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.parser.legacy; - -import java.io.BufferedReader; -import java.io.IOException; -import java.util.Collection; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.core.OCLConstraint; -import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepExpression; -import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException; -import org.rosi_project.model_sync.model_join.representation.util.JoinFactory; -import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.NaturalJoinBuilder; -import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.OuterJoinBuilder; -import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.ThetaJoinBuilder; - -/** - * The {@code JoinParser} takes care of reading an individual {@code join statement} and creates the - * corresponding {@link JoinExpression}. - * <p> - * This class is primarily intended to be created and invoked by the {@link DefaultModelJoinParser} only as - * will modify the state of that as well. - * - * @author Rico Bergmann - */ -@Deprecated -class JoinParser { - - private static final String START_OF_JOIN_BLOCK_DELIMITER = "{"; - private static final String JOIN_TYPE_THETA = "theta"; - private static final Pattern JOIN_TYPE_DECLARATION = Pattern - .compile(".*(?<type>((?<outertype>(right |left )outer)|theta|natural)) join .*"); - private static final Pattern LEFT_SOURCE_DECLARATION = Pattern - .compile(".*join (?<leftsource>[\\w\\\\.]*) .*"); - private static final Pattern RIGHT_SOURCE_DECLARATION = Pattern - .compile(".*with (?<rightsource>[\\w\\\\.]*) .*"); - private static final Pattern TARGET_DECLARATION = Pattern - .compile(".*as (?<target>[\\w\\\\.]*)( .*|\\{)"); - private static final Pattern THETA_PREDICATE_DECLARATION = Pattern - .compile(".*where (?<predicate>[\\w\\\\.]*)\\{"); - - @Nonnull - private final String startingLine; - - @Nonnull - private final BufferedReader modelReader; - - private boolean hasReadStartOfJoinBlockCharacter = false; - - /** - * Full constructor. - * - * @param startingLine the line that was last read by the {@link DefaultModelJoinParser} and should - * therefore become the starting point for {@code this} parser. - * @param modelReader the reader that provides access to the following lines in the {@code - * ModelJoin} file currently being read. - */ - JoinParser(@Nonnull String startingLine, @Nonnull BufferedReader modelReader) { - this.startingLine = startingLine; - this.modelReader = modelReader; - } - - /** - * Creates the {@link JoinExpression} from the current {@code join statement}. - * <p> - * If something goes wrong, either an {@code IOException} will be thrown directly or a {@link - * ModelJoinParsingException} is used. - */ - @Nonnull - public JoinExpression run() throws IOException { - - // first, we will determine the Join type - - Matcher joinTypeDeclarationMatcher = JOIN_TYPE_DECLARATION.matcher(startingLine); - - if (!joinTypeDeclarationMatcher.matches()) { - throw new ModelJoinParsingException( - "Expected beginning of a Join declaration on '" + startingLine + "'"); - } - - String joinType = joinTypeDeclarationMatcher.group("type"); - String outerJoinType = ""; - - if (joinType.equals("outer")) { - outerJoinType = joinTypeDeclarationMatcher.group("outertype"); - } - - // second, we will try to extract all necessary info from the first line - - String leftSource = null; - String rightSource = null; - String target = null; - String thetaPredicate = null; - - Matcher leftSourceMatcher = LEFT_SOURCE_DECLARATION.matcher(startingLine); - Matcher rightSourceMatcher = RIGHT_SOURCE_DECLARATION.matcher(startingLine); - Matcher targetMatcher = TARGET_DECLARATION.matcher(startingLine); - Matcher thetaPredicateMatcher = THETA_PREDICATE_DECLARATION.matcher(startingLine); - - final int necessaryComponents; - int foundComponents = 0; - - if (leftSourceMatcher.matches()) { - leftSource = leftSourceMatcher.group("leftsource"); - foundComponents++; - } - - if (rightSourceMatcher.matches()) { - rightSource = rightSourceMatcher.group("rightsource"); - foundComponents++; - } - - if (targetMatcher.matches()) { - target = targetMatcher.group("target"); - foundComponents++; - } - - if (joinType.equals(JOIN_TYPE_THETA)) { - necessaryComponents = 4; - if (thetaPredicateMatcher.matches()) { - thetaPredicate = thetaPredicateMatcher.group("predicate"); - foundComponents++; - } - } else { - necessaryComponents = 3; - } - - // in case all information is present on the first line, we are done already - - if (startingLine.contains(START_OF_JOIN_BLOCK_DELIMITER)) { - // TODO could the start character be part of an OCL statement? - hasReadStartOfJoinBlockCharacter = true; - } - - // otherwise, we need to read the following lines as well - - String currentLine = ""; - while (!hasReadStartOfJoinBlockCharacter // - && foundComponents < necessaryComponents // - && (currentLine = modelReader.readLine()) != null) { - - // again, we try to extract as much as possible of the info we need - // however, we now also have to check, whether we have already specified a component, as well - - leftSourceMatcher = LEFT_SOURCE_DECLARATION.matcher(currentLine); - if (leftSource == null && leftSourceMatcher.matches()) { - leftSource = leftSourceMatcher.group("leftsource"); - foundComponents++; - } - - rightSourceMatcher = RIGHT_SOURCE_DECLARATION.matcher(currentLine); - if (rightSource == null && rightSourceMatcher.matches()) { - rightSource = rightSourceMatcher.group("rightsource"); - foundComponents++; - } - - targetMatcher = TARGET_DECLARATION.matcher(currentLine); - if (target == null && targetMatcher.matches()) { - target = targetMatcher.group("target"); - } - - if (joinType.equals(JOIN_TYPE_THETA)) { - thetaPredicateMatcher = THETA_PREDICATE_DECLARATION.matcher(currentLine); - if (thetaPredicate == null && thetaPredicateMatcher.matches()) { - thetaPredicate = thetaPredicateMatcher.group("predicate"); - foundComponents++; - } - } - - if (currentLine.contains(START_OF_JOIN_BLOCK_DELIMITER)) { - hasReadStartOfJoinBlockCharacter = true; - } - } - - // if we found the beginning of the Join body, but did not read all our information, the - // ModelJoin file is flawed - - if (foundComponents < necessaryComponents) { - throw new ModelJoinParsingException( - "ModelJoin grammar violation: found components " + foundComponents + " but expected " - + necessaryComponents); - } - - // otherwise we are ready to go. So we skip forward until the Join body is reached. - - while (!hasReadStartOfJoinBlockCharacter && (currentLine = modelReader.readLine()) != null) { - if (currentLine.contains(START_OF_JOIN_BLOCK_DELIMITER)) { - hasReadStartOfJoinBlockCharacter = true; - } - } - - // if we read everything, but did not find the Join body, the ModelJoin file is flawed again - - if (!hasReadStartOfJoinBlockCharacter) { - throw new ModelJoinParsingException( - "Expected start of join block but could not read any further"); - } - - // if not all components are initialized by now, we are working on a flawed ModelJoin file - - if (currentLine == null || leftSource == null || rightSource == null || target == null) { - throw new ModelJoinParsingException( - "Not all required information was found but could not read any further"); - } - - // at this point the declaration of the join statement is valid - // therefore we want the keep expressions it contains. This is the KeepParser's job. - - KeepParser keepParser = new KeepParser(currentLine, modelReader); - Collection<KeepExpression> keeps = keepParser.run(); - - // finally we have to create the correct JoinExpression - - JoinFactory joinFactory = JoinFactory.createNew(); - switch (joinType) { - case "outer": - OuterJoinBuilder outerJoinBuilder = joinFactory.outer(); - if (outerJoinType.equals("left")) { - outerJoinBuilder.leftOuter(); - } else if (outerJoinType.equals("right")) { - outerJoinBuilder.rightOuter(); - } else { - throw new ModelJoinParsingException("Unknown direction for outer join: " + outerJoinType); - } - outerJoinBuilder // - .join(ClassResource.fromQualifiedName(leftSource)) // - .with(ClassResource.fromQualifiedName(rightSource)) // - .as(ClassResource.fromQualifiedName(target)); - keeps.forEach(outerJoinBuilder::keep); - return outerJoinBuilder.done(); - case "theta": - ThetaJoinBuilder thetaJoinBuilder = joinFactory // - .theta() // - .join(ClassResource.fromQualifiedName(leftSource)) // - .with(ClassResource.fromQualifiedName(rightSource)) // - .as(ClassResource.fromQualifiedName(target)) // - .where(OCLConstraint.of(thetaPredicate)); - keeps.forEach(thetaJoinBuilder::keep); - return thetaJoinBuilder.done(); - case "natural": - NaturalJoinBuilder naturalJoinBuilder = joinFactory // - .natural() // - .join(ClassResource.fromQualifiedName(leftSource)) // - .with(ClassResource.fromQualifiedName(rightSource)) // - .as(ClassResource.fromQualifiedName(target)); - keeps.forEach(naturalJoinBuilder::keep); - return naturalJoinBuilder.done(); - default: - throw new ModelJoinParsingException("Unknown join type: " + joinType); - } - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/KeepParser.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/KeepParser.java deleted file mode 100644 index ac82f38..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/parser/legacy/KeepParser.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.parser.legacy; - -import java.io.BufferedReader; -import java.io.IOException; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.AttributePath; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepAttributesExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepExpression; -import org.rosi_project.model_sync.model_join.representation.parser.ModelJoinParsingException; - -/** - * The {@code KeepParser} takes care of reading the {@code keep statements} and creating the - * corresponding {@link KeepExpression}s for the body of an {@code join statement}. - * <p> - * This class is primarily intended to be created and invoked by the {@link JoinParser} only as will - * modify the state of that as well. - * - * @author Rico Bergmann - */ -@Deprecated -class KeepParser { - - private static final String END_OF_JOIN_BLOCK_DELIMITER = "}"; - private static final Pattern KEEP_ATTRIBUTE_DECLARATION = Pattern - .compile(".*keep attributes\\W*(?<attribute>[\\w\\\\.]*)$"); - - @Nonnull - private final String startingLine; - - @Nonnull - private final BufferedReader modelReader; - - private boolean hasReadEndOfJoinBlockDelimiter = false; - - /** - * Full constructor. - * @param startingLine the line that was last read by the {@link JoinParser} and should - * therefore become the starting point for {@code this} parser. - * @param modelReader the reader that provides access to the following lines in the {@code - * ModelJoin} file currently being read. - */ - KeepParser(@Nonnull String startingLine, @Nonnull BufferedReader modelReader) { - this.startingLine = startingLine; - this.modelReader = modelReader; - } - - /** - * Creates the {@link KeepExpression}s for the current {@code join statement}. - * <p> - * If something goes wrong, either an {@code IOException} will be thrown directly or a {@link - * ModelJoinParsingException} is used. - */ - @Nonnull - public Collection<KeepExpression> run() throws IOException { - List<KeepExpression> detectedKeeps = new LinkedList<>(); - Matcher keepMatcher = KEEP_ATTRIBUTE_DECLARATION.matcher(startingLine); - - parseLine(startingLine, keepMatcher).ifPresent(detectedKeeps::add); - - String currentLine; - while (!hasReadEndOfJoinBlockDelimiter && (currentLine = modelReader.readLine()) != null) { - keepMatcher = KEEP_ATTRIBUTE_DECLARATION.matcher(currentLine); - parseLine(currentLine, keepMatcher).ifPresent(detectedKeeps::add); - } - - return detectedKeeps; - } - - /** - * Tries to create a {@link KeepExpression} for a single {@code keep statement} written on the - * {@code current line}. - * <p> - * If there is no such statement, an empty {@code Optional} will be returned. - * <p> - * If the line indicates the end of the keep-block, the state of {@code this} parser will be - * updated accordingly. - */ - @Nonnull - private Optional<KeepExpression> parseLine(String currentLine, Matcher keepMatcher) { - Optional<KeepExpression> result = Optional.empty(); - if (keepMatcher.matches()) { - AttributePath attribute = AttributePath.fromQualifiedPath(keepMatcher.group("attribute")); - result = Optional.of(KeepAttributesExpression.keepAttributes(attribute)); - } - - if (currentLine.contains(END_OF_JOIN_BLOCK_DELIMITER)) { - hasReadEndOfJoinBlockDelimiter = true; - } - return result; - } - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Assert.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Assert.java deleted file mode 100644 index d72ecca..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Assert.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.util; - -import javax.annotation.Nonnull; - -/** - * Utility class to provide a number of useful assertion mechanisms. - * <p> - * On failure, an {@code AssertionError} with a dedicated message will be thrown. - * - * @author Rico Bergmann - */ -public class Assert { - - /** - * Ensures that an object is not {@code null}. - */ - public static void notNull(Object obj, @Nonnull String failureMessage) { - if (obj == null) { - throw new AssertionError(failureMessage); - } - } - - /** - * Ensures that none of the arguments is {@code null}. - */ - public static void noNullArguments(@Nonnull String failureMessage, Object... arguments) { - if (arguments == null) { - throw new AssertionError("Vararg arguments may not be null"); - } - for (Object arg : arguments) { - if (arg == null) { - throw new AssertionError(failureMessage); - } - } - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Functional.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Functional.java deleted file mode 100644 index 853ee96..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Functional.java +++ /dev/null @@ -1,235 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.util; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.swing.text.html.Option; - -/** - * Contains a number of useful classes to mimic behaviour from functional programming languages in - * Java. - * - * @author Rico Bergmann - */ -public class Functional { - - /** - * Emulates a dispatch on the concrete type of an object. Depending on the type, different control - * paths will be executed. - * - * @param something the object to match on - */ - @Nonnull - public static <R> FunctionalMatch<R> match(@Nonnull Object something) { - return new FunctionalMatch<>(something); - } - - /** - * - * @author Rico Bergmann - * - * @param <R> - */ - public static class FunctionalMatch<R> extends Functional { - - @Nonnull - private final Object matchInstance; - - @Nonnull - private final List<Pair<Class<?>, CaseResult<R>>> functions; - - @Nullable - private CaseResult<R> defaultAction; - - /** - * - * @param matchInstance - */ - private FunctionalMatch(@Nonnull Object matchInstance) { - Assert.notNull(matchInstance, "Object to match on may not be null"); - this.matchInstance = matchInstance; - this.functions = new ArrayList<>(); - } - - /** - * @param clazz - * @param action - * @return - */ - @SuppressWarnings("unchecked") - public <T> FunctionalMatch<R> caseOf(@Nonnull Class<T> clazz, @Nonnull Function<T, R> action) { - Assert.notNull(clazz, "Class to match on may not be null"); - Assert.notNull(action, "Action to perform may not be null"); - functions.add( - Pair.of(clazz, new RunnableCaseResult<>((Function<Object, R>) action, matchInstance))); - return this; - } - - /** - * @param clazz - * @param result - * @return - */ - public <T> FunctionalMatch<R> caseOf(@Nonnull Class<T> clazz, @Nonnull R result) { - Assert.notNull(clazz, "Class to match on may not be null"); - Assert.notNull(result, "Match result may not be null"); - functions.add(Pair.of(clazz, new StaticCaseResult<>(result))); - return this; - } - - /** - * @param action - * @return - */ - public FunctionalMatch<R> defaultCase(@Nonnull Function<? super Object, R> action) { - Assert.notNull(action, "Default action may not be null"); - this.defaultAction = new RunnableCaseResult<>(action, matchInstance); - return this; - } - - /** - * @param result - * @return - */ - public FunctionalMatch<R> defaultCase(R result) { - Assert.notNull(result, "Match result may not be null"); - this.defaultAction = new StaticCaseResult<>(result); - return this; - } - - /** - * Performs the match. - * <p> - * This will check for the first case to which the match object is assignable and execute the - * associated action. - * - * @return the result of the action or {@code null} if no matching case was specified. - */ - public R run() { - try { - R res = runOrThrow(); - return res; - } catch (MatchException e) { - return null; - } - } - - public Optional<R> tryRun() { - try { - R res = runOrThrow(); - return Optional.of(res); - } catch (MatchException e) { - return Optional.empty(); - } - } - - /** - * Attempts to perform the match. - * <p> - * This will check for the first case to which the match object is assignable and execute the - * associated action. If no matching action was specified, an exception will be raised. - * - * @return the result of the action or {@code null} if no matching case was specified. - * @throws MatchException if no matching action was given. - */ - public R runOrThrow() { - for (Pair<Class<?>, CaseResult<R>> caseEntry : functions) { - Class<?> entryClass = caseEntry.getFirst(); - if (entryClass.isAssignableFrom(matchInstance.getClass())) { - return caseEntry.getSecond().calculate(); - } - } - if (defaultAction != null) { - return defaultAction.calculate(); - } - throw new MatchException(matchInstance.getClass(), "No case specified"); - } - - private static abstract class CaseResult<R> { - - abstract R calculate(); - - } - - private static class RunnableCaseResult<R> extends CaseResult<R> { - - private final Function<Object, R> action; - private final Object param; - - /** - * @param action - * @param param - */ - RunnableCaseResult(@Nonnull Function<Object, R> action, @Nonnull Object param) { - Assert.notNull(action, "Action may not be null"); - Assert.notNull(param, "Param may not be null"); - this.action = action; - this.param = param; - } - - /* - * (non-Javadoc) - * - * @see de.naju.adebar.util.Functional.FunctionalMatch.CaseResult#calculate() - */ - @Override - R calculate() { - return action.apply(param); - } - - } - - private static class StaticCaseResult<R> extends CaseResult<R> { - - private final R result; - - /** - * @param result - */ - public StaticCaseResult(R result) { - this.result = result; - } - - /* - * (non-Javadoc) - * - * @see de.naju.adebar.util.Functional.FunctionalMatch.CaseResult#calculate() - */ - @Override - R calculate() { - return result; - } - - } - - } - - public static class MatchException extends RuntimeException { - - private static final long serialVersionUID = -3903882205980399140L; - - private final Class<?> actualClass; - - MatchException(Class<?> actualClass) { - this.actualClass = actualClass; - } - - MatchException(Class<?> actualClass, String message) { - super(message); - this.actualClass = actualClass; - } - - /** - * @return the actualClass - */ - public Class<?> getActualClass() { - return actualClass; - } - - } - - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/JoinFactory.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/JoinFactory.java deleted file mode 100644 index bd87373..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/JoinFactory.java +++ /dev/null @@ -1,302 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.util; - -import java.util.ArrayList; -import java.util.List; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.OCLConstraint; -import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.NaturalJoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.OuterJoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.OuterJoinExpression.JoinDirection; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.grammar.ThetaJoinExpression; - -/** - * The {@code JoinFactory} should be used as the main facility to create new {@link JoinExpression} - * instances. It supports instantiation for all subclasses and provides a fluid and natural - * interface to set them up. - * - * @author Rico Bergmann - */ -public class JoinFactory { - - /** - * Starts the construction process for a new join. - */ - @Nonnull - public static JoinFactory createNew() { - return new JoinFactory(); - } - - private JoinFactory() { - // pass - } - - /** - * Constructs a new {@link OuterJoinExpression outer join} - */ - @Nonnull - public OuterJoinBuilder outer() { - return new OuterJoinBuilder(); - } - - /** - * Constructs a new {@link NaturalJoinExpression natural join}. - */ - @Nonnull - public NaturalJoinBuilder natural() { - return new NaturalJoinBuilder(); - } - - /** - * Constructs a new {@link ThetaJoinExpression theta join}. - */ - @Nonnull - public ThetaJoinBuilder theta() { - return new ThetaJoinBuilder(); - } - - /** - * This is the base for all actual join builders and contains the fields that have to be present - * in each join. Consult the documentation of the {@link JoinExpression} class for details on - * those fields. - * <p> - * Despite all builders working very similarly, they may not be refactored to have more logic - * provided through this class due to limitations of the Java language. - * - * @see JoinExpression - */ - public static abstract class AbstractJoinBuilder { - protected ClassResource left; - protected ClassResource right; - protected ClassResource target; - protected List<KeepExpression> keeps = new ArrayList<>(); - } - - /** - * The {@code OuterJoinBuilder} takes care of setting up new {@link OuterJoinExpression} - * instances. - * - * @see OuterJoinExpression - */ - public static class OuterJoinBuilder extends AbstractJoinBuilder { - - private OuterJoinExpression.JoinDirection direction; - - /** - * Default constructor. - * <p> - * {@code private} to prevent direct instantiation. - */ - private OuterJoinBuilder() { - // pass - } - - /** - * Configures the join to use the right source model as the primary one. - */ - @Nonnull - public OuterJoinBuilder rightOuter() { - direction = JoinDirection.RIGHT; - return this; - } - - /** - * Configures the join to use the left source model as the primary one. - */ - @Nonnull - public OuterJoinBuilder leftOuter() { - direction = JoinDirection.LEFT; - return this; - } - - /** - * Specifies the left source. - */ - @Nonnull - public OuterJoinBuilder join(@Nonnull ClassResource left) { - this.left = left; - return this; - } - - /** - * Specifies the right source. - */ - @Nonnull - public OuterJoinBuilder with(@Nonnull ClassResource right) { - this.right = right; - return this; - } - - /** - * Specifies the name of the resulting class. - */ - @Nonnull - public OuterJoinBuilder as(@Nonnull ClassResource target) { - this.target = target; - return this; - } - - /** - * Specifies a field that should be contained in the resulting view. - */ - @Nonnull - public OuterJoinBuilder keep(@Nonnull KeepExpression keep) { - this.keeps.add(keep); - return this; - } - - /** - * Finishes the construction process and provides the resulting {@code join}. - */ - @Nonnull - public OuterJoinExpression done() { - return new OuterJoinExpression(left, right, target, direction, keeps); - } - } - - /** - * The {@code NaturalJoinBuilder} takes care of setting up new {@link NaturalJoinExpression} - * instances. - * - * @see NaturalJoinExpression - */ - public static class NaturalJoinBuilder extends AbstractJoinBuilder { - - /** - * Default constructor. - * <p> - * {@code private} to prevent direct instantiation. - */ - private NaturalJoinBuilder() { - // pass - } - - /** - * Specifies the left source. - */ - @Nonnull - public NaturalJoinBuilder join(@Nonnull ClassResource left) { - this.left = left; - return this; - } - - /** - * Specifies the right source. - */ - @Nonnull - public NaturalJoinBuilder with(@Nonnull ClassResource right) { - this.right = right; - return this; - } - - /** - * Specifies the name of the resulting class. - */ - @Nonnull - public NaturalJoinBuilder as(@Nonnull ClassResource target) { - this.target = target; - return this; - } - - /** - * Specifies a field that should be contained in the resulting view. - */ - @Nonnull - public NaturalJoinBuilder keep(@Nonnull KeepExpression keep) { - this.keeps.add(keep); - return this; - } - - /** - * Finishes the construction process and provides the resulting {@code join}. - */ - @Nonnull - public NaturalJoinExpression done() { - return new NaturalJoinExpression(left, right, target, keeps); - } - } - - /** - * The {@code ThetaJoinBuilder} takes care of setting up new {@link ThetaJoinExpression} - * instances. - * - * @see ThetaJoinExpression - */ - public static class ThetaJoinBuilder extends AbstractJoinBuilder { - - private OCLConstraint condition; - - /** - * Default constructor. - * <p> - * {@code private} to prevent direct instantiation. - */ - private ThetaJoinBuilder() { - // pass - } - - /** - * Specifies the left source. - */ - @Nonnull - public ThetaJoinBuilder join(@Nonnull ClassResource left) { - this.left = left; - return this; - } - - /** - * Specifies the right source. - */ - @Nonnull - public ThetaJoinBuilder with(@Nonnull ClassResource right) { - this.right = right; - return this; - } - - /** - * Specifies the name of the resulting class. - */ - @Nonnull - public ThetaJoinBuilder as(@Nonnull ClassResource target) { - this.target = target; - return this; - } - - /** - * Specifies the join condition. - */ - @Nonnull - public ThetaJoinBuilder where(@Nonnull OCLConstraint condition) { - this.condition = condition; - return this; - } - - /** - * Specifies the join condition. - */ - @Nonnull - public ThetaJoinBuilder where(@Nonnull String oclCondition) { - return where(OCLConstraint.of(oclCondition)); - } - - /** - * Specifies a field that should be contained in the resulting view. - */ - @Nonnull - public ThetaJoinBuilder keep(@Nonnull KeepExpression keep) { - this.keeps.add(keep); - return this; - } - - /** - * Finishes the construction process and provides the resulting {@code join}. - */ - @Nonnull - public ThetaJoinExpression done() { - return new ThetaJoinExpression(left, right, target, condition, keeps); - } - } - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/ModelJoinBuilder.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/ModelJoinBuilder.java deleted file mode 100644 index c92b525..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/ModelJoinBuilder.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.util; - -import java.util.LinkedList; -import java.util.List; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.core.AttributePath; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepAttributesExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepReferenceExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepReferenceExpression.KeepReferenceBuilder; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepSuperTypeExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepSuperTypeExpression.KeepSuperTypeBuilder; -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; -import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.NaturalJoinBuilder; -import org.rosi_project.model_sync.model_join.representation.util.JoinFactory.ThetaJoinBuilder; - -/** - * The {@code ModelJoinBuilder} provides a nice and fluent way of creating new {@code ModelJoin} - * instances. - * - * @author Rico Bergmann - */ -public class ModelJoinBuilder { - - public static ThetaJoinBuilder thetaJoin() { - return JoinFactory.createNew().theta(); - } - - public static NaturalJoinBuilder naturalJoin() { - return JoinFactory.createNew().natural(); - } - - public static KeepAttributesExpression attributes(AttributePath firstAttribute, AttributePath... moreAttributes) { - return KeepAttributesExpression.keepAttributes(firstAttribute, moreAttributes); - } - - public static KeepReferenceBuilder outgoing(AttributePath attr) { - return KeepReferenceExpression.keep().outgoing(attr); - } - - public static KeepSuperTypeBuilder supertype(ClassResource supertype) { - return KeepSuperTypeExpression.keep().supertype(supertype); - } - - /** - * Starts the construction process for a new {@link ModelJoinExpression}. - */ - @Nonnull - public static ModelJoinBuilder createNewModelJoin() { - return new ModelJoinBuilder(); - } - - private List<JoinExpression> joinBuffer = new LinkedList<>(); - - /** - * Full/default constructor. - */ - private ModelJoinBuilder() { - // pass - } - - /** - * Extends the current {@code ModelJoin} by another join. - */ - @Nonnull - public ModelJoinBuilder add(@Nonnull JoinExpression join) { - joinBuffer.add(join); - return this; - } - - /** - * Finishes the construction process and provides the resulting {@code ModelJoin}. - */ - @Nonnull - public ModelJoinExpression build() { - return new ModelJoinExpression(joinBuffer); - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Nothing.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Nothing.java deleted file mode 100644 index 6f4ddf4..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Nothing.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.util; - -public final class Nothing { - - public static Nothing __() { - return new Nothing(); - } - - private Nothing() {}; - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Pair.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Pair.java deleted file mode 100644 index 8cfb469..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/util/Pair.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.util; - -import java.util.Objects; - -public class Pair<F, S> { - - public static <F, S> Pair<F, S> of(F first, S second) { - return new Pair<F, S>(first, second); - } - - private final F first; - private final S second; - - public Pair(F first, S second) { - this.first = first; - this.second = second; - } - - public F getFirst() { - return first; - } - - public S getSecond() { - return second; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof Pair)) { - return false; - } - Pair<?, ?> pair = (Pair<?, ?>) o; - return Objects.equals(first, pair.first) && - Objects.equals(second, pair.second); - } - - @Override - public int hashCode() { - return Objects.hash(first, second); - } - - public String toString() { - return "(" + first + ", " + second + ")"; - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriter.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriter.java deleted file mode 100644 index e9cc804..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriter.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.writer; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardOpenOption; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; - -/** - * The {@code FileBasedModelJoinWriter} outputs a {@link ModelJoinExpression model join description} - * onto the File System. - * - * @author Rico Bergmann - */ -public class FileBasedModelJoinWriter implements ModelJoinWritingService<Boolean> { - - private final File outputFile; - private final StringBasedModelJoinWriter toStringWriter; - - /** - * Full constructor. - * - * @param outputFile the file to write to - */ - public FileBasedModelJoinWriter(@Nonnull File outputFile) { - this.outputFile = outputFile; - this.toStringWriter = StringBasedModelJoinWriter.withNewlines(); - } - - /** - * Writes the given description to the {@code outputFile}. - * - * @return whether the file was successfully written - */ - @Override - public Boolean write(@Nonnull ModelJoinExpression modelJoin) { - try (BufferedWriter writer = Files.newBufferedWriter( - outputFile.toPath(), - StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) { - - String modelJoinTextRepresentation = toStringWriter.write(modelJoin); - writer.write(modelJoinTextRepresentation); - - return true; - } catch (IOException ioe) { - return false; - } - } -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWriter.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWriter.java deleted file mode 100644 index 96d3434..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWriter.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.writer; - -import java.io.File; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; - -/** - * The {@code ModelJoinWriter} acts as an entry point to write and or transform {@link - * ModelJoinExpression model join descriptions} to various representations. - * - * @author Rico Bergmann - */ -public class ModelJoinWriter { - - private static final StringBasedModelJoinWriter stringWriter = StringBasedModelJoinWriter - .createDefault(); - - /** - * Converts a whole model join description to a single {@code String}. - * <p> - * This {@code String} is primarily intended to be human-readable and does not focus in being easy - * to reuse for further purposes. - */ - public static String writeToString(@Nonnull ModelJoinExpression modelJoin) { - return stringWriter.write(modelJoin); - } - - /** - * Outputs a whole model join description to a single file. - * <p> - * The resulting file is intended to be both human-readable as well as to be parsed by further - * applications. - * - * @return whether the expression was written successfully. - */ - public static boolean writeToFile( - @Nonnull File outputFile, - @Nonnull ModelJoinExpression modelJoin) { - return new FileBasedModelJoinWriter(outputFile).write(modelJoin); - } - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWritingService.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWritingService.java deleted file mode 100644 index 4f89772..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/ModelJoinWritingService.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.writer; - -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; - -/** - * A {@code ModelJoinWritingService} transforms a {@link ModelJoinExpression model join description} - * into some different representation. - * - * @author Rico Bergmann - */ -public interface ModelJoinWritingService<T> { - - /** - * Performs the transformation. The result of this method depends on the actual details of the - * writing service and should be documented there. - */ - T write(@Nonnull ModelJoinExpression modelJoin); - -} diff --git a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriter.java b/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriter.java deleted file mode 100644 index 8281979..0000000 --- a/src/main/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriter.java +++ /dev/null @@ -1,160 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.writer; - -import java.util.StringJoiner; -import javax.annotation.Nonnull; -import org.rosi_project.model_sync.model_join.representation.grammar.CompoundKeepExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.JoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepAggregateExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepAttributesExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepCalculatedExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepReferenceExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepSubTypeExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.KeepSuperTypeExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.NaturalJoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.OuterJoinExpression; -import org.rosi_project.model_sync.model_join.representation.grammar.ThetaJoinExpression; -import org.rosi_project.model_sync.model_join.representation.util.Functional; -import org.rosi_project.model_sync.model_join.representation.util.Nothing; - -/** - * The {@code StringBasedModelJoinWriter} transforms a {@link ModelJoinExpression model join description} - * to a single {@code String}. - * - * @author Rico Bergmann - */ -class StringBasedModelJoinWriter implements ModelJoinWritingService<String> { - - private static final String NEWLINE_DELIM = "\n"; - private static final String EMPTY_DELIM = " "; - private static final String DEFAULT_INDENTATION = " "; - - static StringBasedModelJoinWriter createDefault() { - return new StringBasedModelJoinWriter(false); - } - - static StringBasedModelJoinWriter withNewlines() { - return new StringBasedModelJoinWriter(true); - } - - private final String delimiter; - private final boolean useNewlineDelimiters; - - private String currentIndentation = ""; - - private StringBasedModelJoinWriter(boolean useNewlinesDelimiters) { - if (useNewlinesDelimiters) { - this.delimiter = NEWLINE_DELIM; - } else { - this.delimiter = EMPTY_DELIM; - } - this.useNewlineDelimiters = useNewlinesDelimiters; - } - - @Override - public String write(@Nonnull ModelJoinExpression modelJoin) { - StringJoiner joiner = new StringJoiner(delimiter + delimiter); - - modelJoin.getJoins().forEach( - joinStatement -> joiner.merge(writeJoin(joinStatement)) - ); - - return joiner.toString(); - } - - private StringJoiner writeJoin(@Nonnull JoinExpression join) { - StringJoiner joiner = new StringJoiner(" "); - - String joinHeader = Functional.<String>match(join) - .caseOf(ThetaJoinExpression.class, "theta join") - .caseOf(NaturalJoinExpression.class, "natural join") - .caseOf(OuterJoinExpression.class, outerJoin -> { - switch (outerJoin.getDirection()) { - case LEFT: - return "left outer join"; - case RIGHT: - return "right outer join"; - default: - throw new AssertionError(outerJoin.getDirection()); - } - }) - .runOrThrow(); - joiner.add(String.format(currentIndentation + "%s %s with %s as %s", joinHeader, join.getLeft(), join.getRight(), join.getTarget())); - Functional.<Nothing>match(join) - .caseOf(ThetaJoinExpression.class, thetaJoin -> { - joiner.add("where").add(thetaJoin.getCondition().toString()); - return Nothing.__(); - }) - .defaultCase(Nothing.__()) - .runOrThrow(); - - joiner.add("{\n"); - increaseIndentationIfNecessary(); - join.getKeeps().forEach(keep -> joiner.add(currentIndentation + writeKeep(keep) + delimiter)); - decreaseIndentationIfNecessary(); - joiner.add(currentIndentation + "}"); - - return joiner; - } - - private String writeKeep(KeepExpression keep) { - - return Functional.<String>match(keep) - .caseOf(KeepAttributesExpression.class, keepAttributes -> { - StringJoiner attributesJoiner = new StringJoiner(", "); - keepAttributes.getAttributes().forEach(attr -> attributesJoiner.add(attr.toString())); - return "keep attributes " + attributesJoiner; - }) - .caseOf(KeepCalculatedExpression.class, keepCalculated -> - "keep calculated attribute " - + keepCalculated.getCalculationRule() - + " as " + keepCalculated.getTarget()) - .caseOf(KeepAggregateExpression.class, keepAggregate -> - String.format("keep aggregate %s(%s) over %s as %s", - keepAggregate.getAggregation().name().toLowerCase(), - keepAggregate.getAggregatedAttribute(), - keepAggregate.getSource(), keepAggregate.getTarget()) - ) - .caseOf(KeepReferenceExpression.class, keepRef -> { - String header = String.format("keep %s %s as type %s {" + delimiter, keepRef.getReferenceDirection().name().toLowerCase(), keepRef.getAttribute(), keepRef.getTarget()); - return writeCompound(keepRef, header); - }) - .caseOf(KeepSubTypeExpression.class, keepSubtype -> { - String header = String.format("keep subtype %s as type %s {" + delimiter, keepSubtype.getType(), keepSubtype.getTarget()); - return writeCompound(keepSubtype, header); - }) - .caseOf(KeepSuperTypeExpression.class, keepSupertype -> { - String header = String.format("keep supertype %s as type %s {" + delimiter, keepSupertype.getType(), keepSupertype.getTarget()); - return writeCompound(keepSupertype, header); - }) - .runOrThrow(); - - } - - private String writeCompound(CompoundKeepExpression compoundKeep, String header) { - StringJoiner refJoiner = new StringJoiner(" "); - - refJoiner.add(header); - increaseIndentationIfNecessary(); - compoundKeep.getKeeps().forEach(keep -> refJoiner.add(currentIndentation + writeKeep(keep) + delimiter)); - decreaseIndentationIfNecessary(); - refJoiner.add(currentIndentation + "}"); - - return refJoiner.toString(); - } - - private void increaseIndentationIfNecessary() { - if (useNewlineDelimiters) { - currentIndentation += DEFAULT_INDENTATION; - } - } - - private void decreaseIndentationIfNecessary() { - if (useNewlineDelimiters) { - int deletionIdx = currentIndentation.lastIndexOf(DEFAULT_INDENTATION); - currentIndentation = currentIndentation.substring(0, deletionIdx); - } - } - -} diff --git a/src/main/java/org/rosi_project/model_sync/modelrepresentation/ModelJoinCreation.java b/src/main/java/org/rosi_project/model_sync/modelrepresentation/ModelJoinCreation.java deleted file mode 100644 index 44fa819..0000000 --- a/src/main/java/org/rosi_project/model_sync/modelrepresentation/ModelJoinCreation.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.rosi_project.model_sync.modelrepresentation; - -import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.attributes; -import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.outgoing; -import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.supertype; -import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.thetaJoin; -import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.naturalJoin; - -import java.io.File; - -import org.rosi_project.model_sync.model_join.representation.core.AttributePath; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; -import org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder; -import org.rosi_project.model_sync.model_join.representation.writer.*; - -public class ModelJoinCreation { - - public static void main(String[] args) { - /*ClassResource person = ClassResource.fromQualifiedName("contact.Person"); - ClassResource employee = ClassResource.fromQualifiedName("company.Employee"); - AttributePath dateOfBirth = AttributePath.from(person, "dateOfBirth"); - - ModelJoinExpression mj = ModelJoinBuilder.createNewModelJoin() - .add(JoinFactory.createNew() - .natural() - .join(person) - .with(employee) - .as(ClassResource.fromQualifiedName("unified.Person")) - .keep(KeepAttributesExpression - .keepAttributes(dateOfBirth)) - .done() - ).build(); - System.out.println(mj); - for (JoinExpression j: mj.getJoins()) { - System.out.println(j); - for (KeepExpression k: j.getKeeps()) { - System.out.println(k); - } - }*/ - - ClassResource library = ClassResource.from("lib", "Library"); - ClassResource employee = ClassResource.from("lib", "Employee"); - ClassResource person = ClassResource.from("lib", "Person"); - - //ClassResource jointargetMovie = ClassResource.from("jointarget", "Movie"); - //ClassResource jointargetVote = ClassResource.from("jointarget", "Vote"); - //ClassResource jointargetMediaItem = ClassResource.from("jointarget", "MediaItem"); - - AttributePath libraryName = AttributePath.from(library, "name"); - AttributePath libraryEmployees = AttributePath.from(library, "employees"); - AttributePath employeeSalary = AttributePath.from(employee, "salary"); - AttributePath employeeManager = AttributePath.from(employee, "manager"); - AttributePath personName = AttributePath.from(person, "name"); - - ModelJoinExpression mjManager = ModelJoinBuilder.createNewModelJoin() - .add(naturalJoin() - .join(employee) - .with(employee) - .as(employee) - .keep(attributes(employeeSalary)) - .keep(outgoing(employeeManager) - .as(employee) - .buildExpression() - ) - .keep(supertype(person) - .as(person) - .keep(attributes(personName)) - .buildExpression() - ) - .done()) - .build(); - - ModelJoinExpression mjComplete = ModelJoinBuilder.createNewModelJoin() - .add(naturalJoin() - .join(library) - .with(library) - .as(library) - .keep(attributes(libraryName)) - .keep(outgoing(libraryEmployees) - .as(employee) - .keep(attributes(employeeSalary)) - .keep(outgoing(employeeManager) - .as(employee) - .buildExpression() - ) - .keep(supertype(person) - .as(person) - .keep(attributes(personName)) - .buildExpression() - ) - .buildExpression() - ) - .done()) - .build(); - - ModelJoinExpression mjSimple = ModelJoinBuilder.createNewModelJoin() - .add(naturalJoin() - .join(library) - .with(library) - .as(library) - .keep(attributes(libraryName)) - .keep(outgoing(libraryEmployees) - .as(employee) - .keep(attributes(employeeSalary)) - .keep(supertype(person) - .as(person) - .keep(attributes(personName)) - .buildExpression() - ) - .buildExpression() - ) - .done()) - .build(); - - File fileComplete = new File("libraryComplete.modeljoin"); - File fileSimple = new File("librarySimple.modeljoin"); - File fileManager = new File("manager.modeljoin"); - //registerCreatedFile(outputFile); - - FileBasedModelJoinWriter writerComplete = new FileBasedModelJoinWriter(fileComplete); - writerComplete.write(mjComplete); - - FileBasedModelJoinWriter writerSimple = new FileBasedModelJoinWriter(fileSimple); - writerSimple.write(mjSimple); - - FileBasedModelJoinWriter writerManager = new FileBasedModelJoinWriter(fileManager); - writerManager.write(mjManager); - } - -} diff --git a/src/main/scala/org/rosi_project/model_sync/generator/sync/PredefRsumTypes.scala b/src/main/scala/org/rosi_project/model_sync/generator/sync/PredefRsumTypes.scala index 994c2f6..c37d1df 100644 --- a/src/main/scala/org/rosi_project/model_sync/generator/sync/PredefRsumTypes.scala +++ b/src/main/scala/org/rosi_project/model_sync/generator/sync/PredefRsumTypes.scala @@ -37,10 +37,10 @@ object PredefRsumTypes { private val QUERY_HELPER_CLASS = classOf[QueryHelper] val QUERY_HELPER_STYPE = SType(QUERY_HELPER_CLASS.getSimpleName, QUERY_HELPER_CLASS.getPackage.getName) - private val IQUERY_VIEW_COMPARTMENT_CLASS = classOf[IQueryViewCompartment] + private val IQUERY_VIEW_COMPARTMENT_CLASS = classOf[QueryFactory] val IQUERY_VIEW_COMPARTMENT_STYPE = SType(IQUERY_VIEW_COMPARTMENT_CLASS.getSimpleName, IQUERY_VIEW_COMPARTMENT_CLASS.getPackage.getName) - private val AQUERY_VIEW_ROLE_CLASS = classOf[IQueryViewCompartment#AQueryViewRole] + private val AQUERY_VIEW_ROLE_CLASS = classOf[QueryFactory#QueryFactoryElement] val AQUERY_VIEW_ROLE_STYPE = SType(AQUERY_VIEW_ROLE_CLASS.getSimpleName) //, AQUERY_VIEW_ROLE_CLASS.getPackage.getName) //RELATIONAL COMPARTMENT TYPES diff --git a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriterAcceptanceTests.java b/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriterAcceptanceTests.java deleted file mode 100644 index 1155563..0000000 --- a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/FileBasedModelJoinWriterAcceptanceTests.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.writer; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; -import java.util.stream.Collectors; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.rosi_project.model_sync.model_join.representation.writer.TestedModels.Listing2; - -class FileBasedModelJoinWriterAcceptanceTests { - - private static final Logger log = Logger.getLogger(FileBasedModelJoinWriterAcceptanceTests.class.getSimpleName()); - - private List<File> createdFiles = new ArrayList<>(); - - @AfterEach - void tearDown() { - createdFiles.forEach(file -> { - boolean result = file.delete(); - log.info(String.format("Deleting file %s, successfull=%s", file, result)); - }); - createdFiles.clear(); - } - - /** - * Depends on {@link StringBasedModelJoinWriterAcceptanceTests#writeProducesListing2FromTechnicalReport()} - */ - @Test - void writeProducesListing2FromTechnicalReport() { - File outputFile = new File("listing2.modeljoin"); - registerCreatedFile(outputFile); - - FileBasedModelJoinWriter writer = new FileBasedModelJoinWriter(outputFile); - writer.write(Listing2.asModelJoin); - - logFileContent(outputFile); - - String expectedContent = StringBasedModelJoinWriter.withNewlines().write(Listing2.asModelJoin); - assertThat(outputFile).exists(); - assertThat(outputFile).hasContent(expectedContent); - } - - private void registerCreatedFile(File newFile) { - createdFiles.add(newFile); - log.info(String.format("Created new file %s", newFile)); - } - - private void logFileContent(File file) { - try { - String contents = Files.lines(file.toPath()).collect(Collectors.joining()); - log.info(String.format("Content of file %s:", file)); - log.info(contents); - } catch (IOException e) { - log.severe(String.format("Could not read file %s", file)); - } - } - -} diff --git a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriterAcceptanceTests.java b/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriterAcceptanceTests.java deleted file mode 100644 index 716d8d5..0000000 --- a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/StringBasedModelJoinWriterAcceptanceTests.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.writer; - -import static org.assertj.core.api.Assertions.*; - -import java.util.logging.Logger; -import org.junit.jupiter.api.Test; -import org.junit.platform.runner.JUnitPlatform; -import org.junit.runner.RunWith; -import org.rosi_project.model_sync.model_join.representation.writer.TestedModels.Listing2; - -class StringBasedModelJoinWriterAcceptanceTests { - - private static final Logger log = Logger.getLogger(StringBasedModelJoinWriterAcceptanceTests.class.getSimpleName()); - - /** - * @see TestedModels - */ - @Test - void writeProducesListing2FromTechnicalReport() { - StringBasedModelJoinWriter writer = StringBasedModelJoinWriter.withNewlines(); - String writerOutput = writer.write(Listing2.asModelJoin); - - log.info("Writer output:"); - log.info(writerOutput); - - String sanitizedWriterOutput = sanitize(writerOutput); - - String expectedOutput = sanitize(Listing2.asString); - - // Although AssertJ provides an isEqualToIgnoringWhitespace as well as an - // isEqualToIgnoringNewline method, there's none that ignores both. Thus we reside to manual - // sanitization - assertThat(sanitizedWriterOutput).isEqualTo(expectedOutput); - } - - private String sanitize(String rawModelJoin) { - return rawModelJoin.replaceAll("\\s", ""); - } -} diff --git a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/TestedModels.java b/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/TestedModels.java deleted file mode 100644 index 12ab7c1..0000000 --- a/src/test/java/org/rosi_project/model_sync/model_join/representation/writer/TestedModels.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.rosi_project.model_sync.model_join.representation.writer; - -import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.attributes; -import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.outgoing; -import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.supertype; -import static org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder.thetaJoin; - -import org.rosi_project.model_sync.model_join.representation.core.AttributePath; -import org.rosi_project.model_sync.model_join.representation.core.ClassResource; -import org.rosi_project.model_sync.model_join.representation.grammar.ModelJoinExpression; -import org.rosi_project.model_sync.model_join.representation.util.ModelJoinBuilder; - -class TestedModels { - - /* - * The technical report which forms the basis of the tests here is - * - * Burger, E. et Al.: "ModelJoin - A Textual Domain-Specific Language for the Combination of - * Heterogeneous Models"; Karslruhe Institute of Technololgy 2014 - */ - - static class Listing2 { - static final ClassResource imdbFilm = ClassResource.from("imdb", "Film"); - static final ClassResource libraryVideoCassette = ClassResource.from("library", "VideoCassette"); - static final ClassResource libraryAudioVisualItem = ClassResource.from("library", "AudioVisualItem"); - static final ClassResource jointargetMovie = ClassResource.from("jointarget", "Movie"); - static final ClassResource jointargetVote = ClassResource.from("jointarget", "Vote"); - static final ClassResource jointargetMediaItem = ClassResource.from("jointarget", "MediaItem"); - - static final AttributePath imdbFilmYear = AttributePath.from(imdbFilm, "year"); - static final AttributePath imdbFilmVotes = AttributePath.from(imdbFilm, "votes"); - static final AttributePath imdbVoteScore = AttributePath.from("imdb.Vote", "score"); - static final AttributePath libraryAudioVisualItemMinutesLength = AttributePath.from(libraryAudioVisualItem, "minutesLength"); - - static final ModelJoinExpression asModelJoin = ModelJoinBuilder.createNewModelJoin() - .add(thetaJoin() - .join(imdbFilm) - .with(libraryVideoCassette) - .as(jointargetMovie) - .where( - "library.VideoCassette.cast->forAll (p | imdb.Film.figures->playedBy->exists (a | p.firstname.concat(\" \") .concat(p.lastName) == a.name))") - .keep(attributes(imdbFilmYear)) - .keep(outgoing(imdbFilmVotes) - .as(jointargetVote) - .keep(attributes(imdbVoteScore)) - .buildExpression() - ) - .keep(supertype(libraryAudioVisualItem) - .as(jointargetMediaItem) - .keep(attributes(libraryAudioVisualItemMinutesLength)) - .buildExpression() - ) - .done()) - .build(); - - static final String asString = "theta join imdb.Film with library.VideoCassette as jointarget.Movie\n" - + "where library.VideoCassette.cast->forAll (p | imdb.Film.figures->playedBy->exists (a | p.\n" - + "firstname.concat(\" \") .concat(p.lastName) == a.name)) {\n" - + " keep attributes imdb.Film.year\n" - + " keep outgoing imdb.Film.votes as type jointarget.Vote {\n" - + " keep attributes imdb.Vote.score\n" - + "}\n" - + "keep supertype library.AudioVisualItem as type jointarget.MediaItem {\n" - + " keep attributes library.AudioVisualItem.minutesLength\n" - + "}\n" - + "}"; - } - -} -- GitLab