/******************************************************************************* * Copyright (c) 2010 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.databoard.binding.util; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Random; import java.util.WeakHashMap; import org.simantics.databoard.Bindings; import org.simantics.databoard.Datatypes; import org.simantics.databoard.adapter.AdaptException; import org.simantics.databoard.binding.ArrayBinding; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.Binding.Visitor; import org.simantics.databoard.binding.BooleanBinding; import org.simantics.databoard.binding.ByteBinding; import org.simantics.databoard.binding.DoubleBinding; import org.simantics.databoard.binding.FloatBinding; import org.simantics.databoard.binding.IntegerBinding; import org.simantics.databoard.binding.LongBinding; import org.simantics.databoard.binding.MapBinding; import org.simantics.databoard.binding.OptionalBinding; import org.simantics.databoard.binding.RecordBinding; import org.simantics.databoard.binding.StringBinding; import org.simantics.databoard.binding.UnionBinding; import org.simantics.databoard.binding.VariantBinding; import org.simantics.databoard.binding.error.BindingConstructionException; import org.simantics.databoard.binding.error.BindingException; import org.simantics.databoard.binding.error.RuntimeBindingConstructionException; import org.simantics.databoard.binding.error.RuntimeBindingException; import org.simantics.databoard.binding.factory.BindingScheme; import org.simantics.databoard.binding.factory.MutableBindingFactory; import org.simantics.databoard.type.ArrayType; import org.simantics.databoard.type.BooleanType; import org.simantics.databoard.type.ByteType; import org.simantics.databoard.type.Component; import org.simantics.databoard.type.Datatype; import org.simantics.databoard.type.DoubleType; import org.simantics.databoard.type.FloatType; import org.simantics.databoard.type.IntegerType; import org.simantics.databoard.type.LongType; import org.simantics.databoard.type.MapType; import org.simantics.databoard.type.OptionalType; import org.simantics.databoard.type.RecordType; import org.simantics.databoard.type.StringType; import org.simantics.databoard.type.UnionType; import org.simantics.databoard.type.VariantType; import org.simantics.databoard.util.Limit; import org.simantics.databoard.util.Range; /** * Visitor that creates a instance with random value. * This visitor may throw RuntimeBindingException. * * Type Value * ------------------------------------------------------ * Boolean false/true * Byte, Integer, Long value between limits * Float, Double 0..1 if no range, otherwise a valid value in range * String random string of length [0..1024] * Optional novalue / random value * Union random tag / random value * Record each field with random value * Array random elements between 0..1024 unless lower bound is higher * Map 0..1024 random entries with random keys and value * Variant random type (excluding variant) with random value * * TODO Create String according to the pattern * @author Toni Kalajainen */ public class RandomValue implements Visitor { public boolean refereableRecords = true; public Random random; /** Map of default values already created. Used to link back to recursive records */ Map map = new WeakHashMap(1); BindingScheme scheme = new MutableBindingFactory( new HashMap() ); static String CHARS = "abcdefghijklmnopqrstuvwxyz ,.-'/-+ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!\"#�%&/()=\n\\\\r'"; public RandomValue() { this.random = new Random(); } public RandomValue(Random random) { this.random = random; } public RandomValue(int seed) { this.random = new Random(seed); } public Random getRandom() { return random; } @Override public Object visit(ArrayBinding b) { Object result = pickCached() ? map.get(b) : null; if (result!=null) return result; ArrayType at = b.type(); long min = at.minLength(); long max = Math.max(min, Math.min(32, at.maxLength())); int c = (int) (min + nextRandom(max-min+1)); Binding componentBinding = b.getComponentBinding(); Object[] array = new Object[c]; for (int i=0; iresult.maxValue()) result.setRange( (Range) null ); return result; } if (tag==2) { Limit lowerLimit = Limit.inclusive(0); Limit upperLimit = Limit.exclusive(random.nextInt()); Range range = random.nextBoolean() ? Range.between(lowerLimit, upperLimit) : null; IntegerType result = new IntegerType(null, range); if (result.minValue()>result.maxValue()) result.setRange( (Range) null ); return result; } if (tag==3) { Limit lowerLimit = Limit.inclusive(0); Limit upperLimit = Limit.exclusive(random.nextLong()); Range range = random.nextBoolean() ? Range.between(lowerLimit, upperLimit) : null; LongType result = new LongType(null, range); if (result.minValue()>result.maxValue()) result.setRange( (Range) null ); return result; } if (tag==4) { Limit lowerLimit = Limit.inclusive(0); Limit upperLimit = Limit.exclusive(random.nextDouble() * random.nextInt()); Range range = random.nextBoolean() ? Range.between(lowerLimit, upperLimit) : null; FloatType result = new FloatType(null, range); if (result.minValue()>result.maxValue()) result.setRange( (Range) null ); return result; } if (tag==5) { Limit lowerLimit = Limit.inclusive(0); Limit upperLimit = Limit.exclusive(random.nextDouble() * random.nextInt()); Range range = random.nextBoolean() ? Range.between(lowerLimit, upperLimit) : null; DoubleType result = new DoubleType(null, range); if (result.minValue()>result.maxValue()) result.setRange( (Range) null ); return result; } if (tag==6) { Limit lowerLimit = Limit.inclusive(0); Limit upperLimit = Limit.exclusive(random.nextInt(1024)); Range range = random.nextBoolean() ? Range.between(lowerLimit, upperLimit) : null; StringType result = new StringType(null, null, range); if (result.minLength()>result.maxLength()) result.setLength( (Range) null ); return result; } if (tag==7) { int c = random.nextInt(16); Component[] components = new Component[c]; String[] names = randomUniqueNames(c); for (int i=0; iresult.maxLength()) result.setLength( (Range) null ); return result; } if (tag==9) { return new MapType(randomType(depth+1, maxDepth), randomType(depth+1, maxDepth)); } if (tag==10) { return new OptionalType( randomType(depth+1, maxDepth) ); } if (tag==11) { int c = random.nextInt(16)+1; Component[] components = new Component[c]; String[] names = randomUniqueNames(c); for (int i=0; icount unique random names. * * @param count * @return */ String[] randomUniqueNames(int count) { HashSet result = new HashSet(count); for (int i=0; i