2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.yang.model.util;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.util.Queue;
16 import org.opendaylight.controller.yang.common.QName;
17 import org.opendaylight.controller.yang.model.api.*;
19 public final class SchemaContextUtil {
21 private SchemaContextUtil() {
24 public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final SchemaPath schemaPath) {
25 if (schemaPath != null) {
26 final Module module = resolveModuleFromSchemaPath(context, schemaPath);
27 final Queue<QName> prefixedPath = new LinkedList<>(schemaPath.getPath());
29 if ((module != null) && (prefixedPath != null)) {
30 return findSchemaNodeForGivenPath(context, module, prefixedPath);
36 public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final Module module,
37 final RevisionAwareXPath nonCondXPath) {
38 if (nonCondXPath != null) {
39 final String strXPath = nonCondXPath.toString();
41 if (strXPath != null) {
42 if (strXPath.matches(".*//[.* | .*//].*")) {
43 // TODO: function to escape conditions in path
45 if (nonCondXPath.isAbsolute()) {
46 final Queue<QName> qnamedPath = xpathToQNamePath(context, module, strXPath);
47 if (qnamedPath != null) {
48 final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, module, qnamedPath);
57 public static DataSchemaNode findDataSchemaNodeForRelativeXPath(final SchemaContext context, final Module module,
58 final SchemaNode actualSchemaNode, final RevisionAwareXPath relativeXPath) {
59 if ((actualSchemaNode != null) && (relativeXPath != null) && !relativeXPath.isAbsolute()) {
61 final SchemaPath actualNodePath = actualSchemaNode.getPath();
62 if (actualNodePath != null) {
63 final Queue<QName> qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualNodePath);
65 if (qnamePath != null) {
66 final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, module, qnamePath);
75 private static Module resolveModuleFromSchemaPath(final SchemaContext context, final SchemaPath schemaPath) {
76 if ((schemaPath != null) && (schemaPath.getPath() != null)) {
77 final List<QName> path = schemaPath.getPath();
78 if (!path.isEmpty()) {
79 final QName qname = path.get(path.size() - 1);
81 if ((qname != null) && (qname.getNamespace() != null)) {
82 return context.findModuleByNamespace(qname.getNamespace());
89 public static Module findParentModuleForTypeDefinition(final SchemaContext context, final TypeDefinition<?> type) {
90 final SchemaPath schemaPath = type.getPath();
91 if ((schemaPath != null) && (schemaPath.getPath() != null)) {
92 if (type instanceof ExtendedType) {
93 List<QName> path = schemaPath.getPath();
94 final QName qname = path.get(path.size() - 1);
96 if ((qname != null) && (qname.getNamespace() != null)) {
97 return context.findModuleByNamespace(qname.getNamespace());
100 List<QName> path = schemaPath.getPath();
101 final QName qname = path.get(path.size() - 2);
103 if ((qname != null) && (qname.getNamespace() != null)) {
104 return context.findModuleByNamespace(qname.getNamespace());
112 public static Module findParentModule(final SchemaContext context, final SchemaNode schemaNode) {
113 if (context == null) {
114 throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
116 if (schemaNode == null) {
117 throw new IllegalArgumentException("Schema Node cannot be NULL!");
120 final SchemaPath schemaPath = schemaNode.getPath();
121 if (schemaPath == null) {
122 throw new IllegalStateException("Schema Path for Schema Node is not "
123 + "set properly (Schema Path is NULL)");
125 final List<QName> qnamedPath = schemaPath.getPath();
126 if (qnamedPath == null || qnamedPath.isEmpty()) {
127 throw new IllegalStateException("Schema Path contains invalid state of path parts."
128 + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name"
131 final QName qname = qnamedPath.get(qnamedPath.size() - 1);
132 return context.findModuleByNamespace(qname.getNamespace());
135 private static DataSchemaNode findSchemaNodeForGivenPath(final SchemaContext context, final Module module,
136 final Queue<QName> qnamedPath) {
137 if ((module != null) && (module.getNamespace() != null) && (qnamedPath != null)) {
138 DataNodeContainer nextNode = module;
139 final URI moduleNamespace = module.getNamespace();
141 QName childNodeQName;
142 DataSchemaNode schemaNode = null;
143 while ((nextNode != null) && !qnamedPath.isEmpty()) {
144 childNodeQName = qnamedPath.peek();
145 if (childNodeQName != null) {
146 final URI childNodeNamespace = childNodeQName.getNamespace();
148 schemaNode = nextNode.getDataChildByName(childNodeQName);
149 if (schemaNode != null) {
150 if (schemaNode instanceof ContainerSchemaNode) {
151 nextNode = (ContainerSchemaNode) schemaNode;
152 } else if (schemaNode instanceof ListSchemaNode) {
153 nextNode = (ListSchemaNode) schemaNode;
154 } else if (schemaNode instanceof ChoiceNode) {
155 final ChoiceNode choice = (ChoiceNode) schemaNode;
157 if (!qnamedPath.isEmpty()) {
158 childNodeQName = qnamedPath.peek();
159 nextNode = choice.getCaseNodeByName(childNodeQName);
160 schemaNode = (DataSchemaNode)nextNode;
165 } else if (!childNodeNamespace.equals(moduleNamespace)) {
166 final Module nextModule = context.findModuleByNamespace(childNodeNamespace);
167 schemaNode = findSchemaNodeForGivenPath(context, nextModule, qnamedPath);
178 private static Queue<QName> xpathToQNamePath(final SchemaContext context, final Module parentModule,
179 final String xpath) {
180 final Queue<QName> path = new LinkedList<>();
182 final String[] prefixedPath = xpath.split("/");
184 for (int i = 0; i < prefixedPath.length; ++i) {
185 if (!prefixedPath[i].isEmpty()) {
186 path.add(stringPathPartToQName(context, parentModule, prefixedPath[i]));
193 private static QName stringPathPartToQName(final SchemaContext context, final Module parentModule,
194 final String prefixedPathPart) {
195 if (parentModule != null && prefixedPathPart != null) {
196 if (prefixedPathPart.contains(":")) {
197 final String[] prefixedName = prefixedPathPart.split(":");
198 final Module module = resolveModuleForPrefix(context, parentModule, prefixedName[0]);
199 if (module != null) {
200 return new QName(module.getNamespace(), module.getRevision(), prefixedName[1]);
203 return new QName(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
209 private static Module resolveModuleForPrefix(final SchemaContext context, final Module module, final String prefix) {
210 if ((module != null) && (prefix != null)) {
211 if (prefix.equals(module.getPrefix())) {
215 final Set<ModuleImport> imports = module.getImports();
217 for (final ModuleImport mi : imports) {
218 if (prefix.equals(mi.getPrefix())) {
219 return context.findModuleByName(mi.getModuleName(), mi.getRevision());
226 private static Queue<QName> resolveRelativeXPath(final SchemaContext context, final Module module,
227 final RevisionAwareXPath relativeXPath, final SchemaPath leafrefSchemaPath) {
228 final Queue<QName> absolutePath = new LinkedList<>();
230 if ((module != null) && (relativeXPath != null) && !relativeXPath.isAbsolute() && (leafrefSchemaPath != null)) {
231 final String strXPath = relativeXPath.toString();
232 if (strXPath != null) {
233 final String[] xpaths = strXPath.split("/");
235 if (xpaths != null) {
237 while (xpaths[colCount].contains("..")) {
240 final List<QName> path = leafrefSchemaPath.getPath();
242 int lenght = path.size() - colCount - 1;
243 for (int i = 0; i < lenght; ++i) {
244 absolutePath.add(path.get(i));
246 for (int i = colCount; i < xpaths.length; ++i) {
247 absolutePath.add(stringPathPartToQName(context, module, xpaths[i]));