Search in sources :

Example 1 with ProtoSchemaBuilderException

use of org.infinispan.protostream.annotations.ProtoSchemaBuilderException in project protostream by infinispan.

the class AbstractMarshallerCodeGenerator method generateReadMethodBody.

/**
 * Signature of generated method is:
 * <code>
 * public java.lang.Object read(org.infinispan.protostream.ProtoStreamMarshaller.ReadContext $1,
 * java.lang.Object $2) throws java.io.IOException
 * </code>
 */
protected String generateReadMethodBody(ProtoMessageTypeMetadata messageTypeMetadata) {
    // todo [anistor] handle unknown fields for adapters also
    String getUnknownFieldSetFieldStatement = null;
    String setUnknownFieldSetFieldStatement = null;
    if (messageTypeMetadata.getUnknownFieldSetField() != null) {
        getUnknownFieldSetFieldStatement = "o." + messageTypeMetadata.getUnknownFieldSetField().getName();
        setUnknownFieldSetFieldStatement = "o." + messageTypeMetadata.getUnknownFieldSetField().getName() + " = u";
    } else if (messageTypeMetadata.getUnknownFieldSetGetter() != null) {
        getUnknownFieldSetFieldStatement = "o." + messageTypeMetadata.getUnknownFieldSetGetter().getName() + "()";
        setUnknownFieldSetFieldStatement = "o." + messageTypeMetadata.getUnknownFieldSetSetter().getName() + "(u)";
    } else if (messageTypeMetadata.getJavaClass().isAssignableTo(Message.class)) {
        getUnknownFieldSetFieldStatement = "o.getUnknownFieldSet()";
        setUnknownFieldSetFieldStatement = "o.setUnknownFieldSet(u)";
    }
    IndentWriter iw = new IndentWriter();
    iw.append("{\n");
    iw.inc();
    iw.append("final ").append(TagReader.class.getName()).append(" $in = $1.getReader();\n");
    if (messageTypeMetadata.isContainer()) {
        iw.append("Object __v$sizeParam = $1.getParam(\"" + WrappedMessage.CONTAINER_SIZE_CONTEXT_PARAM + "\");\n");
        iw.append("int __v$size = ((java.lang.Integer) __v$sizeParam).intValue();\n");
    }
    // if there is no factory then the class must have setters or the fields should be directly accessible and not be final
    final boolean noFactory = messageTypeMetadata.getFactory() == null;
    if (noFactory) {
        iw.append("final ").append(messageTypeMetadata.getJavaClassName()).append(" o = new ").append(messageTypeMetadata.getJavaClassName()).append("();\n");
    }
    // number of fields that are required and do not have a default value
    int mandatoryFields = 0;
    // fields that should be tracked for presence and be either initialized with defaults if missing at the end
    // or an exception thrown if no default exists
    Map<String, Integer> trackedFields = new LinkedHashMap<>();
    // First pass over fields. Count how many are mandatory and how many need to be tracked for presence.
    for (ProtoFieldMetadata fieldMetadata : messageTypeMetadata.getFields().values()) {
        if (fieldMetadata.isRequired() && fieldMetadata.getDefaultValue() == null) {
            mandatoryFields++;
        }
        if (fieldMetadata.isRequired() || fieldMetadata.getDefaultValue() != null && (noFactory || fieldMetadata.isRepeated() || fieldMetadata.getProtobufType() == Type.BYTES)) {
            int trackedFieldsSize = trackedFields.size();
            if (trackedFieldsSize % 64 == 0) {
                // declare a long variable to emulate a bitset in multiple long variables
                iw.append("long __bits$").append(String.valueOf(trackedFieldsSize >> 6)).append(" = 0;\n");
            }
            trackedFields.put(fieldMetadata.getName(), trackedFieldsSize);
        }
    }
    for (ProtoFieldMetadata fieldMetadata : messageTypeMetadata.getFields().values()) {
        if (fieldMetadata.isRepeated()) {
            // a collection local variable
            iw.append(fieldMetadata.getCollectionImplementation().getCanonicalName()).append(' ').append(makeCollectionLocalVar(fieldMetadata)).append(" = ");
            if (noDefaults || fieldMetadata.isArray()) {
                iw.append("null");
            } else {
                iw.append("new ").append(fieldMetadata.getCollectionImplementation().getCanonicalName()).append("()");
            }
            iw.append(";\n");
            if (!noFactory && fieldMetadata.isArray()) {
                // an array local variable
                iw.append(fieldMetadata.getJavaTypeName()).append("[] ").append(makeArrayLocalVar(fieldMetadata)).append(" = ");
                if (noDefaults) {
                    iw.append("null");
                } else {
                    iw.append("new ").append(fieldMetadata.getJavaTypeName()).append("[0]");
                }
                iw.append(";\n");
            }
        } else if (!noFactory) {
            // immutable messages need a per-field local variable initialized to default value if any
            iw.append(fieldMetadata.getJavaTypeName()).append(' ').append(makeFieldLocalVar(fieldMetadata));
            Object defaultValue = fieldMetadata.getDefaultValue();
            if (defaultValue != null && fieldMetadata.getProtobufType() != Type.BYTES) {
                // fields of type bytes get assigned default values only at the end to avoid a possibly useless byte[] allocation
                String val = toJavaLiteral(defaultValue, fieldMetadata.getJavaType());
                iw.append(" = ").append(box(val, fieldMetadata.getJavaType()));
            } else {
                if (fieldMetadata.isBoxedPrimitive() || fieldMetadata.getProtobufType() == Type.BYTES || fieldMetadata.getProtobufType().getJavaType() == JavaType.STRING || fieldMetadata.getProtobufType().getJavaType() == JavaType.BYTE_STRING || fieldMetadata.getProtobufType().getJavaType() == JavaType.ENUM || fieldMetadata.getProtobufType().getJavaType() == JavaType.MESSAGE || fieldMetadata.getJavaType().getCanonicalName().equals(Date.class.getCanonicalName()) || fieldMetadata.getJavaType().getCanonicalName().equals(Instant.class.getCanonicalName())) {
                    iw.append(" = null");
                } else if (fieldMetadata.isPrimitive()) {
                    if (fieldMetadata.getProtobufType() == Type.BOOL) {
                        iw.append(" = false");
                    } else {
                        iw.append(" = 0");
                    }
                }
            }
            iw.append(";\n");
        }
    }
    iw.append("boolean done = false;\n");
    iw.append("while (!done) {\n");
    iw.inc();
    iw.append("final int tag = $in.readTag();\n");
    iw.append("switch (tag) {\n");
    iw.inc();
    iw.append("case 0: {\n");
    iw.inc();
    iw.append("done = true;\nbreak;\n");
    iw.dec();
    iw.append("}\n");
    for (ProtoFieldMetadata fieldMetadata : messageTypeMetadata.getFields().values()) {
        final String v = makeFieldLocalVar(fieldMetadata);
        iw.append("case ").append(makeFieldTag(fieldMetadata.getNumber(), fieldMetadata.getProtobufType().getWireType())).append(": {\n");
        iw.inc();
        if (BaseProtoSchemaGenerator.generateMarshallerDebugComments) {
            iw.append("// type = ").append(fieldMetadata.getProtobufType().toString()).append(", name = ").append(fieldMetadata.getName()).append('\n');
        }
        switch(fieldMetadata.getProtobufType()) {
            case DOUBLE:
            case FLOAT:
            case INT64:
            case UINT64:
            case INT32:
            case FIXED64:
            case FIXED32:
            case BOOL:
            case STRING:
            case BYTES:
            case UINT32:
            case SFIXED32:
            case SFIXED64:
            case SINT32:
            case SINT64:
                {
                    if (noFactory || fieldMetadata.isRepeated()) {
                        iw.append(fieldMetadata.getJavaTypeName()).append(' ');
                    }
                    iw.append(v).append(" = ").append(box(convert("$in." + makeStreamIOMethodName(fieldMetadata, false) + "()", fieldMetadata), fieldMetadata.getJavaType())).append(";\n");
                    genSetField(iw, fieldMetadata, trackedFields, messageTypeMetadata);
                    break;
                }
            case GROUP:
                {
                    String mdField = initMarshallerDelegateField(iw, fieldMetadata);
                    if (noFactory || fieldMetadata.isRepeated()) {
                        iw.append(fieldMetadata.getJavaTypeName()).append(' ');
                    }
                    iw.append(v).append(" = (").append(fieldMetadata.getJavaTypeName()).append(") readMessage(").append(mdField).append(", $1);\n");
                    iw.append("$in.checkLastTagWas(").append(makeFieldTag(fieldMetadata.getNumber(), WireType.END_GROUP)).append(");\n");
                    genSetField(iw, fieldMetadata, trackedFields, messageTypeMetadata);
                    break;
                }
            case MESSAGE:
                {
                    String mdField = initMarshallerDelegateField(iw, fieldMetadata);
                    iw.append("int length = $in.readUInt32();\n");
                    iw.append("int oldLimit = $in.pushLimit(length);\n");
                    if (noFactory || fieldMetadata.isRepeated()) {
                        iw.append(fieldMetadata.getJavaTypeName()).append(' ');
                    }
                    iw.append(v).append(" = (").append(fieldMetadata.getJavaTypeName()).append(") readMessage(").append(mdField).append(", $1);\n");
                    iw.append("$in.checkLastTagWas(0);\n");
                    iw.append("$in.popLimit(oldLimit);\n");
                    genSetField(iw, fieldMetadata, trackedFields, messageTypeMetadata);
                    break;
                }
            case ENUM:
                {
                    String mdField = initMarshallerDelegateField(iw, fieldMetadata);
                    iw.append("int enumVal = $in.readEnum();\n");
                    if (noFactory || fieldMetadata.isRepeated()) {
                        iw.append(fieldMetadata.getJavaTypeName()).append(' ');
                    }
                    iw.append(v).append(" = (").append(fieldMetadata.getJavaTypeName()).append(") ").append(mdField).append(".getMarshaller().decode(enumVal);\n");
                    iw.append("if (").append(v).append(" == null) {\n");
                    if (getUnknownFieldSetFieldStatement != null) {
                        iw.inc();
                        iw.append(PROTOSTREAM_PACKAGE).append(".UnknownFieldSet u = ").append(getUnknownFieldSetFieldStatement).append(";\n");
                        iw.append("if (u == null) { u = new ").append(PROTOSTREAM_PACKAGE).append(".impl.UnknownFieldSetImpl(); ").append(setUnknownFieldSetFieldStatement).append("; }\n");
                        iw.append("u.putVarintField(").append(String.valueOf(fieldMetadata.getNumber())).append(", enumVal);\n");
                        iw.dec();
                    }
                    iw.append("} else {\n").inc();
                    genSetField(iw, fieldMetadata, trackedFields, messageTypeMetadata);
                    iw.dec().append("}\n");
                    break;
                }
            default:
                throw new IllegalStateException("Unknown field type : " + fieldMetadata.getProtobufType());
        }
        iw.append("break;\n");
        iw.dec();
        iw.append("}\n");
    }
    iw.append("default: {\n");
    iw.inc();
    if (getUnknownFieldSetFieldStatement != null) {
        iw.append(PROTOSTREAM_PACKAGE).append(".UnknownFieldSet u = ").append(getUnknownFieldSetFieldStatement).append(";\n");
        iw.append("if (u == null) u = new ").append(PROTOSTREAM_PACKAGE).append(".impl.UnknownFieldSetImpl();\n");
        iw.append("if (!u.readSingleField(tag, $in)) done = true;\n");
        iw.append("if (!u.isEmpty()) ").append(setUnknownFieldSetFieldStatement).append(";\n");
    } else {
        iw.append("if (!$in.skipField(tag)) done = true;\n");
    }
    iw.dec().append("}\n");
    iw.dec().append("}\n");
    iw.dec().append("}\n");
    // assign defaults to missing fields
    if (BaseProtoSchemaGenerator.generateMarshallerDebugComments) {
        iw.append("\n// default values\n\n");
    }
    for (ProtoFieldMetadata fieldMetadata : messageTypeMetadata.getFields().values()) {
        Object defaultValue = fieldMetadata.getDefaultValue();
        if (defaultValue != null && (noFactory || fieldMetadata.isRepeated() || fieldMetadata.getProtobufType() == Type.BYTES)) {
            iw.append("if ").append(makeTestFieldWasNotSet(fieldMetadata, trackedFields)).append(" {\n");
            iw.inc();
            String val = toJavaLiteral(defaultValue, fieldMetadata.getJavaType());
            if (fieldMetadata.isRepeated()) {
                String c = makeCollectionLocalVar(fieldMetadata);
                if (noDefaults || fieldMetadata.isArray()) {
                    iw.append("if (").append(c).append(" == null) ").append(c).append(" = new ").append(fieldMetadata.getCollectionImplementation().getCanonicalName()).append("();\n");
                }
                iw.append(c).append(".add(").append(box(val, typeFactory.fromClass(defaultValue.getClass()))).append(");\n");
            } else {
                if (noFactory) {
                    iw.append(createSetPropExpr(messageTypeMetadata, fieldMetadata, "o", box(val, fieldMetadata.getJavaType()))).append(";\n");
                } else {
                    iw.append(makeFieldLocalVar(fieldMetadata)).append(" = ").append(box(val, fieldMetadata.getJavaType())).append(";\n");
                }
            }
            iw.dec();
            iw.append("}\n");
        }
    }
    for (ProtoFieldMetadata fieldMetadata : messageTypeMetadata.getFields().values()) {
        if (fieldMetadata.isRepeated()) {
            String c = makeCollectionLocalVar(fieldMetadata);
            if (fieldMetadata.isArray()) {
                if (fieldMetadata.getDefaultValue() == null) {
                    iw.append("if (").append(c).append(" != null) ");
                }
                iw.append("{\n").inc();
                String a = makeArrayLocalVar(fieldMetadata);
                if (fieldMetadata.getJavaType().isPrimitive()) {
                    if (noFactory) {
                        iw.append(fieldMetadata.getJavaTypeName()).append("[] ");
                    }
                    iw.append(a).append(" = new ").append(fieldMetadata.getJavaTypeName()).append("[").append(c).append(".size()];\n");
                    XClass boxedType = box(fieldMetadata.getJavaType());
                    iw.append("int _j = 0;\nfor (java.util.Iterator _it = ").append(c).append(".iterator(); _it.hasNext();) ").append(a).append("[_j++] = ").append(unbox("((" + boxedType.getName() + ") _it.next())", boxedType)).append(";\n");
                    c = a;
                } else {
                    c = "(" + fieldMetadata.getJavaTypeName() + "[])" + c + ".toArray(new " + fieldMetadata.getJavaTypeName() + "[0])";
                }
            }
            if (noFactory) {
                iw.append(createSetPropExpr(messageTypeMetadata, fieldMetadata, "o", c)).append(";\n");
            } else if (fieldMetadata.isArray() && !fieldMetadata.getJavaType().isPrimitive()) {
                iw.append(makeArrayLocalVar(fieldMetadata)).append(" = ").append(c).append(";\n");
            }
            if (fieldMetadata.isArray()) {
                iw.dec().append('}');
                if (!noDefaults && fieldMetadata.getDefaultValue() == null) {
                    c = "new " + fieldMetadata.getJavaTypeName() + "[0]";
                    iw.append(" else {\n").inc();
                    if (noFactory) {
                        iw.append(createSetPropExpr(messageTypeMetadata, fieldMetadata, "o", c)).append(";\n");
                    } else {
                        iw.append(makeArrayLocalVar(fieldMetadata)).append(" = ").append(c).append(";\n");
                    }
                    iw.dec().append("}\n");
                }
            }
            iw.append('\n');
        }
    }
    // complain about missing required fields
    if (mandatoryFields > 0) {
        List<ProtoFieldMetadata> mandatory = messageTypeMetadata.getFields().values().stream().filter(f -> f.isRequired() && f.getDefaultValue() == null).collect(Collectors.toList());
        iw.append("if (").append(makeTestFieldWasNotSet(mandatory, trackedFields)).append(") {\n");
        iw.inc();
        iw.append("final StringBuilder missing = new StringBuilder();\n");
        boolean first = true;
        for (ProtoFieldMetadata fieldMetadata : messageTypeMetadata.getFields().values()) {
            if (fieldMetadata.isRequired()) {
                iw.append("if ").append(makeTestFieldWasNotSet(fieldMetadata, trackedFields)).append(" {\n");
                iw.inc();
                if (first) {
                    first = false;
                } else {
                    iw.append("if (missing.length() > 0) missing.append(\", \");\n");
                }
                iw.append("missing.append(\"").append(fieldMetadata.getName()).append("\");\n");
                iw.dec();
                iw.append("}\n");
            }
        }
        iw.append("throw new java.io.IOException(\"Required field(s) missing from input stream : \" + missing);\n");
        iw.dec();
        iw.append("}\n");
    }
    if (noFactory) {
        // return the instance
        iw.append("return o;\n");
    } else {
        // create and return the instance
        iw.append("return ");
        XExecutable factory = messageTypeMetadata.getFactory();
        if (factory instanceof XConstructor) {
            iw.append("new ").append(messageTypeMetadata.getJavaClassName());
        } else {
            if (factory.isStatic()) {
                iw.append(messageTypeMetadata.getAnnotatedClassName()).append('.').append(factory.getName());
            } else {
                iw.append(ADAPTER_FIELD_NAME).append('.').append(factory.getName());
            }
        }
        iw.append('(');
        boolean first = true;
        for (String paramName : factory.getParameterNames()) {
            if (first) {
                first = false;
                if (messageTypeMetadata.isContainer()) {
                    iw.append("__v$size");
                    continue;
                }
            } else {
                iw.append(", ");
            }
            boolean found = false;
            for (ProtoFieldMetadata fieldMetadata : messageTypeMetadata.getFields().values()) {
                if (fieldMetadata.getPropertyName().equals(paramName)) {
                    String var = fieldMetadata.isRepeated() ? (fieldMetadata.isArray() ? makeArrayLocalVar(fieldMetadata) : makeCollectionLocalVar(fieldMetadata)) : makeFieldLocalVar(fieldMetadata);
                    iw.append(var);
                    found = true;
                    break;
                }
            }
            if (!found) {
                throw new ProtoSchemaBuilderException("Parameter '" + paramName + "' of factory " + factory + " does not map to any Protobuf field");
            }
        }
        iw.append(");\n");
    }
    iw.dec().append("}\n");
    return iw.toString();
}
Also used : Type(org.infinispan.protostream.descriptors.Type) WireType(org.infinispan.protostream.descriptors.WireType) Date(java.util.Date) Collection(java.util.Collection) HashMap(java.util.HashMap) ProtoSchemaBuilderException(org.infinispan.protostream.annotations.ProtoSchemaBuilderException) Message(org.infinispan.protostream.Message) Instant(java.time.Instant) TagWriter(org.infinispan.protostream.TagWriter) XConstructor(org.infinispan.protostream.annotations.impl.types.XConstructor) Collectors(java.util.stream.Collectors) WrappedMessage(org.infinispan.protostream.WrappedMessage) LinkedHashMap(java.util.LinkedHashMap) List(java.util.List) XTypeFactory(org.infinispan.protostream.annotations.impl.types.XTypeFactory) Map(java.util.Map) Optional(java.util.Optional) TagReader(org.infinispan.protostream.TagReader) XClass(org.infinispan.protostream.annotations.impl.types.XClass) SerializationContext(org.infinispan.protostream.SerializationContext) XExecutable(org.infinispan.protostream.annotations.impl.types.XExecutable) JavaType(org.infinispan.protostream.descriptors.JavaType) Instant(java.time.Instant) XClass(org.infinispan.protostream.annotations.impl.types.XClass) LinkedHashMap(java.util.LinkedHashMap) XConstructor(org.infinispan.protostream.annotations.impl.types.XConstructor) XExecutable(org.infinispan.protostream.annotations.impl.types.XExecutable) ProtoSchemaBuilderException(org.infinispan.protostream.annotations.ProtoSchemaBuilderException)

