001package de.learnlib.cache.sul;
002
003import net.automatalib.incremental.mealy.IncrementalMealyBuilder;
004import net.automatalib.incremental.mealy.State;
005import net.automatalib.incremental.mealy.TransitionRecord;
006import net.automatalib.words.Alphabet;
007import net.automatalib.words.WordBuilder;
008import de.learnlib.api.SUL;
009import de.learnlib.cache.mealy.MealyCacheConsistencyTest;
010
011public class SULCache<I, O> implements SUL<I, O> {
012        
013        private final IncrementalMealyBuilder<I, O> incMealy;
014        private final SUL<I,O> delegate;
015        
016        private State current;
017        private final WordBuilder<I> inputWord = new WordBuilder<>();
018        private WordBuilder<O> outputWord;
019
020        public SULCache(Alphabet<I> alphabet, SUL<I,O> sul) {
021                this.incMealy = new IncrementalMealyBuilder<>(alphabet);
022                this.delegate = sul;
023        }
024
025        @Override
026        public void pre() {
027                if(outputWord != null) {
028                        incMealy.insert(inputWord.toWord(), outputWord.toWord());
029                }
030                
031                inputWord.clear();
032                outputWord = null;
033                current = incMealy.getInitialState();
034        }
035
036        @Override
037        public O step(I in) {
038                O out = null;
039                
040                if(current != null) {
041                        TransitionRecord trans = incMealy.getTransition(current, in);
042                        
043                        if(trans != null) {
044                                out = incMealy.getTransitionOutput(trans);
045                                current = incMealy.getSuccessor(trans);
046                                assert current != null;
047                        }
048                        else {
049                                current = null;
050                                outputWord = new WordBuilder<>();
051                                delegate.pre();
052                                for(I prevSym : inputWord) {
053                                        outputWord.append(delegate.step(prevSym));
054                                }
055                        }
056                }
057                
058                inputWord.append(in);
059                
060                if(current == null) {
061                        out = delegate.step(in);
062                        outputWord.add(out);
063                }
064                
065                return out;
066        }
067        
068        public MealyCacheConsistencyTest<I, O> createCacheConsistencyTest() {
069                return new MealyCacheConsistencyTest<>(incMealy);
070        }
071
072    @Override
073    public void post() {
074        delegate.post();
075    }
076
077
078}