Bug 5059: Do not fail when 'refine' targets an extension.
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / SchemaNodeIdentifierBuildNamespace.java
1 /*
2  * Copyright (c) 2015 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.parser.stmt.rfc6020;
10
11 import java.util.Collection;
12 import java.util.Iterator;
13 import org.opendaylight.yangtools.yang.common.QName;
14 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
15 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
16 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
17 import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
18 import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedNamespaceBehaviour;
19 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
23
24 class SchemaNodeIdentifierBuildNamespace extends
25         DerivedNamespaceBehaviour<SchemaNodeIdentifier, StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>, QName, SchemaNodeIdentifierBuildNamespace, ChildSchemaNodes<?, ?>>
26         implements IdentifierNamespace<SchemaNodeIdentifier, StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>> {
27
28     @SuppressWarnings({"unchecked", "rawtypes"})
29     protected SchemaNodeIdentifierBuildNamespace() {
30         super(SchemaNodeIdentifierBuildNamespace.class, (Class) ChildSchemaNodes.class);
31     }
32
33     @Override
34     public StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> get(
35             SchemaNodeIdentifier key) {
36         throw new UnsupportedOperationException("Direct access to namespace is not supported");
37     }
38
39     @SuppressWarnings("unchecked")
40     @Override
41     public StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> getFrom(NamespaceStorageNode storage, SchemaNodeIdentifier key) {
42
43         final NamespaceStorageNode lookupStartStorage;
44         if(key.isAbsolute() || storage.getStorageNodeType() == StorageNodeType.ROOT_STATEMENT_LOCAL) {
45             lookupStartStorage = NamespaceBehaviour.findClosestTowardsRoot(storage, StorageNodeType.GLOBAL);
46         } else {
47             lookupStartStorage = storage;
48         }
49         Iterator<QName> iterator = key.getPathFromRoot().iterator();
50         if(!iterator.hasNext()) {
51             if(lookupStartStorage instanceof StmtContext<?, ?, ?>) {
52                 return (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage;
53             } else {
54                 return null;
55             }
56         }
57         QName nextPath = iterator.next();
58         StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> current = (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage
59                 .getFromLocalStorage(ChildSchemaNodes.class, nextPath);
60         if(current == null && lookupStartStorage instanceof StmtContext<?, ?, ?>) {
61             return tryToFindUnknownStatement(nextPath.getLocalName(), (Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage);
62         }
63         while (current != null && iterator.hasNext()) {
64             nextPath = iterator.next();
65             StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> nextNodeCtx = (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) current
66                     .getFromNamespace(ChildSchemaNodes.class, nextPath);
67             if (nextNodeCtx == null) {
68                 return tryToFindUnknownStatement(nextPath.getLocalName(), current);
69             } else {
70                 current = nextNodeCtx;
71             }
72         }
73         return current;
74     }
75
76     @SuppressWarnings("unchecked")
77     private Mutable<?, ?, EffectiveStatement<?, ?>> tryToFindUnknownStatement(final String localName,
78             final Mutable<?, ?, EffectiveStatement<?, ?>> current) {
79         Collection<StmtContext<?, ?, ?>> unknownSubstatements = StmtContextUtils.findAllSubstatements(current,
80                 UnknownStatement.class);
81         for (StmtContext<?, ?, ?> unknownSubstatement : unknownSubstatements) {
82             if(unknownSubstatement.rawStatementArgument().equals(localName)) {
83                 return (Mutable<?, ?, EffectiveStatement<?, ?>>) unknownSubstatement;
84             }
85         }
86         return null;
87     }
88
89     @Override
90     public QName getSignificantKey(SchemaNodeIdentifier key) {
91         return key.getLastComponent();
92     }
93
94 }