1 /* 2 * db2sa: DB2 Syntax Assistant 3 * Copyright (C) Andres Gomez Casanova 4 * 5 * This file is part of db2sa. 6 * 7 * db2sa is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU Lesser General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * db2sa is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public License 18 * along with this library; if not, see <http://www.gnu.org/licenses/>. 19 * 20 * Contact: 21 * a n g o c a at y a h o o dot c o m 22 * Cra. 45 No 61 - 31, Bogota, Colombia. 23 * 24 * Author: $LastChangedBy: angoca $: 25 * Date: $LastChangedDate: 2009-07-02 15:49:36 +0200 (Thu, 02 Jul 2009) $: 26 * Revision: $LastChangedRevision: 280 $: 27 * URL: $HeadURL: https://db2sa.svn.sourceforge.net/svnroot/db2sa/branches/db2sa_beta/source-code/src/main/java/name/angoca/db2sa/core/syntax/graph/GraphToken.java $: 28 */ 29 package name.angoca.db2sa.core.syntax.graph; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 34 import name.angoca.db2sa.core.syntax.graph.exception.InvalidGraphTokenException; 35 36 import org.slf4j.Logger; 37 import org.slf4j.LoggerFactory; 38 39 /** 40 * This is the representation of a word in the grammar graph. A token can be a 41 * reserved word, a parenthesis, a comma, or a variable word, like a name or a 42 * number.<br/> 43 * The grammar is represented by a graph, and this graph has the possibles ways 44 * that a command can have.<br/> 45 * A token has the following elements: 46 * <ul> 47 * <li>id</li> 48 * <li>reservedWord</li> 49 * <li>ways</li> 50 * </ul> 51 * The name attribute represents the internal identification of the token, and 52 * its content can be the reserved word that it represents, or the name of the 53 * variable. Then, the reservedWord attribute indicates if the id is a 54 * reservedWord or not. This is used when scanning the graph.<br/> 55 * Two nodes are the same if the data that they have is the same, and the ways 56 * that they have are the same.<br/> 57 * <b>Control Version</b><br /> 58 * <ul> 59 * <li>0.0.1 Class creation.</li> 60 * <li>0.0.2</li> 61 * <li>0.1.0 Recommendations from PMD.</li> 62 * <li>0.1.1 Organized.</li> 63 * <li>0.2.0 Comparison not sorted.</li> 64 * <li>0.2.1 Change the Id attribute by Name.</li> 65 * <li>0.2.2 isReservedWord and id as an attribute.</li> 66 * <li>0.2.3 Attribute renamed.</li> 67 * <li>0.2.4 equals reduced in complexity.</li> 68 * <li>0.2.5 Variable name and final.</li> 69 * <li>1.0.0 Moved to version 1.</li> 70 * </ul> 71 * 72 * @author Andres Gomez Casanova <a 73 * href="mailto:a n g o c a at y a h o o dot c o m">(AngocA)</a> 74 * @version 1.0.0 2009-07-19 75 */ 76 public class GraphToken { 77 78 /** 79 * Logger. 80 */ 81 private static final Logger LOGGER = LoggerFactory 82 .getLogger(GraphToken.class); 83 84 /** 85 * Unique identifier of this token. 86 */ 87 private String m_id; 88 89 /** 90 * Represents an internal identification of the token. Most of the cases its 91 * value id the reserved word that the token represents, however it can also 92 * be the name of the variable that represents. 93 */ 94 private final transient String m_name; 95 96 /** 97 * Represents if the token is a reserved word or a variable name. 98 */ 99 private final transient boolean m_reservedWord; 100 101 /** 102 * Represents the destination ways from the current node. 103 */ 104 private final transient List<GraphToken> m_ways; 105 106 /** 107 * Constructor that defines a token object. The name is the name of the 108 * token that this token object represents, and reservedWord says if the 109 * node is a reserved word or a variable name.<br/> 110 * PRE: The token does not have any delimiter, it just have the token. 111 * 112 * @param name 113 * Name of the token. 114 * @param reservedWord 115 * Indicates if the token is a reserved word in the grammar. 116 */ 117 public GraphToken(final String /* ! */name, 118 final boolean/* ! */reservedWord) { 119 this(name, name, reservedWord); 120 } 121 122 /** 123 * Constructor that defines a token object. The id is the unique identifier 124 * of this token. The name is the name of the token that this token object 125 * represents, and reservedWord says if the node is a reserved word or a 126 * variable name.<br/> 127 * PRE: The token does not have any delimiter, it just have the token. 128 * 129 * @param tokenId 130 * Unique id of the token. 131 * @param name 132 * Name of the token. 133 * @param reservedWord 134 * Indicates if the token is a reserved word in the grammar. 135 */ 136 public GraphToken(final String/* ! */tokenId, final String /* ! */name, 137 final boolean/* ! */reservedWord) { 138 if (name.compareTo("") == 0) { //$NON-NLS-1$ 139 throw new InvalidGraphTokenException(); 140 } 141 this.m_id = tokenId; 142 this.m_name = name; 143 this.m_reservedWord = reservedWord; 144 this.m_ways = new ArrayList<GraphToken>(); 145 } 146 147 /** 148 * Adds a possible way to the current token. 149 * 150 * @param token 151 * to connect with the current token. 152 */ 153 public final void addWay(final GraphToken/* ! */token) { 154 if (token == null) { 155 GraphToken.LOGGER.debug("addway null"); //$NON-NLS-1$ 156 } 157 this.m_ways.add(token); 158 } 159 160 /** 161 * Analyzes the given token, and returns true if the current graph token 162 * represents that token. 163 * 164 * @param token 165 * token to analyze. 166 * @return true if the graph node represents that token. 167 */ 168 public final boolean represent(final String/* ! */token) { 169 boolean represents; 170 if (this.m_reservedWord) { 171 if (this.getName().compareToIgnoreCase(token) == 0) { 172 represents = true; 173 } else { 174 represents = false; 175 } 176 } else { 177 represents = true; 178 } 179 return represents; 180 } 181 182 /** 183 * Returns the identifier of this token. 184 * 185 * @return the unique identifier of this token. 186 */ 187 public final String getId() { 188 return this.m_id; 189 } 190 191 /** 192 * Returns the name of the token. 193 * 194 * @return the name of the token. 195 */ 196 public final String/* ! */getName() { 197 return this.m_name; 198 } 199 200 /** 201 * Returns true if the token represents a reserved word in the grammar. 202 * False if not. 203 * 204 * @return if the token represents a reserved word 205 */ 206 public final boolean isReservedWord() { 207 return this.m_reservedWord; 208 } 209 210 /** 211 * This method retrieves all the possibles ways that can be taken from this 212 * node. This is useful to analyze the graph. 213 * 214 * @return set of possibles ways. 215 */ 216 public final List<GraphToken>/* <!>! */getWays() { 217 return this.m_ways; 218 } 219 220 /* 221 * (non-Javadoc) 222 * 223 * @see java.lang.Object#equals(java.lang.Object) 224 */ 225 @Override 226 public boolean equals(final Object/* ? */object) { 227 boolean equals = false; 228 if (object instanceof GraphToken) { 229 final GraphToken token = (GraphToken) object; 230 final List<GraphToken> ways = token.m_ways; 231 if (token.m_name.compareTo(this.m_name) == 0 232 && token.m_reservedWord == this.m_reservedWord 233 && ways.size() == this.m_ways.size()) { 234 equals = true; 235 final int size = ways.size(); 236 for (int i = 0; i < size && equals; i += 1) { 237 if (!this.contains(ways.get(i))) { 238 equals = false; 239 } 240 } 241 } 242 } 243 return equals; 244 } 245 246 /** 247 * Checks is the given graph token is part of one of the children of this 248 * graph token. 249 * 250 * @param graphToken 251 * Graph token to analyze. 252 * @return True is the graph token is part of the children of this token. 253 */ 254 private boolean contains(final GraphToken/* ! */graphToken) { 255 final int size = this.m_ways.size(); 256 boolean ret = false; 257 for (int i = 0; i < size && !ret; i += 1) { 258 if (graphToken.getName().compareTo(this.m_ways.get(i).getName()) == 0) { 259 ret = true; 260 } 261 } 262 return ret; 263 } 264 265 /* 266 * (non-Javadoc) 267 * 268 * @see java.lang.Object#hashCode() 269 */ 270 @Override 271 public int hashCode() { 272 int size = this.m_ways.size(); 273 if (size == 0) { 274 size = 1; 275 } 276 int value = (this.m_name.hashCode() / size) - this.m_ways.size(); 277 if (this.m_reservedWord) { 278 value *= -1; 279 } 280 return value; 281 } 282 283 /** 284 * Returns a string representation of a graph token. The representation is: 285 * <ul> 286 * <li>For a non word reserved token: {name}</li> 287 * <li>For a word reserver token: {name|R}</li> 288 * </ul> 289 * 290 * @see java.lang.Object#toString() 291 * @return String representation of a graph token. 292 */ 293 @Override 294 public String/* ! */toString() { 295 String reserved = "|R"; //$NON-NLS-1$ 296 if (!this.m_reservedWord) { 297 reserved = ""; //$NON-NLS-1$ 298 } 299 return '{' + this.m_name + reserved + '}'; 300 } 301 }