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 java.util.Collection;
25 import java.util.HashMap;
28 import javax.annotation.Nonnull;
29 import org.opendaylight.yangtools.yang.binding.DataObject;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
32 public abstract class AbstractSubtreeManagerRegistryBuilderBuilder<S extends SubtreeManager<? extends DataObject>, R>
33 implements ModifiableSubtreeManagerRegistryBuilder<S>, SubtreeManagerRegistryBuilder<R> {
35 private final Map<InstanceIdentifier<?>, S> handlersMap = new HashMap<>();
36 private final YangDAG dag;
38 protected AbstractSubtreeManagerRegistryBuilderBuilder(@Nonnull final YangDAG yangDAG) {
39 this.dag = Preconditions.checkNotNull(yangDAG, "yangDAG should not be null");
43 * Add handler without any special relationship to any other type.
46 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> add(@Nonnull final S handler) {
47 // Make IID wildcarded just in case
48 // + the way InstanceIdentifier.create + equals work for Identifiable items is unexpected, meaning updates would
49 // not be matched to writers in registry
50 final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
51 checkWriterNotPresentYet(targetType);
52 dag.addVertex(targetType);
53 handlersMap.put(targetType, handler);
58 * Add handler without any special relationship to any other type.
61 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> subtreeAdd(@Nonnull final Set<InstanceIdentifier<?>> handledChildren,
62 @Nonnull final S handler) {
63 add(getSubtreeHandler(handledChildren, handler));
67 private void checkWriterNotPresentYet(final InstanceIdentifier<?> targetType) {
68 Preconditions.checkArgument(!handlersMap.containsKey(targetType),
69 "Writer for type: %s already present: %s", targetType, handlersMap.get(targetType));
73 * Add handler with relationship: to be executed before handler handling relatedType.
76 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> addBefore(@Nonnull final S handler,
77 @Nonnull final InstanceIdentifier<?> relatedType) {
78 final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
79 final InstanceIdentifier<?> wildcardedRelatedType = RWUtils.makeIidWildcarded(relatedType);
80 checkWriterNotPresentYet(targetType);
81 dag.addVertex(targetType);
82 dag.addVertex(wildcardedRelatedType);
83 dag.addEdge(targetType, wildcardedRelatedType);
84 handlersMap.put(targetType, handler);
89 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> addBefore(@Nonnull final S handler,
90 @Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
91 final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
92 checkWriterNotPresentYet(targetType);
93 dag.addVertex(targetType);
95 .map(RWUtils::makeIidWildcarded)
96 .forEach(dag::addVertex);
98 .map(RWUtils::makeIidWildcarded)
99 .forEach(type -> dag.addEdge(targetType, type));
100 handlersMap.put(targetType, handler);
105 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> subtreeAddBefore(
106 @Nonnull final Set<InstanceIdentifier<?>> handledChildren,
107 @Nonnull final S handler,
108 @Nonnull final InstanceIdentifier<?> relatedType) {
109 return addBefore(getSubtreeHandler(handledChildren, handler), relatedType);
113 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> subtreeAddBefore(
114 @Nonnull final Set<InstanceIdentifier<?>> handledChildren,
115 @Nonnull final S handler,
116 @Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
117 return addBefore(getSubtreeHandler(handledChildren, handler), relatedTypes);
120 protected abstract S getSubtreeHandler(@Nonnull final Set<InstanceIdentifier<?>> handledChildren,
121 @Nonnull final S handler);
124 * Add handler with relationship: to be executed after handler handling relatedType.
127 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> addAfter(@Nonnull final S handler,
128 @Nonnull final InstanceIdentifier<?> relatedType) {
129 final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
130 final InstanceIdentifier<?> wildcardedRelatedType = RWUtils.makeIidWildcarded(relatedType);
131 checkWriterNotPresentYet(targetType);
132 dag.addVertex(targetType);
133 dag.addVertex(wildcardedRelatedType);
134 // set edge to indicate before relationship, just reversed
135 dag.addEdge(wildcardedRelatedType, targetType);
136 handlersMap.put(targetType, handler);
141 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> addAfter(@Nonnull final S handler,
142 @Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
143 final InstanceIdentifier<?> targetType = RWUtils.makeIidWildcarded(handler.getManagedDataObjectType());
144 checkWriterNotPresentYet(targetType);
145 dag.addVertex(targetType);
146 relatedTypes.stream()
147 .map(RWUtils::makeIidWildcarded)
148 .forEach(dag::addVertex);
149 // set edge to indicate before relationship, just reversed
150 relatedTypes.stream()
151 .map(RWUtils::makeIidWildcarded)
152 .forEach(type -> dag.addEdge(type, targetType));
153 handlersMap.put(targetType, handler);
158 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> subtreeAddAfter(
159 @Nonnull final Set<InstanceIdentifier<?>> handledChildren,
160 @Nonnull final S handler,
161 @Nonnull final InstanceIdentifier<?> relatedType) {
162 return addAfter(getSubtreeHandler(handledChildren, handler), relatedType);
166 public AbstractSubtreeManagerRegistryBuilderBuilder<S, R> subtreeAddAfter(
167 @Nonnull final Set<InstanceIdentifier<?>> handledChildren,
168 @Nonnull final S handler,
169 @Nonnull final Collection<InstanceIdentifier<?>> relatedTypes) {
170 return addAfter(getSubtreeHandler(handledChildren, handler), relatedTypes);
173 protected ImmutableMap<InstanceIdentifier<?>, S> getMappedHandlers() {
174 final ImmutableMap.Builder<InstanceIdentifier<?>, S> builder = ImmutableMap.builder();
175 // Iterate writer types according to their relationships from graph
176 dag.iterator().forEachRemaining(handlerType -> {
177 // There might be types stored just for relationship sake, no real writer, ignoring those
178 if (handlersMap.containsKey(handlerType)) {
179 builder.put(handlerType, handlersMap.get(handlerType));
183 // TODO HONEYCOMB-171 we could optimize subtree handlers, if there is a dedicated handler for a node managed by a subtree
184 // handler, recreate the subtree handler with a subset of handled child nodes
185 // This way it is not necessary to change the configuration of subtree writer, just to add a dedicated child
188 return builder.build();