blob: 8c94d7d50080c22a6ba4b05a486ce43de5a57b2b [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;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
import com.google.common.base.Strings;
import static org.onosproject.yangutils.datamodel.ResolvableStatus.INTRA_FILE_RESOLVED;
import static org.onosproject.yangutils.datamodel.ResolvableStatus.RESOLVED;
import static org.onosproject.yangutils.datamodel.YangDataTypes.BITS;
import static org.onosproject.yangutils.datamodel.YangDataTypes.BOOLEAN;
import static org.onosproject.yangutils.datamodel.YangDataTypes.DERIVED;
import static org.onosproject.yangutils.datamodel.YangDataTypes.EMPTY;
import static org.onosproject.yangutils.datamodel.YangDataTypes.ENUMERATION;
import static org.onosproject.yangutils.datamodel.YangDataTypes.IDENTITYREF;
import static org.onosproject.yangutils.datamodel.YangDataTypes.LEAFREF;
import static org.onosproject.yangutils.datamodel.YangDataTypes.STRING;
import static org.onosproject.yangutils.datamodel.YangDataTypes.UNION;
import static org.onosproject.yangutils.utils.RestrictionResolver.isOfRangeRestrictedType;
import static org.onosproject.yangutils.utils.RestrictionResolver.processLengthRestriction;
import static org.onosproject.yangutils.utils.RestrictionResolver.processRangeRestriction;
/**
* Represents the derived information.
*
* @param <T> extended information.
*/
public class YangDerivedInfo<T> implements LocationInfo {
/**
* YANG typedef reference.
*/
private YangTypeDef referredTypeDef;
/**
* Resolved additional information about data type after linking, example
* restriction info, named values, etc. The extra information is based
* on the data type. Based on the data type, the extended info can vary.
*/
private T resolvedExtendedInfo;
/**
* Line number of pattern restriction in YANG file.
*/
private int lineNumber;
/**
* Position of pattern restriction in line.
*/
private int charPositionInLine;
/**
* Effective built-in type, requried in case type of typedef is again a
* derived type. This information is to be added during linking.
*/
private YangDataTypes effectiveBuiltInType;
/**
* Length restriction string to temporary store the length restriction when the type
* is derived.
*/
private String lengthRestrictionString;
/**
* Range restriction string to temporary store the range restriction when the type
* is derived.
*/
private String rangeRestrictionString;
/**
* Pattern restriction string to temporary store the pattern restriction when the type
* is derived.
*/
private YangPatternRestriction patternRestriction;
/**
* Returns the referred typedef reference.
*
* @return referred typedef reference
*/
public YangTypeDef getReferredTypeDef() {
return referredTypeDef;
}
/**
* Sets the referred typedef reference.
*
* @param referredTypeDef referred typedef reference
*/
public void setReferredTypeDef(YangTypeDef referredTypeDef) {
this.referredTypeDef = referredTypeDef;
}
/**
* Returns resolved extended information after successful linking.
*
* @return resolved extended information
*/
public T getResolvedExtendedInfo() {
return resolvedExtendedInfo;
}
/**
* Sets resolved extended information after successful linking.
*
* @param resolvedExtendedInfo resolved extended information
*/
public void setResolvedExtendedInfo(T resolvedExtendedInfo) {
this.resolvedExtendedInfo = resolvedExtendedInfo;
}
@Override
public int getLineNumber() {
return lineNumber;
}
@Override
public int getCharPosition() {
return charPositionInLine;
}
@Override
public void setLineNumber(int lineNumber) {
this.lineNumber = lineNumber;
}
@Override
public void setCharPosition(int charPositionInLine) {
this.charPositionInLine = charPositionInLine;
}
/**
* Returns the length restriction string.
*
* @return the length restriction string
*/
public String getLengthRestrictionString() {
return lengthRestrictionString;
}
/**
* Sets the length restriction string.
*
* @param lengthRestrictionString the length restriction string
*/
public void setLengthRestrictionString(String lengthRestrictionString) {
this.lengthRestrictionString = lengthRestrictionString;
}
/**
* Returns the range restriction string.
*
* @return the range restriction string
*/
public String getRangeRestrictionString() {
return rangeRestrictionString;
}
/**
* Sets the range restriction string.
*
* @param rangeRestrictionString the range restriction string
*/
public void setRangeRestrictionString(String rangeRestrictionString) {
this.rangeRestrictionString = rangeRestrictionString;
}
/**
* Returns the pattern restriction.
*
* @return the pattern restriction
*/
public YangPatternRestriction getPatternRestriction() {
return patternRestriction;
}
/**
* Sets the pattern restriction.
*
* @param patternRestriction the pattern restriction
*/
public void setPatternRestriction(YangPatternRestriction patternRestriction) {
this.patternRestriction = patternRestriction;
}
/**
* Returns effective built-in type.
*
* @return effective built-in type
*/
public YangDataTypes getEffectiveBuiltInType() {
return effectiveBuiltInType;
}
/**
* Sets effective built-in type.
*
* @param effectiveBuiltInType effective built-in type
*/
public void setEffectiveBuiltInType(YangDataTypes effectiveBuiltInType) {
this.effectiveBuiltInType = effectiveBuiltInType;
}
/**
* Resolves the type derived info, by obtaining the effective built-in type
* and resolving the restrictions.
*
* @return resolution status
* @throws DataModelException a violation in data mode rule
*/
public ResolvableStatus resolve() throws DataModelException {
YangType<?> baseType = getReferredTypeDef().getTypeDefBaseType();
/*
* Checks the data type of the referred typedef, if it's derived,
* obtain effective built-in type and restrictions from it's derived
* info, otherwise take from the base type of type itself.
*/
if (baseType.getDataType() == DERIVED) {
/*
* Check whether the referred typedef is resolved.
*/
if (baseType.getResolvableStatus() != INTRA_FILE_RESOLVED && baseType.getResolvableStatus() != RESOLVED) {
throw new DataModelException("Linker Error: Referred typedef is not resolved.");
}
/*
* Check if the referred typedef is intra file resolved, if yes sets
* current status also to intra file resolved .
*/
if (getReferredTypeDef().getTypeDefBaseType().getResolvableStatus() == INTRA_FILE_RESOLVED) {
return INTRA_FILE_RESOLVED;
}
setEffectiveBuiltInType(((YangDerivedInfo<?>) baseType.getDataTypeExtendedInfo())
.getEffectiveBuiltInType());
YangDerivedInfo refDerivedInfo = ((YangDerivedInfo<?>) baseType.getDataTypeExtendedInfo());
/*
* Check whether the effective built-in type can have range
* restrictions, if yes call resolution of range.
*/
if (isOfRangeRestrictedType(getEffectiveBuiltInType())) {
if (refDerivedInfo.getResolvedExtendedInfo() == null) {
resolveRangeRestriction(null);
/*
* Return the resolution status as resolved, if it's not
* resolve range/string restriction will throw exception
* in previous function.
*/
return RESOLVED;
} else {
if (!(refDerivedInfo.getResolvedExtendedInfo() instanceof YangRangeRestriction)) {
throw new DataModelException("Linker error: Referred typedef restriction info is of invalid " +
"type.");
}
resolveRangeRestriction((YangRangeRestriction) refDerivedInfo.getResolvedExtendedInfo());
/*
* Return the resolution status as resolved, if it's not
* resolve range/string restriction will throw exception
* in previous function.
*/
return RESOLVED;
}
/*
* If the effective built-in type is of type string calls
* for string resolution.
*/
} else if (getEffectiveBuiltInType() == STRING) {
if (refDerivedInfo.getResolvedExtendedInfo() == null) {
resolveStringRestriction(null);
/*
* Return the resolution status as resolved, if it's not
* resolve range/string restriction will throw exception
* in previous function.
*/
return RESOLVED;
} else {
if (!(refDerivedInfo.getResolvedExtendedInfo() instanceof YangStringRestriction)) {
throw new DataModelException("Linker error: Referred typedef restriction info is of invalid " +
"type.");
}
resolveStringRestriction((YangStringRestriction) refDerivedInfo.getResolvedExtendedInfo());
/*
* Return the resolution status as resolved, if it's not
* resolve range/string restriction will throw exception
* in previous function.
*/
return RESOLVED;
}
}
} else {
setEffectiveBuiltInType((baseType.getDataType()));
/*
* Check whether the effective built-in type can have range
* restrictions, if yes call resolution of range.
*/
if (isOfRangeRestrictedType(getEffectiveBuiltInType())) {
if (baseType.getDataTypeExtendedInfo() == null) {
resolveRangeRestriction(null);
/*
* Return the resolution status as resolved, if it's not
* resolve range/string restriction will throw exception
* in previous function.
*/
return RESOLVED;
} else {
if (!(baseType.getDataTypeExtendedInfo() instanceof YangRangeRestriction)) {
throw new DataModelException("Linker error: Referred typedef restriction info is of invalid " +
"type.");
}
resolveRangeRestriction((YangRangeRestriction) baseType.getDataTypeExtendedInfo());
/*
* Return the resolution status as resolved, if it's not
* resolve range/string restriction will throw exception
* in previous function.
*/
return RESOLVED;
}
/*
* If the effective built-in type is of type string calls
* for string resolution.
*/
} else if (getEffectiveBuiltInType() == STRING) {
if (baseType.getDataTypeExtendedInfo() == null) {
resolveStringRestriction(null);
/*
* Return the resolution status as resolved, if it's not
* resolve range/string restriction will throw exception
* in previous function.
*/
return RESOLVED;
} else {
if (!(baseType.getDataTypeExtendedInfo() instanceof YangStringRestriction)) {
throw new DataModelException("Linker error: Referred typedef restriction info is of invalid " +
"type.");
}
resolveStringRestriction((YangStringRestriction) baseType.getDataTypeExtendedInfo());
/*
* Return the resolution status as resolved, if it's not
* resolve range/string restriction will throw exception
* in previous function.
*/
return RESOLVED;
}
}
}
/*
* Check if the data type is the one which can't be restricted, in
* this case check whether no self restrictions should be present.
*/
if (isOfValidNonRestrictedType(getEffectiveBuiltInType())) {
if (Strings.isNullOrEmpty(getLengthRestrictionString())
&& Strings.isNullOrEmpty(getRangeRestrictionString())
&& getPatternRestriction() == null) {
return RESOLVED;
} else {
throw new DataModelException("YANG file error: Restrictions can't be applied to a given type");
}
}
// Throw exception for unsupported types
throw new DataModelException("Linker error: Unable to process the derived type.");
}
/**
* Resolves the string restrictions.
*
* @param refStringRestriction referred string restriction of typedef
* @throws DataModelException a violation in data model rule
*/
private void resolveStringRestriction(YangStringRestriction refStringRestriction) throws DataModelException {
YangStringRestriction curStringRestriction = null;
YangRangeRestriction refRangeRestriction = null;
YangPatternRestriction refPatternRestriction = null;
/*
* Check that range restriction should be null when built-in type is
* string.
*/
if (!(Strings.isNullOrEmpty(getRangeRestrictionString()))) {
DataModelException dataModelException = new DataModelException("YANG file error: Range restriction " +
"should't be present for string data type.");
dataModelException.setLine(lineNumber);
dataModelException.setCharPosition(charPositionInLine);
throw dataModelException;
}
/*
* If referred restriction and self restriction both are null, no
* resolution is required.
*/
if (refStringRestriction == null && Strings.isNullOrEmpty(getLengthRestrictionString())
&& getPatternRestriction() == null) {
return;
}
/*
* If referred string restriction is not null, take value of length
* and pattern restriction and assign.
*/
if (refStringRestriction != null) {
refRangeRestriction = refStringRestriction.getLengthRestriction();
refPatternRestriction = refStringRestriction.getPatternRestriction();
}
YangRangeRestriction lengthRestriction = resolveLengthRestriction(refRangeRestriction);
YangPatternRestriction patternRestriction = resolvePatternRestriction(refPatternRestriction);
/*
* Check if either of length or pattern restriction is present, if yes
* create string restriction and assign value.
*/
if (lengthRestriction != null || patternRestriction != null) {
curStringRestriction = new YangStringRestriction();
curStringRestriction.setLengthRestriction(lengthRestriction);
curStringRestriction.setPatternRestriction(patternRestriction);
}
setResolvedExtendedInfo((T) curStringRestriction);
}
/**
* Resolves pattern restriction.
*
* @param refPatternRestriction referred pattern restriction of typedef
* @return resolved pattern restriction
*/
private YangPatternRestriction resolvePatternRestriction(YangPatternRestriction refPatternRestriction) {
/*
* If referred restriction and self restriction both are null, no
* resolution is required.
*/
if (refPatternRestriction == null && getPatternRestriction() == null) {
return null;
}
/*
* If self restriction is null, and referred restriction is present
* shallow copy the referred to self.
*/
if (getPatternRestriction() == null) {
return refPatternRestriction;
}
/*
* If referred restriction is null, and self restriction is present
* carry out self resolution.
*/
if (refPatternRestriction == null) {
return getPatternRestriction();
}
/*
* Get patterns of referred type and add it to current pattern
* restrictions.
*/
for (String pattern : refPatternRestriction.getPatternList()) {
getPatternRestriction().addPattern(pattern);
}
return getPatternRestriction();
}
/**
* Resolves the length restrictions.
*
* @param refLengthRestriction referred length restriction of typedef
* @return resolved length restriction
* @throws DataModelException a violation in data model rule
*/
private YangRangeRestriction resolveLengthRestriction(YangRangeRestriction refLengthRestriction) throws
DataModelException {
/*
* If referred restriction and self restriction both are null, no
* resolution is required.
*/
if (refLengthRestriction == null && Strings.isNullOrEmpty(getLengthRestrictionString())) {
return null;
}
/*
* If self restriction is null, and referred restriction is present
* shallow copy the referred to self.
*/
if (Strings.isNullOrEmpty(getLengthRestrictionString())) {
return refLengthRestriction;
}
/*
* If referred restriction is null, and self restriction is present
* carry out self resolution.
*/
if (refLengthRestriction == null) {
YangRangeRestriction curLengthRestriction = processLengthRestriction(null, lineNumber,
charPositionInLine, false, getLengthRestrictionString());
return curLengthRestriction;
}
/*
* Carry out self resolution based with obtained effective built-in
* type and MIN/MAX values as per the referred typedef's values.
*/
YangRangeRestriction curLengthRestriction = processLengthRestriction(refLengthRestriction, lineNumber,
charPositionInLine, true, getLengthRestrictionString());
// Resolve the range with referred typedef's restriction.
resolveLengthAndRangeRestriction(refLengthRestriction, curLengthRestriction);
return curLengthRestriction;
}
/**
* Resolves the length/range self and referred restriction, to check whether
* the all the range interval in self restriction is stricter than the
* referred typedef's restriction.
*
* @param refRestriction referred restriction
* @param curRestriction self restriction
*/
private void resolveLengthAndRangeRestriction(YangRangeRestriction refRestriction,
YangRangeRestriction curRestriction) throws DataModelException {
for (Object curInterval : curRestriction.getAscendingRangeIntervals()) {
if (!(curInterval instanceof YangRangeInterval)) {
throw new DataModelException("Linker error: Current range intervals not processed correctly.");
}
try {
refRestriction.isValidInterval((YangRangeInterval) curInterval);
} catch (DataModelException e) {
DataModelException dataModelException = new DataModelException(e);
dataModelException.setLine(lineNumber);
dataModelException.setCharPosition(charPositionInLine);
throw dataModelException;
}
}
}
/**
* Resolves the range restrictions.
*
* @param refRangeRestriction referred range restriction of typedef
* @throws DataModelException a violation in data model rule
*/
private void resolveRangeRestriction(YangRangeRestriction refRangeRestriction) throws DataModelException {
/*
* Check that string restriction should be null when built-in type is
* of range type.
*/
if (!(Strings.isNullOrEmpty(getLengthRestrictionString())) || getPatternRestriction() != null) {
DataModelException dataModelException = new DataModelException("YANG file error: Length/Pattern " +
"restriction should't be present for int/uint/decimal data type.");
dataModelException.setLine(lineNumber);
dataModelException.setCharPosition(charPositionInLine);
throw dataModelException;
}
/*
* If referred restriction and self restriction both are null, no
* resolution is required.
*/
if (refRangeRestriction == null && Strings.isNullOrEmpty(getRangeRestrictionString())) {
return;
}
/*
* If self restriction is null, and referred restriction is present
* shallow copy the referred to self.
*/
if (Strings.isNullOrEmpty(getRangeRestrictionString())) {
setResolvedExtendedInfo((T) refRangeRestriction);
return;
}
/*
* If referred restriction is null, and self restriction is present
* carry out self resolution.
*/
if (refRangeRestriction == null) {
YangRangeRestriction curRangeRestriction = processRangeRestriction(null, lineNumber,
charPositionInLine, false, getRangeRestrictionString(), getEffectiveBuiltInType());
setResolvedExtendedInfo((T) curRangeRestriction);
return;
}
/*
* Carry out self resolution based with obtained effective built-in
* type and MIN/MAX values as per the referred typedef's values.
*/
YangRangeRestriction curRangeRestriction = processRangeRestriction(refRangeRestriction, lineNumber,
charPositionInLine, true, getRangeRestrictionString(), getEffectiveBuiltInType());
// Resolve the range with referred typedef's restriction.
resolveLengthAndRangeRestriction(refRangeRestriction, curRangeRestriction);
setResolvedExtendedInfo((T) curRangeRestriction);
}
/**
* Returns whether the data type is of non restricted type.
*
* @param dataType data type to be checked
* @return true, if data type can't be restricted, false otherwise
*/
private boolean isOfValidNonRestrictedType(YangDataTypes dataType) {
return (dataType == BOOLEAN
|| dataType == ENUMERATION
|| dataType == BITS
|| dataType == EMPTY
|| dataType == UNION
|| dataType == IDENTITYREF
|| dataType == LEAFREF);
}
}