Skip to content

Commit

Permalink
Added parent property tracking metadata to Node
Browse files Browse the repository at this point in the history
  • Loading branch information
EricWittmann committed Nov 26, 2024
1 parent cf50a5a commit d406d39
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ protected void createSetter(JavaSource<?> javaEntity, PropertyModelWithOrigin pr
method.addParameter(jt.toJavaTypeString(), "value");
}

createSetterBody(property, method);
createSetterBody(javaEntity, property, method);
}
abstract protected void createSetterBody(PropertyModel property, MethodSource<?> method);
abstract protected void createSetterBody(JavaSource<?> javaEntity, PropertyModel property, MethodSource<?> method);

/**
* Creates a factory method for the entity type associated with the given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ protected String getRootNodeEntityClassFQN() {
return getState().getConfig().getRootNamespace() + ".RootNodeImpl";
}

protected String getParentPropertyTypeEnumFQN() {
return getState().getConfig().getRootNamespace() + ".ParentPropertyType";
}

protected String getModelTypeEnumFQN() {
return getState().getConfig().getRootNamespace() + ".ModelType";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Map;

import org.jboss.forge.roaster.model.source.JavaClassSource;
import org.jboss.forge.roaster.model.source.JavaEnumSource;
import org.jboss.forge.roaster.model.source.JavaInterfaceSource;
import org.jboss.forge.roaster.model.source.JavaSource;
import org.jboss.forge.roaster.model.source.MethodHolderSource;
Expand Down Expand Up @@ -135,6 +136,18 @@ protected void createMappedNodeMethods(JavaSource<?> javaEntity, PropertyModelWi
method.addParameter(mappedNodeType, "item");
BodyBuilder body = new BodyBuilder();
body.append("this._items.put(name, item);");
if (isEntity(property)) {
JavaEnumSource parentPropertyTypeSource = getState().getJavaIndex().lookupEnum(getParentPropertyTypeEnumFQN());
javaEntity.addImport(parentPropertyTypeSource);
JavaClassSource nodeImplSource = getState().getJavaIndex().lookupClass(getNodeEntityClassFQN());
javaEntity.addImport(nodeImplSource);

body.append("if (item != null) {");
body.append(" ((NodeImpl) item)._setParentPropertyName(null);");
body.append(" ((NodeImpl) item)._setParentPropertyType(ParentPropertyType.map);");
body.append(" ((NodeImpl) item)._setMapPropertyName(name);");
body.append("}");
}
method.setBody(body.toString());
}

Expand All @@ -160,11 +173,60 @@ protected void createGetterBody(PropertyModel property, MethodSource<?> method)
}

@Override
protected void createSetterBody(PropertyModel property, MethodSource<?> method) {
protected void createSetterBody(JavaSource<?> javaEntity, PropertyModel property, MethodSource<?> method) {
String fieldName = getFieldName(property);
String propertyName = property.getName();

BodyBuilder body = new BodyBuilder();
body.addContext("fieldName", fieldName);
body.addContext("propertyName", propertyName);
body.append("this.${fieldName} = value;");
if (isEntity(property)) {
JavaEnumSource parentPropertyTypeSource = getState().getJavaIndex().lookupEnum(getParentPropertyTypeEnumFQN());
javaEntity.addImport(parentPropertyTypeSource);
JavaClassSource nodeImplSource = getState().getJavaIndex().lookupClass(getNodeEntityClassFQN());
javaEntity.addImport(nodeImplSource);

body.append("if (value != null) {");
body.append(" ((NodeImpl) value)._setParentPropertyName(\"${propertyName}\");");
body.append("}");
} else if (isUnion(property)) {
JavaEnumSource parentPropertyTypeSource = getState().getJavaIndex().lookupEnum(getParentPropertyTypeEnumFQN());
javaEntity.addImport(parentPropertyTypeSource);
JavaClassSource nodeImplSource = getState().getJavaIndex().lookupClass(getNodeEntityClassFQN());
javaEntity.addImport(nodeImplSource);
JavaInterfaceSource unionValueSource = getState().getJavaIndex().lookupInterface(getUnionValueInterfaceFQN());
javaEntity.addImport(unionValueSource);

javaEntity.addImport(Collection.class);
javaEntity.addImport(List.class);
javaEntity.addImport(Map.class);

body.append("if (value != null) {");
body.append(" if (value.isEntity()) {");
body.append(" ((NodeImpl) value)._setParentPropertyName(\"${propertyName}\");");
body.append(" } else if (value.isEntityList()) {");
body.append(" List<?> entityList = (List<?>) ((UnionValue<?>) value).getValue();");
body.append(" for (Object entity : entityList) {");
body.append(" if (entity != null) {");
body.append(" ((NodeImpl) entity)._setParentPropertyName(\"${propertyName}\");");
body.append(" ((NodeImpl) entity)._setParentPropertyType(ParentPropertyType.array);");
body.append(" }");
body.append(" }");
body.append(" } else if (value.isEntityMap()) {");
body.append(" Map<String, ?> entityMap = (Map<String, ?>) ((UnionValue<?>) value).getValue();");
body.append(" Collection<String> keys = entityMap.keySet();");
body.append(" for (String key : keys) {");
body.append(" NodeImpl entity = (NodeImpl) entityMap.get(key);");
body.append(" if (entity != null) {");
body.append(" entity._setParentPropertyName(\"${propertyName}\");");
body.append(" entity._setParentPropertyType(ParentPropertyType.map);");
body.append(" entity._setMapPropertyName(key);");
body.append(" }");
body.append(" }");
body.append(" }");
body.append("}");
}
method.setBody(body.toString());
}

Expand Down Expand Up @@ -192,23 +254,51 @@ protected void createFactoryMethodBody(JavaSource<?> javaEntity, String entityNa
@Override
protected void createAddMethodBody(JavaSource<?> javaEntity, PropertyModel property, MethodSource<?> method) {
PropertyType type = property.getType().getNested().iterator().next();
String fieldName = getFieldName(property);
String propertyName = property.getName();

BodyBuilder body = new BodyBuilder();
body.addContext("fieldName", getFieldName(property));
body.addContext("fieldName", fieldName);
body.addContext("propertyName", propertyName);

if (type.isEntityType() || type.isPrimitiveType()) {
if (property.getType().isMap()) {
javaEntity.addImport(LinkedHashMap.class);

body.append("if (this.${fieldName} == null) {");
body.append(" this.${fieldName} = new LinkedHashMap<>();");
body.append("}");
body.append("this.${fieldName}.put(name, value);");
if (type.isEntityType()) {
JavaEnumSource parentPropertyTypeSource = getState().getJavaIndex().lookupEnum(getParentPropertyTypeEnumFQN());
javaEntity.addImport(parentPropertyTypeSource);
JavaClassSource nodeImplSource = getState().getJavaIndex().lookupClass(getNodeEntityClassFQN());
javaEntity.addImport(nodeImplSource);

body.append("if (value != null) {");
body.append(" ((NodeImpl) value)._setParentPropertyName(\"${propertyName}\");");
body.append(" ((NodeImpl) value)._setParentPropertyType(ParentPropertyType.map);");
body.append(" ((NodeImpl) value)._setMapPropertyName(name);");
body.append("}");
}
} else {
javaEntity.addImport(ArrayList.class);

body.append("if (this.${fieldName} == null) {");
body.append(" this.${fieldName} = new ArrayList<>();");
body.append("}");
body.append("this.${fieldName}.add(value);");
if (type.isEntityType()) {
JavaEnumSource parentPropertyTypeSource = getState().getJavaIndex().lookupEnum(getParentPropertyTypeEnumFQN());
javaEntity.addImport(parentPropertyTypeSource);
JavaClassSource nodeImplSource = getState().getJavaIndex().lookupClass(getNodeEntityClassFQN());
javaEntity.addImport(nodeImplSource);

body.append("if (value != null) {");
body.append(" ((NodeImpl) value)._setParentPropertyName(\"${propertyName}\");");
body.append(" ((NodeImpl) value)._setParentPropertyType(ParentPropertyType.array);");
body.append("}");
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ protected void createGetterBody(PropertyModel property, MethodSource<?> method)
}

@Override
protected void createSetterBody(PropertyModel property, MethodSource<?> method) {
protected void createSetterBody(JavaSource<?> javaEntity, PropertyModel property, MethodSource<?> method) {
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public class LoadBaseClassesStage extends AbstractStage {
protected void doProcess() {
try {
loadBaseEnums(
"io.apicurio.umg.base.visitors.TraversalStepType"
"io.apicurio.umg.base.visitors.TraversalStepType",
"io.apicurio.umg.base.ParentPropertyType"
);
loadBaseClasses(
"io.apicurio.umg.base.NodeImpl",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ public interface Node extends Visitable {
public int modelId();
public RootNode root();
public Node parent();
public String parentPropertyName();
public ParentPropertyType parentPropertyType();
public String mapPropertyName();
public Object getNodeAttribute(String attributeName);
public void setNodeAttribute(String attributeName, Object attributeValue);
public Collection<String> getNodeAttributeNames();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public abstract class NodeImpl implements Node {
private static int __modelIdCounter = 0;

protected int _modelId = __modelIdCounter++;
private String _parentPropertyName;
private String _mapPropertyName;
private ParentPropertyType _parentPropertyType = ParentPropertyType.standard;
private Node _parent;
private Map<String, JsonNode> _extraProperties;
private Map<String, Object> _attributes;
Expand All @@ -28,11 +31,38 @@ public RootNode root() {
public Node parent() {
return this._parent;
}


@Override
public String parentPropertyName() {
return this._parentPropertyName;
}

@Override
public ParentPropertyType parentPropertyType() {
return this._parentPropertyType;
}

@Override
public String mapPropertyName() {
return this._mapPropertyName;
}

public void setParent(Node parent) {
this._parent = parent;
}

public void _setParentPropertyName(String name) {
this._parentPropertyName = name;
}

public void _setParentPropertyType(ParentPropertyType type) {
this._parentPropertyType = type;
}

public void _setMapPropertyName(String name) {
this._mapPropertyName = name;
}

@Override
public int modelId() {
return this._modelId;
Expand Down Expand Up @@ -119,17 +149,17 @@ public boolean isAttached() {
@Override
public void attach(Node parent) {
if (!parent.isAttached())
throw new IllegalArgumentException(
"Target parent node (method argument) is not itself attached.");
throw new IllegalArgumentException("Target parent node (method argument) is not itself attached.");
this.setParent(parent);
}

/*
* Some methods that must be implemented on an entity only when the entity is part
* of a union type. We put them here so we don't have to generate them. But perhaps
* we *should* generate them only on the appropriate entity implementation classes.
* Some methods that must be implemented on an entity only when the entity is
* part of a union type. We put them here so we don't have to generate them. But
* perhaps we *should* generate them only on the appropriate entity
* implementation classes.
*/

public boolean isEntity() {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.apicurio.umg.base;

public enum ParentPropertyType {
standard, map, array
}

0 comments on commit d406d39

Please sign in to comment.