| /* |
| * Copyright 2016-present Open Networking Laboratory |
| * |
| * 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.yms.app.ydt; |
| |
| import org.onosproject.yangutils.datamodel.YangAugment; |
| import org.onosproject.yangutils.datamodel.YangSchemaNode; |
| import org.onosproject.yangutils.datamodel.YangSchemaNodeContextInfo; |
| import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier; |
| import org.onosproject.yangutils.datamodel.exceptions.DataModelException; |
| import org.onosproject.yms.app.ydt.exceptions.YdtException; |
| import org.onosproject.yms.ydt.YdtContextOperationType; |
| |
| import static org.onosproject.yms.app.ydt.YdtAppNodeOperationType.DELETE_ONLY; |
| import static org.onosproject.yms.app.ydt.YdtAppNodeOperationType.OTHER_EDIT; |
| import static org.onosproject.yms.app.ydt.YdtConstants.errorMsg; |
| import static org.onosproject.yms.ydt.YdtContextOperationType.CREATE; |
| import static org.onosproject.yms.ydt.YdtContextOperationType.DELETE; |
| import static org.onosproject.yms.ydt.YdtContextOperationType.MERGE; |
| |
| /** |
| * Utils to support yang data tree node creation. |
| */ |
| final class YdtUtils { |
| |
| // YDT formatted error string |
| private static final String E_CREATE_OP = |
| "Create request is not allowed under delete operation."; |
| private static final String E_DELETE_OP = |
| "Delete request is not allowed under create operation."; |
| private static final String FMT_TOO_FEW = |
| "Too few key parameters in %s. Expected %d; actual %d."; |
| private static final String FMT_TOO_MANY = |
| "Too many key parameters in %s. Expected %d; actual %d."; |
| |
| //No instantiation. |
| private YdtUtils() { |
| } |
| |
| /** |
| * Returns the app tree operation type with the help of YdtOperation type. |
| * |
| * @param opType ydt operation type |
| * @return app tree operation type |
| */ |
| static YdtAppNodeOperationType getAppOpTypeFromYdtOpType( |
| YdtContextOperationType opType) { |
| // Get the app tree operation type. |
| switch (opType) { |
| case CREATE: |
| case MERGE: |
| case REPLACE: |
| return OTHER_EDIT; |
| |
| case DELETE: |
| case REMOVE: |
| return DELETE_ONLY; |
| |
| default: |
| return null; |
| //TODO handle the default data type. |
| } |
| } |
| |
| /** |
| * Validates the various combination of operation type. |
| * |
| * @param parentOpType Reference for parent node operation type |
| * @param childOpType type of YANG data tree node operation |
| * @throws YdtException when user requested node operation type is |
| * not valid as per parent node operation type |
| */ |
| private static void validateOperationType(YdtContextOperationType parentOpType, |
| YdtContextOperationType childOpType) |
| throws YdtException { |
| |
| switch (parentOpType) { |
| case CREATE: |
| // Inside the create operation delete operation should not come. |
| if (childOpType == DELETE) { |
| throw new YdtException(E_CREATE_OP); |
| } |
| break; |
| case DELETE: |
| // Inside the delete operation create operation should not come. |
| if (childOpType == CREATE) { |
| throw new YdtException(E_DELETE_OP); |
| } |
| break; |
| default: |
| //TODO check all possible scenario. |
| } |
| } |
| |
| /** |
| * Returns the operation type for non leaf node. |
| * When "operation" attribute for current node is not specified or null, |
| * then the operation applied to the parent data node of the |
| * configuration is used. If no parent data node is available, |
| * then the default-operation'value is used. |
| * If default operation type is not set, merge will be taken as default |
| * operation type. |
| * |
| * @param type operation type of parent node |
| * @param defType YDT default operation type |
| * @return operation type for current non leaf node |
| */ |
| private static YdtContextOperationType getOperationType( |
| YdtContextOperationType type, YdtContextOperationType defType) { |
| return type != null ? type : (defType != null ? defType : MERGE); |
| } |
| |
| /** |
| * Returns the yang node identifier with requested name and namespace. |
| * |
| * @param name name of the node |
| * @param namespace namespace of the node |
| * @return yang node identifier |
| */ |
| static YangSchemaNodeIdentifier getNodeIdentifier(String name, |
| String namespace) { |
| YangSchemaNodeIdentifier id = new YangSchemaNodeIdentifier(); |
| id.setName(name); |
| id.setNameSpace(new NameSpace(namespace)); |
| return id; |
| } |
| |
| /** |
| * Checks the user supplied list of argument match's the expected value |
| * or not. |
| * |
| * @param name name of the parent list/leaf-list node |
| * @param expected count suppose to be |
| * @param actual user supplied values count |
| * @throws YdtException when user requested multi instance node instance's |
| * count doesn't fit into the allowed instance limit |
| */ |
| static void checkElementCount(String name, int expected, |
| int actual) throws YdtException { |
| if (expected < actual) { |
| throw new YdtException( |
| errorMsg(FMT_TOO_MANY, name, expected, actual)); |
| } else if (expected > actual) { |
| throw new YdtException( |
| errorMsg(FMT_TOO_FEW, name, expected, actual)); |
| } |
| } |
| |
| /** |
| * Returns the valid operation type for requested ydt node after performing |
| * validation. |
| * |
| * @param opType user requested operation type |
| * @param newNode new requested ydt node |
| * @param parentNode parent node under which new node to be added |
| * @param defOpType YDT context operation type |
| * @return operation type |
| * @throws YdtException when user requested node operation type is |
| * not valid as per parent node operation type |
| */ |
| static YdtContextOperationType getValidOpType( |
| YdtContextOperationType opType, YdtContextOperationType defOpType, |
| YdtNode newNode, YdtNode parentNode) |
| throws YdtException { |
| |
| switch (newNode.getYdtType()) { |
| |
| case SINGLE_INSTANCE_NODE: |
| case MULTI_INSTANCE_NODE: |
| |
| // Reference for parent node operation type. |
| YdtContextOperationType parentOpType = |
| parentNode.getYdtContextOperationType(); |
| |
| if (opType == null) { |
| opType = getOperationType(parentOpType, defOpType); |
| } else if (parentOpType != null) { |
| validateOperationType(parentOpType, opType); |
| } |
| |
| return opType; |
| |
| /* |
| * Nodes other then single/multi instance node does not support |
| * operation type so no need of validation for those. |
| */ |
| default: |
| return null; |
| } |
| } |
| |
| /** |
| * Returns augmenting node module yang schema node. |
| * |
| * @param id schema node identifier |
| * @param contextInfo Yang Schema node context info |
| * which is having YangSchemaNode and |
| * ContextSwitchedNode |
| * @return augmenting node module yang schema node |
| * @throws YdtException when user requested node schema doesn't exist |
| */ |
| public static YangSchemaNode getAugmentingSchemaNode( |
| YangSchemaNodeIdentifier id, |
| YangSchemaNodeContextInfo contextInfo) throws YdtException { |
| YangSchemaNode lastAugMod = null; |
| YangSchemaNode switchedNode = |
| contextInfo.getContextSwitchedNode(); |
| |
| // Finding the last augmenting schema for case/choice scenario. |
| while (switchedNode != null) { |
| if (switchedNode instanceof YangAugment) { |
| lastAugMod = switchedNode; |
| } |
| try { |
| switchedNode = switchedNode.getChildSchema(id) |
| .getContextSwitchedNode(); |
| } catch (DataModelException e) { |
| throw new YdtException(e.getMessage()); |
| } |
| } |
| return lastAugMod; |
| } |
| |
| /** |
| * De-reference all the tree node by walking the whole YDT from logical |
| * root node. |
| * This will be called only when any exception occurs while processing |
| * the node in Ydt tree. |
| * |
| * @param rootNode ydt logical root node |
| */ |
| public static void freeRestResources(YdtNode rootNode) { |
| |
| YdtNode currentNode = rootNode; |
| while (currentNode != null) { |
| |
| // Move down to first child |
| YdtNode nextNode = currentNode.getFirstChild(); |
| if (nextNode != null) { |
| currentNode = nextNode; |
| continue; |
| } |
| |
| // No child nodes, so walk tree |
| while (currentNode != null) { |
| // To keep the track of last sibling. |
| YdtNode lastSibling = currentNode; |
| |
| // Move to sibling if possible. |
| nextNode = currentNode.getNextSibling(); |
| |
| // free currentNode resources |
| free(lastSibling); |
| |
| lastSibling.getNamespace(); |
| if (nextNode != null) { |
| currentNode = nextNode; |
| break; |
| } |
| |
| // Move up |
| if (currentNode.equals(rootNode)) { |
| currentNode = null; |
| } else { |
| currentNode = currentNode.getParent(); |
| lastSibling.setParent(null); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Free the give YDT node by de-referencing it to null. |
| * |
| * @param node node to be freed |
| */ |
| private static void free(YdtNode node) { |
| if (node.getParent() != null) { |
| YdtNode parent = node.getParent(); |
| parent.setChild(null); |
| parent.setLastChild(null); |
| if (node.getNextSibling() != null) { |
| parent.setChild(node.getNextSibling()); |
| } |
| } |
| YdtNode parentRef = node.getParent(); |
| node = new YdtLogicalNode(null, null); |
| node.setParent(parentRef); |
| } |
| } |