Degrade DataNodeContainer.getChildNodes() from Set to Collection
[yangtools.git] / yang / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / util / DataNodeIterator.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.yang.model.util;
9
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.Set;
15
16 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
17 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
18 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
19 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
20 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
22 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.Module;
24 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
25 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
26 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
27
28 /**
29  * DataNodeIterator is iterator, which walks down whole YANG DataNodeContainer
30  * and walks all instances of {@link DataSchemaNode} present in subtree.
31  *
32  * Iterator instance is eagerly created, walking happens on initialization.
33  *
34  * Iteration is not ordered.
35  *
36  */
37 public class DataNodeIterator implements Iterator<DataSchemaNode> {
38
39     private final DataNodeContainer container;
40     private final List<ListSchemaNode> allLists;
41     private final List<ContainerSchemaNode> allContainers;
42     private final List<ChoiceNode> allChoices;
43     private final List<DataSchemaNode> allChilds;
44     private final List<GroupingDefinition> allGroupings;
45     private final List<TypeDefinition<?>> allTypedefs;
46
47     public DataNodeIterator(final DataNodeContainer container) {
48         if (container == null) {
49             throw new IllegalArgumentException("Data Node Container MUST be specified and cannot be NULL!");
50         }
51
52         this.allContainers = new ArrayList<>();
53         this.allLists = new ArrayList<>();
54         this.allChilds = new ArrayList<>();
55         this.allChoices = new ArrayList<>();
56         this.allGroupings = new ArrayList<>();
57         this.allTypedefs = new ArrayList<>();
58
59         this.container = container;
60         traverse(this.container);
61     }
62
63     /**
64      * Returns list all containers present in subtree.
65      *
66      * @return Returns list all containers present in subtree.
67      */
68     public List<ContainerSchemaNode> allContainers() {
69         return allContainers;
70     }
71
72     /**
73      * Returns list all lists present in subtree.
74      *
75      * @return Returns list all containers present in subtree.
76      */
77     public List<ListSchemaNode> allLists() {
78         return allLists;
79     }
80
81     /**
82      * Returns list all choices present in subtree.
83      *
84      * @return Returns list all containers present in subtree.
85      */
86     public List<ChoiceNode> allChoices() {
87         return allChoices;
88     }
89
90     /**
91      * Returns list all groupings present in subtree.
92      *
93      * @return Returns list all containers present in subtree.
94      */
95     public List<GroupingDefinition> allGroupings() {
96         return allGroupings;
97     }
98
99     /**
100      * Returns list all typedefs present in subtree.
101      *
102      * @return Returns list all containers present in subtree.
103      */
104     public List<TypeDefinition<?>> allTypedefs() {
105         return allTypedefs;
106     }
107
108     private void traverse(final DataNodeContainer dataNode) {
109         if (dataNode == null) {
110             return;
111         }
112
113         final Iterable<DataSchemaNode> childNodes = dataNode.getChildNodes();
114         if (childNodes != null) {
115             for (DataSchemaNode childNode : childNodes) {
116                 if (childNode.isAugmenting()) {
117                     continue;
118                 }
119                 allChilds.add(childNode);
120                 if (childNode instanceof ContainerSchemaNode) {
121                     final ContainerSchemaNode containerNode = (ContainerSchemaNode) childNode;
122                     allContainers.add(containerNode);
123                     traverse(containerNode);
124                 } else if (childNode instanceof ListSchemaNode) {
125                     final ListSchemaNode list = (ListSchemaNode) childNode;
126                     allLists.add(list);
127                     traverse(list);
128                 } else if (childNode instanceof ChoiceNode) {
129                     final ChoiceNode choiceNode = (ChoiceNode) childNode;
130                     allChoices.add(choiceNode);
131                     final Set<ChoiceCaseNode> cases = choiceNode.getCases();
132                     if (cases != null) {
133                         for (final ChoiceCaseNode caseNode : cases) {
134                             traverse(caseNode);
135                         }
136                     }
137                 }
138             }
139         }
140
141         this.allTypedefs.addAll(dataNode.getTypeDefinitions());
142         traverseModule(dataNode);
143         traverseGroupings(dataNode);
144
145     }
146
147     private void traverseModule(final DataNodeContainer dataNode) {
148         final Module module;
149         if (dataNode instanceof Module) {
150             module = (Module) dataNode;
151         } else {
152             return;
153         }
154
155         final Set<NotificationDefinition> notifications = module.getNotifications();
156         for (NotificationDefinition notificationDefinition : notifications) {
157             traverse(notificationDefinition);
158         }
159
160         final Set<RpcDefinition> rpcs = module.getRpcs();
161         for (RpcDefinition rpcDefinition : rpcs) {
162             this.allTypedefs.addAll(rpcDefinition.getTypeDefinitions());
163             ContainerSchemaNode input = rpcDefinition.getInput();
164             if (input != null) {
165                 traverse(input);
166             }
167             ContainerSchemaNode output = rpcDefinition.getInput();
168             if (input != null) {
169                 traverse(output);
170             }
171         }
172     }
173
174     private void traverseGroupings(final DataNodeContainer dataNode) {
175         final Set<GroupingDefinition> groupings = dataNode.getGroupings();
176         if (groupings != null) {
177             for (GroupingDefinition grouping : groupings) {
178                 allGroupings.add(grouping);
179                 traverse(grouping);
180             }
181         }
182     }
183
184     @Override
185     public boolean hasNext() {
186         if (container.getChildNodes() != null) {
187             final Collection<DataSchemaNode> childNodes = container.getChildNodes();
188
189             if ((childNodes != null) && !childNodes.isEmpty()) {
190                 return childNodes.iterator().hasNext();
191             }
192         }
193         return false;
194     }
195
196     @Override
197     public DataSchemaNode next() {
198         return allChilds.iterator().next();
199     }
200
201     @Override
202     public void remove() {
203         throw new UnsupportedOperationException();
204     }
205 }