All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.onosproject.yang.runtime.impl.YobUtils Maven / Gradle / Ivy

There is a newer version: 2.6.1
Show newest version
/*
 * Copyright 2017-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.onosproject.yang.runtime.impl;

import org.onosproject.yang.compiler.datamodel.RpcNotificationContainer;
import org.onosproject.yang.compiler.datamodel.YangIdentity;
import org.onosproject.yang.compiler.datamodel.YangIdentityRef;
import org.onosproject.yang.compiler.datamodel.YangLeaf;
import org.onosproject.yang.compiler.datamodel.YangLeafList;
import org.onosproject.yang.compiler.datamodel.YangLeafRef;
import org.onosproject.yang.compiler.datamodel.YangLeavesHolder;
import org.onosproject.yang.compiler.datamodel.YangList;
import org.onosproject.yang.compiler.datamodel.YangNode;
import org.onosproject.yang.compiler.datamodel.YangSchemaNode;
import org.onosproject.yang.compiler.datamodel.YangSchemaNodeContextInfo;
import org.onosproject.yang.compiler.datamodel.YangType;
import org.onosproject.yang.compiler.datamodel.utils.builtindatatype.YangDataTypes;
import org.onosproject.yang.model.DataNode;
import org.onosproject.yang.model.InnerModelObject;
import org.onosproject.yang.model.KeyInfo;
import org.onosproject.yang.model.KeyLeaf;
import org.onosproject.yang.model.LeafIdentifier;
import org.onosproject.yang.model.LeafListKey;
import org.onosproject.yang.model.LeafModelObject;
import org.onosproject.yang.model.LeafNode;
import org.onosproject.yang.model.ListKey;
import org.onosproject.yang.model.ModelConverterException;
import org.onosproject.yang.model.ModelObject;
import org.onosproject.yang.model.ModelObjectId;
import org.onosproject.yang.model.MultiInstanceObject;
import org.onosproject.yang.model.NodeKey;
import org.onosproject.yang.model.SchemaContext;
import org.onosproject.yang.model.SchemaId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Base64;
import java.util.Iterator;
import java.util.List;

import static org.onosproject.yang.compiler.datamodel.YangSchemaNodeType.YANG_AUGMENT_NODE;
import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.nonEmpty;
import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.getCamelCase;
import static org.onosproject.yang.runtime.SerializerHelper.getChildSchemaContext;
import static org.onosproject.yang.runtime.impl.YobConstants.DEFAULT;
import static org.onosproject.yang.runtime.impl.YobConstants.E_DATA_TYPE_NOT_SUPPORT;
import static org.onosproject.yang.runtime.impl.YobConstants.E_FAIL_TO_CREATE_OBJ;
import static org.onosproject.yang.runtime.impl.YobConstants.E_FAIL_TO_LOAD_CLASS;
import static org.onosproject.yang.runtime.impl.YobConstants.E_FAIL_TO_LOAD_CONSTRUCTOR;
import static org.onosproject.yang.runtime.impl.YobConstants.E_FAIL_TO_LOAD_LEAF_IDENTIFIER_CLASS;
import static org.onosproject.yang.runtime.impl.YobConstants.E_INVALID_IDENTITY_DATA;
import static org.onosproject.yang.runtime.impl.YobConstants.E_REFLECTION_FAIL_TO_CREATE_OBJ;
import static org.onosproject.yang.runtime.impl.YobConstants.FROM_STRING;
import static org.onosproject.yang.runtime.impl.YobConstants.L_FAIL_TO_CREATE_OBJ;
import static org.onosproject.yang.runtime.impl.YobConstants.L_FAIL_TO_LOAD_CLASS;
import static org.onosproject.yang.runtime.impl.YobConstants.L_REFLECTION_FAIL_TO_CREATE_OBJ;
import static org.onosproject.yang.runtime.impl.YobConstants.OF;
import static org.onosproject.yang.runtime.impl.YobConstants.OP_PARAM;
import static org.onosproject.yang.runtime.impl.YobConstants.PERIOD;

/**
 * Utils to support object creation.
 */
