KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > text > PositionRef


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-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.openide.text;
20
21 import org.openide.util.RequestProcessor;
22
23 import java.io.*;
24
25 import java.lang.ref.ReferenceQueue JavaDoc;
26 import java.lang.ref.WeakReference JavaDoc;
27
28 import java.util.*;
29
30 import javax.swing.text.BadLocationException JavaDoc;
31 import javax.swing.text.Element JavaDoc;
32 import javax.swing.text.Position JavaDoc;
33 import javax.swing.text.StyledDocument JavaDoc;
34
35
36 /** Reference to one position in a document.
37 * This position is held as an integer offset, or as a {@link Position} object.
38 * There is also support for serialization of positions.
39 *
40 * @author Petr Hamernik
41 */

42 public final class PositionRef extends Object JavaDoc implements Serializable {
43     static final long serialVersionUID = -4931337398907426948L;
44
45     /** Which type of position is currently holded - int X Position */
46     transient private Manager.Kind kind;
47
48     /** Manager for this position */
49     private Manager manager;
50
51     /** insert after? */
52     private boolean insertAfter;
53
54     /** Creates new <code>PositionRef</code> using the given manager at the specified
55     * position offset.
56     * @param manager manager for the position
57     * @param offset - position in the document
58     * @param bias the bias for the position
59     */

60     PositionRef(Manager manager, int offset, Position.Bias JavaDoc bias) {
61         this(manager, new Manager.OffsetKind(offset, manager), bias);
62     }
63
64     /** Creates new <code>PositionRef</code> using the given manager at the specified
65     * line and column.
66     * @param manager manager for the position
67     * @param line line number
68     * @param column column number
69     * @param bias the bias for the position
70     */

71     PositionRef(Manager manager, int line, int column, Position.Bias JavaDoc bias) {
72         this(manager, new Manager.LineKind(line, column, manager), bias);
73     }
74
75     /** Constructor for everything.
76     * @param manager manager that we are refering to
77     * @param kind kind of position we hold
78     * @param bias bias for the position
79     */

80     private PositionRef(Manager manager, Manager.Kind kind, Position.Bias JavaDoc bias) {
81         this.manager = manager;
82         this.kind = kind;
83         insertAfter = (bias == Position.Bias.Backward);
84         init();
85     }
86
87     /** Initialize variables after construction and after deserialization. */
88     private void init() {
89         kind = manager.addPosition(this);
90     }
91
92     /** Writes the manager and the offset (int). */
93     private void writeObject(ObjectOutputStream out) throws IOException {
94         out.writeBoolean(insertAfter);
95         out.writeObject(manager);
96         kind.write(out);
97     }
98
99     /** Reads the manager and the offset (int). */
100     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException JavaDoc {
101         insertAfter = in.readBoolean();
102         manager = (Manager) in.readObject();
103         kind = manager.readKind(in);
104         init();
105     }
106
107     /** @return the appropriate manager for this position ref.
108     */

109     public CloneableEditorSupport getCloneableEditorSupport() {
110         return manager.getCloneableEditorSupport();
111     }
112
113     /** @return the bias of the position
114     */

115     public Position.Bias JavaDoc getPositionBias() {
116         return insertAfter ? Position.Bias.Backward : Position.Bias.Forward;
117     }
118
119     /** @return the position as swing.text.Position object.
120     * @exception IOException when an exception occured during reading the file.
121     */

122     public Position JavaDoc getPosition() throws IOException {
123         if (manager.getCloneableEditorSupport().getDocument() == null) {
124             manager.getCloneableEditorSupport().openDocument();
125         }
126
127         synchronized (manager.getLock()) {
128             Manager.PositionKind p = (Manager.PositionKind) kind;
129
130             return p.pos;
131         }
132     }
133
134     /** @return the position as offset index in the file.
135     */

136     public int getOffset() {
137         return kind.getOffset();
138     }
139
140     /** Get the line number where this position points to.
141     * @return the line number for this position
142     * @throws IOException if the document could not be opened to check the line number
143     */

144     public int getLine() throws IOException {
145         return kind.getLine();
146     }
147
148     /** Get the column number where this position points to.
149     * @return the column number within a line (counting starts from zero)
150     * @exception IOException if the document could not be opened to check the column number
151     */

152     public int getColumn() throws IOException {
153         return kind.getColumn();
154     }
155
156     public String JavaDoc toString() {
157         return "Pos[" + getOffset() + "]" + ", kind=" + kind; // NOI18N
158
}
159
160     /** This class is responsible for the holding the Document object
161     * and the switching the status of PositionRef (Position X offset)
162     * objects which depends to this manager.
163     * It has one abstract method for the creating the StyledDocument.
164     */

165     static final class Manager extends Object JavaDoc implements Runnable JavaDoc, Serializable {
166         /** document that this thread should use */
167         // XXX never read, does it have some purpose?
168
private static ThreadLocal JavaDoc<Object JavaDoc> DOCUMENT = new ThreadLocal JavaDoc<Object JavaDoc>();
169         static final long serialVersionUID = -4374030124265110801L;
170
171         /** Head item of data structure replacing linked list here.
172          * @see ChainItem */

173         private transient ChainItem head;
174
175         /** ReferenceQueue where all <code>ChainedItem</code>'s will be enqueued to. */
176         private transient ReferenceQueue JavaDoc<PositionRef> queue;
177
178         /** Counter which counts enqued items and after reaching
179          * number 100 schedules sweepTask. */

180         private transient int counter;
181
182         /** Task which is run in RequestProcessor thread and provides
183          * full pass sweep, i.e. removes items with garbaged referents from
184          * data strucure. */

185         private transient RequestProcessor.Task sweepTask;
186
187         /** support for the editor */
188         transient private CloneableEditorSupport support;
189
190         /** the document for this manager or null if the manager is not in memory */
191         transient private StyledDocument JavaDoc doc;
192
193         /** Creates new manager
194         * @param supp support to work with
195         */

196         public Manager(CloneableEditorSupport supp) {
197             support = supp;
198             init();
199         }
200
201         /** Initialize the variables to the default values. */
202         protected void init() {
203             queue = new ReferenceQueue JavaDoc<PositionRef>();
204
205             // A stable mark used to simplify operations with the list
206
head = new ChainItem(null, queue, null);
207         }
208
209         private Object JavaDoc getLock() {
210             return support.getLock();
211         }
212
213         /** Reads the object and initialize */
214         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException JavaDoc {
215             Object JavaDoc firstObject = in.readObject();
216
217             /* Get rid of backward compatibility
218
219             if (firstObject instanceof DataObject) {
220                 DataObject obj = (DataObject)firstObject;
221                 support = (CloneableEditorSupport) obj.getCookie(CloneableEditorSupport.class);
222             } else */

223             {
224                 // first object is environment
225
CloneableEditorSupport.Env env = (CloneableEditorSupport.Env) firstObject;
226                 support = (CloneableEditorSupport) env.findCloneableOpenSupport();
227             }
228
229             if (support == null) {
230                 //PENDING - what about now ? does exist better way ?
231
throw new IOException();
232             }
233         }
234
235         final Object JavaDoc readResolve() {
236             return support.getPositionManager();
237         }
238
239         private void writeObject(ObjectOutputStream out)
240         throws IOException {
241             // old serialization version out.writeObject(support.findDataObject());
242
out.writeObject(support.cesEnv());
243         }
244
245         /** @return the styled document or null if the document is not loaded.
246         */

247         public CloneableEditorSupport getCloneableEditorSupport() {
248             return support;
249         }
250
251         /** Converts all positions into document one.
252         */

253         void documentOpened(StyledDocument JavaDoc doc) {
254             this.doc = doc;
255
256             processPositions(true);
257         }
258
259         /** Closes the document and switch all positionRefs to the offset (int)
260         * holding status (Position objects willbe forgotten.
261         */

262         void documentClosed() {
263             processPositions(false);
264
265             doc = null;
266         }
267
268         /** Gets the document this object should work on.
269          * @return docoument or null
270          */

271         private StyledDocument JavaDoc getDoc() {
272             Object JavaDoc d = DOCUMENT.get();
273
274             if (d instanceof StyledDocument JavaDoc) {
275                 return (StyledDocument JavaDoc) d;
276             }
277
278             if (d == this) {
279                 return null;
280             }
281
282             return this.doc;
283         }
284
285         /** Puts/gets positions to/from memory. It also provides full
286          * pass sweep of the data structure (inlined in the code).
287          * @param toMemory puts positions to memory if <code>true</code>,
288          * from memory if <code>false</code> */

289         private void processPositions(final boolean toMemory) {
290             // clear the queue, we'll do the sweep inline anyway
291
while (queue.poll() != null)
292                 ;
293
294             counter = 0;
295
296             /* pre-33165
297                         synchronized(this) {
298                             ChainItem previous = head;
299                             ChainItem ref = previous.next;
300
301                             while(ref != null) {
302                                 PositionRef pos = (PositionRef)ref.get();
303                                 if(pos == null) {
304                                     // Remove the item from data structure.
305                                     previous.next = ref.next;
306                                 } else {
307                                     // Process the PostionRef.
308                                     if(toMemory) {
309                                         pos.kind = pos.kind.toMemory(pos.insertAfter);
310                                     } else {
311                                         pos.kind = pos.kind.fromMemory();
312                                     }
313
314                                     previous = ref;
315                                 }
316
317                                 ref = ref.next;
318                             }
319                        }
320              */

321             new DocumentRenderer(this, DocumentRenderer.PROCESS_POSITIONS, toMemory).render();
322         }
323
324         /** Polls queue and increases the <code>counter</code> accordingly.
325          * Schedule full sweep task if counter exceedes 100. */

326         private void checkQueue() {
327             while (queue.poll() != null) {
328                 counter++;
329             }
330
331             if (counter > 100) {
332                 counter = 0;
333
334                 if (sweepTask == null) {
335                     sweepTask = RequestProcessor.getDefault().post(this);
336                 } else if (sweepTask.isFinished()) {
337                     sweepTask.schedule(0);
338                 }
339             }
340         }
341
342         /** Implements <code>Runnable</code> interface.
343          * Does full pass sweep in <code>RequestProcessor</code> thread. */

344         public synchronized void run() {
345             synchronized (getLock()) {
346                 ChainItem previous = head;
347                 ChainItem ref = previous.next;
348
349                 while (ref != null) {
350                     if (ref.get() == null) {
351                         // Remove the item from data structure.
352
previous.next = ref.next;
353                     } else {
354                         previous = ref;
355                     }
356
357                     ref = ref.next;
358                 }
359             }
360         }
361
362         /** Adds the position to this manager. */
363         Kind addPosition(final PositionRef pos) {
364             Kind kind;
365
366             /* pre-33165
367                         synchronized(this) {
368                             head.next = new ChainItem(pos, queue, head.next);
369
370                             kind = (doc == null ?
371                                         pos.kind :
372                                         pos.kind.toMemory(pos.insertAfter));
373                         }
374              */

375             kind = (Kind) new DocumentRenderer(this, DocumentRenderer.ADD_POSITION, pos).renderToObject();
376             checkQueue();
377
378             return kind;
379         }
380
381         //
382
// Kinds
383
//
384

385         /** Loads the kind from the stream */
386         Kind readKind(DataInput is) throws IOException {
387             int offset = is.readInt();
388             int line = is.readInt();
389             int column = is.readInt();
390
391             if (offset == -1) {
392                 // line and column must be valid
393
return new LineKind(line, column, this);
394             }
395
396             if ((line == -1) || (column == -1)) {
397                 // offset kind
398
return new OffsetKind(offset, this);
399             }
400
401             // out of memory representation
402
return new OutKind(offset, line, column, this);
403         }
404
405         // #19694. Item of special data structure replacing
406
// for our purposed LinkedList due to performance reasons.
407

408         /** One item which chained instanced provides data structure
409          * keeping positions for this Manager. */

410         private static class ChainItem extends WeakReference JavaDoc<PositionRef> {
411             /** Next reference keeping the position. */
412             ChainItem next;
413
414             /** Cointructs chanined item.
415              * @param position <code>PositionRef</code> as referent for this
416              * instance
417              * @param queue <code>ReferenceQueue</code> to be used for this instance
418              * @param next next chained item */

419             public ChainItem(PositionRef position, ReferenceQueue JavaDoc<PositionRef> queue, ChainItem next) {
420                 super(position, queue);
421
422                 this.next = next;
423             }
424         }
425          // End of class ChainItem.
426

427         /** Base kind with all methods */
428         private static abstract class Kind extends Object JavaDoc {
429             protected final PositionRef.Manager mgr;
430
431             Kind(PositionRef.Manager mgr) {
432                 this.mgr = mgr;
433             }
434
435             /** Offset */
436             public abstract int getOffset();
437
438             /** Get the line number */
439             public abstract int getLine() throws IOException;
440
441             /** Get the column number */
442             public abstract int getColumn() throws IOException;
443
444             /** Writes the kind to stream */
445             public abstract void write(DataOutput os) throws IOException;
446
447             /** Converts the kind to representation in memory */
448             public PositionKind toMemory(boolean insertAfter) {
449                 /* pre-33165
450                                 // try to find the right position
451                                 Position p;
452                                 try {
453                                     p = NbDocument.createPosition (doc, getOffset (), insertAfter ? Position.Bias.Forward : Position.Bias.Backward);
454                                 } catch (BadLocationException e) {
455                                     p = doc.getEndPosition ();
456                                 }
457                                 return new PositionKind (p);
458                  */

459                 return (PositionKind) new DocumentRenderer(mgr, DocumentRenderer.KIND_TO_MEMORY, this, insertAfter).renderToObject();
460             }
461
462             /** Converts the kind to representation out from memory */
463             public Kind fromMemory() {
464                 return this;
465             }
466         }
467
468         /** Kind for representing position when the document is
469         * in memory.
470         */

471         private static final class PositionKind extends Kind {
472             /** position */
473             private Position JavaDoc pos;
474
475             /** Constructor */
476             public PositionKind(Position JavaDoc pos, PositionRef.Manager mgr) {
477                 super(mgr);
478                 this.pos = pos;
479             }
480
481             /** Offset */
482             public int getOffset() {
483                 return pos.getOffset();
484             }
485
486             /** Get the line number */
487             public int getLine() {
488                 // pre-33165 return NbDocument.findLineNumber(doc, getOffset());
489
return new DocumentRenderer(mgr, DocumentRenderer.POSITION_KIND_GET_LINE, this).renderToInt();
490             }
491
492             /** Get the column number */
493             public int getColumn() {
494                 // pre-33165 return NbDocument.findLineColumn(doc, getOffset());
495
return new DocumentRenderer(mgr, DocumentRenderer.POSITION_KIND_GET_COLUMN, this).renderToInt();
496             }
497
498             /** Writes the kind to stream */
499             public void write(DataOutput os) throws IOException {
500                 /* pre-33165
501                                 int offset = getOffset();
502                                 int line = getLine();
503                                 int column = getColumn();
504                  */

505                 DocumentRenderer renderer = new DocumentRenderer(mgr, DocumentRenderer.POSITION_KIND_WRITE, this);
506
507                 int offset = renderer.renderToIntIOE();
508                 int line = renderer.getLine();
509                 int column = renderer.getColumn();
510
511                 if ((offset < 0) || (line < 0) || (column < 0)) {
512                     throw new IOException(
513                         "Illegal PositionKind: " + pos + "[offset=" // NOI18N
514
+offset + ",line=" // NOI18N
515
+line + ",column=" + column + "] in " // NOI18N
516
+mgr.getDoc() + " used by " + mgr.support + "." // NOI18N
517

518                     );
519                 }
520
521                 os.writeInt(offset);
522                 os.writeInt(line);
523                 os.writeInt(column);
524             }
525
526             /** Converts the kind to representation in memory */
527             public PositionKind toMemory(boolean insertAfter) {
528                 return this;
529             }
530
531             /** Converts the kind to representation out from memory */
532             public Kind fromMemory() {
533                 return new OutKind(this, mgr);
534             }
535         }
536
537         /** Kind for representing position when the document is
538         * out from memory. There are all infomation about the position,
539         * including offset, line and column.
540         */

541         private static final class OutKind extends Kind {
542             private int offset;
543             private int line;
544             private int column;
545
546             /** Constructs the out kind from the position kind.
547             */

548             public OutKind(PositionKind kind, PositionRef.Manager mgr) {
549                 super(mgr);
550
551                 /* pre-33165
552                                 int offset = kind.getOffset();
553                                 int line = kind.getLine();
554                                 int column = kind.getColumn();
555                  */

556                 DocumentRenderer renderer = new DocumentRenderer(mgr, DocumentRenderer.OUT_KIND_CONSTRUCTOR, kind);
557
558                 int offset = renderer.renderToInt();
559                 int line = renderer.getLine();
560                 int column = renderer.getColumn();
561
562                 if ((offset < 0) || (line < 0) || (column < 0)) {
563                     throw new IndexOutOfBoundsException JavaDoc(
564                         "Illegal OutKind[offset=" // NOI18N
565
+offset + ",line=" // NOI18N
566
+line + ",column=" + column + "] in " // NOI18N
567
+mgr.getDoc() + " used by " + mgr.support + "." // NOI18N
568

569                     );
570                 }
571
572                 this.offset = offset;
573                 this.line = line;
574                 this.column = column;
575             }
576
577             /** Constructs the out kind.
578             */

579             OutKind(int offset, int line, int column, PositionRef.Manager mgr) {
580                 super(mgr);
581                 this.offset = offset;
582                 this.line = line;
583                 this.column = column;
584             }
585
586             /** Offset */
587             public int getOffset() {
588                 return offset;
589             }
590
591             /** Get the line number */
592             public int getLine() {
593                 return line;
594             }
595
596             /** Get the column number */
597             public int getColumn() {
598                 return column;
599             }
600
601             /** Writes the kind to stream */
602             public void write(DataOutput os) throws IOException {
603                 if ((offset < 0) || (line < 0) || (column < 0)) {
604                     throw new IOException(
605                         "Illegal OutKind[offset=" // NOI18N
606
+offset + ",line=" // NOI18N
607
+line + ",column=" + column + "] in " // NOI18N
608
+mgr.getDoc() + " used by " + mgr.support + "." // NOI18N
609

610                     );
611                 }
612
613                 os.writeInt(offset);
614                 os.writeInt(line);
615                 os.writeInt(column);
616             }
617         }
618          // OutKind
619

620         /** Kind for representing position when the document is
621         * out from memory. Represents only offset in the document.
622         */

623         private static final class OffsetKind extends Kind {
624             private int offset;
625
626             /** Constructs the out kind from the position kind.
627             */

628             public OffsetKind(int offset, PositionRef.Manager mgr) {
629                 super(mgr);
630
631                 if (offset < 0) {
632                     throw new IndexOutOfBoundsException JavaDoc(
633                         "Illegal OffsetKind[offset=" // NOI18N
634
+offset + "] in " + mgr.getDoc() + " used by " // NOI18N
635
+mgr.support + "." // NOI18N
636

637                     );
638                 }
639
640                 this.offset = offset;
641             }
642
643             /** Offset */
644             public int getOffset() {
645                 return offset;
646             }
647
648             /** Get the line number */
649             public int getLine() throws IOException {
650                 // pre-33165 return NbDocument.findLineNumber(getCloneableEditorSupport().openDocument(), offset);
651
mgr.getCloneableEditorSupport().openDocument(); // make sure document is fully read
652

653                 return new DocumentRenderer(mgr, DocumentRenderer.OFFSET_KIND_GET_LINE, this, offset).renderToIntIOE();
654             }
655
656             /** Get the column number */
657             public int getColumn() throws IOException {
658                 // pre-33165 return NbDocument.findLineColumn (getCloneableEditorSupport().openDocument(), offset);
659
mgr.getCloneableEditorSupport().openDocument(); // make sure document fully read
660

661                 return new DocumentRenderer(mgr, DocumentRenderer.OFFSET_KIND_GET_COLUMN, this, offset).renderToIntIOE();
662             }
663
664             /** Writes the kind to stream */
665             public void write(DataOutput os) throws IOException {
666                 if (offset < 0) {
667                     throw new IOException(
668                         "Illegal OffsetKind[offset=" // NOI18N
669
+offset + "] in " + mgr.getDoc() + " used by " // NOI18N
670
+mgr.support + "." // NOI18N
671

672                     );
673                 }
674
675                 os.writeInt(offset);
676                 os.writeInt(-1);
677                 os.writeInt(-1);
678             }
679         }
680
681         /** Kind for representing position when the document is
682         * out from memory. Represents only line and column in the document.
683         */

684         private static final class LineKind extends Kind {
685             private int line;
686             private int column;
687
688             /** Constructor.
689             */

690             public LineKind(int line, int column, PositionRef.Manager mgr) {
691                 super(mgr);
692
693                 if ((line < 0) || (column < 0)) {
694                     throw new IndexOutOfBoundsException JavaDoc(
695                         "Illegal LineKind[line=" // NOI18N
696
+line + ",column=" + column + "] in " // NOI18N
697
+mgr.getDoc() + " used by " + mgr.support + "." // NOI18N
698

699                     );
700                 }
701
702                 this.line = line;
703                 this.column = column;
704             }
705
706             /** Offset */
707             public int getOffset() {
708                 /* pre-33165
709                                 try {
710                                     StyledDocument doc = getCloneableEditorSupport().getDocument();
711                                     if (doc == null) {
712                                         doc = getCloneableEditorSupport().openDocument();
713                                     }
714                                     return NbDocument.findLineOffset (doc, line) + column;
715                                 } catch (IOException e) {
716                                     // what to do? hopefully unlikelly
717                                     return 0;
718                                 }
719                  */

720                 try {
721                     StyledDocument JavaDoc doc = mgr.getCloneableEditorSupport().getDocument();
722
723                     if (doc == null) {
724                         doc = mgr.getCloneableEditorSupport().openDocument();
725                     }
726
727                     int retOffset = new DocumentRenderer(
728                             mgr, DocumentRenderer.LINE_KIND_GET_OFFSET, this, line, column, doc
729                         ).renderToInt();
730
731                     return retOffset;
732                 } catch (IOException e) {
733                     // what to do? hopefully unlikelly
734
return 0;
735                 }
736             }
737
738             /** Get the line number */
739             public int getLine() throws IOException {
740                 return line;
741             }
742
743             /** Get the column number */
744             public int getColumn() throws IOException {
745                 return column;
746             }
747
748             /** Writes the kind to stream */
749             public void write(DataOutput os) throws IOException {
750                 if ((line < 0) || (column < 0)) {
751                     throw new IOException(
752                         "Illegal LineKind[line=" // NOI18N
753
+line + ",column=" + column + "] in " // NOI18N
754
+mgr.getDoc() + " used by " + mgr.support + "." // NOI18N
755

756                     );
757                 }
758
759                 os.writeInt(-1);
760                 os.writeInt(line);
761                 os.writeInt(column);
762             }
763
764             /** Converts the kind to representation in memory */
765             public PositionKind toMemory(boolean insertAfter) {
766                 /* pre-33165
767                                 // try to find the right position
768                                 Position p;
769                                 try {
770                                     p = NbDocument.createPosition (doc, NbDocument.findLineOffset (doc, line) + column, insertAfter ? Position.Bias.Forward : Position.Bias.Backward);
771                                 } catch (BadLocationException e) {
772                                     p = doc.getEndPosition ();
773                                 }
774                  */

775                 Position JavaDoc p = (Position JavaDoc) new DocumentRenderer(
776                         mgr, DocumentRenderer.LINE_KIND_TO_MEMORY, this, line, column, insertAfter
777                     ).renderToObject();
778
779                 return new PositionKind(p, mgr);
780             }
781         }
782
783         /**
784          * Helper class ensuring that critical parts will run under document's read lock
785          * by using {@link javax.swing.text.Document#render(Runnable)}.
786          */

787         private static final class DocumentRenderer implements Runnable JavaDoc {
788             private static final int KIND_TO_MEMORY = 0;
789             private static final int POSITION_KIND_GET_LINE = KIND_TO_MEMORY + 1;
790             private static final int POSITION_KIND_GET_COLUMN = POSITION_KIND_GET_LINE + 1;
791             private static final int POSITION_KIND_WRITE = POSITION_KIND_GET_COLUMN + 1;
792             private static final int OUT_KIND_CONSTRUCTOR = POSITION_KIND_WRITE + 1;
793             private static final int OFFSET_KIND_GET_LINE = OUT_KIND_CONSTRUCTOR + 1;
794             private static final int OFFSET_KIND_GET_COLUMN = OFFSET_KIND_GET_LINE + 1;
795             private static final int LINE_KIND_GET_OFFSET = OFFSET_KIND_GET_COLUMN + 1;
796             private static final int LINE_KIND_TO_MEMORY = LINE_KIND_GET_OFFSET + 1;
797             private static final int PROCESS_POSITIONS = LINE_KIND_TO_MEMORY + 1;
798             private static final int ADD_POSITION = PROCESS_POSITIONS + 1;
799             private final Manager mgr;
800             private final int opCode;
801             private Kind argKind;
802             private boolean argInsertAfter;
803             private boolean argToMemory;
804             private int argInt;
805             private Object JavaDoc retObject;
806             private int retInt;
807             private int argLine;
808             private int argColumn;
809             private PositionRef argPos;
810             private StyledDocument JavaDoc argDoc;
811             private IOException ioException;
812
813             DocumentRenderer(Manager mgr, int opCode, Kind argKind) {
814                 this.mgr = mgr;
815                 this.opCode = opCode;
816                 this.argKind = argKind;
817             }
818
819             DocumentRenderer(Manager mgr, int opCode, Kind argKind, boolean argInsertAfter) {
820                 this(mgr, opCode, argKind);
821                 this.argInsertAfter = argInsertAfter;
822             }
823
824             DocumentRenderer(Manager mgr, int opCode, Kind argKind, int argInt) {
825                 this(mgr, opCode, argKind);
826                 this.argInt = argInt;
827             }
828
829             DocumentRenderer(Manager mgr, int opCode, Kind argKind, int argLine, int argColumn) {
830                 this(mgr, opCode, argKind);
831                 this.argLine = argLine;
832                 this.argColumn = argColumn;
833             }
834
835             DocumentRenderer(Manager mgr, int opCode, Kind argKind, int argLine, int argColumn, StyledDocument JavaDoc argDoc) {
836                 this(mgr, opCode, argKind, argLine, argColumn);
837                 this.argDoc = argDoc;
838             }
839
840             DocumentRenderer(Manager mgr, int opCode, Kind argKind, int argLine, int argColumn, boolean argInsertAfter) {
841                 this(mgr, opCode, argKind, argLine, argColumn);
842                 this.argInsertAfter = argInsertAfter;
843             }
844
845             DocumentRenderer(Manager mgr, int opCode, boolean toMemory) {
846                 this.mgr = mgr;
847                 this.opCode = opCode;
848                 this.argToMemory = toMemory;
849             }
850
851             DocumentRenderer(Manager mgr, int opCode, PositionRef argPos) {
852                 this.mgr = mgr;
853                 this.opCode = opCode;
854                 this.argPos = argPos;
855             }
856
857             void render() {
858                 StyledDocument JavaDoc d = mgr.getDoc();
859                 Object JavaDoc prev = DOCUMENT.get();
860
861                 try {
862                     if (d != null) {
863                         DOCUMENT.set(d);
864                         d.render(this);
865                     } else {
866                         DOCUMENT.set(mgr);
867                         this.run();
868                     }
869                 } finally {
870                     DOCUMENT.set(prev);
871                 }
872             }
873
874             Object JavaDoc renderToObjectIOE() throws IOException {
875                 Object JavaDoc o = renderToObject();
876
877                 if (ioException != null) {
878                     throw ioException;
879                 }
880
881                 return o;
882             }
883
884             Object JavaDoc renderToObject() {
885                 render();
886
887                 return retObject;
888             }
889
890             int renderToIntIOE() throws IOException {
891                 int i = renderToInt();
892
893                 if (ioException != null) {
894                     throw ioException;
895                 }
896
897                 return i;
898             }
899
900             int renderToInt() {
901                 render();
902
903                 return retInt;
904             }
905
906             int getLine() {
907                 return argLine;
908             }
909
910             int getColumn() {
911                 return argColumn;
912             }
913
914             public void run() {
915                 try {
916                     switch (opCode) {
917                     case KIND_TO_MEMORY: {
918                         // try to find the right position
919
Position JavaDoc p;
920
921                         int offset = argKind.getOffset();
922
923                         // #33165
924
// Try to use line:column instead
925
// Following code can be commented out to retain old behavior
926
if (argKind.getClass() == OutKind.class) {
927                             try {
928                                 int line = argKind.getLine();
929                                 int col = argKind.getColumn();
930                                 Element JavaDoc lineRoot = NbDocument.findLineRootElement(mgr.getDoc());
931
932                                 if (line < lineRoot.getElementCount()) {
933                                     Element JavaDoc lineElem = lineRoot.getElement(line);
934                                     int lineStartOffset = lineElem.getStartOffset();
935                                     int lineLen = lineElem.getEndOffset() - lineStartOffset;
936
937                                     if (lineLen >= 1) { // should always be at least '\n'
938
col = Math.min(col, lineLen - 1);
939                                         offset = lineStartOffset + col;
940                                     }
941                                 }
942                             } catch (IOException e) {
943                                 // use offset in that case
944
}
945                         }
946
947                         try {
948                             p = NbDocument.createPosition(
949                                     mgr.getDoc(), offset,
950                                     argInsertAfter ? Position.Bias.Backward : Position.Bias.Forward
951                                 );
952                         } catch (BadLocationException JavaDoc e) {
953                             p = mgr.getDoc().getEndPosition();
954                         }
955
956                         retObject = new PositionKind(p, mgr);
957
958                         break;
959                     }
960
961                     case POSITION_KIND_GET_LINE: {
962                         retInt = NbDocument.findLineNumber(mgr.getDoc(), argKind.getOffset());
963
964                         break;
965                     }
966
967                     case POSITION_KIND_GET_COLUMN: {
968                         retInt = NbDocument.findLineColumn(mgr.getDoc(), argKind.getOffset());
969
970                         break;
971                     }
972
973                     case POSITION_KIND_WRITE:
974                     case OUT_KIND_CONSTRUCTOR: {
975                         retInt = argKind.getOffset();
976                         argLine = argKind.getLine();
977                         argColumn = argKind.getColumn();
978
979                         break;
980                     }
981
982                     case OFFSET_KIND_GET_LINE: {
983                         retInt = NbDocument.findLineNumber(mgr.getCloneableEditorSupport().openDocument(), argInt);
984
985                         break;
986                     }
987
988                     case OFFSET_KIND_GET_COLUMN: {
989                         retInt = NbDocument.findLineColumn(mgr.getCloneableEditorSupport().openDocument(), argInt);
990
991                         break;
992                     }
993
994                     case LINE_KIND_GET_OFFSET: {
995                         retInt = NbDocument.findLineOffset(argDoc, argLine) + argColumn;
996
997                         break;
998                     }
999
1000                    case LINE_KIND_TO_MEMORY: {
1001                        // try to find the right position
1002
try {
1003                            retObject = NbDocument.createPosition(
1004                                    mgr.getDoc(), NbDocument.findLineOffset(mgr.getDoc(), argLine) + argColumn,
1005                                    argInsertAfter ? Position.Bias.Backward : Position.Bias.Forward
1006                                );
1007                        } catch (BadLocationException JavaDoc e) {
1008                            retObject = mgr.getDoc().getEndPosition();
1009                        } catch (IndexOutOfBoundsException JavaDoc e) {
1010                            retObject = mgr.getDoc().getEndPosition();
1011                        }
1012
1013                        break;
1014                    }
1015
1016                    case PROCESS_POSITIONS: {
1017                        synchronized (mgr.getLock()) {
1018                            ChainItem previous = mgr.head;
1019                            ChainItem ref = previous.next;
1020
1021                            while (ref != null) {
1022                                PositionRef pos = ref.get();
1023
1024                                if (pos == null) {
1025                                    // Remove the item from data structure.
1026
previous.next = ref.next;
1027                                } else {
1028                                    // Process the PostionRef.
1029
if (argToMemory) {
1030                                        pos.kind = pos.kind.toMemory(pos.insertAfter);
1031                                    } else {
1032                                        pos.kind = pos.kind.fromMemory();
1033                                    }
1034
1035                                    previous = ref;
1036                                }
1037
1038                                ref = ref.next;
1039                            }
1040                        }
1041
1042                        break;
1043                    }
1044
1045                    case ADD_POSITION: {
1046                        // [pnejedly] these are testability hooks
1047
mgr.support.howToReproduceDeadlock40766(true);
1048
1049                        synchronized (mgr.getLock()) {
1050                            mgr.support.howToReproduceDeadlock40766(false);
1051                            mgr.head.next = new ChainItem(argPos, mgr.queue, mgr.head.next);
1052
1053                            retObject = ((mgr.getDoc() == null) ? argPos.kind : argPos.kind.toMemory(
1054                                    argPos.insertAfter
1055                                ));
1056                        }
1057
1058                        break;
1059                    }
1060
1061                    default:
1062                        throw new IllegalStateException JavaDoc(); // Unknown opcode
1063
}
1064                } catch (IOException e) {
1065                    ioException = e;
1066                }
1067            }
1068        }
1069    }
1070}
1071
Popular Tags