Skip to content

Parameterize Node DynamicLabels #3034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: 7.4.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ final class DynamicLabels implements UnaryOperator<OngoingMatchAndUpdate> {
public OngoingMatchAndUpdate apply(OngoingMatchAndUpdate ongoingMatchAndUpdate) {

OngoingMatchAndUpdate decoratedMatchAndUpdate = ongoingMatchAndUpdate;

if (oldLabels.equals(newLabels) || oldLabels.isEmpty()) {
// Returning if old label equals new label or old labels are empty, nothing to do here
return decoratedMatchAndUpdate;
}

if (!oldLabels.isEmpty()) {
decoratedMatchAndUpdate = decoratedMatchAndUpdate.remove(rootNode, oldLabels.toArray(new String[0]));
}
Expand All @@ -60,4 +66,8 @@ public OngoingMatchAndUpdate apply(OngoingMatchAndUpdate ongoingMatchAndUpdate)
}
return decoratedMatchAndUpdate;
}

public List<String> getNewLabels() {
return newLabels;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,10 @@ private <T> T saveImpl(T instance, @Nullable Collection<PropertyFilter.Projected

DynamicLabels dynamicLabels = determineDynamicLabels(entityToBeSaved, entityMetaData);

// Clear existing dynamic labels and populate the list with the updated set of labels.
entityMetaData.getDynamicLabels().clear();
entityMetaData.getDynamicLabels().addAll(dynamicLabels.getNewLabels());

@SuppressWarnings("unchecked") // Applies to retrieving the meta data
TemplateSupport.FilteredBinderFunction<T> binderFunction = TemplateSupport.createAndApplyPropertyFilter(
includedProperties, entityMetaData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,10 @@ private <T> Mono<T> saveImpl(T instance, @Nullable Collection<PropertyFilter.Pro

DynamicLabels dynamicLabels = t.getT2();

// Clear existing dynamic labels and populate the list with the updated set of labels.
entityMetaData.getDynamicLabels().clear();
entityMetaData.getDynamicLabels().addAll(dynamicLabels.getNewLabels());

@SuppressWarnings("unchecked")
FilteredBinderFunction<T> binderFunction = TemplateSupport.createAndApplyPropertyFilter(
includedProperties, entityMetaData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ public Statement prepareSaveOf(NodeDescription<?> nodeDescription,
String primaryLabel = nodeDescription.getPrimaryLabel();
List<String> additionalLabels = nodeDescription.getAdditionalLabels();

List<String> additionalLabelsNew = new ArrayList<>(additionalLabels);
additionalLabelsNew.addAll(nodeDescription.getDynamicLabels());
Node rootNodeWithDynamicLabels = node(primaryLabel, additionalLabelsNew).named(Constants.NAME_OF_TYPED_ROOT_NODE.apply(nodeDescription));

Node rootNode = node(primaryLabel, additionalLabels).named(Constants.NAME_OF_TYPED_ROOT_NODE.apply(nodeDescription));
IdDescription idDescription = nodeDescription.getIdDescription();
Assert.notNull(idDescription, "Cannot save individual nodes without an id attribute");
Expand All @@ -320,9 +324,9 @@ public Statement prepareSaveOf(NodeDescription<?> nodeDescription,
.where(createCompositePropertyCondition(idPropertyDescription, possibleExistingNode.getRequiredSymbolicName(), idParameter))
.with(possibleExistingNode)
.where(possibleExistingNode.isNull())
.create(rootNode.withProperties(versionProperty, literalOf(0)))
.with(rootNode)
.mutate(rootNode, parameter(Constants.NAME_OF_PROPERTIES_PARAM))).returning(rootNode)
.create(rootNodeWithDynamicLabels.withProperties(versionProperty, literalOf(0)))
.with(rootNodeWithDynamicLabels)
.mutate(rootNodeWithDynamicLabels, parameter(Constants.NAME_OF_PROPERTIES_PARAM))).returning(rootNodeWithDynamicLabels)
.build();

Statement updateIfExists = updateDecorator.apply(match(rootNode)
Expand All @@ -345,9 +349,9 @@ public Statement prepareSaveOf(NodeDescription<?> nodeDescription,
.where(createCompositePropertyCondition(idPropertyDescription, possibleExistingNode.getRequiredSymbolicName(), idParameter))
.with(possibleExistingNode)
.where(possibleExistingNode.isNull())
.create(rootNode)
.with(rootNode)
.mutate(rootNode, parameter(Constants.NAME_OF_PROPERTIES_PARAM))).returning(rootNode)
.create(rootNodeWithDynamicLabels)
.with(rootNodeWithDynamicLabels)
.mutate(rootNodeWithDynamicLabels, parameter(Constants.NAME_OF_PROPERTIES_PARAM))).returning(rootNodeWithDynamicLabels)
.build();

Statement updateIfExists = updateDecorator.apply(match(rootNode)
Expand Down Expand Up @@ -375,10 +379,10 @@ public Statement prepareSaveOf(NodeDescription<?> nodeDescription,
.where(nodeIdFunction.apply(possibleExistingNode).isEqualTo(idParameter))
.with(possibleExistingNode)
.where(possibleExistingNode.isNull())
.create(rootNode.withProperties(versionProperty, literalOf(0)))
.with(rootNode)
.mutate(rootNode, parameter(Constants.NAME_OF_PROPERTIES_PARAM)))
.returning(rootNode)
.create(rootNodeWithDynamicLabels.withProperties(versionProperty, literalOf(0)))
.with(rootNodeWithDynamicLabels)
.mutate(rootNodeWithDynamicLabels, parameter(Constants.NAME_OF_PROPERTIES_PARAM)))
.returning(rootNodeWithDynamicLabels)
.build();

updateIfExists = updateDecorator.apply(match(rootNode)
Expand All @@ -393,9 +397,9 @@ public Statement prepareSaveOf(NodeDescription<?> nodeDescription,
} else {
createIfNew = updateDecorator
.apply(optionalMatch(possibleExistingNode).where(nodeIdFunction.apply(possibleExistingNode).isEqualTo(idParameter))
.with(possibleExistingNode).where(possibleExistingNode.isNull()).create(rootNode)
.set(rootNode, parameter(Constants.NAME_OF_PROPERTIES_PARAM)))
.returning(rootNode).build();
.with(possibleExistingNode).where(possibleExistingNode.isNull()).create(rootNodeWithDynamicLabels)
.set(rootNodeWithDynamicLabels, parameter(Constants.NAME_OF_PROPERTIES_PARAM)))
.returning(rootNodeWithDynamicLabels).build();

updateIfExists = updateDecorator.apply(match(rootNode).where(nodeIdFunction.apply(rootNode).isEqualTo(idParameter))
.mutate(rootNode, parameter(Constants.NAME_OF_PROPERTIES_PARAM))).returning(rootNode).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ final class DefaultNeo4jPersistentEntity<T> extends BasicPersistentEntity<T, Neo

private final Lazy<List<String>> additionalLabels;

private List<String> dynamicLabels;

/**
* Projections need to be also be eligible entities but don't define id fields.
*/
Expand All @@ -90,8 +92,8 @@ final class DefaultNeo4jPersistentEntity<T> extends BasicPersistentEntity<T, Neo

DefaultNeo4jPersistentEntity(TypeInformation<T> information) {
super(information);

this.primaryLabel = computePrimaryLabel(this.getType());
this.dynamicLabels = new ArrayList<>();
this.primaryLabel = computePrimaryLabel(this.getType());
this.additionalLabels = Lazy.of(this::computeAdditionalLabels);
this.graphProperties = Lazy.of(this::computeGraphProperties);
this.dynamicLabelsProperty = Lazy.of(() -> getGraphProperties().stream().map(Neo4jPersistentProperty.class::cast)
Expand Down Expand Up @@ -166,6 +168,11 @@ public List<String> getAdditionalLabels() {
return this.additionalLabels.get();
}

@Override
public List<String> getDynamicLabels() {
return this.dynamicLabels;
}

/*
* (non-Javadoc)
* @see NodeDescription#getGraphProperty(String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public interface NodeDescription<T> {
*/
List<String> getAdditionalLabels();

/**
* @return a list of dynamic label names applied to the entity
*/
List<String> getDynamicLabels();

/**
* @return The list of all static labels, that is the union of {@link #getPrimaryLabel()} +
* {@link #getAdditionalLabels()}. Order is guaranteed to be the primary first, then the others.
Expand Down