Added capability to resolve Enumeration type definitions;
[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.util.LinkedList;
11 import java.util.List;
12 import java.util.Queue;
13 import java.util.Set;
14
15 import org.opendaylight.controller.yang.common.QName;
16 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
17 import org.opendaylight.controller.yang.model.api.DataNodeContainer;
18 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
19 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
20 import org.opendaylight.controller.yang.model.api.Module;
21 import org.opendaylight.controller.yang.model.api.ModuleImport;
22 import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
23 import org.opendaylight.controller.yang.model.api.SchemaContext;
24 import org.opendaylight.controller.yang.model.api.SchemaNode;
25 import org.opendaylight.controller.yang.model.api.SchemaPath;
26
27 public final class SchemaContextUtil {
28
29     private final SchemaContext context;
30
31     public SchemaContextUtil(final SchemaContext context) {
32         this.context = context;
33     }
34
35     public DataSchemaNode findDataSchemaNode(final Module module,
36             final RevisionAwareXPath nonCondXPath) {
37         if (nonCondXPath != null) {
38             final String strXPath = nonCondXPath.toString();
39
40             if (strXPath != null) {
41                 if (strXPath.matches(".*//[.* | .*//].*")) {
42                     // TODO: function to escape conditions in path   
43                 }
44                 if (nonCondXPath.isAbsolute()) {
45                     final Queue<String> queuedPath = xpathToQueuedPath(strXPath);
46                     if (queuedPath != null) {
47                         final DataSchemaNode dataNode = findSchemaNodeForGivenPath(
48                                 module, queuedPath);
49                         return dataNode;
50                     }
51                 }
52             }
53         }
54         return null;
55     }
56
57     public DataSchemaNode findDataSchemaNodeForRelativeXPath(
58             final Module module, final SchemaNode actualSchemaNode,
59             final RevisionAwareXPath relativeXPath) {
60         if ((actualSchemaNode != null) && (relativeXPath != null)
61                 && !relativeXPath.isAbsolute()) {
62
63             final SchemaPath actualNodePath = actualSchemaNode.getPath();
64             if (actualNodePath != null) {
65                 final Queue<String> queuedPath = resolveRelativeXPath(
66                         relativeXPath, actualNodePath);
67
68                 if (queuedPath != null) {
69                     final DataSchemaNode dataNode = findSchemaNodeForGivenPath(
70                             module, queuedPath);
71                     return dataNode;
72                 }
73             }
74         }
75
76         return null;
77     }
78     
79     public Module resolveModuleFromSchemaPath(final SchemaPath schemaPath) {
80         if ((schemaPath != null) && (schemaPath.getPath() != null)) {
81             final QName qname = schemaPath.getPath().get(0);
82
83             if ((qname != null) && (qname.getNamespace() != null)) {
84                 return context
85                         .findModuleByNamespace(qname.getNamespace());
86             }
87         }
88         return null;
89     }
90     
91     /**
92      * Search which starts from root of Module.
93      * 
94      * @param module
95      * @param prefixedPath
96      * @return
97      */
98     private DataSchemaNode findSchemaNodeForGivenPath(final Module module,
99             final Queue<String> prefixedPath) {
100         if ((module != null) && (prefixedPath != null)) {
101             DataNodeContainer nextContainer = module;
102             final String modulePrefix = module.getPrefix();
103
104             String childNodeName = null;
105             DataSchemaNode schemaNode = null;
106             while ((nextContainer != null) && (prefixedPath.size() > 0)) {
107                 childNodeName = prefixedPath.poll();
108                 if (childNodeName.contains(":")) {
109                     final String[] prefixedChildNode = childNodeName.split(":");
110                     if ((modulePrefix != null)
111                             && modulePrefix.equals(prefixedChildNode[0])) {
112
113                         childNodeName = prefixedChildNode[1];
114                     } else {
115                         final Module nextModule = resolveModuleForPrefix(
116                                 prefixedChildNode[0], module);
117                         final Queue<String> nextModulePrefixedPath = new LinkedList<String>();
118                         nextModulePrefixedPath.add(childNodeName);
119                         nextModulePrefixedPath.addAll(prefixedPath);
120                         prefixedPath.clear();
121
122                         schemaNode = findSchemaNodeForGivenPath(nextModule,
123                                 nextModulePrefixedPath);
124
125                         return schemaNode;
126                     }
127                 }
128
129                 schemaNode = nextContainer.getDataChildByName(childNodeName);
130                 if (schemaNode instanceof ContainerSchemaNode) {
131                     nextContainer = (ContainerSchemaNode) schemaNode;
132                 } else if (schemaNode instanceof ListSchemaNode) {
133                     nextContainer = (ListSchemaNode) schemaNode;
134                 } else {
135                     return schemaNode;
136                 }
137             }
138         }
139         return null;
140     }
141
142     private Module resolveModuleForPrefix(final String prefix,
143             final Module parent) {
144         if ((prefix != null) && (parent != null)) {
145             final Set<ModuleImport> imports = parent.getImports();
146
147             if (imports != null) {
148                 for (final ModuleImport impModule : imports) {
149                     final String impModPrefix = impModule.getPrefix();
150                     if ((impModPrefix != null) && prefix.equals(impModPrefix)) {
151                         return resolveModuleFromContext(prefix,
152                                 impModule.getModuleName());
153                     }
154                 }
155             }
156         }
157         return null;
158     }
159
160     private Module resolveModuleFromContext(final String prefix,
161             final String moduleName) {
162         final Set<Module> modules = context.getModules();
163
164         if ((prefix != null) && (moduleName != null) && (modules != null)) {
165             for (Module module : modules) {
166                 if ((module != null) && prefix.equals(module.getPrefix())
167                         && moduleName.equals(module.getName())) {
168                     return module;
169                 }
170             }
171         }
172         return null;
173     }
174
175     private Queue<String> xpathToQueuedPath(final String xpath) {
176         final Queue<String> retQueue = new LinkedList<String>();
177         if ((xpath != null)) {
178             final String[] prefixedPath = xpath.split("/");
179
180             if (prefixedPath != null) {
181                 for (int i = 0; i < prefixedPath.length; ++i) {
182                     if (!prefixedPath[i].isEmpty()) {
183                         retQueue.add(prefixedPath[i]);
184                     }
185                 }
186             }
187         }
188         return retQueue;
189     }
190
191     private Queue<String> resolveRelativeXPath(
192             final RevisionAwareXPath relativeXPath,
193             final SchemaPath leafrefSchemaPath) {
194         final Queue<String> absolutePath = new LinkedList<String>();
195
196         if ((relativeXPath != null) && !relativeXPath.isAbsolute()
197                 && (leafrefSchemaPath != null)) {
198             final String strXPath = relativeXPath.toString();
199             if (strXPath != null) {
200                 final String[] xpaths = strXPath.split("/");
201
202                 if (xpaths != null) {
203                     int colCount = 0;
204                     while (xpaths[colCount].contains("..")) {
205                         ++colCount;
206                     }
207                     final List<QName> path = leafrefSchemaPath.getPath();
208                     if (path != null) {
209                         int lenght = path.size() - colCount;
210                         for (int i = 0; i < lenght; ++i) {
211                             absolutePath.add(path.get(i).getLocalName());
212                         }
213                         for (int i = colCount; i < xpaths.length; ++i) {
214                             absolutePath.add(xpaths[i]);
215                         }
216                     }
217                 }
218             }
219         }
220         return absolutePath;
221     }
222 }