final class YobUtils {

    public static final String FORWARD_SLASH = "/";
    private static final Logger log = LoggerFactory.getLogger(YobUtils.class);
    private static final String ENUM_LEAF_IDENTIFIER = "$LeafIdentifier";
    static final String ANYDATA_SETTER = "addAnydata";

    // no instantiation
    private YobUtils() {
    }

    /**
     * Sets data from string value in parent method.
     *
     * @param type         refers to YANG data type
     * @param value        value argument is used to set the value in method
     * @param parentSetter Invokes the underlying method represented
     *                     by this parentSetter
     * @param parentObj    the parentObject is to invoke the underlying method
     * @param schemaNode   schema information
     * @param parentSchema schema information of parent
     * @throws InvocationTargetException if failed to invoke method
     * @throws IllegalAccessException    if member cannot be accessed
     * @throws NoSuchMethodException     if method is not found
     */
    static void setDataFromStringValue(YangDataTypes type,
                                       Object value,
                                       Method parentSetter,
                                       Object parentObj,
                                       YangSchemaNode schemaNode,
                                       YangSchemaNode parentSchema)
            throws InvocationTargetException, IllegalAccessException,
            NoSuchMethodException {
        switch (type) {
            case INT8:
            case UINT8:
            case INT16:
            case UINT16:
            case INT32:
            case UINT32:
            case INT64:
            case UINT64:
            case BOOLEAN:
            case STRING:
            case DECIMAL64:
            case INSTANCE_IDENTIFIER:
                parentSetter.invoke(parentObj, value);
                break;

            case BINARY:
                byte[] data = Base64.getDecoder().decode((String) value);
                parentSetter.invoke(parentObj, data);
                break;

            case BITS:
                parseBitSetTypeInfo(parentSetter, parentObj, value,
                                    schemaNode, parentSchema);
                break;

            case DERIVED:
                parseDerivedTypeInfo(parentSetter, parentObj, value,
                                     false, schemaNode);
                break;

            case IDENTITYREF:
                parseIdentityRefInfo(parentSetter, parentObj, value,
                                     schemaNode);
                break;

            case UNION:
                parseDerivedTypeInfo(parentSetter, parentObj, value,
                                     false, schemaNode);
                break;

            case LEAFREF:
                parseLeafRefTypeInfo(parentSetter, parentObj, value,
                                     schemaNode);
                break;

            case ENUMERATION:
                parseDerivedTypeInfo(parentSetter, parentObj, value.toString(),
                                     true, schemaNode);
                break;

            case EMPTY:
                if (value == null) {
                    parentSetter.invoke(parentObj, true);
                }
                break;

            default:
                log.error(E_DATA_TYPE_NOT_SUPPORT);
        }
    }

