Add string attributes to self-containd objects.
- Add common super class to *Event classes, which handles attributes.
- Add string attributes to *Event classes (ONOS-1564)
- Populate string attributes.
Picked random attribute obtained from OF, just to initially populate attrs.
Attributes to be used for each elements should be revisited later.
- *Impl class to use/reference self-contained objects
prep-work for snapshot in mind.
- unified equals implementations
- Add unfrozen Copy constructor.
- Add freeze check to fixed attributes.
- Remove get*Impl which was not really adding value.
Change-Id: I10f9538f87d133a22237bd8ab97b8de421d3930b
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyElement.java b/src/main/java/net/onrc/onos/core/topology/TopologyElement.java
new file mode 100644
index 0000000..3a6dad8
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyElement.java
@@ -0,0 +1,154 @@
+package net.onrc.onos.core.topology;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.commons.lang.Validate;
+
+/**
+ * Base class for Topology Elements.
+ * <p/>
+ * Self-contained element, it is expected to be used as if it is an immutable
+ * object.
+ *
+ * @param <T> Sub-class' type.
+ * (Required to define a method returning itself's type)
+ */
+public class TopologyElement<T extends TopologyElement<T>>
+ implements StringAttributes, UpdateStringAttributes {
+
+ private boolean isFrozen = false;
+
+ private ConcurrentMap<String, String> stringAttributes;
+
+
+
+ /**
+ * Default constructor for serializer.
+ */
+ protected TopologyElement() {
+ this.isFrozen = false;
+ this.stringAttributes = new ConcurrentHashMap<>();
+ }
+
+ /**
+ * Create an unfrozen copy of given Object.
+ * <p/>
+ * Sub-classes should do a deep-copies if necessary.
+ *
+ * @param original to make copy of.
+ */
+ public TopologyElement(TopologyElement<T> original) {
+ this.isFrozen = false;
+ this.stringAttributes = new ConcurrentHashMap<>(original.stringAttributes);
+ }
+
+
+ /**
+ * Tests if this instance is frozen.
+ *
+ * @return true if frozen.
+ */
+ public boolean isFrozen() {
+ return isFrozen;
+ }
+
+ /**
+ * Freezes this instance to avoid further modifications.
+ *
+ * @return this
+ */
+ @SuppressWarnings("unchecked")
+ public T freeze() {
+ isFrozen = true;
+ return (T) this;
+ }
+
+ @Override
+ public int hashCode() {
+ return stringAttributes.hashCode();
+ }
+
+ /*
+ * (non-Javadoc)
+ * Equality based only on string attributes.
+ *
+ * Subclasses should call super.equals().
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ @SuppressWarnings("unchecked")
+ TopologyElement<T> other = (TopologyElement<T>) obj;
+ return Objects.equals(stringAttributes, other.stringAttributes);
+ }
+
+ @Override
+ public String getStringAttribute(String attr) {
+ return this.stringAttributes.get(attr);
+ }
+
+ @Override
+ public String getStringAttribute(String attr, String def) {
+ final String v = getStringAttribute(attr);
+ if (v == null) {
+ return def;
+ } else {
+ return v;
+ }
+ }
+
+ @Override
+ public Map<String, String> getAllStringAttributes() {
+ return Collections.unmodifiableMap(this.stringAttributes);
+ }
+
+ @Override
+ public boolean createStringAttribute(String attr, String value) {
+ if (isFrozen) {
+ throw new IllegalStateException("Tried to modify frozen object: " + this);
+ }
+ Validate.notNull(value, "attribute value cannot be null");
+
+ return this.stringAttributes.putIfAbsent(attr, value) == null;
+ }
+
+ @Override
+ public boolean replaceStringAttribute(String attr, String oldValue, String value) {
+ if (isFrozen) {
+ throw new IllegalStateException("Tried to modify frozen object: " + this);
+ }
+ Validate.notNull(value, "attribute value cannot be null");
+
+ return this.stringAttributes.replace(attr, oldValue, value);
+ }
+
+ @Override
+ public boolean deleteStringAttribute(String attr, String expectedValue) {
+ if (isFrozen) {
+ throw new IllegalStateException("Tried to modify frozen object: " + this);
+ }
+
+ return this.stringAttributes.remove(attr, expectedValue);
+ }
+
+ @Override
+ public void deleteStringAttribute(String attr) {
+ if (isFrozen) {
+ throw new IllegalStateException("Tried to modify frozen object: " + this);
+ }
+
+ this.stringAttributes.remove(attr);
+ }
+}