/* * funCKit - functional Circuit Kit * Copyright (C) 2013 Lukas Elsner <open@mindrunner.de> * Copyright (C) 2013 Peter Dahlberg <catdog2@tuxzone.org> * Copyright (C) 2013 Julian Stier <mail@julian-stier.de> * Copyright (C) 2013 Sebastian Vetter <mail@b4sti.eu> * Copyright (C) 2013 Thomas Poxrucker <poxrucker_t@web.de> * Copyright (C) 2013 Alexander Treml <alex.treml@directbox.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * 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 de.sep2011.funckit.drawer; import de.sep2011.funckit.model.graphmodel.AccessPoint; import de.sep2011.funckit.model.graphmodel.Brick; import de.sep2011.funckit.model.graphmodel.Component; import de.sep2011.funckit.model.graphmodel.Element; import de.sep2011.funckit.model.graphmodel.ElementDispatcher; import de.sep2011.funckit.model.graphmodel.Input; import de.sep2011.funckit.model.graphmodel.Output; import de.sep2011.funckit.model.graphmodel.Switch; import de.sep2011.funckit.model.graphmodel.Wire; import de.sep2011.funckit.model.graphmodel.implementations.And; import de.sep2011.funckit.model.graphmodel.implementations.IdPoint; import de.sep2011.funckit.model.graphmodel.implementations.Light; import de.sep2011.funckit.model.graphmodel.implementations.Not; import de.sep2011.funckit.model.graphmodel.implementations.Or; import de.sep2011.funckit.model.simulationmodel.ComponentSimulationState; import de.sep2011.funckit.model.simulationmodel.GateSimulationState; import de.sep2011.funckit.model.simulationmodel.LightSimulationState; import de.sep2011.funckit.model.simulationmodel.Simulation; import de.sep2011.funckit.model.simulationmodel.SimulationBrick; import de.sep2011.funckit.model.simulationmodel.SimulationState; import de.sep2011.funckit.model.simulationmodel.SwitchSimulationState; import java.util.Deque; public class LayoutResolver implements ElementDispatcher { private Deque<Component> elementComponentStack; private Simulation simulation; private Layout layout; /** * Injection for layout object. * * @param layout Layout object to inject further information. */ public void setLayout(Layout layout) { this.layout = layout; } /** * Injects component stack of associated {@link Element} of {@link Layout}, * that was injected by {@link LayoutResolver#setLayout}. Specifies path of * element in graph. * * @param stack Stack of parent components. */ public void setComponentStack(Deque<Component> stack) { this.elementComponentStack = stack; } /** * Setter injection method for current simulation object to initialize * layout object with simulation state information and output queue maps. * * @param simulation Current simulation object. */ public void setSimulation(Simulation simulation) { this.simulation = simulation; } /** * {@inheritDoc} */ @Override public void visit(Element element) { throw new UnsupportedOperationException("Unknown element dispatched."); } /** * {@inheritDoc} */ @Override public void visit(Wire wire) { assert elementComponentStack != null; assert layout != null; if (simulation != null) { /* * Basically we can assume, that in simulation mode inputs are only * connected to outputs. But for safety reasons, we first check for * the outputs correct type, before we cast it. In some cases it * occurred, that ghosts were drawn in simulation mode, too. As we * can not assume only-input-to-output-connections with ghosts, we * have to check this cast here and ignore wires, that don't support * that assumption. */ AccessPoint accessPoint = (wire.getFirstAccessPoint() instanceof Output ? wire .getFirstAccessPoint() : wire.getSecondAccessPoint()); if (accessPoint instanceof Output) { /* Now we have our output to receive the current simulation state. */ Output o = (Output) accessPoint; SimulationBrick simBrick = new SimulationBrick(o.getBrick(), elementComponentStack); SimulationState state = simulation.getSimulationState(simBrick); boolean value = state.getValue(o); layout.setSimulationState(value); } } } /** * {@inheritDoc} */ @Override public void visit(Component component) { resolve(component); } /** * {@inheritDoc} */ @Override public void visit(Switch s) { assert elementComponentStack != null; assert layout != null; /* Resolve simulation state information */ if (simulation != null) { SimulationBrick simBrick = new SimulationBrick(s, elementComponentStack); SwitchSimulationState state = (SwitchSimulationState) simulation .getSimulationState(simBrick); boolean value = state.getValue(); layout.setSimulationState(value); } /* Resolve common layout information */ resolve(s); } /** * {@inheritDoc} */ @Override public void visit(Light light) { assert elementComponentStack != null; assert layout != null; if (simulation != null) { Input firstInput = light.getInputs().iterator().next(); SimulationBrick simBrick = new SimulationBrick(light, elementComponentStack); LightSimulationState state = (LightSimulationState) simulation .getSimulationState(simBrick); boolean value = state.getValue(firstInput); layout.setSimulationState(value); } } /** * {@inheritDoc} */ @Override public void visit(And and) { resolve(and); } /** * {@inheritDoc} */ @Override public void visit(Or or) { resolve(or); } /** * {@inheritDoc} */ @Override public void visit(Not not) { resolve(not); } /** * {@inheritDoc} */ @Override public void visit(IdPoint idPoint) { resolve(idPoint); } public void resolve(Input input) { assert layout != null; if (simulation != null && !input.getWires().isEmpty()) { Wire wire = input.getWires().iterator().next(); /* * Usually getOther(input) has to be an Output, but we ensure that * with an instanceof-operator to ignore cases with ghost elements, * that still exist in simulation mode. */ if (wire.getOther(input) instanceof Output) { Output other = (Output) wire.getOther(input); resolve(other); } } } public void resolve(Output output) { assert layout != null; if (simulation != null) { SimulationBrick simBrick = new SimulationBrick(output.getBrick(), elementComponentStack); SimulationState state = simulation.getSimulationState(simBrick); layout.setSimulationState(state.getValue(output)); } } private void resolve(Brick brick) { if (simulation != null) { /* * If brick has outputs and is no switch, it must have an output * queue */ if (brick.getOutputs().size() != 0 && !(brick instanceof Switch)) { SimulationBrick simBrick = new SimulationBrick(brick, elementComponentStack); SimulationState state = simulation.getSimulationState(simBrick); if (state instanceof GateSimulationState) { layout.setOutputQueueMap(((GateSimulationState) state).getOutputQueueMap()); } else if (state instanceof ComponentSimulationState) { layout.setOutputQueueMap(((ComponentSimulationState) state).getOutputQueueMap()); } } } } }