    /**
     * To set data into parent setter method from string value for derived type.
     *
     * @param parentSetter the parent setter method to be invoked
     * @param parentObj    the parent build object on which to invoke the
     *                     method
     * @param value        value to be set in method
     * @param isEnum       flag to check whether type is enum or derived
     * @param leaf         schema node
     * @throws InvocationTargetException if failed to invoke method
     * @throws IllegalAccessException    if member cannot be accessed
     * @throws NoSuchMethodException     if the required method is not found
     */
    static void parseDerivedTypeInfo(Method parentSetter,
                                     Object parentObj,
                                     Object value,
                                     boolean isEnum,
                                     YangSchemaNode leaf)
            throws InvocationTargetException, IllegalAccessException,
            NoSuchMethodException {
        String val;
        if (value == null) {
            val = "true";
        } else {
            val = value.toString();
        }
        Class childSetClass = null;
        Constructor childConstructor = null;
        Object childValue = null;
        Object childObject = null;
        Method childMethod = null;
        while (leaf.getReferredSchema() != null) {
            leaf = leaf.getReferredSchema();
        }

        String qualifiedClassName = leaf.getJavaPackage() + PERIOD +
                getCapitalCase(leaf.getJavaClassNameOrBuiltInType());

        ClassLoader classLoader = parentObj.getClass().getClassLoader();
        try {
            childSetClass = classLoader.loadClass(qualifiedClassName);
        } catch (ClassNotFoundException e) {
            log.error(L_FAIL_TO_LOAD_CLASS, qualifiedClassName);
        }

        if (!isEnum) {
            if (childSetClass != null) {
                childConstructor = childSetClass.getDeclaredConstructor();
            }

            if (childConstructor != null) {
                childConstructor.setAccessible(true);
            }

            try {
                if (childConstructor != null) {
                    childObject = childConstructor.newInstance();
                }
            } catch (InstantiationException e) {
                log.error(E_FAIL_TO_LOAD_CONSTRUCTOR, qualifiedClassName);
            }
            if (childSetClass != null) {
                childMethod = childSetClass
                        .getDeclaredMethod(FROM_STRING, String.class);
            }
        } else {
            if (childSetClass != null) {
                childMethod = childSetClass.getDeclaredMethod(OF, String.class);
            }
        }
        if (childMethod != null) {
            childValue = childMethod.invoke(childObject, val);
        }
        parentSetter.invoke(parentObj, childValue);
    }

    /**
     * To set data into parent setter method from string value for bits type.
     *
     * @param parentSetterMethod the parent setter method to be invoked
     * @param parentObject       the parent build object on which to invoke the
     *                           method
     * @param leafValue          value to be set in method
     * @param leaf               schema information
     * @param parentSchema       schema information of parent
     * @throws InvocationTargetException if failed to invoke method
     * @throws IllegalAccessException    if member cannot be accessed
     * @throws NoSuchMethodException     if the required method is not found
     */
    static void parseBitSetTypeInfo(Method parentSetterMethod,
                                    Object parentObject,
                                    Object leafValue,
                                    YangSchemaNode leaf,
                                    YangSchemaNode parentSchema)
            throws InvocationTargetException, IllegalAccessException,
            NoSuchMethodException {
        Class childSetClass = null;
        Object childValue = null;
        Object childObject = null;
        Method childMethod = null;

        while (leaf.getReferredSchema() != null) {
            leaf = leaf.getReferredSchema();
        }

        String pName = parentSchema.getJavaClassNameOrBuiltInType()
                .toLowerCase() + PERIOD;

        String qualifiedClassName = parentSchema.getJavaPackage() + PERIOD +
                pName + getCapitalCase(leaf.getJavaAttributeName());

        ClassLoader classLoader = parentObject.getClass().getClassLoader();

        try {
            childSetClass = classLoader.loadClass(qualifiedClassName);
        } catch (ClassNotFoundException e) {
            log.error(L_FAIL_TO_LOAD_CLASS, qualifiedClassName);
        }

        if (childSetClass != null) {
            childMethod = childSetClass.getDeclaredMethod(FROM_STRING, String.class);
        }
        if (childMethod != null) {
            childValue = childMethod.invoke(childObject, leafValue);
        }

        parentSetterMethod.invoke(parentObject, childValue);

    }

    /**
     * To set data into parent setter method from string value for leafref type.
     *
     * @param parentSetter the parent setter method to be invoked
     * @param parentObject the parent build object on which to invoke
     *                     the method
     * @param leafValue    leaf value to be set
     * @param schemaNode   schema information
     * @throws InvocationTargetException if method could not be invoked
     * @throws IllegalAccessException    if method could not be accessed
     * @throws NoSuchMethodException     if method does not exist
     */
    static void parseLeafRefTypeInfo(Method parentSetter, Object parentObject,
                                     Object leafValue,
                                     YangSchemaNode schemaNode)
            throws InvocationTargetException, IllegalAccessException,
            NoSuchMethodException {
        while (schemaNode.getReferredSchema() != null) {
            schemaNode = schemaNode.getReferredSchema();
        }

        YangLeafRef leafRef;
        if (schemaNode instanceof YangLeaf) {
            leafRef = (YangLeafRef) ((YangLeaf) schemaNode)
                    .getDataType().getDataTypeExtendedInfo();
        } else {
            leafRef = (YangLeafRef) ((YangLeafList) schemaNode)
                    .getDataType().getDataTypeExtendedInfo();
        }

        YangType type = leafRef.getEffectiveDataType();
        Object refLeaf = leafRef.getReferredLeafOrLeafList();
        YangLeavesHolder parent;
        if (refLeaf instanceof YangLeaf) {
            parent = ((YangLeaf) refLeaf).getContainedIn();
        } else {
            parent = ((YangLeafList) refLeaf).getContainedIn();
        }
        setDataFromStringValue(type.getDataType(), leafValue, parentSetter,
                               parentObject, (YangSchemaNode) refLeaf,
                               (YangSchemaNode) parent);

    }

