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