From 5f7e37d7b26832b3b512f9dda310cb9bc92c93fb Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Fri, 27 Dec 2019 21:08:44 +0100 Subject: Create new zones with UpdateAttributes message --- .../cloudatlas/agent/messages/StanikMessage.java | 3 +- .../agent/messages/UpdateAttributesMessage.java | 23 +++++++++++ .../edu/mimuw/cloudatlas/agent/modules/Stanik.java | 48 ++++++++++++++++++++++ .../java/pl/edu/mimuw/cloudatlas/model/ZMI.java | 17 ++++++++ .../mimuw/cloudatlas/agent/modules/StanikTest.java | 38 +++++++++++++++++ 5 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/UpdateAttributesMessage.java (limited to 'src') diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/StanikMessage.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/StanikMessage.java index d2b3064..8661c90 100644 --- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/StanikMessage.java +++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/StanikMessage.java @@ -5,7 +5,8 @@ import pl.edu.mimuw.cloudatlas.agent.modules.ModuleType; public abstract class StanikMessage extends AgentMessage { public enum Type { - GET_HIERARCHY + GET_HIERARCHY, + UPDATE_ATTRIBUTES } private Type type; diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/UpdateAttributesMessage.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/UpdateAttributesMessage.java new file mode 100644 index 0000000..7e41631 --- /dev/null +++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/messages/UpdateAttributesMessage.java @@ -0,0 +1,23 @@ +package pl.edu.mimuw.cloudatlas.agent.messages; + +import pl.edu.mimuw.cloudatlas.agent.modules.ModuleType; +import pl.edu.mimuw.cloudatlas.model.AttributesMap; + +public class UpdateAttributesMessage extends StanikMessage { + private String pathName; + private AttributesMap attributes; + + public UpdateAttributesMessage(String messageId, long timestamp, String pathName, AttributesMap attributes) { + super(messageId, timestamp, Type.UPDATE_ATTRIBUTES); + this.pathName = pathName; + this.attributes = attributes; + } + + public String getPathName() { + return pathName; + } + + public AttributesMap getAttributes() { + return attributes; + } +} diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java index b8db08a..a457a94 100644 --- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java +++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/modules/Stanik.java @@ -1,9 +1,17 @@ package pl.edu.mimuw.cloudatlas.agent.modules; +import java.util.Map.Entry; + import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage; import pl.edu.mimuw.cloudatlas.agent.messages.GetHierarchyMessage; import pl.edu.mimuw.cloudatlas.agent.messages.HierarchyMessage; import pl.edu.mimuw.cloudatlas.agent.messages.StanikMessage; +import pl.edu.mimuw.cloudatlas.agent.messages.UpdateAttributesMessage; +import pl.edu.mimuw.cloudatlas.model.AttributesMap; +import pl.edu.mimuw.cloudatlas.model.Attribute; +import pl.edu.mimuw.cloudatlas.model.PathName; +import pl.edu.mimuw.cloudatlas.model.Value; +import pl.edu.mimuw.cloudatlas.model.ValueString; import pl.edu.mimuw.cloudatlas.model.ZMI; public class Stanik extends Module { @@ -19,6 +27,9 @@ public class Stanik extends Module { case GET_HIERARCHY: handleGetHierarchy((GetHierarchyMessage) message); break; + case UPDATE_ATTRIBUTES: + handleUpdateAttributes((UpdateAttributesMessage) message); + break; default: throw new InvalidMessageType("This type of message cannot be handled by Stanik"); } @@ -28,4 +39,41 @@ public class Stanik extends Module { HierarchyMessage response = new HierarchyMessage("", message.getRequestingModule(), 0, message.getRequestId(), hierarchy.clone()); sendMessage(response); } + + public void handleUpdateAttributes(UpdateAttributesMessage message) { + try { + addMissingZones(new PathName(message.getPathName())); + ZMI zone = hierarchy.findDescendant(message.getPathName()); + for (Entry entry : zone.getAttributes()) { + Attribute attribute = entry.getKey(); + Value newValue = message.getAttributes().getOrNull(attribute); + if (newValue == null) { + zone.getAttributes().remove(attribute); + } + } + for (Entry entry : message.getAttributes()) { + zone.getAttributes().addOrChange(entry.getKey(), entry.getValue()); + } + } catch (ZMI.NoSuchZoneException e) { + System.out.println("ERROR: zone should exist after being added"); + } + } + + private void addMissingZones(PathName path) { + try { + if (!hierarchy.descendantExists(path)) { + addMissingZones(path.levelUp()); + ZMI parent = hierarchy.findDescendant(path.levelUp()); + ZMI newSon = new ZMI(parent); + newSon.getAttributes().add("name", new ValueString(path.getSingletonName())); + parent.addSon(newSon); + } + } catch (ZMI.NoSuchZoneException e) { + System.out.println("ERROR: zone should exist after being added"); + } + } + + public ZMI getHierarchy() { + return hierarchy; + } } diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java b/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java index 7f2f604..54fbf43 100644 --- a/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java +++ b/src/main/java/pl/edu/mimuw/cloudatlas/model/ZMI.java @@ -111,6 +111,23 @@ public class ZMI implements Cloneable, Serializable { return descendant; } + public boolean descendantExists(PathName path) { + try { + findDescendant(path); + return true; + } catch (NoSuchZoneException e) { + return false; + } + } + + /* + * Convenient version of findDescendant that takes String representation of + * path. + */ + public ZMI findDescendant(String pathString) throws NoSuchZoneException { + return findDescendant(new PathName(pathString)); + } + /** * Gets the list of sons of this ZMI. Modifying a value in the returned list will cause an exception. * diff --git a/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java b/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java index 1c1e216..31b701d 100644 --- a/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java +++ b/src/test/java/pl/edu/mimuw/cloudatlas/agent/modules/StanikTest.java @@ -7,11 +7,13 @@ import pl.edu.mimuw.cloudatlas.agent.messages.AgentMessage; import pl.edu.mimuw.cloudatlas.agent.messages.GetHierarchyMessage; import pl.edu.mimuw.cloudatlas.agent.messages.HierarchyMessage; import pl.edu.mimuw.cloudatlas.agent.messages.ResponseMessage; +import pl.edu.mimuw.cloudatlas.agent.messages.UpdateAttributesMessage; import pl.edu.mimuw.cloudatlas.agent.MockExecutor; import pl.edu.mimuw.cloudatlas.model.Attribute; import pl.edu.mimuw.cloudatlas.model.AttributesMap; import pl.edu.mimuw.cloudatlas.model.Value; import pl.edu.mimuw.cloudatlas.model.ValueInt; +import pl.edu.mimuw.cloudatlas.model.ValueString; import pl.edu.mimuw.cloudatlas.model.ZMI; import org.junit.Before; @@ -65,4 +67,40 @@ public class StanikTest { AttributesMap newAttributes = newReceivedMessage.getZMI().getAttributes(); assertNull(newAttributes.getOrNull("foo")); } + + @Test + public void updateRootAttributes() throws Exception { + AttributesMap attributes = new AttributesMap(); + attributes.add("foo", new ValueInt(1337l)); + attributes.add("bar", new ValueString("baz")); + UpdateAttributesMessage message = new UpdateAttributesMessage("test_msg", 0, "/", attributes); + stanik.handleTyped(message); + AttributesMap actualAttributes = stanik.getHierarchy().getAttributes(); + assertEquals(2, countAttributes(actualAttributes)); + assertEquals(new ValueInt(1337l), actualAttributes.get("foo")); + assertEquals(new ValueString("baz"), actualAttributes.get("bar")); + } + + @Test + public void updateWithNewZone() throws Exception { + AttributesMap attributes = new AttributesMap(); + attributes.add("foo", new ValueInt(1337l)); + attributes.add("bar", new ValueString("baz")); + attributes.add("name", new ValueString("new")); + UpdateAttributesMessage message = new UpdateAttributesMessage("test_msg", 0, "/new", attributes); + stanik.handleTyped(message); + AttributesMap actualAttributes = stanik.getHierarchy().findDescendant("/new").getAttributes(); + assertEquals(3, countAttributes(actualAttributes)); + assertEquals(new ValueInt(1337l), actualAttributes.getOrNull("foo")); + assertEquals(new ValueString("baz"), actualAttributes.getOrNull("bar")); + } + + public int countAttributes(AttributesMap attributes) { + int count = 0; + for (Entry attribute : attributes) { + count++; + } + + return count; + } } -- cgit v1.2.3