Example 2 with ProtoSchemaBuilderException

use of org.infinispan.protostream.annotations.ProtoSchemaBuilderException in project protostream by infinispan.

the class BaseProtoSchemaGenerator method findOuterType.

private ProtoMessageTypeMetadata findOuterType(XClass c) {
    ProtoTypeMetadata outer = null;
    XClass ec = c.getEnclosingClass();
    while (ec != null) {
        if (ec.isEnum()) {
            throw new ProtoSchemaBuilderException("Classes defined inside an Enum are not allowed : " + c.getCanonicalName());
        }
        outer = metadataByClass.get(ec);
        if (outer != null) {
            break;
        }
        ec = ec.getEnclosingClass();
    }
    return (ProtoMessageTypeMetadata) outer;
}
Also used : ProtoSchemaBuilderException(org.infinispan.protostream.annotations.ProtoSchemaBuilderException) XClass(org.infinispan.protostream.annotations.impl.types.XClass)

Example 3 with ProtoSchemaBuilderException

use of org.infinispan.protostream.annotations.ProtoSchemaBuilderException in project protostream by infinispan.

the class ProtoMessageTypeMetadata method generateProto.

@Override
public void generateProto(IndentWriter iw) {
    // todo [anistor] need to have a better place for this call
    scanMemberAnnotations();
    iw.append("\n\n");
    appendDocumentation(iw, getDocumentation());
    iw.append("message ").append(name);
    if (BaseProtoSchemaGenerator.generateSchemaDebugComments) {
        iw.append(" /* ").append(getJavaClassName()).append(" */");
    }
    iw.append(" {\n");
    iw.inc();
    ReservedProcessor reserved = new ReservedProcessor();
    reserved.scan(annotatedClass);
    for (int memberNumber : fieldsByNumber.keySet()) {
        ProtoFieldMetadata field = fieldsByNumber.get(memberNumber);
        XClass where = reserved.checkReserved(memberNumber);
        if (where != null) {
            throw new ProtoSchemaBuilderException("Protobuf field number " + memberNumber + " of field " + field.getLocation() + " conflicts with 'reserved' statement in " + where.getCanonicalName());
        }
        where = reserved.checkReserved(field.getName());
        if (where != null) {
            throw new ProtoSchemaBuilderException("Protobuf field number " + memberNumber + " of field " + field.getLocation() + " conflicts with 'reserved' statement in " + where.getCanonicalName());
        }
    }
    reserved.generate(iw);
    for (ProtoTypeMetadata t : innerTypes.values()) {
        t.generateProto(iw);
    }
    for (ProtoFieldMetadata f : fieldsByNumber.values()) {
        f.generateProto(iw);
    }
    iw.dec();
    iw.append("}\n");
}
Also used : ProtoSchemaBuilderException(org.infinispan.protostream.annotations.ProtoSchemaBuilderException) XClass(org.infinispan.protostream.annotations.impl.types.XClass)

