/* * (c) Copyright 2009-2011 by Volker Bergmann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, is permitted under the terms of the * GNU General Public License. * * For redistributing this software or a derivative work under a license other * than the GPL-compatible Free Software License as defined by the Free * Software Foundation or approved by OSI, you must first obtain a commercial * license to this software product from Volker Bergmann. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS, * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.databene.benerator.sample; import java.util.HashMap; import java.util.Map; import org.databene.benerator.Generator; import org.databene.benerator.GeneratorContext; import org.databene.benerator.IllegalGeneratorStateException; import org.databene.benerator.InvalidGeneratorSetupException; import org.databene.benerator.util.UnsafeNonNullGenerator; import org.databene.benerator.wrapper.ProductWrapper; import org.databene.commons.ConfigurationError; import org.databene.commons.ParseException; import org.databene.commons.StringUtil; import org.databene.script.DatabeneScriptParser; import org.databene.script.WeightedTransition; /** * Generates states as configured by a state machine.<br/> * <br/> * Created at 17.07.2009 05:41:47 * @since 0.6.0 * @author Volker Bergmann */ public class StateGenerator<E> extends UnsafeNonNullGenerator<E> { private Class<E> generatedType; private Map<E, AttachedWeightSampleGenerator<E>> transitionsGenerators; private E nextState; // initialization -------------------------------------------------------------------------------------------------- public StateGenerator() { this((String) null); } @SuppressWarnings("unchecked") public StateGenerator(String transitionSpec) { this((Class<E>) Object.class); setTransitions(transitionSpec); } public StateGenerator(Class<E> generatedType) { this.generatedType = generatedType; this.transitionsGenerators = new HashMap<E, AttachedWeightSampleGenerator<E>>(); this.nextState = null; } @SuppressWarnings("unchecked") public void setTransitions(String transitionSpec) { if (StringUtil.isEmpty(transitionSpec)) { transitionsGenerators.clear(); return; } try { WeightedTransition[] ts = DatabeneScriptParser.parseTransitionList(transitionSpec); for (WeightedTransition t : ts) addTransition((E) t.getFrom(), (E) t.getTo(), t.getWeight()); } catch (ParseException e) { throw new ConfigurationError("Error parsing state machine specification: " + transitionSpec, e); } } public void addTransition(E from, E to, double weight) { AttachedWeightSampleGenerator<E> subGenerator = transitionsGenerators.get(from); if (subGenerator == null) { subGenerator = new AttachedWeightSampleGenerator<E>(generatedType); transitionsGenerators.put(from, subGenerator); } subGenerator.addSample(to, weight); } // Generator interface implementation ------------------------------------------------------------------------------ public Class<E> getGeneratedType() { return generatedType; } @Override public void init(GeneratorContext context) throws InvalidGeneratorSetupException { assertNotInitialized(); boolean hasEndTransition = false; for (AttachedWeightSampleGenerator<E> tmp : transitionsGenerators.values()) if (tmp.containsSample(null)) { hasEndTransition = true; break; } if (!hasEndTransition) throw new InvalidGeneratorSetupException("No final state defined for " + this); for (Generator<E> tmp : transitionsGenerators.values()) tmp.init(context); AttachedWeightSampleGenerator<E> gen = this.transitionsGenerators.get(null); nextState = gen.generate(getResultWrapper()).unwrap(); super.init(context); } @Override public E generate() { if (nextState == null) return null; E result = nextState; AttachedWeightSampleGenerator<E> transitionGenerator = transitionsGenerators.get(nextState); ProductWrapper<E> wrapper = transitionGenerator.generate(getResultWrapper()); nextState = (wrapper != null ? wrapper.unwrap() : null); return result; } @Override public void reset() throws IllegalGeneratorStateException { AttachedWeightSampleGenerator<E> transitionGenerator = this.transitionsGenerators.get(null); ProductWrapper<E> wrapper = transitionGenerator.generate(getResultWrapper()); nextState = (wrapper != null ? wrapper.unwrap() : null); super.reset(); } @Override public void close() { super.close(); } // java.lang.Object overrides -------------------------------------------------------------------------------------- @Override public String toString() { return getClass().getSimpleName() + transitionsGenerators; } }