d19ac3f1cbd311505b2a8ffb1064062f9624c4d7
[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 com.google.common.annotations.VisibleForTesting;
11 import com.google.common.base.Function;
12 import com.google.common.collect.Lists;
13 import com.google.common.collect.Maps;
14 import com.google.common.collect.Sets;
15 import org.opendaylight.controller.yang.model.api.TypeDefinition;
16 import org.opendaylight.controller.yang.model.api.type.UnionTypeDefinition;
17 import org.opendaylight.controller.yang.model.util.ExtendedType;
18 import org.opendaylight.controller.yang.parser.util.TopologicalSort;
19 import org.opendaylight.controller.yang.parser.util.TopologicalSort.Node;
20 import org.opendaylight.controller.yang.parser.util.TopologicalSort.NodeImpl;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27
28 public class UnionDependencySort {
29     private static final Logger logger = LoggerFactory
30             .getLogger(UnionDependencySort.class);
31
32     public static List<ExtendedType> sort(
33             final Set<TypeDefinition<?>> typeDefinitions) {
34         if (typeDefinitions == null) {
35             logger.error("Set of Type Definitions cannot be NULL!");
36             throw new IllegalArgumentException("Set of Type Definitions " +
37                     "cannot be NULL!");
38         }
39
40         final Set<ExtendedType> extUnionTypes =
41                 unionsFromTypeDefinitions(typeDefinitions);
42
43         final Set<Node> unsorted = unionTypesToUnionNodes(extUnionTypes);
44
45         final List<Node> sortedNodes = TopologicalSort.sort(unsorted);
46         return Lists.transform(sortedNodes, new Function<Node, ExtendedType>() {
47             @Override
48             public ExtendedType apply(Node input) {
49                 return ((UnionNode) input).getUnionType();
50             }
51         });
52     }
53
54     private static Set<ExtendedType> unionsFromTypeDefinitions(
55             final Set<TypeDefinition<?>> typeDefinitions) {
56         final Set<ExtendedType> unions = Sets.newHashSet();
57
58         for (final TypeDefinition<?> typedef : typeDefinitions) {
59             if ((typedef != null) && (typedef.getBaseType() != null)) {
60                 if (typedef instanceof ExtendedType
61                         && typedef.getBaseType() instanceof UnionTypeDefinition) {
62                     unions.add((ExtendedType) typedef);
63                 }
64             }
65         }
66         return unions;
67     }
68
69     private static Set<Node> unionTypesToUnionNodes(
70             final Set<ExtendedType> extUnionTypes) {
71         final Map<ExtendedType, Node> nodeMap = Maps.newHashMap();
72         final Set<Node> resultNodes = Sets.newHashSet();
73
74         for (final ExtendedType unionType : extUnionTypes) {
75             final Node node = new UnionNode(unionType);
76             nodeMap.put(unionType, node);
77             resultNodes.add(node);
78         }
79
80         for (final Node node : resultNodes) {
81             final UnionNode unionNode = (UnionNode) node;
82             final ExtendedType extUnionType = unionNode.getUnionType();
83
84             final UnionTypeDefinition unionType = (UnionTypeDefinition)
85                     extUnionType.getBaseType();
86
87             final List<TypeDefinition<?>> innerTypes = unionType.getTypes();
88             for (final TypeDefinition<?> typedef : innerTypes) {
89                 if (extUnionTypes.contains(typedef)) {
90                     final Node toNode = nodeMap.get(typedef);
91                     unionNode.addEdge(toNode);
92                 }
93             }
94         }
95
96         return resultNodes;
97     }
98
99     private static UnionNode unionTypeToUnionNode(
100             final ExtendedType extUnionType,
101             final Set<ExtendedType> extUnionTypes) {
102         final UnionNode node = new UnionNode(extUnionType);
103
104         if (extUnionType.getBaseType() instanceof UnionTypeDefinition) {
105             final UnionTypeDefinition unionType = (UnionTypeDefinition)
106                     extUnionType.getBaseType();
107
108             final List<TypeDefinition<?>> innerTypes = unionType.getTypes();
109             for (final TypeDefinition<?> typedef : innerTypes) {
110                 if ((typedef != null) && (typedef instanceof ExtendedType)
111                         && (typedef.getBaseType() instanceof UnionTypeDefinition)) {
112                     if (extUnionTypes.contains(typedef)) {
113                         node.addEdge(new UnionNode((ExtendedType) typedef));
114                     }
115                 }
116             }
117         }
118
119         return node;
120     }
121
122     @VisibleForTesting
123     static final class UnionNode extends NodeImpl {
124         private final ExtendedType unionType;
125
126         UnionNode(ExtendedType unionType) {
127             this.unionType = unionType;
128         }
129
130         ExtendedType getUnionType() {
131             return unionType;
132         }
133
134         @Override
135         public boolean equals(Object o) {
136             if (this == o) {
137                 return true;
138             }
139             if (!(o instanceof UnionNode)) {
140                 return false;
141             }
142             UnionNode unionNode = (UnionNode) o;
143             if (!unionType.equals(unionNode.unionType)) {
144                 return false;
145             }
146             return true;
147         }
148
149         @Override
150         public int hashCode() {
151             return unionType.hashCode();
152         }
153
154         @Override
155         public String toString() {
156             return "UnionNode{" +
157                     "unionType=" + unionType +
158                     '}';
159         }
160     }
161 }