package org.radargun.stages.cache.generators; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.radargun.config.DefinitionElement; import org.radargun.config.Init; import org.radargun.config.Property; import org.radargun.logging.Log; import org.radargun.logging.LogFactory; /** * @author Matej Cimbora */ @DefinitionElement(name = "composed", doc = "Creates composed values (containing numeric and text values).") public class ComposedObjectGenerator implements ValueGenerator { private static Log log = LogFactory.getLog(ComposedObjectGenerator.class); @Property(doc = "Text generator.", complexConverter = ValueGenerator.ComplexConverter.class, optional = false) private SingleWordGenerator singleWordGenerator; @Property(doc = "Number generator.", complexConverter = ValueGenerator.ComplexConverter.class, optional = false) private NumberObjectGenerator numberObjectGenerator; @Property(doc = "Size of nested collection. Default is 3. If the value is smaller than 0, collection reference remains null.") private int nestedCollectionSize = 3; @Property(name = "class", doc = "Class instantiated by this generator. Default is 'org.radargun.query.ComposedObject'.") private String clazzName = "org.radargun.query.ComposedObject"; @Property(name = "textClass", doc = "Text object class instantiated by this generator. Default is 'org.radargun.query.TextObject'.") private String textObjectClassName = "org.radargun.query.TextObject"; @Property(name = "numberClass", doc = "Number object class instantiated by this generator. Default is 'org.radargun.query.NumberObject'.") private String numberObjectClassName = "org.radargun.query.NumberObject"; private Class<?> clazz; private Class<?> textObjectClass; private Class<?> numberObjectClass; private Constructor<?> ctor; @Init public void init() { try { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); textObjectClass = classLoader.loadClass(textObjectClassName); numberObjectClass = classLoader.loadClass(numberObjectClassName); clazz = classLoader.loadClass(clazzName); ctor = clazz.getConstructor(textObjectClass, numberObjectClass, List.class, List.class); } catch (Exception e) { // trace as this can happen on master node log.tracef(e, "Could not initialize generator %s", this); } } @Override public Object generateValue(Object key, int size, Random random) { Object textObject = singleWordGenerator.generateValue(key, size, random); Object numberObject = numberObjectGenerator.generateValue(key, size, random); List textObjectList = null; List numberObjectList = null; if (nestedCollectionSize >= 0) { textObjectList = new ArrayList(nestedCollectionSize); numberObjectList = new ArrayList(nestedCollectionSize); for (int i = 0; i < nestedCollectionSize; i++) { try { textObjectList.add(singleWordGenerator.generateValue(key, size, random)); numberObjectList.add(numberObjectGenerator.generateValue(key, size, random)); } catch (Exception e) { log.error("Failed to generate value", e); } } } return newInstance(textObject, numberObject, textObjectList, numberObjectList); } @Override public int sizeOf(Object value) { // FIXME return -1; } @Override public boolean checkValue(Object value, Object key, int expectedSize) { // FIXME return value.getClass().equals(clazz); } private Object newInstance(Object textObject, Object numberObject, List<?> textCollection, List<?> numberCollection) { if (ctor == null) throw new IllegalStateException("The generator was not properly initialized"); try { return ctor.newInstance(textObject, numberObject, textCollection, numberCollection); } catch (Exception e) { return new IllegalStateException(e); } } }