Search in sources :

Example 11 with PMessageDescriptor

use of net.morimekta.providence.descriptor.PMessageDescriptor in project providence by morimekta.

the class ProvidenceMessageBodyReader method getDescriptor.

@Nullable
private PMessageDescriptor getDescriptor(Class<?> type) {
    try {
        if (!PMessage.class.isAssignableFrom(type)) {
            return null;
        }
        Field descField = type.getDeclaredField("kDescriptor");
        Object desc = descField.get(null);
        if (desc instanceof PMessageDescriptor) {
            return (PMessageDescriptor) desc;
        }
    } catch (NoSuchFieldException | IllegalAccessException ignore) {
    // ignore.printStackTrace();
    }
    return null;
}
Also used : Field(java.lang.reflect.Field) PMessage(net.morimekta.providence.PMessage) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) Nullable(javax.annotation.Nullable)

Example 12 with PMessageDescriptor

use of net.morimekta.providence.descriptor.PMessageDescriptor in project providence by morimekta.

the class MessageRowMapper method map.

@Override
public M map(int idx, ResultSet rs, StatementContext ctx) throws SQLException {
    PMessageBuilder<M, F> builder = descriptor.builder();
    for (int i = 1; i <= rs.getMetaData().getColumnCount(); ++i) {
        if (!tableName.isEmpty() && !tableName.equalsIgnoreCase(rs.getMetaData().getTableName(i))) {
            continue;
        }
        String name = rs.getMetaData().getColumnLabel(i).toUpperCase(Locale.US);
        F field = fieldNameMapping.get(name);
        if (field != null) {
            int columnType = rs.getMetaData().getColumnType(i);
            switch(field.getType()) {
                case BOOL:
                    {
                        if (columnType == Types.BOOLEAN || columnType == Types.BIT) {
                            boolean b = rs.getBoolean(i);
                            if (!rs.wasNull()) {
                                builder.set(field, b);
                            }
                        } else {
                            int b = rs.getInt(i);
                            if (!rs.wasNull()) {
                                builder.set(field, b != 0);
                            }
                        }
                        break;
                    }
                case BYTE:
                    {
                        byte b = rs.getByte(i);
                        if (!rs.wasNull()) {
                            builder.set(field, b);
                        }
                        break;
                    }
                case I16:
                    {
                        short b = rs.getShort(i);
                        if (!rs.wasNull()) {
                            builder.set(field, b);
                        }
                        break;
                    }
                case I32:
                    {
                        if (columnType == Types.TIMESTAMP) {
                            Timestamp ts = rs.getTimestamp(i);
                            if (ts != null) {
                                builder.set(field, (int) (ts.getTime() / 1000L));
                            }
                        } else {
                            int b = rs.getInt(i);
                            if (!rs.wasNull()) {
                                builder.set(field, b);
                            }
                        }
                        break;
                    }
                case I64:
                    {
                        if (columnType == Types.TIMESTAMP) {
                            Timestamp ts = rs.getTimestamp(i);
                            if (ts != null) {
                                builder.set(field, ts.getTime());
                            }
                        } else {
                            long b = rs.getLong(i);
                            if (!rs.wasNull()) {
                                builder.set(field, b);
                            }
                        }
                        break;
                    }
                case DOUBLE:
                    {
                        double b = rs.getDouble(i);
                        if (!rs.wasNull()) {
                            builder.set(field, b);
                        }
                        break;
                    }
                case STRING:
                    {
                        builder.set(field, rs.getString(i));
                        break;
                    }
                case BINARY:
                    {
                        switch(columnType) {
                            case Types.BINARY:
                            case Types.VARBINARY:
                                byte[] ts = rs.getBytes(i);
                                if (ts != null) {
                                    builder.set(field, Binary.copy(ts));
                                }
                                break;
                            case Types.BLOB:
                                Blob blob = rs.getBlob(i);
                                if (blob != null) {
                                    try {
                                        builder.set(field, Binary.read(blob.getBinaryStream(), (int) blob.length()));
                                    } catch (IOException e) {
                                        throw new UncheckedIOException(e.getMessage(), e);
                                    }
                                }
                                break;
                            case Types.CHAR:
                            case Types.VARCHAR:
                            case Types.NCHAR:
                            case Types.NVARCHAR:
                                {
                                    String tmp = rs.getString(i);
                                    if (tmp != null) {
                                        builder.set(field, Binary.fromBase64(tmp));
                                    }
                                    break;
                                }
                            case Types.NULL:
                                break;
                            default:
                                throw new SQLDataException("Unknown column type " + rs.getMetaData().getColumnTypeName(i) + " for " + descriptor.getType().toString() + " field " + name + " in " + descriptor.getQualifiedName());
                        }
                        break;
                    }
                case ENUM:
                    {
                        int val = rs.getInt(i);
                        if (!rs.wasNull()) {
                            PEnumDescriptor ed = (PEnumDescriptor) field.getDescriptor();
                            builder.set(field, ed.findById(val));
                        }
                        break;
                    }
                case MESSAGE:
                    {
                        try {
                            PMessageDescriptor<?, ?> md = (PMessageDescriptor) field.getDescriptor();
                            switch(columnType) {
                                case Types.BINARY:
                                case Types.VARBINARY:
                                    byte[] data = rs.getBytes(i);
                                    if (data != null) {
                                        ByteArrayInputStream in = new ByteArrayInputStream(data);
                                        builder.set(field, BINARY.deserialize(in, md));
                                    }
                                    break;
                                case Types.BLOB:
                                    {
                                        Blob blob = rs.getBlob(i);
                                        if (blob != null) {
                                            builder.set(field, BINARY.deserialize(blob.getBinaryStream(), md));
                                        }
                                        break;
                                    }
                                case Types.CHAR:
                                case Types.VARCHAR:
                                case Types.NCHAR:
                                case Types.NVARCHAR:
                                    {
                                        String tmp = rs.getString(i);
                                        if (tmp != null) {
                                            StringReader reader = new StringReader(tmp);
                                            builder.set(field, JSON.deserialize(reader, md));
                                        }
                                        break;
                                    }
                                case Types.CLOB:
                                    {
                                        Clob clob = rs.getClob(i);
                                        if (clob != null) {
                                            builder.set(field, JSON.deserialize(clob.getCharacterStream(), md));
                                        }
                                        break;
                                    }
                                case Types.NULL:
                                    break;
                                default:
                                    throw new SQLDataException("Unknown column type " + rs.getMetaData().getColumnTypeName(i) + " for " + descriptor.getType().toString() + " field " + name + " in " + descriptor.getQualifiedName());
                            }
                        } catch (IOException e) {
                            throw new UncheckedIOException(e.getMessage(), e);
                        }
                        break;
                    }
                case LIST:
                case SET:
                case MAP:
                    {
                    // ... woot?
                    }
                case VOID:
                default:
                    {
                        throw new SQLDataException("Unhandled column of type " + rs.getMetaData().getColumnTypeName(i) + " for " + descriptor.getType().toString() + " field " + name + " in " + descriptor.getQualifiedName());
                    }
            }
        }
    }
    return builder.build();
}
Also used : Blob(java.sql.Blob) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) PEnumDescriptor(net.morimekta.providence.descriptor.PEnumDescriptor) Timestamp(java.sql.Timestamp) SQLDataException(java.sql.SQLDataException) ByteArrayInputStream(java.io.ByteArrayInputStream) StringReader(java.io.StringReader) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) Clob(java.sql.Clob)

