2 * Copyright (c) 2016 Cisco and/or its affiliates.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package io.fd.honeycomb.translate.util;
19 import com.google.common.base.Preconditions;
20 import com.google.common.collect.ImmutableMap;
21 import io.fd.honeycomb.translate.ModifiableSubtreeManagerRegistryBuilder;
22 import io.fd.honeycomb.translate.SubtreeManager;
23 import io.fd.honeycomb.translate.SubtreeManagerRegistryBuilder;
24 import org.opendaylight.yangtools.yang.binding.DataObject;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import javax.annotation.Nonnull;
28 import java.util.Collection;
29 import java.util.HashMap;
33 public abstract class AbstractSubtreeManagerRegistryBuilderBuilder<S extends SubtreeManager<? extends DataObject>, R>
34 implements ModifiableSubtreeManagerRegistryBuilder<S>, SubtreeManagerRegistryBuilder<R> {
36 private final Map<InstanceIdentifier<?>, S> handlersMap = new HashMap<>();
37 private final YangDAG dag;
39 protected AbstractSubtreeManagerRegistryBuilderBuilder(@Nonnull final YangDAG yangDAG) {
40 this.dag = Preconditions.checkNotNull(yangDAG, "yangDAG should not be null");
44 * Add handler without any special relationship to any other type.
47 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> add(@Nonnull final S handler) {
48 // Make IID wildcarded just in case
49 // + the way InstanceIdentifier.create + equals work for Identifiable items is unexpected, meaning updates would
50 // not be matched to writers in registry
51 final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
52 checkWriterNotPresentYet(targetType);
53 dag.addVertex(targetType);
54 handlersMap.put(targetType, handler);
59 * Add handler without any special relationship to any other type.
62 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> subtreeAdd(@Nonnull final Set<InstanceIdentifier<?>> handledChildren,
63 @Nonnull final S handler) {
64 add(getSubtreeHandler(handledChildren, handler));
69 public ModifiableSubtreeManagerRegistryBuilder<S> wildcardedSubtreeAdd(@Nonnull S handler) {
70 add(getWildcardedSubtreeHandler(handler));
74 private void checkWriterNotPresentYet(final InstanceIdentifier<?> targetType) {
75 Preconditions.checkArgument(!handlersMap.containsKey(targetType),
76 "Writer for type: %s already present: %s", targetType, handlersMap.get(targetType));
80 * Add handler with relationship: to be executed before handler handling relatedType.
83 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> addBefore(@Nonnull final S handler,
84 @Nonnull final InstanceIdentifier<?> relatedType) {
85 final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
86 final InstanceIdentifier<?> wildcardedRelatedType = RWUtils.makeIidWildcarded(relatedType);
87 checkWriterNotPresentYet(targetType);
88 dag.addVertex(targetType);
89 dag.addVertex(wildcardedRelatedType);
90 dag.addEdge(targetType, wildcardedRelatedType);
91 handlersMap.put(targetType, handler);
96 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> addBefore(@Nonnull final S handler,
97 @Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
98 final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
99 checkWriterNotPresentYet(targetType);
100 dag.addVertex(targetType);
101 relatedTypes.stream()
102 .map(RWUtils::makeIidWildcarded)
103 .forEach(dag::addVertex);
104 relatedTypes.stream()
105 .map(RWUtils::makeIidWildcarded)
106 .forEach(type -> dag.addEdge(targetType, type));
107 handlersMap.put(targetType, handler);
112 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> subtreeAddBefore(
113 @Nonnull final Set<InstanceIdentifier<?>> handledChildren,
114 @Nonnull final S handler,
115 @Nonnull final InstanceIdentifier<?> relatedType) {
116 return addBefore(getSubtreeHandler(handledChildren, handler), relatedType);
120 public ModifiableSubtreeManagerRegistryBuilder<S> wildcardedSubtreeAddBefore(@Nonnull final S handler,
121 @Nonnull final InstanceIdentifier<?> relatedType) {
122 return addBefore(getWildcardedSubtreeHandler(handler), relatedType);
126 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> subtreeAddBefore(
127 @Nonnull final Set<InstanceIdentifier<?>> handledChildren,
128 @Nonnull final S handler,
129 @Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
130 return addBefore(getSubtreeHandler(handledChildren, handler), relatedTypes);
134 public ModifiableSubtreeManagerRegistryBuilder<S> wildcardedSubtreeAddBefore(@Nonnull final S handler,
135 @Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
136 return addBefore(getWildcardedSubtreeHandler(handler), relatedTypes);
139 protected abstract S getSubtreeHandler(@Nonnull final Set<InstanceIdentifier<?>> handledChildren,
140 @Nonnull final S handler);
142 protected abstract S getWildcardedSubtreeHandler(@Nonnull final S handler);
145 * Add handler with relationship: to be executed after handler handling relatedType.
148 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> addAfter(@Nonnull final S handler,
149 @Nonnull final InstanceIdentifier<?> relatedType) {
150 final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
151 final InstanceIdentifier<?> wildcardedRelatedType = RWUtils.makeIidWildcarded(relatedType);
152 checkWriterNotPresentYet(targetType);
153 dag.addVertex(targetType);
154 dag.addVertex(wildcardedRelatedType);
155 // set edge to indicate before relationship, just reversed
156 dag.addEdge(wildcardedRelatedType, targetType);
157 handlersMap.put(targetType, handler);
162 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> addAfter(@Nonnull final S handler,
163 @Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
164 final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
165 checkWriterNotPresentYet(targetType);
166 dag.addVertex(targetType);
167 relatedTypes.stream()
168 .map(RWUtils::makeIidWildcarded)
169 .forEach(dag::addVertex);
170 // set edge to indicate before relationship, just reversed
171 relatedTypes.stream()
172 .map(RWUtils::makeIidWildcarded)
173 .forEach(type -> dag.addEdge(type, targetType));
174 handlersMap.put(targetType, handler);
179 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> subtreeAddAfter(
180 @Nonnull final Set<InstanceIdentifier<?>> handledChildren,
181 @Nonnull final S handler,
182 @Nonnull final InstanceIdentifier<?> relatedType) {
183 return addAfter(getSubtreeHandler(handledChildren, handler), relatedType);
187 public ModifiableSubtreeManagerRegistryBuilder<S> wildcardedSubtreeAddAfter(@Nonnull final S handler,
188 @Nonnull final InstanceIdentifier<?> relatedType) {
189 return addAfter(getWildcardedSubtreeHandler(handler), relatedType);
193 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> subtreeAddAfter(
194 @Nonnull final Set<InstanceIdentifier<?>> handledChildren,
195 @Nonnull final S handler,
196 @Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
197 return addAfter(getSubtreeHandler(handledChildren, handler), relatedTypes);
201 public ModifiableSubtreeManagerRegistryBuilder<S> wildcardedSubtreeAddAfter(@Nonnull S handler, @Nonnull Collection<InstanceIdentifier<?>> relatedTypes) {
202 return addAfter(getWildcardedSubtreeHandler(handler), relatedTypes);
205 protected ImmutableMap<InstanceIdentifier<?>, S> getMappedHandlers() {
206 final ImmutableMap.Builder<InstanceIdentifier<?>, S> builder = ImmutableMap.builder();
207 // Iterate writer types according to their relationships from graph
208 dag.iterator().forEachRemaining(handlerType -> {
209 // There might be types stored just for relationship sake, no real writer, ignoring those
210 if (handlersMap.containsKey(handlerType)) {
211 builder.put(handlerType, handlersMap.get(handlerType));
215 // TODO HONEYCOMB-171 we could optimize subtree handlers, if there is a dedicated handler for a node managed by a subtree
216 // handler, recreate the subtree handler with a subset of handled child nodes
217 // This way it is not necessary to change the configuration of subtree writer, just to add a dedicated child
220 return builder.build();