blob: 1ec6929c16c19f5f45727fb6da5577df3d2920a8 [file] [log] [blame]
Yuta HIGUCHId6a576d2017-08-03 18:35:55 -07001/*
2 * Copyright 2017-present Open Networking Foundation
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.d.config;
17
18import static com.google.common.base.Preconditions.checkArgument;
19import static com.google.common.base.Preconditions.checkNotNull;
20import static org.slf4j.LoggerFactory.getLogger;
21
22import java.util.Collections;
23import java.util.IdentityHashMap;
24import java.util.Map;
25import java.util.concurrent.CompletableFuture;
26
27import org.onosproject.config.DynamicConfigEvent;
28import org.onosproject.config.DynamicConfigListener;
29import org.onosproject.config.DynamicConfigService;
30import org.onosproject.config.Filter;
31import org.onosproject.config.ForwardingDynamicConfigService;
32import org.onosproject.net.DeviceId;
33import org.onosproject.yang.model.DataNode;
34import org.onosproject.yang.model.ResourceId;
35import org.onosproject.yang.model.RpcInput;
36import org.onosproject.yang.model.RpcOutput;
37import org.slf4j.Logger;
38
39import com.google.common.annotations.Beta;
40
41/**
42 * DynamicConfigService interface to provide a viewport
43 * under specified Device's tree.
44 */
45@Beta
46public class DynamicDeviceConfigServiceView
47 extends ForwardingDynamicConfigService
48 implements DynamicConfigService {
49
50 private static final Logger log = getLogger(DynamicDeviceConfigServiceView.class);
51
52 private final DeviceId deviceId;
53
54 private ResourceId deviceRoot;
55
56 /**
57 * original to wrapped listener.
58 */
59 private final Map<DynamicConfigListener, DynamicConfigListener> wrapped =
60 Collections.synchronizedMap(new IdentityHashMap<>());
61
62 protected DynamicDeviceConfigServiceView(DynamicConfigService delegate, DeviceId deviceId) {
63 super(delegate);
64 this.deviceId = checkNotNull(deviceId);
65 this.deviceRoot = DeviceResourceIds.toResourceId(this.deviceId);
66 }
67
68 /**
69 * Create a DynamicDeviceConfigServiceView for specified {@code deviceId}.
70 *
71 * @param service reference to actual DynamicConfigService.
72 * @param deviceId of the Device to provide view port about.
73 * @return DynamicDeviceConfigServiceView
74 */
75 public static DynamicDeviceConfigServiceView deviceView(DynamicConfigService service,
76 DeviceId deviceId) {
77 return new DynamicDeviceConfigServiceView(service, deviceId);
78 }
79
80 @Override
81 public void createNode(ResourceId path, DataNode node) {
82 super.createNode(toAbsoluteId(path), node);
83 }
84
85 @Override
86 public DataNode readNode(ResourceId path, Filter filter) {
87 // FIXME transform filter? is it possible?
88 return super.readNode(toAbsoluteId(path), filter);
89 }
90
91 @Override
92 public Boolean nodeExist(ResourceId path) {
93 return super.nodeExist(toAbsoluteId(path));
94 }
95
96 @Override
97 public void updateNode(ResourceId path, DataNode node) {
98 super.updateNode(toAbsoluteId(path), node);
99 }
100
101 @Override
102 public void replaceNode(ResourceId path, DataNode node) {
103 super.replaceNode(toAbsoluteId(path), node);
104 }
105
106 @Override
107 public void deleteNode(ResourceId path) {
108 super.deleteNode(toAbsoluteId(path));
109 }
110
111 @Override
112 public CompletableFuture<RpcOutput> invokeRpc(ResourceId id,
113 RpcInput input) {
114 return super.invokeRpc(toAbsoluteId(id), input);
115 }
116
117 @Override
118 public void addListener(DynamicConfigListener listener) {
119 super.addListener(wrapped.computeIfAbsent(listener,
120 DynamicDeviceConfigListener::new));
121 }
122
123 @Override
124 public void removeListener(DynamicConfigListener listener) {
125 DynamicConfigListener w = wrapped.remove(listener);
126 if (w != null) {
127 super.removeListener(w);
128 }
129 }
130
131 private ResourceId toAbsoluteId(ResourceId path) {
132 checkArgument(!path.nodeKeys().contains(DeviceResourceIds.ROOT_NODE),
133 "%s was already absolute path", path);
134
135 return ResourceIds.concat(deviceRoot, path);
136 }
137
138 private ResourceId toDeviceRelativeId(ResourceId path) {
139 checkArgument(path.nodeKeys().contains(DeviceResourceIds.ROOT_NODE),
140 "%s was not absolute path", path);
141
142 return ResourceIds.relativize(deviceRoot, path);
143 }
144
145 class DynamicDeviceConfigListener implements DynamicConfigListener {
146
147 private final DynamicConfigListener lsnr;
148
149 DynamicDeviceConfigListener(DynamicConfigListener lsnr) {
150 this.lsnr = checkNotNull(lsnr);
151 }
152
153 private DynamicConfigEvent deviceEvent(DynamicConfigEvent event) {
154 return new DynamicConfigEvent(event.type(),
155 toDeviceRelativeId(event.subject()));
156 }
157
158 @Override
159 public boolean isRelevant(DynamicConfigEvent event) {
160 // FIXME ignore event irrelevant to current device
161 return lsnr.isRelevant(deviceEvent(event));
162 }
163
164 @Override
165 public void event(DynamicConfigEvent event) {
166 lsnr.event(deviceEvent(event));
167 }
168
169 }
170}