Merge branch 'master' of ../controller
[yangtools.git] / yang / yang-data-util / src / main / java / org / opendaylight / yangtools / yang / data / util / ParserStreamUtils.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.yangtools.yang.data.util;
10
11 import java.net.URI;
12 import java.util.ArrayDeque;
13 import java.util.ArrayList;
14 import java.util.Deque;
15 import java.util.List;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.common.Revision;
18 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
19 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
21 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
22
23 public final class ParserStreamUtils {
24
25     private ParserStreamUtils() {
26         throw new UnsupportedOperationException("Utility class should not be instantiated.");
27     }
28
29     /**
30      * Returns stack of schema nodes via which it was necessary to pass to get schema node with specified
31      * {@code childName} and {@code namespace}.
32      *
33      * @return stack of schema nodes via which it was passed through. If found schema node is direct child then stack
34      *         contains only one node. If it is found under choice and case then stack should contains 2*n+1 element
35      *         (where n is number of choices through it was passed)
36      */
37     public static Deque<DataSchemaNode> findSchemaNodeByNameAndNamespace(final DataSchemaNode dataSchemaNode,
38                                                                    final String childName, final URI namespace) {
39         final Deque<DataSchemaNode> result = new ArrayDeque<>();
40         final List<ChoiceSchemaNode> childChoices = new ArrayList<>();
41         DataSchemaNode potentialChildNode = null;
42         if (dataSchemaNode instanceof DataNodeContainer) {
43             for (final DataSchemaNode childNode : ((DataNodeContainer) dataSchemaNode).getChildNodes()) {
44                 if (childNode instanceof ChoiceSchemaNode) {
45                     childChoices.add((ChoiceSchemaNode) childNode);
46                 } else {
47                     final QName childQName = childNode.getQName();
48                     if (childQName.getLocalName().equals(childName) && childQName.getNamespace().equals(namespace)
49                             && (potentialChildNode == null || Revision.compare(childQName.getRevision(),
50                                 potentialChildNode.getQName().getRevision()) > 0)) {
51                         potentialChildNode = childNode;
52                     }
53                 }
54             }
55         }
56         if (potentialChildNode != null) {
57             result.push(potentialChildNode);
58             return result;
59         }
60
61         // try to find data schema node in choice (looking for first match)
62         for (final ChoiceSchemaNode choiceNode : childChoices) {
63             for (final CaseSchemaNode concreteCase : choiceNode.getCases().values()) {
64                 final Deque<DataSchemaNode> resultFromRecursion = findSchemaNodeByNameAndNamespace(concreteCase,
65                         childName, namespace);
66                 if (!resultFromRecursion.isEmpty()) {
67                     resultFromRecursion.push(concreteCase);
68                     resultFromRecursion.push(choiceNode);
69                     return resultFromRecursion;
70                 }
71             }
72         }
73         return result;
74     }
75 }