Search in sources :

Example 1 with AnnotationParserException

use of org.infinispan.protostream.AnnotationParserException in project protostream by infinispan.

the class AnnotatedDescriptorImpl method validateAttributes.

private void validateAttributes(AnnotationElement.Annotation annotation, AnnotationConfiguration annotationConfig) {
    for (Map.Entry<String, AnnotationElement.Attribute> entry : annotation.getAttributes().entrySet()) {
        AnnotationElement.Attribute attribute = entry.getValue();
        final AnnotationAttributeConfiguration attributeConfig = annotationConfig.attributes().get(attribute.getName());
        if (attributeConfig == null) {
            throw new AnnotationParserException("Unexpected attribute '" + attribute.getName() + "' in annotation '" + annotation.getName() + "' on " + getFullName());
        }
        AnnotationElement.Value value = attribute.getValue();
        if (!attributeConfig.multiple() && value instanceof AnnotationElement.Array) {
            throw new AnnotationParserException("Annotation attribute '" + attribute.getName() + "' in annotation '" + annotation.getName() + "' on " + getFullName() + " does not accept array values");
        }
        if (value instanceof AnnotationElement.Array) {
            for (AnnotationElement.Value v : ((AnnotationElement.Array) value).getValues()) {
                validateAttribute(annotation, attribute, attributeConfig, v);
            }
        } else {
            validateAttribute(annotation, attribute, attributeConfig, value);
        }
    }
}
Also used : AnnotationElement(org.infinispan.protostream.descriptors.AnnotationElement) AnnotationAttributeConfiguration(org.infinispan.protostream.config.AnnotationAttributeConfiguration) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) AnnotationParserException(org.infinispan.protostream.AnnotationParserException)

Example 2 with AnnotationParserException

use of org.infinispan.protostream.AnnotationParserException in project protostream by infinispan.

the class AnnotatedDescriptorImpl method processAnnotations.

/**
 * Extract annotations by parsing the documentation comment and run the configured {@link
 * AnnotationMetadataCreator}s.
 *
 * @throws AnnotationParserException if annotation parsing fails
 */