    /**
     * Returns class loader.
     *
     * @param schemaNode schema information
     * @param reg        YANG model registry
     * @return class loader
     */
    static ClassLoader getClassLoader(YangSchemaNode schemaNode,
                                      DefaultYangModelRegistry reg) {

        YangSchemaNode curNode = schemaNode;
        while (!(curNode instanceof RpcNotificationContainer)) {
            curNode = ((YangNode) curNode).getParent();
        }

        Class regClass = reg.getRegisteredClass(curNode);
        return regClass.getClassLoader();
    }

    /**
     * Returns the class loader to be used for the switched context schema node.
     *
     * @param curLoader current context class loader
     * @param context   switched context
     * @param reg       schema registry
     * @return class loader to be used for the switched context schema node
     */
    static ClassLoader getTargetClassLoader(ClassLoader curLoader,
                                            YangSchemaNodeContextInfo context,
                                            DefaultYangModelRegistry
                                                    reg) {
        YangSchemaNode augment = context.getContextSwitchedNode();
        if (augment.getYangSchemaNodeType() == YANG_AUGMENT_NODE) {
            YangSchemaNode parent = ((YangNode) augment).getParent();
            while (((YangNode) parent).getParent() != null) {
                parent = ((YangNode) parent).getParent();
            }
            Class moduleClass = reg.getRegisteredClass(parent);
            if (moduleClass == null) {
                throw new ModelConverterException(E_FAIL_TO_LOAD_CLASS + parent
                        .getJavaClassNameOrBuiltInType());
            }
            return moduleClass.getClassLoader();
        }
        return curLoader;
    }

    /**
     * Returns the qualified default / op param class.
     *
     * @param schemaNode schema node of the required class
     * @return qualified default / op param class name
     */
    static String getQualifiedDefaultClass(YangSchemaNode schemaNode) {
        String packageName = schemaNode.getJavaPackage();
        String className = getCapitalCase(
                schemaNode.getJavaClassNameOrBuiltInType());

        if (schemaNode instanceof RpcNotificationContainer) {
            return packageName + PERIOD + className + OP_PARAM;
        }

        return packageName + PERIOD + DEFAULT + className;
    }

    /**
     * Returns the qualified interface name.
     *
     * @param schemaNode schema node of the required class
     * @return qualified interface name
     */
    static String getQualifiedinterface(YangSchemaNode schemaNode) {
        String packageName = schemaNode.getJavaPackage();
        String className = getCapitalCase(
                schemaNode.getJavaClassNameOrBuiltInType());

        return packageName + PERIOD + className;
    }

    /**
     * Returns the capital cased first letter of the given string.
     *
     * @param name string to be capital cased
     * @return capital cased string
     */
    static String getCapitalCase(String name) {
        return name.substring(0, 1).toUpperCase() +
                name.substring(1);
    }

