Thomas Vachuska
Committed by Gerrit Code Review

Adding ability for Config to be backed by generic JsonNode, i.e. either ObjectNode or ArrayNode.

Change-Id: I5f9ec423cd5f23f61c97a57073d9d11071c47997
...@@ -46,7 +46,7 @@ public class BgpConfig extends Config<ApplicationId> { ...@@ -46,7 +46,7 @@ public class BgpConfig extends Config<ApplicationId> {
46 public Set<BgpSpeakerConfig> bgpSpeakers() { 46 public Set<BgpSpeakerConfig> bgpSpeakers() {
47 Set<BgpSpeakerConfig> speakers = Sets.newHashSet(); 47 Set<BgpSpeakerConfig> speakers = Sets.newHashSet();
48 48
49 - JsonNode speakersNode = node.get(SPEAKERS); 49 + JsonNode speakersNode = object.get(SPEAKERS);
50 speakersNode.forEach(jsonNode -> { 50 speakersNode.forEach(jsonNode -> {
51 Set<IpAddress> listenAddresses = Sets.newHashSet(); 51 Set<IpAddress> listenAddresses = Sets.newHashSet();
52 jsonNode.path(PEERS).forEach(addressNode -> 52 jsonNode.path(PEERS).forEach(addressNode ->
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.cli.cfg; 16 package org.onosproject.cli.cfg;
17 17
18 +import com.fasterxml.jackson.databind.JsonNode;
18 import com.fasterxml.jackson.databind.ObjectMapper; 19 import com.fasterxml.jackson.databind.ObjectMapper;
19 import com.fasterxml.jackson.databind.node.ObjectNode; 20 import com.fasterxml.jackson.databind.node.ObjectNode;
20 import org.apache.karaf.shell.commands.Argument; 21 import org.apache.karaf.shell.commands.Argument;
...@@ -51,17 +52,17 @@ public class NetworkConfigCommand extends AbstractShellCommand { ...@@ -51,17 +52,17 @@ public class NetworkConfigCommand extends AbstractShellCommand {
51 @Override 52 @Override
52 protected void execute() { 53 protected void execute() {
53 service = get(NetworkConfigService.class); 54 service = get(NetworkConfigService.class);
54 - ObjectNode root = new ObjectMapper().createObjectNode(); 55 + JsonNode root = new ObjectMapper().createObjectNode();
55 if (isNullOrEmpty(subjectKey)) { 56 if (isNullOrEmpty(subjectKey)) {
56 - addAll(root); 57 + addAll((ObjectNode) root);
57 } else { 58 } else {
58 SubjectFactory subjectFactory = service.getSubjectFactory(subjectKey); 59 SubjectFactory subjectFactory = service.getSubjectFactory(subjectKey);
59 if (isNullOrEmpty(subject)) { 60 if (isNullOrEmpty(subject)) {
60 - addSubjectClass(root, subjectFactory); 61 + addSubjectClass((ObjectNode) root, subjectFactory);
61 } else { 62 } else {
62 Object s = subjectFactory.createSubject(subject); 63 Object s = subjectFactory.createSubject(subject);
63 if (isNullOrEmpty(configKey)) { 64 if (isNullOrEmpty(configKey)) {
64 - addSubject(root, s); 65 + addSubject((ObjectNode) root, s);
65 } else { 66 } else {
66 root = getSubjectConfig(getConfig(s, subjectKey, configKey)); 67 root = getSubjectConfig(getConfig(s, subjectKey, configKey));
67 } 68 }
...@@ -89,7 +90,7 @@ public class NetworkConfigCommand extends AbstractShellCommand { ...@@ -89,7 +90,7 @@ public class NetworkConfigCommand extends AbstractShellCommand {
89 service.getConfigs(s).forEach(c -> root.set(c.key(), c.node())); 90 service.getConfigs(s).forEach(c -> root.set(c.key(), c.node()));
90 } 91 }
91 92
92 - private ObjectNode getSubjectConfig(Config config) { 93 + private JsonNode getSubjectConfig(Config config) {
93 return config != null ? config.node() : null; 94 return config != null ? config.node() : null;
94 } 95 }
95 96
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.net.config; 16 package org.onosproject.net.config;
17 17
18 +import com.fasterxml.jackson.databind.JsonNode;
18 import com.fasterxml.jackson.databind.ObjectMapper; 19 import com.fasterxml.jackson.databind.ObjectMapper;
19 import com.fasterxml.jackson.databind.node.ArrayNode; 20 import com.fasterxml.jackson.databind.node.ArrayNode;
20 import com.fasterxml.jackson.databind.node.ObjectNode; 21 import com.fasterxml.jackson.databind.node.ObjectNode;
...@@ -41,8 +42,12 @@ public abstract class Config<S> { ...@@ -41,8 +42,12 @@ public abstract class Config<S> {
41 42
42 protected S subject; 43 protected S subject;
43 protected String key; 44 protected String key;
44 - protected ObjectNode node; 45 +
46 + protected JsonNode node;
47 + protected ObjectNode object;
48 + protected ArrayNode array;
45 protected ObjectMapper mapper; 49 protected ObjectMapper mapper;
50 +
46 protected ConfigApplyDelegate delegate; 51 protected ConfigApplyDelegate delegate;
47 52
48 /** 53 /**
...@@ -50,15 +55,17 @@ public abstract class Config<S> { ...@@ -50,15 +55,17 @@ public abstract class Config<S> {
50 * 55 *
51 * @param subject configuration subject 56 * @param subject configuration subject
52 * @param key configuration key 57 * @param key configuration key
53 - * @param node JSON object node where configuration data is stored 58 + * @param node JSON node where configuration data is stored
54 * @param mapper JSON object mapper 59 * @param mapper JSON object mapper
55 * @param delegate delegate context 60 * @param delegate delegate context
56 */ 61 */
57 - public void init(S subject, String key, ObjectNode node, ObjectMapper mapper, 62 + public void init(S subject, String key, JsonNode node, ObjectMapper mapper,
58 ConfigApplyDelegate delegate) { 63 ConfigApplyDelegate delegate) {
59 this.subject = checkNotNull(subject); 64 this.subject = checkNotNull(subject);
60 this.key = key; 65 this.key = key;
61 this.node = checkNotNull(node); 66 this.node = checkNotNull(node);
67 + this.object = node instanceof ObjectNode ? (ObjectNode) node : null;
68 + this.array = node instanceof ArrayNode ? (ArrayNode) node : null;
62 this.mapper = checkNotNull(mapper); 69 this.mapper = checkNotNull(mapper);
63 this.delegate = checkNotNull(delegate); 70 this.delegate = checkNotNull(delegate);
64 } 71 }
...@@ -88,8 +95,8 @@ public abstract class Config<S> { ...@@ -88,8 +95,8 @@ public abstract class Config<S> {
88 * 95 *
89 * @return JSON node backing the configuration 96 * @return JSON node backing the configuration
90 */ 97 */
91 - public ObjectNode node() { 98 + public JsonNode node() {
92 - return node; 99 + return object;
93 } 100 }
94 101
95 /** 102 /**
...@@ -110,7 +117,7 @@ public abstract class Config<S> { ...@@ -110,7 +117,7 @@ public abstract class Config<S> {
110 * @return property value or default value 117 * @return property value or default value
111 */ 118 */
112 protected String get(String name, String defaultValue) { 119 protected String get(String name, String defaultValue) {
113 - return node.path(name).asText(defaultValue); 120 + return object.path(name).asText(defaultValue);
114 } 121 }
115 122
116 /** 123 /**
...@@ -122,9 +129,9 @@ public abstract class Config<S> { ...@@ -122,9 +129,9 @@ public abstract class Config<S> {
122 */ 129 */
123 protected Config<S> setOrClear(String name, String value) { 130 protected Config<S> setOrClear(String name, String value) {
124 if (value != null) { 131 if (value != null) {
125 - node.put(name, value); 132 + object.put(name, value);
126 } else { 133 } else {
127 - node.remove(name); 134 + object.remove(name);
128 } 135 }
129 return this; 136 return this;
130 } 137 }
...@@ -137,7 +144,7 @@ public abstract class Config<S> { ...@@ -137,7 +144,7 @@ public abstract class Config<S> {
137 * @return property value or default value 144 * @return property value or default value
138 */ 145 */
139 protected boolean get(String name, boolean defaultValue) { 146 protected boolean get(String name, boolean defaultValue) {
140 - return node.path(name).asBoolean(defaultValue); 147 + return object.path(name).asBoolean(defaultValue);
141 } 148 }
142 149
143 /** 150 /**
...@@ -149,9 +156,9 @@ public abstract class Config<S> { ...@@ -149,9 +156,9 @@ public abstract class Config<S> {
149 */ 156 */
150 protected Config<S> setOrClear(String name, Boolean value) { 157 protected Config<S> setOrClear(String name, Boolean value) {
151 if (value != null) { 158 if (value != null) {
152 - node.put(name, value.booleanValue()); 159 + object.put(name, value.booleanValue());
153 } else { 160 } else {
154 - node.remove(name); 161 + object.remove(name);
155 } 162 }
156 return this; 163 return this;
157 } 164 }
...@@ -164,7 +171,7 @@ public abstract class Config<S> { ...@@ -164,7 +171,7 @@ public abstract class Config<S> {
164 * @return property value or default value 171 * @return property value or default value
165 */ 172 */
166 protected int get(String name, int defaultValue) { 173 protected int get(String name, int defaultValue) {
167 - return node.path(name).asInt(defaultValue); 174 + return object.path(name).asInt(defaultValue);
168 } 175 }
169 176
170 /** 177 /**
...@@ -176,9 +183,9 @@ public abstract class Config<S> { ...@@ -176,9 +183,9 @@ public abstract class Config<S> {
176 */ 183 */
177 protected Config<S> setOrClear(String name, Integer value) { 184 protected Config<S> setOrClear(String name, Integer value) {
178 if (value != null) { 185 if (value != null) {
179 - node.put(name, value.intValue()); 186 + object.put(name, value.intValue());
180 } else { 187 } else {
181 - node.remove(name); 188 + object.remove(name);
182 } 189 }
183 return this; 190 return this;
184 } 191 }
...@@ -191,7 +198,7 @@ public abstract class Config<S> { ...@@ -191,7 +198,7 @@ public abstract class Config<S> {
191 * @return property value or default value 198 * @return property value or default value
192 */ 199 */
193 protected long get(String name, long defaultValue) { 200 protected long get(String name, long defaultValue) {
194 - return node.path(name).asLong(defaultValue); 201 + return object.path(name).asLong(defaultValue);
195 } 202 }
196 203
197 /** 204 /**
...@@ -203,9 +210,9 @@ public abstract class Config<S> { ...@@ -203,9 +210,9 @@ public abstract class Config<S> {
203 */ 210 */
204 protected Config<S> setOrClear(String name, Long value) { 211 protected Config<S> setOrClear(String name, Long value) {
205 if (value != null) { 212 if (value != null) {
206 - node.put(name, value.longValue()); 213 + object.put(name, value.longValue());
207 } else { 214 } else {
208 - node.remove(name); 215 + object.remove(name);
209 } 216 }
210 return this; 217 return this;
211 } 218 }
...@@ -218,7 +225,7 @@ public abstract class Config<S> { ...@@ -218,7 +225,7 @@ public abstract class Config<S> {
218 * @return property value or default value 225 * @return property value or default value
219 */ 226 */
220 protected double get(String name, double defaultValue) { 227 protected double get(String name, double defaultValue) {
221 - return node.path(name).asDouble(defaultValue); 228 + return object.path(name).asDouble(defaultValue);
222 } 229 }
223 230
224 /** 231 /**
...@@ -230,9 +237,9 @@ public abstract class Config<S> { ...@@ -230,9 +237,9 @@ public abstract class Config<S> {
230 */ 237 */
231 protected Config<S> setOrClear(String name, Double value) { 238 protected Config<S> setOrClear(String name, Double value) {
232 if (value != null) { 239 if (value != null) {
233 - node.put(name, value.doubleValue()); 240 + object.put(name, value.doubleValue());
234 } else { 241 } else {
235 - node.remove(name); 242 + object.remove(name);
236 } 243 }
237 return this; 244 return this;
238 } 245 }
...@@ -247,7 +254,7 @@ public abstract class Config<S> { ...@@ -247,7 +254,7 @@ public abstract class Config<S> {
247 * @return property value or default value 254 * @return property value or default value
248 */ 255 */
249 protected <E extends Enum<E>> E get(String name, E defaultValue, Class<E> enumClass) { 256 protected <E extends Enum<E>> E get(String name, E defaultValue, Class<E> enumClass) {
250 - return Enum.valueOf(enumClass, node.path(name).asText(defaultValue.toString())); 257 + return Enum.valueOf(enumClass, object.path(name).asText(defaultValue.toString()));
251 } 258 }
252 259
253 /** 260 /**
...@@ -260,9 +267,9 @@ public abstract class Config<S> { ...@@ -260,9 +267,9 @@ public abstract class Config<S> {
260 */ 267 */
261 protected <E extends Enum> Config<S> setOrClear(String name, E value) { 268 protected <E extends Enum> Config<S> setOrClear(String name, E value) {
262 if (value != null) { 269 if (value != null) {
263 - node.put(name, value.toString()); 270 + object.put(name, value.toString());
264 } else { 271 } else {
265 - node.remove(name); 272 + object.remove(name);
266 } 273 }
267 return this; 274 return this;
268 } 275 }
...@@ -277,7 +284,7 @@ public abstract class Config<S> { ...@@ -277,7 +284,7 @@ public abstract class Config<S> {
277 */ 284 */
278 protected <T> List<T> getList(String name, Function<String, T> function) { 285 protected <T> List<T> getList(String name, Function<String, T> function) {
279 List<T> list = Lists.newArrayList(); 286 List<T> list = Lists.newArrayList();
280 - ArrayNode arrayNode = (ArrayNode) node.path(name); 287 + ArrayNode arrayNode = (ArrayNode) object.path(name);
281 arrayNode.forEach(i -> list.add(function.apply(i.asText()))); 288 arrayNode.forEach(i -> list.add(function.apply(i.asText())));
282 return list; 289 return list;
283 } 290 }
...@@ -293,11 +300,11 @@ public abstract class Config<S> { ...@@ -293,11 +300,11 @@ public abstract class Config<S> {
293 */ 300 */
294 protected <T> Config<S> setOrClear(String name, Collection<T> collection) { 301 protected <T> Config<S> setOrClear(String name, Collection<T> collection) {
295 if (collection == null) { 302 if (collection == null) {
296 - node.remove(name); 303 + object.remove(name);
297 } else { 304 } else {
298 ArrayNode arrayNode = mapper.createArrayNode(); 305 ArrayNode arrayNode = mapper.createArrayNode();
299 collection.forEach(i -> arrayNode.add(i.toString())); 306 collection.forEach(i -> arrayNode.add(i.toString()));
300 - node.set(name, arrayNode); 307 + object.set(name, arrayNode);
301 } 308 }
302 return this; 309 return this;
303 } 310 }
......
...@@ -30,6 +30,7 @@ public abstract class ConfigFactory<S, C extends Config<S>> { ...@@ -30,6 +30,7 @@ public abstract class ConfigFactory<S, C extends Config<S>> {
30 private final SubjectFactory<S> subjectFactory; 30 private final SubjectFactory<S> subjectFactory;
31 private final Class<C> configClass; 31 private final Class<C> configClass;
32 private final String configKey; 32 private final String configKey;
33 + private final boolean isList;
33 34
34 /** 35 /**
35 * Creates a new configuration factory for the specified class of subjects 36 * Creates a new configuration factory for the specified class of subjects
...@@ -38,14 +39,37 @@ public abstract class ConfigFactory<S, C extends Config<S>> { ...@@ -38,14 +39,37 @@ public abstract class ConfigFactory<S, C extends Config<S>> {
38 * composite JSON trees. 39 * composite JSON trees.
39 * 40 *
40 * @param subjectFactory subject factory 41 * @param subjectFactory subject factory
41 - * @param configClass configuration class 42 + * @param configClass configuration class
42 - * @param configKey configuration class key 43 + * @param configKey configuration class key
43 */ 44 */
44 protected ConfigFactory(SubjectFactory<S> subjectFactory, 45 protected ConfigFactory(SubjectFactory<S> subjectFactory,
45 Class<C> configClass, String configKey) { 46 Class<C> configClass, String configKey) {
47 + this(subjectFactory, configClass, configKey, false);
48 + }
49 +
50 + /**
51 + * Creates a new configuration factory for the specified class of subjects
52 + * capable of generating the configurations of the specified class. The
53 + * subject and configuration class keys are used merely as keys for use in
54 + * composite JSON trees.
55 + * <p>
56 + * Note that configurations backed by JSON array are not easily extensible
57 + * at the top-level as they are inherently limited to holding an ordered
58 + * list of items.
59 + * </p>
60 + *
61 + * @param subjectFactory subject factory
62 + * @param configClass configuration class
63 + * @param configKey configuration class key
64 + * @param isList true to indicate backing by JSON array
65 + */
66 + protected ConfigFactory(SubjectFactory<S> subjectFactory,
67 + Class<C> configClass, String configKey,
68 + boolean isList) {
46 this.subjectFactory = subjectFactory; 69 this.subjectFactory = subjectFactory;
47 this.configClass = configClass; 70 this.configClass = configClass;
48 this.configKey = configKey; 71 this.configKey = configKey;
72 + this.isList = isList;
49 } 73 }
50 74
51 /** 75 /**
...@@ -85,4 +109,14 @@ public abstract class ConfigFactory<S, C extends Config<S>> { ...@@ -85,4 +109,14 @@ public abstract class ConfigFactory<S, C extends Config<S>> {
85 */ 109 */
86 public abstract C createConfig(); 110 public abstract C createConfig();
87 111
112 + /**
113 + * Indicates whether the configuration is a list and should be backed by
114 + * a JSON array rather than JSON object.
115 + *
116 + * @return true if backed by JSON array
117 + */
118 + public boolean isList() {
119 + return isList;
120 + }
121 +
88 } 122 }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 */ 15 */
16 package org.onosproject.net.config; 16 package org.onosproject.net.config;
17 17
18 -import com.fasterxml.jackson.databind.node.ObjectNode; 18 +import com.fasterxml.jackson.databind.JsonNode;
19 import com.google.common.annotations.Beta; 19 import com.google.common.annotations.Beta;
20 import org.onosproject.event.ListenerService; 20 import org.onosproject.event.ListenerService;
21 21
...@@ -130,7 +130,7 @@ public interface NetworkConfigService ...@@ -130,7 +130,7 @@ public interface NetworkConfigService
130 * @return configuration or null if one is not available 130 * @return configuration or null if one is not available
131 */ 131 */
132 <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, 132 <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass,
133 - ObjectNode json); 133 + JsonNode json);
134 134
135 /** 135 /**
136 * Clears any configuration for the specified subject and configuration 136 * Clears any configuration for the specified subject and configuration
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 */ 15 */
16 package org.onosproject.net.config; 16 package org.onosproject.net.config;
17 17
18 -import com.fasterxml.jackson.databind.node.ObjectNode; 18 +import com.fasterxml.jackson.databind.JsonNode;
19 import org.onosproject.store.Store; 19 import org.onosproject.store.Store;
20 20
21 import java.util.Set; 21 import java.util.Set;
...@@ -115,7 +115,7 @@ public interface NetworkConfigStore extends Store<NetworkConfigEvent, NetworkCon ...@@ -115,7 +115,7 @@ public interface NetworkConfigStore extends Store<NetworkConfigEvent, NetworkCon
115 * @return configuration object 115 * @return configuration object
116 */ 116 */
117 <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, 117 <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass,
118 - ObjectNode json); 118 + JsonNode json);
119 119
120 /** 120 /**
121 * Clears the configuration of the given class for the specified subject. 121 * Clears the configuration of the given class for the specified subject.
......
...@@ -33,7 +33,7 @@ public class OpticalPortConfig extends Config<ConnectPoint> { ...@@ -33,7 +33,7 @@ public class OpticalPortConfig extends Config<ConnectPoint> {
33 * @return the port type, or null if invalid or unset 33 * @return the port type, or null if invalid or unset
34 */ 34 */
35 public Port.Type type() { 35 public Port.Type type() {
36 - JsonNode type = node.path(TYPE); 36 + JsonNode type = object.path(TYPE);
37 if (type.isMissingNode()) { 37 if (type.isMissingNode()) {
38 return null; 38 return null;
39 } 39 }
...@@ -72,7 +72,7 @@ public class OpticalPortConfig extends Config<ConnectPoint> { ...@@ -72,7 +72,7 @@ public class OpticalPortConfig extends Config<ConnectPoint> {
72 } 72 }
73 73
74 private String getStringValue(String field) { 74 private String getStringValue(String field) {
75 - JsonNode name = node.path(field); 75 + JsonNode name = object.path(field);
76 return name.isMissingNode() ? "" : name.asText(); 76 return name.isMissingNode() ? "" : name.asText();
77 } 77 }
78 78
...@@ -84,7 +84,7 @@ public class OpticalPortConfig extends Config<ConnectPoint> { ...@@ -84,7 +84,7 @@ public class OpticalPortConfig extends Config<ConnectPoint> {
84 * @return an Optional that may contain a frequency value. 84 * @return an Optional that may contain a frequency value.
85 */ 85 */
86 public Optional<Long> staticLambda() { 86 public Optional<Long> staticLambda() {
87 - JsonNode sl = node.path(STATIC_LAMBDA); 87 + JsonNode sl = object.path(STATIC_LAMBDA);
88 if (sl.isMissingNode()) { 88 if (sl.isMissingNode()) {
89 return Optional.empty(); 89 return Optional.empty();
90 } 90 }
...@@ -98,7 +98,7 @@ public class OpticalPortConfig extends Config<ConnectPoint> { ...@@ -98,7 +98,7 @@ public class OpticalPortConfig extends Config<ConnectPoint> {
98 * @return a port speed value whose default is 0. 98 * @return a port speed value whose default is 0.
99 */ 99 */
100 public Optional<Integer> speed() { 100 public Optional<Integer> speed() {
101 - JsonNode s = node.path(SPEED); 101 + JsonNode s = object.path(SPEED);
102 if (s.isMissingNode()) { 102 if (s.isMissingNode()) {
103 return Optional.empty(); 103 return Optional.empty();
104 } 104 }
......
1 -
2 /* 1 /*
3 * Copyright 2015 Open Networking Laboratory 2 * Copyright 2015 Open Networking Laboratory
4 * 3 *
...@@ -14,10 +13,9 @@ ...@@ -14,10 +13,9 @@
14 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
15 * limitations under the License. 14 * limitations under the License.
16 */ 15 */
17 -
18 package org.onosproject.net.config; 16 package org.onosproject.net.config;
19 17
20 -import com.fasterxml.jackson.databind.node.ObjectNode; 18 +import com.fasterxml.jackson.databind.JsonNode;
21 19
22 import java.util.Set; 20 import java.util.Set;
23 21
...@@ -71,7 +69,7 @@ public class NetworkConfigServiceAdapter implements NetworkConfigService { ...@@ -71,7 +69,7 @@ public class NetworkConfigServiceAdapter implements NetworkConfigService {
71 } 69 }
72 70
73 @Override 71 @Override
74 - public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, ObjectNode json) { 72 + public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
75 return null; 73 return null;
76 } 74 }
77 75
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 */ 15 */
16 package org.onosproject.net.config.impl; 16 package org.onosproject.net.config.impl;
17 17
18 -import com.fasterxml.jackson.databind.node.ObjectNode; 18 +import com.fasterxml.jackson.databind.JsonNode;
19 import com.google.common.collect.ImmutableSet; 19 import com.google.common.collect.ImmutableSet;
20 import com.google.common.collect.Maps; 20 import com.google.common.collect.Maps;
21 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
...@@ -197,7 +197,7 @@ public class NetworkConfigManager ...@@ -197,7 +197,7 @@ public class NetworkConfigManager
197 } 197 }
198 198
199 @Override 199 @Override
200 - public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, ObjectNode json) { 200 + public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
201 checkNotNull(subject, NULL_SUBJECT_MSG); 201 checkNotNull(subject, NULL_SUBJECT_MSG);
202 checkNotNull(configClass, NULL_CCLASS_MSG); 202 checkNotNull(configClass, NULL_CCLASS_MSG);
203 return store.applyConfig(subject, configClass, json); 203 return store.applyConfig(subject, configClass, json);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.store.config.impl; 16 package org.onosproject.store.config.impl;
17 17
18 +import com.fasterxml.jackson.databind.JsonNode;
18 import com.fasterxml.jackson.databind.ObjectMapper; 19 import com.fasterxml.jackson.databind.ObjectMapper;
19 import com.fasterxml.jackson.databind.node.ArrayNode; 20 import com.fasterxml.jackson.databind.node.ArrayNode;
20 import com.fasterxml.jackson.databind.node.BooleanNode; 21 import com.fasterxml.jackson.databind.node.BooleanNode;
...@@ -77,12 +78,12 @@ public class DistributedNetworkConfigStore ...@@ -77,12 +78,12 @@ public class DistributedNetworkConfigStore
77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 protected StorageService storageService; 79 protected StorageService storageService;
79 80
80 - private ConsistentMap<ConfigKey, ObjectNode> configs; 81 + private ConsistentMap<ConfigKey, JsonNode> configs;
81 82
82 private final Map<String, ConfigFactory> factoriesByConfig = Maps.newConcurrentMap(); 83 private final Map<String, ConfigFactory> factoriesByConfig = Maps.newConcurrentMap();
83 private final ObjectMapper mapper = new ObjectMapper(); 84 private final ObjectMapper mapper = new ObjectMapper();
84 private final ConfigApplyDelegate applyDelegate = new InternalApplyDelegate(); 85 private final ConfigApplyDelegate applyDelegate = new InternalApplyDelegate();
85 - private final MapEventListener<ConfigKey, ObjectNode> listener = new InternalMapListener(); 86 + private final MapEventListener<ConfigKey, JsonNode> listener = new InternalMapListener();
86 87
87 @Activate 88 @Activate
88 public void activate() { 89 public void activate() {
...@@ -93,7 +94,7 @@ public class DistributedNetworkConfigStore ...@@ -93,7 +94,7 @@ public class DistributedNetworkConfigStore
93 TextNode.class, BooleanNode.class, 94 TextNode.class, BooleanNode.class,
94 LongNode.class, DoubleNode.class, ShortNode.class, IntNode.class); 95 LongNode.class, DoubleNode.class, ShortNode.class, IntNode.class);
95 96
96 - configs = storageService.<ConfigKey, ObjectNode>consistentMapBuilder() 97 + configs = storageService.<ConfigKey, JsonNode>consistentMapBuilder()
97 .withSerializer(Serializer.using(kryoBuilder.build())) 98 .withSerializer(Serializer.using(kryoBuilder.build()))
98 .withName("onos-network-configs") 99 .withName("onos-network-configs")
99 .withRelaxedReadConsistency() 100 .withRelaxedReadConsistency()
...@@ -168,21 +169,24 @@ public class DistributedNetworkConfigStore ...@@ -168,21 +169,24 @@ public class DistributedNetworkConfigStore
168 @Override 169 @Override
169 public <S, T extends Config<S>> T getConfig(S subject, Class<T> configClass) { 170 public <S, T extends Config<S>> T getConfig(S subject, Class<T> configClass) {
170 // TODO: need to identify and address the root cause for timeouts. 171 // TODO: need to identify and address the root cause for timeouts.
171 - Versioned<ObjectNode> json = Tools.retryable(configs::get, ConsistentMapException.class, 1, MAX_BACKOFF) 172 + Versioned<JsonNode> json = Tools.retryable(configs::get, ConsistentMapException.class, 1, MAX_BACKOFF)
172 - .apply(key(subject, configClass)); 173 + .apply(key(subject, configClass));
173 return json != null ? createConfig(subject, configClass, json.value()) : null; 174 return json != null ? createConfig(subject, configClass, json.value()) : null;
174 } 175 }
175 176
176 177
177 @Override 178 @Override
178 public <S, C extends Config<S>> C createConfig(S subject, Class<C> configClass) { 179 public <S, C extends Config<S>> C createConfig(S subject, Class<C> configClass) {
179 - Versioned<ObjectNode> json = configs.computeIfAbsent(key(subject, configClass), 180 + ConfigFactory<S, C> factory = getConfigFactory(configClass);
180 - k -> mapper.createObjectNode()); 181 + Versioned<JsonNode> json = configs.computeIfAbsent(key(subject, configClass),
182 + k -> factory.isList() ?
183 + mapper.createArrayNode() :
184 + mapper.createObjectNode());
181 return createConfig(subject, configClass, json.value()); 185 return createConfig(subject, configClass, json.value());
182 } 186 }
183 187
184 @Override 188 @Override
185 - public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, ObjectNode json) { 189 + public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
186 return createConfig(subject, configClass, 190 return createConfig(subject, configClass,
187 configs.putAndGet(key(subject, configClass), json).value()); 191 configs.putAndGet(key(subject, configClass), json).value());
188 } 192 }
...@@ -203,7 +207,7 @@ public class DistributedNetworkConfigStore ...@@ -203,7 +207,7 @@ public class DistributedNetworkConfigStore
203 */ 207 */
204 @SuppressWarnings("unchecked") 208 @SuppressWarnings("unchecked")
205 private <S, C extends Config<S>> C createConfig(S subject, Class<C> configClass, 209 private <S, C extends Config<S>> C createConfig(S subject, Class<C> configClass,
206 - ObjectNode json) { 210 + JsonNode json) {
207 if (json != null) { 211 if (json != null) {
208 ConfigFactory<S, C> factory = factoriesByConfig.get(configClass.getName()); 212 ConfigFactory<S, C> factory = factoriesByConfig.get(configClass.getName());
209 if (factory != null) { 213 if (factory != null) {
...@@ -259,9 +263,9 @@ public class DistributedNetworkConfigStore ...@@ -259,9 +263,9 @@ public class DistributedNetworkConfigStore
259 } 263 }
260 } 264 }
261 265
262 - private class InternalMapListener implements MapEventListener<ConfigKey, ObjectNode> { 266 + private class InternalMapListener implements MapEventListener<ConfigKey, JsonNode> {
263 @Override 267 @Override
264 - public void event(MapEvent<ConfigKey, ObjectNode> event) { 268 + public void event(MapEvent<ConfigKey, JsonNode> event) {
265 NetworkConfigEvent.Type type; 269 NetworkConfigEvent.Type type;
266 switch (event.type()) { 270 switch (event.type()) {
267 case INSERT: 271 case INSERT:
......
...@@ -50,7 +50,8 @@ public class InterfaceConfig extends Config<ConnectPoint> { ...@@ -50,7 +50,8 @@ public class InterfaceConfig extends Config<ConnectPoint> {
50 Set<Interface> interfaces = Sets.newHashSet(); 50 Set<Interface> interfaces = Sets.newHashSet();
51 51
52 try { 52 try {
53 - for (JsonNode intfNode : node.path(INTERFACES)) { 53 + // TODO: rework this to take advantage of ArrayNode backing
54 + for (JsonNode intfNode : object.path(INTERFACES)) {
54 Set<InterfaceIpAddress> ips = getIps(intfNode); 55 Set<InterfaceIpAddress> ips = getIps(intfNode);
55 if (ips.isEmpty()) { 56 if (ips.isEmpty()) {
56 throw new ConfigException(IP_MISSING_ERROR); 57 throw new ConfigException(IP_MISSING_ERROR);
......