private void processAnnotations() throws AnnotationParserException {
    // we are lazily processing the annotations, if there is a documentation text attached to this element
    if (annotations == null) {
        if (documentation != null) {
            AnnotationParser parser = new AnnotationParser(documentation, true);
            List<AnnotationElement.Annotation> parsedAnnotations = parser.parse();
            Map<String, AnnotationElement.Annotation> _annotations = new LinkedHashMap<>();
            Map<String, AnnotationElement.Annotation> _containers = new LinkedHashMap<>();
            for (AnnotationElement.Annotation annotation : parsedAnnotations) {
                AnnotationConfiguration annotationConfig = getAnnotationConfig(annotation);
                if (annotationConfig == null) {
                    // unknown annotations are ignored, but we might want to log a warning
                    if (getAnnotationsConfig().logUndefinedAnnotations()) {
                        log.warnf("Encountered and ignored and unknown annotation \"%s\" on %s", annotation.getName(), fullName);
                    }
                } else {
                    validateAttributes(annotation, annotationConfig);
                    // convert single values to arrays if needed and set the default values for missing attributes
                    normalizeValues(annotation, annotationConfig);
                    if (_annotations.containsKey(annotation.getName()) || _containers.containsKey(annotation.getName())) {
                        // did we just find a repeatable annotation?
                        if (annotationConfig.repeatable() != null) {
                            AnnotationElement.Annotation container = _containers.get(annotation.getName());
                            if (container == null) {
                                List<AnnotationElement.Value> values = new LinkedList<>();
                                values.add(_annotations.remove(annotation.getName()));
                                values.add(annotation);
                                AnnotationElement.Attribute value = new AnnotationElement.Attribute(annotation.position, AnnotationElement.Annotation.VALUE_DEFAULT_ATTRIBUTE, new AnnotationElement.Array(annotation.position, values));
                                container = new AnnotationElement.Annotation(annotation.position, annotationConfig.repeatable(), Collections.singletonMap(value.getName(), value));
                                _containers.put(annotation.getName(), container);
                                _annotations.put(container.getName(), container);
                            } else {
                                AnnotationElement.Array value = (AnnotationElement.Array) container.getAttributeValue(AnnotationElement.Annotation.VALUE_DEFAULT_ATTRIBUTE);
                                value.getValues().add(annotation);
                            }
                        } else {
                            // it's just a duplicate, not a proper 'repeated' annotation
                            throw new AnnotationParserException(String.format("Error: %s: duplicate annotation definition \"%s\" on %s", AnnotationElement.positionToString(annotation.position), annotation.getName(), fullName));
                        }
                    } else {
                        _annotations.put(annotation.getName(), annotation);
                    }
                }
            }
            // annotations are now completely parsed and validated
            annotations = _annotations.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(_annotations);
            // create metadata based on the annotations
            processedAnnotations = new LinkedHashMap<>();
            for (AnnotationElement.Annotation annotation : annotations.values()) {
                AnnotationConfiguration annotationConfig = getAnnotationConfig(annotation);
                AnnotationMetadataCreator<Object, AnnotatedDescriptor> creator = (AnnotationMetadataCreator<Object, AnnotatedDescriptor>) annotationConfig.metadataCreator();
                if (creator != null) {
                    Object metadataForAnnotation;
                    try {
                        metadataForAnnotation = creator.create(this, annotation);
                    } catch (Exception ex) {
                        log.errorf(ex, "Exception encountered while processing annotation \"%s\" on %s", annotation.getName(), fullName);
                        throw ex;
                    }
                    processedAnnotations.put(annotation.getName(), metadataForAnnotation);
                }
            }
        } else {
            annotations = Collections.emptyMap();
            processedAnnotations = Collections.emptyMap();
        }
    }
}
Also used : AnnotationMetadataCreator(org.infinispan.protostream.AnnotationMetadataCreator) AnnotationParser(org.infinispan.protostream.impl.parser.AnnotationParser) AnnotatedDescriptor(org.infinispan.protostream.descriptors.AnnotatedDescriptor) AnnotationParserException(org.infinispan.protostream.AnnotationParserException) LinkedList(java.util.LinkedList) DescriptorParserException(org.infinispan.protostream.DescriptorParserException) AnnotationParserException(org.infinispan.protostream.AnnotationParserException) LinkedHashMap(java.util.LinkedHashMap) AnnotationElement(org.infinispan.protostream.descriptors.AnnotationElement) AnnotationConfiguration(org.infinispan.protostream.config.AnnotationConfiguration)

Example 3 with AnnotationParserException

use of org.infinispan.protostream.AnnotationParserException in project protostream by infinispan.

the class AnnotationLexer method nextToken.

