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 }