Example 4 with ProtoSchemaBuilderException

use of org.infinispan.protostream.annotations.ProtoSchemaBuilderException in project protostream by infinispan.

the class ProtoMessageTypeMetadata method getDefaultValue.

/**
 * Parses the value from string form (coming from proto schema) to an actual Java instance value, according to its
 * type.
 */
private Object getDefaultValue(XClass clazz, String fieldName, XClass fieldType, Type protobufType, String defaultValue) {
    if (defaultValue == null || defaultValue.isEmpty()) {
        return null;
    }
    if (fieldType == typeFactory.fromClass(String.class)) {
        return defaultValue;
    }
    if (fieldType.isEnum()) {
        ProtoTypeMetadata protoEnumTypeMetadata = protoSchemaGenerator.scanAnnotations(fieldType);
        ProtoEnumValueMetadata enumVal = protoEnumTypeMetadata.getEnumMemberByName(defaultValue);
        if (enumVal == null) {
            throw new ProtoSchemaBuilderException("Invalid default value for field '" + fieldName + "' of Java type " + fieldType.getCanonicalName() + " from class " + clazz.getCanonicalName() + ": " + defaultValue + " is not a member of " + protoEnumTypeMetadata.getFullName() + " enum");
        }
        return enumVal;
    }
    if (fieldType == typeFactory.fromClass(Character.class) || fieldType == typeFactory.fromClass(char.class)) {
        if (defaultValue.length() > 1) {
            throw new ProtoSchemaBuilderException("Invalid default value for field '" + fieldName + "' of Java type " + fieldType.getCanonicalName() + " from class " + clazz.getCanonicalName() + ": " + defaultValue);
        }
        return defaultValue.charAt(0);
    }
    if (fieldType == typeFactory.fromClass(Boolean.class) || fieldType == typeFactory.fromClass(boolean.class)) {
        return Boolean.valueOf(defaultValue);
    }
    try {
        if (fieldType == typeFactory.fromClass(Integer.class) || fieldType == typeFactory.fromClass(int.class)) {
            int v = parseInt(defaultValue);
            if (v < 0 && protobufType.isUnsigned()) {
                throw new ProtoSchemaBuilderException("Field '" + fieldName + "' of unsigned Protobuf type " + protobufType + " from class " + clazz.getCanonicalName() + " does not allow a negative default value : " + defaultValue);
            }
            return v;
        }
        if (fieldType == typeFactory.fromClass(Long.class) || fieldType == typeFactory.fromClass(long.class)) {
            long v = parseLong(defaultValue);
            if (v < 0 && protobufType.isUnsigned()) {
                throw new ProtoSchemaBuilderException("Field '" + fieldName + "' of unsigned Protobuf type " + protobufType + " from class " + clazz.getCanonicalName() + " does not allow a negative default value : " + defaultValue);
            }
            return v;
        }
        if (fieldType == typeFactory.fromClass(Short.class) || fieldType == typeFactory.fromClass(short.class)) {
            int v = parseInt(defaultValue);
            if (v < 0 && protobufType.isUnsigned()) {
                throw new ProtoSchemaBuilderException("Field '" + fieldName + "' of unsigned Protobuf type " + protobufType + " from class " + clazz.getCanonicalName() + " does not allow a negative default value : " + defaultValue);
            }
            if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
                throw new NumberFormatException("Value out of range for \"" + protobufType + "\": \"" + defaultValue);
            }
            return (short) v;
        }
        if (fieldType == typeFactory.fromClass(Double.class) || fieldType == typeFactory.fromClass(double.class)) {
            return Double.valueOf(defaultValue);
        }
        if (fieldType == typeFactory.fromClass(Float.class) || fieldType == typeFactory.fromClass(float.class)) {
            return Float.valueOf(defaultValue);
        }
        if (fieldType == typeFactory.fromClass(Byte.class) || fieldType == typeFactory.fromClass(byte.class)) {
            int v = parseInt(defaultValue);
            if (v < 0 && protobufType.isUnsigned()) {
                throw new ProtoSchemaBuilderException("Field '" + fieldName + "' of unsigned Protobuf type " + protobufType + " from class " + clazz.getCanonicalName() + " does not allow a negative default value : " + defaultValue);
            }
            if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) {
                throw new NumberFormatException("Value out of range for \"" + protobufType + "\": \"" + defaultValue);
            }
            return (byte) v;
        }
        if (fieldType.isAssignableTo(Date.class)) {
            return Long.parseUnsignedLong(defaultValue);
        }
        if (fieldType.isAssignableTo(Instant.class)) {
            return Long.parseUnsignedLong(defaultValue);
        }
    } catch (NumberFormatException e) {
        throw new ProtoSchemaBuilderException("Invalid default value for field '" + fieldName + "' of Java type " + fieldType.getCanonicalName() + " from class " + clazz.getCanonicalName() + ": " + defaultValue, e);
    }
    if (protobufType == Type.BYTES) {
        if (fieldType == typeFactory.fromClass(byte[].class)) {
            return cescape(defaultValue);
        } else {
            throw new ProtoSchemaBuilderException("Invalid default value for field '" + fieldName + "' of Java type " + fieldType.getCanonicalName() + " from class " + clazz.getCanonicalName() + ": " + defaultValue);
        }
    }
    throw new ProtoSchemaBuilderException("No default value is allowed for field '" + fieldName + "' of Java type " + fieldType.getCanonicalName() + " from class " + clazz.getCanonicalName());
}
Also used : ProtoSchemaBuilderException(org.infinispan.protostream.annotations.ProtoSchemaBuilderException)

