Skip to content

Commit

Permalink
[core] Introduce StructureValueAccessor#getFieldAccessor.
Browse files Browse the repository at this point in the history
  • Loading branch information
dmvk committed Jun 8, 2021
1 parent e17d78d commit 75e1fae
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
/**
* Interface for value accessors allowed create and get value of attribute
*
* @param <InputT> input type
* @param <OutputT> output type
* @param <InputT> Type of "raw" input element, that we want to convert into normalized form.
* @param <OutputT> Normalized "output" type, eg. `bytes -> string` for schema type `string`.
*/
@Experimental
public interface AttributeValueAccessor<InputT, OutputT> extends Serializable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,28 @@ static StructureValue of(Map<String, Object> value) {

public interface StructureValueAccessor<T> extends AttributeValueAccessor<T, StructureValue> {

/**
* Get accessor for a given field. Please not that accessors only work on "raw values". See
* {@link #getRawFieldValue(String, Object)} for more details.
*
* @param name Name of the field to get accessor for.
* @return Field accessor.
*/
AttributeValueAccessor<?, ?> getFieldAccessor(String name);

/**
* Get raw value of a given field. In this context, raw value means a value before applying a
* field accessor on it (for example it can be a byte representation, that would be converted to
* a string after "accessing"). This is intended for partial message parsing and to be used in
* combination with {@link #getFieldAccessor(String)}.
*
* @param name Name of the field.
* @param structure Structure to get a raw value from.
* @param <OutputT> Type of raw value. This is only to simplify casting of returned value.
* @return Raw value.
*/
<OutputT> OutputT getRawFieldValue(String name, T structure);

@Override
default Type getType() {
return Type.STRUCTURE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ public void testArrayWithStructureValue() {
private static class TestStructureAccessor
implements StructureValueAccessor<Map<String, Object>> {

@Override
public AttributeValueAccessor<?, ?> getFieldAccessor(String name) {
throw new UnsupportedOperationException("Not implemented.");
}

@Override
public <OutputT> OutputT getRawFieldValue(String name, Map<String, Object> structure) {
throw new UnsupportedOperationException("Not implemented.");
}

@Override
public StructureValue valueOf(Map<String, Object> object) {
return StructureValue.of(object);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,31 @@ public ProtoMessageValueAccessor(Factory<T> defaultValueFactory) {
}));
}

@Override
public AttributeValueAccessor<?, ?> getFieldAccessor(String name) {
return fieldAccessors.get(name);
}

@Override
public <OutputT> OutputT getRawFieldValue(String name, T structure) {
for (FieldDescriptor field : structure.getDescriptorForType().getFields()) {
if (name.equals(field.getName())) {
final Object rawValue = structure.getField(field);
if (rawValue instanceof EnumValueDescriptor) {
final EnumValueDescriptor cast = (EnumValueDescriptor) rawValue;
@SuppressWarnings("unchecked")
final OutputT result = (OutputT) cast.getName();
return result;
}
@SuppressWarnings("unchecked")
final OutputT result = (OutputT) rawValue;
return result;
}
}
throw new IllegalStateException(
String.format("Field %s not found in %s.", name, structure.getClass()));
}

@Override
public StructureValue valueOf(T object) {
return StructureValue.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

import com.google.protobuf.ByteString;
import cz.o2.proxima.scheme.AttributeValueAccessors;
import cz.o2.proxima.scheme.AttributeValueAccessors.StructureValue;
import cz.o2.proxima.scheme.AttributeValueAccessors.StructureValueAccessor;
import cz.o2.proxima.scheme.proto.test.Scheme.Event;
Expand Down Expand Up @@ -229,4 +231,42 @@ public void testCreateProtoWhereRepeatedFieldChangedToOptional() {
assertArrayEquals(
"second".getBytes(StandardCharsets.UTF_8), created.getPayload().toByteArray());
}

@Test
public void testFieldAccessors() {
final StructureValueAccessor<ValueSchemeMessage> accessor =
new ProtoMessageValueAccessor<>(ValueSchemeMessage::getDefaultInstance);
final InnerMessage innerMessage = InnerMessage.newBuilder().setInnerDoubleType(1.2).build();
final ValueSchemeMessage message =
ValueSchemeMessage.newBuilder()
.setStringType("test string")
.setInnerMessage(innerMessage)
.build();

// Test getting "raw field value". This means that inner message doesn't get converted into map.
assertEquals("test string", accessor.getRawFieldValue("string_type", message));
assertEquals(innerMessage, accessor.getRawFieldValue("inner_message", message));

// Test inner message accessor.
@SuppressWarnings("unchecked")
final StructureValueAccessor<InnerMessage> innerMessageAccessor =
(StructureValueAccessor<InnerMessage>) accessor.getFieldAccessor("inner_message");
assertEquals(
1.2d, innerMessageAccessor.getRawFieldValue("inner_double_type", innerMessage), 0.0);

// Test string type accessor.
@SuppressWarnings("unchecked")
final AttributeValueAccessors.PrimitiveValueAccessor<String, String> stringTypeAccessor =
(AttributeValueAccessors.PrimitiveValueAccessor<String, String>)
accessor.getFieldAccessor("string_type");
assertEquals(
"test string",
stringTypeAccessor.valueOf(accessor.getRawFieldValue("string_type", message)));

// Test accessing unknown field.
assertThrows(IllegalStateException.class, () -> accessor.getRawFieldValue("unknown", message));

// Test defaults.
assertEquals(0L, (long) accessor.getRawFieldValue("long_type", message));
}
}
2 changes: 1 addition & 1 deletion scheme/proto/src/test/resources/test-proto.conf
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
attributes: [ "*" ]
storage: "inmem:///data/proxima/gateway"
type: replica
access: [ commit-log, random-access ]
access: [ random-access ]
}
dummy-storage: {
entity: dummy
Expand Down

0 comments on commit 75e1fae

Please sign in to comment.