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 }