CORD Subscriber GUI - XosFunction mementos now stored inside each SubscriberUser…
… to capture the parameter state per user. Change-Id: I678249f63a68172db66a5d3faa0b1747c670bf6e
Showing
12 changed files
with
504 additions
and
92 deletions
... | @@ -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 | } | ... | ... |
-
Please register or login to post a comment