/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hazelcast.aggregation.impl; import com.hazelcast.aggregation.Aggregator; import com.hazelcast.query.impl.Extractable; import com.hazelcast.query.impl.getters.MultiResult; import java.util.List; import java.util.Map; /** * Abstract class providing convenience for concrete implementations of an {@link Aggregator} * It provides built-in extraction capabilities that may be used in the accumulation phase. * <p> * Extraction rules: * <ul> * <li>If the attributePath is not null and the input object is an instance of Extractable the value will be extracted * from the attributePath in the input object and accumulated instead of the whole input object. * </li> * <li>If the attributePath is null and the input object is an instance of Map.Entry the Map.Entry.getValue() will be * accumulated instead of the whole input object. * </li> * </ul> * * @param <I> input type * @param <E> extracted value type * @param <R> result type */ public abstract class AbstractAggregator<I, E, R> extends Aggregator<I, R> { protected String attributePath; public AbstractAggregator() { this(null); } public AbstractAggregator(String attributePath) { this.attributePath = attributePath; } @Override public final void accumulate(I entry) { E extractedValue = extract(entry); if (extractedValue instanceof MultiResult) { @SuppressWarnings("unchecked") List<E> results = ((MultiResult<E>) extractedValue).getResults(); for (E o : results) { accumulateExtracted(o); } } else { accumulateExtracted(extractedValue); } } /** * Extract the value of the given attributePath from the given entry. */ @SuppressWarnings("unchecked") private <T> T extract(I input) { if (attributePath == null) { if (input instanceof Map.Entry) { return (T) ((Map.Entry) input).getValue(); } } else if (input instanceof Extractable) { return (T) ((Extractable) input).getAttributeValue(attributePath); } throw new IllegalArgumentException("Can't extract " + attributePath + " from the given input"); } /** * Accumulates a single extracted value. * This method may be called multiple times per accumulated entry if the attributePath contains [any] operator. * * @param value If attributePath is not null the methods accumulates the value extracted from the attributePath. * If attributePath is null and the input object is a Map.Entry the method accumulates Map.Entry.getValue(). * Otherwise the method accumulates the input value as-is. */ protected abstract void accumulateExtracted(E value); }