KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > source > save > PositionEstimator


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.java.source.save;
20
21 import com.sun.source.tree.CompilationUnitTree;
22 import com.sun.source.tree.ExpressionTree;
23 import com.sun.source.tree.ImportTree;
24 import com.sun.source.tree.Tree;
25 import com.sun.source.util.SourcePositions;
26 import java.util.ArrayList JavaDoc;
27 import java.util.EnumSet JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import org.netbeans.api.java.lexer.JavaTokenId;
32 import static org.netbeans.api.java.lexer.JavaTokenId.*;
33 import org.netbeans.api.java.source.WorkingCopy;
34 import org.netbeans.api.lexer.Token;
35 import org.netbeans.api.lexer.TokenSequence;
36 import org.netbeans.modules.java.source.save.TreeDiff.LineInsertionType;
37
38 /**
39  * Estimates the position for given element or element set. Offsets are
40  * available from SourcePositions, but these are not precise enough for
41  * generator. -- Generator has to handle comments and empty lines and
42  * spaces too.
43  *
44  * @author Pavel Flaska
45  */

46 abstract class PositionEstimator {
47     
48     final List JavaDoc<? extends Tree> oldL;
49     final List JavaDoc<? extends Tree> newL;
50     final WorkingCopy copy;
51     boolean initialized;
52     final TokenSequence<JavaTokenId> seq;
53
54     PositionEstimator(final List JavaDoc<? extends Tree> oldL, final List JavaDoc<? extends Tree> newL, final WorkingCopy copy) {
55         this.oldL = oldL;
56         this.newL = newL;
57         this.copy = copy;
58         this.seq = copy != null ? copy.getTokenHierarchy().tokenSequence() : null;
59         initialized = false;
60     }
61         
62     int[][] matrix;
63     
64     /**
65      * Initialize data for provided lists.
66      */

67     protected abstract void initialize();
68
69     /**
70      * Computes the offset position when inserting to {@code index}.
71      *
72      * @param index represents order in list
73      * @return offset where to insert
74      */

75     public abstract int getInsertPos(int index);
76     
77     /**
78      * Computes the start and end positions for element at {@code index}.
79      *
80      * @param index
81      * @return two integers containing start and end position
82      * @throws IndexOutOfBoundsException {@inheritDoc}
83      */

84     public abstract int[] getPositions(int index);
85
86     /**
87      * In case old list does not contain any element, try to estimate the
88      * position where to start. User has to provide empty buffers to allow
89      * to put some formatting stuff to head and tail of section.
90      *
91      * @param startPos
92      * @param aHead buffer where head formatting stuff will be added
93      * @param aTail buffer where tail formatting stuff will be added
94      * @return position where to start
95      */

96     abstract int prepare(final int startPos, StringBuilder JavaDoc aHead, StringBuilder JavaDoc aTail);
97
98     /**
99      * Returns of whole section. Used, when all item in the list are removed,
100      * e.g. when all imports are removed.
101      *
102      * @param replacement can contain the text which will replace the whole
103      * section
104      *
105      * @return start offset and end offset of the section
106      */

107     public abstract int[] sectionRemovalBounds(StringBuilder JavaDoc replacement);
108             
109     /**
110      * Return line insertion type for given estimator.
111      */

112     public LineInsertionType lineInsertType() {
113         return LineInsertionType.NONE;
114     }
115     
116     public abstract String JavaDoc head();
117     public abstract String JavaDoc sep();
118     public abstract String JavaDoc getIndentString();
119     
120     // remove the method after all calls will be refactored!
121
public int[][] getMatrix() {
122         if (!initialized) initialize();
123         return matrix;
124     }
125     
126     ////////////////////////////////////////////////////////////////////////////
127
// implementors
128
static class ImplementsEstimator extends BaseEstimator {
129         ImplementsEstimator(List JavaDoc<? extends Tree> oldL,
130                             List JavaDoc<? extends Tree> newL,
131                             WorkingCopy copy)
132         {
133             super(IMPLEMENTS, oldL, newL, copy);
134         }
135     }
136     
137     static class ExtendsEstimator extends BaseEstimator {
138         ExtendsEstimator(List JavaDoc<? extends Tree> oldL,
139                          List JavaDoc<? extends Tree> newL,
140                          WorkingCopy copy)
141         {
142             super(EXTENDS, oldL, newL, copy);
143         }
144     }
145     
146     static class ThrowsEstimator extends BaseEstimator {
147         ThrowsEstimator(List JavaDoc<? extends ExpressionTree> oldL,
148                         List JavaDoc<? extends ExpressionTree> newL,
149                         WorkingCopy copy)
150         {
151             super(THROWS, oldL, newL, copy);
152         }
153     }
154
155     /**
156      * Provides positions for imports section. Computes positions for exisiting
157      * imports and suggest insert position for newly added/inserted import.
158      */

159     static class ImportsEstimator extends PositionEstimator {
160         
161         public ImportsEstimator(final List JavaDoc<? extends ImportTree> oldL,
162                                 final List JavaDoc<? extends ImportTree> newL,
163                                 final WorkingCopy copy)
164         {
165             super(oldL, newL, copy);
166         }
167
168         List JavaDoc<int[]> data;
169         
170         @Override JavaDoc()
171         public void initialize() {
172             int size = oldL.size();
173             data = new ArrayList JavaDoc(size);
174             SourcePositions positions = copy.getTrees().getSourcePositions();
175             CompilationUnitTree compilationUnit = copy.getCompilationUnit();
176             
177             for (Tree item : oldL) {
178                 int treeStart = (int) positions.getStartPosition(compilationUnit, item);
179                 int treeEnd = (int) positions.getEndPosition(compilationUnit, item);
180                 
181                 seq.move(treeStart);
182                 seq.moveNext();
183                 int wideStart = goAfterLastNewLine(seq);
184                 seq.move(treeStart);
185                 seq.moveNext();
186                 if (null != moveToSrcRelevant(seq, Direction.BACKWARD)) {
187                     seq.moveNext();
188                 }
189                 int previousEnd = seq.offset();
190                 Token<JavaTokenId> token;
191                 while (nonRelevant.contains((token = seq.token()).id())) {
192                     int localResult = -1;
193                     switch (token.id()) {
194                         case WHITESPACE:
195                             int indexOf = token.text().toString().indexOf('\n');
196                             if (indexOf > 0) {
197                                 localResult = seq.offset() + indexOf + 1;
198                             }
199                             break;
200                         case LINE_COMMENT:
201                             previousEnd = seq.offset() + token.text().length();
202                             break;
203                     }
204                     if (localResult > 0) {
205                         previousEnd = localResult;
206                         break;
207                     }
208                     if (!seq.moveNext()) break;
209                 }
210                 seq.move(treeEnd);
211                 int wideEnd = treeEnd;
212                 while (seq.moveNext() && nonRelevant.contains((token = seq.token()).id())) {
213                     if (JavaTokenId.WHITESPACE == token.id()) {
214                         int indexOf = token.text().toString().indexOf('\n');
215                         if (indexOf > -1) {
216                             wideEnd = seq.offset() + indexOf + 1;
217                         } else {
218                             wideEnd = seq.offset();
219                         }
220                     } else if (JavaTokenId.LINE_COMMENT == token.id()) {
221                         wideEnd = seq.offset() + token.text().length();
222                         break;
223                     } else if (JavaTokenId.JAVADOC_COMMENT == token.id()) {
224                         break;
225                     }
226                 }
227                 if (wideEnd < treeEnd) wideEnd = treeEnd;
228                 data.add(new int[] { wideStart, wideEnd, previousEnd });
229             }
230             initialized = true;
231         }
232
233         @Override JavaDoc()
234         public int getInsertPos(int index) {
235             if (!initialized) initialize();
236             if (data.isEmpty()) {
237                 return -1;
238             } else {
239                 return index == data.size() ? data.get(index-1)[2] : data.get(index)[0];
240             }
241         }
242
243         // when first element is inserted, analyse the spacing and
244
// do decision about adding new lines.
245
@Override JavaDoc()
246         public int prepare(final int startPos, StringBuilder JavaDoc aHead, StringBuilder JavaDoc aTail) {
247             if (!initialized) initialize();
248             CompilationUnitTree cut = copy.getCompilationUnit();
249             int resultPos = 0;
250             if (cut.getTypeDecls().isEmpty()) {
251             } else {
252                 Tree t = cut.getTypeDecls().get(0);
253                 SourcePositions positions = copy.getTrees().getSourcePositions();
254                 int typeDeclStart = (int) positions.getStartPosition(cut, t);
255                 seq.move(typeDeclStart);
256                 moveToSrcRelevant(seq, Direction.BACKWARD);
257                 resultPos = seq.offset() + seq.token().length();
258             }
259             int counter = 0;
260             while (seq.moveNext() && nonRelevant.contains(seq.token().id()) && counter < 3) {
261                 if (JavaTokenId.WHITESPACE == seq.token().id()) {
262                     String JavaDoc white = seq.token().text().toString();
263                     int index = 0, pos = 0;
264                     while ((pos = white.indexOf('\n', pos)) > -1) {
265                         ++counter;
266                         ++pos;
267                         if (counter < 3) {
268                             index = pos;
269                         }
270                     }
271                     resultPos += index;
272                 } else if (JavaTokenId.LINE_COMMENT == seq.token().id()) {
273                     ++counter;
274                     resultPos += seq.token().text().toString().length();
275                 } else if (JavaTokenId.BLOCK_COMMENT == seq.token().id() ||
276                            JavaTokenId.JAVADOC_COMMENT == seq.token().id()) {
277                     // do not continue when javadoc comment was found!
278
break;
279                 }
280             }
281             if (counter < 3) {
282                 if (counter == 0) {
283                     aHead.append("\n\n");
284                 } else if (counter == 1) {
285                     aHead.append('\n');
286                 }
287                 aTail.append('\n');
288             }
289             return resultPos;
290         }
291         
292         @Override JavaDoc()
293         public int[] getPositions(int index) {
294             if (!initialized) initialize();
295             return data.get(index);
296         }
297         
298         public LineInsertionType lineInsertType() {
299             return LineInsertionType.AFTER;
300         }
301         
302         @Override JavaDoc()
303         public String JavaDoc head() {
304             throw new UnsupportedOperationException JavaDoc("Not applicable for imports!");
305         }
306
307         @Override JavaDoc()
308         public String JavaDoc sep() {
309             throw new UnsupportedOperationException JavaDoc("Not applicable for imports!");
310         }
311
312         @Override JavaDoc()
313         public String JavaDoc getIndentString() {
314             throw new UnsupportedOperationException JavaDoc("Not applicable for imports!");
315         }
316
317         @Override JavaDoc
318         public String JavaDoc toString() {
319             String JavaDoc result = "";
320             for (int i = 0; i < data.size(); i++) {
321                 int[] pos = data.get(i);
322                 String JavaDoc s = copy.getText().substring(pos[0], pos[1]);
323                 result += "\"" + s + "\"\n";
324             }
325             return result;
326         }
327     
328         /**
329          * Used when all elements from the list was removed.
330          */

331         public int[] sectionRemovalBounds(StringBuilder JavaDoc replacement) {
332             // this part should be generalized
333
assert !oldL.isEmpty() && newL.isEmpty(); // check the call correctness
334
SourcePositions positions = copy.getTrees().getSourcePositions();
335             CompilationUnitTree compilationUnit = copy.getCompilationUnit();
336             int sectionStart = (int) positions.getStartPosition(compilationUnit, oldL.get(0));
337             int sectionEnd = (int) positions.getEndPosition(compilationUnit, oldL.get(oldL.size()-1));
338             // end of generalization part
339

340             seq.move(sectionStart);
341             seq.moveNext();
342             Token<JavaTokenId> token;
343             while (seq.movePrevious() && nonRelevant.contains((token = seq.token()).id())) {
344                 if (JavaTokenId.LINE_COMMENT == token.id()) {
345                     seq.moveNext();
346                     sectionStart = seq.offset();
347                     break;
348                 } else if (JavaTokenId.BLOCK_COMMENT == token.id() || JavaTokenId.JAVADOC_COMMENT == token.id()) {
349                     break;
350                 } else if (JavaTokenId.WHITESPACE == token.id()) {
351                     int indexOf = token.text().toString().indexOf('\n');
352                     if (indexOf > -1) {
353                         sectionStart = seq.offset() + indexOf + 1;
354                     } else {
355                         sectionStart = seq.offset();
356                     }
357                 }
358             }
359             seq.move(sectionEnd);
360             seq.movePrevious();
361             while (seq.moveNext() && nonRelevant.contains((token = seq.token()).id())) {
362                 if (JavaTokenId.LINE_COMMENT == token.id()) {
363                     sectionEnd = seq.offset();
364                     if (seq.moveNext()) {
365                         sectionEnd = seq.offset();
366                     }
367                     break;
368                 } else if (JavaTokenId.BLOCK_COMMENT == token.id() || JavaTokenId.JAVADOC_COMMENT == token.id()) {
369                     break;
370                 } else if (JavaTokenId.WHITESPACE == token.id()) {
371                     int indexOf = token.text().toString().lastIndexOf('\n');
372                     if (indexOf > -1) {
373                         sectionEnd = seq.offset() + indexOf + 1;
374                     } else {
375                         sectionEnd += seq.offset() + token.text().length();
376                     }
377                 }
378             }
379             return new int[] { sectionStart, sectionEnd };
380         }
381     }
382
383     /**
384      * Provides position estimator for features in type declaration.
385      */

386     static class MembersEstimator extends PositionEstimator {
387         
388         public MembersEstimator(final List JavaDoc<? extends Tree> oldL,
389                                 final List JavaDoc<? extends Tree> newL,
390                                 final WorkingCopy copy)
391         {
392             super(oldL, newL, copy);
393         }
394         
395         public void initialize() {
396             int size = oldL.size();
397             matrix = new int[size+1][5];
398             matrix[size] = new int[] { -1, -1, -1, -1, -1 };
399             SourcePositions positions = copy.getTrees().getSourcePositions();
400             CompilationUnitTree compilationUnit = copy.getCompilationUnit();
401             int i = 0;
402             
403             for (Tree item : oldL) {
404                 int treeStart = (int) positions.getStartPosition(compilationUnit, item);
405                 int treeEnd = (int) positions.getEndPosition(compilationUnit, item);
406                 if (treeEnd < 0) {
407                     if (Tree.Kind.BLOCK == item.getKind()) {
408                         // handle the semicolon written in the source. Represeted
409
// by empty initializer in the source -- useful for
410
// bluff API users. -- It does not have position, this
411
// means we have to find it.
412
if (i > 0) {
413                             seq.moveIndex(matrix[i-1][4]);
414                             seq.moveNext();
415                             TokenUtilities.moveFwdToToken(seq, seq.offset(), JavaTokenId.SEMICOLON);
416                             treeStart = seq.offset();
417                             treeEnd = treeStart + 1;
418                         } else {
419                             // a ted babo rad.
420
}
421                     } else {
422                         // because the tree parsed does not represent exactly
423
// the source, we have to do many stupid hacks like
424
// this. -- Currently, we have found (hopefully) the
425
// syntetic thing which does not have its source
426
// representation.
427
continue;
428                     }
429                 }
430                 
431                 seq.move(treeStart);
432                 seq.moveNext();
433                 int startIndex = seq.index();
434                 // go back to opening/closing curly, semicolon or other
435
// token java-compiler important token.
436
moveToSrcRelevant(seq, Direction.BACKWARD);
437                 seq.moveNext();
438                 int veryBeg = seq.index();
439                 seq.move(treeEnd);
440                 matrix[i++] = new int[] { veryBeg, veryBeg, veryBeg, startIndex, seq.index() };
441                 if (i == size) {
442                     seq.move(treeEnd);
443                     matrix[i][2] = seq.index();
444                 }
445             }
446             initialized = true;
447         }
448         
449         @Override JavaDoc()
450         public int getInsertPos(int index) {
451             if (!initialized) initialize();
452             int tokenIndex = matrix[index][2];
453             // cannot do any decision about the position - probably first
454
// element is inserted, no information is available. Call has
455
// to decide.
456
if (tokenIndex == -1) return -1;
457             seq.moveIndex(tokenIndex);
458             seq.moveNext();
459             return goAfterFirstNewLine(seq);
460         }
461         
462         public String JavaDoc head() { return ""; }
463
464         public String JavaDoc sep() { return ""; }
465
466         public String JavaDoc getIndentString() { return ""; }
467         
468         public int[] getPositions(int index) {
469             if (!initialized) initialize();
470             int begin = getInsertPos(index);
471             if (matrix[index][4] != -1) {
472                 seq.moveIndex(matrix[index][4]);
473                 seq.moveNext();
474             }
475             int end = goAfterFirstNewLine(seq);
476             return new int [] { begin, end };
477         }
478         
479         public LineInsertionType lineInsertType() {
480             return LineInsertionType.AFTER;
481         }
482         
483         public int prepare(int startPos, StringBuilder JavaDoc aHead,
484                            StringBuilder JavaDoc aTail) {
485             return startPos;
486         }
487         
488         public int[] sectionRemovalBounds(StringBuilder JavaDoc replacement) {
489             throw new UnsupportedOperationException JavaDoc("Not supported yet.");
490         }
491
492     }
493     
494     /**
495      * Provides position estimator for features in type declaration.
496      */

497     static class TopLevelEstimator extends PositionEstimator {
498         
499         public TopLevelEstimator(List JavaDoc<? extends Tree> oldL,
500                                  List JavaDoc<? extends Tree> newL,
501                                  WorkingCopy copy)
502         {
503             super(oldL, newL, copy);
504         }
505
506         public void initialize() {
507             int size = oldL.size();
508             matrix = new int[size+1][5];
509             matrix[size] = new int[] { -1, -1, -1, -1, -1 };
510             SourcePositions positions = copy.getTrees().getSourcePositions();
511             CompilationUnitTree compilationUnit = copy.getCompilationUnit();
512             int i = 0;
513             
514             for (Tree item : oldL) {
515                 int treeStart = (int) positions.getStartPosition(compilationUnit, item);
516                 int treeEnd = (int) positions.getEndPosition(compilationUnit, item);
517                 // stupid hack, we have to remove syntetic constructors --
518
// should be filtered before and shouldn't be part of this
519
// collection (oldL)
520
if (treeEnd < 0) continue;
521                 
522                 seq.move(treeStart);
523                 int startIndex = seq.index();
524                 // go back to opening/closing curly, semicolon or other
525
// token java-compiler important token.
526
moveToSrcRelevant(seq, Direction.BACKWARD);
527                 seq.moveNext();
528                 int veryBeg = seq.index();
529                 seq.move(treeEnd);
530                 matrix[i++] = new int[] { veryBeg, veryBeg, veryBeg, startIndex, seq.index() };
531                 if (i == size) {
532                     seq.move(treeEnd);
533                     matrix[i][2] = seq.index();
534                 }
535             }
536         }
537         
538         @Override JavaDoc()
539         public int getInsertPos(int index) {
540             if (!initialized) initialize();
541             int tokenIndex = matrix[index][2];
542             // cannot do any decision about the position - probably first
543
// element is inserted, no information is available. Call has
544
// to decide.
545
if (tokenIndex == -1) return -1;
546             seq.moveIndex(tokenIndex);
547             seq.moveNext();
548             int off = goAfterFirstNewLine(seq);
549             return off;
550         }
551         
552         public String JavaDoc head() { return ""; }
553
554         public String JavaDoc sep() { return ""; }
555
556         public String JavaDoc getIndentString() { return ""; }
557         
558         public int[] getPositions(int index) {
559             if (!initialized) initialize();
560             int begin = getInsertPos(index);
561             if (matrix[index][4] != -1) {
562                 seq.moveIndex(matrix[index][4]);
563                 seq.moveNext();
564             }
565             int end = goAfterFirstNewLine(seq);
566             return new int [] { begin, end };
567         }
568         
569         public LineInsertionType lineInsertType() {
570             return LineInsertionType.AFTER;
571         }
572         
573         public int prepare(int startPos, StringBuilder JavaDoc aHead,
574                            StringBuilder JavaDoc aTail) {
575             return startPos;
576         }
577         
578         public int[] sectionRemovalBounds(StringBuilder JavaDoc replacement) {
579             throw new UnsupportedOperationException JavaDoc("Not supported yet.");
580         }
581
582     }
583     
584     private static abstract class BaseEstimator extends PositionEstimator {
585         
586         JavaTokenId precToken;
587         private ArrayList JavaDoc<String JavaDoc> separatorList;
588
589         private BaseEstimator(JavaTokenId precToken,
590                 List JavaDoc<? extends Tree> oldL,
591                 List JavaDoc<? extends Tree> newL,
592                 WorkingCopy copy)
593         {
594             super(oldL, newL, copy);
595             this.precToken = precToken;
596         }
597         
598         public String JavaDoc head() { return " " + precToken.fixedText() + " "; }
599         public String JavaDoc sep() { return ", "; }
600         
601         public void initialize() {
602             separatorList = new ArrayList JavaDoc<String JavaDoc>(oldL.size());
603             boolean first = true;
604             int size = oldL.size();
605             matrix = new int[size+1][5];
606             matrix[size] = new int[] { -1, -1, -1, -1, -1 };
607             TokenSequence<JavaTokenId> seq = copy.getTokenHierarchy().tokenSequence();
608             int i = 0;
609             SourcePositions positions = copy.getTrees().getSourcePositions();
610             CompilationUnitTree compilationUnit = copy.getCompilationUnit();
611             for (Tree item : oldL) {
612                 String JavaDoc separatedText = "";
613                 int treeStart = (int) positions.getStartPosition(compilationUnit, item);
614                 int treeEnd = (int) positions.getEndPosition(compilationUnit, item);
615                 seq.move(treeStart);
616                 int startIndex = seq.index();
617                 int beforer = -1;
618                 if (first) {
619                     // go back to throws keywrd.
620
while (seq.movePrevious() && seq.token().id() != precToken) ;
621                     int throwsIndex = seq.index();
622                     beforer = throwsIndex+1;
623                     // go back to closing )
624
moveToSrcRelevant(seq, Direction.BACKWARD);
625                     seq.moveNext();
626                     int beg = seq.index();
627                     seq.move(treeEnd);
628                     matrix[i++] = new int[] { beg, throwsIndex, beforer, startIndex, seq.index() };
629                     first = false;
630                 } else {
631                     int afterPrevious = matrix[i-1][4];
632                     // move to comma
633
while (seq.movePrevious() && (seq.token().id() != COMMA))
634                         if (seq.token().id() == WHITESPACE)
635                             separatedText = seq.token().text() + separatedText;
636                         else if (seq.token().id() == LINE_COMMENT)
637                             separatedText = '\n' + separatedText;
638                     separatorList.add(separatedText);
639                     int separator = seq.index();
640                     int afterSeparator = separator + 1; // bug
641
if (afterPrevious == separator) {
642                         afterPrevious = -1;
643                     }
644                     seq.move(treeEnd);
645                     matrix[i++] = new int[] { afterPrevious, separator, afterSeparator, startIndex, seq.index() };
646                 }
647                 if (i == size) {
648                     // go forward to { or ;
649
moveToSrcRelevant(seq, Direction.FORWARD);
650                     matrix[i][2] = seq.index();
651                 }
652                 seq.move(treeEnd);
653             }
654             initialized = true;
655         }
656         
657         public String JavaDoc getIndentString() {
658             if (!initialized) initialize();
659             Map JavaDoc<String JavaDoc, Integer JavaDoc> map = new HashMap JavaDoc<String JavaDoc, Integer JavaDoc>();
660             for (String JavaDoc item : separatorList) {
661                 String JavaDoc s = item;
662                 if (s.lastIndexOf("\n") > -1) {
663                     s = s.substring(item.lastIndexOf("\n"));
664                 }
665                 Integer JavaDoc count = map.get(s);
666                 if (count != null) {
667                     map.put(s, count++);
668                 } else {
669                     map.put(s, 1);
670                 }
671             }
672             int max = -1;
673             String JavaDoc s = null;
674             for (String JavaDoc item : map.keySet()) {
675                 if (map.get(item) > max) {
676                     s = item;
677                     max = map.get(item);
678                 }
679             }
680             return s;
681         }
682         
683         public int getInsertPos(int index) {
684             throw new UnsupportedOperationException JavaDoc("Not supported yet.");
685         }
686         
687         public int[] getPositions(int index) {
688             throw new UnsupportedOperationException JavaDoc("Not supported yet.");
689         }
690     
691         public int prepare(int startPos, StringBuilder JavaDoc aHead,
692                            StringBuilder JavaDoc aTail) {
693             throw new UnsupportedOperationException JavaDoc("Not supported yet.");
694         }
695         
696         public int[] sectionRemovalBounds(StringBuilder JavaDoc replacement) {
697             throw new UnsupportedOperationException JavaDoc("Not supported yet.");
698         }
699
700     }
701
702     // todo (#pf): remove - used for debugging reasons, doesn't do good job
703
public void tablePrint(int[][] matrix, TokenSequence seq) {
704         for (int i = 0; i < matrix.length; i++) {
705             for (int j = 0; j < matrix[i].length; j++) {
706                 int item = matrix[i][j];
707                 String JavaDoc s = "(nothing)";
708                 if (item > -1) {
709                     seq.moveIndex(item);
710                     seq.moveNext();
711                     s = "'" + seq.token().text();
712                 }
713                 s += "' ";
714     // System.err.print(s.substring(0, 25));
715
System.err.print(item + "\t");
716             }
717             System.err.println("");
718         }
719     }
720         
721     ////////////////////////////////////////////////////////////////////////////
722
// Utility methods
723

724     /**
725      * Moves in specified direction to java source relevant token.
726      *
727      * In other words, it moves until the token is something important
728      * for javac compiler. (every token except WHITESPACE, BLOCK_COMMENT,
729      * LINE_COMMENT and JAVADOC_COMMENT)
730      *
731      * @param seq token sequence which is used for move.
732      * @param dir direction - either forward or backward.
733      * @return relevant token identifier.
734      *
735      */

736     protected static JavaTokenId moveToSrcRelevant(TokenSequence<JavaTokenId> seq,
737                                                  Direction dir)
738     {
739         return moveToDifferentThan(seq, dir, nonRelevant);
740     }
741     
742     private static JavaTokenId moveToDifferentThan(
743         TokenSequence<JavaTokenId> seq,
744         Direction dir,
745         EnumSet JavaDoc<JavaTokenId> set)
746     {
747         boolean notBound = false;
748         switch (dir) {
749             case BACKWARD:
750                 while ((notBound = seq.movePrevious()) && set.contains(seq.token().id())) ;
751                 break;
752             case FORWARD:
753                 while ((notBound = seq.moveNext()) && set.contains(seq.token().id())) ;
754                 break;
755         }
756         return notBound ? seq.token().id() : null;
757     }
758     
759     private static int goAfterFirstNewLine(final TokenSequence<JavaTokenId> seq) {
760         // ensure that we are not after the last token, if so,
761
// go to last
762
if (seq.token() == null)
763             seq.movePrevious();
764         
765         int base = seq.offset();
766         seq.movePrevious();
767         while (seq.moveNext() && nonRelevant.contains(seq.token().id())) {
768             switch (seq.token().id()) {
769                 case LINE_COMMENT:
770                     seq.moveNext();
771                     return seq.offset();
772                 case WHITESPACE:
773                     char[] c = seq.token().text().toString().toCharArray();
774                     int index = 0;
775                     while (index < c.length) {
776                         if (c[index++] == '\n') {
777                             while (index < c.length)
778                                 if (c[index] != ' ' && c[index] != '\t')
779                                     break;
780                                 else
781                                     ++index;
782                             return base + index;
783                         }
784                     }
785             }
786         }
787         return base;
788     }
789     
790     private static int goAfterLastNewLine(final TokenSequence<JavaTokenId> seq) {
791         int base = seq.offset();
792         seq.movePrevious();
793         while (seq.moveNext() && nonRelevant.contains(seq.token().id())) ;
794         
795         while (seq.movePrevious() && nonRelevant.contains(seq.token().id())) {
796             switch (seq.token().id()) {
797                 case LINE_COMMENT:
798                     seq.moveNext();
799                     return seq.offset();
800                 case WHITESPACE:
801                     char[] c = seq.token().text().toString().toCharArray();
802                     for (int i = c.length; i > 0; ) {
803                         if (c[--i] == '\n') {
804                             return seq.offset() + i + 1;
805                         }
806                     }
807             }
808         }
809         if ((seq.index() == 0 || seq.moveNext()) && nonRelevant.contains(seq.token().id())) {
810             return seq.offset();
811         }
812         return base;
813     }
814     
815     /**
816      * Represents non-relevant tokens in java source. (Tokens which are not
817      * important for javac, i.e. line and block comments, empty lines and
818      * whitespaces.)
819      */

820     static final EnumSet JavaDoc<JavaTokenId> nonRelevant = EnumSet.<JavaTokenId>of(
821             LINE_COMMENT,
822             BLOCK_COMMENT,
823             JAVADOC_COMMENT,
824             WHITESPACE
825     );
826
827     /**
828      * Represents the direction to move. Either forward or backward.
829      */

830     protected enum Direction {
831         FORWARD, BACKWARD;
832     }
833 }
834
Popular Tags