    /**
     * To set data into parent setter method from string value for identity ref.
     *
     * @param parentSetterMethod the parent setter method to be invoked
     * @param parentObject       the parent build object on which to invoke
     *                           the method
     * @param leafValue          leaf value to be set
     * @param schemaNode         schema information
     * @throws InvocationTargetException if method could not be invoked
     * @throws IllegalAccessException    if method could not be accessed
     * @throws NoSuchMethodException     if method does not exist
     */
    static void parseIdentityRefInfo(Method parentSetterMethod,
                                     Object parentObject,
                                     Object leafValue,
                                     YangSchemaNode schemaNode)
            throws InvocationTargetException, IllegalAccessException,
            NoSuchMethodException {
        Class childSetClass = null;
        Object childValue = null;
        Method childMethod = null;

        while (schemaNode.getReferredSchema() != null) {
            schemaNode = schemaNode.getReferredSchema();
        }

        String qualifiedClassName;
        YangType type;
        if (schemaNode instanceof YangLeaf) {
            type = ((YangLeaf) schemaNode).getDataType();
        } else {
            type = ((YangLeafList) schemaNode).getDataType();
        }

        YangIdentityRef identityRef = null;
        YangIdentity derivedId;
        if (type.getDataType() == YangDataTypes.LEAFREF && schemaNode
                .getJavaPackage().equals(YobConstants.JAVA_LANG)) {
            YangLeafRef leafref = ((YangLeafRef) type.getDataTypeExtendedInfo());
            YangType effectiveType = leafref.getEffectiveDataType();
            if (effectiveType.getDataType() == YangDataTypes.IDENTITYREF) {
                identityRef = ((YangIdentityRef) effectiveType
                        .getDataTypeExtendedInfo());
            }
        } else {
            identityRef = ((YangIdentityRef) type.getDataTypeExtendedInfo());
        }

        derivedId = getDerivedIdentity(leafValue.toString(), identityRef
                .getReferredIdentity());
        if (derivedId == null) {
            throw new ModelConverterException(E_INVALID_IDENTITY_DATA +
                                                      leafValue.toString());
        }
        qualifiedClassName = derivedId.getJavaPackage() + PERIOD +
                getCapitalCase(derivedId.getJavaClassNameOrBuiltInType());
        ClassLoader classLoader = parentObject.getClass().getClassLoader();
        try {
            childSetClass = classLoader.loadClass(qualifiedClassName);
        } catch (ClassNotFoundException e) {
            log.error(L_FAIL_TO_LOAD_CLASS, qualifiedClassName);
        }

        if (childSetClass != null) {
            childMethod = childSetClass
                    .getDeclaredMethod(FROM_STRING, String.class);
        }

        if (childMethod != null) {
            childValue = childMethod.invoke(null, leafValue);
        }

        parentSetterMethod.invoke(parentObject, childValue);
    }

    /**
     * Returns schema node for given data node.
     *
     * @param dataNode data node
     * @param context  schema context
     * @return child schema node
     */
    static YangSchemaNode getChildSchemaNode(DataNode dataNode,
                                             SchemaContext context) {
        SchemaId schemaId = dataNode.key().schemaId();
        SchemaContext schemaContext = getChildSchemaContext(context,
                                                            schemaId.name(),
                                                            schemaId.namespace());
        return ((YangSchemaNode) schemaContext);
    }

    /**
     * Builds leaf model object.
     *
     * @param dataNode   data node
     * @param leafHolder schema context
     * @param reg        YANG model registry
     * @return leaf model object
     */
    static ModelObject buildLeafModelObject(DataNode dataNode,
                                            YangSchemaNode leafHolder,
                                            DefaultYangModelRegistry reg) {
        if (leafHolder == null) {
            YangSchemaNode schemaNode = ((YangSchemaNode) reg
                    .getChildContext(dataNode.key().schemaId()));
            if (schemaNode instanceof YangLeaf) {
                leafHolder = ((YangSchemaNode) ((YangLeaf) schemaNode)
                        .getContainedIn());
            } else {
                leafHolder = ((YangSchemaNode) ((YangLeafList) schemaNode)
                        .getContainedIn());
            }
        }
        LeafModelObject leafObj = new LeafModelObject();
        leafObj.addValue(((LeafNode) dataNode).value());
        LeafIdentifier leafId = getLeafIdentifier(dataNode.key().schemaId(),
                                                  leafHolder, reg);
        leafObj.leafIdentifier(leafId);
        return leafObj;
    }

