X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Futil%2FParserListenerUtils.java;h=ff96d95d8294ed59d96218b65bb922fda2c3bada;hb=36368e8e6f9a791c355a7e61010a04e6a4f347d4;hp=51d7e3120b23bed689f06163b5db9f37f41d9d86;hpb=df1236c753c1e917b587686efb9251f83e49cfb2;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserListenerUtils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserListenerUtils.java index 51d7e3120b..ff96d95d82 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserListenerUtils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserListenerUtils.java @@ -7,6 +7,7 @@ */ package org.opendaylight.yangtools.yang.parser.util; +import java.math.BigDecimal; import java.net.URI; import java.util.ArrayList; import java.util.Collections; @@ -15,6 +16,7 @@ import java.util.List; import java.util.Stack; import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.TerminalNode; import org.opendaylight.yangtools.antlrv4.code.gen.*; import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Argument_stmtContext; import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Base_stmtContext; @@ -40,6 +42,7 @@ import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Max_elements_stmtC import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Max_value_argContext; import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Min_elements_stmtContext; import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Min_value_argContext; +import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Module_stmtContext; import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Must_stmtContext; import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Numerical_restrictionsContext; import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Ordered_by_argContext; @@ -112,7 +115,6 @@ import org.opendaylight.yangtools.yang.parser.builder.api.Builder; import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder; import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder; import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder; -import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceCaseBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.ConstraintsBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.UnionTypeBuilder; @@ -133,18 +135,52 @@ public final class ParserListenerUtils { * @return first string value from given tree */ public static String stringFromNode(final ParseTree treeNode) { - final String result = ""; + String result = ""; for (int i = 0; i < treeNode.getChildCount(); ++i) { if (treeNode.getChild(i) instanceof StringContext) { final StringContext context = (StringContext) treeNode.getChild(i); if (context != null) { - return context.getChild(0).getText().replace("\"", ""); + return stringFromStringContext(context,treeNode); + } } } return result; } + private static String stringFromStringContext(StringContext context, ParseTree treeNode) { + StringBuilder str = new StringBuilder(); + for (TerminalNode stringNode : context.STRING()) { + String result = stringNode.getText(); + if(!result.contains("\"")){ + str.append(result); + } else if (!(result.startsWith("\"")) && result.endsWith("\"")) { + LOG.error("Syntax error in module {} at line {}: missing '\"'.", getParentModule(treeNode), + context.getStart().getLine()); + } else { + str.append(result.replace("\"", "")); + } + } + return str.toString(); + } + + private static String getParentModule(final ParseTree ctx) { + ParseTree current = ctx; + while (current != null && !(current instanceof Module_stmtContext)) { + current = current.getParent(); + } + if (current instanceof Module_stmtContext) { + Module_stmtContext module = (Module_stmtContext) current; + for (int i = 0; i < module.getChildCount(); i++) { + if (module.getChild(i) instanceof StringContext) { + final StringContext str = (StringContext) module.getChild(i); + return str.getChild(0).getText(); + } + } + } + return ""; + } + /** * Parse 'description', 'reference' and 'status' statements and fill in * given builder. @@ -183,13 +219,17 @@ public final class ParserListenerUtils { ParseTree statusArg = ctx.getChild(i); if (statusArg instanceof Status_argContext) { String statusArgStr = stringFromNode(statusArg); - if ("current".equals(statusArgStr)) { + switch (statusArgStr) { + case "current": result = Status.CURRENT; - } else if ("deprecated".equals(statusArgStr)) { + break; + case "deprecated": result = Status.DEPRECATED; - } else if ("obsolete".equals(statusArgStr)) { + break; + case "obsolete": result = Status.OBSOLETE; - } else { + break; + default: LOG.warn("Invalid 'status' statement: " + statusArgStr); } } @@ -245,7 +285,7 @@ public final class ParserListenerUtils { * @return SchemaPath object */ public static SchemaPath createActualSchemaPath(final Stack actualPath) { - final List path = new ArrayList(actualPath); + final List path = new ArrayList<>(actualPath); return new SchemaPath(path, true); } @@ -265,10 +305,10 @@ public final class ParserListenerUtils { */ public static List createListKey(final String keyDefinition, final URI namespace, final Date revision, final String prefix) { - List key = new ArrayList(); + List key = new ArrayList<>(); String[] splittedKey = keyDefinition.split(" "); - QName qname = null; + QName qname; for (String keyElement : splittedKey) { if (keyElement.length() != 0) { qname = new QName(namespace, revision, prefix, keyElement); @@ -291,7 +331,7 @@ public final class ParserListenerUtils { */ private static List getEnumConstants(final Type_body_stmtsContext ctx, final Stack path, final String moduleName) { - List enumConstants = new ArrayList(); + List enumConstants = new ArrayList<>(); for (int i = 0; i < ctx.getChildCount(); i++) { ParseTree enumSpecChild = ctx.getChild(i); @@ -319,7 +359,7 @@ public final class ParserListenerUtils { * enum statement context * @param highestValue * current highest value in enumeration - * @param path + * @param actualPath * actual position in YANG model * @param moduleName * current module name @@ -495,12 +535,14 @@ public final class ParserListenerUtils { * @param ctx * type body context to parse * @param moduleName + * name of current module * @return List of RangeConstraint created from this context */ private static List getRangeConstraints(final Type_body_stmtsContext ctx, final String moduleName) { List rangeConstraints = Collections.emptyList(); outer: for (int i = 0; i < ctx.getChildCount(); i++) { ParseTree numRestrChild = ctx.getChild(i); + if (numRestrChild instanceof Numerical_restrictionsContext) { for (int j = 0; j < numRestrChild.getChildCount(); j++) { ParseTree rangeChild = numRestrChild.getChild(j); @@ -510,6 +552,22 @@ public final class ParserListenerUtils { } } } + + if (numRestrChild instanceof Decimal64_specificationContext) { + for (int j = 0; j < numRestrChild.getChildCount(); j++) { + ParseTree decRestr = numRestrChild.getChild(j); + if (decRestr instanceof Numerical_restrictionsContext) { + for (int k = 0; k < decRestr.getChildCount(); k++) { + ParseTree rangeChild = decRestr.getChild(k); + if (rangeChild instanceof Range_stmtContext) { + rangeConstraints = parseRangeConstraints((Range_stmtContext) rangeChild, moduleName); + break outer; + } + } + + } + } + } } return rangeConstraints; } @@ -520,11 +578,12 @@ public final class ParserListenerUtils { * @param ctx * range context to parse * @param moduleName + * name of current module * @return List of RangeConstraints parsed from this context */ private static List parseRangeConstraints(final Range_stmtContext ctx, final String moduleName) { final int line = ctx.getStart().getLine(); - List rangeConstraints = new ArrayList(); + List rangeConstraints = new ArrayList<>(); String description = null; String reference = null; @@ -563,6 +622,7 @@ public final class ParserListenerUtils { * @param ctx * type body context to parse * @param moduleName + * name of current module * @return List of LengthConstraint created from this context */ private static List getLengthConstraints(final Type_body_stmtsContext ctx, final String moduleName) { @@ -588,11 +648,12 @@ public final class ParserListenerUtils { * @param ctx * length context to parse * @param moduleName + * name of current module * @return List of LengthConstraints parsed from this context */ private static List parseLengthConstraints(final Length_stmtContext ctx, final String moduleName) { final int line = ctx.getStart().getLine(); - List lengthConstraints = new ArrayList(); + List lengthConstraints = new ArrayList<>(); String description = null; String reference = null; @@ -628,18 +689,24 @@ public final class ParserListenerUtils { /** * @param value * value to parse - * @param moduleName name of current module - * @param line current line in module + * @param moduleName + * name of current module + * @param line + * current line in module * @return wrapper object of primitive java type or UnknownBoundaryNumber if * type is one of special YANG values 'min' or 'max' */ private static Number parseNumberConstraintValue(final String value, final String moduleName, final int line) { - Number result = null; + Number result; if ("min".equals(value) || "max".equals(value)) { result = new UnknownBoundaryNumber(value); } else { try { - result = Long.valueOf(value); + if (value.contains(".")) { + result = new BigDecimal(value); + } else { + result = Long.valueOf(value); + } } catch (NumberFormatException e) { throw new YangParseException(moduleName, line, "Unable to parse range value '" + value + "'.", e); } @@ -655,7 +722,7 @@ public final class ParserListenerUtils { * @return list of pattern constraints */ private static List getPatternConstraint(final Type_body_stmtsContext ctx) { - List patterns = new ArrayList(); + List patterns = new ArrayList<>(); for (int i = 0; i < ctx.getChildCount(); i++) { ParseTree stringRestrChild = ctx.getChild(i); @@ -689,7 +756,7 @@ public final class ParserListenerUtils { reference = stringFromNode(child); } } - String pattern = patternStringFromNode(ctx); + String pattern = parsePatternString(ctx); return BaseConstraints.patternConstraint(pattern, description, reference); } @@ -700,7 +767,7 @@ public final class ParserListenerUtils { * context to parse * @return pattern value as String */ - public static String patternStringFromNode(final Pattern_stmtContext ctx) { + private static String parsePatternString(final Pattern_stmtContext ctx) { StringBuilder result = new StringBuilder(); for (int i = 0; i < ctx.getChildCount(); ++i) { ParseTree child = ctx.getChild(i); @@ -777,7 +844,7 @@ public final class ParserListenerUtils { */ private static List getBits(Type_body_stmtsContext ctx, Stack actualPath, String moduleName) { - final List bits = new ArrayList(); + final List bits = new ArrayList<>(); for (int j = 0; j < ctx.getChildCount(); j++) { ParseTree bitsSpecChild = ctx.getChild(j); if (bitsSpecChild instanceof Bits_specificationContext) { @@ -865,11 +932,14 @@ public final class ParserListenerUtils { ParseTree orderArg = ctx.getChild(j); if (orderArg instanceof Ordered_by_argContext) { String orderStr = stringFromNode(orderArg); - if ("system".equals(orderStr)) { + switch (orderStr) { + case "system": result = false; - } else if ("user".equals(orderStr)) { + break; + case "user": result = true; - } else { + break; + default: LOG.warn("Invalid 'ordered-by' statement."); } } @@ -892,7 +962,7 @@ public final class ParserListenerUtils { * @return config statement parsed from given context */ public static Boolean getConfig(final ParseTree ctx, final Builder parent, final String moduleName, final int line) { - Boolean result = null; + Boolean result; // parse configuration statement Boolean config = null; for (int i = 0; i < ctx.getChildCount(); i++) { @@ -911,18 +981,6 @@ public final class ParserListenerUtils { // If the parent node is a rpc input or output, it can has // config set to null result = parentConfig == null ? true : parentConfig; - } else if (parent instanceof ChoiceCaseBuilder) { - // If the parent node is a 'case' node, the value is the same as - // the 'case' node's parent 'choice' node - ChoiceCaseBuilder choiceCase = (ChoiceCaseBuilder) parent; - Builder choice = choiceCase.getParent(); - Boolean parentConfig = null; - if (choice instanceof ChoiceBuilder) { - parentConfig = ((ChoiceBuilder) choice).isConfiguration(); - } else { - parentConfig = true; - } - result = parentConfig; } else { result = true; } @@ -958,13 +1016,14 @@ public final class ParserListenerUtils { final ParseTree configContext = ctx.getChild(i); if (configContext instanceof Config_argContext) { final String value = stringFromNode(configContext); - if ("true".equals(value)) { + switch (value) { + case "true": result = true; break; - } else if ("false".equals(value)) { + case "false": result = false; break; - } else { + default: throw new YangParseException(moduleName, ctx.getStart().getLine(), "Failed to parse 'config' statement value: '" + value + "'."); } @@ -982,10 +1041,15 @@ public final class ParserListenerUtils { * @param ctx * type body * @param actualPath + * actual path in model * @param namespace + * module namespace * @param revision + * module revision * @param prefix + * module prefix * @param parent + * current node parent * @return UnknownType object with constraints from parsed type body */ public static TypeDefinition parseUnknownTypeWithBody(final QName typedefQName, @@ -1011,7 +1075,6 @@ public final class ParserListenerUtils { return unknownType.build(); } else { TypeDefinition baseType = unknownType.build(); - TypeDefinition result = null; QName qname = new QName(namespace, revision, prefix, typeName); SchemaPath schemaPath = createTypePath(actualPath, typeName); @@ -1020,9 +1083,8 @@ public final class ParserListenerUtils { typeBuilder.lengths(lengthStatements); typeBuilder.patterns(patternStatements); typeBuilder.fractionDigits(fractionDigits); - result = typeBuilder.build(); - return result; + return typeBuilder.build(); } } @@ -1076,49 +1138,63 @@ public final class ParserListenerUtils { if ("decimal64".equals(typeName)) { if (rangeStatements.isEmpty()) { - return new Decimal64(baseTypePath, fractionDigits); + try { + return new Decimal64(baseTypePath, fractionDigits); + } catch(Exception e) { + throw new YangParseException(moduleName, line, e.getMessage()); + } } Decimal64 decimalType = new Decimal64(extBaseTypePath, fractionDigits); - constraints.addRanges(decimalType.getRangeStatements()); + constraints.addRanges(decimalType.getRangeConstraints()); baseType = decimalType; } else if (typeName.startsWith("int")) { IntegerTypeDefinition intType = null; - if ("int8".equals(typeName)) { - intType = new Int8(extBaseTypePath); - } else if ("int16".equals(typeName)) { - intType = new Int16(extBaseTypePath); - } else if ("int32".equals(typeName)) { - intType = new Int32(extBaseTypePath); - } else if ("int64".equals(typeName)) { - intType = new Int64(extBaseTypePath); + switch (typeName) { + case "int8": + intType = Int8.getInstance(); + break; + case "int16": + intType = Int16.getInstance(); + break; + case "int32": + intType = Int32.getInstance(); + break; + case "int64": + intType = Int64.getInstance(); + break; } if (intType == null) { throw new YangParseException(moduleName, line, "Unknown yang type " + typeName); } - constraints.addRanges(intType.getRangeStatements()); + constraints.addRanges(intType.getRangeConstraints()); baseType = intType; } else if (typeName.startsWith("uint")) { UnsignedIntegerTypeDefinition uintType = null; - if ("uint8".equals(typeName)) { - uintType = new Uint8(extBaseTypePath); - } else if ("uint16".equals(typeName)) { - uintType = new Uint16(extBaseTypePath); - } else if ("uint32".equals(typeName)) { - uintType = new Uint32(extBaseTypePath); - } else if ("uint64".equals(typeName)) { - uintType = new Uint64(extBaseTypePath); + switch (typeName) { + case "uint8": + uintType = Uint8.getInstance(); + break; + case "uint16": + uintType = Uint16.getInstance(); + break; + case "uint32": + uintType = Uint32.getInstance(); + break; + case "uint64": + uintType = Uint64.getInstance(); + break; } if (uintType == null) { throw new YangParseException(moduleName, line, "Unknown yang type " + typeName); } - constraints.addRanges(uintType.getRangeStatements()); + constraints.addRanges(uintType.getRangeConstraints()); baseType = uintType; } else if ("enumeration".equals(typeName)) { List enumConstants = getEnumConstants(typeBody, actualPath, moduleName); return new EnumerationType(baseTypePath, enumConstants); } else if ("string".equals(typeName)) { - StringTypeDefinition stringType = new StringType(extBaseTypePath); - constraints.addLengths(stringType.getLengthStatements()); + StringTypeDefinition stringType = StringType.getInstance(); + constraints.addLengths(stringType.getLengthConstraints()); baseType = stringType; } else if ("bits".equals(typeName)) { return new BitsType(baseTypePath, getBits(typeBody, actualPath, moduleName)); @@ -1126,14 +1202,14 @@ public final class ParserListenerUtils { final String path = parseLeafrefPath(typeBody); final boolean absolute = path.startsWith("/"); RevisionAwareXPath xpath = new RevisionAwareXPathImpl(path, absolute); - return new Leafref(baseTypePath, xpath); + return new Leafref(xpath); } else if ("binary".equals(typeName)) { - BinaryTypeDefinition binaryType = new BinaryType(extBaseTypePath); + BinaryTypeDefinition binaryType = BinaryType.getInstance(); constraints.addLengths(binaryType.getLengthConstraints()); baseType = binaryType; } else if ("instance-identifier".equals(typeName)) { boolean requireInstance = isRequireInstance(typeBody); - return new InstanceIdentifier(extBaseTypePath, null, requireInstance); + return new InstanceIdentifier(null, requireInstance); } if (parent instanceof TypeDefinitionBuilder && !(parent instanceof UnionTypeBuilder)) { @@ -1145,35 +1221,31 @@ public final class ParserListenerUtils { return baseType; } - TypeDefinition result = null; - ExtendedType.Builder typeBuilder = null; - - List path = new ArrayList(actualPath); + List path = new ArrayList<>(actualPath); path.add(new QName(namespace, revision, prefix, typeName)); SchemaPath schemaPath = new SchemaPath(path, true); QName qname = schemaPath.getPath().get(schemaPath.getPath().size() - 1); - typeBuilder = new ExtendedType.Builder(qname, baseType, "", "", schemaPath); + ExtendedType.Builder typeBuilder = new ExtendedType.Builder(qname, baseType, "", "", schemaPath); typeBuilder.ranges(constraints.getRange()); typeBuilder.lengths(constraints.getLength()); typeBuilder.patterns(constraints.getPatterns()); typeBuilder.fractionDigits(constraints.getFractionDigits()); - result = typeBuilder.build(); - return result; + return typeBuilder.build(); } private static SchemaPath createTypePath(Stack actual, String typeName) { QName last = actual.peek(); QName typeQName = new QName(last.getNamespace(), last.getRevision(), last.getPrefix(), typeName); - List path = new ArrayList(actual); + List path = new ArrayList<>(actual); path.add(typeQName); return new SchemaPath(path, true); } private static SchemaPath createBaseTypePath(Stack actual, String typeName) { - List path = new ArrayList(actual); + List path = new ArrayList<>(actual); path.add(BaseTypes.constructQName(typeName)); return new SchemaPath(path, true); } @@ -1182,7 +1254,7 @@ public final class ParserListenerUtils { String prefix, String typeName) { QName extTypeName = new QName(namespace, revision, prefix, typeName); QName baseTypeName = BaseTypes.constructQName(typeName); - List path = new ArrayList(actual); + List path = new ArrayList<>(actual); path.add(extTypeName); path.add(baseTypeName); return new SchemaPath(path, true); @@ -1305,9 +1377,7 @@ public final class ParserListenerUtils { } } - MustDefinition must = new MustDefinitionImpl(mustText.toString(), description, reference, errorAppTag, - errorMessage); - return must; + return new MustDefinitionImpl(mustText.toString(), description, reference, errorAppTag, errorMessage); } /** @@ -1420,20 +1490,20 @@ public final class ParserListenerUtils { * if this is one of YANG type which MUST contain additional * informations in its body */ - public static void checkMissingBody(final String typeName, final String moduleName, final int line) - throws YangParseException { - if ("decimal64".equals(typeName)) { + public static void checkMissingBody(final String typeName, final String moduleName, final int line) { + switch (typeName) { + case "decimal64": throw new YangParseException(moduleName, line, "The 'fraction-digits' statement MUST be present if the type is 'decimal64'."); - } else if ("identityref".equals(typeName)) { + case "identityref": throw new YangParseException(moduleName, line, "The 'base' statement MUST be present if the type is 'identityref'."); - } else if ("leafref".equals(typeName)) { + case "leafref": throw new YangParseException(moduleName, line, "The 'path' statement MUST be present if the type is 'leafref'."); - } else if ("bits".equals(typeName)) { + case "bits": throw new YangParseException(moduleName, line, "The 'bit' statement MUST be present if the type is 'bits'."); - } else if ("enumeration".equals(typeName)) { + case "enumeration": throw new YangParseException(moduleName, line, "The 'enum' statement MUST be present if the type is 'enumeration'."); } @@ -1444,7 +1514,8 @@ public final class ParserListenerUtils { * * @param refineCtx * refine statement - * @param moduleName name of current module + * @param moduleName + * name of current module * @return RefineHolder object representing this refine statement */ public static RefineHolder parseRefine(Refine_stmtContext refineCtx, String moduleName) {