001    /**
002     * Copyright (c) 2010, SIB. All rights reserved.
003     * 
004     * SIB (Swiss Institute of Bioinformatics) - http://www.isb-sib.ch Host -
005     * https://sourceforge.net/projects/javaprotlib/
006     * 
007     * Redistribution and use in source and binary forms, with or without
008     * modification, are permitted provided that the following conditions are met:
009     * Redistributions of source code must retain the above copyright notice, this
010     * list of conditions and the following disclaimer. Redistributions in binary
011     * form must reproduce the above copyright notice, this list of conditions and
012     * the following disclaimer in the documentation and/or other materials provided
013     * with the distribution. Neither the name of the SIB/GENEBIO nor the names of
014     * its contributors may be used to endorse or promote products derived from this
015     * software without specific prior written permission.
016     * 
017     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
020     * ARE DISCLAIMED. IN NO EVENT SHALL SIB/GENEBIO BE LIABLE FOR ANY DIRECT,
021     * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
024     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027     */
028    package org.expasy.jpl.commons.collection.symbol;
029    
030    
031    import java.util.Collections;
032    import java.util.HashMap;
033    import java.util.HashSet;
034    import java.util.Map;
035    import java.util.Set;
036    import java.util.TreeSet;
037    import org.expasy.jpl.commons.collection.symbol.Symbol.SymbolType;
038    import org.expasy.jpl.commons.collection.tree.TreeView;
039    
040    
041    /**
042     * An alphabet is a finite set of symbols.
043     * 
044     * @author nikitin
045     * 
046     * @param <T> the symbol type.
047     * 
048     * @version 1.0
049     */
050    public final class AlphabetImpl<T> implements Alphabet<T>, AlphabetView<T> {
051            
052            private static final long serialVersionUID = -5097124740396112979L;
053            
054            /** mapping letter -> symbol tree */
055            protected Map<Character, TreeView<? extends Symbol<T>>> map;
056            
057            /** the type of alphabet defined by its symbol type */
058            protected SymbolType<T> type;
059            
060            private Set<Symbol<T>> leaves;
061            
062            private String regex;
063            
064            private AlphabetImpl(SymbolType<T> type) {
065                    map = new HashMap<Character, TreeView<? extends Symbol<T>>>();
066                    leaves = new HashSet<Symbol<T>>();
067                    this.type = type;
068            }
069            
070            public static <T> AlphabetImpl<T> newInstance(SymbolType<T> type) {
071                    return new AlphabetImpl<T>(type);
072            }
073            
074            /**
075             * Create an alphabet from the tree of symbols (mapping name -> symbol
076             * tree).
077             * 
078             * @return an alphabet over molecules.
079             */
080            public static <T> AlphabetImpl<T> fromSymbols(SymbolType<T> type,
081                TreeView<? extends Symbol<T>> tree) {
082                    AlphabetImpl<T> alphabet = AlphabetImpl.newInstance(type);
083                    
084                    for (TreeView<? extends Symbol<T>> node : tree.getNodes()) {
085                            alphabet.registerSymbolNode(node);
086                    }
087                    
088                    return alphabet;
089            }
090            
091            public final SymbolType<T> getSymbolType() {
092                    return type;
093            }
094            
095            public final Set<Symbol<T>> getSymbolLeaves() {
096                    return leaves;
097            }
098            
099            /** {@inheritDoc} */
100            public Set<Character> getLetters() {
101                    return Collections.unmodifiableSet(map.keySet());
102            }
103            
104            /** {@inheritDoc} */
105            public String getRegEx() {
106                    if (regex == null) {
107                            regex = getLetters().toString().replaceAll("[\\s,]", "");
108                    }
109                    return regex;
110            }
111            
112            public final void registerSymbolNode(
113                TreeView<? extends Symbol<T>> symbolNode) {
114                    if (!hasSymbol(symbolNode.getData().getName())) {
115                            map.put(symbolNode.getData().getName(), symbolNode);
116                            if (symbolNode.isLeave()) {
117                                    leaves.add(symbolNode.getData());
118                            }
119                    } else {
120                            System.err.println(symbolNode + " already entered");
121                    }
122            }
123            
124            public final void registerAllSymbolNodes(
125                TreeView<? extends Symbol<T>> symbolNode) {
126                    
127                    /* add all other nodes and leaves */
128                    for (TreeView<? extends Symbol<T>> node : symbolNode.getNodes()) {
129                            registerSymbolNode(node);
130                    }
131            }
132            
133            public final TreeView<? extends Symbol<T>> lookupSymbolNode(char name) {
134                    if (!hasSymbol(name)) {
135                            throw new SymbolNotFoundException(name
136                                + ": symbol node not found among " + map.keySet());
137                    }
138                    return map.get(name);
139            }
140            
141            public final Symbol<T> lookupSymbol(char name) {
142                    return lookupSymbolNode(name).getData();
143            }
144            
145            public final int getSymbolNumber() {
146                    return map.size();
147            }
148            
149            public boolean hasSymbol(char name) {
150                    return map.containsKey(name);
151            }
152            
153            public boolean isTerminalSymbol(Symbol<T> symbol) {
154                    return leaves.contains(symbol);
155            }
156            
157            public String toString() {
158                    StringBuilder sb = new StringBuilder();
159                    
160                    sb.append("Alphabet '" + type.getName() + "', ");
161                    sb.append(getSymbolNumber() + " symbols: ");
162                    sb.append("[");
163                    
164                    TreeSet<Character> s = new TreeSet<Character>(map.keySet());
165                    
166                    for (char key : s) {
167                            sb.append(key);
168                            sb.append(", ");
169                    }
170                    if (getSymbolNumber() > 0) {
171                            sb.delete(sb.length() - 2, sb.length());
172                    }
173                    sb.append("]");
174                    return sb.toString();
175            }
176            
177    }