    /**
     * Returns leaf identifier of the leaf.
     *
     * @param id         schema id class loader
     * @param leafHolder parent of leaf
     * @param reg        YANG model registry
     * @return leaf identifier of the leaf
     */
    static LeafIdentifier getLeafIdentifier(SchemaId id,
                                            YangSchemaNode leafHolder,
                                            DefaultYangModelRegistry reg) {
        String qualName = getQualifiedDefaultClass(leafHolder);
        ClassLoader classLoader = getClassLoader(leafHolder, reg);
        try {
            Class cls = (Class) classLoader
                    .loadClass(qualName);
            Class[] intfs = cls.getInterfaces();
            Class intf = null;
            for (Class in : intfs) {
                if (in.getName()
                        .equals(getJavaQualifiedInterFaceName(leafHolder))) {
                    intf = in;
                    break;
                }
            }
            String leafId;
            if (intf != null) {
                leafId = intf.getName() + ENUM_LEAF_IDENTIFIER;
            } else {
                throw new ModelConverterException(E_FAIL_TO_LOAD_LEAF_IDENTIFIER_CLASS);
            }

            Class leafIdentifier =
                    (Class) cls.getClassLoader().loadClass(leafId);
            Enum[] enumConst = leafIdentifier.getEnumConstants();
            for (Enum e : enumConst) {
                if (e.name().equalsIgnoreCase(id.name())) {
                    return ((LeafIdentifier) e);
                }
            }
        } catch (ClassNotFoundException e) {
            throw new ModelConverterException(E_FAIL_TO_LOAD_CLASS, e);
        }
        return null;
    }

    /**
     * Returns class.
     *
     * @param loader class loader
     * @param name   class name
     * @return java class
     */
    static Class fetchClassForNode(ClassLoader loader, String name) {
        try {
            return loader.loadClass(name);
        } catch (ClassNotFoundException e) {
            throw new ModelConverterException(E_FAIL_TO_LOAD_CLASS + name, e);
        }
    }

    /**
     * Returns instance of class.
     *
     * @param loader class loader
     * @param name   class name
     * @return instance of class
     */
    static Object getInstanceOfClass(ClassLoader loader, String name) {
        try {
            Class defaultClass = loader.loadClass(name);
            return defaultClass.newInstance();
        } catch (ClassNotFoundException e) {
            log.error(L_FAIL_TO_LOAD_CLASS, name);
            throw new ModelConverterException(E_FAIL_TO_LOAD_CLASS + name, e);
        } catch (NullPointerException e) {
            log.error(L_REFLECTION_FAIL_TO_CREATE_OBJ, name);
            throw new ModelConverterException(E_REFLECTION_FAIL_TO_CREATE_OBJ +
                                                      name, e);
        } catch (InstantiationException | IllegalAccessException e) {
            log.error(L_FAIL_TO_CREATE_OBJ, name);
            throw new ModelConverterException(E_FAIL_TO_CREATE_OBJ + name, e);
        }
    }

    /**
     * Returns java class name.
     *
     * @param node YANG node
     * @return java class name
     */
    static String getJavaQualifiedInterFaceName(YangSchemaNode node) {
        if (node != null) {
            return node.getJavaPackage() + PERIOD
                    + getCapitalCase(node.getJavaClassNameOrBuiltInType());
        }
        return null;
    }

    /**
     * Returns key class name.
     *
     * @param node schema node
     * @return key class name
     */
    static String getKeyClassName(YangSchemaNode node) {
        if (node != null) {
            return getJavaQualifiedInterFaceName(node) + "Keys";
        }
        return null;
    }

