Added capability to resolve Enumeration type definitions; 51/651/1
authorlsedlak <lsedlak@cisco.com>
Tue, 23 Apr 2013 13:48:53 +0000 (15:48 +0200)
committerMartin Vitez <mvitez@cisco.com>
Wed, 24 Jul 2013 11:44:51 +0000 (13:44 +0200)
Added ReferencedTypeImpl for resolving of referenced enumeration types;
Modified GeneratedTypeBuilder for setting correct package name for
enumeration types defined as inner enums in Generated Types;
Modified EnumBuilder added extends of Type interface in
binding-model-api;
Added test case for resolving of Leaf Enumeration in GeneratedTypesTest;

Modified BindingGeneratorImpl accordingly:
Added Implementation to resolve Enumeration type,
The Schema Tree traversal methods removed - replaced by
DataNodeIterator,

Refactored TypeProviderImpl - resolving of leafrefs now through
SchemaContextUtil methods;

Chenged package name in code-generator-demo to
org.opendaylight.controller.yang;

Added DataNodeIterator and SchemaContextUtil into yang-model-util

Fixed Raw TypeDefinition in ExtendedType implementation;
Fixed SchemaPath setting in EnumerationType implementation - added two
parametric constructors that contains SchemaPath parameter;
Updated parseTypeBody method in YangModelBuilderUtil in
yang-model-parser-impl - added Enumeration constructor call with schema
path parameter;
Fixed constructor with XPath parameter visbility in Leafref
implementation;

Added extension of AugmentationTarget for ChoiceNode in yang-model-api;

Signed-off-by: Lukas Sedlak <lsedlak@cisco.com>
yang-model-api/src/main/java/org/opendaylight/controller/yang/model/api/ChoiceNode.java
yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/DataNodeIterator.java [new file with mode: 0644]
yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/EnumerationType.java
yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/ExtendedType.java
yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/Leafref.java
yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java [new file with mode: 0644]

