use of net.morimekta.providence.PMessage in project providence by morimekta.
the class MessageFieldArgument method apply.
@Override
@SuppressWarnings("unchecked")
public void apply(int position, PreparedStatement statement, StatementContext ctx) throws SQLException {
if (message.has(field)) {
switch(field.getType()) {
case BOOL:
{
boolean value = message.get(field);
if (type == Types.BOOLEAN || type == Types.BIT) {
statement.setBoolean(position, value);
} else {
statement.setInt(position, value ? 1 : 0);
}
break;
}
case BYTE:
{
statement.setByte(position, message.get(field));
break;
}
case I16:
{
statement.setShort(position, message.get(field));
break;
}
case I32:
{
if (type == Types.TIMESTAMP) {
Timestamp timestamp = new Timestamp(1000L * (int) message.get(field));
statement.setTimestamp(position, timestamp);
} else {
statement.setInt(position, message.get(field));
}
break;
}
case I64:
{
if (type == Types.TIMESTAMP) {
Timestamp timestamp = new Timestamp(message.get(field));
statement.setTimestamp(position, timestamp);
} else {
statement.setLong(position, message.get(field));
}
break;
}
case DOUBLE:
{
statement.setDouble(position, message.get(field));
break;
}
case STRING:
{
statement.setString(position, message.get(field));
break;
}
case BINARY:
{
Binary binary = message.get(field);
switch(type) {
case Types.BINARY:
case Types.VARBINARY:
{
statement.setBytes(position, binary.get());
break;
}
case Types.BLOB:
{
statement.setBlob(position, binary.getInputStream());
break;
}
case Types.CHAR:
case Types.VARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
{
statement.setString(position, binary.toBase64());
break;
}
default:
throw new ResultSetException("Unknown binary field type: " + type + " for " + field, null, ctx);
}
break;
}
case ENUM:
{
PEnumValue value = message.get(field);
statement.setInt(position, value.asInteger());
break;
}
case MESSAGE:
{
PMessage value = message.get(field);
switch(type) {
case Types.BINARY:
case Types.VARBINARY:
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
BINARY.serialize(out, value);
statement.setBytes(position, out.toByteArray());
} catch (IOException e) {
throw new ResultSetException(e.getMessage(), e, ctx);
}
break;
}
case Types.BLOB:
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
BINARY.serialize(out, value);
statement.setBlob(position, new ByteArrayInputStream(out.toByteArray()));
} catch (IOException e) {
throw new ResultSetException(e.getMessage(), e, ctx);
}
break;
}
case Types.CHAR:
case Types.VARCHAR:
case Types.NCHAR:
case Types.NVARCHAR:
{
StringWriter writer = new StringWriter();
try {
JSON.serialize(new PrintWriter(writer), value);
statement.setString(position, writer.getBuffer().toString());
} catch (IOException e) {
throw new ResultSetException(e.getMessage(), e, ctx);
}
break;
}
case Types.CLOB:
{
StringWriter writer = new StringWriter();
try {
JSON.serialize(new PrintWriter(writer), value);
statement.setClob(position, new StringReader(writer.getBuffer().toString()));
} catch (IOException e) {
throw new ResultSetException(e.getMessage(), e, ctx);
}
break;
}
default:
throw new ResultSetException("Unknown message field type: " + type + " for " + field, null, ctx);
}
break;
}
default:
throw new ResultSetException("Unhandled field type in SQL: " + field, null, ctx);
}
} else {
statement.setNull(position, type);
}
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class MessageNamedArgumentFinder method find.
@Nonnull
@Override
@SuppressWarnings("unchecked")
public Optional<Argument> find(String name, StatementContext ctx) {
if (!prefix.isEmpty()) {
if (name.startsWith(prefix)) {
name = name.substring(prefix.length());
} else {
return Optional.empty();
}
}
String[] parts = name.split("[.]");
PMessage leaf = message;
PMessageDescriptor leafDescriptor = message.descriptor();
for (int i = 0; i < parts.length - 1; ++i) {
String part = parts[i];
PField field = leafDescriptor.findFieldByName(part);
if (field == null)
return Optional.empty();
if (field.getType() != PType.MESSAGE) {
throw new IllegalArgumentException("");
}
leafDescriptor = (PMessageDescriptor) field.getDescriptor();
if (leaf != null) {
leaf = (PMessage) leaf.get(field.getId());
}
}
String leafName = parts[parts.length - 1];
PField field = leafDescriptor.findFieldByName(leafName);
if (field != null) {
if (leaf != null) {
return Optional.of(new MessageFieldArgument(leaf, field, getColumnType(field)));
}
return Optional.of(new NullArgument(getColumnType(field)));
}
return Optional.empty();
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class OverrideConfigSupplier method buildOverrideConfig.
private static <Message extends PMessage<Message, Field>, Field extends PField> Message buildOverrideConfig(Message parent, Map<String, String> overrides, boolean strict) throws ProvidenceConfigException {
PMessageBuilder<Message, Field> builder = parent.mutate();
for (Map.Entry<String, String> override : overrides.entrySet()) {
String[] path = override.getKey().split("[.]");
String fieldName = lastFieldName(path);
PMessageBuilder containedBuilder = builderForField(strict, builder, path);
if (containedBuilder == null) {
continue;
}
PField field = containedBuilder.descriptor().findFieldByName(fieldName);
if (field == null) {
if (strict) {
throw new ProvidenceConfigException("No such field %s in %s [%s]", fieldName, containedBuilder.descriptor().getQualifiedName(), String.join(".", path));
}
continue;
}
if (UNDEFINED.equals(override.getValue())) {
containedBuilder.clear(field.getId());
} else {
containedBuilder.set(field.getId(), readFieldValue(override.getKey(), override.getValue(), field.getDescriptor()));
}
}
return builder.build();
}
use of net.morimekta.providence.PMessage 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;
}
use of net.morimekta.providence.PMessage in project providence by morimekta.
the class GenericMethods method assertValueIntegrity.
@SuppressWarnings("unchecked")
private void assertValueIntegrity(PField expectedField, Object actualValue, Object expectedValue) {
if (actualValue == null || expectedValue == null) {
assertThat(expectedField.toString(), actualValue, is(expectedValue));
} else if (actualValue instanceof PMessage && expectedValue instanceof PMessage) {
assertFieldIntegrity((PMessage<?, ?>) actualValue, (PMessage<?, ?>) expectedValue);
} else if (actualValue instanceof PEnumValue && expectedValue instanceof PEnumValue) {
assertThat(expectedField.toString(), ((PEnumValue) actualValue).getId(), is(((PEnumValue) expectedValue).getId()));
} else if (actualValue instanceof List && expectedValue instanceof List) {
List<Object> actualList = (List) actualValue;
List<Object> expectedList = (List) expectedValue;
assertThat(expectedField.toString(), actualList, hasSize(expectedList.size()));
for (int i = 0; i < actualList.size(); ++i) {
assertValueIntegrity(expectedField, actualList.get(i), expectedList.get(i));
}
} else if (actualValue instanceof Set && expectedValue instanceof Set) {
TreeSet<Object> actualSet = new TreeSet<>((Set<Object>) actualValue);
TreeSet<Object> expectedSet = new TreeSet<>((Set<Object>) expectedValue);
assertThat(expectedField.toString(), actualSet, hasSize(expectedSet.size()));
while (actualSet.size() > 0) {
assertValueIntegrity(expectedField, actualSet.pollFirst(), expectedSet.pollFirst());
}
} else if (actualValue instanceof Map && expectedValue instanceof Map) {
Map actualMap = (Map) actualValue;
Map expectedMap = (Map) expectedValue;
assertValueIntegrity(expectedField, actualMap.keySet(), expectedMap.keySet());
for (Object key : actualMap.keySet()) {
if (key instanceof PEnumValue) {
// Search for the enum with the same ID in the expected map keys.
Object expectedKey = expectedMap.keySet().stream().filter(k -> ((PEnumValue) k).getId() == ((PEnumValue) key).getId()).findFirst().orElse(null);
if (expectedKey == null) {
throw new AssertionError("No expected map key matching " + key);
}
assertValueIntegrity(expectedField, actualMap.get(key), expectedMap.get(expectedKey));
} else if (key instanceof PMessage) {
// The messages should sort identically.
TreeSet<PMessage> actualKeys = new TreeSet<>(actualMap.keySet());
TreeSet<PMessage> expectedKeys = new TreeSet<>(expectedMap.keySet());
while (expectedKeys.size() > 0) {
PMessage actual = actualKeys.pollFirst();
PMessage expected = expectedKeys.pollFirst();
assertFieldIntegrity(actual, expected);
assertValueIntegrity(expectedField, actualMap.get(actual), expectedMap.get(expected));
}
} else {
assertValueIntegrity(expectedField, actualMap.get(key), expectedMap.get(key));
}
}
} else {
assertThat(expectedField.toString(), actualValue, is(expectedValue));
}
}
Aggregations