blob: 2f70780defba93fa06753cc5db5073ea9e623136 [file] [log] [blame]
Simon Huntd2747a02015-04-30 22:41:16 -07001/*
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 */
16package org.onosproject.ui;
17
18import com.fasterxml.jackson.databind.ObjectMapper;
19import com.fasterxml.jackson.databind.node.ObjectNode;
20import org.onlab.osgi.ServiceDirectory;
21
22import java.util.Collection;
23import java.util.Collections;
24import java.util.HashMap;
25import java.util.Map;
26import java.util.Set;
27
28import static com.google.common.base.Preconditions.checkArgument;
29import static com.google.common.base.Preconditions.checkNotNull;
30
31/**
32 * Abstraction of an entity capable of processing a JSON message from the user
33 * interface client.
34 * <p>
35 * The message is a JSON object with the following structure:
36 * </p>
37 * <pre>
38 * {
39 * "type": "<em>event-type</em>",
40 * "sid": "<em>sequence-number</em>",
41 * "payload": {
42 * <em>arbitrary JSON object structure</em>
43 * }
44 * }
45 * </pre>
46 */
Simon Hunta0ddb022015-05-01 09:53:01 -070047public abstract class UiMessageHandler {
Simon Huntd2747a02015-04-30 22:41:16 -070048
49 private final Map<String, RequestHandler> handlerMap = new HashMap<>();
50
51 private UiConnection connection;
52 private ServiceDirectory directory;
53
54 /**
55 * Mapper for creating ObjectNodes and ArrayNodes etc.
56 */
57 protected final ObjectMapper mapper = new ObjectMapper();
58
Simon Huntd2747a02015-04-30 22:41:16 -070059
60 /**
61 * Subclasses must return the collection of handlers for the
62 * message types they handle.
63 *
64 * @return the message handler instances
65 */
66 protected abstract Collection<RequestHandler> getHandlers();
67
68 /**
69 * Returns the set of message types which this handler is capable of
70 * processing.
71 *
72 * @return set of message types
73 */
74 public Set<String> messageTypes() {
75 return Collections.unmodifiableSet(handlerMap.keySet());
76 }
77
78 /**
79 * Processes a JSON message from the user interface client.
80 *
81 * @param message JSON message
82 */
83 public void process(ObjectNode message) {
84 String type = JsonUtils.eventType(message);
85 long sid = JsonUtils.sid(message);
86 ObjectNode payload = JsonUtils.payload(message);
87 exec(type, sid, payload);
88 }
89
90 /**
91 * Finds the appropriate handler and executes the process method.
92 *
93 * @param eventType event type
94 * @param sid sequence identifier
95 * @param payload message payload
96 */
97 void exec(String eventType, long sid, ObjectNode payload) {
98 RequestHandler handler = handlerMap.get(eventType);
99 if (handler != null) {
100 handler.process(sid, payload);
101 }
102 }
103
Simon Hunta0ddb022015-05-01 09:53:01 -0700104 private void bindHandlers() {
105 Collection<RequestHandler> handlers = getHandlers();
106 checkNotNull(handlers, "Handlers cannot be null");
107 checkArgument(!handlers.isEmpty(), "Handlers cannot be empty");
108
109 for (RequestHandler h : handlers) {
110 h.setParent(this);
111 handlerMap.put(h.eventType(), h);
112 }
113 }
114
Simon Huntd2747a02015-04-30 22:41:16 -0700115 /**
116 * Initializes the handler with the user interface connection and
117 * service directory context.
118 *
119 * @param connection user interface connection
120 * @param directory service directory
121 */
122 public void init(UiConnection connection, ServiceDirectory directory) {
123 this.connection = connection;
124 this.directory = directory;
125 bindHandlers();
126 }
127
128 /**
129 * Destroys the message handler context.
130 */
131 public void destroy() {
132 this.connection = null;
133 this.directory = null;
134 }
135
136 /**
137 * Returns the user interface connection with which this handler was primed.
138 *
139 * @return user interface connection
140 */
141 public UiConnection connection() {
142 return connection;
143 }
144
145 /**
146 * Returns the user interface connection with which this handler was primed.
147 *
148 * @return user interface connection
149 */
150 public ServiceDirectory directory() {
151 return directory;
152 }
153
154 /**
155 * Returns implementation of the specified service class.
156 *
157 * @param serviceClass service class
158 * @param <T> type of service
159 * @return implementation class
160 * @throws org.onlab.osgi.ServiceNotFoundException if no implementation found
161 */
162 protected <T> T get(Class<T> serviceClass) {
163 return directory.get(serviceClass);
164 }
165
166}