Example 13 with PMessageDescriptor

use of net.morimekta.providence.descriptor.PMessageDescriptor in project providence by morimekta.

the class ProvidenceConfigUtil method getInMessage.

/**
 * Look up a key in the message structure. If the key is not found, return
 * the default value. Note that the default value will be converted to the
 * type of the declared field, not returned verbatim.
 *
 * @param message The message to look up into.
 * @param key The key to look up.
 * @param defValue The default value.
 * @return The value found or the default.
 * @throws ProvidenceConfigException When unable to get value from message.
 */
static Object getInMessage(PMessage message, final String key, Object defValue) throws ProvidenceConfigException {
    String sub = key;
    String name;
    PMessageDescriptor descriptor = message.descriptor();
    while (sub.contains(".")) {
        int idx = sub.indexOf(".");
        name = sub.substring(0, idx);
        sub = sub.substring(idx + 1);
        PField field = descriptor.findFieldByName(name);
        if (field == null) {
            throw new ProvidenceConfigException("Message " + descriptor.getQualifiedName() + " has no field named " + name);
        }
        PDescriptor fieldDesc = field.getDescriptor();
        if (fieldDesc.getType() != PType.MESSAGE) {
            throw new ProvidenceConfigException("Field '" + name + "' is not of message type in " + descriptor.getQualifiedName());
        }
        descriptor = (PMessageDescriptor) fieldDesc;
        if (message != null) {
            message = (PMessage) message.get(field.getId());
        }
    }
    PField field = descriptor.findFieldByName(sub);
    if (field == null) {
        throw new ProvidenceConfigException("Message " + descriptor.getQualifiedName() + " has no field named " + sub);
    }
    if (message == null || !message.has(field.getId())) {
        return asType(field.getDescriptor(), defValue);
    }
    return message.get(field.getId());
}
Also used : PDescriptor(net.morimekta.providence.descriptor.PDescriptor) PField(net.morimekta.providence.descriptor.PField) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) ProvidenceConfigException(net.morimekta.providence.config.ProvidenceConfigException)

Example 14 with PMessageDescriptor

use of net.morimekta.providence.descriptor.PMessageDescriptor in project providence by morimekta.

the class ProvidenceConfigParser method parseDefinitionValue.

