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