blob: c9863c05d0ca3ddfc4b6d58585156fe30b8f053c [file] [log] [blame]
/*
* 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.yangutils.datamodel.utils;
import static org.onosproject.yangutils.datamodel.YangDataTypes.DECIMAL64;
import static org.onosproject.yangutils.datamodel.YangDataTypes.INT16;
import static org.onosproject.yangutils.datamodel.YangDataTypes.INT32;
import static org.onosproject.yangutils.datamodel.YangDataTypes.INT64;
import static org.onosproject.yangutils.datamodel.YangDataTypes.INT8;
import static org.onosproject.yangutils.datamodel.YangDataTypes.UINT16;
import static org.onosproject.yangutils.datamodel.YangDataTypes.UINT32;
import static org.onosproject.yangutils.datamodel.YangDataTypes.UINT64;
import static org.onosproject.yangutils.datamodel.YangDataTypes.UINT8;
import static org.onosproject.yangutils.datamodel.utils.YangConstructType.LENGTH_DATA;
import static org.onosproject.yangutils.datamodel.utils.YangConstructType.RANGE_DATA;
import static org.onosproject.yangutils.datamodel.utils.builtindatatype.BuiltInTypeObjectFactory.getDataObjectFromString;
import java.util.regex.Pattern;
import org.onosproject.yangutils.datamodel.YangDataTypes;
import org.onosproject.yangutils.datamodel.YangRangeInterval;
import org.onosproject.yangutils.datamodel.YangRangeRestriction;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangBuiltInDataTypeInfo;
/**
* Represents restriction resolver which provide common utility used by parser
* and during linking for restriction resolution.
*/
public final class RestrictionResolver {
private static final String PIPE = "|";
private static final String ADD = "+";
private static final String EMPTY_STRING = "";
private static final String INTERVAL = "..";
private static final int MAX_RANGE_BOUNDARY = 2;
private static final int MIN_RANGE_BOUNDARY = 1;
private static final String MIN_KEYWORD = "min";
private static final String MAX_KEYWORD = "max";
/**
* Creates a restriction resolver.
*/
private RestrictionResolver() {
}
/**
* Processes the range restriction for parser and linker.
*
* @param refRangeRestriction range restriction of referred typedef
* @param lineNumber error line number
* @param charPositionInLine error character position in line
* @param hasReferredRestriction whether has referred restriction
* @param curRangeString caller type's range string
* @param effectiveType effective type, when called from linker
* @return YANG range restriction
* @throws DataModelException a violation in data model rule
*/
public static YangRangeRestriction processRangeRestriction(YangRangeRestriction refRangeRestriction,
int lineNumber, int charPositionInLine,
boolean hasReferredRestriction,
String curRangeString, YangDataTypes effectiveType)
throws DataModelException {
YangBuiltInDataTypeInfo<?> startValue;
YangBuiltInDataTypeInfo<?> endValue;
YangRangeRestriction rangeRestriction = new YangRangeRestriction();
String rangeArgument = removeQuotesAndHandleConcat(curRangeString);
String[] rangeArguments = rangeArgument.trim().split(Pattern.quote(PIPE));
for (String rangePart : rangeArguments) {
String startInterval;
String endInterval;
YangRangeInterval rangeInterval = new YangRangeInterval();
String[] rangeBoundary = rangePart.trim().split(Pattern.quote(INTERVAL));
if (rangeBoundary.length > MAX_RANGE_BOUNDARY) {
DataModelException dataModelException = new DataModelException("YANG file error : " +
YangConstructType.getYangConstructType(RANGE_DATA) + " " + rangeArgument +
" is not valid.");
dataModelException.setLine(lineNumber);
dataModelException.setCharPosition(charPositionInLine);
throw dataModelException;
}
if (rangeBoundary.length == MIN_RANGE_BOUNDARY) {
startInterval = rangeBoundary[0].trim();
endInterval = rangeBoundary[0].trim();
} else {
startInterval = rangeBoundary[0].trim();
endInterval = rangeBoundary[1].trim();
}
try {
if (hasReferredRestriction && startInterval.equals(MIN_KEYWORD)
&& refRangeRestriction.getMinRestrictedvalue() != null) {
startValue = refRangeRestriction.getMinRestrictedvalue();
} else if (hasReferredRestriction && startInterval.equals(MAX_KEYWORD)
&& refRangeRestriction.getMaxRestrictedvalue() != null) {
startValue = refRangeRestriction.getMaxRestrictedvalue();
} else {
startValue = getDataObjectFromString(startInterval, effectiveType);
}
if (hasReferredRestriction && endInterval.equals(MIN_KEYWORD)
&& refRangeRestriction.getMinRestrictedvalue() != null) {
endValue = refRangeRestriction.getMinRestrictedvalue();
} else if (hasReferredRestriction && endInterval.equals(MAX_KEYWORD)
&& refRangeRestriction.getMaxRestrictedvalue() != null) {
endValue = refRangeRestriction.getMaxRestrictedvalue();
} else {
endValue = getDataObjectFromString(endInterval, effectiveType);
}
} catch (Exception e) {
DataModelException dataModelException = new DataModelException(e.getMessage());
dataModelException.setLine(lineNumber);
dataModelException.setCharPosition(charPositionInLine);
throw dataModelException;
}
rangeInterval.setStartValue(startValue);
rangeInterval.setEndValue(endValue);
try {
rangeRestriction.addRangeRestrictionInterval(rangeInterval);
} catch (DataModelException dataModelException) {
dataModelException.setLine(lineNumber);
dataModelException.setCharPosition(charPositionInLine);
throw dataModelException;
}
}
return rangeRestriction;
}
/**
* Processes the length restriction for parser and linker.
*
* @param refLengthRestriction length restriction of referred typedef
* @param lineNumber error line number
* @param charPositionInLine error character position in line
* @param hasReferredRestriction whether has referred restriction
* @param curLengthString caller type's length string
* @return YANG range restriction
* @throws DataModelException a violation in data model rule
*/
public static YangRangeRestriction processLengthRestriction(YangRangeRestriction refLengthRestriction,
int lineNumber, int charPositionInLine,
boolean hasReferredRestriction,
String curLengthString) throws DataModelException {
YangBuiltInDataTypeInfo<?> startValue;
YangBuiltInDataTypeInfo<?> endValue;
YangRangeRestriction lengthRestriction = new YangRangeRestriction<>();
String rangeArgument = removeQuotesAndHandleConcat(curLengthString);
String[] rangeArguments = rangeArgument.trim().split(Pattern.quote(PIPE));
for (String rangePart : rangeArguments) {
String startInterval;
String endInterval;
YangRangeInterval rangeInterval = new YangRangeInterval<>();
String[] rangeBoundary = rangePart.trim().split(Pattern.quote(INTERVAL));
if (rangeBoundary.length > MAX_RANGE_BOUNDARY) {
DataModelException dataModelException = new DataModelException("YANG file error : " +
YangConstructType.getYangConstructType(LENGTH_DATA) + " " + rangeArgument +
" is not valid.");
dataModelException.setLine(lineNumber);
dataModelException.setCharPosition(charPositionInLine);
throw dataModelException;
}
if (rangeBoundary.length == MIN_RANGE_BOUNDARY) {
startInterval = rangeBoundary[0].trim();
endInterval = rangeBoundary[0].trim();
} else {
startInterval = rangeBoundary[0].trim();
endInterval = rangeBoundary[1].trim();
}
try {
if (hasReferredRestriction && startInterval.equals(MIN_KEYWORD)
&& refLengthRestriction.getMinRestrictedvalue() != null) {
startValue = refLengthRestriction.getMinRestrictedvalue();
} else if (hasReferredRestriction && startInterval.equals(MAX_KEYWORD)
&& refLengthRestriction.getMaxRestrictedvalue() != null) {
startValue = refLengthRestriction.getMaxRestrictedvalue();
} else {
startValue = getDataObjectFromString(startInterval, YangDataTypes.UINT64);
}
if (hasReferredRestriction && endInterval.equals(MIN_KEYWORD)
&& refLengthRestriction.getMinRestrictedvalue() != null) {
endValue = refLengthRestriction.getMinRestrictedvalue();
} else if (hasReferredRestriction && endInterval.equals(MAX_KEYWORD)
&& refLengthRestriction.getMaxRestrictedvalue() != null) {
endValue = refLengthRestriction.getMaxRestrictedvalue();
} else {
endValue = getDataObjectFromString(endInterval, YangDataTypes.UINT64);
}
} catch (Exception e) {
DataModelException dataModelException = new DataModelException(e.getMessage());
dataModelException.setLine(lineNumber);
dataModelException.setCharPosition(charPositionInLine);
throw dataModelException;
}
rangeInterval.setStartValue(startValue);
rangeInterval.setEndValue(endValue);
try {
lengthRestriction.addRangeRestrictionInterval(rangeInterval);
} catch (DataModelException dataModelException) {
dataModelException.setLine(lineNumber);
dataModelException.setCharPosition(charPositionInLine);
throw dataModelException;
}
}
return lengthRestriction;
}
/**
* Returns whether the data type is of range restricted type.
*
* @param dataType data type to be checked
* @return true, if data type can have range restrictions, false otherwise
*/
public static boolean isOfRangeRestrictedType(YangDataTypes dataType) {
return dataType == INT8
|| dataType == INT16
|| dataType == INT32
|| dataType == INT64
|| dataType == UINT8
|| dataType == UINT16
|| dataType == UINT32
|| dataType == UINT64
|| dataType == DECIMAL64;
}
/**
* Removes doubles quotes and concatenates if string has plus symbol.
*
* @param yangStringData string from yang file
* @return concatenated string after removing double quotes
*/
private static String removeQuotesAndHandleConcat(String yangStringData) {
yangStringData = yangStringData.replace("\"", EMPTY_STRING);
String[] tmpData = yangStringData.split(Pattern.quote(ADD));
StringBuilder builder = new StringBuilder();
for (String yangString : tmpData) {
builder.append(yangString);
}
return builder.toString();
}
}