Skip to content

Commit 38a26f2

Browse files
author
Bob Garner
committed
Added support for relationship fields.
1 parent 3e2bffc commit 38a26f2

File tree

5 files changed

+184
-40
lines changed

5 files changed

+184
-40
lines changed

src/main/antlr4/org/entityc/compiler/EntityLanguage.g4

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,32 @@ domainAttributeBody
898898
)*
899899
;
900900

901+
/*
902+
These are attributes of the "to" entity of a relationship. This allows
903+
tagging of attributes with respect to its "path" from a relationship.
904+
*/
905+
domainRelationshipAttributes
906+
: ATTRIBUTES '{' domainRelationshipAttributesBody '}'
907+
;
908+
909+
domainRelationshipAttributesBody
910+
:
911+
( tagStatement
912+
| domainRelationshipAttribute
913+
)*
914+
;
915+
916+
domainRelationshipAttribute
917+
: id '{' domainRelationshipAttributeBody '}'
918+
;
919+
920+
domainRelationshipAttributeBody
921+
:
922+
( descriptionStatement
923+
| tagStatement
924+
)*
925+
;
926+
901927
domainRelationships
902928
: RELATIONSHIPS '{' domainRelationshipsBody '}'
903929
;
@@ -917,6 +943,7 @@ domainRelationshipBody
917943
:
918944
( descriptionStatement
919945
| tagStatement
946+
| domainRelationshipAttributes
920947
)*
921948
;
922949

src/main/java/org/entityc/compiler/ASTVisitor.java

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,7 @@
2222
import org.entityc.compiler.model.config.MTSpaceInclude;
2323
import org.entityc.compiler.model.config.MTTemplate;
2424
import org.entityc.compiler.model.config.MTTransform;
25-
import org.entityc.compiler.model.domain.MTDApplyTemplate;
26-
import org.entityc.compiler.model.domain.MTDEAttribute;
27-
import org.entityc.compiler.model.domain.MTDEAttributeBitField;
28-
import org.entityc.compiler.model.domain.MTDEInterface;
29-
import org.entityc.compiler.model.domain.MTDEInterfaceOperation;
30-
import org.entityc.compiler.model.domain.MTDEInterfaceOperationConfig;
31-
import org.entityc.compiler.model.domain.MTDERelationship;
32-
import org.entityc.compiler.model.domain.MTDEntity;
33-
import org.entityc.compiler.model.domain.MTDEnum;
34-
import org.entityc.compiler.model.domain.MTDEnumItem;
35-
import org.entityc.compiler.model.domain.MTDModule;
36-
import org.entityc.compiler.model.domain.MTDView;
37-
import org.entityc.compiler.model.domain.MTDomain;
38-
import org.entityc.compiler.model.domain.MTNaming;
39-
import org.entityc.compiler.model.domain.MTNamingMethod;
25+
import org.entityc.compiler.model.domain.*;
4026
import org.entityc.compiler.model.entity.HalfRelationshipPlurality;
4127
import org.entityc.compiler.model.entity.MTAttribute;
4228
import org.entityc.compiler.model.entity.MTAttributeConstraint;
@@ -105,6 +91,7 @@ public class ASTVisitor extends EntityLanguageBaseVisitor {
10591
private MTAttribute currentAttribute;
10692
private MTDModule currentDomainModule;
10793
private MTDEntity currentDomainEntity;
94+
private MTDERelationship currentDomainRelationship;
10895
private MTDEnum currentDomainEnum;
10996
private MTLanguage currentLanguage;
11097
private MTConfiguration currentConfiguration;
@@ -1990,8 +1977,24 @@ public Object visitDomainRelationship(EntityLanguageParser.DomainRelationshipCon
19901977
domainEntityRelationship.addTagsWithValues(tagStringsFromTagStatements(bodyContext.tagStatement()));
19911978
}
19921979
}
1980+
this.currentDomainRelationship = domainEntityRelationship;
19931981
}
1994-
return null;
1982+
Object object = super.visitDomainRelationship(ctx);
1983+
1984+
this.currentDomainRelationship = null;
1985+
1986+
return object;
1987+
}
1988+
1989+
@Override
1990+
public Object visitDomainRelationshipAttribute(EntityLanguageParser.DomainRelationshipAttributeContext ctx) {
1991+
String attributeName = ctx.id().getText();
1992+
1993+
MTDERelationshipField relationshipField = new MTDERelationshipField(ctx, currentDomainRelationship, attributeName);
1994+
currentDomainRelationship.addField(relationshipField);
1995+
Object object = super.visitDomainRelationshipAttribute(ctx);
1996+
1997+
return object;
19951998
}
19961999

19972000
@Override

src/main/java/org/entityc/compiler/EntityCompiler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@
5252

