blob: 685bc98f5d272dd936940ae508e4630329944280 [file] [log] [blame]
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -07001package net.onrc.onos.core.topology;
2
3import java.util.Collections;
4import java.util.Map;
5import java.util.Objects;
6import java.util.concurrent.ConcurrentHashMap;
7import java.util.concurrent.ConcurrentMap;
8
9import org.apache.commons.lang.Validate;
10
11/**
12 * Base class for Topology Elements.
13 * <p/>
14 * Self-contained element, it is expected to be used as if it is an immutable
15 * object.
16 *
17 * @param <T> Sub-class' type.
18 * (Required to define a method returning itself's type)
19 */
20public class TopologyElement<T extends TopologyElement<T>>
Yuta HIGUCHI1222ac52014-07-09 16:50:28 -070021 implements ITopologyElement, StringAttributes, UpdateStringAttributes {
22
23 // TODO: Where should the attribute names be defined?
24 /**
25 * Attribute name for type.
26 */
27 public static final String TYPE = "type";
28 /**
29 * Attribute "type" value representing that the object belongs to Packet layer.
30 */
Yuta HIGUCHIdbc33122014-07-10 13:32:32 -070031 public static final String TYPE_PACKET_LAYER = "packet";
Yuta HIGUCHI1222ac52014-07-09 16:50:28 -070032 /**
33 * Attribute "type" value representing that the object belongs to Optical layer.
34 */
Yuta HIGUCHIdbc33122014-07-10 13:32:32 -070035 public static final String TYPE_OPTICAL_LAYER = "optical";
Yuta HIGUCHI1222ac52014-07-09 16:50:28 -070036
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -070037
38 private boolean isFrozen = false;
39
40 private ConcurrentMap<String, String> stringAttributes;
41
42
43
44 /**
45 * Default constructor for serializer.
46 */
47 protected TopologyElement() {
48 this.isFrozen = false;
49 this.stringAttributes = new ConcurrentHashMap<>();
50 }
51
52 /**
Yuta HIGUCHI7926ba32014-07-09 11:39:32 -070053 * Creates an unfrozen copy of given Object.
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -070054 * <p/>
55 * Sub-classes should do a deep-copies if necessary.
56 *
57 * @param original to make copy of.
58 */
59 public TopologyElement(TopologyElement<T> original) {
60 this.isFrozen = false;
61 this.stringAttributes = new ConcurrentHashMap<>(original.stringAttributes);
62 }
63
64
65 /**
66 * Tests if this instance is frozen.
67 *
68 * @return true if frozen.
69 */
70 public boolean isFrozen() {
71 return isFrozen;
72 }
73
74 /**
75 * Freezes this instance to avoid further modifications.
76 *
77 * @return this
78 */
79 @SuppressWarnings("unchecked")
80 public T freeze() {
81 isFrozen = true;
82 return (T) this;
83 }
84
85 @Override
86 public int hashCode() {
87 return stringAttributes.hashCode();
88 }
89
90 /*
91 * (non-Javadoc)
92 * Equality based only on string attributes.
93 *
94 * Subclasses should call super.equals().
95 */
96 @Override
97 public boolean equals(Object obj) {
98 if (this == obj) {
99 return true;
100 }
101 if (obj == null) {
102 return false;
103 }
104 if (getClass() != obj.getClass()) {
105 return false;
106 }
107 @SuppressWarnings("unchecked")
108 TopologyElement<T> other = (TopologyElement<T>) obj;
109 return Objects.equals(stringAttributes, other.stringAttributes);
110 }
111
112 @Override
113 public String getStringAttribute(String attr) {
114 return this.stringAttributes.get(attr);
115 }
116
117 @Override
118 public String getStringAttribute(String attr, String def) {
119 final String v = getStringAttribute(attr);
120 if (v == null) {
121 return def;
122 } else {
123 return v;
124 }
125 }
126
127 @Override
128 public Map<String, String> getAllStringAttributes() {
129 return Collections.unmodifiableMap(this.stringAttributes);
130 }
131
132 @Override
133 public boolean createStringAttribute(String attr, String value) {
134 if (isFrozen) {
135 throw new IllegalStateException("Tried to modify frozen object: " + this);
136 }
137 Validate.notNull(value, "attribute value cannot be null");
138
139 return this.stringAttributes.putIfAbsent(attr, value) == null;
140 }
141
142 @Override
143 public boolean replaceStringAttribute(String attr, String oldValue, String value) {
144 if (isFrozen) {
145 throw new IllegalStateException("Tried to modify frozen object: " + this);
146 }
147 Validate.notNull(value, "attribute value cannot be null");
148
149 return this.stringAttributes.replace(attr, oldValue, value);
150 }
151
152 @Override
153 public boolean deleteStringAttribute(String attr, String expectedValue) {
154 if (isFrozen) {
155 throw new IllegalStateException("Tried to modify frozen object: " + this);
156 }
157
158 return this.stringAttributes.remove(attr, expectedValue);
159 }
160
161 @Override
162 public void deleteStringAttribute(String attr) {
163 if (isFrozen) {
164 throw new IllegalStateException("Tried to modify frozen object: " + this);
165 }
166
167 this.stringAttributes.remove(attr);
168 }
Yuta HIGUCHI1222ac52014-07-09 16:50:28 -0700169
170 @Override
171 public String getType() {
Yuta HIGUCHIdbc33122014-07-10 13:32:32 -0700172 return getStringAttribute(TYPE, TYPE_PACKET_LAYER);
Yuta HIGUCHI1222ac52014-07-09 16:50:28 -0700173 }
Yuta HIGUCHIbf0a8712014-06-30 18:59:46 -0700174}