001 package org.maltparser.core.symbol.trie; 002 003 import org.maltparser.core.helper.HashMap; 004 005 import org.maltparser.core.symbol.SymbolException; 006 007 /** 008 009 @author Johan Hall 010 */ 011 public class TrieNode { 012 /** 013 * Initial capacity of the hash maps. 014 */ 015 // private final static int INITIAL_CAPACITY = 2; 016 /** 017 * the character that corresponds to the trie node 018 */ 019 private final char character; 020 /** 021 * Maps a symbol table into an entry (if not cached) 022 */ 023 private HashMap<TrieSymbolTable,Integer> entries; 024 /** 025 * Maps a symbol table (cachedKeyEntry) into an entry (cachedValueEntry), caches only the first occurrence. 026 */ 027 private TrieSymbolTable cachedKeyEntry; 028 private Integer cachedValueEntry; 029 030 /** 031 * Maps a character into a child trie node (if not cached) 032 */ 033 private HashMap<Character,TrieNode> children; 034 private char cachedKeyChar; 035 private TrieNode cachedValueTrieNode; 036 037 /** 038 * The parent trie node 039 */ 040 private final TrieNode parent; 041 042 /** 043 * Constructs a trie node 044 * 045 * @param character which character that the trie node belongs to 046 * @param parent the parent trie node 047 */ 048 public TrieNode(char character, TrieNode parent) { 049 this.character = character; 050 this.parent = parent; 051 } 052 053 /** 054 * Adds and/or retrieve a child trie node. It only adds a entry if the parameter isWord is true. 055 * 056 * @param isWord true if it is a word (entry), otherwise false 057 * @param c the character to the child node 058 * @param table which symbol table to look in or add to 059 * @param code the integer representation of the string value 060 * @return the child trie node that corresponds to the character 061 * @throws SymbolException 062 */ 063 public TrieNode getOrAddChild(boolean isWord, char c, TrieSymbolTable table, int code) throws SymbolException { 064 if (cachedValueTrieNode == null) { 065 cachedValueTrieNode = new TrieNode(c, this); 066 cachedKeyChar = c; 067 if (isWord) { 068 cachedValueTrieNode.addEntry(table, code); 069 } 070 return cachedValueTrieNode; 071 } else if (cachedKeyChar == c) { 072 if (isWord) { 073 cachedValueTrieNode.addEntry(table, code); 074 } 075 return cachedValueTrieNode; 076 } else { 077 TrieNode child = null; 078 if (children == null) { 079 children = new HashMap<Character, TrieNode>(); 080 // children = new HashMap<Character, TrieNode>(INITIAL_CAPACITY); 081 child = new TrieNode(c, this); 082 children.put(c,child); 083 } else { 084 child = children.get(c); 085 if (child == null) { 086 child = new TrieNode(c, this); 087 children.put(c,child); 088 } 089 } 090 if (isWord) { 091 child.addEntry(table, code); 092 } 093 return child; 094 } 095 } 096 097 /** 098 * Adds an entry if it does not exist 099 * 100 * @param table which symbol table to add an entry 101 * @param code the integer representation of the string value 102 * @throws SymbolException 103 */ 104 private void addEntry(TrieSymbolTable table, int code) throws SymbolException { 105 if (table == null) { 106 throw new SymbolException("Symbol table cannot be found. "); 107 } 108 if (cachedValueEntry == null) { 109 if (code != -1) { 110 cachedValueEntry = code; //new TrieEntry(code,true); 111 table.updateValueCounter(code); 112 } else { 113 cachedValueEntry = table.increaseValueCounter(); //new TrieEntry(table.increaseValueCounter(),false); 114 } 115 cachedKeyEntry = table; 116 } else if (!table.equals(cachedKeyEntry)) { 117 if (entries == null) { 118 entries = new HashMap<TrieSymbolTable, Integer>(); 119 // entries = new HashMap<TrieSymbolTable, TrieEntry>(INITIAL_CAPACITY); 120 } 121 if (!entries.containsKey(table)) { 122 if (code != -1) { 123 entries.put(table, code); //new TrieEntry(code,true)); 124 table.updateValueCounter(code); 125 } else { 126 entries.put(table, table.increaseValueCounter()); //new TrieEntry(table.increaseValueCounter(),false)); 127 } 128 } 129 } 130 } 131 132 /** 133 * Returns the child node that corresponds to the character 134 * 135 * @param c the character of the child node 136 * @return the child node 137 */ 138 public TrieNode getChild(char c) { 139 if (cachedKeyChar == c) { 140 return cachedValueTrieNode; 141 } else if (children != null) { 142 return children.get(c); 143 } 144 return null; 145 } 146 147 148 149 /** 150 * Returns the entry of the symbol table 'table' 151 * 152 * @param table which symbol table 153 * @return the entry of the symbol table 'table' 154 */ 155 public Integer getEntry(TrieSymbolTable table) { 156 if (table != null) { 157 if (table.equals(cachedKeyEntry)) { 158 return cachedValueEntry; 159 } else if (entries != null) { 160 return entries.get(table); 161 } 162 } 163 return null; 164 } 165 166 /** 167 * Returns the character of the trie node 168 * 169 * @return the character of the trie node 170 */ 171 public char getCharacter() { 172 return character; 173 } 174 175 /** 176 * Returns the parent node 177 * 178 * @return the parent node 179 */ 180 public TrieNode getParent() { 181 return parent; 182 } 183 184 public boolean equals(Object obj) { 185 return super.equals(obj); 186 } 187 188 public int hashCode() { 189 return super.hashCode(); 190 } 191 192 public String toString() { 193 final StringBuilder sb = new StringBuilder(); 194 sb.append(character); 195 return sb.toString(); 196 } 197 }