15734fb3d71589e01531b87ce7265421950fdb27
[yangtools.git] / yang / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / util / SchemaContextUtil.xtend
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.yangtools.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
15 import org.opendaylight.yangtools.yang.common.QName;
16 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
17 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
18 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
19 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.Module;
22 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
23 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
24 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
25 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
27 import org.opendaylight.yangtools.yang.model.api.RpcDefinition
28 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
29 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
30 import java.util.Date
31 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
32 import java.util.Set
33
34 /**
35  * The Schema Context Util contains support methods for searching through Schema Context modules for specified schema
36  * nodes via Schema Path or Revision Aware XPath. The Schema Context Util is designed as mixin,
37  * so it is not instantiable.
38  *
39  * @author Lukas Sedlak <lsedlak@cisco.com>
40  */
41 public  class SchemaContextUtil {
42
43     private new() {
44     }
45
46     /**
47      * Method attempts to find DataSchemaNode in Schema Context via specified Schema Path. The returned
48      * DataSchemaNode from method will be the node at the end of the SchemaPath. If the DataSchemaNode is not present
49      * in the Schema Context the method will return <code>null</code>.
50      * <br>
51      * In case that Schema Context or Schema Path are not specified correctly (i.e. contains <code>null</code>
52      * values) the method will return IllegalArgumentException.
53      *
54      * @throws IllegalArgumentException
55      *
56      * @param context
57      *            Schema Context
58      * @param schemaPath
59      *            Schema Path to search for
60      * @return DataSchemaNode from the end of the Schema Path or
61      *         <code>null</code> if the Node is not present.
62      */
63     public static def SchemaNode findDataSchemaNode( SchemaContext context,  SchemaPath schemaPath) {
64         if (context === null) {
65             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
66         }
67         if (schemaPath === null) {
68             throw new IllegalArgumentException("Schema Path reference cannot be NULL");
69         }
70         val prefixedPath = (schemaPath.getPath());
71         if (prefixedPath != null) {
72             return findNodeInSchemaContext(context,prefixedPath);
73         }
74         return null;
75     }
76
77     /**
78      * Method attempts to find DataSchemaNode inside of provided Schema Context and Yang Module accordingly to
79      * Non-conditional Revision Aware XPath. The specified Module MUST be present in Schema Context otherwise the
80      * operation would fail and return <code>null</code>.
81      * <br>
82      * The Revision Aware XPath MUST be specified WITHOUT the conditional statement (i.e. without [cond]) in path,
83      * because in this state the Schema Context is completely unaware of data state and will be not able to properly
84      * resolve XPath. If the XPath contains condition the method will return IllegalArgumentException.
85      * <br>
86      * In case that Schema Context or Module or Revision Aware XPath contains <code>null</code> references the method
87      * will throw IllegalArgumentException
88      * <br>
89      * If the Revision Aware XPath is correct and desired Data Schema Node is present in Yang module or in depending
90      * module in Schema Context the method will return specified Data Schema Node, otherwise the operation will fail
91      * and method will return <code>null</code>.
92      *
93      * @throws IllegalArgumentException
94      *
95      * @param context Schema Context
96      * @param module Yang Module
97      * @param nonCondXPath Non Conditional Revision Aware XPath
98      * @return Returns Data Schema Node for specified Schema Context for given Non-conditional Revision Aware XPath,
99      * or <code>null</code> if the DataSchemaNode is not present in Schema Context.
100      */
101     public static def SchemaNode findDataSchemaNode( SchemaContext context,  Module module,
102              RevisionAwareXPath nonCondXPath) {
103         if (context === null) {
104             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
105         }
106         if (module === null) {
107             throw new IllegalArgumentException("Module reference cannot be NULL!");
108         }
109         if (nonCondXPath === null) {
110             throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!");
111         }
112
113          val  strXPath = nonCondXPath.toString();
114         if (strXPath != null) {
115             if (strXPath.contains("[")) {
116                 throw new IllegalArgumentException("Revision Aware XPath cannot contains condition!");
117             }
118             if (nonCondXPath.isAbsolute()) {
119                  val qnamedPath = xpathToQNamePath(context, module, strXPath);
120                 if (qnamedPath != null) {
121                     return findNodeInSchemaContext(context,qnamedPath);
122                 }
123             }
124         }
125         return null;
126     }
127
128     /**
129      * Method attempts to find DataSchemaNode inside of provided Schema Context and Yang Module accordingly to
130      * Non-conditional relative Revision Aware XPath. The specified Module MUST be present in Schema Context otherwise
131      * the operation would fail and return <code>null</code>.
132      * <br>
133      * The relative Revision Aware XPath MUST be specified WITHOUT the conditional statement (i.e. without [cond]) in
134      * path, because in this state the Schema Context is completely unaware of data state and will be not able to
135      * properly resolve XPath. If the XPath contains condition the method will return IllegalArgumentException.
136      * <br>
137      * The Actual Schema Node MUST be specified correctly because from this Schema Node will search starts. If the
138      * Actual Schema Node is not correct the operation will simply fail, because it will be unable to find desired
139      * DataSchemaNode.
140      * <br>
141      * In case that Schema Context or Module or Actual Schema Node or relative Revision Aware XPath contains
142      * <code>null</code> references the method will throw IllegalArgumentException
143      * <br>
144      * If the Revision Aware XPath doesn't have flag <code>isAbsolute == false</code> the method will
145      * throw IllegalArgumentException.
146      * <br>
147      * If the relative Revision Aware XPath is correct and desired Data Schema Node is present in Yang module or in
148      * depending module in Schema Context the method will return specified Data Schema Node,
149      * otherwise the operation will fail
150      * and method will return <code>null</code>.
151      *
152      * @throws IllegalArgumentException
153      *
154      * @param context Schema Context
155      * @param module Yang Module
156      * @param actualSchemaNode Actual Schema Node
157      * @param relativeXPath Relative Non Conditional Revision Aware XPath
158      * @return DataSchemaNode if is present in specified Schema Context for given relative Revision Aware XPath,
159      * otherwise will return <code>null</code>.
160      */
161     public static def SchemaNode findDataSchemaNodeForRelativeXPath( SchemaContext context,  Module module,
162              SchemaNode actualSchemaNode,  RevisionAwareXPath relativeXPath) {
163         if (context === null) {
164             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
165         }
166         if (module === null) {
167             throw new IllegalArgumentException("Module reference cannot be NULL!");
168         }
169         if (actualSchemaNode === null) {
170             throw new IllegalArgumentException("Actual Schema Node reference cannot be NULL!");
171         }
172         if (relativeXPath === null) {
173             throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!");
174         }
175         if (relativeXPath.isAbsolute()) {
176             throw new IllegalArgumentException("Revision Aware XPath MUST be relative i.e. MUST contains ../, "
177                     + "for non relative Revision Aware XPath use findDataSchemaNode method!");
178         }
179
180          val actualNodePath = actualSchemaNode.getPath();
181         if (actualNodePath != null) {
182              val qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualSchemaNode);
183
184             if (qnamePath != null) {
185                 return findNodeInSchemaContext(context,qnamePath);
186             }
187         }
188         return null;
189     }
190
191     /**
192      * Returns parent Yang Module for specified Schema Context in which Schema Node is declared. If the Schema Node
193      * is not present in Schema Context the operation will return <code>null</code>.
194      * <br>
195      * If Schema Context or Schema Node contains <code>null</code> references the method will throw IllegalArgumentException
196      *
197      * @throws IllegalArgumentException
198      *
199      * @param context Schema Context
200      * @param schemaNode Schema Node
201      * @return Yang Module for specified Schema Context and Schema Node, if Schema Node is NOT present,
202      * the method will returns <code>null</code>
203      */
204     public static def Module findParentModule( SchemaContext context,  SchemaNode schemaNode) {
205         if (context === null) {
206             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
207         }
208         if (schemaNode === null) {
209             throw new IllegalArgumentException("Schema Node cannot be NULL!");
210         }
211
212         val schemaPath = schemaNode.getPath();
213         if (schemaPath === null) {
214             throw new IllegalStateException("Schema Path for Schema Node is not "
215                     + "set properly (Schema Path is NULL)");
216         }
217         val qnamedPath = schemaPath.path;
218         if (qnamedPath === null || qnamedPath.empty) {
219             throw new IllegalStateException("Schema Path contains invalid state of path parts."
220                     + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name"
221                     + "of path.");
222         }
223         val qname = qnamedPath.get(qnamedPath.size() - 1);
224         return context.findModuleByNamespaceAndRevision(qname.namespace,qname.revision);
225     }
226
227     /**
228      * Method will attempt to find DataSchemaNode from specified Module and Queue of QNames through the Schema
229      * Context. The QNamed path could be defined across multiple modules in Schema Context so the method is called
230      * recursively. If the QNamed path contains QNames that are not part of any Module or Schema Context Path the
231      * operation will fail and returns <code>null</code>
232      * <br>
233      * If Schema Context, Module or Queue of QNames refers to <code>null</code> values,
234      * the method will throws IllegalArgumentException
235      *
236      * @throws IllegalArgumentException
237      *
238      * @param context Schema Context
239      * @param module Yang Module
240      * @param qnamedPath Queue of QNames
241      * @return DataSchemaNode if is present in Module(s) for specified Schema Context and given QNamed Path,
242      * otherwise will return <code>null</code>.
243      */
244     private static def SchemaNode findSchemaNodeForGivenPath( SchemaContext context,  Module module,
245              Queue<QName> qnamedPath) {
246         if (context === null) {
247             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
248         }
249         if (module === null) {
250             throw new IllegalArgumentException("Module reference cannot be NULL!");
251         }
252         if (module.getNamespace() === null) {
253             throw new IllegalArgumentException("Namespace for Module cannot contains NULL reference!");
254         }
255         if (qnamedPath === null || qnamedPath.isEmpty()) {
256             throw new IllegalStateException("Schema Path contains invalid state of path parts."
257                     + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name"
258                     + "of path.");
259         }
260
261         var DataNodeContainer nextNode = module;
262         val moduleNamespace = module.getNamespace();
263
264         var QName childNodeQName;
265         var SchemaNode schemaNode = null;
266         while ((nextNode != null) && !qnamedPath.isEmpty()) {
267             childNodeQName = qnamedPath.peek();
268             if (childNodeQName != null) {
269                 schemaNode = nextNode.getDataChildByName(childNodeQName.getLocalName());
270                 if(schemaNode === null && nextNode instanceof Module) {
271                     schemaNode = (nextNode as Module).getNotificationByName(childNodeQName);
272                 }
273                 if(schemaNode === null && nextNode instanceof Module) {
274                     
275                 }
276                 val URI childNamespace = childNodeQName.getNamespace();
277                 val Date childRevision = childNodeQName.getRevision();
278                 
279                 if (schemaNode != null) {
280                     if (schemaNode instanceof ContainerSchemaNode) {
281                         nextNode = schemaNode as ContainerSchemaNode;
282                     } else if (schemaNode instanceof ListSchemaNode) {
283                         nextNode = schemaNode as ListSchemaNode;
284                     } else if (schemaNode instanceof ChoiceNode) {
285                         val choice =  schemaNode as ChoiceNode;
286                         qnamedPath.poll();
287                         if (!qnamedPath.isEmpty()) {
288                             childNodeQName = qnamedPath.peek();
289                             nextNode = choice.getCaseNodeByName(childNodeQName);
290                             schemaNode = nextNode as DataSchemaNode;
291                         }
292                     } else {
293                         nextNode = null;
294                     }
295                 } else if (!childNamespace.equals(moduleNamespace)) {
296                     val Module nextModule = context.findModuleByNamespaceAndRevision(childNamespace,childRevision);
297                     schemaNode = findSchemaNodeForGivenPath(context, nextModule, qnamedPath);
298                     return schemaNode;
299                 }
300                 qnamedPath.poll();
301             }
302         }
303         return schemaNode;
304     }
305     
306     
307     public static def SchemaNode findNodeInSchemaContext(SchemaContext context, List<QName> path) {
308         val current = path.get(0);
309         val module = context.findModuleByNamespaceAndRevision(current.namespace,current.revision);
310         if(module === null) return null;
311         return findNodeInModule(module,path);
312     }
313
314     public static def GroupingDefinition findGrouping(SchemaContext context, Module module, List<QName> path) {
315         var first = path.get(0);
316         var firstPrefix = first.getPrefix();
317         var Module m = context.findModuleByNamespace(first.namespace).iterator().next();
318         var DataNodeContainer currentParent = m;
319         for (qname : path) {
320             var boolean found = false;
321             var DataNodeContainer node = currentParent.getDataChildByName(qname.localName) as DataNodeContainer;
322             if (node == null) {
323                 var Set<GroupingDefinition> groupings = currentParent.getGroupings();
324                 for (gr : groupings) {
325                     if(gr.getQName().localName.equals(qname.localName)) {
326                         currentParent = gr;
327                         found = true;
328                     }
329                 }
330             } else {
331                 found = true;
332                 currentParent = node;
333             }
334             if (!found) {
335                 throw new IllegalArgumentException("Failed to find referenced grouping: " + path + "(" + qname.localName + ")");
336             }
337         }
338         
339         return currentParent as GroupingDefinition;
340     }
341
342     private static def SchemaNode findNodeInModule(Module module, List<QName> path) {
343         val current = path.get(0);
344         var SchemaNode node = module.getDataChildByName(current);
345         if (node != null) return findNode(node as DataSchemaNode,path.nextLevel);
346         node = module.getRpcByName(current);
347         if (node != null) return findNodeInRpc(node as RpcDefinition,path.nextLevel)
348         node = module.getNotificationByName(current);
349         if (node != null) return findNodeInNotification(node as NotificationDefinition,path.nextLevel)
350         return null
351     }
352      
353     private static def SchemaNode findNodeInRpc(RpcDefinition rpc,List<QName> path) {
354         if(path.empty) return rpc;
355         val current = path.get(0);
356         switch (current.localName) {
357             case "input": return findNode(rpc.input,path.nextLevel)
358             case "output": return  findNode(rpc.output,path.nextLevel)
359         }
360         return null
361     }
362     
363     private static def SchemaNode findNodeInNotification(NotificationDefinition rpc,List<QName> path) {
364         if(path.empty) return rpc;
365         val current = path.get(0);
366         val node = rpc.getDataChildByName(current)
367         if(node != null) return findNode(node,path.nextLevel)
368         return null
369     }
370     
371     private static dispatch def SchemaNode findNode(ChoiceNode parent,List<QName> path) {
372         if(path.empty) return parent;
373         val current = path.get(0);
374         val node = parent.getCaseNodeByName(current)
375         if (node != null) return findNodeInCase(node,path.nextLevel)
376         return null
377     }
378     
379     private static dispatch def SchemaNode findNode(ContainerSchemaNode parent,List<QName> path) {
380         if(path.empty) return parent;
381          val current = path.get(0);
382         val node = parent.getDataChildByName(current)
383         if (node != null) return findNode(node,path.nextLevel)
384         return null
385     }
386     
387     private static dispatch def SchemaNode findNode(ListSchemaNode parent,List<QName> path) {
388         if(path.empty) return parent;
389          val current = path.get(0);
390         val node = parent.getDataChildByName(current)
391         if (node != null) return findNode(node,path.nextLevel)
392         return null
393     }
394     
395     private static dispatch def SchemaNode findNode(DataSchemaNode parent,List<QName> path){
396         if(path.empty) {
397             return parent
398         } else {
399             throw new IllegalArgumentException("Path nesting violation");
400         }
401     }
402     
403     public static  def SchemaNode findNodeInCase(ChoiceCaseNode parent,List<QName> path) {
404         if(path.empty) return parent;
405          val current = path.get(0);
406         val node = parent.getDataChildByName(current)
407         if (node != null) return findNode(node,path.nextLevel)
408         return null
409     }
410     
411      
412     public static def RpcDefinition getRpcByName(Module module, QName name) {
413         for(notification : module.rpcs) {
414             if(notification.QName == name) {
415                 return notification;
416             }
417         }
418         return null;
419     }
420     
421     
422     private static def nextLevel(List<QName> path){
423         return path.subList(1,path.size)
424     }
425     
426     public static def NotificationDefinition getNotificationByName(Module module, QName name) {
427         for(notification : module.notifications) {
428             if(notification.QName == name) {
429                 return notification;
430             }
431         }
432         return null;
433     }
434
435     /**
436      * Transforms string representation of XPath to Queue of QNames. The XPath is split by "/" and for each part of
437      * XPath is assigned correct module in Schema Path.
438      * <br>
439      * If Schema Context, Parent Module or XPath string contains <code>null</code> values,
440      * the method will throws IllegalArgumentException
441      *
442      * @throws IllegalArgumentException
443      *
444      * @param context Schema Context
445      * @param parentModule Parent Module
446      * @param xpath XPath String
447      * @return return a list of QName
448      */
449     private static def xpathToQNamePath( SchemaContext context,  Module parentModule,
450              String xpath) {
451         if (context === null) {
452             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
453         }
454         if (parentModule === null) {
455             throw new IllegalArgumentException("Parent Module reference cannot be NULL!");
456         }
457         if (xpath === null) {
458             throw new IllegalArgumentException("XPath string reference cannot be NULL!");
459         }
460
461         val path = new LinkedList<QName>();
462         val String[] prefixedPath = xpath.split("/");
463         for (pathComponent : prefixedPath) {
464             if (!pathComponent.isEmpty()) {
465                 path.add(stringPathPartToQName(context, parentModule, pathComponent));
466             }
467         }
468         return path;
469     }
470
471     /**
472      * Transforms part of Prefixed Path as java String to QName.
473      * <br>
474      * If the string contains module prefix separated by ":" (i.e. mod:container) this module is provided from from
475      * Parent Module list of imports. If the Prefixed module is present in Schema Context the QName can be
476      * constructed.
477      * <br>
478      * If the Prefixed Path Part does not contains prefix the Parent's Module namespace is taken for construction of
479      * QName.
480      * <br>
481      * If Schema Context, Parent Module or Prefixed Path Part refers to <code>null</code> the method will throw
482      * IllegalArgumentException
483      *
484      * @throws IllegalArgumentException
485      *
486      * @param context Schema Context
487      * @param parentModule Parent Module
488      * @param prefixedPathPart Prefixed Path Part string
489      * @return QName from prefixed Path Part String.
490      */
491     private static def QName stringPathPartToQName( SchemaContext context,  Module parentModule,
492              String prefixedPathPart) {
493         if (context === null) {
494             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
495         }
496         if (parentModule === null) {
497             throw new IllegalArgumentException("Parent Module reference cannot be NULL!");
498         }
499         if (prefixedPathPart === null) {
500             throw new IllegalArgumentException("Prefixed Path Part cannot be NULL!");
501         }
502
503         if (prefixedPathPart.contains(":")) {
504              val String[] prefixedName = prefixedPathPart.split(":");
505              val module = resolveModuleForPrefix(context, parentModule, prefixedName.get(0));
506             if (module != null) {
507                 return new QName(module.getNamespace(), module.getRevision(), prefixedName.get(1));
508             }
509         } else {
510             return new QName(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
511         }
512         return null;
513     }
514
515     /**
516      * Method will attempt to resolve and provide Module reference for specified module prefix. Each Yang module
517      * could contains multiple imports which MUST be associated with corresponding module prefix. The method simply
518      * looks into module imports and returns the module that is bounded with specified prefix. If the prefix is not
519      * present in module or the prefixed module is not present in specified Schema Context,
520      * the method will return <code>null</code>.
521      * <br>
522      * If String prefix is the same as prefix of the specified Module the reference to this module is returned.
523      * <br>
524      * If Schema Context, Module or Prefix are referring to <code>null</code> the method will return
525      * IllegalArgumentException
526      *
527      * @throws IllegalArgumentException
528      *
529      * @param context Schema Context
530      * @param module Yang Module
531      * @param prefix Module Prefix
532      * @return Module for given prefix in specified Schema Context if is present, otherwise returns <code>null</code>
533      */
534     private static def Module resolveModuleForPrefix( SchemaContext context,  Module module,  String prefix) {
535         if (context === null) {
536             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
537         }
538         if (module === null) {
539             throw new IllegalArgumentException("Module reference cannot be NULL!");
540         }
541         if (prefix === null) {
542             throw new IllegalArgumentException("Prefix string cannot be NULL!");
543         }
544
545         if (prefix.equals(module.getPrefix())) {
546             return module;
547         }
548
549         val imports = module.getImports();
550         for ( ModuleImport mi : imports) {
551             if (prefix.equals(mi.getPrefix())) {
552                 return context.findModuleByName(mi.getModuleName(), mi.getRevision());
553             }
554         }
555         return null;
556     }
557
558     /**
559      * @throws IllegalArgumentException
560      *
561      * @param context Schema Context
562      * @param module Yang Module
563      * @param relativeXPath Non conditional Revision Aware Relative XPath
564      * @param leafrefSchemaPath Schema Path for Leafref
565      * @return list of QName
566      */
567     private static def resolveRelativeXPath( SchemaContext context,  Module module,
568              RevisionAwareXPath relativeXPath,  SchemaNode leafrefParentNode) {
569
570         if (context === null) {
571             throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
572         }
573         if (module === null) {
574             throw new IllegalArgumentException("Module reference cannot be NULL!");
575         }
576         if (relativeXPath === null) {
577             throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!");
578         }
579         if (relativeXPath.isAbsolute()) {
580             throw new IllegalArgumentException("Revision Aware XPath MUST be relative i.e. MUST contains ../, "
581                     + "for non relative Revision Aware XPath use findDataSchemaNode method!");
582         }
583         if (leafrefParentNode.getPath() === null) {
584             throw new IllegalArgumentException("Schema Path reference for Leafref cannot be NULL!");
585         }
586         val absolutePath = new LinkedList<QName>();
587         val String strXPath = relativeXPath.toString();
588         if (strXPath != null) {
589             val String[] xpaths = strXPath.split("/");
590             if (xpaths != null) {
591                 var int colCount = 0;
592                 while (xpaths.get(colCount).contains("..")) {
593                     colCount = colCount+ 1;
594                 }
595                 val path = leafrefParentNode.getPath().getPath();
596                 if (path != null) {
597                     val int lenght = path.size() - colCount;
598                     absolutePath.addAll(path.subList(0,lenght));
599                     absolutePath.addAll(
600                         xpaths.subList(colCount,xpaths.length).map[stringPathPartToQName(context, module,it)]
601                     )
602                 }
603             }
604         }
605         return absolutePath;
606     }
607 }