public void nextToken() {
    lastPos = AnnotationElement.makePosition(line, col);
    sb.setLength(0);
    while (true) {
        pos = AnnotationElement.makePosition(line, col);
        switch(ch) {
            case ',':
                scanNextChar();
                token = AnnotationTokens.COMMA;
                return;
            case '(':
                scanNextChar();
                token = AnnotationTokens.LPAREN;
                return;
            case ')':
                scanNextChar();
                token = AnnotationTokens.RPAREN;
                return;
            case '{':
                scanNextChar();
                token = AnnotationTokens.LBRACE;
                return;
            case '}':
                scanNextChar();
                token = AnnotationTokens.RBRACE;
                return;
            case '@':
                scanNextChar();
                token = AnnotationTokens.AT;
                return;
            case '=':
                scanNextChar();
                token = AnnotationTokens.EQ;
                return;
            case '.':
                scanNextChar();
                if ('0' <= ch && ch <= '9') {
                    sb.append('.');
                    scanDecimal();
                } else {
                    token = AnnotationTokens.DOT;
                }
                return;
            case '_':
            case '$':
            case 'A':
            case 'B':
            case 'C':
            case 'D':
            case 'E':
            case 'F':
            case 'G':
            case 'H':
            case 'I':
            case 'J':
            case 'K':
            case 'L':
            case 'M':
            case 'N':
            case 'O':
            case 'P':
            case 'Q':
            case 'R':
            case 'S':
            case 'T':
            case 'U':
            case 'V':
            case 'W':
            case 'X':
            case 'Y':
            case 'Z':
            case 'a':
            case 'b':
            case 'c':
            case 'd':
            case 'e':
            case 'f':
            case 'g':
            case 'h':
            case 'i':
            case 'j':
            case 'k':
            case 'l':
            case 'm':
            case 'n':
            case 'o':
            case 'p':
            case 'q':
            case 'r':
            case 's':
            case 't':
            case 'u':
            case 'v':
            case 'w':
            case 'x':
            case 'y':
            case 'z':
                scanIdentifier();
                return;
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                scanNumber();
                return;
            case '\'':
                scanNextChar();
                if (ch == '\'') {
                    throw new AnnotationParserException(String.format("Error: %s: empty character literal", AnnotationElement.positionToString(pos)));
                } else {
                    if (ch == '\r' || ch == '\n') {
                        throw new AnnotationParserException(String.format("Error: %s: illegal line end in character literal", AnnotationElement.positionToString(pos)));
                    }
                    scanLiteralChar();
                    if (ch == '\'') {
                        scanNextChar();
                        token = AnnotationTokens.CHARACTER_LITERAL;
                    } else {
                        throw new AnnotationParserException(String.format("Error: %s: unclosed character literal", AnnotationElement.positionToString(pos)));
                    }
                }
                return;
            case '"':
                scanNextChar();
                while (ch != '"' && ch != '\r' && ch != '\n' && inputPos < input.length) {
                    scanLiteralChar();
                }
                if (ch == '"') {
                    token = AnnotationTokens.STRING_LITERAL;
                    scanNextChar();
                } else {
                    throw new AnnotationParserException(String.format("Error: %s: unclosed string literal", AnnotationElement.positionToString(pos)));
                }
                return;
            case ' ':
            case '\t':
                scanNextChar();
                continue;
            case '\f':
                col = 0;
                leadingWhitespace = true;
                scanNextChar();
                continue;
            case '\r':
                line++;
                col = 0;
                leadingWhitespace = true;
                scanNextChar();
                if (ch == '\n') {
                    col = 0;
                    leadingWhitespace = true;
                    scanNextChar();
                }
                continue;
            case '\n':
                line++;
                col = 0;
                leadingWhitespace = true;
                scanNextChar();
                continue;
            default:
                if (ch == '\0' && inputPos == input.length) {
                    token = AnnotationTokens.EOF;
                } else if (Character.isJavaIdentifierStart(ch)) {
                    scanIdentifier();
                } else {
                    throw new AnnotationParserException(String.format("Error: %s: illegal character: %c", AnnotationElement.positionToString(pos), ch));
                }
                return;
        }
    }
}
Also used : AnnotationParserException(org.infinispan.protostream.AnnotationParserException)

Example 4 with AnnotationParserException

use of org.infinispan.protostream.AnnotationParserException in project protostream by infinispan.

the class AnnotationParser method parseValue.

private AnnotationElement.Value parseValue(int start) {
    long pos = lexer.pos;
    switch(lexer.token) {
        case AT:
            return parseAnnotation();
        case LBRACE:
            return parseArray();
        case IDENTIFIER:
            return parseIdentifier();
        case INT_LITERAL:
        case LONG_LITERAL:
        case FLOAT_LITERAL:
        case DOUBLE_LITERAL:
        case CHARACTER_LITERAL:
        case STRING_LITERAL:
        case TRUE:
        case FALSE:
            AnnotationTokens tok = lexer.token;
            String text = lexer.getText(start, lexer.getBufferPos());
            Object value = null;
            try {
                switch(tok) {
                    case INT_LITERAL:
                        value = Integer.parseInt(text.trim());
                        break;
                    case LONG_LITERAL:
                        value = Long.parseLong(text.trim());
                        break;
                    case FLOAT_LITERAL:
                        value = Float.parseFloat(text.trim());
                        break;
                    case DOUBLE_LITERAL:
                        value = Double.parseDouble(text.trim());
                        break;
                    case CHARACTER_LITERAL:
                        value = text.charAt(1);
                        break;
                    case STRING_LITERAL:
                        {
                            value = text.substring(text.indexOf("\"") + 1, text.length() - 1);
                            break;
                        }
                    case TRUE:
                        value = Boolean.TRUE;
                        break;
                    case FALSE:
                        value = Boolean.FALSE;
                        break;
                }
            } catch (NumberFormatException e) {
                throw new AnnotationParserException(String.format("Error: %s: invalid numeric value: %s", AnnotationElement.positionToString(lexer.pos), e.getMessage()));
            }
            AnnotationElement.Literal literal = new AnnotationElement.Literal(pos, value);
            lexer.nextToken();
            return literal;
    }
    throw new AnnotationParserException(String.format("Error: %s: literal expected", AnnotationElement.positionToString(lexer.pos)));
}
Also used : AnnotationElement(org.infinispan.protostream.descriptors.AnnotationElement) AnnotationParserException(org.infinispan.protostream.AnnotationParserException)

