alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.openide.text;

import java.io.*;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Date;
import java.util.WeakHashMap;
import org.openide.util.Lookup;

import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;

/** Represents one line in a text document.
 * The line number may change
* when the text is modified, but the identity of the line is retained. It is designed to allow line-dependent
* modules of the IDE (such as the compiler and debugger) to make use of a line consistently even as the text is modified.
*
* @author Ales Novak, Petr Hamernik, Jan Jancura, Jaroslav Tulach, David Konecny
*/
public abstract class Line extends Annotatable implements java.io.Serializable {
    /** generated Serialized Version UID */
    static final long serialVersionUID = 9113186289600795476L;

    /** Property name of the line number */
    public static final String PROP_LINE_NUMBER = "lineNumber"; // NOI18N

    /** context of this line */
    private org.openide.util.Lookup dataObject;

    /** Create a new line object based on a given data object.
     * This implementation is abstract, so the specific line number is not used here.
     * Subclasses should somehow specify the position.
     * 

* The context argument shall contain information about the * producer of the Line, that can be then extracted by {@link Line#getLookup} call. * * @param context the context for this line */ public Line(Lookup context) { if (context == null) throw new NullPointerException(); dataObject = context; } /** * Create a new line object based on a given data object. * This implementation is abstract, so the specific line number is not used here. Subclasses should somehow specify the position. * @param source the object that is producing the Line */ public Line(Object source) { this(source instanceof Lookup ? (Lookup)source : Lookups.singleton(source)); if (source == null) throw new NullPointerException(); } /** Shows the line only if the editor is open. * @see #show(int) show */ public final static int SHOW_TRY_SHOW = 0; /** Opens the editor if necessary and shows the line. * @see #show(int) show */ public final static int SHOW_SHOW = 1; /** Opens the editor if necessary, shows the line, and takes the focus. * @see #show(int) show */ public final static int SHOW_GOTO = 2; /** Instance of null implementation of Line.Part */ static final private Line.Part nullPart = new Line.NullPart(); /** Composes a human presentable name for the line. The default * implementation uses the name of data object and the line number * to create the display name. * * @return human presentable name that should identify the line */ public String getDisplayName () { return getClass().getName() + ":" + getLineNumber(); // NOI18N } /** Provides access to the context passed into the line constructor. * For example lines produced by DataEditorSupport * provide DataObject as the content of the lookup. * One can use: *

     *   dataObjectOrNull = (DataObject)line.getLookup ().lookup (DataObject.class);
     * 
* to get the access. * * @return context associated with the line * @since 4.3 */ public final org.openide.util.Lookup getLookup () { return dataObject; } /** Get the line number. The last condition in following should * always be true: *
    *   Line.Set lineSet = 
    *   Line l = 
    *   
    *   l.equals (lineSet.getCurrent (l.getLineNumber ())) 
    * 
* * @return current line number (may change as text is edited) */ public abstract int getLineNumber (); /** Show the line. * @param kind one of {@link #SHOW_TRY_SHOW}, {@link #SHOW_SHOW}, or {@link #SHOW_GOTO} * @param column the column of this line which should be selected */ public abstract void show(int kind, int column); /** Shows the line (at the first column). * @param kind one of {@link #SHOW_TRY_SHOW}, {@link #SHOW_SHOW}, or {@link #SHOW_GOTO} * @see #show(int, int) */ public void show(int kind) { show(kind, 0); } /** Set or clear a (debugger) breakpoint at this line. * @param b true to turn on * @deprecated Deprecated since 1.20. Use {@link Annotation#attach} instead. */ public abstract void setBreakpoint(boolean b); /** Test if there is a breakpoint set at this line. * @return true is there is * @deprecated Deprecated since 1.20. Use {@link Annotation} instead. */ public abstract boolean isBreakpoint(); /** Mark an error at this line. * @deprecated Deprecated since 1.20. Use {@link Annotation#attach} instead. */ public abstract void markError(); /** Unmark error at this line. * @deprecated Deprecated since 1.20. Use {@link Annotation#detach} instead. */ public abstract void unmarkError(); /** Mark this line as current. * @deprecated Deprecated since 1.20. Use {@link Annotation#attach} instead. */ public abstract void markCurrentLine(); /** Unmark this line as current. * @deprecated Deprecated since 1.20. Use {@link Annotation#detach} instead. */ public abstract void unmarkCurrentLine(); /** Method that should allow the debugger to communicate with lines that * wants to have a control over the current line of debugger. It allows the * line to refuse the current status and force the debugger to continue * over this line. *

* The default implementation simply returns true. * * @param action type of action that is trying to mark this line as current * one of constants (Debugger.ACTION_BREAKPOINT_HIT, * Debugger.ACTION_TRACE_OVER, etc.) * @param previousLine previous line (if any) or null * * @return true if this line accepts the "current" state or false if the * line wants the debugger to proceed with next instruction * * @deprecated Deprecated since 1.20, as {@link #markCurrentLine} is deprecated by {@link Annotation#attach}. */ public boolean canBeMarkedCurrent (int action, Line previousLine) { return true; } /** Create object which represent part of the text on the line. This part * of the line can be used for attaching of annotations. * @param column starting column of the part of the text * @param length length of the part of the text * @return instance of the Line.Part which represent the part of the text * @since 1.20 */ public Line.Part createPart( int column, int length ) { return nullPart; } public String getText() { return null; } /** Representation of the part of the Line's text. The part of the text is defined by * the starting column, length of the part and reference to Line. The length of the * part never cross the end of the line. * @since 1.20 */ public static abstract class Part extends Annotatable { /** Property name for the line attribute */ public static final String PROP_LINE = "line"; // NOI18N /** Property name for the column attribute */ public static final String PROP_COLUMN = "column"; // NOI18N /** Property name for the length attribute */ public static final String PROP_LENGTH = "length"; // NOI18N /** Start column of annotation * @return column at which this part begining */ public abstract int getColumn(); /** Length of the annotated text. The length does not cross line end. If the annotated text is * split during the editing, the annotation is shorten till the end of the line. Modules can listen on * changes of this value * @return length of the part */ public abstract int getLength(); /** Line can change during editting * @return reference to the Line to which this part belongs */ public abstract Line getLine(); } /** Implementation of Line.Part which is presenting empty part */ static final private class NullPart extends Part { NullPart() {} public int getColumn() { return 0; } public int getLength() { return 0; } public Line getLine() { return null; } public String getText() { return null; } } /** Object that represents a snapshot of lines at the time it was created. * It is used to create a mapping from line * numbers to line objects, for example when the file is saved. * Such a mapping can then be used by the compiler, e.g., to find * the correct {@link Line} object, assuming it has a line number. *

* Mappings of line numbers to line objects will survive modifications * of the text, and continue to represent the original lines as close as possible. * For example: if a new line is inserted at the 10th line of a document * and the compiler module asks for the 25th line (because the compiler reports an error at line 25 in the saved file) via the line set, the 26th line * of the current document will be marked as being in error. */ public static abstract class Set extends Object { /** date when the object has been created */ private Date date; /** Map which contains all lines as keys and * values weakReferences on itself. There woudl be better use * set but there is missing get method, returning equal object. * belonging to this Line.Set. * @see DocumentLine#hashCode * @see DocumentLine#equals * @see #registerLine */ private WeakHashMap whm; /** Create a new snapshot. Remembers the date when it was created. */ public Set () { date = new Date (); } /** Returns a set of line objects sorted by their * line numbers. This immutable list will contains all lines held by this * line set. * * @return list of element type {@link Line} */ public abstract java.util.List getLines (); /** Get creation time for this line set. * @return time */ public final Date getDate() { return date; } /** Find line object in the line set corresponding to original line number. * That is, finds the line in the current document which originally had the indicated line number. * If there have been modifications of that line, find one as close as possible. * * @param line number of the line * @return line object * @exception IndexOutOfBoundsException if line is an invalid index for the original set of lines */ public abstract Line getOriginal (int line) throws IndexOutOfBoundsException; /** Find line object representing the line in current document. * * * @param line number of the line in current state of the document * @return line object * @exception IndexOutOfBoundsException if line is an invalid index for the original set of lines */ public abstract Line getCurrent (int line) throws IndexOutOfBoundsException; /** Finds an original line number for given line in this line set. * @param line the line to look for * @return the number that best matches the line number of the line or -1 * if the line does seem to be produced by this line set * @since 4.38 */ public int getOriginalLineNumber (Line line) { return computeOriginal (this, line); } /** Lazyly creates or finds already created map for internal use. */ WeakHashMap findWeakHashMap () { synchronized (date) { if (whm != null) return whm; whm = new WeakHashMap (); return whm; } } /** Registers the line to this Line.Set. * @param line Line to register * @return registered Line. Note: the retruned * Line could be different (identityHashCode not equal) * from the one passed in */ final Line registerLine(Line line) { WeakHashMap lines = findWeakHashMap (); synchronized(lines) { Reference r = (Reference)lines.get(line); Line in = (r != null ? (Line)r.get() : null); if(in == null) { if(line instanceof DocumentLine) { ((DocumentLine)line).init(); } lines.put(line, new WeakReference(line)); in = line; } return in; } } /** Finds whether a line equal to provided is already registered. * @param line the line to register * @return the registered line equal to line or null */ final Line findLine (Line line) { WeakHashMap lines = findWeakHashMap (); synchronized (lines) { Reference r = (Reference)lines.get(line); Line in = (r != null ? (Line)r.get() : null); return in; } } /** A method that for a given Line.Set and a line computes the best * original line number based on the querying the set. This is called * in default implementation of getOriginal (Line) to provide * inefficient (but better then most people would write) way to * compute the number. It is static so it can be tested from * tests working on DocumentLine objects that override the * getOriginal (Line) method. * * @param set the set to search in * @param line the line to look for * @return closest possible line number for given line */ static int computeOriginal (Line.Set set, Line line) { int n = line.getLineNumber (); Line current = null; try { current = set.getOriginal (n); if (line.equals (current)) { return n; } } catch (IndexOutOfBoundsException ex) { // ok, few lines have been added and this one is now // bellow the end of the document } if (current == null) { return binarySearch (set, n, 0, findMaxLine (set)); } if (n < current.getLineNumber ()) { return binarySearch (set, n, 0, current.getLineNumber ()); } else { return binarySearch (set, n, current.getLineNumber (), findMaxLine (set)); } } /** Does a search for a given line number in a given Line.Set. */ private static int binarySearch (Line.Set set, int number, int from, int to) { while (from < to) { int middle = (from + to) / 2; Line l = set.getOriginal (middle); int ln = l.getLineNumber (); if (ln == number) { return middle; } if (ln < number) { // try after the middle from = middle + 1; } else { // try before the middle to = middle - 1; } } return from; } private static int findMaxLine (Line.Set set) { int from = 0; int to = 32000; // probably larger than any existing document for (;;) { try { set.getOriginal (to); // if the line exists, double the max number, but keep // for reference that it exists from = to; to *= 2; } catch (IndexOutOfBoundsException ex) { break; } } while (from < to) { int middle = (from + to + 1) / 2; try { set.getOriginal (middle); // line exists from = middle; } catch (IndexOutOfBoundsException ex) { // line does not exists, we have to search lower to = middle - 1; } } return from; } } // End of class Line.Set. }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.