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.words.impl;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.HashMap;
022import java.util.Iterator;
023import java.util.List;
024import java.util.Map;
025
026import net.automatalib.words.GrowingAlphabet;
027import net.automatalib.words.abstractimpl.AbstractAlphabet;
028
029
030/**
031 * A simple alphabet implementation, that does not impose any restriction on the input
032 * symbol class. However, the id lookup for a symbol might be slightly slower.
033 * 
034 * @author Malte Isberner <malte.isberner@gmail.com>
035 *
036 * @param <I> input symbol class.
037 */
038public class SimpleAlphabet<I> extends AbstractAlphabet<I> implements GrowingAlphabet<I> {
039        
040        private final List<I> symbols = new ArrayList<I>();
041        
042        private final Map<I,Integer> indexMap = new HashMap<I,Integer>();
043        
044        /*
045         * (non-Javadoc)
046         * @see java.util.AbstractList#add(java.lang.Object)
047         */
048        @Override
049        public boolean add(I a) {
050                int s = size();
051                int idx = addSymbol(a);
052                if(idx != s)
053                        return false;
054                return true;
055        }
056
057        /*
058         * (non-Javadoc)
059         * @see net.automatalib.words.GrowingAlphabet#addSymbol(java.lang.Object)
060         */
061        @Override
062        public int addSymbol(I a) {
063                Integer idx = indexMap.get(a);
064                if(idx != null)
065                        return idx;
066                idx = size();
067                symbols.add(a);
068                indexMap.put(a, idx);
069                return idx;
070        }
071
072        /*
073         * (non-Javadoc)
074         * @see java.util.AbstractList#iterator()
075         */
076        @Override
077        public Iterator<I> iterator() {
078                return Collections.unmodifiableList(symbols).iterator();
079        }
080
081        /*
082         * (non-Javadoc)
083         * @see java.util.AbstractCollection#size()
084         */
085        @Override
086        public int size() {
087                return symbols.size();
088        }
089
090        /*
091         * (non-Javadoc)
092         * @see de.ls5.words.Alphabet#getSymbol(int)
093         */
094        @Override
095        public I getSymbol(int index) {
096                return symbols.get(index);
097        }
098
099        /*
100         * (non-Javadoc)
101         * @see de.ls5.words.Alphabet#getSymbolIndex(java.lang.Object)
102         */
103        @Override
104        public int getSymbolIndex(I symbol) {
105                return indexMap.get(symbol);
106        }
107
108        /*
109         * (non-Javadoc)
110         * @see java.util.AbstractList#get(int)
111         */
112        @Override
113        public I get(int index) {
114                return getSymbol(index);
115        }
116
117        /*
118         * (non-Javadoc)
119         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
120         */
121        @Override
122        public int compare(I o1, I o2) {
123                return indexMap.get(o1) - indexMap.get(o2);
124        }
125
126}