Fixed some major sonar issues in yang-validation-tool
[yangtools.git] / code-generator / binding-type-provider / src / main / java / org / opendaylight / yangtools / 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.yangtools.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.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 import com.google.common.base.Function;
23 import com.google.common.collect.Lists;
24 import com.google.common.collect.Maps;
25 import com.google.common.collect.Sets;
26
27 public class UnionDependencySort {
28     private static final Logger LOGGER = LoggerFactory.getLogger(UnionDependencySort.class);
29
30     /**
31      * Sorts union types by mutual dependencies.
32      * 
33      * At the beginning the union types are selected from
34      * <code>typeDefinitions</code> and wrapped to nodes. The nodes are sorted
35      * and then the wrapped payload is extracted.
36      * 
37      * @param typeDefinitions
38      *            set of type definitions.
39      * @return list of extended type which are sorted by mutual dependencies
40      * @throws IllegalArgumentException
41      *             if <code>typeDefinitions</code> equals <code>null</code>
42      */
43     public List<ExtendedType> sort(final Set<TypeDefinition<?>> typeDefinitions) {
44         if (typeDefinitions == null) {
45             LOGGER.error("Set of Type Definitions cannot be NULL!");
46             throw new IllegalArgumentException("Set of Type Definitions " + "cannot be NULL!");
47         }
48
49         final Set<ExtendedType> extUnionTypes = unionsFromTypeDefinitions(typeDefinitions);
50
51         final Set<Node> unsorted = unionTypesToNodes(extUnionTypes);
52
53         final List<Node> sortedNodes = TopologicalSort.sort(unsorted);
54         return Lists.transform(sortedNodes, new Function<Node, ExtendedType>() {
55             @Override
56             public ExtendedType apply(Node input) {
57                 return (ExtendedType) (((NodeWrappedType) input).getWrappedType());
58             }
59         });
60     }
61
62     /**
63      * Extracts only union types from <code>typeDefinitions</code> set.
64      * 
65      * @param typeDefinitions
66      *            set of all type definitions
67      * @return set of extended type which are union type definition
68      */
69     private Set<ExtendedType> unionsFromTypeDefinitions(final Set<TypeDefinition<?>> typeDefinitions) {
70         final Set<ExtendedType> unions = Sets.newHashSet();
71
72         for (final TypeDefinition<?> typedef : typeDefinitions) {
73             if ((typedef != null) && (typedef.getBaseType() != null) && (typedef instanceof ExtendedType)
74                     && (typedef.getBaseType() instanceof UnionTypeDefinition)) {
75                 unions.add((ExtendedType) typedef);
76             }
77         }
78         return unions;
79     }
80
81     /**
82      * Wraps every extended type which represents union to node type and adds to
83      * every node information about dependencies.
84      * 
85      * The mapping from union type to node is created. For every created node
86      * (next <i>nodeFrom</i>) is for its wrapped union type passed the list of
87      * inner types through and only those inner types which represent union type
88      * are next considered. For every inner union type is found its wrapping
89      * node (next as <i>nodeTo</i>). This dependency relationship between
90      * nodeFrom and all found nodesTo is modeled with creating of one edge from
91      * nodeFrom to nodeTo.
92      * 
93      * 
94      * @param extUnionTypes
95      *            set of extended types which represents union types
96      * @return set of nodes which contains wrapped union types set of node where
97      *         each one contains wrapped one union type
98      */
99     private Set<Node> unionTypesToNodes(final Set<ExtendedType> extUnionTypes) {
100         final Map<ExtendedType, Node> nodeMap = Maps.newHashMap();
101         final Set<Node> resultNodes = Sets.newHashSet();
102
103         for (final ExtendedType unionType : extUnionTypes) {
104             final Node node = new NodeWrappedType(unionType);
105             nodeMap.put(unionType, node);
106             resultNodes.add(node);
107         }
108
109         for (final Node node : resultNodes) {
110             final NodeWrappedType nodeFrom = (NodeWrappedType) node;
111             final ExtendedType extUnionType = (ExtendedType) nodeFrom.getWrappedType();
112
113             final UnionTypeDefinition unionType = (UnionTypeDefinition) extUnionType.getBaseType();
114
115             final List<TypeDefinition<?>> innerTypes = unionType.getTypes();
116             for (final TypeDefinition<?> typedef : innerTypes) {
117                 if (extUnionTypes.contains(typedef)) {
118                     final Node toNode = nodeMap.get(typedef);
119                     nodeFrom.addEdge(toNode);
120                 }
121             }
122         }
123
124         return resultNodes;
125     }
126
127 }