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.ContainerSchemaNode;
18 import org.opendaylight.controller.yang.model.api.DataNodeContainer;
19 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
20 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
21 import org.opendaylight.controller.yang.model.api.Module;
22 import org.opendaylight.controller.yang.model.api.ModuleImport;
23 import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
24 import org.opendaylight.controller.yang.model.api.SchemaContext;
25 import org.opendaylight.controller.yang.model.api.SchemaNode;
26 import org.opendaylight.controller.yang.model.api.SchemaPath;
28 public final class SchemaContextUtil {
30 private SchemaContextUtil() {}
32 public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final SchemaPath schemaPath) {
33 if (schemaPath != null) {
34 final Module module = resolveModuleFromSchemaPath(context, schemaPath);
35 final Queue<QName> prefixedPath = new LinkedList<QName>(schemaPath.getPath());
37 if ((module != null) && (prefixedPath != null)) {
38 return findSchemaNodeForGivenPath(context, module, prefixedPath);
44 public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final Module module,
45 final RevisionAwareXPath nonCondXPath) {
46 if (nonCondXPath != null) {
47 final String strXPath = nonCondXPath.toString();
49 if (strXPath != null) {
50 if (strXPath.matches(".*//[.* | .*//].*")) {
51 // TODO: function to escape conditions in path
53 if (nonCondXPath.isAbsolute()) {
54 final Queue<QName> qnamedPath = xpathToQNamePath(context, module,
56 if (qnamedPath != null) {
57 final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context,
67 public static DataSchemaNode findDataSchemaNodeForRelativeXPath(final SchemaContext context,
68 final Module module, final SchemaNode actualSchemaNode,
69 final RevisionAwareXPath relativeXPath) {
70 if ((actualSchemaNode != null) && (relativeXPath != null)
71 && !relativeXPath.isAbsolute()) {
73 final SchemaPath actualNodePath = actualSchemaNode.getPath();
74 if (actualNodePath != null) {
75 final Queue<QName> qnamePath = resolveRelativeXPath(context, module,
76 relativeXPath, actualNodePath);
78 if (qnamePath != null) {
79 final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context,
89 public static Module resolveModuleFromSchemaPath(final SchemaContext context, final SchemaPath schemaPath) {
90 if ((schemaPath != null) && (schemaPath.getPath() != null)) {
91 final QName qname = schemaPath.getPath().get(0);
93 if ((qname != null) && (qname.getNamespace() != null)) {
94 return context.findModuleByNamespace(qname.getNamespace());
100 public static Module findParentModule(final SchemaContext context, final SchemaNode schemaNode) {
101 if (context == null) {
102 throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
104 if (schemaNode == null) {
105 throw new IllegalArgumentException("Schema Node cannot be NULL!");
108 final SchemaPath schemaPath = schemaNode.getPath();
109 if (schemaPath == null) {
110 throw new IllegalStateException("Schema Path for Schema Node is not " +
111 "set properly (Schema Path is NULL)");
113 final List<QName> qnamedPath = schemaPath.getPath();
114 if (qnamedPath == null || qnamedPath.isEmpty()) {
115 throw new IllegalStateException("Schema Path contains invalid state of path parts." +
116 "The Schema Path MUST contain at least ONE QName which defines namespace and Local name" +
119 final QName qname = qnamedPath.get(0);
120 return context.findModuleByNamespace(qname.getNamespace());
123 private static DataSchemaNode findSchemaNodeForGivenPath(final SchemaContext context, final Module module,
124 final Queue<QName> qnamedPath) {
125 if ((module != null) && (module.getNamespace() != null)
126 && (qnamedPath != null)) {
127 DataNodeContainer nextNode = module;
128 final URI moduleNamespace = module.getNamespace();
130 QName childNodeQName = null;
131 DataSchemaNode schemaNode = null;
132 while ((nextNode != null) && !qnamedPath.isEmpty()) {
133 childNodeQName = qnamedPath.peek();
134 if (childNodeQName != null) {
135 final URI childNodeNamespace = childNodeQName.getNamespace();
137 schemaNode = nextNode.getDataChildByName(childNodeQName);
138 if (schemaNode != null) {
139 if (schemaNode instanceof ContainerSchemaNode) {
140 nextNode = (ContainerSchemaNode) schemaNode;
141 } else if (schemaNode instanceof ListSchemaNode) {
142 nextNode = (ListSchemaNode) schemaNode;
146 } else if (!childNodeNamespace.equals(moduleNamespace)) {
147 final Module nextModule = context
148 .findModuleByNamespace(childNodeNamespace);
149 schemaNode = findSchemaNodeForGivenPath(context, nextModule,
161 private static Queue<QName> xpathToQNamePath(final SchemaContext context, final Module parentModule,
162 final String xpath) {
163 final Queue<QName> path = new LinkedList<QName>();
165 final String[] prefixedPath = xpath.split("/");
167 for (int i = 0; i < prefixedPath.length; ++i) {
168 if (!prefixedPath[i].isEmpty()) {
169 path.add(stringPathPartToQName(context, parentModule, prefixedPath[i]));
176 private static QName stringPathPartToQName(final SchemaContext context, final Module parentModule,
177 final String prefixedPathPart) {
178 if (parentModule != null && prefixedPathPart != null) {
179 if (prefixedPathPart.contains(":")) {
180 final String[] prefixedName = prefixedPathPart.split(":");
181 final Module module = resolveModuleForPrefix(context, parentModule,
183 if (module != null) {
184 return new QName(module.getNamespace(), module
185 .getRevision(), prefixedName[1]);
188 return new QName(parentModule.getNamespace(),
189 parentModule.getRevision(), prefixedPathPart);
195 private static Module resolveModuleForPrefix(final SchemaContext context, final Module module,
196 final String prefix) {
197 if ((module != null) && (prefix != null)) {
198 if (prefix.equals(module.getPrefix())) {
202 final Set<ModuleImport> imports = module.getImports();
204 for (final ModuleImport mi : imports) {
205 if (prefix.equals(mi.getPrefix())) {
206 return context.findModuleByName(mi.getModuleName(),
214 private static Queue<QName> resolveRelativeXPath(final SchemaContext context, final Module module,
215 final RevisionAwareXPath relativeXPath,
216 final SchemaPath leafrefSchemaPath) {
217 final Queue<QName> absolutePath = new LinkedList<QName>();
219 if ((module != null) && (relativeXPath != null) && !relativeXPath.isAbsolute()
220 && (leafrefSchemaPath != null)) {
221 final String strXPath = relativeXPath.toString();
222 if (strXPath != null) {
223 final String[] xpaths = strXPath.split("/");
225 if (xpaths != null) {
227 while (xpaths[colCount].contains("..")) {
230 final List<QName> path = leafrefSchemaPath.getPath();
232 int lenght = path.size() - colCount;
233 for (int i = 0; i < lenght; ++i) {
234 absolutePath.add(path.get(i));
236 for (int i = colCount; i < xpaths.length; ++i) {
237 absolutePath.add(stringPathPartToQName(context, module, xpaths[i]));