/* (C) ActiveViam 2020
* ALL RIGHTS RESERVED. This material is the CONFIDENTIAL and PROPRIETARY
* property of ActiveViam Ltd. Any unauthorized use,
* reproduction or transfer of this material is strictly prohibited
*/
package com.activeviam.biz.pivot.filtering.impl;
import com.activeviam.activepivot.core.ext.api.postprocessing.fwk.AAdvancedPostProcessor;
import com.activeviam.activepivot.core.ext.api.postprocessing.fwk.APrefetcher;
import com.activeviam.activepivot.core.impl.api.cube.hierarchy.HierarchiesUtil;
import com.activeviam.activepivot.core.impl.api.location.LocationUtil;
import com.activeviam.activepivot.core.intf.api.contextvalues.subcube.ICubeFilter;
import com.activeviam.activepivot.core.intf.api.cube.hierarchy.IAxisHierarchy;
import com.activeviam.activepivot.core.intf.api.cube.hierarchy.IAxisMember;
import com.activeviam.activepivot.core.intf.api.cube.metadata.ILevelInfo;
import com.activeviam.activepivot.core.intf.api.location.ILocation;
import com.activeviam.activepivot.core.intf.api.postprocessing.IAdvancedAggregatesRetriever;
import com.activeviam.activepivot.core.intf.api.postprocessing.IAggregatesRetrievalResult;
import com.activeviam.activepivot.core.intf.api.postprocessing.IPostProcessor;
import com.activeviam.activepivot.core.intf.api.postprocessing.IPostProcessorCreationContext;
import com.activeviam.activepivot.core.intf.api.postprocessing.IPrefetcher;
import com.activeviam.database.api.types.ILiteralType;
import com.activeviam.tech.core.api.exceptions.ActiveViamException;
import com.activeviam.tech.core.api.filtering.impl.InCondition;
import com.activeviam.tech.core.api.registry.AtotiExtendedPluginValue;
import com.activeviam.tech.core.internal.util.ArrayUtil;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
/**
* <b>TrendPostProcessor</b><br>
* TrendPostProcessor does the difference between today and the day before if no measure retrieved
* from the day before then return null.
*
* @author ActiveViam
*/
@AtotiExtendedPluginValue(intf = IPostProcessor.class, key = TrendPostProcessor.PLUGIN_KEY)
public class TrendPostProcessor extends AAdvancedPostProcessor {
protected static final long serialVersionUID = 2722596108421670864L;
public static final String PLUGIN_KEY = "TREND";
public static final String LEVEL_DESCRIPTION_PROPERTY = "LEVEL";
public static final String HIERARCHY_DESCRIPTION_PROPERTY = "HIERARCHY";
protected static final String INCLUDE_PREFETCHER = "INCLUDE_PREFETCHER";
protected ILevelInfo levelInfo = null;
protected IAxisHierarchy hierarchy = null;
public TrendPostProcessor(
final String name, final IPostProcessorCreationContext creationContext) {
super(name, creationContext);
}
@Override
public void init(final Properties properties) throws ActiveViamException {
properties.setProperty(OUTPUT_TYPE_PROPERTY, ILiteralType.DOUBLE);
super.init(properties);
final String levelDescription = properties.getProperty(LEVEL_DESCRIPTION_PROPERTY);
this.levelInfo = HierarchiesUtil.getLevel(getActivePivot(), levelDescription);
// get the IHierarchy needed instance
final String hierarchyDescription = properties.getProperty(HIERARCHY_DESCRIPTION_PROPERTY);
this.hierarchy =
(IAxisHierarchy) HierarchiesUtil.getHierarchy(getActivePivot(), hierarchyDescription);
}
@Override
protected List<IPrefetcher<?>> initializePrefetchers(final Properties properties) {
return ArrayUtil.mutableList(
new APrefetcher(INCLUDE_PREFETCHER, this.measuresProvider) {
@Override
protected Collection<String> computeMeasures(final ILocation location) {
return underlyingMeasures;
}
@Override
protected Collection<ILocation> computeLocations(final ILocation location) {
return List.of(TrendPostProcessor.this.computeLocation(location));
}
@Override
protected ICubeFilter computeFilter(
final ILocation location, final ICubeFilter queryFilter) {
return TrendPostProcessor.this.computeFilter(location, queryFilter);
}
});
}
protected ICubeFilter computeFilter(final ILocation location, final ICubeFilter queryFilter) {
final Object value = LocationUtil.getCoordinate(location, levelInfo);
ICubeFilter filter = queryFilter;
if (value == null) {
// we deal with a range location here, we add all the required
// members and edit the filter
final List<? extends IAxisMember> members =
queryFilter.retrieveMembers(hierarchy, levelInfo.getOrdinal());
final Set<Date> membersToInclude = new HashSet<>();
for (final IAxisMember member : members) {
final Date date = (Date) member.getDiscriminator();
membersToInclude.add(date);
membersToInclude.add(TrainingUtils.retrievePreviousDate(date));
}
filter =
queryFilter
.edit()
.includeMembersWithConditions(
hierarchy.getHierarchyInfo().getIdentifier(), new InCondition(membersToInclude))
.build();
}
return filter;
}
protected ILocation computeLocation(final ILocation location) {
final Object value = LocationUtil.getCoordinate(location, levelInfo);
if (value instanceof Date) {
// we deal with a point location here
// build range location with previous date,
// use a Set having current and previous dates
final Set<Object> dates = new HashSet<>();
dates.add(value);
dates.add(TrainingUtils.retrievePreviousDate((Date) value));
return createModifiedLocation(location, dates);
}
// nothing to do here as we deal with a range location
return location;
}
protected ILocation createModifiedLocation(final ILocation location, final Object membersToAdd) {
if (LocationUtil.isAtLevel(location, levelInfo)) {
final Object[] newMembers = LocationUtil.copyPath(location, levelInfo.getHierarchyInfo());
newMembers[levelInfo.getOrdinal()] = membersToAdd;
return LocationUtil.createModifiedLocation(
location, levelInfo.getHierarchyInfo(), newMembers);
}
return location;
}
@Override
public void compute(final ILocation location, final IAdvancedAggregatesRetriever retriever) {
final IAggregatesRetrievalResult results = retriever.retrieveAggregates(INCLUDE_PREFETCHER);
final int measureForResults = results.getMeasureId(underlyingMeasures.get(0));
results.forEachPoint(
new int[] {measureForResults},
(pointReader, rowId) -> {
final int rowIdPrevious = results.getRow(retrievePreviousDateLocation(pointReader));
final Double currentValue;
final Double previousValue;
if (rowIdPrevious != -1) { // -1 if the point does not exist
currentValue = (Double) results.read(rowId, measureForResults);
previousValue = (Double) results.read(rowIdPrevious, measureForResults);
if (currentValue != null && previousValue != null) {
retriever.write(retriever.addPoint(pointReader), currentValue - previousValue);
}
}
return true;
});
}
protected ILocation retrievePreviousDateLocation(final ILocation currentLocation) {
final Date currentDate = (Date) LocationUtil.getCoordinate(currentLocation, levelInfo);
return createModifiedLocation(currentLocation, TrainingUtils.retrievePreviousDate(currentDate));
}
@Override
public String getType() {
return PLUGIN_KEY;
}
}