public abstract class SequenceParameter {

    private final int initialPosition;
    private final int finalPosition;
    private final int value;

    protected SequenceParameter(int initialPosition, int finalPosition, int value) {
        this.initialPosition = initialPosition;
        this.finalPosition = finalPosition;
        this.value = value;
    }

    public int getInitialPosition() {
        return initialPosition;
    }

    public int getFinalPosition() {
        return finalPosition;
    }

    public int getValue() {
        return value;
    }

} public abstract class SimulationBuilder<A extends State, O extends Combination, N extends Transition, R extends Rule,
        E extends Cell, C extends CellularAutomaton, T extends Time, S extends Space, U extends Universe, I extends Simulation> {

    private final SimulationParameter simulationParameter;

    protected SimulationBuilder(SimulationParameter simulationParameter) {
        this.simulationParameter = simulationParameter;
    }

    public SimulationParameter getSimulationParameter() {
        return simulationParameter;
    }

    public I build() throws SimulationBuilderException {
        try {
            List<A> states = buildStates();
            List<O> combinations = buildCombinations(states);
            List<N> transitions = buildTransitions(states, combinations);
            R rule = buildRule(transitions);
            C cellularAutomaton = buildCellularAutomaton(rule);
            T time = buildTime();
            List<E> initialCondition = buildInitialCondition(states);
            S space = buildSpace(time, initialCondition);
            U universe = buildUniverse(space, time);
            return buildSimulation(universe, cellularAutomaton);
        } catch (InvalidStateException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidCombinationException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidTransitionException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidRuleException e) {
            throw new SimulationBuilderException(e);
        } catch (CloneNotSupportedException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidAbsoluteTimeLimitException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidRelativeTimeLimitException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidDimensionalAmountException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidInitialConditionException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidDimensionalSpaceException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidSpaceException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidTimeException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidUniverseException e) {
            throw new SimulationBuilderException(e);
        } catch (InvalidCellularAutomataException e) {
            throw new SimulationBuilderException(e);
        }
    }

    public abstract List<A> buildStates();

    public abstract List<O> buildCombinations(List<A> states) throws InvalidStateException;

    public abstract List<N> buildTransitions(List<A> states, List<O> combinations)
            throws InvalidCombinationException, InvalidStateException;

    public abstract R buildRule(List<N> transitions) throws InvalidTransitionException;

    public abstract C buildCellularAutomaton(R rule) throws InvalidRuleException;

    public abstract T buildTime()
            throws CloneNotSupportedException, InvalidAbsoluteTimeLimitException, InvalidRelativeTimeLimitException;

    public abstract List<E> buildInitialCondition(List<A> states) throws InvalidStateException;

    public abstract S buildSpace(T time, List<E> initialCondition) throws InvalidDimensionalAmountException,
            InvalidInitialConditionException, InvalidDimensionalSpaceException;

    public abstract U buildUniverse(S space, T time) throws InvalidSpaceException, InvalidTimeException;

    public abstract I buildSimulation(U universe, C cellularAutomaton)
            throws InvalidUniverseException, InvalidCellularAutomataException;

} public abstract class SimulationParameter {

    private final RuleTypeParameter ruleTypeParameter;
    private final RuleConfigurationParameter ruleConfigurationParameter;
    private final LimitsParameter limitsParameter;
    private final InitialConditionParameter initialConditionParameter;

    protected SimulationParameter(RuleTypeParameter ruleTypeParameter,
                                  RuleConfigurationParameter ruleConfigurationParameter, LimitsParameter limitsParameter,
                                  InitialConditionParameter initialConditionParameter) throws InvalidSimulationParameterException {
        this.ruleTypeParameter = ruleTypeParameter;
        this.ruleConfigurationParameter = ruleConfigurationParameter;
        this.limitsParameter = limitsParameter;
        this.initialConditionParameter = initialConditionParameter;
        validate();
    }

    public RuleTypeParameter getRuleTypeParameter() {
        return ruleTypeParameter;
    }

    public RuleConfigurationParameter getRuleConfigurationParameter() {
        return ruleConfigurationParameter;
    }

    public LimitsParameter getLimitsParameter() {
        return limitsParameter;
    }

    public InitialConditionParameter getInitialConditionParameter() {
        return initialConditionParameter;
    }

    public void validate() throws InvalidSimulationParameterException {
        validateRuleType();
        validateRuleConfiguration();
        validateLimits();
        validateInitialCondition();
    }

    protected abstract void validateRuleType() throws InvalidSimulationParameterException;

    protected abstract void validateRuleConfiguration() throws InvalidSimulationParameterException;

    protected abstract void validateLimits() throws InvalidSimulationParameterException;

    protected abstract void validateInitialCondition() throws InvalidSimulationParameterException;

} public class InvalidAbsoluteTimeLimitException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = 8503779819489685979L;

} public class InvalidCellularAutomataException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = -4104738409967924193L;

} public class InvalidCombinationException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = 884762124844706448L;

} public class InvalidDimensionalAmountException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = 1514291655215196494L;

} public class InvalidDimensionalSpaceException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = -859556206406629948L;

} public class InvalidInitialConditionException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = 3070196019858178183L;

} public class InvalidRelativeTimeLimitException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = -8421027467680752602L;

} public class InvalidRuleException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = 5840928619484335072L;

} public class InvalidSpaceException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = 9045617613507195324L;

} public class InvalidStateException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = -7435119307025647318L;

} public class InvalidTimeException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = 4810377526354040415L;

} public class InvalidTransitionException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = 1848434169756515614L;

} public class InvalidUniverseException extends Exception {

    /**
     * Serialization management
     */
    private static final long serialVersionUID = -5140302667570723804L;

} public final class UnidimensionalCellularAutomaton extends CellularAutomaton<UnidimensionalGeneralRule,
        UnidimensionalSpace, UnidimensionalTime, UnidimensionalCombination, UnidimensionalTransition> {

    public UnidimensionalCellularAutomaton(UnidimensionalGeneralRule rule) throws InvalidRuleException {
        super(rule);
    }

} public final class UnidimensionalCombination extends Combination<UnidimensionalState> {

    public UnidimensionalCombination(UnidimensionalState reference, UnidimensionalState... neighbors) throws InvalidStateException {
        super(reference, neighbors);
    }

} public final class UnidimensionalGeneralRule extends Rule<UnidimensionalState, UnidimensionalTransition, UnidimensionalCombination> {

    public UnidimensionalGeneralRule(UnidimensionalTransition... transitions) throws InvalidTransitionException {
        super(transitions);
    }

} public final class UnidimensionalState extends State {

    public UnidimensionalState(String name, int value) {
        super(name, value);
    }

} public final class UnidimensionalTransition extends Transition<UnidimensionalCombination, UnidimensionalState> {

    public UnidimensionalTransition(UnidimensionalCombination combination, UnidimensionalState state)
            throws InvalidCombinationException, InvalidStateException {
        super(combination, state);
    }

} public final class UnidimensionalCell extends Cell<UnidimensionalState, UnidimensionalTransition> {

    public UnidimensionalCell(UnidimensionalTransition transition) throws InvalidTransitionException {
        super(transition);
    }

    public UnidimensionalCell(UnidimensionalState state) throws InvalidStateException {
        super(state);
    }

} public final class UnidimensionalSpace extends Space<UnidimensionalCell, UnidimensionalTime, UnidimensionalTransition, UnidimensionalCombination> {

    public UnidimensionalSpace(UnidimensionalTime time, List<UnidimensionalCell> initialCondition) throws InvalidDimensionalAmountException,
            InvalidInitialConditionException, InvalidDimensionalSpaceException {
        super(time, initialCondition, true);
    }

    @Override
    protected UnidimensionalCombination getCombination(UnidimensionalTime time, List<UnidimensionalCell> space) throws InvalidStateException {
        final int referencePosition = time.getRelative().get(0).getAbsolute();
        final int lastPosition = time.getRelative().get(0).getLimit() - 1;
        UnidimensionalState leftCellState = getLeftCellState(referencePosition, lastPosition, space);
        UnidimensionalState referenceCellState = getReferenceCellState(referencePosition, space);
        UnidimensionalState rightCellState = getRightCellState(referencePosition, lastPosition, space);
        return new UnidimensionalCombination(referenceCellState, leftCellState, rightCellState);
    }

    private UnidimensionalState getLeftCellState(final int referencePosition, final int lastPosition, final List<UnidimensionalCell> space) {
        UnidimensionalState leftCellState;
        if (referencePosition == 0) {
            UnidimensionalCell leftCell = space.get(lastPosition);
            leftCellState = leftCell.getState();
        } else {
            UnidimensionalCell leftCell = space.get(referencePosition - 1);
            leftCellState = leftCell.getState();
        }
        return leftCellState;
    }

    private UnidimensionalState getReferenceCellState(final int referencePosition, final List<UnidimensionalCell> space) {
        UnidimensionalCell referenceCell = space.get(referencePosition);
        return referenceCell.getState();
    }

    private UnidimensionalState getRightCellState(final int referencePosition, final int lastPosition, final List<UnidimensionalCell> space) {
        UnidimensionalState rightCellState;
        if (referencePosition == lastPosition) {
            UnidimensionalCell rightCell = space.get(0);
            rightCellState = rightCell.getState();
        } else {
            UnidimensionalCell rightCell = space.get(referencePosition + 1);
            rightCellState = rightCell.getState();
        }
        return rightCellState;
    }

    @Override
    protected void initialize() {
        if (super.keepHistory) {
            super.history = new ArrayList<List<UnidimensionalCell>>();
        }
        super.current = new ArrayList<UnidimensionalCell>();
    }

    @Override
    protected void createNewIteration(UnidimensionalTime time) {
        this.current = new ArrayList<UnidimensionalCell>();
    }

    @Override
    protected void createNewCell(UnidimensionalTime time, UnidimensionalTransition transition) throws InvalidTransitionException {
        // time parameter is not used in this method because dimensional access
        // is linear for one dimension, but it should be used for more than one
        // dimension
        UnidimensionalCell cell = new UnidimensionalCell(transition);
        current.add(cell);
    }

} public final class UnidimensionalTime extends Time {

    public UnidimensionalTime(final int limit, int... limits)
            throws CloneNotSupportedException, InvalidAbsoluteTimeLimitException, InvalidRelativeTimeLimitException {
        super(limit, limits);
    }

} public final class UnidimensionalUniverse extends Universe<UnidimensionalSpace, UnidimensionalTime> {

    public UnidimensionalUniverse(UnidimensionalSpace space, UnidimensionalTime time) throws InvalidSpaceException, InvalidTimeException {
        super(space, time);
    }

} public final class UnidimensionalSimulation extends Simulation<UnidimensionalUniverse,UnidimensionalCellularAutomaton> {

	public UnidimensionalSimulation(UnidimensionalUniverse universe, UnidimensionalCellularAutomaton ca)
			throws InvalidUniverseException, InvalidCellularAutomataException {
		super(universe, ca);
	}

}
import java.util.ArrayList;
import java.util.List;
import com.ghjansen.cas.control.parameter.SequenceParameter;
import com.ghjansen.cas.control.simulation.SimulationBuilder;
import com.ghjansen.cas.control.simulation.SimulationParameter;
import com.ghjansen.cas.core.exception.InvalidAbsoluteTimeLimitException;
import com.ghjansen.cas.core.exception.InvalidCellularAutomataException;
import com.ghjansen.cas.core.exception.InvalidCombinationException;
import com.ghjansen.cas.core.exception.InvalidDimensionalAmountException;
import com.ghjansen.cas.core.exception.InvalidDimensionalSpaceException;
import com.ghjansen.cas.core.exception.InvalidInitialConditionException;
import com.ghjansen.cas.core.exception.InvalidRelativeTimeLimitException;
import com.ghjansen.cas.core.exception.InvalidRuleException;
import com.ghjansen.cas.core.exception.InvalidSpaceException;
import com.ghjansen.cas.core.exception.InvalidStateException;
import com.ghjansen.cas.core.exception.InvalidTimeException;
import com.ghjansen.cas.core.exception.InvalidTransitionException;
import com.ghjansen.cas.core.exception.InvalidUniverseException;
import com.ghjansen.cas.unidimensional.ca.UnidimensionalCellularAutomaton;
import com.ghjansen.cas.unidimensional.ca.UnidimensionalCombination;
import com.ghjansen.cas.unidimensional.ca.UnidimensionalGeneralRule;
import com.ghjansen.cas.unidimensional.ca.UnidimensionalState;
import com.ghjansen.cas.unidimensional.ca.UnidimensionalTransition;
import com.ghjansen.cas.unidimensional.physics.UnidimensionalCell;
import com.ghjansen.cas.unidimensional.physics.UnidimensionalSpace;
import com.ghjansen.cas.unidimensional.physics.UnidimensionalTime;
import com.ghjansen.cas.unidimensional.physics.UnidimensionalUniverse;
import com.ghjansen.cas.unidimensional.simulation.UnidimensionalSimulation;
/*
 * CAS - Cellular Automata Simulator
 * Copyright (C) 2016  Guilherme Humberto Jansen
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.ghjansen.cas.unidimensional.control;



/**
 * @author Guilherme Humberto Jansen (contact.ghjansen@gmail.com)
 */
public class UnidimensionalSimulationBuilder extends SimulationBuilder<UnidimensionalState, UnidimensionalCombination,
        UnidimensionalTransition, UnidimensionalGeneralRule, UnidimensionalCell, UnidimensionalCellularAutomaton,
        UnidimensionalTime, UnidimensionalSpace, UnidimensionalUniverse, UnidimensionalSimulation> {

    public UnidimensionalSimulationBuilder(SimulationParameter simulationParameter) {