Example 5 with AnnotationParserException

use of org.infinispan.protostream.AnnotationParserException in project protostream by infinispan.

the class AnnotatedDescriptorImpl method normalizeValues.

private void normalizeValues(AnnotationElement.Annotation annotation, AnnotationConfiguration annotationConfig) {
    for (AnnotationAttributeConfiguration attributeConfig : annotationConfig.attributes().values()) {
        AnnotationElement.Attribute attribute = annotation.getAttributes().get(attributeConfig.name());
        if (attribute != null) {
            AnnotationElement.Value value = attribute.getValue();
            if (attributeConfig.multiple() && !(value instanceof AnnotationElement.Array)) {
                // a single value will be automatically wrapped in an array node if the attribute was defined as 'multiple'
                value = new AnnotationElement.Array(value.position, Collections.singletonList(value));
                attribute = new AnnotationElement.Attribute(attribute.position, attributeConfig.name(), value);
                annotation.getAttributes().put(attributeConfig.name(), attribute);
            }
        } else if (attributeConfig.defaultValue() != null) {
            AnnotationElement.Value value = attributeConfig.type() == AnnotationElement.AttributeType.IDENTIFIER ? new AnnotationElement.Identifier(AnnotationElement.UNKNOWN_POSITION, (String) attributeConfig.defaultValue()) : new AnnotationElement.Literal(AnnotationElement.UNKNOWN_POSITION, attributeConfig.defaultValue());
            if (attributeConfig.multiple()) {
                value = new AnnotationElement.Array(value.position, Collections.singletonList(value));
            }
            attribute = new AnnotationElement.Attribute(AnnotationElement.UNKNOWN_POSITION, attributeConfig.name(), value);
            annotation.getAttributes().put(attributeConfig.name(), attribute);
        } else {
            throw new AnnotationParserException("Attribute '" + attributeConfig.name() + "' of annotation '" + annotation.getName() + "' on " + getFullName() + " is required");
        }
    }
}
Also used : AnnotationElement(org.infinispan.protostream.descriptors.AnnotationElement) AnnotationAttributeConfiguration(org.infinispan.protostream.config.AnnotationAttributeConfiguration) AnnotationParserException(org.infinispan.protostream.AnnotationParserException)

Aggregations

AnnotationParserException (org.infinispan.protostream.AnnotationParserException)5 AnnotationElement (org.infinispan.protostream.descriptors.AnnotationElement)4 LinkedHashMap (java.util.LinkedHashMap)2 AnnotationAttributeConfiguration (org.infinispan.protostream.config.AnnotationAttributeConfiguration)2 LinkedList (java.util.LinkedList)1 Map (java.util.Map)1 AnnotationMetadataCreator (org.infinispan.protostream.AnnotationMetadataCreator)1 DescriptorParserException (org.infinispan.protostream.DescriptorParserException)1 AnnotationConfiguration (org.infinispan.protostream.config.AnnotationConfiguration)1 AnnotatedDescriptor (org.infinispan.protostream.descriptors.AnnotatedDescriptor)1 AnnotationParser (org.infinispan.protostream.impl.parser.AnnotationParser)1