diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangBit.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangBit.java index 5e33e36fd6..77f19c1e66 100644 --- a/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangBit.java +++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangBit.java @@ -20,6 +20,8 @@ import org.onosproject.yangutils.datamodel.exceptions.DataModelException; import org.onosproject.yangutils.parser.Parsable; import org.onosproject.yangutils.parser.ParsableDataType; +import java.util.Objects; + /*- * The "bit" statement, which is a sub-statement to the "type" statement, * MUST be present if the type is "bits". It is repeatedly used to @@ -57,7 +59,7 @@ public class YangBit implements YangCommonInfo, Parsable { private String description; /** - * reference info of the bit field. + * Reference info of the bit field. */ private String reference; @@ -67,7 +69,7 @@ public class YangBit implements YangCommonInfo, Parsable { private YangStatusType status; /** - * position of the bit whose name bit is described. + * Position of the bit whose name bit is described. */ private int position; @@ -79,7 +81,7 @@ public class YangBit implements YangCommonInfo, Parsable { } /** - * Get the bit name. + * Returns bit name. * * @return the bit name. */ @@ -97,7 +99,7 @@ public class YangBit implements YangCommonInfo, Parsable { } /** - * Get the description. + * Returns description. * * @return the description. */ @@ -117,7 +119,7 @@ public class YangBit implements YangCommonInfo, Parsable { } /** - * Get the textual reference. + * Returns textual reference. * * @return the reference. */ @@ -137,7 +139,7 @@ public class YangBit implements YangCommonInfo, Parsable { } /** - * Get the status. + * Returns status. * * @return the status. */ @@ -157,7 +159,7 @@ public class YangBit implements YangCommonInfo, Parsable { } /** - * Get the bit position. + * Returns bit position. * * @return the position */ @@ -184,6 +186,23 @@ public class YangBit implements YangCommonInfo, Parsable { return ParsableDataType.BIT_DATA; } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof YangBit) { + final YangBit other = (YangBit) obj; + return Objects.equals(this.bitName, other.bitName); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.bitName); + } + /** * Validate the data on entering the corresponding parse tree node. * diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangBits.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangBits.java index d519925110..54898a4cf0 100644 --- a/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangBits.java +++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/datamodel/YangBits.java @@ -36,8 +36,12 @@ import org.onosproject.yangutils.parser.ParsableDataType; */ public class YangBits implements Parsable { + // Bits information set. private Set bitSet; + // BITS name. + private String bitsName; + /** * Create a YANG bits type object. */ @@ -46,7 +50,7 @@ public class YangBits implements Parsable { } /** - * Get the bit set. + * Returns the bit set. * * @return the bit set */ @@ -55,7 +59,7 @@ public class YangBits implements Parsable { } /** - * set the bit set. + * Set the bit set. * * @param bitSet the bit set */ @@ -66,10 +70,13 @@ public class YangBits implements Parsable { /** * Add bit info. * - * @param bitInfo the bit Info to add. + * @param bitInfo the bit information to be added. + * @throws DataModelException due to violation in data model rules. */ - public void addBitInfo(YangBit bitInfo) { - getBitSet().add(bitInfo); + public void addBitInfo(YangBit bitInfo) throws DataModelException { + if (!getBitSet().add(bitInfo)) { + throw new DataModelException("YANG Bit already exists"); + } } /** @@ -82,6 +89,24 @@ public class YangBits implements Parsable { return ParsableDataType.BITS_DATA; } + /** + * Returns the bits name. + * + * @return name of the bits. + */ + public String getBitsName() { + return bitsName; + } + + /** + * Set bits name. + * + * @param bitsName bit name to be set. + */ + public void setBitsName(String bitsName) { + this.bitsName = bitsName; + } + /** * Validate the data on entering the corresponding parse tree node. * diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/ParsableDataType.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/ParsableDataType.java index 9d2cfb0ee2..046a2141b4 100644 --- a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/ParsableDataType.java +++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/ParsableDataType.java @@ -224,6 +224,11 @@ public enum ParsableDataType { */ ORGANIZATION_DATA, + /** + * Identifies the YANG position element parsed data. + */ + POSITION_DATA, + /** * Identifies the derived data type. */ @@ -318,6 +323,8 @@ public enum ParsableDataType { return "organization"; case VALUE_DATA: return "value"; + case POSITION_DATA: + return "position"; case DEFAULT_DATA: return "default"; case DERIVED: diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/TreeWalkListener.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/TreeWalkListener.java index 20e086fc44..e2f4d703f0 100644 --- a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/TreeWalkListener.java +++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/TreeWalkListener.java @@ -27,6 +27,8 @@ import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangListener; import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; import org.onosproject.yangutils.parser.impl.listeners.BaseFileListener; import org.onosproject.yangutils.parser.impl.listeners.BelongsToListener; +import org.onosproject.yangutils.parser.impl.listeners.BitListener; +import org.onosproject.yangutils.parser.impl.listeners.BitsListener; import org.onosproject.yangutils.parser.impl.listeners.ConfigListener; import org.onosproject.yangutils.parser.impl.listeners.ContactListener; import org.onosproject.yangutils.parser.impl.listeners.ContainerListener; @@ -46,6 +48,7 @@ import org.onosproject.yangutils.parser.impl.listeners.MinElementsListener; import org.onosproject.yangutils.parser.impl.listeners.ModuleListener; import org.onosproject.yangutils.parser.impl.listeners.NamespaceListener; import org.onosproject.yangutils.parser.impl.listeners.OrganizationListener; +import org.onosproject.yangutils.parser.impl.listeners.PositionListener; import org.onosproject.yangutils.parser.impl.listeners.PrefixListener; import org.onosproject.yangutils.parser.impl.listeners.PresenceListener; import org.onosproject.yangutils.parser.impl.listeners.ReferenceListener; @@ -691,22 +694,22 @@ public class TreeWalkListener implements GeneratedYangListener { @Override public void enterBitsSpecification(GeneratedYangParser.BitsSpecificationContext ctx) { - // TODO: implement the method. + BitsListener.processBitsEntry(this, ctx); } @Override public void exitBitsSpecification(GeneratedYangParser.BitsSpecificationContext ctx) { - // TODO: implement the method. + BitsListener.processBitsExit(this, ctx); } @Override public void enterBitStatement(GeneratedYangParser.BitStatementContext ctx) { - // TODO: implement the method. + BitListener.processBitEntry(this, ctx); } @Override public void exitBitStatement(GeneratedYangParser.BitStatementContext ctx) { - // TODO: implement the method. + BitListener.processBitExit(this, ctx); } @Override @@ -721,7 +724,7 @@ public class TreeWalkListener implements GeneratedYangListener { @Override public void enterPositionStatement(GeneratedYangParser.PositionStatementContext ctx) { - // TODO: implement the method. + PositionListener.processPositionEntry(this, ctx); } @Override diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/BitListener.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/BitListener.java new file mode 100644 index 0000000000..a574091a26 --- /dev/null +++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/BitListener.java @@ -0,0 +1,171 @@ +/* + * Copyright 2014-2016 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.parser.impl.listeners; + +/* + * Reference: RFC6020 and YANG ANTLR Grammar + * + * ABNF grammar as per RFC6020 + * bit-stmt = bit-keyword sep identifier-arg-str optsep + * (";" / + * "{" stmtsep + * ;; these stmts can appear in any order + * [position-stmt stmtsep] + * [status-stmt stmtsep] + * [description-stmt stmtsep] + * [reference-stmt stmtsep] + * "}" + * "}") + * + * ANTLR grammar rule + * bitStatement : BIT_KEYWORD IDENTIFIER (STMTEND | LEFT_CURLY_BRACE bitBodyStatement RIGHT_CURLY_BRACE); + * + * bitBodyStatement : positionStatement? statusStatement? descriptionStatement? referenceStatement? + * | positionStatement? statusStatement? referenceStatement? descriptionStatement? + * | positionStatement? descriptionStatement? statusStatement? referenceStatement? + * | positionStatement? descriptionStatement? referenceStatement? statusStatement? + * | positionStatement? referenceStatement? statusStatement? descriptionStatement? + * | positionStatement? referenceStatement? descriptionStatement? statusStatement? + * | statusStatement? positionStatement? descriptionStatement? referenceStatement? + * | statusStatement? positionStatement? referenceStatement? descriptionStatement? + * | statusStatement? descriptionStatement? descriptionStatement? positionStatement? + * | statusStatement? descriptionStatement? positionStatement? descriptionStatement? + * | statusStatement? referenceStatement? positionStatement? descriptionStatement? + * | statusStatement? referenceStatement? descriptionStatement? positionStatement? + * | descriptionStatement? positionStatement? statusStatement? referenceStatement? + * | descriptionStatement? positionStatement? referenceStatement? statusStatement? + * | descriptionStatement? statusStatement? positionStatement? referenceStatement? + * | descriptionStatement? statusStatement? referenceStatement? positionStatement? + * | descriptionStatement? referenceStatement? positionStatement? statusStatement? + * | descriptionStatement? referenceStatement? statusStatement? positionStatement? + * | referenceStatement? positionStatement? descriptionStatement? statusStatement? + * | referenceStatement? positionStatement? statusStatement? descriptionStatement? + * | referenceStatement? statusStatement? descriptionStatement? positionStatement? + * | referenceStatement? statusStatement? positionStatement? descriptionStatement? + * | referenceStatement? descriptionStatement? positionStatement? statusStatement? + * | referenceStatement? descriptionStatement? statusStatement? positionStatement? + * ; + */ + +import org.onosproject.yangutils.datamodel.YangBit; +import org.onosproject.yangutils.datamodel.YangBits; +import org.onosproject.yangutils.datamodel.exceptions.DataModelException; +import org.onosproject.yangutils.parser.Parsable; +import static org.onosproject.yangutils.parser.ParsableDataType.BIT_DATA; +import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; +import org.onosproject.yangutils.parser.exceptions.ParserException; +import org.onosproject.yangutils.parser.impl.TreeWalkListener; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_CONTENT; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty; + +/** + * Implements listener based call back function corresponding to the "bit" + * rule defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020. + */ +public final class BitListener { + + /** + * Creates a new bit listener. + */ + private BitListener() { + } + + /** + * It is called when parser enters grammar rule (bit), it perform + * validations and updates the data model tree. + * + * @param listener listener's object. + * @param ctx context object of the grammar rule. + */ + public static void processBitEntry(TreeWalkListener listener, + GeneratedYangParser.BitStatementContext ctx) { + + // Check for stack to be non empty. + checkStackIsNotEmpty(listener, MISSING_HOLDER, BIT_DATA, ctx.IDENTIFIER().getText(), ENTRY); + + YangBit bitNode = new YangBit(); + bitNode.setBitName(ctx.IDENTIFIER().getText()); + listener.getParsedDataStack().push(bitNode); + } + + /** + * It is called when parser exits from grammar rule (bit), it perform + * validations and update the data model tree. + * + * @param listener Listener's object. + * @param ctx context object of the grammar rule. + */ + public static void processBitExit(TreeWalkListener listener, + GeneratedYangParser.BitStatementContext ctx) { + + // Check for stack to be non empty. + checkStackIsNotEmpty(listener, MISSING_HOLDER, BIT_DATA, ctx.IDENTIFIER().getText(), EXIT); + + Parsable tmpBitNode = listener.getParsedDataStack().peek(); + if (tmpBitNode instanceof YangBit) { + listener.getParsedDataStack().pop(); + + // Check for stack to be non empty. + checkStackIsNotEmpty(listener, MISSING_HOLDER, BIT_DATA, ctx.IDENTIFIER().getText(), EXIT); + + Parsable tmpNode = listener.getParsedDataStack().peek(); + switch (tmpNode.getParsableDataType()) { + case BITS_DATA: { + YangBits yangBits = (YangBits) tmpNode; + if ((ctx.bitBodyStatement() == null) || (ctx.bitBodyStatement().positionStatement() == null)) { + int maxPosition = 0; + boolean isPositionPresent = false; + + for (YangBit curBit : yangBits.getBitSet()) { + if (maxPosition <= curBit.getPosition()) { + maxPosition = curBit.getPosition(); + isPositionPresent = true; + } + } + if (isPositionPresent) { + maxPosition++; + } + ((YangBit) tmpBitNode).setPosition(maxPosition); + } + try { + yangBits.addBitInfo((YangBit) tmpBitNode); + } catch (DataModelException e) { + ParserException parserException = new ParserException(constructExtendedListenerErrorMessage( + INVALID_CONTENT, BIT_DATA, ctx.IDENTIFIER().getText(), EXIT, e.getMessage())); + parserException.setLine(ctx.IDENTIFIER().getSymbol().getLine()); + parserException.setCharPosition(ctx.IDENTIFIER().getSymbol().getCharPositionInLine()); + throw parserException; + } + break; + } + default: + throw new ParserException( + constructListenerErrorMessage(INVALID_HOLDER, BIT_DATA, ctx.IDENTIFIER().getText(), EXIT)); + } + } else { + throw new ParserException( + constructListenerErrorMessage(MISSING_CURRENT_HOLDER, BIT_DATA, ctx.IDENTIFIER().getText(), EXIT)); + } + } +} diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/BitsListener.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/BitsListener.java new file mode 100644 index 0000000000..d8f8467020 --- /dev/null +++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/BitsListener.java @@ -0,0 +1,151 @@ +/* + * Copyright 2014-2016 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.parser.impl.listeners; + +/* + * Reference: RFC6020 and YANG ANTLR Grammar + * + * ABNF grammar as per RFC6020 + * type-body-stmts = numerical-restrictions / + * decimal64-specification / + * string-restrictions / + * enum-specification / + * leafref-specification / + * identityref-specification / + * instance-identifier-specification / + * bits-specification / + * union-specification + * + * bits-specification = 1*(bit-stmt stmtsep) + * + * ANTLR grammar rule + * + * typeBodyStatements : numericalRestrictions | stringRestrictions | enumSpecification + * | leafrefSpecification | identityrefSpecification | instanceIdentifierSpecification + * | bitsSpecification | unionSpecification; + * + * bitsSpecification : bitStatement+; + */ + +import org.onosproject.yangutils.datamodel.YangBits; +import org.onosproject.yangutils.datamodel.YangLeaf; +import org.onosproject.yangutils.datamodel.YangLeafList; +import org.onosproject.yangutils.datamodel.YangType; +import org.onosproject.yangutils.parser.Parsable; +import static org.onosproject.yangutils.parser.ParsableDataType.BITS_DATA; +import static org.onosproject.yangutils.parser.ParsableDataType.TYPE_DATA; +import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; +import org.onosproject.yangutils.parser.exceptions.ParserException; +import org.onosproject.yangutils.parser.impl.TreeWalkListener; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty; + +/** + * Implements listener based call back function corresponding to the "bits" + * rule defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020. + */ +public final class BitsListener { + + /** + * Creates a new bits listener. + */ + private BitsListener() { + } + + /** + * It is called when parser enters grammar rule (bits), it perform + * validations and updates the data model tree. + * + * @param listener listener's object. + * @param ctx context object of the grammar rule. + */ + public static void processBitsEntry(TreeWalkListener listener, + GeneratedYangParser.BitsSpecificationContext ctx) { + + // Check for stack to be non empty. + checkStackIsNotEmpty(listener, MISSING_HOLDER, BITS_DATA, "", ENTRY); + + if (listener.getParsedDataStack().peek() instanceof YangType) { + YangBits bitsNode = new YangBits(); + Parsable typeData = listener.getParsedDataStack().pop(); + + // Check for stack to be non empty. + checkStackIsNotEmpty(listener, MISSING_HOLDER, BITS_DATA, "", ENTRY); + + Parsable tmpData = listener.getParsedDataStack().peek(); + + switch (tmpData.getParsableDataType()) { + case LEAF_DATA: + bitsNode.setBitsName(((YangLeaf) tmpData).getLeafName()); + break; + case LEAF_LIST_DATA: + bitsNode.setBitsName(((YangLeafList) tmpData).getLeafName()); + break; + // TODO typedef, union, deviate. + default: + throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, TYPE_DATA, + ((YangType) typeData).getDataTypeName(), ENTRY)); + } + listener.getParsedDataStack().push(typeData); + listener.getParsedDataStack().push(bitsNode); + } else { + throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, BITS_DATA, "", ENTRY)); + } + } + + /** + * It is called when parser exits from grammar rule (bits), it perform + * validations and update the data model tree. + * + * @param listener Listener's object. + * @param ctx context object of the grammar rule. + */ + public static void processBitsExit(TreeWalkListener listener, + GeneratedYangParser.BitsSpecificationContext ctx) { + + // Check for stack to be non empty. + checkStackIsNotEmpty(listener, MISSING_HOLDER, BITS_DATA, "", EXIT); + + Parsable tmpBitsNode = listener.getParsedDataStack().peek(); + if (tmpBitsNode instanceof YangBits) { + listener.getParsedDataStack().pop(); + + // Check for stack to be non empty. + checkStackIsNotEmpty(listener, MISSING_HOLDER, BITS_DATA, "", EXIT); + + Parsable tmpNode = listener.getParsedDataStack().peek(); + switch (tmpNode.getParsableDataType()) { + case TYPE_DATA: { + YangType typeNode = (YangType) tmpNode; + typeNode.setDataTypeExtendedInfo((YangBits) tmpBitsNode); + break; + } + default: + throw new ParserException( + constructListenerErrorMessage(INVALID_HOLDER, BITS_DATA, "", EXIT)); + } + } else { + throw new ParserException( + constructListenerErrorMessage(MISSING_CURRENT_HOLDER, BITS_DATA, "", EXIT)); + } + } +} diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/PositionListener.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/PositionListener.java new file mode 100644 index 0000000000..92b3e686aa --- /dev/null +++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/PositionListener.java @@ -0,0 +1,137 @@ +/* + * Copyright 2014-2016 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.parser.impl.listeners; + +/* + * Reference: RFC6020 and YANG ANTLR Grammar + * + * ABNF grammar as per RFC6020 + * position-stmt = position-keyword sep + * position-value-arg-str stmtend + * position-value-arg-str = < a string that matches the rule + * position-value-arg > + * position-value-arg = non-negative-integer-value + * non-negative-integer-value = "0" / positive-integer-value + * positive-integer-value = (non-zero-digit *DIGIT) + * zero-integer-value = 1*DIGIT + * + * ANTLR grammar rule + * positionStatement : POSITION_KEYWORD INTEGER STMTEND; + */ + +import org.onosproject.yangutils.datamodel.YangBit; +import org.onosproject.yangutils.datamodel.YangBits; +import org.onosproject.yangutils.parser.Parsable; +import static org.onosproject.yangutils.parser.ParsableDataType.POSITION_DATA; +import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; +import org.onosproject.yangutils.parser.exceptions.ParserException; +import org.onosproject.yangutils.parser.impl.TreeWalkListener; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER; +import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty; + +/** + * Implements listener based call back function corresponding to the "position" + * rule defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020. + */ +public final class PositionListener { + + // Exact message in case position is invalid. + private static String errMsg; + + /** + * Creates a new position listener. + */ + private PositionListener() { + } + + /** + * It is called when parser receives an input matching the grammar rule + * (position), perform validations and update the data model tree. + * + * @param listener Listener's object. + * @param ctx context object of the grammar rule. + */ + public static void processPositionEntry(TreeWalkListener listener, + GeneratedYangParser.PositionStatementContext ctx) { + + // Check for stack to be non empty. + checkStackIsNotEmpty(listener, MISSING_HOLDER, POSITION_DATA, ctx.INTEGER().getText(), ENTRY); + + // Obtain the node of the stack. + Parsable tmpNode = listener.getParsedDataStack().peek(); + switch (tmpNode.getParsableDataType()) { + case BIT_DATA: { + YangBit bitNode = (YangBit) tmpNode; + if (!isBitPositionValid(listener, ctx)) { + ParserException parserException = new ParserException(errMsg); + parserException.setLine(ctx.INTEGER().getSymbol().getLine()); + parserException.setCharPosition(ctx.INTEGER().getSymbol().getCharPositionInLine()); + throw parserException; + } + bitNode.setPosition(Integer.valueOf(ctx.INTEGER().getText())); + break; + } + default: + throw new ParserException( + constructListenerErrorMessage(INVALID_HOLDER, POSITION_DATA, ctx.INTEGER().getText(), ENTRY)); + } + } + + /** + * Validates BITS position value correctness and uniqueness. + * + * @param listener Listener's object. + * @param ctx context object of the grammar rule. + * @return validation result + */ + private static boolean isBitPositionValid(TreeWalkListener listener, + GeneratedYangParser.PositionStatementContext ctx) { + Parsable bitNode = listener.getParsedDataStack().pop(); + + // Check for stack to be non empty. + checkStackIsNotEmpty(listener, MISSING_HOLDER, POSITION_DATA, ctx.INTEGER().getText(), ENTRY); + + if (Integer.valueOf(ctx.INTEGER().getText()) < 0) { + errMsg = "Negative value of position is invalid"; + listener.getParsedDataStack().push(bitNode); + return false; + } + + Parsable tmpNode = listener.getParsedDataStack().peek(); + switch (tmpNode.getParsableDataType()) { + case BITS_DATA: { + YangBits yangBits = (YangBits) tmpNode; + for (YangBit curBit : yangBits.getBitSet()) { + if (Integer.valueOf(ctx.INTEGER().getText()) == curBit.getPosition()) { + errMsg = "Duplicate value of position is invalid"; + listener.getParsedDataStack().push(bitNode); + return false; + } + } + listener.getParsedDataStack().push(bitNode); + return true; + } + default: + listener.getParsedDataStack().push(bitNode); + throw new ParserException( + constructListenerErrorMessage(INVALID_HOLDER, POSITION_DATA, ctx.INTEGER().getText(), ENTRY)); + } + } +} \ No newline at end of file diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ValueListener.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ValueListener.java index 07ada45f8a..7c050dcd03 100644 --- a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ValueListener.java +++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ValueListener.java @@ -34,7 +34,6 @@ import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser; import org.onosproject.yangutils.parser.exceptions.ParserException; import org.onosproject.yangutils.parser.impl.TreeWalkListener; import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY; -import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT; import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage; import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER; import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER; @@ -70,7 +69,7 @@ public final class ValueListener { case ENUM_DATA: { YangEnum enumNode = (YangEnum) tmpNode; if (!isEnumValueValid(listener, ctx)) { - ParserException parserException = new ParserException("Input version not supported"); + ParserException parserException = new ParserException("Duplicate Value Entry"); parserException.setLine(ctx.INTEGER().getSymbol().getLine()); parserException.setCharPosition(ctx.INTEGER().getSymbol().getCharPositionInLine()); throw parserException; @@ -93,6 +92,10 @@ public final class ValueListener { */ private static boolean isEnumValueValid(TreeWalkListener listener, GeneratedYangParser.ValueStatementContext ctx) { Parsable enumNode = listener.getParsedDataStack().pop(); + + // Check for stack to be non empty. + checkStackIsNotEmpty(listener, MISSING_HOLDER, VALUE_DATA, ctx.INTEGER().getText(), ENTRY); + Parsable tmpNode = listener.getParsedDataStack().peek(); switch (tmpNode.getParsableDataType()) { case ENUMERATION_DATA: { @@ -109,7 +112,7 @@ public final class ValueListener { default: listener.getParsedDataStack().push(enumNode); throw new ParserException( - constructListenerErrorMessage(INVALID_HOLDER, VALUE_DATA, ctx.INTEGER().getText(), EXIT)); + constructListenerErrorMessage(INVALID_HOLDER, VALUE_DATA, ctx.INTEGER().getText(), ENTRY)); } } } diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/parserutils/ListenerErrorType.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/parserutils/ListenerErrorType.java index e28d186c1d..1d061d7cb8 100644 --- a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/parserutils/ListenerErrorType.java +++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/parserutils/ListenerErrorType.java @@ -54,6 +54,11 @@ public enum ListenerErrorType { */ DUPLICATE_ENTRY(), + /** + * Represents that the content is invalid. + */ + INVALID_CONTENT(), + /** * Represents that some of earlier parsed data is not handled correctly. */ @@ -80,6 +85,8 @@ public enum ListenerErrorType { return "Invalid cardinality in"; case DUPLICATE_ENTRY: return "Duplicate"; + case INVALID_CONTENT: + return "Invalid content in"; case UNHANDLED_PARSED_DATA: return "Unhandled parsed data at"; default: diff --git a/utils/yangutils/src/test/java/org/onosproject/yangutils/parser/impl/listeners/BitListenerTest.java b/utils/yangutils/src/test/java/org/onosproject/yangutils/parser/impl/listeners/BitListenerTest.java new file mode 100644 index 0000000000..d741ac398e --- /dev/null +++ b/utils/yangutils/src/test/java/org/onosproject/yangutils/parser/impl/listeners/BitListenerTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2014-2016 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.parser.impl.listeners; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import org.junit.Test; +import org.onosproject.yangutils.datamodel.YangBit; +import org.onosproject.yangutils.datamodel.YangBits; +import org.onosproject.yangutils.datamodel.YangDataTypes; +import org.onosproject.yangutils.datamodel.YangLeaf; +import org.onosproject.yangutils.datamodel.YangModule; +import org.onosproject.yangutils.datamodel.YangNode; +import org.onosproject.yangutils.datamodel.YangNodeType; +import org.onosproject.yangutils.parser.exceptions.ParserException; +import org.onosproject.yangutils.parser.impl.YangUtilsParserManager; + +import java.io.IOException; +import java.util.ListIterator; +import java.util.Set; + +/** + * Test cases for bit listener. + */ +public class BitListenerTest { + + private final YangUtilsParserManager manager = new YangUtilsParserManager(); + + /** + * Checks bit statement without position. + */ + @Test + public void processBitTypeStatement() throws IOException, ParserException { + + YangNode node = manager.getDataModel("src/test/resources/BitTypeStatement.yang"); + + // Check whether the data model tree returned is of type module. + assertThat((node instanceof YangModule), is(true)); + + // Check whether the node type is set properly to module. + assertThat(node.getNodeType(), is(YangNodeType.MODULE_NODE)); + + // Check whether the module name is set correctly. + YangModule yangNode = (YangModule) node; + assertThat(yangNode.getName(), is("Test")); + + ListIterator leafIterator = yangNode.getListOfLeaf().listIterator(); + YangLeaf leafInfo = leafIterator.next(); + + assertThat(leafInfo.getLeafName(), is("mybits")); + assertThat(leafInfo.getDataType().getDataTypeName(), is("bits")); + assertThat(leafInfo.getDataType().getDataType(), is(YangDataTypes.BITS)); + assertThat(((YangBits) leafInfo.getDataType().getDataTypeExtendedInfo()).getBitsName(), + is("mybits")); + + Set bitSet = ((YangBits) leafInfo.getDataType().getDataTypeExtendedInfo()).getBitSet(); + for (YangBit tmp : bitSet) { + if (tmp.getBitName().equals("disable-nagle")) { + assertThat(tmp.getPosition(), is(0)); + } else if (tmp.getBitName().equals("auto-sense-speed")) { + assertThat(tmp.getPosition(), is(1)); + } else if (tmp.getBitName().equals("Ten-Mb-only")) { + assertThat(tmp.getPosition(), is(2)); + } + } + } + + /** + * Checks if enum with same name is not allowed. + */ + @Test(expected = ParserException.class) + public void processBitWithDuplicateName() throws IOException, ParserException { + + YangNode node = manager.getDataModel("src/test/resources/BitWithDuplicateName.yang"); + } +} diff --git a/utils/yangutils/src/test/java/org/onosproject/yangutils/parser/impl/listeners/EnumListenerTest.java b/utils/yangutils/src/test/java/org/onosproject/yangutils/parser/impl/listeners/EnumListenerTest.java index 60de57fc9a..7041fdf90f 100644 --- a/utils/yangutils/src/test/java/org/onosproject/yangutils/parser/impl/listeners/EnumListenerTest.java +++ b/utils/yangutils/src/test/java/org/onosproject/yangutils/parser/impl/listeners/EnumListenerTest.java @@ -78,4 +78,13 @@ public class EnumListenerTest { } } } + + /** + * Checks if enum with same name is not allowed. + */ + @Test(expected = ParserException.class) + public void processEnumWithDuplicateName() throws IOException, ParserException { + + YangNode node = manager.getDataModel("src/test/resources/EnumWithDuplicateName.yang"); + } } diff --git a/utils/yangutils/src/test/java/org/onosproject/yangutils/parser/impl/listeners/PositionListenerTest.java b/utils/yangutils/src/test/java/org/onosproject/yangutils/parser/impl/listeners/PositionListenerTest.java new file mode 100644 index 0000000000..7033dddd00 --- /dev/null +++ b/utils/yangutils/src/test/java/org/onosproject/yangutils/parser/impl/listeners/PositionListenerTest.java @@ -0,0 +1,147 @@ +/* + * Copyright 2014-2016 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.parser.impl.listeners; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import org.junit.Test; +import org.onosproject.yangutils.datamodel.YangBit; +import org.onosproject.yangutils.datamodel.YangBits; +import org.onosproject.yangutils.datamodel.YangDataTypes; +import org.onosproject.yangutils.datamodel.YangLeaf; +import org.onosproject.yangutils.datamodel.YangModule; +import org.onosproject.yangutils.datamodel.YangNode; +import org.onosproject.yangutils.datamodel.YangNodeType; +import org.onosproject.yangutils.parser.exceptions.ParserException; +import org.onosproject.yangutils.parser.impl.YangUtilsParserManager; + +import java.io.IOException; +import java.util.ListIterator; +import java.util.Set; + +/** + * Test cases for position listener. + */ +public class PositionListenerTest { + + private final YangUtilsParserManager manager = new YangUtilsParserManager(); + + /** + * Checks explicitly configured value. + */ + @Test + public void processPositionStatement() throws IOException, ParserException { + + YangNode node = manager.getDataModel("src/test/resources/PositionStatement.yang"); + + // Check whether the data model tree returned is of type module. + assertThat((node instanceof YangModule), is(true)); + + // Check whether the node type is set properly to module. + assertThat(node.getNodeType(), is(YangNodeType.MODULE_NODE)); + + // Check whether the module name is set correctly. + YangModule yangNode = (YangModule) node; + assertThat(yangNode.getName(), is("Test")); + + ListIterator leafIterator = yangNode.getListOfLeaf().listIterator(); + YangLeaf leafInfo = leafIterator.next(); + + assertThat(leafInfo.getLeafName(), is("mybits")); + assertThat(leafInfo.getDataType().getDataTypeName(), is("bits")); + assertThat(leafInfo.getDataType().getDataType(), is(YangDataTypes.BITS)); + assertThat(((YangBits) leafInfo.getDataType().getDataTypeExtendedInfo()).getBitsName(), + is("mybits")); + + Set bitSet = ((YangBits) leafInfo.getDataType().getDataTypeExtendedInfo()).getBitSet(); + for (YangBit tmp : bitSet) { + if (tmp.getBitName().equals("disable-nagle")) { + assertThat(tmp.getPosition(), is(0)); + } else if (tmp.getBitName().equals("auto-sense-speed")) { + assertThat(tmp.getPosition(), is(1)); + } else if (tmp.getBitName().equals("Ten-Mb-only")) { + assertThat(tmp.getPosition(), is(2)); + } + } + } + + /** + * Checks explicit value and auto generated value. + */ + @Test + public void processPositionImplicitAndExplicit() throws IOException, ParserException { + + YangNode node = manager.getDataModel("src/test/resources/PositionImplicitAndExplicit.yang"); + + // Check whether the data model tree returned is of type module. + assertThat((node instanceof YangModule), is(true)); + + // Check whether the node type is set properly to module. + assertThat(node.getNodeType(), is(YangNodeType.MODULE_NODE)); + + // Check whether the module name is set correctly. + YangModule yangNode = (YangModule) node; + assertThat(yangNode.getName(), is("Test")); + + ListIterator leafIterator = yangNode.getListOfLeaf().listIterator(); + YangLeaf leafInfo = leafIterator.next(); + + assertThat(leafInfo.getLeafName(), is("mybits")); + assertThat(leafInfo.getDataType().getDataTypeName(), is("bits")); + assertThat(leafInfo.getDataType().getDataType(), is(YangDataTypes.BITS)); + assertThat(((YangBits) leafInfo.getDataType().getDataTypeExtendedInfo()).getBitsName(), + is("mybits")); + + Set bitSet = ((YangBits) leafInfo.getDataType().getDataTypeExtendedInfo()).getBitSet(); + for (YangBit tmp : bitSet) { + if (tmp.getBitName().equals("disable-nagle")) { + assertThat(tmp.getPosition(), is(0)); + } else if (tmp.getBitName().equals("auto-sense-speed")) { + assertThat(tmp.getPosition(), is(1)); + } else if (tmp.getBitName().equals("Ten-Mb-only")) { + assertThat(tmp.getPosition(), is(2)); + } + } + } + + /** + * Checks explicit value should not be repeated. + */ + @Test(expected = ParserException.class) + public void processPositionDuplication() throws IOException, ParserException { + + YangNode node = manager.getDataModel("src/test/resources/PositionDuplication.yang"); + } + + /** + * Checks explicit or auto generated value should not be repeated. + */ + @Test(expected = ParserException.class) + public void processPositionImplicitAndExplicitDuplication() throws IOException, ParserException { + + YangNode node = manager.getDataModel("src/test/resources/PositionImplicitAndExplicitDuplication.yang"); + } + + /** + * Checks if negative value of position is not allowed. + */ + @Test(expected = ParserException.class) + public void processPositionNegativeValue() throws IOException, ParserException { + + YangNode node = manager.getDataModel("src/test/resources/PositionNegativeValue.yang"); + } +} diff --git a/utils/yangutils/src/test/resources/BitTypeStatement.yang b/utils/yangutils/src/test/resources/BitTypeStatement.yang new file mode 100644 index 0000000000..9d13495104 --- /dev/null +++ b/utils/yangutils/src/test/resources/BitTypeStatement.yang @@ -0,0 +1,12 @@ +module Test { + yang-version 1; + namespace http://huawei.com; + prefix Ant; + leaf mybits { + type bits { + bit disable-nagle; + bit auto-sense-speed; + bit Ten-Mb-only; + } + } +} diff --git a/utils/yangutils/src/test/resources/BitWithDuplicateName.yang b/utils/yangutils/src/test/resources/BitWithDuplicateName.yang new file mode 100644 index 0000000000..ed5cc3238f --- /dev/null +++ b/utils/yangutils/src/test/resources/BitWithDuplicateName.yang @@ -0,0 +1,12 @@ +module Test { + yang-version 1; + namespace http://huawei.com; + prefix Ant; + leaf mybits { + type bits { + bit disable-nagle; + bit disable-nagle; + bit Ten-Mb-only; + } + } +} diff --git a/utils/yangutils/src/test/resources/EnumWithDuplicateName.yang b/utils/yangutils/src/test/resources/EnumWithDuplicateName.yang new file mode 100644 index 0000000000..d81558fc4c --- /dev/null +++ b/utils/yangutils/src/test/resources/EnumWithDuplicateName.yang @@ -0,0 +1,14 @@ +module Test { + yang-version 1; + namespace http://huawei.com; + prefix Ant; + leaf speed { + type enumeration { + enum 10m; + enum 100m; + enum 10m { + value 11; + } + } + } +} diff --git a/utils/yangutils/src/test/resources/PositionDuplication.yang b/utils/yangutils/src/test/resources/PositionDuplication.yang new file mode 100644 index 0000000000..81eeb16a49 --- /dev/null +++ b/utils/yangutils/src/test/resources/PositionDuplication.yang @@ -0,0 +1,18 @@ +module Test { + yang-version 1; + namespace http://huawei.com; + prefix Ant; + leaf mybits { + type bits { + bit disable-nagle { + position 0; + } + bit auto-sense-speed { + position 1; + } + bit Ten-Mb-only { + position 1; + } + } + } +} diff --git a/utils/yangutils/src/test/resources/PositionImplicitAndExplicit.yang b/utils/yangutils/src/test/resources/PositionImplicitAndExplicit.yang new file mode 100644 index 0000000000..5be4cbb5df --- /dev/null +++ b/utils/yangutils/src/test/resources/PositionImplicitAndExplicit.yang @@ -0,0 +1,15 @@ +module Test { + yang-version 1; + namespace http://huawei.com; + prefix Ant; + leaf mybits { + type bits { + bit disable-nagle; + bit auto-sense-speed { + position 1; + } + bit Ten-Mb-only; + } + } + } +} diff --git a/utils/yangutils/src/test/resources/PositionImplicitAndExplicitDuplication.yang b/utils/yangutils/src/test/resources/PositionImplicitAndExplicitDuplication.yang new file mode 100644 index 0000000000..30b81abcb6 --- /dev/null +++ b/utils/yangutils/src/test/resources/PositionImplicitAndExplicitDuplication.yang @@ -0,0 +1,15 @@ +module Test { + yang-version 1; + namespace http://huawei.com; + prefix Ant; + leaf mybits { + type bits { + bit disable-nagle; + bit auto-sense-speed { + position 0; + } + bit Ten-Mb-only; + } + } + } +} diff --git a/utils/yangutils/src/test/resources/PositionNegativeValue.yang b/utils/yangutils/src/test/resources/PositionNegativeValue.yang new file mode 100644 index 0000000000..60330e0e24 --- /dev/null +++ b/utils/yangutils/src/test/resources/PositionNegativeValue.yang @@ -0,0 +1,15 @@ +module Test { + yang-version 1; + namespace http://huawei.com; + prefix Ant; + leaf mybits { + type bits { + bit disable-nagle; + bit auto-sense-speed { + position -2; + } + bit Ten-Mb-only; + } + } + } +} diff --git a/utils/yangutils/src/test/resources/PositionStatement.yang b/utils/yangutils/src/test/resources/PositionStatement.yang new file mode 100644 index 0000000000..76c204d22a --- /dev/null +++ b/utils/yangutils/src/test/resources/PositionStatement.yang @@ -0,0 +1,18 @@ +module Test { + yang-version 1; + namespace http://huawei.com; + prefix Ant; + leaf mybits { + type bits { + bit disable-nagle { + position 0; + } + bit auto-sense-speed { + position 1; + } + bit Ten-Mb-only { + position 2; + } + } + } +}