/*
* 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.datasource.generated;
import java.util.*;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import com.google.common.collect.*;
import org.apache.commons.math3.random.JDKRandomGenerator;
import org.apache.commons.math3.random.RandomGenerator;
import org.obiba.magma.Datasource;
import org.obiba.magma.NoSuchValueSetException;
import org.obiba.magma.NoSuchVariableException;
import org.obiba.magma.Timestamps;
import org.obiba.magma.Value;
import org.obiba.magma.ValueSet;
import org.obiba.magma.ValueTable;
import org.obiba.magma.Variable;
import org.obiba.magma.VariableEntity;
import org.obiba.magma.VariableValueSource;
import org.obiba.magma.support.VariableEntityBean;
import org.obiba.magma.type.DateTimeType;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
public class GeneratedValueTable implements ValueTable {
private final Datasource datasource;
private final Set<Variable> dictionary;
private final Set<VariableEntity> entities;
private final RandomGenerator randomGenerator;
private final Map<String, VariableValueSource> generators;
@NotNull
private final Value timestamp;
public GeneratedValueTable(@Nullable Datasource ds, Collection<Variable> dictionary, int entities) {
this(ds, dictionary, entities, System.currentTimeMillis());
}
public GeneratedValueTable(@Nullable Datasource ds, Collection<Variable> dictionary, int entities, long seed) {
datasource = ds;
this.dictionary = ImmutableSet.copyOf(dictionary);
this.entities = Sets.newTreeSet();
randomGenerator = new JDKRandomGenerator();
randomGenerator.setSeed(seed);
timestamp = DateTimeType.get().now();
while(this.entities.size() < entities) {
VariableEntity entity = generateEntity();
if(!this.entities.contains(entity)) this.entities.add(entity);
}
VariableValueGeneratorFactory factory = new DefaultVariableValueGeneratorFactory();
generators = Maps.newHashMap();
for(Variable v : this.dictionary) {
generators.put(v.getName(), factory.newGenerator(v));
}
}
@NotNull
@Override
public Datasource getDatasource() {
return datasource;
}
@Override
public String getEntityType() {
return dictionary.iterator().next().getEntityType();
}
@NotNull
@Override
public String getName() {
return "generated";
}
@NotNull
@Override
public Timestamps getTimestamps() {
return new Timestamps() {
@NotNull
@Override
public Value getLastUpdate() {
return timestamp;
}
@NotNull
@Override
public Value getCreated() {
return timestamp;
}
};
}
@Override
public Value getValue(Variable variable, ValueSet valueSet) {
return getVariableValueSource(variable.getName()).getValue(valueSet);
}
@Override
public ValueSet getValueSet(VariableEntity entity) throws NoSuchValueSetException {
if(entities.contains(entity)) {
return new GeneratedValueSet(this, entity);
}
throw new NoSuchValueSetException(this, entity);
}
@Override
public boolean canDropValueSets() {
return false;
}
@Override
public void dropValueSets() {
}
@Override
public Timestamps getValueSetTimestamps(VariableEntity entity) throws NoSuchValueSetException {
return getValueSet(entity).getTimestamps();
}
@Override
public Iterable<Timestamps> getValueSetTimestamps(SortedSet<VariableEntity> entities) {
return Iterables.transform(entities, new Function<VariableEntity, Timestamps>() {
@Nullable
@Override
public Timestamps apply(@Nullable VariableEntity input) {
return getValueSetTimestamps(input);
}
});
}
@Override
public Iterable<ValueSet> getValueSets() {
return getValueSets(entities);
}
@Override
public Iterable<ValueSet> getValueSets(Iterable<VariableEntity> entities) {
List<ValueSet> valueSets = Lists.newArrayList();
for (VariableEntity entity : entities) {
valueSets.add(new GeneratedValueSet(GeneratedValueTable.this, entity));
}
return valueSets;
}
@Override
public Variable getVariable(final String name) throws NoSuchVariableException {
try {
return Iterables.find(getVariables(), new Predicate<Variable>() {
@Override
public boolean apply(Variable input) {
return input.getName().equals(name);
}
});
} catch(NoSuchElementException e) {
throw new NoSuchVariableException(getName(), name);
}
}
@Override
public Set<VariableEntity> getVariableEntities() {
return Collections.unmodifiableSet(entities);
}
@Override
public int getVariableEntityCount() {
return Iterables.size(getVariableEntities());
}
@Override
public VariableValueSource getVariableValueSource(String variableName) throws NoSuchVariableException {
return generators.get(variableName);
}
@Override
public Iterable<Variable> getVariables() {
return dictionary;
}
@Override
public boolean hasValueSet(VariableEntity entity) {
return entities.contains(entity);
}
@Override
public boolean hasVariable(String name) {
return generators.containsKey(name);
}
@Override
public boolean isForEntityType(String entityType) {
return getEntityType().equalsIgnoreCase(entityType);
}
private VariableEntity generateEntity() {
return generateEntity(randomGenerator.nextInt(99999999), 8);
}
private VariableEntity generateEntity(long seed, int length) {
StringBuilder id = new StringBuilder(Long.toString(Math.abs(seed)));
while(id.length() < length) {
id.append(0).append(id);
}
return new VariableEntityBean(getEntityType(), id.toString());
}
@Override
public boolean isView() {
return false;
}
@Override
public String getTableReference() {
return (datasource == null ? "" : datasource.getName()) + "." + getName();
}
@Override
public int getVariableCount() {
return Iterables.size(getVariables());
}
@Override
public int getValueSetCount() {
return Iterables.size(getValueSets());
}
}