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