Reorganize YangFunctionContext 20/71520/2
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 27 Apr 2018 16:15:00 +0000 (18:15 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 27 Apr 2018 18:31:35 +0000 (20:31 +0200)
Sonar is not very happy about large lambdas, so reorganize this
class to use static methods and method handles as an alternative
to to constants.

Change-Id: I60a31091ed623eed001042574892d55cf9238c09
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-data-jaxen/src/main/java/org/opendaylight/yangtools/yang/data/jaxen/YangFunctionContext.java

index f9757db883ad61223b89cb698f02b509fc36b54a..1dba740c600710e33e1b212b56985b53354c8bfd 100644 (file)
@@ -17,6 +17,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
+import org.jaxen.Context;
 import org.jaxen.ContextSupport;
 import org.jaxen.Function;
 import org.jaxen.FunctionCallException;
@@ -61,159 +62,120 @@ final class YangFunctionContext implements FunctionContext {
 
     // Core XPath functions, as per http://tools.ietf.org/html/rfc6020#section-6.4.1
     private static final FunctionContext XPATH_FUNCTION_CONTEXT = new XPathFunctionContext(false);
-    // current() function, as per http://tools.ietf.org/html/rfc6020#section-6.4.1
-    private static final Function CURRENT_FUNCTION = (context, args) -> {
-        if (!args.isEmpty()) {
-            throw new FunctionCallException("current() takes no arguments.");
-        }
 
-        Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
-        return (NormalizedNodeContext) context;
-    };
+    // Singleton instance of reuse
+    private static final YangFunctionContext INSTANCE = new YangFunctionContext();
 
-    // re-match(string subject, string pattern) function as per https://tools.ietf.org/html/rfc7950#section-10.2.1
-    private static final Function REMATCH_FUNCTION = (context, args) -> {
-        if (args == null || args.size() != 2) {
-            throw new FunctionCallException("re-match() takes two arguments: string subject, string pattern.");
-        }
+    private YangFunctionContext() {
+    }
 
-        if (!(args.get(0) instanceof String)) {
-            throw new FunctionCallException("First argument of re-match() should be a String.");
-        }
+    static YangFunctionContext getInstance() {
+        return INSTANCE;
+    }
 
-        if (!(args.get(1) instanceof String)) {
-            throw new FunctionCallException("Second argument of re-match() should be a String.");
+    @Override
+    public Function getFunction(final String namespaceURI, final String prefix, final String localName)
+            throws UnresolvableException {
+        if (prefix == null) {
+            switch (localName) {
+                case "bit-is-set":
+                    return YangFunctionContext::bitIsSet;
+                case "current":
+                    return YangFunctionContext::current;
+                case "deref":
+                    return YangFunctionContext::deref;
+                case "derived-from":
+                    return YangFunctionContext::derivedFrom;
+                case "derived-from-or-self":
+                    return YangFunctionContext::derivedFromOrSelf;
+                case "enum-value":
+                    return YangFunctionContext::enumValueFunction;
+                case "re-match":
+                    return YangFunctionContext::reMatch;
+                default:
+                    break;
+            }
         }
 
-        final String subject = (String) args.get(0);
-        final String rawPattern = (String) args.get(1);
-
-        final String pattern = RegexUtils.getJavaRegexFromXSD(rawPattern);
+        return XPATH_FUNCTION_CONTEXT.getFunction(namespaceURI, prefix, localName);
+    }
 
-        return (Boolean) subject.matches(pattern);
-    };
+    // bit-is-set(node-set nodes, string bit-name) function as per
+    // https://tools.ietf.org/html/rfc7950#section-10.6.1
+    private static boolean bitIsSet(final Context context, final List<?> args) throws FunctionCallException {
+        if (args == null || args.size() != 1) {
+            throw new FunctionCallException("bit-is-set() takes two arguments: node-set nodes, string bit-name");
+        }
 
-    // deref(node-set nodes) function as per https://tools.ietf.org/html/rfc7950#section-10.3.1
-    private static final Function DEREF_FUNCTION = (context, args) -> {
-        if (!args.isEmpty()) {
-            throw new FunctionCallException("deref() takes only one argument: node-set nodes.");
+        if (!(args.get(0) instanceof String)) {
+            throw new FunctionCallException("Argument bit-name of bit-is-set() function should be a String");
         }
 
+        final String bitName = (String) args.get(0);
+
         Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
 
         final NormalizedNodeContext currentNodeContext = (NormalizedNodeContext) context;
         final SchemaContext schemaContext = getSchemaContext(currentNodeContext);
         final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(schemaContext,
-                currentNodeContext);
-
-        final Object nodeValue = currentNodeContext.getNode().getValue();
-
-        if (correspondingSchemaNode.getType() instanceof InstanceIdentifierTypeDefinition
-                && nodeValue instanceof YangInstanceIdentifier) {
-            return getNodeReferencedByInstanceIdentifier((YangInstanceIdentifier) nodeValue, currentNodeContext);
-        }
-
-        if (correspondingSchemaNode.getType() instanceof LeafrefTypeDefinition) {
-            final LeafrefTypeDefinition leafrefType = (LeafrefTypeDefinition) correspondingSchemaNode.getType();
-            final RevisionAwareXPath xpath = leafrefType.getPathStatement();
-            return getNodeReferencedByLeafref(xpath, currentNodeContext, schemaContext, correspondingSchemaNode,
-                    nodeValue);
-        }
-
-        return null;
-    };
-
-    private static NormalizedNode<?, ?> getNodeReferencedByInstanceIdentifier(final YangInstanceIdentifier path,
-            final NormalizedNodeContext currentNodeContext) {
-        final NormalizedNodeNavigator navigator = (NormalizedNodeNavigator) currentNodeContext.getNavigator();
-        final NormalizedNode<?, ?> rootNode = navigator.getRootNode();
-        final List<PathArgument> pathArguments = path.getPathArguments();
-        if (pathArguments.get(0).getNodeType().equals(rootNode.getNodeType())) {
-            final List<PathArgument> relPath = pathArguments.subList(1, pathArguments.size());
-            final Optional<NormalizedNode<?, ?>> possibleNode = NormalizedNodes.findNode(rootNode, relPath);
-            if (possibleNode.isPresent()) {
-                return possibleNode.get();
-            }
-        }
-
-        return null;
-    }
-
-    private static NormalizedNode<?, ?> getNodeReferencedByLeafref(final RevisionAwareXPath xpath,
-            final NormalizedNodeContext currentNodeContext, final SchemaContext schemaContext,
-            final TypedDataSchemaNode correspondingSchemaNode, final Object nodeValue) {
-        final NormalizedNode<?, ?> referencedNode = xpath.isAbsolute() ? getNodeReferencedByAbsoluteLeafref(xpath,
-                currentNodeContext, schemaContext, correspondingSchemaNode) : getNodeReferencedByRelativeLeafref(xpath,
-                currentNodeContext, schemaContext, correspondingSchemaNode);
+            currentNodeContext);
 
-        if (referencedNode instanceof LeafSetNode) {
-            return getReferencedLeafSetEntryNode((LeafSetNode<?>) referencedNode, nodeValue);
+        final TypeDefinition<?> nodeType = correspondingSchemaNode.getType();
+        if (!(nodeType instanceof BitsTypeDefinition)) {
+            return false;
         }
 
-        if (referencedNode instanceof LeafNode && referencedNode.getValue().equals(nodeValue)) {
-            return referencedNode;
+        final Object nodeValue = currentNodeContext.getNode().getValue();
+        if (!(nodeValue instanceof Set)) {
+            return false;
         }
 
-        return null;
+        final BitsTypeDefinition bitsType = (BitsTypeDefinition) nodeType;
+        Preconditions.checkState(containsBit(bitsType, bitName), "Bit %s does not belong to bits %s.", bitName,
+            bitsType);
+        return ((Set<?>)nodeValue).contains(bitName);
     }
 
-    private static NormalizedNode<?, ?> getNodeReferencedByAbsoluteLeafref(final RevisionAwareXPath xpath,
-            final NormalizedNodeContext currentNodeContext, final SchemaContext schemaContext,
-            final TypedDataSchemaNode correspondingSchemaNode) {
-        final LeafrefXPathStringParsingPathArgumentBuilder builder = new LeafrefXPathStringParsingPathArgumentBuilder(
-                xpath.toString(), schemaContext, correspondingSchemaNode, currentNodeContext);
-        final List<PathArgument> pathArguments = builder.build();
-        final NormalizedNodeNavigator navigator = (NormalizedNodeNavigator) currentNodeContext.getNavigator();
-        final NormalizedNode<?, ?> rootNode = navigator.getRootNode();
-        if (pathArguments.get(0).getNodeType().equals(rootNode.getNodeType())) {
-            final List<PathArgument> relPath = pathArguments.subList(1, pathArguments.size());
-            final Optional<NormalizedNode<?, ?>> possibleNode = NormalizedNodes.findNode(rootNode, relPath);
-            if (possibleNode.isPresent()) {
-                return possibleNode.get();
-            }
+    // current() function, as per http://tools.ietf.org/html/rfc6020#section-6.4.1
+    private static NormalizedNodeContext current(final Context context, final List<?> args)
+            throws FunctionCallException {
+        if (!args.isEmpty()) {
+            throw new FunctionCallException("current() takes no arguments.");
         }
 
-        return null;
+        Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
+        return (NormalizedNodeContext) context;
     }
 
-    private static NormalizedNode<?, ?> getNodeReferencedByRelativeLeafref(final RevisionAwareXPath xpath,
-            final NormalizedNodeContext currentNodeContext, final SchemaContext schemaContext,
-            final TypedDataSchemaNode correspondingSchemaNode) {
-        NormalizedNodeContext relativeNodeContext = currentNodeContext;
-        final StringBuilder xPathStringBuilder = new StringBuilder(xpath.toString());
-        // strip the relative path of all ../ at the beginning
-        while (xPathStringBuilder.indexOf("../") == 0) {
-            xPathStringBuilder.delete(0, 3);
-            relativeNodeContext = relativeNodeContext.getParent();
-        }
-
-        // add / to the beginning of the path so that it can be processed the same way as an absolute path
-        xPathStringBuilder.insert(0, '/');
-        final LeafrefXPathStringParsingPathArgumentBuilder builder = new LeafrefXPathStringParsingPathArgumentBuilder(
-                xPathStringBuilder.toString(), schemaContext, correspondingSchemaNode, currentNodeContext);
-        final List<PathArgument> pathArguments = builder.build();
-        final NormalizedNode<?, ?> relativeNode = relativeNodeContext.getNode();
-        final Optional<NormalizedNode<?, ?>> possibleNode = NormalizedNodes.findNode(relativeNode, pathArguments);
-        if (possibleNode.isPresent()) {
-            return possibleNode.get();
+    // deref(node-set nodes) function as per https://tools.ietf.org/html/rfc7950#section-10.3.1
+    private static NormalizedNode<?, ?> deref(final Context context, final List<?> args) throws FunctionCallException {
+        if (!args.isEmpty()) {
+            throw new FunctionCallException("deref() takes only one argument: node-set nodes.");
         }
 
-        return null;
-    }
+        Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
+        final NormalizedNodeContext currentNodeContext = (NormalizedNodeContext) context;
+        final SchemaContext schemaContext = getSchemaContext(currentNodeContext);
+        final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(schemaContext,
+                currentNodeContext);
 
-    private static LeafSetEntryNode<?> getReferencedLeafSetEntryNode(final LeafSetNode<?> referencedNode,
-            final Object currentNodeValue) {
-        for (final LeafSetEntryNode<?> entryNode : referencedNode.getValue()) {
-            if (currentNodeValue.equals(entryNode.getValue())) {
-                return entryNode;
-            }
+        final Object nodeValue = currentNodeContext.getNode().getValue();
+        final TypeDefinition<?> type = correspondingSchemaNode.getType();
+        if (type instanceof InstanceIdentifierTypeDefinition) {
+            return nodeValue instanceof YangInstanceIdentifier
+                    ? getNodeReferencedByInstanceIdentifier((YangInstanceIdentifier) nodeValue, currentNodeContext)
+                            : null;
+        }
+        if (type instanceof LeafrefTypeDefinition) {
+            final RevisionAwareXPath xpath = ((LeafrefTypeDefinition) type).getPathStatement();
+            return getNodeReferencedByLeafref(xpath, currentNodeContext, schemaContext, correspondingSchemaNode,
+                    nodeValue);
         }
-
         return null;
     }
 
     // derived-from(node-set nodes, string identity) function as per https://tools.ietf.org/html/rfc7950#section-10.4.1
-    private static final Function DERIVED_FROM_FUNCTION = (context, args) -> {
+    private static boolean derivedFrom(final Context context, final List<?> args) throws FunctionCallException {
         if (args == null || args.size() != 1) {
             throw new FunctionCallException("derived-from() takes two arguments: node-set nodes, string identity.");
         }
@@ -232,11 +194,11 @@ final class YangFunctionContext implements FunctionContext {
             currentNodeContext);
 
         if (!(correspondingSchemaNode.getType() instanceof IdentityrefTypeDefinition)) {
-            return Boolean.FALSE;
+            return false;
         }
 
         if (!(currentNodeContext.getNode().getValue() instanceof QName)) {
-            return Boolean.FALSE;
+            return false;
         }
 
         final QName currentNodeValue = (QName) currentNodeContext.getNode().getValue();
@@ -249,12 +211,12 @@ final class YangFunctionContext implements FunctionContext {
         final Set<IdentitySchemaNode> ancestorIdentities = new HashSet<>();
         collectAncestorIdentities(currentNodeIdentitySchemaNode, ancestorIdentities);
 
-        return Boolean.valueOf(ancestorIdentities.contains(identityArgSchemaNode));
-    };
+        return ancestorIdentities.contains(identityArgSchemaNode);
+    }
 
     // derived-from-or-self(node-set nodes, string identity) function as per
     // https://tools.ietf.org/html/rfc7950#section-10.4.2
-    private static final Function DERIVED_FROM_OR_SELF_FUNCTION = (context, args) -> {
+    private static boolean derivedFromOrSelf(final Context context, final List<?> args) throws FunctionCallException {
         if (args == null || args.size() != 1) {
             throw new FunctionCallException(
                 "derived-from-or-self() takes two arguments: node-set nodes, string identity");
@@ -275,11 +237,11 @@ final class YangFunctionContext implements FunctionContext {
             currentNodeContext);
 
         if (!(correspondingSchemaNode.getType() instanceof IdentityrefTypeDefinition)) {
-            return Boolean.FALSE;
+            return false;
         }
 
         if (!(currentNodeContext.getNode().getValue() instanceof QName)) {
-            return Boolean.FALSE;
+            return false;
         }
 
         final QName currentNodeValue = (QName) currentNodeContext.getNode().getValue();
@@ -289,14 +251,60 @@ final class YangFunctionContext implements FunctionContext {
         final IdentitySchemaNode currentNodeIdentitySchemaNode = getIdentitySchemaNodeFromQName(currentNodeValue,
                 schemaContext);
         if (currentNodeIdentitySchemaNode.equals(identityArgSchemaNode)) {
-            return Boolean.TRUE;
+            return true;
         }
 
         final Set<IdentitySchemaNode> ancestorIdentities = new HashSet<>();
         collectAncestorIdentities(currentNodeIdentitySchemaNode, ancestorIdentities);
 
-        return Boolean.valueOf(ancestorIdentities.contains(identityArgSchemaNode));
-    };
+        return ancestorIdentities.contains(identityArgSchemaNode);
+    }
+
+    // enum-value(node-set nodes) function as per https://tools.ietf.org/html/rfc7950#section-10.5.1
+    private static Object enumValueFunction(final Context context, final List<?> args) throws FunctionCallException {
+        if (!args.isEmpty()) {
+            throw new FunctionCallException("enum-value() takes one argument: node-set nodes.");
+        }
+
+        Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
+
+        final NormalizedNodeContext currentNodeContext = (NormalizedNodeContext) context;
+        final SchemaContext schemaContext = getSchemaContext(currentNodeContext);
+        final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(schemaContext,
+            currentNodeContext);
+
+        final TypeDefinition<?> nodeType = correspondingSchemaNode.getType();
+        if (!(nodeType instanceof EnumTypeDefinition)) {
+            return DOUBLE_NAN;
+        }
+
+        final Object nodeValue = currentNodeContext.getNode().getValue();
+        if (!(nodeValue instanceof String)) {
+            return DOUBLE_NAN;
+        }
+
+        final EnumTypeDefinition enumerationType = (EnumTypeDefinition) nodeType;
+        final String enumName = (String) nodeValue;
+
+        return getEnumValue(enumerationType, enumName);
+    }
+
+    // re-match(string subject, string pattern) function as per https://tools.ietf.org/html/rfc7950#section-10.2.1
+    private static boolean reMatch(final Context context, final List<?> args) throws FunctionCallException {
+        if (args == null || args.size() != 2) {
+            throw new FunctionCallException("re-match() takes two arguments: string subject, string pattern.");
+        }
+        final Object subject = args.get(0);
+        if (!(subject instanceof String)) {
+            throw new FunctionCallException("First argument of re-match() should be a String.");
+        }
+        final Object pattern = args.get(1);
+        if (!(pattern instanceof String)) {
+            throw new FunctionCallException("Second argument of re-match() should be a String.");
+        }
+
+        return ((String) subject).matches(RegexUtils.getJavaRegexFromXSD((String) pattern));
+    }
 
     private static void collectAncestorIdentities(final IdentitySchemaNode identity,
             final Set<IdentitySchemaNode> ancestorIdentities) {
@@ -357,81 +365,95 @@ final class YangFunctionContext implements FunctionContext {
                     + " identity schema node in the module %s.", identityQName, module));
     }
 
-    // enum-value(node-set nodes) function as per https://tools.ietf.org/html/rfc7950#section-10.5.1
-    private static final Function ENUM_VALUE_FUNCTION = (context, args) -> {
-        if (!args.isEmpty()) {
-            throw new FunctionCallException("enum-value() takes one argument: node-set nodes.");
+    private static NormalizedNode<?, ?> getNodeReferencedByInstanceIdentifier(final YangInstanceIdentifier path,
+            final NormalizedNodeContext currentNodeContext) {
+        final NormalizedNodeNavigator navigator = (NormalizedNodeNavigator) currentNodeContext.getNavigator();
+        final NormalizedNode<?, ?> rootNode = navigator.getRootNode();
+        final List<PathArgument> pathArguments = path.getPathArguments();
+        if (pathArguments.get(0).getNodeType().equals(rootNode.getNodeType())) {
+            final List<PathArgument> relPath = pathArguments.subList(1, pathArguments.size());
+            final Optional<NormalizedNode<?, ?>> possibleNode = NormalizedNodes.findNode(rootNode, relPath);
+            if (possibleNode.isPresent()) {
+                return possibleNode.get();
+            }
         }
 
-        Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
+        return null;
+    }
 
-        final NormalizedNodeContext currentNodeContext = (NormalizedNodeContext) context;
-        final SchemaContext schemaContext = getSchemaContext(currentNodeContext);
-        final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(schemaContext,
-            currentNodeContext);
+    private static NormalizedNode<?, ?> getNodeReferencedByLeafref(final RevisionAwareXPath xpath,
+            final NormalizedNodeContext currentNodeContext, final SchemaContext schemaContext,
+            final TypedDataSchemaNode correspondingSchemaNode, final Object nodeValue) {
+        final NormalizedNode<?, ?> referencedNode = xpath.isAbsolute() ? getNodeReferencedByAbsoluteLeafref(xpath,
+                currentNodeContext, schemaContext, correspondingSchemaNode) : getNodeReferencedByRelativeLeafref(xpath,
+                currentNodeContext, schemaContext, correspondingSchemaNode);
 
-        final TypeDefinition<?> nodeType = correspondingSchemaNode.getType();
-        if (!(nodeType instanceof EnumTypeDefinition)) {
-            return DOUBLE_NAN;
+        if (referencedNode instanceof LeafSetNode) {
+            return getReferencedLeafSetEntryNode((LeafSetNode<?>) referencedNode, nodeValue);
         }
 
-        final Object nodeValue = currentNodeContext.getNode().getValue();
-        if (!(nodeValue instanceof String)) {
-            return DOUBLE_NAN;
+        if (referencedNode instanceof LeafNode && referencedNode.getValue().equals(nodeValue)) {
+            return referencedNode;
         }
 
-        final EnumTypeDefinition enumerationType = (EnumTypeDefinition) nodeType;
-        final String enumName = (String) nodeValue;
-
-        return getEnumValue(enumerationType, enumName);
-    };
+        return null;
+    }
 
-    private static int getEnumValue(final EnumTypeDefinition enumerationType, final String enumName) {
-        for (final EnumTypeDefinition.EnumPair enumPair : enumerationType.getValues()) {
-            if (enumName.equals(enumPair.getName())) {
-                return enumPair.getValue();
+    private static NormalizedNode<?, ?> getNodeReferencedByAbsoluteLeafref(final RevisionAwareXPath xpath,
+            final NormalizedNodeContext currentNodeContext, final SchemaContext schemaContext,
+            final TypedDataSchemaNode correspondingSchemaNode) {
+        final LeafrefXPathStringParsingPathArgumentBuilder builder = new LeafrefXPathStringParsingPathArgumentBuilder(
+                xpath.toString(), schemaContext, correspondingSchemaNode, currentNodeContext);
+        final List<PathArgument> pathArguments = builder.build();
+        final NormalizedNodeNavigator navigator = (NormalizedNodeNavigator) currentNodeContext.getNavigator();
+        final NormalizedNode<?, ?> rootNode = navigator.getRootNode();
+        if (pathArguments.get(0).getNodeType().equals(rootNode.getNodeType())) {
+            final List<PathArgument> relPath = pathArguments.subList(1, pathArguments.size());
+            final Optional<NormalizedNode<?, ?>> possibleNode = NormalizedNodes.findNode(rootNode, relPath);
+            if (possibleNode.isPresent()) {
+                return possibleNode.get();
             }
         }
 
-        throw new IllegalStateException(String.format("Enum %s does not belong to enumeration %s.",
-                enumName, enumerationType));
+        return null;
     }
 
-    // bit-is-set(node-set nodes, string bit-name) function as per
-    // https://tools.ietf.org/html/rfc7950#section-10.6.1
-    private static final Function BIT_IS_SET_FUNCTION = (context, args) -> {
-        if (args == null || args.size() != 1) {
-            throw new FunctionCallException("bit-is-set() takes two arguments: node-set nodes, string bit-name");
+    private static NormalizedNode<?, ?> getNodeReferencedByRelativeLeafref(final RevisionAwareXPath xpath,
+            final NormalizedNodeContext currentNodeContext, final SchemaContext schemaContext,
+            final TypedDataSchemaNode correspondingSchemaNode) {
+        NormalizedNodeContext relativeNodeContext = currentNodeContext;
+        final StringBuilder xPathStringBuilder = new StringBuilder(xpath.toString());
+        // strip the relative path of all ../ at the beginning
+        while (xPathStringBuilder.indexOf("../") == 0) {
+            xPathStringBuilder.delete(0, 3);
+            relativeNodeContext = relativeNodeContext.getParent();
         }
 
-        if (!(args.get(0) instanceof String)) {
-            throw new FunctionCallException("Argument bit-name of bit-is-set() function should be a String");
+        // add / to the beginning of the path so that it can be processed the same way as an absolute path
+        xPathStringBuilder.insert(0, '/');
+        final LeafrefXPathStringParsingPathArgumentBuilder builder = new LeafrefXPathStringParsingPathArgumentBuilder(
+                xPathStringBuilder.toString(), schemaContext, correspondingSchemaNode, currentNodeContext);
+        final List<PathArgument> pathArguments = builder.build();
+        final NormalizedNode<?, ?> relativeNode = relativeNodeContext.getNode();
+        final Optional<NormalizedNode<?, ?>> possibleNode = NormalizedNodes.findNode(relativeNode, pathArguments);
+        if (possibleNode.isPresent()) {
+            return possibleNode.get();
         }
 
-        final String bitName = (String) args.get(0);
-
-        Verify.verify(context instanceof NormalizedNodeContext, "Unhandled context %s", context.getClass());
-
-        final NormalizedNodeContext currentNodeContext = (NormalizedNodeContext) context;
-        final SchemaContext schemaContext = getSchemaContext(currentNodeContext);
-        final TypedDataSchemaNode correspondingSchemaNode = getCorrespondingTypedSchemaNode(schemaContext,
-            currentNodeContext);
+        return null;
+    }
 
-        final TypeDefinition<?> nodeType = correspondingSchemaNode.getType();
-        if (!(nodeType instanceof BitsTypeDefinition)) {
-            return Boolean.FALSE;
+    private static LeafSetEntryNode<?> getReferencedLeafSetEntryNode(final LeafSetNode<?> referencedNode,
+            final Object currentNodeValue) {
+        for (final LeafSetEntryNode<?> entryNode : referencedNode.getValue()) {
+            if (currentNodeValue.equals(entryNode.getValue())) {
+                return entryNode;
+            }
         }
 
-        final Object nodeValue = currentNodeContext.getNode().getValue();
-        if (!(nodeValue instanceof Set)) {
-            return Boolean.FALSE;
-        }
+        return null;
+    }
 
-        final BitsTypeDefinition bitsType = (BitsTypeDefinition) nodeType;
-        Preconditions.checkState(containsBit(bitsType, bitName), "Bit %s does not belong to bits %s.", bitName,
-            bitsType);
-        return Boolean.valueOf(((Set<?>)nodeValue).contains(bitName));
-    };
 
     private static boolean containsBit(final BitsTypeDefinition bitsType, final String bitName) {
         for (BitsTypeDefinition.Bit bit : bitsType.getBits()) {
@@ -443,6 +465,17 @@ final class YangFunctionContext implements FunctionContext {
         return false;
     }
 
+    private static int getEnumValue(final EnumTypeDefinition enumerationType, final String enumName) {
+        for (final EnumTypeDefinition.EnumPair enumPair : enumerationType.getValues()) {
+            if (enumName.equals(enumPair.getName())) {
+                return enumPair.getValue();
+            }
+        }
+
+        throw new IllegalStateException(String.format("Enum %s does not belong to enumeration %s.",
+                enumName, enumerationType));
+    }
+
     private static SchemaContext getSchemaContext(final NormalizedNodeContext normalizedNodeContext) {
         final ContextSupport contextSupport = normalizedNodeContext.getContextSupport();
         Verify.verify(contextSupport instanceof NormalizedNodeContextSupport, "Unhandled context support %s",
@@ -477,41 +510,4 @@ final class YangFunctionContext implements FunctionContext {
                 currentNodeContext.getNode());
         return (TypedDataSchemaNode) schemaNode;
     }
-
-    // Singleton instance of reuse
-    private static final YangFunctionContext INSTANCE = new YangFunctionContext();
-
-    private YangFunctionContext() {
-    }
-
-    static YangFunctionContext getInstance() {
-        return INSTANCE;
-    }
-
-    @Override
-    public Function getFunction(final String namespaceURI, final String prefix, final String localName)
-            throws UnresolvableException {
-        if (prefix == null) {
-            switch (localName) {
-                case "bit-is-set":
-                    return BIT_IS_SET_FUNCTION;
-                case "current":
-                    return CURRENT_FUNCTION;
-                case "deref":
-                    return DEREF_FUNCTION;
-                case "derived-from":
-                    return DERIVED_FROM_FUNCTION;
-                case "derived-from-or-self":
-                    return DERIVED_FROM_OR_SELF_FUNCTION;
-                case "enum-value":
-                    return ENUM_VALUE_FUNCTION;
-                case "re-match":
-                    return REMATCH_FUNCTION;
-                default:
-                    break;
-            }
-        }
-
-        return XPATH_FUNCTION_CONTEXT.getFunction(namespaceURI, prefix, localName);
-    }
 }