/* * 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 org.obiba.magma.Value; import org.obiba.magma.ValueSet; import org.obiba.magma.ValueSource; import org.obiba.magma.Variable; import org.obiba.magma.support.Initialisables; import org.obiba.magma.type.DecimalType; import org.obiba.magma.type.IntegerType; class NumericValueGenerator extends AbstractMissingValueVariableValueGenerator { private static final long MIN_VALUE = 0; private static final long MAX_VALUE = 100; private final ValueSource minimum; private final ValueSource maximum; private final ValueSource mean; private final ValueSource stddev; NumericValueGenerator(Variable variable) { super(variable); minimum = makeSource(variable, "minimum", "min"); maximum = makeSource(variable, "maximum", "max"); mean = makeSource(variable, DecimalType.get(), "mean"); stddev = makeSource(variable, DecimalType.get(), "stddev", "stdev"); Initialisables.initialise(minimum, maximum, mean, stddev); } @Override protected Value nonMissingValue(Variable variable, GeneratedValueSet gvs) { return getInteger(gvs, getMinimum(gvs), getMaximum(gvs)); } protected Value getInteger(GeneratedValueSet gvs, Number min, Number max) { Value meanValue = getMeanValue(gvs); Value stddevValue = getStdDevValue(gvs); if(meanValue.isNull() || stddevValue.isNull()) { if(getValueType() == IntegerType.get()) { return getValueType() .valueOf(min.equals(max) ? min : gvs.dataGenerator.nextLong(min.longValue(), max.longValue())); } if(getValueType() == DecimalType.get()) { return getValueType() .valueOf(min.equals(max) ? min : gvs.dataGenerator.nextUniform(min.doubleValue(), max.doubleValue())); } throw new IllegalStateException(); } double value = gvs.dataGenerator .nextGaussian(((Number) meanValue.getValue()).doubleValue(), ((Number) stddevValue.getValue()).doubleValue()); // Make sure value is between absolute min and max value = Math.min(value, max.doubleValue()); value = Math.max(value, min.doubleValue()); return getValueType().valueOf(value); } private ValueSource makeSource(Variable variable, String... scriptAttributes) { return makeSource(variable, variable.getValueType(), scriptAttributes); } private Number getMinimum(ValueSet valueSet) { try { Value minimumValue = minimum.getValue(valueSet); return minimumValue.isNull() ? MIN_VALUE : (Number) minimumValue.getValue(); } catch(Exception ignored) { return MIN_VALUE; } } private Number getMaximum(ValueSet valueSet) { try { Value maximumValue = maximum.getValue(valueSet); return maximumValue.isNull() ? MAX_VALUE : (Number) maximumValue.getValue(); } catch(Exception ignored) { return MAX_VALUE; } } private Value getMeanValue(ValueSet valueSet) { try { Value meanValue = mean.getValue(valueSet); if (!meanValue.isNull()) return meanValue; Number min = getMinimum(valueSet); Number max = getMaximum(valueSet); double meanDouble = (min.longValue() + max.longValue())/2; return DecimalType.get().valueOf(new Double(meanDouble)); } catch(Exception e) { return mean.getValueType().nullValue(); } } private Value getStdDevValue(ValueSet valueSet) { try { return stddev.getValue(valueSet); } catch(Exception e) { return stddev.getValueType().nullValue(); } } }