Refactored SchemaPath for yang java types. Fixed SchemaPath for augmented nodes types.
[controller.git] / opendaylight / sal / yang-prototype / yang / yang-model-util / src / main / java / org / opendaylight / controller / yang / model / util / SchemaContextUtil.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.controller.yang.model.util;
9
10 import java.net.URI;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.util.Queue;
14 import java.util.Set;
15
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;
27 import org.opendaylight.controller.yang.model.api.TypeDefinition;
28
29 public final class SchemaContextUtil {
30
31     private SchemaContextUtil() {}
32
33     public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final SchemaPath schemaPath) {
34         if (schemaPath != null) {
35             final Module module = resolveModuleFromSchemaPath(context, schemaPath);
36             final Queue<QName> prefixedPath = new LinkedList<QName>(schemaPath.getPath());
37
38             if ((module != null) && (prefixedPath != null)) {
39                 return findSchemaNodeForGivenPath(context, module, prefixedPath);
40             }
41         }
42         return null;
43     }
44
45     public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final Module module,
46             final RevisionAwareXPath nonCondXPath) {
47         if (nonCondXPath != null) {
48             final String strXPath = nonCondXPath.toString();
49
50             if (strXPath != null) {
51                 if (strXPath.matches(".*//[.* | .*//].*")) {
52                     // TODO: function to escape conditions in path
53                 }
54                 if (nonCondXPath.isAbsolute()) {
55                     final Queue<QName> qnamedPath = xpathToQNamePath(context, module,
56                             strXPath);
57                     if (qnamedPath != null) {
58                         final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context,
59                                 module, qnamedPath);
60                         return dataNode;
61                     }
62                 }
63             }
64         }
65         return null;
66     }
67
68     public static DataSchemaNode findDataSchemaNodeForRelativeXPath(final SchemaContext context,
69             final Module module, final SchemaNode actualSchemaNode,
70             final RevisionAwareXPath relativeXPath) {
71         if ((actualSchemaNode != null) && (relativeXPath != null)
72                 && !relativeXPath.isAbsolute()) {
73
74             final SchemaPath actualNodePath = actualSchemaNode.getPath();
75             if (actualNodePath != null) {
76                 final Queue<QName> qnamePath = resolveRelativeXPath(context, module,
77                         relativeXPath, actualNodePath);
78
79                 if (qnamePath != null) {
80                     final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context,
81                             module, qnamePath);
82                     return dataNode;
83                 }
84             }
85         }
86
87         return null;
88     }
89
90     public static Module resolveModuleFromSchemaPath(final SchemaContext context, final SchemaPath schemaPath) {
91         if ((schemaPath != null) && (schemaPath.getPath() != null)) {
92             List<QName> path = schemaPath.getPath();
93             final QName qname = path.get(path.size()-1);
94
95             if ((qname != null) && (qname.getNamespace() != null)) {
96                 return context.findModuleByNamespace(qname.getNamespace());
97             }
98         }
99         return null;
100     }
101
102     public static Module resolveModuleFromTypePath(final SchemaContext context, final TypeDefinition<?> type) {
103         final SchemaPath schemaPath = type.getPath();
104         if ((schemaPath != null) && (schemaPath.getPath() != null)) {
105             if(type instanceof ExtendedType) {
106                 List<QName> path = schemaPath.getPath();
107                 final QName qname = path.get(path.size()-1);
108
109                 if ((qname != null) && (qname.getNamespace() != null)) {
110                     return context.findModuleByNamespace(qname.getNamespace());
111                 }
112             } else {
113                 LinkedList<QName> path = new LinkedList<QName>(schemaPath.getPath());
114                 path.removeLast();
115                 final QName qname = path.get(path.size()-1);
116
117                 if ((qname != null) && (qname.getNamespace() != null)) {
118                     return context.findModuleByNamespace(qname.getNamespace());
119                 }
120             }
121
122         }
123         return null;
124     }
125
126     public static Module findParentModule(final SchemaContext context, final SchemaNode schemaNode) {
127         if (context == null) {
128             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
129         }
130         if (schemaNode == null) {
131             throw new IllegalArgumentException("Schema Node cannot be NULL!");
132         }
133
134         final SchemaPath schemaPath = schemaNode.getPath();
135         if (schemaPath == null) {
136             throw new IllegalStateException("Schema Path for Schema Node is not " +
137                     "set properly (Schema Path is NULL)");
138         }
139         final List<QName> qnamedPath = schemaPath.getPath();
140         if (qnamedPath == null || qnamedPath.isEmpty()) {
141             throw new IllegalStateException("Schema Path contains invalid state of path parts." +
142                     "The Schema Path MUST contain at least ONE QName which defines namespace and Local name" +
143                     "of path.");
144         }
145         final QName qname = qnamedPath.get(0);
146         return context.findModuleByNamespace(qname.getNamespace());
147     }
148
149     private static DataSchemaNode findSchemaNodeForGivenPath(final SchemaContext context, final Module module,
150             final Queue<QName> qnamedPath) {
151         if ((module != null) && (module.getNamespace() != null)
152                 && (qnamedPath != null)) {
153             DataNodeContainer nextNode = module;
154             final URI moduleNamespace = module.getNamespace();
155
156             QName childNodeQName = null;
157             DataSchemaNode schemaNode = null;
158             while ((nextNode != null) && !qnamedPath.isEmpty()) {
159                 childNodeQName = qnamedPath.peek();
160                 if (childNodeQName != null) {
161                     final URI childNodeNamespace = childNodeQName.getNamespace();
162
163                     schemaNode = nextNode.getDataChildByName(childNodeQName);
164                     if (schemaNode != null) {
165                         if (schemaNode instanceof ContainerSchemaNode) {
166                             nextNode = (ContainerSchemaNode) schemaNode;
167                         } else if (schemaNode instanceof ListSchemaNode) {
168                             nextNode = (ListSchemaNode) schemaNode;
169                         } else {
170                             nextNode = null;
171                         }
172                     } else if (!childNodeNamespace.equals(moduleNamespace)) {
173                         final Module nextModule = context
174                                 .findModuleByNamespace(childNodeNamespace);
175                         schemaNode = findSchemaNodeForGivenPath(context, nextModule,
176                                 qnamedPath);
177                         return schemaNode;
178                     }
179                     qnamedPath.poll();
180                 }
181             }
182             return schemaNode;
183         }
184         return null;
185     }
186
187     private static Queue<QName> xpathToQNamePath(final SchemaContext context, final Module parentModule,
188             final String xpath) {
189         final Queue<QName> path = new LinkedList<QName>();
190         if (xpath != null) {
191             final String[] prefixedPath = xpath.split("/");
192
193             for (int i = 0; i < prefixedPath.length; ++i) {
194                 if (!prefixedPath[i].isEmpty()) {
195                     path.add(stringPathPartToQName(context, parentModule, prefixedPath[i]));
196                 }
197             }
198         }
199         return path;
200     }
201
202     private static QName stringPathPartToQName(final SchemaContext context, final Module parentModule,
203             final String prefixedPathPart) {
204         if (parentModule != null && prefixedPathPart != null) {
205             if (prefixedPathPart.contains(":")) {
206                 final String[] prefixedName = prefixedPathPart.split(":");
207                 final Module module = resolveModuleForPrefix(context, parentModule,
208                         prefixedName[0]);
209                 if (module != null) {
210                     return new QName(module.getNamespace(), module
211                             .getRevision(), prefixedName[1]);
212                 }
213             } else {
214                 return new QName(parentModule.getNamespace(),
215                         parentModule.getRevision(), prefixedPathPart);
216             }
217         }
218         return null;
219     }
220
221     private static Module resolveModuleForPrefix(final SchemaContext context, final Module module,
222             final String prefix) {
223         if ((module != null) && (prefix != null)) {
224             if (prefix.equals(module.getPrefix())) {
225                 return module;
226             }
227
228             final Set<ModuleImport> imports = module.getImports();
229
230             for (final ModuleImport mi : imports) {
231                 if (prefix.equals(mi.getPrefix())) {
232                     return context.findModuleByName(mi.getModuleName(),
233                             mi.getRevision());
234                 }
235             }
236         }
237         return null;
238     }
239
240     private static Queue<QName> resolveRelativeXPath(final SchemaContext context, final Module module,
241             final RevisionAwareXPath relativeXPath,
242             final SchemaPath leafrefSchemaPath) {
243         final Queue<QName> absolutePath = new LinkedList<QName>();
244
245         if ((module != null) && (relativeXPath != null) && !relativeXPath.isAbsolute()
246                 && (leafrefSchemaPath != null)) {
247             final String strXPath = relativeXPath.toString();
248             if (strXPath != null) {
249                 final String[] xpaths = strXPath.split("/");
250
251                 if (xpaths != null) {
252                     int colCount = 0;
253                     while (xpaths[colCount].contains("..")) {
254                         ++colCount;
255                     }
256                     final List<QName> path = leafrefSchemaPath.getPath();
257                     if (path != null) {
258                         int lenght = path.size() - colCount - 1;
259                         for (int i = 0; i < lenght; ++i) {
260                             absolutePath.add(path.get(i));
261                         }
262                         for (int i = colCount; i < xpaths.length; ++i) {
263                             absolutePath.add(stringPathPartToQName(context, module, xpaths[i]));
264                         }
265                     }
266                 }
267             }
268         }
269         return absolutePath;
270     }
271 }