    /**
     * Returns key leaf schema.
     *
     * @param keyleaf key leaf
     * @param node to look in
     * @return node YANG schema node
     */
    static YangLeaf getKeyLeafSchema(KeyLeaf keyleaf, YangSchemaNode
            node) {
        YangList list = ((YangList) node);
        List keyLeaves = list.getListOfLeaf();
        Iterator it = keyLeaves.iterator();
        while (it.hasNext()) {
            YangLeaf leaf = it.next();
            if (leaf.getName().equals(keyleaf.leafSchema().name())) {
                return leaf;
            }
        }
        return null;
    }


    /**
     * Adds list node key to model object id builder.
     *
     * @param midb model object identifier
     * @param reg  model registry
     * @param node YANG node
     * @param key  node key
     * @return model object id builder
     * @param  list class type
     * @param  key type
     */
    static ,
            K extends KeyInfo> ModelObjectId.Builder handleListKey(
            ModelObjectId.Builder midb, DefaultYangModelRegistry reg,
            YangSchemaNode node, NodeKey key) {
        ListKey listKey = (ListKey) key;
        List keyLeaves = listKey.keyLeafs();
        String keyClassName;
        Class keyClass;
        Object value;
        String javaName = null;
        Method setter;
        if (nonEmpty(keyLeaves)) {
            String qualName = getQualifiedDefaultClass(node);
            ClassLoader classLoader = getClassLoader(node, reg);
            Class listClass = ((Class) fetchClassForNode(classLoader,
                                                               qualName));
            K keyObj;
            if (listClass != null) {
                keyClassName = getKeyClassName(node);
                try {
                    keyClass = (Class) listClass.getClassLoader()
                            .loadClass(keyClassName);
                    keyObj = (K) keyClass.newInstance();
                    for (KeyLeaf leaf : keyLeaves) {
                        YangLeaf leafSchema = getKeyLeafSchema(leaf, node);
                        YangDataTypes datatype = leafSchema.getDataType()
                                .getDataType();
                        javaName = getCamelCase(leaf.leafSchema().name(), null);
                        Field leafName = keyClass.getDeclaredField(javaName);
                        setter = keyClass.getDeclaredMethod(javaName,
                                                            leafName.getType());
                        value = leaf.leafValue();
                        setDataFromStringValue(datatype,
                                               value, setter, keyObj,
                                               leafSchema, node);
                        midb = midb.addChild(listClass, keyObj);
                    }
                } catch (NoSuchMethodException e) {
                    throw new ModelConverterException(
                            "Failed to load setter method for " +
                                    javaName + " in key class"
                                    + keyClassName, e);
                } catch (InvocationTargetException e) {
                    throw new ModelConverterException(
                            "Failed to invoke setter method for " +
                                    javaName + " in key class"
                                    + keyClassName, e);
                } catch (ClassNotFoundException e) {
                    throw new ModelConverterException("Failed to load key class"
                                                              + keyClassName, e);
                } catch (IllegalAccessException | InstantiationException e) {
                    throw new ModelConverterException("Failed Instantiation of key class"
                                                              + keyClassName, e);
                } catch (NoSuchFieldException e) {
                    throw new ModelConverterException("Field " + javaName + " not found", e);
                }
            }
        }
        return midb;
    }

    /**
     * Adds leaf list node key to model object id builder.
     *
     * @param midb       model object identifier
     * @param reg        model registry
     * @param schemaNode leaf schema node
     * @param key        leaf list node key
     * @return model object id builder
     */
    static ModelObjectId.Builder handleLeafListKey(
            ModelObjectId.Builder midb, DefaultYangModelRegistry reg,
            YangSchemaNode schemaNode, LeafListKey key) {
        Class intf = null;
        YangSchemaNode parentSchema = ((YangSchemaNode) ((YangLeafList)
                schemaNode).getContainedIn());
        String qualName = getQualifiedDefaultClass(parentSchema);
        ClassLoader classLoader = getClassLoader(parentSchema, reg);
        Class parentClass = fetchClassForNode(classLoader, qualName);
        Class[] interfaces = parentClass.getInterfaces();
        for (Class in : interfaces) {
            if (in.getName().equals(getJavaQualifiedInterFaceName(parentSchema))) {
                intf = in;
                break;
            }
        }
        String leafName;
        if (intf != null) {
            leafName = intf.getName() + ENUM_LEAF_IDENTIFIER;
            try {
                Class leafId =
                        (Class) parentClass.getClassLoader()
                                .loadClass(leafName);
                Enum[] enumConst = leafId.getEnumConstants();
                for (Enum e : enumConst) {
                    if (e.name().equalsIgnoreCase(key.schemaId().name())) {
                        midb = midb.addChild(((LeafIdentifier) e), key.value());
                        return midb;
                    }
                }
            } catch (ClassNotFoundException e) {
                throw new ModelConverterException("Failed to load leaf identifier class." +
                                                          leafName, e);
            }
        }
        return midb;
    }


