blob: 5e6927f86e6a4eb384fb929202cba7ba76f1ceb9 [file] [log] [blame]
Simon Huntf679c4e2016-04-01 17:02:24 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Simon Huntf679c4e2016-04-01 17:02:24 -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
17package org.onosproject.ui.impl.topo;
18
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -070019import com.google.common.collect.ImmutableSet;
Simon Huntf679c4e2016-04-01 17:02:24 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -070023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
Simon Huntf679c4e2016-04-01 17:02:24 -070025import org.apache.felix.scr.annotations.Service;
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -070026import org.onlab.util.KryoNamespace;
Simon Hunt4f4ffc32016-08-03 18:30:47 -070027import org.onosproject.net.region.RegionId;
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -070028import org.onosproject.store.serializers.KryoNamespaces;
29import org.onosproject.store.service.ConsistentMap;
30import org.onosproject.store.service.Serializer;
31import org.onosproject.store.service.StorageService;
Simon Huntf679c4e2016-04-01 17:02:24 -070032import org.onosproject.ui.UiTopoLayoutService;
Simon Hunt4f4ffc32016-08-03 18:30:47 -070033import org.onosproject.ui.model.topo.UiRegion;
Simon Huntf679c4e2016-04-01 17:02:24 -070034import org.onosproject.ui.model.topo.UiTopoLayout;
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -070035import org.onosproject.ui.model.topo.UiTopoLayoutId;
Simon Huntf679c4e2016-04-01 17:02:24 -070036import org.slf4j.Logger;
37import org.slf4j.LoggerFactory;
38
Simon Huntb1ce2602016-07-23 14:04:31 -070039import java.util.Collections;
Simon Hunt4f4ffc32016-08-03 18:30:47 -070040import java.util.List;
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -070041import java.util.Map;
Thomas Vachuska92b016b2016-05-20 11:37:57 -070042import java.util.Objects;
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -070043import java.util.Set;
Thomas Vachuska92b016b2016-05-20 11:37:57 -070044import java.util.stream.Collectors;
45
46import static com.google.common.base.Preconditions.checkNotNull;
Thomas Vachuskaeb851cd2016-07-21 15:41:05 -070047import static org.onosproject.ui.model.topo.UiTopoLayoutId.DEFAULT_ID;
Simon Huntf679c4e2016-04-01 17:02:24 -070048
49/**
50 * Manages the user interface topology layouts.
51 * Note that these layouts are persisted and distributed across the cluster.
52 */
53@Component(immediate = true)
54@Service
55public class UiTopoLayoutManager implements UiTopoLayoutService {
56
Simon Huntf679c4e2016-04-01 17:02:24 -070057 private final Logger log = LoggerFactory.getLogger(getClass());
58
Thomas Vachuska92b016b2016-05-20 11:37:57 -070059 private static final String ID_NULL = "Layout ID cannot be null";
60 private static final String LAYOUT_NULL = "Layout cannot be null";
61
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -070062 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected StorageService storageService;
64
65 private ConsistentMap<UiTopoLayoutId, UiTopoLayout> layouts;
66 private Map<UiTopoLayoutId, UiTopoLayout> layoutMap;
67
Simon Huntf679c4e2016-04-01 17:02:24 -070068 @Activate
69 public void activate() {
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -070070 KryoNamespace.Builder kryoBuilder = new KryoNamespace.Builder()
71 .register(KryoNamespaces.API)
72 .register(UiTopoLayout.class);
73
74 layouts = storageService.<UiTopoLayoutId, UiTopoLayout>consistentMapBuilder()
75 .withSerializer(Serializer.using(kryoBuilder.build()))
76 .withName("onos-topo-layouts")
77 .withRelaxedReadConsistency()
78 .build();
79 layoutMap = layouts.asJavaMap();
80
Thomas Vachuska92b016b2016-05-20 11:37:57 -070081 // Create and add the default layout, if needed.
82 layoutMap.computeIfAbsent(DEFAULT_ID, k -> new UiTopoLayout(k, null, null));
83
Simon Huntf679c4e2016-04-01 17:02:24 -070084 log.info("Started");
85 }
86
87 @Deactivate
88 public void deactivate() {
Simon Huntf679c4e2016-04-01 17:02:24 -070089 log.info("Stopped");
90 }
91
92
93 @Override
Thomas Vachuska92b016b2016-05-20 11:37:57 -070094 public UiTopoLayout getRootLayout() {
95 return getLayout(DEFAULT_ID);
96 }
97
98 @Override
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -070099 public Set<UiTopoLayout> getLayouts() {
100 return ImmutableSet.copyOf(layoutMap.values());
Simon Huntf679c4e2016-04-01 17:02:24 -0700101 }
102
103 @Override
104 public boolean addLayout(UiTopoLayout layout) {
Thomas Vachuska92b016b2016-05-20 11:37:57 -0700105 checkNotNull(layout, LAYOUT_NULL);
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -0700106 return layouts.put(layout.id(), layout) == null;
107 }
108
109 @Override
110 public UiTopoLayout getLayout(UiTopoLayoutId layoutId) {
Thomas Vachuska92b016b2016-05-20 11:37:57 -0700111 checkNotNull(layoutId, ID_NULL);
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -0700112 return layoutMap.get(layoutId);
Simon Huntf679c4e2016-04-01 17:02:24 -0700113 }
114
115 @Override
Simon Hunt4f4ffc32016-08-03 18:30:47 -0700116 public UiTopoLayout getLayout(RegionId regionId) {
117 if (regionId == null || regionId.equals(UiRegion.NULL_ID)) {
118 return getRootLayout();
119 }
120
121 List<UiTopoLayout> matchingLayouts = layoutMap.values().stream()
122 .filter(l -> Objects.equals(regionId, l.regionId()))
123 .collect(Collectors.toList());
124 return matchingLayouts.isEmpty() ? null : matchingLayouts.get(0);
125 }
126
127 @Override
Simon Hunt98189192016-07-29 19:02:27 -0700128 public Set<UiTopoLayout> getPeerLayouts(UiTopoLayoutId layoutId) {
Simon Huntb1ce2602016-07-23 14:04:31 -0700129 checkNotNull(layoutId, ID_NULL);
Simon Hunt98189192016-07-29 19:02:27 -0700130
Simon Huntb1ce2602016-07-23 14:04:31 -0700131 UiTopoLayout layout = layoutMap.get(layoutId);
Simon Hunt98189192016-07-29 19:02:27 -0700132 if (layout == null || layout.isRoot()) {
Simon Huntb1ce2602016-07-23 14:04:31 -0700133 return Collections.emptySet();
134 }
135
136 UiTopoLayoutId parentId = layout.parent();
137 return layoutMap.values().stream()
Simon Hunte43cccebf2016-09-01 17:01:58 -0700138 // all layouts who are NOT me (or root) and who share my parent...
Simon Huntb1ce2602016-07-23 14:04:31 -0700139 .filter(l -> !Objects.equals(l.id(), layoutId) &&
Simon Hunte43cccebf2016-09-01 17:01:58 -0700140 !Objects.equals(l.id(), UiTopoLayoutId.DEFAULT_ID) &&
Simon Huntb1ce2602016-07-23 14:04:31 -0700141 Objects.equals(l.parent(), parentId))
142 .collect(Collectors.toSet());
143 }
144
145 @Override
Thomas Vachuska92b016b2016-05-20 11:37:57 -0700146 public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) {
147 checkNotNull(layoutId, ID_NULL);
148 return layoutMap.values().stream()
Simon Hunt98189192016-07-29 19:02:27 -0700149 .filter(l -> !l.isRoot() && Objects.equals(l.parent(), layoutId))
Thomas Vachuska92b016b2016-05-20 11:37:57 -0700150 .collect(Collectors.toSet());
151 }
152
153 @Override
Simon Huntf679c4e2016-04-01 17:02:24 -0700154 public boolean removeLayout(UiTopoLayout layout) {
Thomas Vachuska92b016b2016-05-20 11:37:57 -0700155 checkNotNull(layout, LAYOUT_NULL);
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -0700156 return layouts.remove(layout.id()) != null;
Simon Huntf679c4e2016-04-01 17:02:24 -0700157 }
Thomas Vachuska4d66d0a2016-04-15 15:48:13 -0700158
Simon Huntf679c4e2016-04-01 17:02:24 -0700159}