5353
public class EntityCompiler {
5454

55-
public static final String COMPILER_VERSION = "0.17.0";
56-
public static final String LANGUAGE_VERSION = "0.14.0";
55+
public static final String COMPILER_VERSION = "0.18.0";
56+
public static final String LANGUAGE_VERSION = "0.15.0";
5757
private static final Map<String, String> defineValues = new HashMap<>();
5858
private static final Set<String> templateSearchPath = new HashSet<>();
5959
private static CommandLine commandLine;

src/main/java/org/entityc/compiler/model/domain/MTDERelationship.java

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,36 @@
1818
import org.entityc.compiler.model.entity.MTRelationship;
1919
import org.entityc.compiler.model.visitor.MTVisitor;
2020

21+
import java.util.ArrayList;
22+
import java.util.Collection;
23+
import java.util.List;
24+
2125
@ModelClass(type = ModelClassType.DOMAIN,
2226
description = "Represents a relationship in your model in the context of a domain.")
2327
public class MTDERelationship extends MTNode implements MTNamed, MTDomainBased, MTReferenceResolution {
2428

25-
private final String relationshipName;
26-
private MTDomain domain;
27-
private MTDEntity domainEntity;
28-
private MTRelationship relationship;
29-
private String explicitName;
30-
private String withViewName; // to-entity should map to a specific view
31-
private boolean withPrimaryKey; // to-entity should map as its primary key only
32-
private MTDERelationshipHalf to;
33-
private boolean resolvedReferences = false;
29+
private final String relationshipName;
30+
private MTDomain domain;
31+
private MTDEntity domainEntity;
32+
private MTRelationship relationship;
33+
private String explicitName;
34+
private String withViewName; // to-entity should map to a specific view
35+
private boolean withPrimaryKey; // to-entity should map as its primary key only
36+
private MTDERelationshipHalf to;
37+
private boolean resolvedReferences = false;
38+
private List<MTDERelationshipField> fields;
3439

3540
public MTDERelationship(ParserRuleContext ctx, MTDEntity domainEntity, String relationshipName) {
3641
super(ctx);
37-
this.domain = domainEntity.getDomain();
38-
this.domainEntity = domainEntity;
42+
this.domain = domainEntity.getDomain();
43+
this.domainEntity = domainEntity;
3944
this.relationshipName = relationshipName;
4045
}
4146

4247
public MTDERelationship(ParserRuleContext ctx, MTDomain domain, MTRelationship relationship) {
4348
super(ctx);
44-
this.domain = domain;
45-
this.relationship = relationship;
49+
this.domain = domain;
50+
this.relationship = relationship;
4651
this.relationshipName = relationship.getName();
4752
}
4853

@@ -77,7 +82,7 @@ public void setWithViewName(String withViewName) {
7782
@ModelMethod(category = ModelMethodCategory.RELATIONSHIP,
7883
description =
7984
"If this relationship was explicitly renamed within its domain, it will return that name. Otherwise "
80-
+ "it will return `null`.")
85+
+ "it will return `null`.")
8186
public String getExplicitName() {
8287
return explicitName;
8388
}
@@ -108,6 +113,22 @@ public boolean isManyToMany() {
108113
return relationship != null && relationship.isManyToMany();
109114
}
110115

116+
public void addField(MTDERelationshipField field) {
117+
if (this.fields == null) {
118+
this.fields = new ArrayList<>();
119+
}
120+
this.fields.add(field);
121+
}
122+
123+
public boolean hasFields() {
124+
return this.fields != null && this.fields.size() > 0;
125+
}
126+
@ModelMethod(category = ModelMethodCategory.RELATIONSHIP,
127+
description = "Returns all the declared fields of this relationship.")
128+
public Collection<MTDERelationshipField> getFields() {
129+
return this.fields;
130+
}
131+
111132
@Override
112133
public boolean resolveReferences(MTSpace space, int pass) {
113134
if (domain != null && domain.isSpecialized()) {
@@ -126,12 +147,19 @@ public boolean resolveReferences(MTSpace space, int pass) {
126147
}
127148
if (relationship != null && to == null) {
128149
to = new MTDERelationshipHalf(relationship.getParserRuleContext(), domain, relationship.getTo(),
129-
withViewName);
150+
withViewName);
130151
to.setAsPrimaryKey(withPrimaryKey);
131152
if (to.resolveReferences(space, pass)) {
132153
anotherPass = true;
133154
}
134155
}
156+
if (fields != null) {
157+
for (MTDERelationshipField field : fields) {
158+
if (field.resolveReferences(space, pass)) {
159+
anotherPass = true;
160+
}
161+
}
162+
}
135163
if (!anotherPass) {
136164
resolvedReferences = true;
137165
}
@@ -146,21 +174,21 @@ public void accept(MTVisitor visitor) {
146174
@ModelMethod(category = ModelMethodCategory.RELATIONSHIP,
147175
description =
148176
"This returns the full name of this domain relationship which includes not only its domain based name "
149-
+ "but is also preceded with the domain's entity's full name. The delimiter can be provided which "
150-
+ "is used between all parts of the full name.")
177+
+ "but is also preceded with the domain's entity's full name. The delimiter can be provided which "
178+
+ "is used between all parts of the full name.")
151179
@Override
152180
public String getFullname(
153181
@ModelMethodParameter(description = "A delimiter to place between the segments of the domain namespace as well "
154-
+ "as between that namespace and the domain entity name and between the "
155-
+ "domain entity name and the domain relationship name.")
156-
String delim) {
182+
+ "as between that namespace and the domain entity name and between the "
183+
+ "domain entity name and the domain relationship name.")
184+
String delim) {
157185
return domainEntity.getFullname(delim) + delim + getName();
158186
}
159187

160188
@ModelMethod(category = ModelMethodCategory.RELATIONSHIP,
161189
description =
162190
"Returns the domain relationship name which is the result of applying any defined naming conventions "
163-
+ "or explicit renaming.")
191+
+ "or explicit renaming.")
164192
@Override
165193
public String getName() {
166194
if (explicitName != null) {
@@ -230,7 +258,7 @@ public boolean isPrimaryParent() {
230258
description = "Returns whether this relationship's \"to\" entity is tagged with the specified tag.")
231259
public boolean hasToEntityTagged(
232260
@ModelMethodParameter(description = "The tag with which to check.")
233-
String tag) {
261+
String tag) {
234262
return to != null && to.getEntity().hasTag(tag);
235263
}
236264
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package org.entityc.compiler.model.domain;
2+
3+
import org.antlr.v4.runtime.ParserRuleContext;
4+
import org.entityc.compiler.doc.annotation.ModelClass;
5+
import org.entityc.compiler.doc.annotation.ModelClassType;
6+
import org.entityc.compiler.model.MTNode;
7+
import org.entityc.compiler.model.MTReferenceResolution;
8+
import org.entityc.compiler.model.config.MTSpace;
9+
import org.entityc.compiler.model.entity.MTEntity;
10+
import org.entityc.compiler.model.entity.MTRelationship;
11+
import org.entityc.compiler.model.visitor.MTVisitor;
12+
import org.entityc.compiler.util.ECLog;
13+
14+
@ModelClass(type = ModelClassType.DOMAIN,
15+
description = "Represents a field (attribute or relationship) associated with the __to__ entity of the relationship.")
16+
public class MTDERelationshipField extends MTNode implements MTNamed, MTDomainBased, MTReferenceResolution {
17+
18+
public MTDERelationshipField(ParserRuleContext ctx, MTDERelationship domainRelationship, String fieldName) {
19+
super(ctx);
20+
this.domainRelationship = domainRelationship;
21+
this.fieldName = fieldName;
22+
}
23+
private MTDERelationship domainRelationship;
24+
private MTDEAttribute fieldAttribute;
25+
private MTDERelationship fieldRelationship;
26+
27+
private String fieldName;
28+
29+
public boolean fieldIsAttribute() {
30+
return fieldAttribute != null;
31+
}
32+
33+
public boolean fieldIsRelationship() {
34+
return fieldRelationship != null;
35+
}
36+
37+
public MTDEAttribute getAttribute() {
38+
return fieldAttribute;
39+
}
40+
41+
@Override
42+
public void accept(MTVisitor visitor) {
43+
44+
}
45+
46+
@Override
47+
public boolean resolveReferences(MTSpace space, int pass) {
48+
ECLog.logInfo("Resolving domain relationship field references...");
49+
if ( fieldIsAttribute() || fieldIsRelationship() ) {
50+
return false;
51+
}
52+
MTRelationship relationship = domainRelationship.getRelationship();
53+
if (relationship == null) {
54+
return true;
55+
}
56+
MTEntity entity = relationship.getTo() != null && relationship.getTo().getEntity() != null ? relationship.getTo().getEntity() : null;
57+
if (entity == null) {
58+
return true;
59+
}
60+
61+
if (entity.hasAttributeNamed(fieldName)) {
62+
this.fieldAttribute = new MTDEAttribute(getParserRuleContext(), domainRelationship.getDomain(), entity.getName(), fieldName);
63+
this.fieldAttribute.addTagsWithValues(this.getTagsWithValues()); // transfer the tags to it
64+
} else if (entity.hasRelationshipNamed(fieldName)) {
65+
ECLog.logFatal(getParserRuleContext(), "Domain relationship fields of type relationship currently not supported.");
66+
} else {
67+
ECLog.logFatal(getParserRuleContext(), "Domain relationship " + this.domainRelationship.getName() + " of entity " + entity.getName() + " does not have an attribute or relationship named: " + fieldName);
68+
}
69+
return false;
70+
}
71+
72+
@Override
73+
public MTDomain getDomain() {
74+
return this.domainRelationship.getDomain();
75+
}
76+
77+
@Override
78+
public String getFullname(String delim) {
79+
return this.domainRelationship.getFullname(delim) + delim + this.fieldName;
80+
}
81+
82+
@Override
83+
public String getName() {
84+
return this.fieldName;
85+
}
86+
}

0 commit comments

Comments
 (0)