    /**
     * Adds node key for container node or single instance nodes to model
     * object id builder.
     *
     * @param midb model object identifier builder
     * @param reg  model registry
     * @param node YANG node
     * @param key  node key
     * @return model object builder with single instance node
     */
    static ModelObjectId.Builder handleNodeKey(
            ModelObjectId.Builder midb, DefaultYangModelRegistry reg,
            YangSchemaNode node, NodeKey key) {
        if (node != null) {
            if (!(node instanceof YangLeaf)) {
                String qualName = getQualifiedDefaultClass(node);
                ClassLoader classLoader = getClassLoader(node, reg);
                Class nodeClass = (Class)
                        fetchClassForNode(classLoader, qualName);
                if (nodeClass != null) {
                    midb = midb.addChild(nodeClass);
                }
            } else {
                midb = handleLeafInfo(midb, reg, key, node);
            }
        }
        return midb;
    }

    /**
     * Adds node key for leaf node to model object id builder.
     *
     * @param midb       model object identifier builder
     * @param reg        model registry
     * @param key        leaf node key
     * @param schemaNode YANG schema node
     * @return model object builder with single instance node
     */
    static ModelObjectId.Builder handleLeafInfo(
            ModelObjectId.Builder midb, DefaultYangModelRegistry reg,
            NodeKey key, YangSchemaNode schemaNode) {
        YangSchemaNode parentSchema = ((YangSchemaNode) ((YangLeaf) schemaNode)
                .getContainedIn());
        String qualName = getQualifiedDefaultClass(parentSchema);
        ClassLoader classLoader = getClassLoader(parentSchema, reg);
        Class nodeClass = (Class)
                fetchClassForNode(classLoader, qualName);
        Class[] interfaces = nodeClass.getInterfaces();
        for (Class intf : interfaces) {
            String leafId = intf.getName() + ENUM_LEAF_IDENTIFIER;
            try {
                Class leafIdentifier =
                        (Class) nodeClass.getClassLoader()
                                .loadClass(leafId);
                Enum[] enumConst = leafIdentifier.getEnumConstants();
                for (Enum e : enumConst) {
                    if (e.name().equalsIgnoreCase(key.schemaId().name())) {
                        midb = midb.addChild(((LeafIdentifier) e));
                        return midb;
                    }
                }
            } catch (ClassNotFoundException e) {
                throw new ModelConverterException(E_FAIL_TO_LOAD_LEAF_IDENTIFIER_CLASS, e);
            }
        }
        return midb;
    }

    /**
     * Returns derived identity based on the leaf value.
     *
     * @param value      leaf value
     * @param referredId referred identity of leaf
     * @return derived identity
     */
    static YangIdentity getDerivedIdentity(String value,
                                           YangIdentity referredId) {
        if (referredId.getJavaClassNameOrBuiltInType().equalsIgnoreCase(value)) {
            return referredId;
        }

        List extendList = referredId.getExtendList();
        if (extendList != null && !extendList.isEmpty()) {
            for (YangIdentity identity : extendList) {
                if (identity.getYangSchemaNodeIdentifier().getName()
                        .equalsIgnoreCase(value)) {
                    return identity;
                }
            }
        }
        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy