public Properties apply(final Properties state, final Properties properties) { if (null == state) { return properties; } propertiesTuple.setProperties(properties); stateTuple.setProperties(state); apply(stateTuple, propertiesTuple); return state; }
/** * Aggregates the element. Note - only the element properties are aggregated. * Aggregation requires elements to have the same identifiers and group. * * @param state the other element to aggregate. This is normally the 'state' where the aggregated results will be set. * @param element the element to aggregated * @return Element - the aggregated element */ public Element apply(final Element state, final Element element) { if (null == state) { return element; } apply(state.getProperties(), element.getProperties()); return state; }
@Test public void shouldAggregateWithNoPropertiesOrFunctions() { // Given final ElementAggregator aggregator = new ElementAggregator(); final Edge edge1 = new Edge.Builder().group("group").build(); final Edge edge2 = new Edge.Builder().group("group").build(); // When - aggregate and set state final Element result = aggregator.apply(edge1, edge2); // Then assertEquals(edge2, result); assertTrue(result.getProperties().isEmpty()); }
@Test public void shouldAggregatePropertiesWithMultipleSelection() { // Given final BinaryOperator<Tuple3<Integer, Integer, Integer>> maxMinRange = (t1, t2) -> new Tuple3<>( Math.max(t1.get0(), t2.get0()), Math.min(t1.get1(), t2.get1()), Math.max(t1.get0(), t2.get0()) - Math.min(t1.get1(), t2.get1()) ); final ElementAggregator aggregator = new ElementAggregator.Builder() .select("max", "min", "range") .execute(maxMinRange) .build(); final Properties properties1 = new Properties(); properties1.put("max", 10); properties1.put("min", 10); final Properties properties2 = new Properties(); properties2.put("max", 100); properties2.put("min", 100); final Properties properties3 = new Properties(); properties3.put("max", 1000); properties3.put("min", 1000); // When Properties state = aggregator.apply(properties1, properties2); state = aggregator.apply(state, properties3); // Then assertEquals(1000, state.get("max")); assertEquals(10, state.get("min")); assertEquals(1000 - 10, state.get("range")); }
@Test public void shouldAggregateWithTuple2BinaryOperator() { // Given final String property1 = "property 1"; final String property2 = "property 2"; final BinaryOperator func1 = new ExampleTuple2BinaryOperator(); final ElementAggregator aggregator = new ElementAggregator.Builder() .select(property1, property2) .execute(func1) .build(); final Properties props1 = new Properties(); props1.put(property1, 1); props1.put(property2, "value1"); final Properties props2 = new Properties(); props2.put(property1, 10); props2.put(property2, "value10"); final Properties props3 = new Properties(); props3.put(property1, 5); props3.put(property2, "value5"); // When Properties state = props1; state = aggregator.apply(state, props2); state = aggregator.apply(state, props3); // Then assertEquals(props2, state); }
@Test public void shouldAggregateProperties() { // Given final String reference = "reference1"; final Integer value1 = 1; final Integer value2 = 2; final Integer valueResult = 3; final BinaryOperator<Integer> function = mock(BinaryOperator.class); given(function.apply(value1, value2)).willReturn(valueResult); final ElementAggregator aggregator = new ElementAggregator.Builder() .select(reference) .execute(function) .build(); final Properties properties1 = new Properties(reference, value1); final Properties properties2 = new Properties(reference, value2); // When final Properties result = aggregator.apply(properties1, properties2); // Then assertEquals(valueResult, result.get(reference)); }
@Test public void shouldAggregatePropertiesWithMultipleOfFunctions() { // Given final BinaryOperator<Integer> max = Math::max; final BinaryOperator<Integer> min = Math::min; final ElementAggregator aggregator = new ElementAggregator.Builder() .select("max") .execute(max) .select("min") .execute(min) .build(); final Properties properties1 = new Properties(); properties1.put("max", 10); properties1.put("min", 10); final Properties properties2 = new Properties(); properties2.put("max", 100); properties2.put("min", 100); final Properties properties3 = new Properties(); properties3.put("max", 1000); properties3.put("min", 1000); // When Properties state = aggregator.apply(properties1, properties2); state = aggregator.apply(state, properties3); // Then assertEquals(1000, state.get("max")); assertEquals(10, state.get("min")); }
@Test public void shouldAggregateElementUsingMockBinaryOperator() { // Given final String reference = "reference1"; final Integer valueResult = 3; final BinaryOperator<Integer> function = mock(BinaryOperator.class); given(function.apply(1, 2)).willReturn(valueResult); final ElementAggregator aggregator = new ElementAggregator.Builder() .select(reference) .execute(function) .build(); final Edge edge1 = new Edge.Builder() .property(reference, 1) .build(); final Edge edge2 = new Edge.Builder() .property(reference, 2) .build(); // When final Element result = aggregator.apply(edge1, edge2); // Then assertEquals(valueResult, result.getProperty(reference)); }
@Test public void shouldAggregateElementUsingLambdaBinaryOperator() { // Given final String reference = "reference1"; final BinaryOperator<String> function = (a, b) -> a + "," + b; final ElementAggregator aggregator = new ElementAggregator.Builder() .select(reference) .execute(function) .build(); final Edge edge1 = new Edge.Builder() .property(reference, "value1") .build(); final Edge edge2 = new Edge.Builder() .property(reference, "value2") .build(); // When final Element result = aggregator.apply(edge1, edge2); // Then assertEquals("value1,value2", result.getProperty(reference)); }
@Test public void shouldAggregateElementUsingKorypheBinaryOperator() { // Given final String reference = "reference1"; final BinaryOperator<Integer> function = new KorypheBinaryOperator<Integer>() { @Override public Integer _apply(final Integer a, final Integer b) { return a + b; } }; final ElementAggregator aggregator = new ElementAggregator.Builder() .select(reference) .execute(function) .build(); final Edge edge1 = new Edge.Builder() .property(reference, 1) .build(); final Edge edge2 = new Edge.Builder() .property(reference, 2) .build(); // When final Element result = aggregator.apply(edge1, edge2); // Then assertEquals(3, result.getProperty(reference)); }
private Properties reduce(final Iterator<Properties> iter) { Properties state = null; Properties properties; while (iter.hasNext()) { properties = iter.next(); if (null != properties) { state = aggregator.apply(state, properties); } } return state; }
@Override public Properties reduce(final String group, final Key key, final Iterator<Properties> iter, final Set<String> groupBy, final ElementAggregator viewAggregator) { if (!iter.hasNext()) { return new Properties(); } final Properties properties = iter.next(); if (!iter.hasNext()) { return properties; } final ElementAggregator aggregator = schema.getElement(group).getQueryAggregator(groupBy, viewAggregator); Properties aggregatedProps = properties; while (iter.hasNext()) { aggregatedProps = aggregator.apply(aggregatedProps, iter.next()); } return aggregatedProps; }
public Properties apply(final Properties state, final Properties properties) { if (null == state) { return properties; } propertiesTuple.setProperties(properties); stateTuple.setProperties(state); apply(stateTuple, propertiesTuple); return state; }
/** * Aggregates the element. Note - only the element properties are aggregated. * Aggregation requires elements to have the same identifiers and group. * * @param state the other element to aggregate. This is normally the 'state' where the aggregated results will be set. * @param element the element to aggregated * @return Element - the aggregated element */ public Element apply(final Element state, final Element element) { if (null == state) { return element; } apply(state.getProperties(), element.getProperties()); return state; }
protected void reduceMultiValue(final KEY key, final Iterator<VALUE> iter, final VALUE firstValue, final Context context) throws IOException, InterruptedException { String group = null; try { group = getGroup(key, firstValue); final SchemaElementDefinition elementDef = schema.getElement(group); if (elementDef.isAggregate()) { Properties state; final ElementAggregator aggregator = elementDef.getIngestAggregator(); state = getValueProperties(key, firstValue, group); while (iter.hasNext()) { state = aggregator.apply(state, getValueProperties(key, iter.next(), group)); } context.write(key, createValue(key, firstValue, state, group)); } else { // The group has aggregation disabled - so write all values out. context.write(key, firstValue); while (iter.hasNext()) { context.write(key, iter.next()); } } } catch (final Exception e) { if (null == group) { group = "UNKNOWN"; } throw new RuntimeException("Failed to reduce values for group: " + group, e); } }
@Override public Element call(final Element v1, final Element v2) { if (null == gafferSchema) { gafferSchema = Schema.fromJson(jsonGafferSchema); } final ElementAggregator aggregator = gafferSchema.getElement(v2.getGroup()).getIngestAggregator(); return aggregator.apply(v1, v2); } }
aggregator = JSONSerialiser.deserialise(aggregatorJson, ElementAggregator.class); Properties mergedProperties = aggregator.apply(prop1, prop2); LOGGER.trace("Merged properties object after aggregation: {}", mergedProperties);
throw new AggregationException("Failed to recreate a graph element from a key and value", e); aggregatedProps = aggregator.apply(aggregatedProps, properties);