001/* Copyright (C) 2013 TU Dortmund
002 * This file is part of AutomataLib, http://www.automatalib.net/.
003 * 
004 * AutomataLib is free software; you can redistribute it and/or
005 * modify it under the terms of the GNU Lesser General Public
006 * License version 3.0 as published by the Free Software Foundation.
007 * 
008 * AutomataLib is distributed in the hope that it will be useful,
009 * but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
011 * Lesser General Public License for more details.
012 * 
013 * You should have received a copy of the GNU Lesser General Public
014 * License along with AutomataLib; if not, see
015 * http://www.gnu.de/documents/lgpl.en.html.
016 */
017package net.automatalib.automata.abstractimpl;
018
019import java.util.Collection;
020
021import net.automatalib.automata.MutableDeterministic;
022
023
024/**
025 * Abstract base class for mutable deterministic automata.
026 * 
027 * @author Malte Isberner <malte.isberner@gmail.com>
028 *
029 * @param <S> state class
030 * @param <I> input symbol class
031 * @param <T> transition class
032 * @param <SP> state property class
033 * @param <TP> transition property class
034 */
035public abstract class AbstractMutableDeterministic<S,I,T,SP,TP> extends
036                AbstractDeterministicAutomaton<S,I,T> implements
037                MutableDeterministic<S,I,T,SP,TP> {
038        
039        
040        /**
041         * Provides a realization of {@link MutableDeterministic#addTransition(Object, Object, Object)}
042         * using {@link MutableDeterministic#getTransition(Object, Object)} and
043         * {@link MutableDeterministic#setTransition(Object, Object, Object)}.
044         * @see MutableDeterministic#addTransition(Object, Object, Object)
045         */
046        public static <S,I,T,SP,TP> void addTransition(MutableDeterministic<S, I, T, SP, TP> $this,
047                        S state, I input, T transition) {
048                T currTrans = $this.getTransition(state, input);
049                if(currTrans != null)
050                        throw new IllegalStateException("Cannot add transition " + transition
051                                        + " to deterministic automaton: transition already defined for state "
052                                        + state + " and input " + input + ".");
053                $this.setTransition(state, input, transition);
054        }
055        
056        /**
057         * Provides a realization of {@link MutableDeterministic#removeTransition(Object, Object, Object)}
058         * using {@link MutableDeterministic#getTransition(Object, Object)} and
059         * {@link MutableDeterministic#setTransition(Object, Object, Object)}.
060         * @see MutableDeterministic#removeTransition(Object, Object, Object)
061         */
062        public static <S,I,T,SP,TP> void removeTransition(MutableDeterministic<S, I, T, SP, TP> $this,
063                        S state, I input, T transition) {
064                if(transition == null)
065                        return;
066                T currTrans = $this.getTransition(state, input);
067                if(transition.equals(currTrans))
068                        $this.setTransition(state, input, null);
069        }
070        
071        /**
072         * Provides a realization of {@link MutableDeterministic#removeAllTransitions(Object, Object)}
073         * using {@link MutableDeterministic#setTransition(Object, Object, Object)}.
074         * @see MutableDeterministic#removeAllTransitions(Object, Object)
075         */
076        public static <S,I,T,SP,TP> void removeAllTransitions(MutableDeterministic<S,I,T,SP,TP> $this, S state, I input) {
077                $this.setTransition(state, input, null);
078        }
079        
080        /**
081         * Provides a realization of {@link MutableDeterministic#setTransitions(Object, Object, Collection)}
082         * using {@link MutableDeterministic#setTransition(Object, Object, Object)}
083         * @see MutableDeterministic#setTransitions(Object, Object, Collection)
084         */
085        public static <S,I,T,SP,TP> void setTransitions(MutableDeterministic<S,I,T,SP,TP> $this,
086                        S state, I input, Collection<? extends T> transitions) {
087                
088                int num = transitions.size();
089                if(num > 1) {
090                        throw new IllegalArgumentException("Deterministic automaton can not "
091                                        + "have multiple transitions for the same input symbol.");
092                }
093                
094                T trans = (num > 0) ? transitions.iterator().next() : null;
095                
096                $this.setTransition(state, input, trans);
097        }
098        
099        /**
100         * Provides a realization of {@link MutableDeterministic#setTransition(Object, Object, Object, Object)}
101         * using {@link MutableDeterministic#createTransition(Object, Object)} and
102         * {@link MutableDeterministic#setTransition(Object, Object, Object)}.
103         * @see MutableDeterministic#setTransition(Object, Object, Object, Object)
104         */
105        public static <S,I,T,SP,TP> void setTransition(MutableDeterministic<S, I, T, SP, TP> $this,
106                        S state, I input, S successor, TP property) {
107                T trans = $this.createTransition(successor, property);
108                $this.setTransition(state, input, trans);
109        }
110        
111        
112        /**
113         * Provides a realization of {@link MutableDeterministic#setInitial(Object, boolean)}
114         * using {@link MutableDeterministic#getInitialState()} and
115         * {@link MutableDeterministic#setInitialState(Object)}.
116         * @see MutableDeterministic#setInitial(Object, boolean)
117         */
118        public static <S,I,T,SP,TP> void setInitial(MutableDeterministic<S,I,T,SP,TP> $this,
119                        S state, boolean initial) {
120                S currInitial = $this.getInitialState();
121                if(state.equals(currInitial)) {
122                        if(!initial)
123                                $this.setInitialState(null);
124                }
125                else if(currInitial == null)
126                        $this.setInitialState(state);
127                else
128                        throw new IllegalStateException("Cannot set state '" + state + "' as "
129                                        + "additional initial state (current initial state: '"
130                                        + currInitial + "'.");
131        }
132        
133        //////////////////////////////////////////////////////////////////////////////////////////////
134        
135        /*
136         * (non-Javadoc)
137         * @see net.automatalib.automata.MutableAutomaton#addTransition(java.lang.Object, java.lang.Object, java.lang.Object)
138         */
139        @Override
140        public void addTransition(S state, I input, T transition) {
141                addTransition(this, state, input, transition);
142        }
143        
144        @Override
145        public void addTransitions(S state, I input, Collection<? extends T> transitions) {
146                AbstractMutableAutomaton.addTransitions(this, state, input, transitions);
147        }
148        /*
149         * (non-Javadoc)
150         * @see net.automatalib.automata.MutableAutomaton#addTransition(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object)
151         */
152        @Override
153        public T addTransition(S state, I input, S successor, TP property) {
154                return AbstractMutableAutomaton.addTransition(this, state, input, successor, property);
155        }
156        
157        /*
158         * (non-Javadoc)
159         * @see net.automatalib.automata.MutableAutomaton#removeTransition(java.lang.Object, java.lang.Object, java.lang.Object)
160         */
161        @Override
162        public void removeTransition(S state, I input, T transition) {
163                removeTransition(this, state, input, transition);
164        }
165        
166        /*
167         * (non-Javadoc)
168         * @see net.automatalib.automata.MutableAutomaton#removeAllTransitions(java.lang.Object, java.lang.Object)
169         */
170        @Override
171        public void removeAllTransitions(S state, I input) {
172                removeAllTransitions(this, state, input);
173        }
174        
175        /*
176         * (non-Javadoc)
177         * @see net.automatalib.automata.MutableAutomaton#setInitial(java.lang.Object, boolean)
178         */
179        @Override
180        public void setInitial(S state, boolean initial) {
181                setInitial(this, state, initial);
182        }
183        
184        /*
185         * (non-Javadoc)
186         * @see net.automatalib.automata.MutableAutomaton#setTransitions(java.lang.Object, java.lang.Object, java.util.Collection)
187         */
188        @Override
189        public void setTransitions(S state, I input, Collection<? extends T> transitions) {
190                setTransitions(this, state, input, transitions);
191        }
192        
193        /*
194         * (non-Javadoc)
195         * @see net.automatalib.automata.MutableDeterministic#setTransition(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object)
196         */
197        @Override
198        public void setTransition(S state, I input, S succ, TP properties) {
199                setTransition(this, state, input, succ, properties);
200        }
201        
202        /*
203         * (non-Javadoc)
204         * @see net.automatalib.automata.MutableAutomaton#addInitialState(java.lang.Object)
205         */
206        @Override
207        public S addInitialState(SP property) {
208                return AbstractMutableAutomaton.addInitialState(this, property);
209        }
210        
211        /*
212         * (non-Javadoc)
213         * @see net.automatalib.automata.MutableAutomaton#addInitialState()
214         */
215        @Override
216        public S addInitialState() {
217                return AbstractMutableAutomaton.addInitialState(this);
218        }
219        
220        /*
221         * (non-Javadoc)
222         * @see net.automatalib.automata.MutableAutomaton#addState()
223         */
224        @Override
225        public S addState() {
226                return AbstractMutableAutomaton.addState(this);
227        }
228}