Skip to content

Commit

Permalink
Clean up the API of EntityUpdate #636
Browse files Browse the repository at this point in the history
* lazy init of EntityUpdate collections
  • Loading branch information
andrus committed Jun 27, 2023
1 parent b6d3542 commit 6864c81
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 85 deletions.
1 change: 1 addition & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* #633 Optimize and clean up update parser
* #634 Recursive EntityUpdate parser
* #635 Write constraint only applied to "id" in the path, but not in the body
* #636 Clean up the API of EntityUpdate

## Release 5.0.M16

Expand Down
200 changes: 134 additions & 66 deletions agrest-engine/src/main/java/io/agrest/EntityUpdate.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,17 @@ public class EntityUpdate<T> implements UpdateRequest<T> {

private final AgEntity<T> entity;

private final Map<String, Object> idParts;
private final Map<String, Object> attributes;
private final Map<String, EntityUpdate<?>> toOnes;
private final Map<String, List<EntityUpdate<?>>> toManys;
private final Map<String, Object> toOneIds;
private final Map<String, Set<Object>> toManyIds;
private Map<String, Object> idParts;
private Map<String, Object> attributes;
private Map<String, EntityUpdate<?>> toOnes;
private Map<String, List<EntityUpdate<?>>> toManys;
private Map<String, Object> toOneIds;
private Map<String, Set<Object>> toManyIds;

private T targetObject;

public EntityUpdate(AgEntity<T> entity) {
this.entity = Objects.requireNonNull(entity);

this.idParts = new HashMap<>();
this.attributes = new HashMap<>();
this.toManys = new HashMap<>();
this.toOnes = new HashMap<>();
this.toOneIds = new HashMap<>();
this.toManyIds = new HashMap<>();
}

/**
Expand All @@ -49,15 +42,15 @@ public EntityUpdate(AgEntity<T> entity) {
*/
public EntityUpdate<T> merge(EntityUpdate<T> anotherUpdate) {

this.idParts.putAll(anotherUpdate.idParts);
this.attributes.putAll(anotherUpdate.attributes);
this.toOnes.putAll(anotherUpdate.toOnes);
this.toManys.putAll(anotherUpdate.toManys);
this.toOneIds.putAll(anotherUpdate.toOneIds);
this.toManyIds.putAll(anotherUpdate.toManyIds);
this.idParts = mergeMaps(idParts, anotherUpdate.idParts);
this.attributes = mergeMaps(attributes, anotherUpdate.attributes);
this.toOnes = mergeMaps(toOnes, anotherUpdate.toOnes);
this.toManys = mergeMaps(toManys, anotherUpdate.toManys);
this.toOneIds = mergeMaps(toOneIds, anotherUpdate.toOneIds);
this.toManyIds = mergeMaps(toManyIds, anotherUpdate.toManyIds);

// If we are merging a compatible update, "entity", "mergedTo" should all be identical already.
// Do not override them.
// We are presumably merging a compatible update, so "entity", "targetObject" should all be identical and
// require no override

return this;
}
Expand All @@ -70,77 +63,96 @@ public AgEntity<T> getEntity() {
}

/**
* Returns an object targeted by this update. The object is null until it is initialized by Agrest, usually during
* {@link UpdateStage#MERGE_CHANGES} step of the pipeline.
*
* @since 5.0
*/
public void setIdParts(Map<String, Object> id) {
idParts.putAll(id);
public T getTargetObject() {
return targetObject;
}

/**
* Sets an object targeted by this update.
*
* @since 5.0
*/
public void addIdPart(String idPart, Object value) {
idParts.put(idPart, value);
public void setTargetObject(T targetObject) {
this.targetObject = targetObject;
}

/**
* @since 5.0
*/
public void addIdPartIfAbsent(String idPart, Object value) {
idParts.putIfAbsent(idPart, value);
public Map<String, Object> getIdParts() {
return idParts != null ? idParts : Collections.emptyMap();
}

/**
* @since 5.0
*/
public Map<String, Object> getAttributes() {
return attributes;
public Object getIdPart(String idPart) {
return idParts != null ? idParts.get(idPart) : null;
}

public Object getAttribute(String attribute) {
return attributes.get(attribute);
/**
* @since 5.0
*/
public void setIdParts(Map<String, Object> id) {
mutableIdParts().putAll(id);
}

/**
* @since 5.0
*/
public void setAttribute(String attribute, Object value) {
attributes.put(attribute, value);
public void addIdPart(String idPart, Object value) {
mutableIdParts().put(idPart, value);
}

/**
* @since 5.0
*/
public Map<String, Set<Object>> getToManyIds() {
return toManyIds;
public void addIdPartIfAbsent(String idPart, Object value) {
mutableIdParts().putIfAbsent(idPart, value);
}

/**
* @since 5.0
*/
public void addToManyId(String relationship, Object value) {
toManyIds.computeIfAbsent(relationship, n -> new HashSet<>()).add(value);
public Map<String, Object> getAttributes() {
return attributes != null ? attributes : Collections.emptyMap();
}

public Object getAttribute(String attribute) {
return attributes != null ? attributes.get(attribute) : null;
}

/**
* @since 5.0
*/
public void setToOneId(String relationship, Object value) {
toOneIds.put(relationship, value);
public void setAttribute(String attribute, Object value) {
mutableAttributes().put(attribute, value);
}

/**
* @since 5.0
*/
public Object getToOneId(String relationship) {
return toOneIds.get(relationship);
public Map<String, EntityUpdate<?>> getToOnes() {
return toOnes != null ? toOnes : Collections.emptyMap();
}

/**
* @since 5.0
*/
public Map<String, Object> getToOneIds() {
return toOneIds;
public <R> EntityUpdate<R> getToOne(String relationship) {
return toOnes != null ? (EntityUpdate<R>) toOnes.get(relationship) : null;
}

/**
* @since 5.0
*/
public void setToOne(String relationshipName, EntityUpdate<?> update) {
mutableToOnes().put(relationshipName, update);
}

/**
Expand All @@ -151,68 +163,124 @@ public Map<String, Object> getToOneIds() {
* @since 5.0
*/
public Map<String, List<EntityUpdate<?>>> getToManys() {
return toManys;
return toManys != null ? toManys : Collections.emptyMap();
}

/**
* @since 5.0
*/
public void addToMany(String relationshipName, EntityUpdate<?> update) {
toManys.computeIfAbsent(relationshipName, n -> new ArrayList<>()).add(update);
public <R> List<EntityUpdate<R>> getToMany(String relationship) {
List updates = toManys != null ? toManys.get(relationship) : Collections.emptyList();
return updates != null ? updates : Collections.emptyList();
}

/**
* @since 5.0
*/
public void setToOne(String relationshipName, EntityUpdate<?> update) {
toOnes.put(relationshipName, update);
public void addToMany(String relationshipName, EntityUpdate<?> update) {
mutableToManys().computeIfAbsent(relationshipName, n -> new ArrayList<>()).add(update);
}

/**
* @since 5.0
*/
public <R> EntityUpdate<R> getToOne(String relationship) {
return (EntityUpdate<R>) toOnes.get(relationship);
public Map<String, Object> getToOneIds() {
return toOneIds != null ? toOneIds : Collections.emptyMap();
}

/**
* @since 5.0
*/
public Map<String, EntityUpdate<?>> getToOnes() {
return toOnes;
public Object getToOneId(String relationship) {
return toOneIds != null ? toOneIds.get(relationship) : null;
}

/**
* @since 5.0
*/
public <R> List<EntityUpdate<R>> getToMany(String relationship) {
List updates = toManys.get(relationship);
return updates != null ? updates : Collections.emptyList();
public void setToOneId(String relationship, Object value) {
mutableToOneIds().put(relationship, value);
}

/**
* @since 5.0
*/
public Map<String, Object> getIdParts() {
return idParts;
public Map<String, Set<Object>> getToManyIds() {
return toManyIds != null ? toManyIds : Collections.emptyMap();
}

/**
* Returns an object targeted by this update. The object is null until it is initialized by Agrest, usually during
* {@link UpdateStage#MERGE_CHANGES} step of the pipeline.
*
* @since 5.0
*/
public T getTargetObject() {
return targetObject;
public Set<Object> getToManyIds(String relationship) {
return toManyIds != null ? toManyIds.get(relationship) : null;
}

/**
* Sets an object targeted by this update.
*
* @since 5.0
*/
public void setTargetObject(T targetObject) {
this.targetObject = targetObject;
public void addToManyId(String relationship, Object value) {
mutableToManyIds().computeIfAbsent(relationship, n -> new HashSet<>()).add(value);
}

private <M> Map<String, M> mergeMaps(Map<String, M> to, Map<String, M> from) {
if (from == null || from.isEmpty()) {
return to;
}

if (to != null) {
to.putAll(from);
return to;
}

return new HashMap<>(from);
}

private Map<String, Object> mutableIdParts() {
if (idParts == null) {
idParts = new HashMap<>();
}

return idParts;
}

private Map<String, Object> mutableAttributes() {
if (attributes == null) {
attributes = new HashMap<>();
}

return attributes;
}

private Map<String, EntityUpdate<?>> mutableToOnes() {
if (toOnes == null) {
toOnes = new HashMap<>();
}

return toOnes;
}

private Map<String, List<EntityUpdate<?>>> mutableToManys() {
if (toManys == null) {
toManys = new HashMap<>();
}

return toManys;
}

private Map<String, Object> mutableToOneIds() {
if (toOneIds == null) {
toOneIds = new HashMap<>();
}

return toOneIds;
}

private Map<String, Set<Object>> mutableToManyIds() {
if (toManyIds == null) {
toManyIds = new HashMap<>();
}

return toManyIds;
}
}
Loading

0 comments on commit 6864c81

Please sign in to comment.