index f289048fcb771255899fa8e6abcb64fbab400b31..fd3c640b5e33d2ae8d10e07cef46d6b5d18abb7e 100644 (file)
@@ -1,15 +1,15 @@
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.yang.model.api;\r
-\r
-import java.util.Set;\r
-\r
-public interface ChoiceNode extends DataSchemaNode {\r
-\r
-    Set<ChoiceCaseNode> getCases();\r
-}\r
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.yang.model.api;
+
+import java.util.Set;
+
+public interface ChoiceNode extends DataSchemaNode, AugmentationTarget {
+
+    Set<ChoiceCaseNode> getCases();
+}
diff --git a/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/DataNodeIterator.java b/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/DataNodeIterator.java
new file mode 100644 (file)
index 0000000..ded4a75
--- /dev/null
@@ -0,0 +1,130 @@
+package org.opendaylight.controller.yang.model.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataNodeContainer;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+
+public class DataNodeIterator implements Iterator<DataSchemaNode> {
+    
+    private final DataNodeContainer container;
+    private final List<ListSchemaNode> allLists;
+    private final List<ContainerSchemaNode> allContainers;
+    private final List<LeafSchemaNode> allLeafs;
+    private final List<LeafListSchemaNode> allLeafLists;
+    private final List<DataSchemaNode> allChilds;
+    
+    public DataNodeIterator(final DataNodeContainer container) {
+        if (container == null) {
+            throw new IllegalArgumentException("Data Node Container MUST be specified!");
+        }
+        
+        this.allContainers = new ArrayList<ContainerSchemaNode>();
+        this.allLists = new ArrayList<ListSchemaNode>();
+        this.allLeafs = new ArrayList<LeafSchemaNode>();
+        this.allLeafLists = new ArrayList<LeafListSchemaNode>();
+        this.allChilds = new ArrayList<DataSchemaNode>();
+        
+        this.container = container;
+        
+        traverse(this.container);
+    }
+    
+    public List<ContainerSchemaNode> allContainers() {
+        return allContainers;
+    }
+    
+    public List<ListSchemaNode> allLists() {
+        return allLists;
+    }
+    
+    public List<LeafSchemaNode> allLeafs() {
+        return allLeafs;
+    }
+    
+    public List<LeafListSchemaNode> allLeafLists() {
+        return allLeafLists;
+    }
+    
+    private void traverse(final DataNodeContainer dataNode) {
+        if (!containChildDataNodeContainer(dataNode)) {
+            return;
+        }
+
+        final Set<DataSchemaNode> childs = dataNode.getChildNodes();
+        if (childs != null) {
+            for (DataSchemaNode childNode : childs) {
+                allChilds.add(childNode);
+                if (childNode instanceof ContainerSchemaNode) {
+                    final ContainerSchemaNode container = (ContainerSchemaNode) childNode;
+                    allContainers.add(container);
+                    traverse(container);
+                } else if (childNode instanceof ListSchemaNode) {
+                    final ListSchemaNode list = (ListSchemaNode) childNode;
+                    allLists.add(list);
+                    traverse(list);
+                } else if (childNode instanceof LeafSchemaNode) {
+                    final LeafSchemaNode leaf = (LeafSchemaNode) childNode;
+                    allLeafs.add(leaf);
+                } else if (childNode instanceof LeafListSchemaNode) {
+                    final LeafListSchemaNode leafList = (LeafListSchemaNode) childNode;
+                    allLeafLists.add(leafList);
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns <code>true</code> if and only if the child node contain at least
+     * one child container schema node or child list schema node, otherwise will
+     * always returns <code>false</code>
+     * 
+     * @param container
+     * @return <code>true</code> if and only if the child node contain at least
+     *         one child container schema node or child list schema node,
+     *         otherwise will always returns <code>false</code>
+     */
+    private boolean containChildDataNodeContainer(
+            final DataNodeContainer container) {
+        if (container != null) {
+            final Set<DataSchemaNode> childs = container.getChildNodes();
+            if ((childs != null) && (childs.size() > 0)) {
+                for (final DataSchemaNode childNode : childs) {
+                    if (childNode instanceof DataNodeContainer) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+    
+    @Override
+    public boolean hasNext() {
+        if (container.getChildNodes() != null) {
+            Set<DataSchemaNode> childs = container.getChildNodes();
+            
+            if ((childs != null) && !childs.isEmpty()) {
+                return childs.iterator().hasNext();
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public DataSchemaNode next() {
+        return allChilds.iterator().next();
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+}
index 696ec4f39e255277bf2c1ca055b972618b640cc0..c825390f38d98415c8fab8250a27f213816edbbc 100644 (file)
@@ -7,7 +7,9 @@
   */
 package org.opendaylight.controller.yang.model.util;
 
+import java.net.URI;
 import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 
 import org.opendaylight.controller.yang.common.QName;
@@ -24,24 +26,38 @@ import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition;
 public class EnumerationType implements EnumTypeDefinition {
 
     private final QName name = BaseTypes.constructQName("enumeration");
-    private final SchemaPath path = BaseTypes.schemaPath(name);
+    private final SchemaPath path;
     private final String description = "The enumeration built-in type represents values from a set of assigned names.";
     private final String reference = "https://tools.ietf.org/html/rfc6020#section-9.6";
 
-    private final List<EnumPair> defaultEnum;
+    private final EnumPair defaultEnum;
     private final List<EnumPair> enums;
     private String units = "";
-
-    public EnumerationType(final List<EnumPair> enums) {
+    private final EnumTypeDefinition baseType;
+    
+    private EnumerationType(final List<EnumPair> enums) {
+        this.path = BaseTypes.schemaPath(name);
+        this.enums = Collections.unmodifiableList(enums);
+        this.defaultEnum = null;
+        baseType = this;
+    }
+    
+    public EnumerationType(final List<String> actualPath, final URI namespace,
+            final Date revision, final List<EnumPair> enums) {
         super();
+        this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
         this.enums = Collections.unmodifiableList(enums);
-        defaultEnum = Collections.emptyList();
+        this.defaultEnum = null;
+        baseType = new EnumerationType(enums);
     }
 
-    public EnumerationType(final List<EnumPair> defaultEnum,
+    public EnumerationType(final List<String> actualPath, final URI namespace,
+            final Date revision, final EnumTypeDefinition baseType, final EnumPair defaultEnum,
             final List<EnumPair> enums, final String units) {
         super();
-        this.defaultEnum = Collections.unmodifiableList(defaultEnum);
+        this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
+        this.baseType = baseType;
+        this.defaultEnum = defaultEnum;
         this.enums = Collections.unmodifiableList(enums);
         this.units = units;
     }
@@ -53,7 +69,7 @@ public class EnumerationType implements EnumTypeDefinition {
      */
     @Override
     public EnumTypeDefinition getBaseType() {
-        return this;
+        return baseType;
     }
 
     /*
index 03f06387f1d70a251c82510dbdc5ec61dd3d1a95..2057a42eb6490bf659d11149ff85bb138326634b 100644 (file)
@@ -19,7 +19,7 @@ import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
 import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
 import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
 
-public class ExtendedType implements TypeDefinition {
+public class ExtendedType implements TypeDefinition<TypeDefinition<?>> {
 
     private final QName typeName;
     private final TypeDefinition<?> baseType;
index 9253895e3fec79af913029a020a3bc0e3113c057..a143f5a629a90c8440b0bd850e927963bb19dbf9 100644 (file)
-/*\r
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-package org.opendaylight.controller.yang.model.util;\r
-\r
-import java.net.URI;\r
-import java.util.Collections;\r
-import java.util.Date;\r
-import java.util.List;\r
-\r
-import org.opendaylight.controller.yang.common.QName;\r
-import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;\r
-import org.opendaylight.controller.yang.model.api.SchemaPath;\r
-import org.opendaylight.controller.yang.model.api.Status;\r
-import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;\r
-import org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition;\r
-\r
-/**\r
- * The <code>default</code> implementation of Instance Leafref Type Definition\r
- * interface.\r
- *\r
- * @see LeafrefTypeDefinition\r
- */\r
-public class Leafref implements LeafrefTypeDefinition {\r
-    private static final QName name = BaseTypes.constructQName("leafref");\r
-    private static final String description = "The leafref type is used to reference a "\r
-            + "particular leaf instance in the data tree.";\r
-    private static final String reference = "https://tools.ietf.org/html/rfc6020#section-9.9";\r
-    private final SchemaPath path;\r
-    private final RevisionAwareXPath xpath;\r
-    private final String units = "";\r
-    private final LeafrefTypeDefinition baseType;\r
-\r
-    public Leafref(final RevisionAwareXPath xpath) {\r
-        this.xpath = xpath;\r
-        this.path = BaseTypes.schemaPath(name);\r
-        this.baseType = this;\r
-    }\r
-\r
-    public Leafref(final List<String> actualPath, final URI namespace,\r
-            final Date revision, final RevisionAwareXPath xpath) {\r
-        super();\r
-        this.path = BaseTypes.schemaPath(actualPath, namespace, revision);\r
-        this.xpath = xpath;\r
-        baseType = new Leafref(xpath);\r
-    }\r
-\r
-    public Leafref(final List<String> actualPath, final URI namespace,\r
-            final Date revision, final LeafrefTypeDefinition baseType,\r
-            final RevisionAwareXPath xpath) {\r
-        super();\r
-        this.path = BaseTypes.schemaPath(actualPath, namespace, revision);\r
-        this.xpath = xpath;\r
-        this.baseType = baseType;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see\r
-     * org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType()\r
-     */\r
-    @Override\r
-    public LeafrefTypeDefinition getBaseType() {\r
-        return baseType;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits()\r
-     */\r
-    @Override\r
-    public String getUnits() {\r
-        return units;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see\r
-     * org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue\r
-     * ()\r
-     */\r
-    @Override\r
-    public Object getDefaultValue() {\r
-        return this;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName()\r
-     */\r
-    @Override\r
-    public QName getQName() {\r
-        return name;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath()\r
-     */\r
-    @Override\r
-    public SchemaPath getPath() {\r
-        return path;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see\r
-     * org.opendaylight.controller.yang.model.api.SchemaNode#getDescription()\r
-     */\r
-    @Override\r
-    public String getDescription() {\r
-        return description;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference()\r
-     */\r
-    @Override\r
-    public String getReference() {\r
-        return reference;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus()\r
-     */\r
-    @Override\r
-    public Status getStatus() {\r
-        return Status.CURRENT;\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see\r
-     * org.opendaylight.controller.yang.model.api.SchemaNode#getExtensionSchemaNodes\r
-     * ()\r
-     */\r
-    @Override\r
-    public List<UnknownSchemaNode> getUnknownSchemaNodes() {\r
-        return Collections.emptyList();\r
-    }\r
-\r
-    /*\r
-     * (non-Javadoc)\r
-     *\r
-     * @see\r
-     * org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition\r
-     * #getPathStatement()\r
-     */\r
-    @Override\r
-    public RevisionAwareXPath getPathStatement() {\r
-        return xpath;\r
-    }\r
-\r
-    @Override\r
-    public int hashCode() {\r
-        final int prime = 31;\r
-        int result = 1;\r
-        result = prime * result + ((path == null) ? 0 : path.hashCode());\r
-        result = prime * result + ((units == null) ? 0 : units.hashCode());\r
-        result = prime * result + ((xpath == null) ? 0 : xpath.hashCode());\r
-        return result;\r
-    }\r
-\r
-    @Override\r
-    public boolean equals(Object obj) {\r
-        if (this == obj) {\r
-            return true;\r
-        }\r
-        if (obj == null) {\r
-            return false;\r
-        }\r
-        if (getClass() != obj.getClass()) {\r
-            return false;\r
-        }\r
-        Leafref other = (Leafref) obj;\r
-        if (path == null) {\r
-            if (other.path != null) {\r
-                return false;\r
-            }\r
-        } else if (!path.equals(other.path)) {\r
-            return false;\r
-        }\r
-        if (units == null) {\r
-            if (other.units != null) {\r
-                return false;\r
-            }\r
-        } else if (!units.equals(other.units)) {\r
-            return false;\r
-        }\r
-        if (xpath == null) {\r
-            if (other.xpath != null) {\r
-                return false;\r
-            }\r
-        } else if (!xpath.equals(other.xpath)) {\r
-            return false;\r
-        }\r
-        return true;\r
-    }\r
-\r
-    @Override\r
-    public String toString() {\r
-        StringBuilder builder = new StringBuilder();\r
-        builder.append("Leafref [path=");\r
-        builder.append(path);\r
-        builder.append(", xpath=");\r
-        builder.append(xpath);\r
-        builder.append(", units=");\r
-        builder.append(units);\r
-        builder.append("]");\r
-        return builder.toString();\r
-    }\r
-}\r
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.yang.model.util;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition;
+
+/**
+ * The <code>default</code> implementation of Instance Leafref Type Definition
+ * interface.
+ *
+ * @see LeafrefTypeDefinition
+ */
+public class Leafref implements LeafrefTypeDefinition {
+    private static final QName name = BaseTypes.constructQName("leafref");
+    private static final String description = "The leafref type is used to reference a "
+            + "particular leaf instance in the data tree.";
+    private static final String reference = "https://tools.ietf.org/html/rfc6020#section-9.9";
+    private final SchemaPath path;
+    private final RevisionAwareXPath xpath;
+    private final String units = "";
+    private final LeafrefTypeDefinition baseType;
+
+    private Leafref(final RevisionAwareXPath xpath) {
+        this.xpath = xpath;
+        this.path = BaseTypes.schemaPath(name);
+        this.baseType = this;
+    }
+
+    public Leafref(final List<String> actualPath, final URI namespace,
+            final Date revision, final RevisionAwareXPath xpath) {
+        super();
+        this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
+        this.xpath = xpath;
+        baseType = new Leafref(xpath);
+    }
+
+    public Leafref(final List<String> actualPath, final URI namespace,
+            final Date revision, final LeafrefTypeDefinition baseType,
+            final RevisionAwareXPath xpath) {
+        super();
+        this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
+        this.xpath = xpath;
+        this.baseType = baseType;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.opendaylight.controller.yang.model.api.TypeDefinition#getBaseType()
+     */
+    @Override
+    public LeafrefTypeDefinition getBaseType() {
+        return baseType;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.controller.yang.model.api.TypeDefinition#getUnits()
+     */
+    @Override
+    public String getUnits() {
+        return units;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.opendaylight.controller.yang.model.api.TypeDefinition#getDefaultValue
+     * ()
+     */
+    @Override
+    public Object getDefaultValue() {
+        return this;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.controller.yang.model.api.SchemaNode#getQName()
+     */
+    @Override
+    public QName getQName() {
+        return name;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.controller.yang.model.api.SchemaNode#getPath()
+     */
+    @Override
+    public SchemaPath getPath() {
+        return path;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.opendaylight.controller.yang.model.api.SchemaNode#getDescription()
+     */
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.controller.yang.model.api.SchemaNode#getReference()
+     */
+    @Override
+    public String getReference() {
+        return reference;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.opendaylight.controller.yang.model.api.SchemaNode#getStatus()
+     */
+    @Override
+    public Status getStatus() {
+        return Status.CURRENT;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.opendaylight.controller.yang.model.api.SchemaNode#getExtensionSchemaNodes
+     * ()
+     */
+    @Override
+    public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+        return Collections.emptyList();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition
+     * #getPathStatement()
+     */
+    @Override
+    public RevisionAwareXPath getPathStatement() {
+        return xpath;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((path == null) ? 0 : path.hashCode());
+        result = prime * result + ((units == null) ? 0 : units.hashCode());
+        result = prime * result + ((xpath == null) ? 0 : xpath.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        Leafref other = (Leafref) obj;
+        if (path == null) {
+            if (other.path != null) {
+                return false;
+            }
+        } else if (!path.equals(other.path)) {
+            return false;
+        }
+        if (units == null) {
+            if (other.units != null) {
+                return false;
+            }
+        } else if (!units.equals(other.units)) {
+            return false;
+        }
+        if (xpath == null) {
+            if (other.xpath != null) {
+                return false;
+            }
+        } else if (!xpath.equals(other.xpath)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Leafref [path=");
+        builder.append(path);
+        builder.append(", xpath=");
+        builder.append(xpath);
+        builder.append(", units=");
+        builder.append(units);
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java b/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java
new file mode 100644 (file)
index 0000000..ab50982
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.yang.model.util;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+
+import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataNodeContainer;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
+import org.opendaylight.controller.yang.model.api.ModuleImport;
+import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.model.api.SchemaNode;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+
+public final class SchemaContextUtil {
+
+    private final SchemaContext context;
+
+    public SchemaContextUtil(final SchemaContext context) {
+        this.context = context;
+    }
+
+    public DataSchemaNode findDataSchemaNode(final Module module,
+            final RevisionAwareXPath nonCondXPath) {
+        if (nonCondXPath != null) {
+            final String strXPath = nonCondXPath.toString();
+
+            if (strXPath != null) {
+                if (strXPath.matches(".*//[.* | .*//].*")) {
+                    // TODO: function to escape conditions in path   
+                }
+                if (nonCondXPath.isAbsolute()) {
+                    final Queue<String> queuedPath = xpathToQueuedPath(strXPath);
+                    if (queuedPath != null) {
+                        final DataSchemaNode dataNode = findSchemaNodeForGivenPath(
+                                module, queuedPath);
+                        return dataNode;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    public DataSchemaNode findDataSchemaNodeForRelativeXPath(
+            final Module module, final SchemaNode actualSchemaNode,
+            final RevisionAwareXPath relativeXPath) {
+        if ((actualSchemaNode != null) && (relativeXPath != null)
+                && !relativeXPath.isAbsolute()) {
+
+            final SchemaPath actualNodePath = actualSchemaNode.getPath();
+            if (actualNodePath != null) {
+                final Queue<String> queuedPath = resolveRelativeXPath(
+                        relativeXPath, actualNodePath);
+
+                if (queuedPath != null) {
+                    final DataSchemaNode dataNode = findSchemaNodeForGivenPath(
+                            module, queuedPath);
+                    return dataNode;
+                }
+            }
+        }
+
+        return null;
+    }
+    
+    public Module resolveModuleFromSchemaPath(final SchemaPath schemaPath) {
+        if ((schemaPath != null) && (schemaPath.getPath() != null)) {
+            final QName qname = schemaPath.getPath().get(0);
+
+            if ((qname != null) && (qname.getNamespace() != null)) {
+                return context
+                        .findModuleByNamespace(qname.getNamespace());
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * Search which starts from root of Module.
+     * 
+     * @param module
+     * @param prefixedPath
+     * @return
+     */
+    private DataSchemaNode findSchemaNodeForGivenPath(final Module module,
+            final Queue<String> prefixedPath) {
+        if ((module != null) && (prefixedPath != null)) {
+            DataNodeContainer nextContainer = module;
+            final String modulePrefix = module.getPrefix();
+
+            String childNodeName = null;
+            DataSchemaNode schemaNode = null;
+            while ((nextContainer != null) && (prefixedPath.size() > 0)) {
+                childNodeName = prefixedPath.poll();
+                if (childNodeName.contains(":")) {
+                    final String[] prefixedChildNode = childNodeName.split(":");
+                    if ((modulePrefix != null)
+                            && modulePrefix.equals(prefixedChildNode[0])) {
+
+                        childNodeName = prefixedChildNode[1];
+                    } else {
+                        final Module nextModule = resolveModuleForPrefix(
+                                prefixedChildNode[0], module);
+                        final Queue<String> nextModulePrefixedPath = new LinkedList<String>();
+                        nextModulePrefixedPath.add(childNodeName);
+                        nextModulePrefixedPath.addAll(prefixedPath);
+                        prefixedPath.clear();
+
+                        schemaNode = findSchemaNodeForGivenPath(nextModule,
+                                nextModulePrefixedPath);
+
+                        return schemaNode;
+                    }
+                }
+
+                schemaNode = nextContainer.getDataChildByName(childNodeName);
+                if (schemaNode instanceof ContainerSchemaNode) {
+                    nextContainer = (ContainerSchemaNode) schemaNode;
+                } else if (schemaNode instanceof ListSchemaNode) {
+                    nextContainer = (ListSchemaNode) schemaNode;
+                } else {
+                    return schemaNode;
+                }
+            }
+        }
+        return null;
+    }
+
+    private Module resolveModuleForPrefix(final String prefix,
+            final Module parent) {
+        if ((prefix != null) && (parent != null)) {
+            final Set<ModuleImport> imports = parent.getImports();
+
+            if (imports != null) {
+                for (final ModuleImport impModule : imports) {
+                    final String impModPrefix = impModule.getPrefix();
+                    if ((impModPrefix != null) && prefix.equals(impModPrefix)) {
+                        return resolveModuleFromContext(prefix,
+                                impModule.getModuleName());
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private Module resolveModuleFromContext(final String prefix,
+            final String moduleName) {
+        final Set<Module> modules = context.getModules();
+
+        if ((prefix != null) && (moduleName != null) && (modules != null)) {
+            for (Module module : modules) {
+                if ((module != null) && prefix.equals(module.getPrefix())
+                        && moduleName.equals(module.getName())) {
+                    return module;
+                }
+            }
+        }
+        return null;
+    }
+
+    private Queue<String> xpathToQueuedPath(final String xpath) {
+        final Queue<String> retQueue = new LinkedList<String>();
+        if ((xpath != null)) {
+            final String[] prefixedPath = xpath.split("/");
+
+            if (prefixedPath != null) {
+                for (int i = 0; i < prefixedPath.length; ++i) {
+                    if (!prefixedPath[i].isEmpty()) {
+                        retQueue.add(prefixedPath[i]);
+                    }
+                }
+            }
+        }
+        return retQueue;
+    }
+
+    private Queue<String> resolveRelativeXPath(
+            final RevisionAwareXPath relativeXPath,
+            final SchemaPath leafrefSchemaPath) {
+        final Queue<String> absolutePath = new LinkedList<String>();
+
+        if ((relativeXPath != null) && !relativeXPath.isAbsolute()
+                && (leafrefSchemaPath != null)) {
+            final String strXPath = relativeXPath.toString();
+            if (strXPath != null) {
+                final String[] xpaths = strXPath.split("/");
+
+                if (xpaths != null) {
+                    int colCount = 0;
+                    while (xpaths[colCount].contains("..")) {
+                        ++colCount;
+                    }
+                    final List<QName> path = leafrefSchemaPath.getPath();
+                    if (path != null) {
+                        int lenght = path.size() - colCount;
+                        for (int i = 0; i < lenght; ++i) {
+                            absolutePath.add(path.get(i).getLocalName());
+                        }
+                        for (int i = colCount; i < xpaths.length; ++i) {
+                            absolutePath.add(xpaths[i]);
+                        }
+                    }
+                }
+            }
+        }
+        return absolutePath;
+    }
+}