Simon Hunt

CORD Subscriber GUI - XosFunction mementos now stored inside each SubscriberUser…

… to capture the parameter state per user.

Change-Id: I678249f63a68172db66a5d3faa0b1747c670bf6e
...@@ -26,6 +26,9 @@ import org.onosproject.cord.gui.model.BundleFactory; ...@@ -26,6 +26,9 @@ import org.onosproject.cord.gui.model.BundleFactory;
26 import org.onosproject.cord.gui.model.JsonFactory; 26 import org.onosproject.cord.gui.model.JsonFactory;
27 import org.onosproject.cord.gui.model.SubscriberUser; 27 import org.onosproject.cord.gui.model.SubscriberUser;
28 import org.onosproject.cord.gui.model.UserFactory; 28 import org.onosproject.cord.gui.model.UserFactory;
29 +import org.onosproject.cord.gui.model.XosFunction;
30 +import org.onosproject.cord.gui.model.XosFunctionDescriptor;
31 +import org.onosproject.cord.gui.model.XosFunctionFactory;
29 32
30 import java.util.ArrayList; 33 import java.util.ArrayList;
31 import java.util.List; 34 import java.util.List;
...@@ -62,12 +65,21 @@ public class CordModelCache extends JsonFactory { ...@@ -62,12 +65,21 @@ public class CordModelCache extends JsonFactory {
62 * Used to initialize users for the demo. These are currently fake. 65 * Used to initialize users for the demo. These are currently fake.
63 */ 66 */
64 public void initUsers() { 67 public void initUsers() {
65 - users.add(new SubscriberUser(1, "Mom's MacBook", MAC_1)); 68 + users.add(createUser(1, "Mom's MacBook", MAC_1));
66 - users.add(new SubscriberUser(2, "Dad's iPad", MAC_2)); 69 + users.add(createUser(2, "Dad's iPad", MAC_2));
67 - users.add(new SubscriberUser(3, "Dick's laptop", MAC_3)); 70 + users.add(createUser(3, "Dick's laptop", MAC_3));
68 - users.add(new SubscriberUser(4, "Jane's laptop", MAC_4)); 71 + users.add(createUser(4, "Jane's laptop", MAC_4));
69 } 72 }
70 73
74 + private SubscriberUser createUser(int uid, String name, String mac) {
75 + SubscriberUser user = new SubscriberUser(uid, name, mac);
76 + for (XosFunction f: currentBundle.functions()) {
77 + user.setMemento(f.descriptor(), f.createMemento());
78 + }
79 + return user;
80 + }
81 +
82 +
71 /** 83 /**
72 * Returns the currently selected bundle. 84 * Returns the currently selected bundle.
73 * 85 *
...@@ -84,10 +96,20 @@ public class CordModelCache extends JsonFactory { ...@@ -84,10 +96,20 @@ public class CordModelCache extends JsonFactory {
84 * @throws IllegalArgumentException if bundle ID is unknown 96 * @throws IllegalArgumentException if bundle ID is unknown
85 */ 97 */
86 public void setCurrentBundle(String bundleId) { 98 public void setCurrentBundle(String bundleId) {
87 - BundleDescriptor bdesc = BundleFactory.bundleFromId(bundleId); 99 + BundleDescriptor bd = BundleFactory.bundleFromId(bundleId);
88 - currentBundle = new Bundle(bdesc); 100 + currentBundle = new Bundle(bd);
101 + // update the user mementos
102 + for (SubscriberUser user: users) {
103 + user.clearMementos();
104 + for (XosFunction f: currentBundle.functions()) {
105 + user.setMemento(f.descriptor(), f.createMemento());
106 + }
107 + }
108 +
109 + // TODO: tell XOS which functions are enabled / disabled
89 } 110 }
90 111
112 +
91 /** 113 /**
92 * Returns the list of current users for this subscriber account. 114 * Returns the list of current users for this subscriber account.
93 * 115 *
...@@ -97,6 +119,25 @@ public class CordModelCache extends JsonFactory { ...@@ -97,6 +119,25 @@ public class CordModelCache extends JsonFactory {
97 return ImmutableList.copyOf(users); 119 return ImmutableList.copyOf(users);
98 } 120 }
99 121
122 + /**
123 + * Applies a function parameter change for a user.
124 + *
125 + * @param userId user identifier
126 + * @param funcId function identifier
127 + * @param param function parameter to change
128 + * @param value new value for function parameter
129 + */
130 + public void applyPerUserParam(String userId, String funcId,
131 + String param, String value) {
132 + // FIXME: this is not right yet...
133 + int uid = Integer.parseInt(userId);
134 + XosFunctionDescriptor xfd =
135 + XosFunctionDescriptor.valueOf(funcId.toUpperCase());
136 + XosFunctionFactory.apply(xfd, uid, param, value);
137 + }
138 +
139 + // =============
140 +
100 private ArrayNode userJsonArray() { 141 private ArrayNode userJsonArray() {
101 ArrayNode userList = arrayNode(); 142 ArrayNode userList = arrayNode();
102 for (SubscriberUser user: users) { 143 for (SubscriberUser user: users) {
......
...@@ -55,9 +55,19 @@ public class CordWebResource { ...@@ -55,9 +55,19 @@ public class CordWebResource {
55 @GET 55 @GET
56 @Produces(MediaType.APPLICATION_JSON) 56 @Produces(MediaType.APPLICATION_JSON)
57 @Path("bundle/{id}") 57 @Path("bundle/{id}")
58 - @Deprecated
59 public Response bundle(@PathParam("id") String bundleId) { 58 public Response bundle(@PathParam("id") String bundleId) {
60 CordModelCache.INSTANCE.setCurrentBundle(bundleId); 59 CordModelCache.INSTANCE.setCurrentBundle(bundleId);
61 return bundle(); 60 return bundle();
62 } 61 }
62 +
63 + @GET
64 + @Produces(MediaType.APPLICATION_JSON)
65 + @Path("users/{id}/apply/{func}/{param}/{value}")
66 + public Response bundle(@PathParam("id") String userId,
67 + @PathParam("func") String funcId,
68 + @PathParam("param") String param,
69 + @PathParam("value") String value) {
70 + CordModelCache.INSTANCE.applyPerUserParam(userId, funcId, param, value);
71 + return users();
72 + }
63 } 73 }
......
...@@ -17,11 +17,17 @@ ...@@ -17,11 +17,17 @@
17 17
18 package org.onosproject.cord.gui.model; 18 package org.onosproject.cord.gui.model;
19 19
20 +import com.google.common.collect.ImmutableSet;
21 +
22 +import java.util.HashSet;
23 +import java.util.Set;
24 +
20 /** 25 /**
21 * Encapsulates a bundle, including current state. 26 * Encapsulates a bundle, including current state.
22 */ 27 */
23 public class Bundle { 28 public class Bundle {
24 private final BundleDescriptor bundleDescriptor; 29 private final BundleDescriptor bundleDescriptor;
30 + private final Set<XosFunction> functions;
25 31
26 /** 32 /**
27 * Constructs a new bundle instance. 33 * Constructs a new bundle instance.
...@@ -30,6 +36,7 @@ public class Bundle { ...@@ -30,6 +36,7 @@ public class Bundle {
30 */ 36 */
31 public Bundle(BundleDescriptor bundleDescriptor) { 37 public Bundle(BundleDescriptor bundleDescriptor) {
32 this.bundleDescriptor = bundleDescriptor; 38 this.bundleDescriptor = bundleDescriptor;
39 + this.functions = initFunctions();
33 } 40 }
34 41
35 /** 42 /**
...@@ -41,4 +48,39 @@ public class Bundle { ...@@ -41,4 +48,39 @@ public class Bundle {
41 return bundleDescriptor; 48 return bundleDescriptor;
42 } 49 }
43 50
51 + /**
52 + * Returns the set of function instances for this bundle.
53 + *
54 + * @return the functions
55 + */
56 + public Set<XosFunction> functions() {
57 + return ImmutableSet.copyOf(functions);
58 + }
59 +
60 + /**
61 + * Creates an initial set of function instances.
62 + *
63 + * @return initial function instances
64 + */
65 + private Set<XosFunction> initFunctions() {
66 + Set<XosFunction> funcs = new HashSet<XosFunction>();
67 + for (XosFunctionDescriptor xfd: bundleDescriptor.functions()) {
68 + funcs.add(createFunction(xfd));
69 + }
70 + return funcs;
71 + }
72 +
73 + private XosFunction createFunction(XosFunctionDescriptor xfd) {
74 + XosFunction func;
75 + switch (xfd) {
76 + case URL_FILTER:
77 + func = new UrlFilterFunction(xfd);
78 + break;
79 +
80 + default:
81 + func = new DefaultXosFunction(xfd);
82 + break;
83 + }
84 + return func;
85 + }
44 } 86 }
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + *
16 + */
17 +
18 +package org.onosproject.cord.gui.model;
19 +
20 +import com.fasterxml.jackson.databind.ObjectMapper;
21 +
22 +/**
23 + * Default XOS function implementation, that does not have any parameters
24 + * to tweak.
25 + */
26 +public class DefaultXosFunction implements XosFunction {
27 +
28 + protected static final ObjectMapper MAPPER = new ObjectMapper();
29 +
30 + private final XosFunctionDescriptor xfd;
31 +
32 + public DefaultXosFunction(XosFunctionDescriptor xfd) {
33 + this.xfd = xfd;
34 + }
35 +
36 + public XosFunctionDescriptor descriptor() {
37 + return xfd;
38 + }
39 +
40 + /**
41 + * {@inheritDoc}
42 + * <p>
43 + * This default implementation throws an exception.
44 + *
45 + * @param user user to apply the change to
46 + * @param param parameter name
47 + * @param value new parameter value
48 + * @throws UnsupportedOperationException if invoked
49 + */
50 + public void applyParam(SubscriberUser user, String param, String value) {
51 + throw new UnsupportedOperationException();
52 + }
53 +
54 + public Memento createMemento() {
55 + return null;
56 + }
57 +
58 +}
...@@ -26,7 +26,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; ...@@ -26,7 +26,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
26 */ 26 */
27 public abstract class JsonFactory { 27 public abstract class JsonFactory {
28 28
29 - private static final ObjectMapper mapper = new ObjectMapper(); 29 + private static final ObjectMapper MAPPER = new ObjectMapper();
30 30
31 protected static final String ID = "id"; 31 protected static final String ID = "id";
32 protected static final String NAME = "name"; 32 protected static final String NAME = "name";
...@@ -38,7 +38,7 @@ public abstract class JsonFactory { ...@@ -38,7 +38,7 @@ public abstract class JsonFactory {
38 * @return empty object node 38 * @return empty object node
39 */ 39 */
40 protected static ObjectNode objectNode() { 40 protected static ObjectNode objectNode() {
41 - return mapper.createObjectNode(); 41 + return MAPPER.createObjectNode();
42 } 42 }
43 43
44 /** 44 /**
...@@ -47,6 +47,6 @@ public abstract class JsonFactory { ...@@ -47,6 +47,6 @@ public abstract class JsonFactory {
47 * @return empty array node 47 * @return empty array node
48 */ 48 */
49 protected static ArrayNode arrayNode() { 49 protected static ArrayNode arrayNode() {
50 - return mapper.createArrayNode(); 50 + return MAPPER.createArrayNode();
51 } 51 }
52 } 52 }
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
17 17
18 package org.onosproject.cord.gui.model; 18 package org.onosproject.cord.gui.model;
19 19
20 +import java.util.HashMap;
21 +import java.util.Map;
22 +
20 /** 23 /**
21 * Designates a user of a subscriber's account. 24 * Designates a user of a subscriber's account.
22 */ 25 */
...@@ -25,6 +28,9 @@ public class SubscriberUser { ...@@ -25,6 +28,9 @@ public class SubscriberUser {
25 private final String name; 28 private final String name;
26 private final String mac; 29 private final String mac;
27 30
31 + private final Map<XosFunctionDescriptor, XosFunction.Memento> mementos =
32 + new HashMap<XosFunctionDescriptor, XosFunction.Memento>();
33 +
28 /** 34 /**
29 * Constructs a subscriber user from the given parameters. 35 * Constructs a subscriber user from the given parameters.
30 * 36 *
...@@ -64,4 +70,33 @@ public class SubscriberUser { ...@@ -64,4 +70,33 @@ public class SubscriberUser {
64 public String mac() { 70 public String mac() {
65 return mac; 71 return mac;
66 } 72 }
73 +
74 + /**
75 + * Stores a memento for the given XOS function.
76 + *
77 + * @param f XOS function
78 + * @param m memento
79 + */
80 + public void setMemento(XosFunctionDescriptor f, XosFunction.Memento m) {
81 + if (m != null) {
82 + mementos.put(f, m);
83 + }
84 + }
85 +
86 + /**
87 + * Returns the memento stored on this user, for the given XOS function.
88 + *
89 + * @param f XOS function
90 + * @return memento
91 + */
92 + public XosFunction.Memento getMemento(XosFunctionDescriptor f) {
93 + return mementos.get(f);
94 + }
95 +
96 + /**
97 + * Clears the memento map.
98 + */
99 + public void clearMementos() {
100 + mementos.clear();
101 + }
67 } 102 }
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + *
16 + */
17 +
18 +package org.onosproject.cord.gui.model;
19 +
20 +import com.fasterxml.jackson.databind.node.ObjectNode;
21 +
22 +/**
23 + * Specialization of XosFunction for URL filtering.
24 + */
25 +public class UrlFilterFunction extends DefaultXosFunction {
26 +
27 + private static final String LEVEL = "level";
28 +
29 + /**
30 + * Denotes the URL filtering levels available.
31 + */
32 + public enum Level { PG, PG_13, R }
33 +
34 + /**
35 + * The default URL filtering level
36 + */
37 + public static final Level DEFAULT_LEVEL = Level.PG;
38 +
39 + public UrlFilterFunction(XosFunctionDescriptor xfd) {
40 + super(xfd);
41 + }
42 +
43 + @Override
44 + public Memento createMemento() {
45 + return new UrlFilterMemento();
46 + }
47 +
48 + class UrlFilterMemento implements Memento {
49 + private Level level = DEFAULT_LEVEL;
50 +
51 + public ObjectNode toObjectNode() {
52 + ObjectNode node = MAPPER.createObjectNode();
53 + node.put(LEVEL, level.name());
54 + return node;
55 + }
56 +
57 + public void setLevel(Level level) {
58 + this.level = level;
59 + }
60 + }
61 +}
...@@ -41,7 +41,7 @@ public class UserFactory extends JsonFactory { ...@@ -41,7 +41,7 @@ public class UserFactory extends JsonFactory {
41 .put(ID, user.id()) 41 .put(ID, user.id())
42 .put(NAME, user.name()) 42 .put(NAME, user.name())
43 .put(MAC, user.mac()); 43 .put(MAC, user.mac());
44 - // TODO: add profile data 44 + root.set(PROFILE, XosFunctionFactory.profileForUser(user));
45 return root; 45 return root;
46 } 46 }
47 47
......
...@@ -28,16 +28,37 @@ public interface XosFunction { ...@@ -28,16 +28,37 @@ public interface XosFunction {
28 /** 28 /**
29 * Returns the descriptor for this function. 29 * Returns the descriptor for this function.
30 * 30 *
31 - * @return function identifier 31 + * @return function descriptor
32 */ 32 */
33 XosFunctionDescriptor descriptor(); 33 XosFunctionDescriptor descriptor();
34 34
35 /** 35 /**
36 - * Returns the current state of this function, encapsulated 36 + * Applies a parameter change for the given user.
37 - * as a JSON node.
38 * 37 *
39 - * @return parameters for the function 38 + * @param user user to apply change to
39 + * @param param parameter name
40 + * @param value new parameter value
40 */ 41 */
41 - ObjectNode params(); 42 + void applyParam(SubscriberUser user, String param, String value);
43 +
44 + /**
45 + * Create an initialized memento.
46 + * If the function maintains no state per user, return null.
47 + *
48 + * @return a new memento
49 + */
50 + Memento createMemento();
51 +
52 + /**
53 + * Internal state memento.
54 + */
55 + interface Memento {
56 + /**
57 + * Returns a JSON representation of this memento.
58 + *
59 + * @return memento state as object node
60 + */
61 + ObjectNode toObjectNode();
62 + }
42 } 63 }
43 64
......
1 package org.onosproject.cord.gui.model; 1 package org.onosproject.cord.gui.model;
2 2
3 -import com.fasterxml.jackson.databind.JsonNode;
4 import com.fasterxml.jackson.databind.node.ArrayNode; 3 import com.fasterxml.jackson.databind.node.ArrayNode;
5 import com.fasterxml.jackson.databind.node.ObjectNode; 4 import com.fasterxml.jackson.databind.node.ObjectNode;
6 5
7 import java.util.HashMap; 6 import java.util.HashMap;
8 import java.util.Map; 7 import java.util.Map;
9 8
9 +import static org.onosproject.cord.gui.model.XosFunctionDescriptor.URL_FILTER;
10 +
10 /** 11 /**
11 * Utility factory for operating on XOS functions. 12 * Utility factory for operating on XOS functions.
12 */ 13 */
13 public class XosFunctionFactory extends JsonFactory { 14 public class XosFunctionFactory extends JsonFactory {
14 15
15 private static final String PARAMS = "params"; 16 private static final String PARAMS = "params";
16 -
17 private static final String LEVEL = "level"; 17 private static final String LEVEL = "level";
18 private static final String LEVELS = "levels"; 18 private static final String LEVELS = "levels";
19 19
20 - 20 + private static final UrlFilterFunction.Level DEFAULT_FILTER_LEVEL =
21 - // URL Filtering Levels... 21 + UrlFilterFunction.Level.PG;
22 - private static final String PG = "PG";
23 - private static final String PG13 = "PG-13";
24 - private static final String R = "R";
25 -
26 - private static final String[] FILTER_LEVELS = { PG, PG13, R };
27 - private static final String DEFAULT_FILTER_LEVEL = PG;
28 22
29 23
30 // no instantiation 24 // no instantiation
...@@ -45,38 +39,76 @@ public class XosFunctionFactory extends JsonFactory { ...@@ -45,38 +39,76 @@ public class XosFunctionFactory extends JsonFactory {
45 return root; 39 return root;
46 } 40 }
47 41
48 - private static JsonNode paramsForXfd(XosFunctionDescriptor xfd) { 42 + private static ObjectNode paramsForXfd(XosFunctionDescriptor xfd) {
49 - ParamStructFactory psf = PARAM_MAP.get(xfd); 43 + ParamsFactory psf = PARAM_MAP.get(xfd);
50 if (psf == null) { 44 if (psf == null) {
51 - psf = DEF_PARAMS; 45 + psf = DEF_PARAMS_FACTORY;
52 } 46 }
53 return psf.params(); 47 return psf.params();
54 } 48 }
55 49
50 +
56 // ==== handling different parameter structures... 51 // ==== handling different parameter structures...
57 - private static final Map<XosFunctionDescriptor, ParamStructFactory> 52 + private static final Map<XosFunctionDescriptor, ParamsFactory>
58 - PARAM_MAP = new HashMap<XosFunctionDescriptor, ParamStructFactory>(); 53 + PARAM_MAP = new HashMap<XosFunctionDescriptor, ParamsFactory>();
59 54
60 - private static final ParamStructFactory DEF_PARAMS = new ParamStructFactory(); 55 + private static final ParamsFactory DEF_PARAMS_FACTORY = new ParamsFactory();
61 static { 56 static {
62 - PARAM_MAP.put(XosFunctionDescriptor.URL_FILTER, new UrlFilterParams()); 57 + PARAM_MAP.put(URL_FILTER, new UrlFilterParamsFactory());
58 + }
59 +
60 + /**
61 + * Applies a parameter change for the given function, in the context of
62 + * the specified user.
63 + *
64 + * @param xfd function context
65 + * @param userId user identifier
66 + * @param param parameter name
67 + * @param value value to apply
68 + */
69 + public static void apply(XosFunctionDescriptor xfd, int userId,
70 + String param, String value) {
71 + // TODO:
63 } 72 }
64 73
74 + /**
75 + * Creates an object node representation of the profile for the
76 + * specified user.
77 + *
78 + * @param user the user
79 + * @return object node profile
80 + */
81 + public static ObjectNode profileForUser(SubscriberUser user) {
82 + ObjectNode root = objectNode();
83 + for (XosFunctionDescriptor xfd: XosFunctionDescriptor.values()) {
84 + XosFunction.Memento mem = user.getMemento(xfd);
85 + if (mem != null) {
86 + root.set(xfd.id(), mem.toObjectNode());
87 + }
88 + }
89 + return root;
90 + }
91 +
92 +
93 + // ===================================================================
94 + // === factories for creating parameter structures, both default
95 + // and from a memento...
96 +
65 // private parameter structure creator 97 // private parameter structure creator
66 - static class ParamStructFactory { 98 + static class ParamsFactory {
67 ObjectNode params() { 99 ObjectNode params() {
68 return objectNode(); 100 return objectNode();
69 } 101 }
70 } 102 }
71 103
72 - static class UrlFilterParams extends ParamStructFactory { 104 + static class UrlFilterParamsFactory extends ParamsFactory {
73 @Override 105 @Override
74 ObjectNode params() { 106 ObjectNode params() {
75 ObjectNode result = objectNode(); 107 ObjectNode result = objectNode();
76 - result.put(LEVEL, DEFAULT_FILTER_LEVEL); 108 + result.put(LEVEL, DEFAULT_FILTER_LEVEL.name());
77 ArrayNode levels = arrayNode(); 109 ArrayNode levels = arrayNode();
78 - for (String lvl: FILTER_LEVELS) { 110 + for (UrlFilterFunction.Level lvl: UrlFilterFunction.Level.values()) {
79 - levels.add(lvl); 111 + levels.add(lvl.name());
80 } 112 }
81 result.set(LEVELS, levels); 113 result.set(LEVELS, levels);
82 return result; 114 return result;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 { 3 {
4 "id": 1, 4 "id": 1,
5 "name": "Mom's MacBook", 5 "name": "Mom's MacBook",
6 - "mac": "01:02:03:04:05:06", 6 + "mac": "010203040506",
7 "profile": { 7 "profile": {
8 "url_filter": { 8 "url_filter": {
9 "level": "R" 9 "level": "R"
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
13 { 13 {
14 "id": 2, 14 "id": 2,
15 "name": "Dad's iPad", 15 "name": "Dad's iPad",
16 - "mac": "01:02:03:04:05:77", 16 + "mac": "010203040507",
17 "profile": { 17 "profile": {
18 "url_filter": { 18 "url_filter": {
19 "level": "R" 19 "level": "R"
...@@ -23,17 +23,17 @@ ...@@ -23,17 +23,17 @@
23 { 23 {
24 "id": 3, 24 "id": 3,
25 "name": "Dick's laptop", 25 "name": "Dick's laptop",
26 - "mac": "01:02:03:04:05:88", 26 + "mac": "010203040508",
27 "profile": { 27 "profile": {
28 "url_filter": { 28 "url_filter": {
29 - "level": "PG-13" 29 + "level": "PG_13"
30 } 30 }
31 } 31 }
32 }, 32 },
33 { 33 {
34 "id": 4, 34 "id": 4,
35 "name": "Jane's laptop", 35 "name": "Jane's laptop",
36 - "mac": "01:02:03:04:05:99", 36 + "mac": "010203040509",
37 "profile": { 37 "profile": {
38 "url_filter": { 38 "url_filter": {
39 "level": "PG" 39 "level": "PG"
......
...@@ -51,6 +51,7 @@ public class CoreModelCacheTest { ...@@ -51,6 +51,7 @@ public class CoreModelCacheTest {
51 @Test 51 @Test
52 public void basicBundleJson() { 52 public void basicBundleJson() {
53 String json = BundleFactory.toJson(cache.getCurrentBundle()); 53 String json = BundleFactory.toJson(cache.getCurrentBundle());
54 + System.out.println(json);
54 assertTrue("bad basic json", sameJson(BASIC_BUNDLE_JSON, json)); 55 assertTrue("bad basic json", sameJson(BASIC_BUNDLE_JSON, json));
55 } 56 }
56 57
...@@ -75,6 +76,21 @@ public class CoreModelCacheTest { ...@@ -75,6 +76,21 @@ public class CoreModelCacheTest {
75 assertEquals("wrong # users", 4, users.size()); 76 assertEquals("wrong # users", 4, users.size());
76 } 77 }
77 78
79 + @Test
80 + public void usersBasicJson() {
81 + String json = cache.jsonUsers();
82 + System.out.println(json);
83 + assertTrue("bad users basic json", sameJson(USERS_BASIC, json));
84 + }
85 +
86 + @Test
87 + public void usersFamilyJson() {
88 + cache.setCurrentBundle("family");
89 + String json = cache.jsonUsers();
90 + System.out.println(json);
91 + assertTrue("bad users family json", sameJson(USERS_FAMILY, json));
92 + }
93 +
78 // ============= 94 // =============
79 95
80 private boolean sameJson(String s1, String s2) { 96 private boolean sameJson(String s1, String s2) {
...@@ -91,61 +107,157 @@ public class CoreModelCacheTest { ...@@ -91,61 +107,157 @@ public class CoreModelCacheTest {
91 private static final ObjectMapper MAPPER = new ObjectMapper(); 107 private static final ObjectMapper MAPPER = new ObjectMapper();
92 108
93 private static final String BASIC_BUNDLE_JSON = "{\n" + 109 private static final String BASIC_BUNDLE_JSON = "{\n" +
94 - " \"bundle\": {\n" + 110 + " \"bundle\": {\n" +
95 - " \"id\": \"basic\",\n" + 111 + " \"id\": \"basic\",\n" +
96 - " \"name\": \"Basic Bundle\",\n" + 112 + " \"name\": \"Basic Bundle\",\n" +
97 - " \"functions\": [\n" + 113 + " \"desc\": \"Provides basic internet and firewall functions.\",\n" +
98 - " {\n" + 114 + " \"functions\": [\n" +
99 - " \"id\": \"internet\",\n" + 115 + " {\n" +
100 - " \"name\": \"Internet\",\n" + 116 + " \"id\": \"internet\",\n" +
101 - " \"desc\": \"Basic internet connectivity.\",\n" + 117 + " \"name\": \"Internet\",\n" +
102 - " \"params\": {}\n" + 118 + " \"desc\": \"Basic internet connectivity.\",\n" +
103 - " },\n" + 119 + " \"params\": {}\n" +
104 - " {\n" + 120 + " },\n" +
105 - " \"id\": \"firewall\",\n" + 121 + " {\n" +
106 - " \"name\": \"Firewall\",\n" + 122 + " \"id\": \"firewall\",\n" +
107 - " \"desc\": \"Normal firewall protection.\",\n" + 123 + " \"name\": \"Firewall\",\n" +
108 - " \"params\": {}\n" + 124 + " \"desc\": \"Normal firewall protection.\",\n" +
109 - " }\n" + 125 + " \"params\": {}\n" +
126 + " }\n" +
127 + " ]\n" +
128 + " },\n" +
129 + " \"bundles\": [\n" +
130 + " {\n" +
131 + " \"id\": \"basic\",\n" +
132 + " \"name\": \"Basic Bundle\",\n" +
133 + " \"desc\": \"Provides basic internet and firewall functions.\"\n" +
134 + " },\n" +
135 + " {\n" +
136 + " \"id\": \"family\",\n" +
137 + " \"name\": \"Family Bundle\",\n" +
138 + " \"desc\": \"Provides internet, firewall and parental control functions.\"\n" +
139 + " }\n" +
110 " ]\n" + 140 " ]\n" +
111 - " },\n" +
112 - " \"bundles\": [\n" +
113 - " { \"id\": \"basic\", \"name\": \"Basic Bundle\" },\n" +
114 - " { \"id\": \"family\", \"name\": \"Family Bundle\" }\n" +
115 - " ]\n" +
116 "}\n"; 141 "}\n";
117 142
118 private static final String FAMILY_BUNDLE_JSON = "{\n" + 143 private static final String FAMILY_BUNDLE_JSON = "{\n" +
119 - " \"bundle\": {\n" + 144 + " \"bundle\": {\n" +
120 - " \"id\": \"family\",\n" + 145 + " \"id\": \"family\",\n" +
121 - " \"name\": \"Family Bundle\",\n" + 146 + " \"name\": \"Family Bundle\",\n" +
122 - " \"functions\": [\n" + 147 + " \"desc\": \"Provides internet, firewall and parental control functions.\",\n" +
123 - " {\n" + 148 + " \"functions\": [\n" +
124 - " \"id\": \"internet\",\n" + 149 + " {\n" +
125 - " \"name\": \"Internet\",\n" + 150 + " \"id\": \"internet\",\n" +
126 - " \"desc\": \"Basic internet connectivity.\",\n" + 151 + " \"name\": \"Internet\",\n" +
127 - " \"params\": {}\n" + 152 + " \"desc\": \"Basic internet connectivity.\",\n" +
128 - " },\n" + 153 + " \"params\": {}\n" +
129 - " {\n" + 154 + " },\n" +
130 - " \"id\": \"firewall\",\n" + 155 + " {\n" +
131 - " \"name\": \"Firewall\",\n" + 156 + " \"id\": \"firewall\",\n" +
132 - " \"desc\": \"Normal firewall protection.\",\n" + 157 + " \"name\": \"Firewall\",\n" +
133 - " \"params\": {}\n" + 158 + " \"desc\": \"Normal firewall protection.\",\n" +
134 - " },\n" + 159 + " \"params\": {}\n" +
135 - " {\n" + 160 + " },\n" +
136 - " \"id\": \"url_filter\",\n" + 161 + " {\n" +
137 - " \"name\": \"Parental Control\",\n" + 162 + " \"id\": \"url_filter\",\n" +
138 - " \"desc\": \"Variable levels of URL filtering.\",\n" + 163 + " \"name\": \"Parental Control\",\n" +
139 - " \"params\": {\n" + 164 + " \"desc\": \"Variable levels of URL filtering.\",\n" +
140 - " \"level\": \"PG\",\n" + 165 + " \"params\": {\n" +
141 - " \"levels\": [ \"PG\", \"PG-13\", \"R\" ]\n" + 166 + " \"level\": \"PG\",\n" +
167 + " \"levels\": [\n" +
168 + " \"PG\",\n" +
169 + " \"PG_13\",\n" +
170 + " \"R\"\n" +
171 + " ]\n" +
172 + " }\n" +
173 + " }\n" +
174 + " ]\n" +
175 + " },\n" +
176 + " \"bundles\": [\n" +
177 + " {\n" +
178 + " \"id\": \"basic\",\n" +
179 + " \"name\": \"Basic Bundle\",\n" +
180 + " \"desc\": \"Provides basic internet and firewall functions.\"\n" +
181 + " },\n" +
182 + " {\n" +
183 + " \"id\": \"family\",\n" +
184 + " \"name\": \"Family Bundle\",\n" +
185 + " \"desc\": \"Provides internet, firewall and parental control functions.\"\n" +
142 " }\n" + 186 " }\n" +
143 - " }\n" +
144 " ]\n" + 187 " ]\n" +
145 - " },\n" + 188 + "}\n";
146 - " \"bundles\": [\n" + 189 +
147 - " { \"id\": \"basic\", \"name\": \"Basic Bundle\" },\n" + 190 + private static final String USERS_BASIC = "{\n" +
148 - " { \"id\": \"family\", \"name\": \"Family Bundle\" }\n" + 191 + " \"users\": [\n" +
192 + " {\n" +
193 + " \"id\": 1,\n" +
194 + " \"name\": \"Mom's MacBook\",\n" +
195 + " \"mac\": \"010203040506\",\n" +
196 + " \"profile\": { }\n" +
197 + " },\n" +
198 + " {\n" +
199 + " \"id\": 2,\n" +
200 + " \"name\": \"Dad's iPad\",\n" +
201 + " \"mac\": \"010203040507\",\n" +
202 + " \"profile\": { }\n" +
203 + " },\n" +
204 + " {\n" +
205 + " \"id\": 3,\n" +
206 + " \"name\": \"Dick's laptop\",\n" +
207 + " \"mac\": \"010203040508\",\n" +
208 + " \"profile\": { }\n" +
209 + " },\n" +
210 + " {\n" +
211 + " \"id\": 4,\n" +
212 + " \"name\": \"Jane's laptop\",\n" +
213 + " \"mac\": \"010203040509\",\n" +
214 + " \"profile\": { }\n" +
215 + " }\n" +
216 + " ]\n" +
217 + "}\n";
218 +
219 + private static final String USERS_FAMILY = "{\n" +
220 + " \"users\": [\n" +
221 + " {\n" +
222 + " \"id\": 1,\n" +
223 + " \"name\": \"Mom's MacBook\",\n" +
224 + " \"mac\": \"010203040506\",\n" +
225 + " \"profile\": {\n" +
226 + " \"url_filter\": {\n" +
227 + " \"level\": \"PG\"\n" +
228 + " }\n" +
229 + " }\n" +
230 + " },\n" +
231 + " {\n" +
232 + " \"id\": 2,\n" +
233 + " \"name\": \"Dad's iPad\",\n" +
234 + " \"mac\": \"010203040507\",\n" +
235 + " \"profile\": {\n" +
236 + " \"url_filter\": {\n" +
237 + " \"level\": \"PG\"\n" +
238 + " }\n" +
239 + " }\n" +
240 + " },\n" +
241 + " {\n" +
242 + " \"id\": 3,\n" +
243 + " \"name\": \"Dick's laptop\",\n" +
244 + " \"mac\": \"010203040508\",\n" +
245 + " \"profile\": {\n" +
246 + " \"url_filter\": {\n" +
247 + " \"level\": \"PG\"\n" +
248 + " }\n" +
249 + " }\n" +
250 + " },\n" +
251 + " {\n" +
252 + " \"id\": 4,\n" +
253 + " \"name\": \"Jane's laptop\",\n" +
254 + " \"mac\": \"010203040509\",\n" +
255 + " \"profile\": {\n" +
256 + " \"url_filter\": {\n" +
257 + " \"level\": \"PG\"\n" +
258 + " }\n" +
259 + " }\n" +
260 + " }\n" +
149 " ]\n" + 261 " ]\n" +
150 "}\n"; 262 "}\n";
151 } 263 }
......