Merge "OF plugin classes must have a strict dependency on Connection Service"
[controller.git] / opendaylight / sal / yang-prototype / code-generator / binding-generator-impl / src / main / java / org / opendaylight / controller / sal / binding / yang / types / UnionDependencySort.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.sal.binding.yang.types;
9
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13
14 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
15 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
16 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
17 import org.opendaylight.yangtools.yang.parser.util.TopologicalSort;
18 import org.opendaylight.yangtools.yang.parser.util.TopologicalSort.Node;
19 import org.opendaylight.yangtools.yang.parser.util.TopologicalSort.NodeImpl;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 import com.google.common.annotations.VisibleForTesting;
24 import com.google.common.base.Function;
25 import com.google.common.collect.Lists;
26 import com.google.common.collect.Maps;
27 import com.google.common.collect.Sets;
28
29 public class UnionDependencySort {
30     private static final Logger logger = LoggerFactory
31             .getLogger(UnionDependencySort.class);
32
33     public static List<ExtendedType> sort(
34             final Set<TypeDefinition<?>> typeDefinitions) {
35         if (typeDefinitions == null) {
36             logger.error("Set of Type Definitions cannot be NULL!");
37             throw new IllegalArgumentException("Set of Type Definitions " +
38                     "cannot be NULL!");
39         }
40
41         final Set<ExtendedType> extUnionTypes =
42                 unionsFromTypeDefinitions(typeDefinitions);
43
44         final Set<Node> unsorted = unionTypesToUnionNodes(extUnionTypes);
45
46         final List<Node> sortedNodes = TopologicalSort.sort(unsorted);
47         return Lists.transform(sortedNodes, new Function<Node, ExtendedType>() {
48             @Override
49             public ExtendedType apply(Node input) {
50                 return ((UnionNode) input).getUnionType();
51             }
52         });
53     }
54
55     private static Set<ExtendedType> unionsFromTypeDefinitions(
56             final Set<TypeDefinition<?>> typeDefinitions) {
57         final Set<ExtendedType> unions = Sets.newHashSet();
58
59         for (final TypeDefinition<?> typedef : typeDefinitions) {
60             if ((typedef != null) && (typedef.getBaseType() != null)) {
61                 if (typedef instanceof ExtendedType
62                         && typedef.getBaseType() instanceof UnionTypeDefinition) {
63                     unions.add((ExtendedType) typedef);
64                 }
65             }
66         }
67         return unions;
68     }
69
70     private static Set<Node> unionTypesToUnionNodes(
71             final Set<ExtendedType> extUnionTypes) {
72         final Map<ExtendedType, Node> nodeMap = Maps.newHashMap();
73         final Set<Node> resultNodes = Sets.newHashSet();
74
75         for (final ExtendedType unionType : extUnionTypes) {
76             final Node node = new UnionNode(unionType);
77             nodeMap.put(unionType, node);
78             resultNodes.add(node);
79         }
80
81         for (final Node node : resultNodes) {
82             final UnionNode unionNode = (UnionNode) node;
83             final ExtendedType extUnionType = unionNode.getUnionType();
84
85             final UnionTypeDefinition unionType = (UnionTypeDefinition)
86                     extUnionType.getBaseType();
87
88             final List<TypeDefinition<?>> innerTypes = unionType.getTypes();
89             for (final TypeDefinition<?> typedef : innerTypes) {
90                 if (extUnionTypes.contains(typedef)) {
91                     final Node toNode = nodeMap.get(typedef);
92                     unionNode.addEdge(toNode);
93                 }
94             }
95         }
96
97         return resultNodes;
98     }
99
100     private static UnionNode unionTypeToUnionNode(
101             final ExtendedType extUnionType,
102             final Set<ExtendedType> extUnionTypes) {
103         final UnionNode node = new UnionNode(extUnionType);
104
105         if (extUnionType.getBaseType() instanceof UnionTypeDefinition) {
106             final UnionTypeDefinition unionType = (UnionTypeDefinition)
107                     extUnionType.getBaseType();
108
109             final List<TypeDefinition<?>> innerTypes = unionType.getTypes();
110             for (final TypeDefinition<?> typedef : innerTypes) {
111                 if ((typedef != null) && (typedef instanceof ExtendedType)
112                         && (typedef.getBaseType() instanceof UnionTypeDefinition)) {
113                     if (extUnionTypes.contains(typedef)) {
114                         node.addEdge(new UnionNode((ExtendedType) typedef));
115                     }
116                 }
117             }
118         }
119
120         return node;
121     }
122
123     @VisibleForTesting
124     static final class UnionNode extends NodeImpl {
125         private final ExtendedType unionType;
126
127         UnionNode(ExtendedType unionType) {
128             this.unionType = unionType;
129         }
130
131         ExtendedType getUnionType() {
132             return unionType;
133         }
134
135         @Override
136         public boolean equals(Object o) {
137             if (this == o) {
138                 return true;
139             }
140             if (!(o instanceof UnionNode)) {
141                 return false;
142             }
143             UnionNode unionNode = (UnionNode) o;
144             if (!unionType.equals(unionNode.unionType)) {
145                 return false;
146             }
147             return true;
148         }
149
150         @Override
151         public int hashCode() {
152             return unionType.hashCode();
153         }
154
155         @Override
156         public String toString() {
157             return "UnionNode{" +
158                     "unionType=" + unionType +
159                     '}';
160         }
161     }
162 }