blob: 9846ab3140421b0d7da08df06983d4bedb0a79d2 [file] [log] [blame]
/*
* Copyright 2016-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.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);
}
}