Example 5 with ProtoSchemaBuilderException

use of org.infinispan.protostream.annotations.ProtoSchemaBuilderException in project protostream by infinispan.

the class ProtoMessageTypeMetadata method scanMemberAnnotations.

@Override
public void scanMemberAnnotations() {
    if (fieldsByNumber == null) {
        // All the fields discovered in this class hierarchy, the key is their number.
        // We use a TreeMap to ensure ascending order by field number.
        fieldsByNumber = new TreeMap<>();
        // all the fields discovered in this class hierarchy, by name
        fieldsByName = new HashMap<>();
        discoverFields(annotatedClass, new HashSet<>());
        if (fieldsByNumber.isEmpty()) {
            // todo avoid this warning in case where not necessary
            // TODO [anistor] remove the "The class should be either annotated or it should have a custom marshaller" part after MessageMarshaller is removed in 5
            log.warnf("Class %s does not have any @ProtoField annotated members. The class should be either annotated or it should have a custom marshaller.", getAnnotatedClassName());
        }
        // If we have a factory method / constructor, we must ensure its parameters match the declared fields
        if (factory != null) {
            String factoryKind = factory instanceof XConstructor ? "constructor" : (factory.isStatic() ? "static method" : "method");
            XClass[] parameterTypes = factory.getParameterTypes();
            int startPos = 0;
            if (isIndexedContainer || isIterableContainer) {
                if (parameterTypes.length == 0 || parameterTypes[0] != typeFactory.fromClass(int.class)) {
                    throw new ProtoSchemaBuilderException("@ProtoFactory annotated " + factoryKind + " signature mismatch. The first parameter is expected to be of type 'int' : " + factory.toGenericString());
                }
                startPos = 1;
            }
            String[] parameterNames = factory.getParameterNames();
            if (parameterNames.length != fieldsByNumber.size() + startPos) {
                throw new ProtoSchemaBuilderException("@ProtoFactory annotated " + factoryKind + " signature mismatch. Expected " + (fieldsByNumber.size() + startPos) + " parameters but found " + parameterNames.length + " : " + factory.toGenericString());
            }
            for (; startPos < parameterNames.length; startPos++) {
                String parameterName = parameterNames[startPos];
                ProtoFieldMetadata fieldMetadata = getFieldByPropertyName(parameterName);
                if (fieldMetadata == null) {
                    throw new ProtoSchemaBuilderException("@ProtoFactory annotated " + factoryKind + " signature mismatch. The parameter '" + parameterName + "' does not match any field : " + factory.toGenericString());
                }
                XClass parameterType = parameterTypes[startPos];
                boolean paramTypeMismatch = false;
                if (fieldMetadata.isArray()) {
                    if (!parameterType.isArray() || parameterType.getComponentType() != fieldMetadata.getJavaType()) {
                        paramTypeMismatch = true;
                    }
                } else if (fieldMetadata.isRepeated()) {
                    if (!fieldMetadata.getCollectionImplementation().isAssignableTo(parameterType)) {
                        paramTypeMismatch = true;
                    }
                // todo [anistor] also check the collection's type parameter
                } else if (fieldMetadata.getJavaType() != parameterType) {
                    paramTypeMismatch = true;
                }
                if (paramTypeMismatch) {
                    throw new ProtoSchemaBuilderException("@ProtoFactory annotated " + factoryKind + " signature mismatch: " + factory.toGenericString() + ". The parameter '" + parameterName + "' does not match the type from the field definition.");
                }
            }
        }
    }
}
Also used : ProtoSchemaBuilderException(org.infinispan.protostream.annotations.ProtoSchemaBuilderException) XClass(org.infinispan.protostream.annotations.impl.types.XClass) XConstructor(org.infinispan.protostream.annotations.impl.types.XConstructor)

Aggregations

ProtoSchemaBuilderException (org.infinispan.protostream.annotations.ProtoSchemaBuilderException)18 XClass (org.infinispan.protostream.annotations.impl.types.XClass)12 Optional (java.util.Optional)4 SerializationContext (org.infinispan.protostream.SerializationContext)4 ArrayList (java.util.ArrayList)3 Collection (java.util.Collection)3 List (java.util.List)3 XMethod (org.infinispan.protostream.annotations.impl.types.XMethod)3 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Map (java.util.Map)2 Set (java.util.Set)2 TypeMirror (javax.lang.model.type.TypeMirror)2 ProtoUnknownFieldSet (org.infinispan.protostream.annotations.ProtoUnknownFieldSet)2 XConstructor (org.infinispan.protostream.annotations.impl.types.XConstructor)2 AutoService (com.google.auto.service.AutoService)1 IOException (java.io.IOException)1 PrintWriter (java.io.PrintWriter)1 StringWriter (java.io.StringWriter)1 Instant (java.time.Instant)1