View Javadoc

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 }