001: /*
002: * Author: Mike Atkinson
003: *
004: * This software has been developed under the copyleft
005: * rules of the GNU General Public License. Please
006: * consult the GNU General Public License for more
007: * details about use and distribution of this software.
008: */
009: package net.sourceforge.jrefactory.ast;
010:
011: import java.util.StringTokenizer;
012: import net.sourceforge.jrefactory.parser.JavaParser;
013: import net.sourceforge.jrefactory.parser.JavaParserTreeConstants;
014: import net.sourceforge.jrefactory.parser.JavaParserVisitor;
015:
016: /**
017: * Stores a name. The name can consist of a number of parts separated by periods.
018: *
019: * The name consists of parts which are stored as ASTIdentifier nodes in this objects children.
020: *
021: * @author Mike Atkinson
022: * @since jRefactory 2.9.0, created October 16, 2003
023: */
024: public class ASTName extends SimpleNode implements Cloneable {
025: /** The cached value of the name. */
026: protected String name = null;
027:
028: /**
029: * Constructor for the ASTName node.
030: *
031: */
032: public ASTName() {
033: super (JavaParserTreeConstants.JJTNAME);
034: }
035:
036: /**
037: * Constructor for the ASTName node.
038: *
039: * @param identifier The id of this node (JJTNAME).
040: */
041: public ASTName(int identifier) {
042: super (identifier);
043: }
044:
045: /**
046: * Constructor for the ASTName node.
047: *
048: * @param parser The JavaParser that created this ASTName node.
049: * @param identifier The id of this node (JJTNAME).
050: */
051: public ASTName(JavaParser parser, int identifier) {
052: super (parser, identifier);
053: }
054:
055: /**
056: * Add a component of the name
057: *
058: * @param ndx the index of the part requested
059: * @param value The new NamePart value
060: */
061: public void setNamePart(int ndx, String value) {
062: name = null;
063: int count = 0;
064: for (int i = 0; i < children.length; i++) {
065: if (children[i] instanceof ASTIdentifier) {
066: if (count == ndx) {
067: ((ASTIdentifier) children[i]).setName(value);
068: return;
069: }
070: count++;
071: }
072: }
073: }
074:
075: /**
076: * Convert this object from a string (used for PMD testing)
077: *
078: * @param image The name in form "org.test.AName" for example
079: */
080: public void setImage(String image) {
081: fromString(image);
082: }
083:
084: /**
085: * Add a component of the name
086: *
087: * @param ndx the index of the part requested
088: * @return the portion of the name requested
089: */
090: public String getNamePart(int ndx) {
091: int count = 0;
092: for (int i = 0; i < children.length; i++) {
093: if (children[i] instanceof ASTIdentifier) {
094: if (count == ndx) {
095: return ((ASTIdentifier) children[i]).getName();
096: }
097: count++;
098: }
099: }
100:
101: return null;
102: }
103:
104: /**
105: * Get the node's name
106: *
107: * @return the name
108: */
109: public String getName() {
110: if (name == null) {
111: if (children == null) {
112: name = "";
113: return name;
114: }
115: // Local Variables
116: StringBuffer buf = new StringBuffer();
117: boolean first = true;
118:
119: // Iterate through the parts
120: for (int i = 0; i < children.length; i++) {
121: if (children[i] instanceof ASTIdentifier) {
122: if (!first) {
123: buf.append(".");
124: }
125: buf.append(((ASTIdentifier) children[i]).getName());
126: first = false;
127: }
128: }
129:
130: // Return the buffer
131: name = buf.toString();
132: }
133: return name;
134: }
135:
136: /**
137: * Get the length of the name
138: *
139: * @return the number of parts in the name
140: */
141: public int getNameSize() {
142: int count = 0;
143: for (int i = 0; i < children.length; i++) {
144: if (children[i] instanceof ASTIdentifier) {
145: count++;
146: }
147: }
148: return count;
149: }
150:
151: /**
152: * Add a component of the name
153: *
154: * @param ndx the index of the part requested
155: * @param value Description of Parameter
156: */
157: public void insertNamePart(int ndx, String value) {
158: name = null;
159: int count = 0;
160: ASTIdentifier ident = new ASTIdentifier(parser,
161: JavaParserTreeConstants.JJTIDENTIFIER);
162: ident.setName(value);
163: for (int i = 0; i < children.length; i++) {
164: if (children[i] instanceof ASTIdentifier) {
165: if (count == ndx) {
166: jjtInsertChild(ident, i);
167: return;
168: }
169: count++;
170: }
171: }
172: ident.setLineAndColumnInfo(getBeginLine(), getBeginColumn(),
173: getEndLine(), getEndColumn());
174: }
175:
176: /**
177: * Set the node's name
178: *
179: * @param newName the new name
180: */
181: public void addNamePart(String newName) {
182: name = null;
183: ASTIdentifier ident = new ASTIdentifier(parser,
184: JavaParserTreeConstants.JJTIDENTIFIER);
185: ident.setName(newName);
186: jjtAddChild(ident, ((children == null) ? 0 : children.length));
187: }
188:
189: /**
190: * Convert this object from a string
191: *
192: * @param input Description of Parameter
193: */
194: public void fromString(String input) {
195: // Clean the old one
196: name = null;//FIXME? = input
197: children = null;
198:
199: // Load it
200: StringTokenizer tok = new StringTokenizer(input, ".");
201: while (tok.hasMoreTokens()) {
202: String next = tok.nextToken();
203: //System.out.println("ASTName.fromString.addNamePart("+next+")");
204: addNamePart(next);
205: }
206: }
207:
208: /**
209: * Checks to see if the two names are equal
210: *
211: * @param other Description of Parameter
212: * @return Description of the Returned Value
213: */
214: public boolean equals(Object other) {
215: if (other == this ) {
216: return true;
217: }
218: if (other instanceof ASTName) {
219: ASTName otherName = (ASTName) other;
220:
221: if (otherName.getNameSize() == getNameSize()) {
222: return getName().equals(otherName.getName());
223: }
224: }
225: return false;
226: }
227:
228: /**
229: * Computes a hash value for this node.
230: *
231: * @return The hash value for this node.
232: */
233: public int hashCode() {
234: if (name == null) {
235: name = getName();
236: }
237: return name.hashCode();
238: }
239:
240: /**
241: * Determines if two names start with the same series of items
242: *
243: * @param otherName Description of Parameter
244: * @return Description of the Returned Value
245: */
246: public boolean startsWith(ASTName otherName) {
247: // To start with the other name, the other name must be less than or equal in parts
248: if (otherName.getNameSize() > getNameSize()) {
249: return false;
250: }
251:
252: // Look for the point where they are different
253: int last = Math.min(otherName.getNameSize(), getNameSize());
254: for (int ndx = 0; ndx < last; ndx++) {
255: if (!getNamePart(ndx).equals(otherName.getNamePart(ndx))) {
256: return false;
257: }
258: }
259:
260: // They must be the same
261: return true;
262: }
263:
264: /**
265: * Change starting part. Presumes that otherName is less than the length of the current name.
266: *
267: * @param oldBase Description of Parameter
268: * @param newBase Description of Parameter
269: * @return Description of the Returned Value
270: */
271: public ASTName changeStartingPart(ASTName oldBase, ASTName newBase) {
272: ASTName result = new ASTName();
273:
274: int last = newBase.getNameSize();
275: for (int ndx = 0; ndx < last; ndx++) {
276: result.addNamePart(newBase.getNamePart(ndx));
277: }
278:
279: int end = getNameSize();
280: int start = oldBase.getNameSize();
281: for (int ndx = start; ndx < end; ndx++) {
282: result.addNamePart(getNamePart(ndx));
283: }
284: result.setLineAndColumnInfo(getBeginLine(), getBeginColumn(),
285: getEndLine(), getEndColumn());
286:
287: return result;
288: }
289:
290: /**
291: * Accept the visitor.
292: *
293: * @param visitor An implementation of JavaParserVisitor that processes the ASTName node.
294: * @param data Some data being passed between the visitor methods.
295: * @return Usually the data parameter (possibly modified).
296: */
297: public Object jjtAccept(JavaParserVisitor visitor, Object data) {
298: return visitor.visit(this, data);
299: }
300: }
|