KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > TextUtilities


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.text;
12
13
14 import java.util.HashMap JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.ListIterator JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.Set JavaDoc;
21
22 import org.eclipse.core.runtime.Assert;
23
24
25 /**
26  * A collection of text functions.
27  * <p>
28  * This class is neither intended to be instantiated nor instantiated.
29  * </p>
30  */

31 public class TextUtilities {
32
33     /**
34      * Default line delimiters used by the text functions of this class.
35      */

36     public final static String JavaDoc[] DELIMITERS= new String JavaDoc[] { "\n", "\r", "\r\n" }; //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
37

38     /**
39      * Default line delimiters used by these text functions.
40      *
41      * @deprecated use DELIMITERS instead
42      */

43     public final static String JavaDoc[] fgDelimiters= DELIMITERS;
44
45
46
47     /**
48      * Determines which one of default line delimiters appears first in the list. If none of them the
49      * hint is returned.
50      *
51      * @param text the text to be checked
52      * @param hint the line delimiter hint
53      * @return the line delimiter
54      */

55     public static String JavaDoc determineLineDelimiter(String JavaDoc text, String JavaDoc hint) {
56         try {
57             int[] info= indexOf(DELIMITERS, text, 0);
58             return DELIMITERS[info[1]];
59         } catch (ArrayIndexOutOfBoundsException JavaDoc x) {
60         }
61         return hint;
62     }
63
64     /**
65      * Returns the starting position and the index of the first matching search string
66      * in the given text that is greater than the given offset. If more than one search
67      * string matches with the same starting position then the longest one is returned.
68      *
69      * @param searchStrings the strings to search for
70      * @param text the text to be searched
71      * @param offset the offset at which to start the search
72      * @return an <code>int[]</code> with two elements where the first is the starting offset, the second the index of the found
73      * search string in the given <code>searchStrings</code> array, returns <code>[-1, -1]</code> if no match exists
74      */

75     public static int[] indexOf(String JavaDoc[] searchStrings, String JavaDoc text, int offset) {
76
77         int[] result= { -1, -1 };
78         int zeroIndex= -1;
79
80         for (int i= 0; i < searchStrings.length; i++) {
81
82             int length= searchStrings[i].length();
83
84             if (length == 0) {
85                 zeroIndex= i;
86                 continue;
87             }
88
89             int index= text.indexOf(searchStrings[i], offset);
90             if (index >= 0) {
91
92                 if (result[0] == -1) {
93                     result[0]= index;
94                     result[1]= i;
95                 } else if (index < result[0]) {
96                     result[0]= index;
97                     result[1]= i;
98                 } else if (index == result[0] && length > searchStrings[result[1]].length()) {
99                     result[0]= index;
100                     result[1]= i;
101                 }
102             }
103         }
104
105         if (zeroIndex > -1 && result[0] == -1) {
106             result[0]= 0;
107             result[1]= zeroIndex;
108         }
109
110         return result;
111     }
112
113     /**
114      * Returns the index of the longest search string with which the given text ends or
115      * <code>-1</code> if none matches.
116      *
117      * @param searchStrings the strings to search for
118      * @param text the text to search
119      * @return the index in <code>searchStrings</code> of the longest string with which <code>text</code> ends or <code>-1</code>
120      */

121     public static int endsWith(String JavaDoc[] searchStrings, String JavaDoc text) {
122
123         int index= -1;
124
125         for (int i= 0; i < searchStrings.length; i++) {
126             if (text.endsWith(searchStrings[i])) {
127                 if (index == -1 || searchStrings[i].length() > searchStrings[index].length())
128                     index= i;
129             }
130         }
131
132         return index;
133     }
134
135     /**
136      * Returns the index of the longest search string with which the given text starts or <code>-1</code>
137      * if none matches.
138      *
139      * @param searchStrings the strings to search for
140      * @param text the text to search
141      * @return the index in <code>searchStrings</code> of the longest string with which <code>text</code> starts or <code>-1</code>
142      */

143     public static int startsWith(String JavaDoc[] searchStrings, String JavaDoc text) {
144
145         int index= -1;
146
147         for (int i= 0; i < searchStrings.length; i++) {
148             if (text.startsWith(searchStrings[i])) {
149                 if (index == -1 || searchStrings[i].length() > searchStrings[index].length())
150                     index= i;
151             }
152         }
153
154         return index;
155     }
156
157     /**
158      * Returns the index of the first compare string that equals the given text or <code>-1</code>
159      * if none is equal.
160      *
161      * @param compareStrings the strings to compare with
162      * @param text the text to check
163      * @return the index of the first equal compare string or <code>-1</code>
164      */

165     public static int equals(String JavaDoc[] compareStrings, String JavaDoc text) {
166         for (int i= 0; i < compareStrings.length; i++) {
167             if (text.equals(compareStrings[i]))
168                 return i;
169         }
170         return -1;
171     }
172
173     /**
174      * Returns a document event which is an accumulation of a list of document events,
175      * <code>null</code> if the list of documentEvents is empty.
176      * The document of the document events are ignored.
177      *
178      * @param unprocessedDocument the document to which the document events would be applied
179      * @param documentEvents the list of document events to merge
180      * @return returns the merged document event
181      * @throws BadLocationException might be thrown if document is not in the correct state with respect to document events
182      */

183     public static DocumentEvent mergeUnprocessedDocumentEvents(IDocument unprocessedDocument, List JavaDoc documentEvents) throws BadLocationException {
184
185         if (documentEvents.size() == 0)
186             return null;
187
188         final Iterator JavaDoc iterator= documentEvents.iterator();
189         final DocumentEvent firstEvent= (DocumentEvent) iterator.next();
190
191         // current merged event
192
final IDocument document= unprocessedDocument;
193         int offset= firstEvent.getOffset();
194         int length= firstEvent.getLength();
195         final StringBuffer JavaDoc text= new StringBuffer JavaDoc(firstEvent.getText() == null ? "" : firstEvent.getText()); //$NON-NLS-1$
196

197         while (iterator.hasNext()) {
198
199             final int delta= text.length() - length;
200
201             final DocumentEvent event= (DocumentEvent) iterator.next();
202             final int eventOffset= event.getOffset();
203             final int eventLength= event.getLength();
204             final String JavaDoc eventText= event.getText() == null ? "" : event.getText(); //$NON-NLS-1$
205

206             // event is right from merged event
207
if (eventOffset > offset + length + delta) {
208                 final String JavaDoc string= document.get(offset + length, (eventOffset - delta) - (offset + length));
209                 text.append(string);
210                 text.append(eventText);
211
212                 length= (eventOffset - delta) + eventLength - offset;
213
214             // event is left from merged event
215
} else if (eventOffset + eventLength < offset) {
216                 final String JavaDoc string= document.get(eventOffset + eventLength, offset - (eventOffset + eventLength));
217                 text.insert(0, string);
218                 text.insert(0, eventText);
219
220                 length= offset + length - eventOffset;
221                 offset= eventOffset;
222
223             // events overlap each other
224
} else {
225                 final int start= Math.max(0, eventOffset - offset);
226                 final int end= Math.min(text.length(), eventLength + eventOffset - offset);
227                 text.replace(start, end, eventText);
228
229                 offset= Math.min(offset, eventOffset);
230                 final int totalDelta= delta + eventText.length() - eventLength;
231                 length= text.length() - totalDelta;
232             }
233         }
234
235         return new DocumentEvent(document, offset, length, text.toString());
236     }
237
238     /**
239      * Returns a document event which is an accumulation of a list of document events,
240      * <code>null</code> if the list of document events is empty.
241      * The document events being merged must all refer to the same document, to which
242      * the document changes have been already applied.
243      *
244      * @param documentEvents the list of document events to merge
245      * @return returns the merged document event
246      * @throws BadLocationException might be thrown if document is not in the correct state with respect to document events
247      */

248     public static DocumentEvent mergeProcessedDocumentEvents(List JavaDoc documentEvents) throws BadLocationException {
249
250         if (documentEvents.size() == 0)
251             return null;
252
253         final ListIterator JavaDoc iterator= documentEvents.listIterator(documentEvents.size());
254         final DocumentEvent firstEvent= (DocumentEvent) iterator.previous();
255
256         // current merged event
257
final IDocument document= firstEvent.getDocument();
258         int offset= firstEvent.getOffset();
259         int length= firstEvent.getLength();
260         int textLength= firstEvent.getText() == null ? 0 : firstEvent.getText().length();
261
262         while (iterator.hasPrevious()) {
263
264             final int delta= length - textLength;
265
266             final DocumentEvent event= (DocumentEvent) iterator.previous();
267             final int eventOffset= event.getOffset();
268             final int eventLength= event.getLength();
269             final int eventTextLength= event.getText() == null ? 0 : event.getText().length();
270
271             // event is right from merged event
272
if (eventOffset > offset + textLength + delta) {
273                 length= (eventOffset - delta) - (offset + textLength) + length + eventLength;
274                 textLength= (eventOffset - delta) + eventTextLength - offset;
275
276             // event is left from merged event
277
} else if (eventOffset + eventTextLength < offset) {
278                 length= offset - (eventOffset + eventTextLength) + length + eventLength;
279                 textLength= offset + textLength - eventOffset;
280                 offset= eventOffset;
281
282             // events overlap each other
283
} else {
284                 final int start= Math.max(0, eventOffset - offset);
285                 final int end= Math.min(length, eventTextLength + eventOffset - offset);
286                 length += eventLength - (end - start);
287
288                 offset= Math.min(offset, eventOffset);
289                 final int totalDelta= delta + eventLength - eventTextLength;
290                 textLength= length - totalDelta;
291             }
292         }
293
294         final String JavaDoc text= document.get(offset, textLength);
295         return new DocumentEvent(document, offset, length, text);
296     }
297
298     /**
299      * Removes all connected document partitioners from the given document and stores them
300      * under their partitioning name in a map. This map is returned. After this method has been called
301      * the given document is no longer connected to any document partitioner.
302      *
303      * @param document the document
304      * @return the map containing the removed partitioners
305      */

306     public static Map JavaDoc removeDocumentPartitioners(IDocument document) {
307         Map JavaDoc partitioners= new HashMap JavaDoc();
308         if (document instanceof IDocumentExtension3) {
309             IDocumentExtension3 extension3= (IDocumentExtension3) document;
310             String JavaDoc[] partitionings= extension3.getPartitionings();
311             for (int i= 0; i < partitionings.length; i++) {
312                 IDocumentPartitioner partitioner= extension3.getDocumentPartitioner(partitionings[i]);
313                 if (partitioner != null) {
314                     extension3.setDocumentPartitioner(partitionings[i], null);
315                     partitioner.disconnect();
316                     partitioners.put(partitionings[i], partitioner);
317                 }
318             }
319         } else {
320             IDocumentPartitioner partitioner= document.getDocumentPartitioner();
321             if (partitioner != null) {
322                 document.setDocumentPartitioner(null);
323                 partitioner.disconnect();
324                 partitioners.put(IDocumentExtension3.DEFAULT_PARTITIONING, partitioner);
325             }
326         }
327         return partitioners;
328     }
329
330     /**
331      * Connects the given document with all document partitioners stored in the given map under
332      * their partitioning name. This method cleans the given map.
333      *
334      * @param document the document
335      * @param partitioners the map containing the partitioners to be connected
336      * @since 3.0
337      */

338     public static void addDocumentPartitioners(IDocument document, Map JavaDoc partitioners) {
339         if (document instanceof IDocumentExtension3) {
340             IDocumentExtension3 extension3= (IDocumentExtension3) document;
341             Iterator JavaDoc e= partitioners.keySet().iterator();
342             while (e.hasNext()) {
343                 String JavaDoc partitioning= (String JavaDoc) e.next();
344                 IDocumentPartitioner partitioner= (IDocumentPartitioner) partitioners.get(partitioning);
345                 partitioner.connect(document);
346                 extension3.setDocumentPartitioner(partitioning, partitioner);
347             }
348             partitioners.clear();
349         } else {
350             IDocumentPartitioner partitioner= (IDocumentPartitioner) partitioners.get(IDocumentExtension3.DEFAULT_PARTITIONING);
351             partitioner.connect(document);
352             document.setDocumentPartitioner(partitioner);
353         }
354     }
355
356     /**
357      * Returns the content type at the given offset of the given document.
358      *
359      * @param document the document
360      * @param partitioning the partitioning to be used
361      * @param offset the offset
362      * @param preferOpenPartitions <code>true</code> if precedence should be
363      * given to a open partition ending at <code>offset</code> over a
364      * closed partition starting at <code>offset</code>
365      * @return the content type at the given offset of the document
366      * @throws BadLocationException if offset is invalid in the document
367      * @since 3.0
368      */

369     public static String JavaDoc getContentType(IDocument document, String JavaDoc partitioning, int offset, boolean preferOpenPartitions) throws BadLocationException {
370         if (document instanceof IDocumentExtension3) {
371             IDocumentExtension3 extension3= (IDocumentExtension3) document;
372             try {
373                 return extension3.getContentType(partitioning, offset, preferOpenPartitions);
374             } catch (BadPartitioningException x) {
375                 return IDocument.DEFAULT_CONTENT_TYPE;
376             }
377         }
378
379         return document.getContentType(offset);
380     }
381
382     /**
383      * Returns the partition of the given offset of the given document.
384      *
385      * @param document the document
386      * @param partitioning the partitioning to be used
387      * @param offset the offset
388      * @param preferOpenPartitions <code>true</code> if precedence should be
389      * given to a open partition ending at <code>offset</code> over a
390      * closed partition starting at <code>offset</code>
391      * @return the content type at the given offset of this viewer's input
392      * document
393      * @throws BadLocationException if offset is invalid in the given document
394      * @since 3.0
395      */

396     public static ITypedRegion getPartition(IDocument document, String JavaDoc partitioning, int offset, boolean preferOpenPartitions) throws BadLocationException {
397         if (document instanceof IDocumentExtension3) {
398             IDocumentExtension3 extension3= (IDocumentExtension3) document;
399             try {
400                 return extension3.getPartition(partitioning, offset, preferOpenPartitions);
401             } catch (BadPartitioningException x) {
402                 return new TypedRegion(0, document.getLength(), IDocument.DEFAULT_CONTENT_TYPE);
403             }
404         }
405
406         return document.getPartition(offset);
407     }
408
409     /**
410      * Computes and returns the partitioning for the given region of the given
411      * document for the given partitioning name.
412      *
413      * @param document the document
414      * @param partitioning the partitioning name
415      * @param offset the region offset
416      * @param length the region length
417      * @param includeZeroLengthPartitions whether to include zero-length partitions
418      * @return the partitioning for the given region of the given document for
419      * the given partitioning name
420      * @throws BadLocationException if the given region is invalid for the given
421      * document
422      * @since 3.0
423      */

424     public static ITypedRegion[] computePartitioning(IDocument document, String JavaDoc partitioning, int offset, int length, boolean includeZeroLengthPartitions) throws BadLocationException {
425         if (document instanceof IDocumentExtension3) {
426             IDocumentExtension3 extension3= (IDocumentExtension3) document;
427             try {
428                 return extension3.computePartitioning(partitioning, offset, length, includeZeroLengthPartitions);
429             } catch (BadPartitioningException x) {
430                 return new ITypedRegion[0];
431             }
432         }
433
434         return document.computePartitioning(offset, length);
435     }
436
437     /**
438      * Computes and returns the partition managing position categories for the
439      * given document or <code>null</code> if this was impossible.
440      *
441      * @param document the document
442      * @return the partition managing position categories or <code>null</code>
443      * @since 3.0
444      */

445     public static String JavaDoc[] computePartitionManagingCategories(IDocument document) {
446         if (document instanceof IDocumentExtension3) {
447             IDocumentExtension3 extension3= (IDocumentExtension3) document;
448             String JavaDoc[] partitionings= extension3.getPartitionings();
449             if (partitionings != null) {
450                 Set JavaDoc categories= new HashSet JavaDoc();
451                 for (int i= 0; i < partitionings.length; i++) {
452                     IDocumentPartitioner p= extension3.getDocumentPartitioner(partitionings[i]);
453                     if (p instanceof IDocumentPartitionerExtension2) {
454                         IDocumentPartitionerExtension2 extension2= (IDocumentPartitionerExtension2) p;
455                         String JavaDoc[] c= extension2.getManagingPositionCategories();
456                         if (c != null) {
457                             for (int j= 0; j < c.length; j++)
458                                 categories.add(c[j]);
459                         }
460                     }
461                 }
462                 String JavaDoc[] result= new String JavaDoc[categories.size()];
463                 categories.toArray(result);
464                 return result;
465             }
466         }
467         return null;
468     }
469
470     /**
471      * Returns the default line delimiter for the given document. This is either the delimiter of the first line, or the platform line delimiter if it is
472      * a legal line delimiter or the first one of the legal line delimiters. The default line delimiter should be used when performing document
473      * manipulations that span multiple lines.
474      *
475      * @param document the document
476      * @return the document's default line delimiter
477      * @since 3.0
478      */

479     public static String JavaDoc getDefaultLineDelimiter(IDocument document) {
480
481         if (document instanceof IDocumentExtension4)
482             return ((IDocumentExtension4)document).getDefaultLineDelimiter();
483         
484         String JavaDoc lineDelimiter= null;
485             
486         try {
487             lineDelimiter= document.getLineDelimiter(0);
488         } catch (BadLocationException x) {
489         }
490
491         if (lineDelimiter != null)
492             return lineDelimiter;
493         
494         String JavaDoc sysLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$
495
String JavaDoc[] delimiters= document.getLegalLineDelimiters();
496         Assert.isTrue(delimiters.length > 0);
497         for (int i= 0; i < delimiters.length; i++) {
498             if (delimiters[i].equals(sysLineDelimiter)) {
499                 lineDelimiter= sysLineDelimiter;
500                 break;
501             }
502         }
503         
504         if (lineDelimiter == null)
505             lineDelimiter= delimiters[0];
506
507         return lineDelimiter;
508     }
509
510     /**
511      * Returns <code>true</code> if the two regions overlap. Returns <code>false</code> if one of the
512      * arguments is <code>null</code>.
513      *
514      * @param left the left region
515      * @param right the right region
516      * @return <code>true</code> if the two regions overlap, <code>false</code> otherwise
517      * @since 3.0
518      */

519     public static boolean overlaps(IRegion left, IRegion right) {
520
521         if (left == null || right == null)
522             return false;
523
524         int rightEnd= right.getOffset() + right.getLength();
525         int leftEnd= left.getOffset()+ left.getLength();
526
527         if (right.getLength() > 0) {
528             if (left.getLength() > 0)
529                 return left.getOffset() < rightEnd && right.getOffset() < leftEnd;
530             return right.getOffset() <= left.getOffset() && left.getOffset() < rightEnd;
531         }
532
533         if (left.getLength() > 0)
534             return left.getOffset() <= right.getOffset() && right.getOffset() < leftEnd;
535
536         return left.getOffset() == right.getOffset();
537     }
538
539     /**
540      * Returns a copy of the given string array.
541      *
542      * @param array the string array to be copied
543      * @return a copy of the given string array or <code>null</code> when <code>array</code> is <code>null</code>
544      * @since 3.1
545      */

546     public static String JavaDoc[] copy(String JavaDoc[] array) {
547         if (array != null) {
548             String JavaDoc[] copy= new String JavaDoc[array.length];
549             System.arraycopy(array, 0, copy, 0, array.length);
550             return copy;
551         }
552         return null;
553     }
554
555     /**
556      * Returns a copy of the given integer array.
557      *
558      * @param array the integer array to be copied
559      * @return a copy of the given integer array or <code>null</code> when <code>array</code> is <code>null</code>
560      * @since 3.1
561      */

562     public static int[] copy(int[] array) {
563         if (array != null) {
564             int[] copy= new int[array.length];
565             System.arraycopy(array, 0, copy, 0, array.length);
566             return copy;
567         }
568         return null;
569     }
570 }
571
Popular Tags