blob: 2b2734749de220f9793a6d7b46f4a7987d20b3e4 [file] [log] [blame]
Simon Hunted804d52016-03-30 09:51:40 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Simon Hunted804d52016-03-30 09:51:40 -07003 *
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
Simon Huntf679c4e2016-04-01 17:02:24 -070017package org.onosproject.ui.impl.topo;
Simon Hunted804d52016-03-30 09:51:40 -070018
Simon Huntb1ce2602016-07-23 14:04:31 -070019import org.onosproject.net.region.RegionId;
Simon Huntf679c4e2016-04-01 17:02:24 -070020import org.onosproject.ui.UiTopoLayoutService;
21import org.onosproject.ui.impl.UiWebSocket;
Simon Huntcda9c032016-04-11 10:32:54 -070022import org.onosproject.ui.impl.topo.model.UiModelEvent;
23import org.onosproject.ui.impl.topo.model.UiModelListener;
Simon Huntf679c4e2016-04-01 17:02:24 -070024import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel;
Simon Huntd5b96732016-07-08 13:22:27 -070025import org.onosproject.ui.model.topo.UiClusterMember;
Simon Hunt98189192016-07-29 19:02:27 -070026import org.onosproject.ui.model.topo.UiNode;
Simon Huntd5b96732016-07-08 13:22:27 -070027import org.onosproject.ui.model.topo.UiRegion;
Simon Huntc13082f2016-08-03 21:20:23 -070028import org.onosproject.ui.model.topo.UiSynthLink;
Simon Huntf679c4e2016-04-01 17:02:24 -070029import org.onosproject.ui.model.topo.UiTopoLayout;
Simon Hunted804d52016-03-30 09:51:40 -070030import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
Simon Huntf836a872016-08-10 17:37:36 -070033import java.util.ArrayList;
Simon Huntb1ce2602016-07-23 14:04:31 -070034import java.util.HashSet;
Simon Huntd5b96732016-07-08 13:22:27 -070035import java.util.List;
Simon Hunt977aa052016-07-20 17:08:29 -070036import java.util.Set;
Simon Huntd5b96732016-07-08 13:22:27 -070037
Simon Hunted804d52016-03-30 09:51:40 -070038/**
Simon Huntf679c4e2016-04-01 17:02:24 -070039 * Coordinates with the {@link UiTopoLayoutService} to access
40 * {@link UiTopoLayout}s, and with the {@link UiSharedTopologyModel} which
Simon Huntcda9c032016-04-11 10:32:54 -070041 * maintains a local model of the network entities, tailored specifically
42 * for displaying on the UI.
Simon Hunted804d52016-03-30 09:51:40 -070043 * <p>
44 * Note that an instance of this class will be created for each
Simon Huntf679c4e2016-04-01 17:02:24 -070045 * {@link UiWebSocket} connection, and will contain
Simon Hunted804d52016-03-30 09:51:40 -070046 * the state of how the topology is laid out for the logged-in user.
Simon Huntd5b96732016-07-08 13:22:27 -070047 * <p>
48 * The expected pattern is for the {@link Topo2ViewMessageHandler} to obtain
49 * a reference to the session instance (via the {@link UiWebSocket}), and
50 * interact with it when topo-related events come in from the client.
Simon Hunted804d52016-03-30 09:51:40 -070051 */
Simon Huntcda9c032016-04-11 10:32:54 -070052public class UiTopoSession implements UiModelListener {
Simon Hunt977aa052016-07-20 17:08:29 -070053
Simon Hunted804d52016-03-30 09:51:40 -070054 private final Logger log = LoggerFactory.getLogger(getClass());
55
Simon Huntf679c4e2016-04-01 17:02:24 -070056 private final UiWebSocket webSocket;
Simon Hunt7092cc42016-04-06 18:40:17 -070057 private final String username;
58
59 final UiSharedTopologyModel sharedModel;
Simon Hunted804d52016-03-30 09:51:40 -070060
61 private boolean registered = false;
62
Thomas Vachuska92b016b2016-05-20 11:37:57 -070063 private UiTopoLayoutService layoutService;
Simon Hunt7092cc42016-04-06 18:40:17 -070064 private UiTopoLayout currentLayout;
Thomas Vachuska92b016b2016-05-20 11:37:57 -070065 private boolean messagesEnabled;
Simon Huntf679c4e2016-04-01 17:02:24 -070066
Simon Hunted804d52016-03-30 09:51:40 -070067 /**
Simon Hunt7092cc42016-04-06 18:40:17 -070068 * Creates a new topology session for the specified web socket connection.
69 *
Thomas Vachuska92b016b2016-05-20 11:37:57 -070070 * @param webSocket web socket
71 * @param model share topology model
72 * @param layoutService topology layout service
Simon Hunted804d52016-03-30 09:51:40 -070073 */
Thomas Vachuska92b016b2016-05-20 11:37:57 -070074 public UiTopoSession(UiWebSocket webSocket,
75 UiSharedTopologyModel model,
76 UiTopoLayoutService layoutService) {
Simon Huntf679c4e2016-04-01 17:02:24 -070077 this.webSocket = webSocket;
Simon Hunt7092cc42016-04-06 18:40:17 -070078 this.username = webSocket.userName();
Simon Huntcda9c032016-04-11 10:32:54 -070079 this.sharedModel = model;
Thomas Vachuska92b016b2016-05-20 11:37:57 -070080 this.layoutService = layoutService;
Simon Hunted804d52016-03-30 09:51:40 -070081 }
82
Simon Hunt977aa052016-07-20 17:08:29 -070083 // constructs a neutered instance, for unit testing
84 UiTopoSession() {
85 webSocket = null;
86 username = null;
87 sharedModel = null;
88 }
89
Simon Hunted804d52016-03-30 09:51:40 -070090 /**
Simon Hunt7092cc42016-04-06 18:40:17 -070091 * Initializes the session; registering with the shared model.
Simon Hunted804d52016-03-30 09:51:40 -070092 */
93 public void init() {
94 if (!registered) {
Simon Hunt7092cc42016-04-06 18:40:17 -070095 log.debug("{} : Registering with shared model", this);
Simon Hunted804d52016-03-30 09:51:40 -070096 sharedModel.register(this);
Thomas Vachuska92b016b2016-05-20 11:37:57 -070097 currentLayout = layoutService.getRootLayout();
Simon Hunted804d52016-03-30 09:51:40 -070098 registered = true;
99 } else {
100 log.warn("already registered");
101 }
102 }
103
104 /**
Simon Hunt7092cc42016-04-06 18:40:17 -0700105 * Destroys the session; unregistering from the shared model.
Simon Hunted804d52016-03-30 09:51:40 -0700106 */
107 public void destroy() {
Simon Hunt7092cc42016-04-06 18:40:17 -0700108 if (registered) {
109 log.debug("{} : Unregistering from shared model", this);
Simon Hunted804d52016-03-30 09:51:40 -0700110 sharedModel.unregister(this);
Simon Huntf679c4e2016-04-01 17:02:24 -0700111 registered = false;
Simon Hunted804d52016-03-30 09:51:40 -0700112 } else {
113 log.warn("already unregistered");
114 }
115 }
116
117 @Override
118 public String toString() {
Simon Huntf679c4e2016-04-01 17:02:24 -0700119 return String.format("{UiTopoSession for user <%s>}", username);
Simon Hunted804d52016-03-30 09:51:40 -0700120 }
Simon Huntcda9c032016-04-11 10:32:54 -0700121
122 @Override
123 public void event(UiModelEvent event) {
Yuta HIGUCHI28ad09a2016-06-28 17:08:29 -0700124 log.debug("Event received: {}", event);
Simon Huntcda9c032016-04-11 10:32:54 -0700125 // TODO: handle model events from the cache...
126 }
Thomas Vachuska92b016b2016-05-20 11:37:57 -0700127
128 /**
129 * Returns the current layout context.
130 *
131 * @return current topology layout
132 */
133 public UiTopoLayout currentLayout() {
134 return currentLayout;
135 }
136
137 /**
Simon Huntf836a872016-08-10 17:37:36 -0700138 * Returns the breadcrumb trail from current layout to root. That is,
139 * element 0 of the list will be the current layout; the last element
140 * of the list will be the root layout. This list is guaranteed to have
141 * size of at least 1.
142 *
143 * @return breadcrumb trail
144 */
145 public List<UiTopoLayout> breadCrumbs() {
146 UiTopoLayout current = currentLayout;
147 List<UiTopoLayout> crumbs = new ArrayList<>();
148 crumbs.add(current);
149 while (!current.isRoot()) {
150 current = layoutService.getLayout(current.parent());
151 crumbs.add(current);
152 }
153 return crumbs;
154 }
155
156 /**
Thomas Vachuska92b016b2016-05-20 11:37:57 -0700157 * Changes the current layout context to the specified layout.
158 *
159 * @param topoLayout new topology layout context
160 */
161 public void setCurrentLayout(UiTopoLayout topoLayout) {
162 currentLayout = topoLayout;
163 }
164
165 /**
166 * Enables or disables the transmission of topology event update messages.
167 *
168 * @param enabled true if messages should be sent
169 */
170 public void enableEvent(boolean enabled) {
171 messagesEnabled = enabled;
172 }
Simon Huntd5b96732016-07-08 13:22:27 -0700173
174 /**
175 * Returns the list of ONOS instances (cluster members).
176 *
177 * @return the list of ONOS instances
178 */
179 public List<UiClusterMember> getAllInstances() {
180 return sharedModel.getClusterMembers();
181 }
182
183 /**
184 * Returns the region for the specified layout.
185 *
186 * @param layout layout filter
187 * @return region that the layout is based upon
188 */
189 public UiRegion getRegion(UiTopoLayout layout) {
Simon Huntb1ce2602016-07-23 14:04:31 -0700190 RegionId rid = layout.regionId();
191 return rid == null ? sharedModel.getNullRegion() : sharedModel.getRegion(rid);
Simon Huntd5b96732016-07-08 13:22:27 -0700192 }
Simon Hunt977aa052016-07-20 17:08:29 -0700193
194 /**
Simon Hunt98189192016-07-29 19:02:27 -0700195 * Returns the regions/devices that are "peers" to this region. That is,
196 * based on the layout the user is viewing, all the regions/devices that
197 * are associated with layouts that share the same parent layout as this
198 * layout, AND that are linked to an element within this region.
Simon Hunt977aa052016-07-20 17:08:29 -0700199 *
200 * @param layout the layout being viewed
Simon Hunt98189192016-07-29 19:02:27 -0700201 * @return all regions/devices that are "siblings" to this layout's region
Simon Hunt977aa052016-07-20 17:08:29 -0700202 */
Simon Hunt98189192016-07-29 19:02:27 -0700203 public Set<UiNode> getPeerNodes(UiTopoLayout layout) {
204 Set<UiNode> peers = new HashSet<>();
205
206 // first, get the peer regions
207 Set<UiTopoLayout> peerLayouts = layoutService.getPeerLayouts(layout.id());
208 peerLayouts.forEach(l -> {
209 RegionId peerRegion = l.regionId();
210 peers.add(sharedModel.getRegion(peerRegion));
211 });
212
213 // now add the devices that reside in the parent region
214 if (!layout.isRoot()) {
215 UiTopoLayout parentLayout = layoutService.getLayout(layout.parent());
216 getRegion(parentLayout).devices().forEach(peers::add);
217 }
218
219 // TODO: Finally, filter out regions / devices that are not connected
220 // directly to this region by an implicit link
Simon Huntb1ce2602016-07-23 14:04:31 -0700221 return peers;
Simon Hunt977aa052016-07-20 17:08:29 -0700222 }
223
224 /**
225 * Returns the subregions of the region in the specified layout.
226 *
227 * @param layout the layout being viewed
228 * @return all regions that are "contained within" this layout's region
229 */
230 public Set<UiRegion> getSubRegions(UiTopoLayout layout) {
Simon Huntb1ce2602016-07-23 14:04:31 -0700231 Set<UiTopoLayout> kidLayouts = layoutService.getChildren(layout.id());
232 Set<UiRegion> kids = new HashSet<>();
233 kidLayouts.forEach(l -> kids.add(sharedModel.getRegion(l.regionId())));
234 return kids;
Simon Hunt977aa052016-07-20 17:08:29 -0700235 }
236
237 /**
Simon Huntc13082f2016-08-03 21:20:23 -0700238 * Returns the (synthetic) links of the region in the specified layout.
239 *
240 * @param layout the layout being viewed
241 * @return all links that are contained by this layout's region
242 */
243 public List<UiSynthLink> getLinks(UiTopoLayout layout) {
244 return sharedModel.getSynthLinks(layout.regionId());
245 }
246
247 /**
Simon Huntb1ce2602016-07-23 14:04:31 -0700248 * Refreshes the model's internal state.
Simon Hunt977aa052016-07-20 17:08:29 -0700249 */
Simon Huntb1ce2602016-07-23 14:04:31 -0700250 public void refreshModel() {
251 sharedModel.refresh();
Simon Hunt977aa052016-07-20 17:08:29 -0700252 }
Simon Hunt377f5d22016-09-01 16:27:21 -0700253
254 /**
255 * Navigates to the specified region by setting the associated layout as
256 * current.
257 *
258 * @param regionId region identifier
259 */
260 public void navToRegion(String regionId) {
261 // 1. find the layout corresponding to the region ID
262 // 2. set this layout to be "current"
263 RegionId r = RegionId.regionId(regionId);
264 UiTopoLayout layout = layoutService.getLayout(r);
265 setCurrentLayout(layout);
266 }
Simon Hunted804d52016-03-30 09:51:40 -0700267}