private Object windowStructuralValue() { return windowCoder.structuralValue(window); }
private Object windowStructuralValue() { return windowCoder.structuralValue(window); }
@Override public Iterable<V> get(K k) { return structuralKeyToValuesMap.get(keyCoder.structuralValue(k)); } }
@Override public Object structuralValue(Iterable<T> value) { ArrayList<Object> result = new ArrayList<>(); for (T elem : value) { result.add(getElemCoder().structuralValue(elem)); } return result; }
/** * Verifies that for the given {@code Coder<T>}, {@code Coder.Context}, and value of type {@code * T}, the structural value is equal to the structural value yield by encoding and decoding the * original value, in any {@code Coder.Context}. */ public static <T> void structuralValueDecodeEncodeEqualInContext( Coder<T> coder, Coder.Context context, T value) throws Exception { assertEquals( coder.structuralValue(value), coder.structuralValue(decodeEncode(coder, context, value))); }
private CoderStructuralKey(Coder<K> coder, K key) throws Exception { this.coder = coder; this.structuralValue = coder.structuralValue(key); this.encoded = CoderUtils.encodeToByteArray(coder, key); }
@Override public Iterable<T> get(byte[] key, W window) { return windowToValues.get(windowCoder.structuralValue(window)); }
@Override public Iterable<T> get(byte[] key, W window) { return windowToValues.get(windowCoder.structuralValue(window)); }
/** * {@inheritDoc} * * @return a structural for a value of type {@code T} obtained by first converting to {@code * IntermediateT} and then obtaining a structural value according to the underlying coder. */ @Override public Object structuralValue(T value) { try { IntermediateT intermediate = toFn.apply(value); return coder.structuralValue(intermediate); } catch (Exception exn) { throw new IllegalArgumentException( "Unable to encode element '" + value + "' with coder '" + this + "'.", exn); } }
@Override public Iterable<V> get(byte[] keyBytes, W window) { K key; try { // TODO: We could skip decoding and just compare encoded values for deterministic keyCoders. key = keyCoder.decode(new ByteArrayInputStream(keyBytes)); } catch (IOException e) { throw new RuntimeException(e); } return collection.get( SideInputKey.of(keyCoder.structuralValue(key), windowCoder.structuralValue(window))); }
@Override public Iterable<V> get(byte[] keyBytes, W window) { K key; try { // TODO: We could skip decoding and just compare encoded values for deterministic keyCoders. key = keyCoder.decode(new ByteArrayInputStream(keyBytes)); } catch (IOException e) { throw new RuntimeException(e); } return collection.get( SideInputKey.of(keyCoder.structuralValue(key), windowCoder.structuralValue(window))); }
/** * Testing utilities below depend on standard assertions and matchers to compare elements read by * sources. In general the elements may not implement {@code equals}/{@code hashCode} properly, * however every source has a {@link Coder} and every {@code Coder} can produce a {@link * Coder#structuralValue} whose {@code equals}/{@code hashCode} is consistent with equality of * encoded format. So we use this {@link Coder#structuralValue} to compare elements read by * sources. */ public static <T> List<ReadableStructuralValue<T>> createStructuralValues( Coder<T> coder, List<T> list) throws Exception { List<ReadableStructuralValue<T>> result = new ArrayList<>(); for (T elem : list) { result.add(new ReadableStructuralValue<>(elem, coder.structuralValue(elem))); } return result; }
/** * Verifies that for the given {@code Coder<T>}, {@code Coder.Context}, and values of type {@code * T}, the structural values are equal if and only if the encoded bytes are equal, in any {@code * Coder.Context}. */ public static <T> void structuralValueConsistentWithEqualsInContext( Coder<T> coder, Coder.Context context, T value1, T value2) throws Exception { assertEquals( coder.structuralValue(value1).equals(coder.structuralValue(value2)), Arrays.equals(encode(coder, context, value1), encode(coder, context, value2))); }
@Override public Object structuralValue(@Nullable T value) { if (value == null) { return Optional.absent(); } return Optional.of(valueCoder.structuralValue(value)); }
@Test public void testStructuralValueSharesSameObject() { assertEquals(TEST_CODER.structuralValue(null), TEST_CODER.structuralValue(null)); // This is a minor performance optimization to not encode and compare empty byte // arrays. assertSame(TEST_CODER.structuralValue(null), TEST_CODER.structuralValue(null)); } }
@Override public Object structuralValue(KV<K, V> kv) { if (consistentWithEquals()) { return kv; } else { return KV.of( getKeyCoder().structuralValue(kv.getKey()), getValueCoder().structuralValue(kv.getValue())); } }
@Override public Object structuralValue(TimestampedValue<T> value) { Object structuralValue = valueCoder.structuralValue(value.getValue()); return TimestampedValue.of(structuralValue, value.getTimestamp()); }
private static <T> Iterable<Object> asStructural( final Iterable<T> iterable, final Coder<T> coder) { return StreamSupport.stream(iterable.spliterator(), false) .map( input -> { try { return coder.structuralValue(input); } catch (Exception e) { Assert.fail("Could not structural values."); throw new RuntimeException(); // to satisfy the compiler... } }) .collect(Collectors.toList()); }
@Override public Object structuralValue(Timer<T> value) { return Timer.of(value.getTimestamp(), payloadCoder.structuralValue(value.getPayload())); }
/** * Create a mutation detector for the provided {@code value}, using the provided {@link Coder} * for cloning and checking serialized forms for equality. */ public CodedValueMutationDetector(T value, Coder<T> coder) throws CoderException { this.coder = coder; // We need to clone the original value before getting it's structural value. // If the object is consistent with equals, the Structural value will be the // exact same object reference making it impossible to detect changes. clonedOriginalValue = CoderUtils.clone(coder, value); this.originalStructuralValue = coder.structuralValue(clonedOriginalValue); this.possiblyModifiedObject = value; this.encodedOriginalObject = CoderUtils.encodeToByteArray(coder, value); this.clonedOriginalObject = CoderUtils.decodeFromByteArray(coder, encodedOriginalObject); }