raml-org / raml-java-parser

(deprecated) A RAML parser based on SnakeYAML written in Java
Other
174 stars 121 forks source link

Interger as name of `Type` produces a `ClassCastException` during parsing #679

Open pierCo opened 4 years ago

pierCo commented 4 years ago

When I attempt to parse a RAML definition that contains a type where its name is an Integer it failed. A ClassCastException is thrown.

I try to fix that by patch the source code of TypeDeclaration.java. It works but after a few search in the source code this error could be produced at many places.

So my question is more: is it allowed to use Integer as key of a type (or another resource)? And if not, how to handle this error more cleanly? For example, to indicate that the RAML definition is invalid.

Attempt to fix the issue

I try to fix that by patch the source code of TypeDeclaration.java as below:

    public String name()
    {
        if (node instanceof PropertyNode)
        {
            return ((PropertyNode) node).getName();
        }
        // Code that produces the ClassCastException
        // String keyValue = ((StringNode) node.getKey()).getValue();
        String keyValue = getValueAsString(node)
        Node parentTypeNode = node.getValue();
        if (node.getParent() instanceof TypeDeclarationNode && parentTypeNode instanceof TypeExpressionNode)
        {
            // getting name of parent type
            if (parentTypeNode instanceof ExternalSchemaTypeExpressionNode)
            {
                return null;
            }
            return ((TypeExpressionNode) parentTypeNode).getTypeExpressionText();
        }
        return keyValue;
    }

    // COPY PASTE OF the class PropertyUtils.java
    private static String getValueAsString(KeyValueNode node)
    {
        final String keyValue;
        if (node.getKey() instanceof IntegerNode)
        {
            keyValue = String.valueOf(((IntegerNode) node.getKey()).getValue());
        }
        else
        {
            StringNode key = (StringNode) node.getKey();
            keyValue = key.getValue();
        }
        return keyValue;
    }

Error information

RAML Content

#%RAML 1.0
title: "Tasks API"
version: "1.1.0"
types:
  125:
    type: "object"
    description: "An object"
    properties:
      id:
        type: "string"
/tasks:
  get:
    body:
      application/json:
        type: "125"

Error stack trace

Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.raml.yagi.framework.model.ModelProxyBuilder$SimpleProxy.fromMethod(ModelProxyBuilder.java:98)
    at org.raml.yagi.framework.model.ModelProxyBuilder$SimpleProxy.invoke(ModelProxyBuilder.java:74)
    ... 38 more
Caused by: java.lang.ClassCastException: class org.raml.yagi.framework.nodes.snakeyaml.SYIntegerNode cannot be cast to class org.raml.yagi.framework.nodes.StringNode (org.raml.yagi.framework.nodes.snakeyaml.SYIntegerNode and org.raml.yagi.framework.nodes.StringNode are in unnamed module of loader 'app')
    at org.raml.v2.internal.impl.commons.model.type.TypeDeclaration.name(TypeDeclaration.java:99)
    ... 44 more
jstoiko commented 4 years ago

This seems related to the way the underlying YAML parser handles keys in general. See this issue. Feel free to submit a PR with a few test cases if this is something you really need to be addressed.

Otherwise, note that this parser is deprecated in favor of webapi-parser, which should behave as expected.