@SuppressWarnings("unchecked")
Object parseDefinitionValue(ProvidenceConfigContext context, Tokenizer tokenizer) throws IOException {
    Token token = tokenizer.expect("Start of def value");
    if (token.isReal()) {
        return Double.parseDouble(token.asString());
    } else if (token.isInteger()) {
        return Long.parseLong(token.asString());
    } else if (token.isStringLiteral()) {
        return token.decodeLiteral(strict);
    } else if (TRUE.equalsIgnoreCase(token.asString())) {
        return Boolean.TRUE;
    } else if (FALSE.equalsIgnoreCase(token.asString())) {
        return Boolean.FALSE;
    } else if (Token.B64.equals(token.asString())) {
        tokenizer.expectSymbol("binary data enclosing start", Token.kParamsStart);
        return Binary.fromBase64(tokenizer.readBinary(Token.kParamsEnd));
    } else if (Token.HEX.equals(token.asString())) {
        tokenizer.expectSymbol("binary data enclosing start", Token.kParamsStart);
        return Binary.fromHexString(tokenizer.readBinary(Token.kParamsEnd));
    } else if (token.isDoubleQualifiedIdentifier()) {
        // this may be an enum reference, must be
        // - package.EnumType.IDENTIFIER
        String id = token.asString();
        int l = id.lastIndexOf(Token.kIdentifierSep);
        try {
            PEnumDescriptor ed = registry.getEnumType(id.substring(0, l));
            PEnumValue val = ed.findByName(id.substring(l + 1));
            if (val == null && strict) {
                throw new TokenizerException(token, "Unknown %s value: %s", id.substring(0, l), id.substring(l + 1)).setLine(tokenizer.getLine());
            }
            // Note that unknown enum value results in null. Therefore we don't catch null values here.
            return val;
        } catch (IllegalArgumentException e) {
            // No such declared type.
            if (strict) {
                throw new TokenizerException(token, "Unknown enum identifier: %s", id.substring(0, l)).setLine(tokenizer.getLine());
            }
            consumeValue(context, tokenizer, token);
        } catch (ClassCastException e) {
            // Not an enum.
            throw new TokenizerException(token, "Identifier " + id + " does not reference an enum, from " + token.asString()).setLine(tokenizer.getLine());
        }
    } else if (token.isQualifiedIdentifier()) {
        // Message type.
        PMessageDescriptor descriptor;
        try {
            descriptor = registry.getMessageType(token.asString());
        } catch (IllegalArgumentException e) {
            // - strict mode: all types must be known.
            if (strict) {
                throw new TokenizerException(token, "Unknown declared type: %s", token.asString()).setLine(tokenizer.getLine());
            }
            consumeValue(context, tokenizer, token);
            return null;
        }
        PMessageBuilder builder = descriptor.builder();
        if (tokenizer.expectSymbol("message start or inherits", '{', ':') == ':') {
            token = tokenizer.expect("inherits reference");
            PMessage inheritsFrom = resolve(context, token, tokenizer, descriptor);
            if (inheritsFrom == null) {
                throw new TokenizerException(token, "Inheriting from null reference: %s", token.asString()).setLine(tokenizer.getLine());
            }
            builder.merge(inheritsFrom);
            tokenizer.expectSymbol("message start", '{');
        }
        return parseMessage(tokenizer, context, builder);
    } else {
        throw new TokenizerException(token, "Invalid define value " + token.asString()).setLine(tokenizer.getLine());
    }
    return null;
}
Also used : PMessageBuilder(net.morimekta.providence.PMessageBuilder) PMessage(net.morimekta.providence.PMessage) PEnumValue(net.morimekta.providence.PEnumValue) Token(net.morimekta.providence.serializer.pretty.Token) TokenizerException(net.morimekta.providence.serializer.pretty.TokenizerException) PMessageDescriptor(net.morimekta.providence.descriptor.PMessageDescriptor) PEnumDescriptor(net.morimekta.providence.descriptor.PEnumDescriptor)

Aggregations

PMessageDescriptor (net.morimekta.providence.descriptor.PMessageDescriptor)14 PEnumDescriptor (net.morimekta.providence.descriptor.PEnumDescriptor)7 PMessage (net.morimekta.providence.PMessage)5 IOException (java.io.IOException)4 PField (net.morimekta.providence.descriptor.PField)4 ByteArrayInputStream (java.io.ByteArrayInputStream)3 StringReader (java.io.StringReader)2 UncheckedIOException (java.io.UncheckedIOException)2 Blob (java.sql.Blob)2 Clob (java.sql.Clob)2 Timestamp (java.sql.Timestamp)2 TreeSet (java.util.TreeSet)2 Nonnull (javax.annotation.Nonnull)2 PEnumValue (net.morimekta.providence.PEnumValue)2 PMessageBuilder (net.morimekta.providence.PMessageBuilder)2 ProvidenceConfigException (net.morimekta.providence.config.ProvidenceConfigException)2 PDeclaredDescriptor (net.morimekta.providence.descriptor.PDeclaredDescriptor)2 PDescriptor (net.morimekta.providence.descriptor.PDescriptor)2 PList (net.morimekta.providence.descriptor.PList)2 PMap (net.morimekta.providence.descriptor.PMap)2