/* * Copyright (c) 2017 OBiBa. All rights reserved. * * This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.obiba.magma.support; import java.util.Map; import javax.annotation.Nullable; import javax.validation.constraints.NotNull; import org.obiba.magma.Datasource; import org.obiba.magma.NoSuchValueSetException; import org.obiba.magma.NoSuchValueTableException; import org.obiba.magma.Timestamps; import org.obiba.magma.Value; import org.obiba.magma.ValueTable; import org.obiba.magma.VariableEntity; import org.obiba.magma.transform.BijectiveFunction; import org.obiba.magma.type.DateTimeType; import org.obiba.magma.views.AbstractTransformingValueTableWrapper; import com.google.common.collect.Maps; /** * */ public class IncrementalValueTable extends AbstractTransformingValueTableWrapper { // private static final Logger log = LoggerFactory.getLogger(IncrementalValueTable.class); private final IncrementalFunction variableEntityMappingFunction; @Override public ValueTable getWrappedValueTable() { return sourceTable; } public static class Factory { private Factory() { } public static ValueTable create(@NotNull ValueTable sourceTable, @Nullable ValueTable destinationTable) { return destinationTable == null ? sourceTable : new IncrementalValueTable(sourceTable, destinationTable); } public static ValueTable create(ValueTable sourceTable, Datasource destinationDatasource) { ValueTable destinationTable = null; try { destinationTable = destinationDatasource.getValueTable(sourceTable.getName()); } catch(NoSuchValueTableException ignored) { } return create(sourceTable, destinationTable); } } @NotNull private final ValueTable sourceTable; @NotNull private final ValueTable destinationTable; private IncrementalValueTable(@NotNull ValueTable sourceTable, @NotNull ValueTable destinationTable) { this.sourceTable = sourceTable; this.destinationTable = destinationTable; variableEntityMappingFunction = new IncrementalFunction(); } @NotNull @Override public BijectiveFunction<VariableEntity, VariableEntity> getVariableEntityMappingFunction() { return variableEntityMappingFunction; } /** * <pre> * apply: source entity <b>older</b> than destination * unapply: source entity <b>newer</b> than destination * </pre> */ private class IncrementalFunction implements BijectiveFunction<VariableEntity, VariableEntity> { private final Map<VariableEntity, VariableEntity> applyCache = Maps.newHashMap(); @Override public VariableEntity apply(VariableEntity from) { if(applyCache.containsKey(from)) { //log.info("apply has cached: {}", from.getIdentifier()); return applyCache.get(from); } boolean newer = isSourceNewerThanDestination(from); VariableEntity entity = newer ? from : null; //log.info("View: {}, entity: {}, sourceIsNewer: {}, return {}", getName(), from, newer, entity); applyCache.put(from, entity); return entity; } @Override public VariableEntity unapply(VariableEntity from) { return from; } private boolean isSourceNewerThanDestination(VariableEntity from) { Timestamps sourceTimestamps = null; Value sourceLastUpdate = DateTimeType.get().nullValue(); Value destinationLastUpdate = DateTimeType.get().nullValue(); try { sourceTimestamps = getWrappedValueTable().getValueSetTimestamps(from); if(sourceTimestamps != null) sourceLastUpdate = sourceTimestamps.getLastUpdate(); } catch(NoSuchValueSetException ignored) { } Timestamps destinationTimestamps = null; try { destinationTimestamps = destinationTable.getValueSetTimestamps(from); if(destinationTimestamps != null) destinationLastUpdate = destinationTimestamps.getLastUpdate(); } catch(NoSuchValueSetException ignored) { } //log.info("{} - sourceLastUpdate: {}, destinationLastUpdate: {}", from, sourceLastUpdate, destinationLastUpdate); return sourceLastUpdate.isNull() || destinationLastUpdate.isNull() || sourceLastUpdate.compareTo(destinationLastUpdate) > 0; } } }