005e3bc8d36b4ace13e1b0ef079abc58e8c4c89e
[hc2vpp.git] /
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
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  */
16
17 package io.fd.honeycomb.v3po.translate.util.read.registry;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20
21 import com.google.common.collect.Iterables;
22 import java.util.HashSet;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Set;
26 import java.util.stream.Collectors;
27 import javax.annotation.Nonnull;
28 import org.jgrapht.experimental.dag.DirectedAcyclicGraph;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30
31 final class TypeHierarchy {
32     private final DirectedAcyclicGraph<InstanceIdentifier<?>, Parent> hierarchy;
33
34     private TypeHierarchy(@Nonnull final DirectedAcyclicGraph<InstanceIdentifier<?>, Parent> hierarchy) {
35         this.hierarchy = hierarchy;
36     }
37
38     Set<InstanceIdentifier<?>> getAllChildren(InstanceIdentifier<?> id) {
39         final HashSet<InstanceIdentifier<?>> instanceIdentifiers = new HashSet<>();
40         for (InstanceIdentifier<?> childId : getDirectChildren(id)) {
41             instanceIdentifiers.add(childId);
42             instanceIdentifiers.addAll(getAllChildren(childId));
43         }
44         return instanceIdentifiers;
45     }
46
47     Set<InstanceIdentifier<?>> getDirectChildren(InstanceIdentifier<?> id) {
48         checkArgument(hierarchy.vertexSet().contains(id),
49                 "Unknown reader: %s. Known readers: %s", id, hierarchy.vertexSet());
50
51         return hierarchy.outgoingEdgesOf(id).stream()
52                 .map(hierarchy::getEdgeTarget)
53                 .collect(Collectors.toSet());
54     }
55
56     Set<InstanceIdentifier<?>> getRoots() {
57         return hierarchy.vertexSet().stream()
58                 .filter(vertex -> hierarchy.incomingEdgesOf(vertex).size() == 0)
59                 .collect(Collectors.toSet());
60     }
61
62     /**
63      * Create reader hierarchy from a flat set of instance identifiers.
64      *
65      * @param allIds Set of unkeyed instance identifiers
66      */
67     static TypeHierarchy create(@Nonnull Set<InstanceIdentifier<?>> allIds) {
68         final DirectedAcyclicGraph<InstanceIdentifier<?>, Parent>
69                 readersHierarchy = new DirectedAcyclicGraph<>((sourceVertex, targetVertex) -> new Parent());
70
71         for (InstanceIdentifier<?> allId : allIds) {
72             checkArgument(!Iterables.isEmpty(allId.getPathArguments()), "Empty ID detected");
73
74             if (Iterables.size(allId.getPathArguments()) == 1) {
75                 readersHierarchy.addVertex(allId);
76             }
77
78             List<InstanceIdentifier.PathArgument> pathArgs = new LinkedList<>();
79             pathArgs.add(allId.getPathArguments().iterator().next());
80
81             for (InstanceIdentifier.PathArgument pathArgument : Iterables.skip(allId.getPathArguments(), 1)) {
82                 final InstanceIdentifier<?> previous = InstanceIdentifier.create(pathArgs);
83                 pathArgs.add(pathArgument);
84                 final InstanceIdentifier<?> current = InstanceIdentifier.create(pathArgs);
85
86                 readersHierarchy.addVertex(previous);
87                 readersHierarchy.addVertex(current);
88
89                 try {
90                     readersHierarchy.addDagEdge(previous, current);
91                 } catch (DirectedAcyclicGraph.CycleFoundException e) {
92                     throw new IllegalArgumentException("Loop in hierarchy detected", e);
93                 }
94             }
95         }
96
97         return new TypeHierarchy(readersHierarchy);
98     }
99
100     private static final class Parent{}
101 }