aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/text/AbstractDocument.java
diff options
context:
space:
mode:
authorTom Tromey <tromey@gcc.gnu.org>2005-09-23 21:31:04 +0000
committerTom Tromey <tromey@gcc.gnu.org>2005-09-23 21:31:04 +0000
commit1ea63ef8be1cc54dd0de9d82c684713a1dcf1e06 (patch)
tree3ca4b2e68dc14c3128b9c781d23f1d0b1f2bee49 /libjava/classpath/javax/swing/text/AbstractDocument.java
parent9b044d19517541c95681d35a92dbc81e6e21d94f (diff)
downloadgcc-1ea63ef8be1cc54dd0de9d82c684713a1dcf1e06.zip
gcc-1ea63ef8be1cc54dd0de9d82c684713a1dcf1e06.tar.gz
gcc-1ea63ef8be1cc54dd0de9d82c684713a1dcf1e06.tar.bz2
Imported Classpath 0.18.
* sources.am, Makefile.in: Updated. * Makefile.am (nat_source_files): Removed natProxy.cc. * java/lang/reflect/natProxy.cc: Removed. * gnu/classpath/jdwp/VMFrame.java, gnu/classpath/jdwp/VMIdManager.java, gnu/classpath/jdwp/VMVirtualMachine.java, java/lang/reflect/VMProxy.java: New files. 2005-09-23 Thomas Fitzsimmons <fitzsim@redhat.com> * scripts/makemake.tcl (verbose): Add gnu/java/awt/peer/qt to BC list. 2005-09-23 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/net/DefaultContentHandlerFactory.java (getContent): Remove ClasspathToolkit references. 2005-09-23 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/awt/xlib/XCanvasPeer.java: Add new peer methods. * gnu/awt/xlib/XFramePeer.java: Likewise. * gnu/awt/xlib/XGraphicsConfiguration.java: Likewise. 2005-09-23 Thomas Fitzsimmons <fitzsim@redhat.com> * Makefile.am (libgcjawt_la_SOURCES): Remove jawt.c. Add classpath/native/jawt/jawt.c. * Makefile.in: Regenerate. * jawt.c: Remove file. * include/Makefile.am (tool_include__HEADERS): Remove jawt.h and jawt_md.h. Add ../classpath/include/jawt.h and ../classpath/include/jawt_md.h. * include/Makefile.in: Regenerate. * include/jawt.h: Regenerate. * include/jawt_md.h: Regenerate. From-SVN: r104586
Diffstat (limited to 'libjava/classpath/javax/swing/text/AbstractDocument.java')
-rw-r--r--libjava/classpath/javax/swing/text/AbstractDocument.java1236
1 files changed, 1167 insertions, 69 deletions
diff --git a/libjava/classpath/javax/swing/text/AbstractDocument.java b/libjava/classpath/javax/swing/text/AbstractDocument.java
index c3a3d70..3c9a4d4 100644
--- a/libjava/classpath/javax/swing/text/AbstractDocument.java
+++ b/libjava/classpath/javax/swing/text/AbstractDocument.java
@@ -56,70 +56,193 @@ import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoableEdit;
+/**
+ * An abstract base implementation for the {@link Document} interface.
+ * This class provides some common functionality for all <code>Element</code>s,
+ * most notably it implements a locking mechanism to make document modification
+ * thread-safe.
+ *
+ * @author original author unknown
+ * @author Roman Kennke (roman@kennke.org)
+ */
public abstract class AbstractDocument
implements Document, Serializable
{
+ /** The serial version UID for this class as of JDK1.4. */
private static final long serialVersionUID = -116069779446114664L;
-
+
+ /**
+ * Standard error message to indicate a bad location.
+ */
protected static final String BAD_LOCATION = "document location failure";
-
+
+ /**
+ * Standard name for unidirectional <code>Element</code>s.
+ */
public static final String BidiElementName = "bidi level";
+
+ /**
+ * Standard name for content <code>Element</code>s. These are usually
+ * {@link LeafElement}s.
+ */
public static final String ContentElementName = "content";
+
+ /**
+ * Standard name for paragraph <code>Element</code>s. These are usually
+ * {@link BranchElement}s.
+ */
public static final String ParagraphElementName = "paragraph";
+
+ /**
+ * Standard name for section <code>Element</code>s. These are usually
+ * {@link DefaultStyledDocument.SectionElement}s.
+ */
public static final String SectionElementName = "section";
+
+ /**
+ * Attribute key for storing the element name.
+ */
public static final String ElementNameAttribute = "$ename";
+ /**
+ * The actual content model of this <code>Document</code>.
+ */
Content content;
+
+ /**
+ * The AttributeContext for this <code>Document</code>.
+ */
AttributeContext context;
+
+ /**
+ * The currently installed <code>DocumentFilter</code>.
+ */
DocumentFilter documentFilter;
- /** The documents properties. */
+ /**
+ * The documents properties.
+ */
Dictionary properties;
+ /**
+ * Manages event listeners for this <code>Document</code>.
+ */
protected EventListenerList listenerList = new EventListenerList();
+ /**
+ * Creates a new <code>AbstractDocument</code> with the specified
+ * {@link Content} model.
+ *
+ * @param doc the <code>Content</code> model to be used in this
+ * <code>Document<code>
+ *
+ * @see GapContent
+ * @see StringContent
+ */
protected AbstractDocument(Content doc)
{
this(doc, StyleContext.getDefaultStyleContext());
}
+ /**
+ * Creates a new <code>AbstractDocument</code> with the specified
+ * {@link Content} model and {@link AttributeContext}.
+ *
+ * @param doc the <code>Content</code> model to be used in this
+ * <code>Document<code>
+ * @param ctx the <code>AttributeContext</code> to use
+ *
+ * @see GapContent
+ * @see StringContent
+ */
protected AbstractDocument(Content doc, AttributeContext ctx)
{
content = doc;
context = ctx;
}
- // These still need to be implemented by a derived class:
+ /**
+ * Returns the paragraph {@link Element} that holds the specified position.
+ *
+ * @param pos the position for which to get the paragraph element
+ *
+ * @return the paragraph {@link Element} that holds the specified position
+ */
public abstract Element getParagraphElement(int pos);
+ /**
+ * Returns the default root {@link Element} of this <code>Document</code>.
+ * Usual <code>Document</code>s only have one root element and return this.
+ * However, there may be <code>Document</code> implementations that
+ * support multiple root elements, they have to return a default root element
+ * here.
+ *
+ * @return the default root {@link Element} of this <code>Document</code>
+ */
public abstract Element getDefaultRootElement();
+ /**
+ * Creates and returns a branch element with the specified
+ * <code>parent</code> and <code>attributes</code>. Note that the new
+ * <code>Element</code> is linked to the parent <code>Element</code>
+ * through {@link Element#getParentElement}, but it is not yet added
+ * to the parent <code>Element</code> as child.
+ *
+ * @param parent the parent <code>Element</code> for the new branch element
+ * @param attributes the text attributes to be installed in the new element
+ *
+ * @return the new branch <code>Element</code>
+ *
+ * @see BranchElement
+ */
protected Element createBranchElement(Element parent,
AttributeSet attributes)
{
return new BranchElement(parent, attributes);
}
+ /**
+ * Creates and returns a leaf element with the specified
+ * <code>parent</code> and <code>attributes</code>. Note that the new
+ * <code>Element</code> is linked to the parent <code>Element</code>
+ * through {@link Element#getParentElement}, but it is not yet added
+ * to the parent <code>Element</code> as child.
+ *
+ * @param parent the parent <code>Element</code> for the new branch element
+ * @param attributes the text attributes to be installed in the new element
+ *
+ * @return the new branch <code>Element</code>
+ *
+ * @see LeafElement
+ */
protected Element createLeafElement(Element parent, AttributeSet attributes,
int start, int end)
{
return new LeafElement(parent, attributes, start, end);
}
+ /**
+ * Creates a {@link Position} that keeps track of the location at the
+ * specified <code>offset</code>.
+ *
+ * @param offset the location in the document to keep track by the new
+ * <code>Position</code>
+ *
+ * @return the newly created <code>Position</code>
+ *
+ * @throws BadLocationException if <code>offset</code> is not a valid
+ * location in the documents content model
+ */
public Position createPosition(final int offset) throws BadLocationException
{
- if (offset < 0 || offset > getLength())
- throw new BadLocationException(getText(0, getLength()), offset);
-
- return new Position()
- {
- public int getOffset()
- {
- return offset;
- }
- };
+ return content.createPosition(offset);
}
+ /**
+ * Notifies all registered listeners when the document model changes.
+ *
+ * @param event the <code>DocumentEvent</code> to be fired
+ */
protected void fireChangedUpdate(DocumentEvent event)
{
DocumentListener[] listeners = getDocumentListeners();
@@ -128,6 +251,12 @@ public abstract class AbstractDocument
listeners[index].changedUpdate(event);
}
+ /**
+ * Notifies all registered listeners when content is inserted in the document
+ * model.
+ *
+ * @param event the <code>DocumentEvent</code> to be fired
+ */
protected void fireInsertUpdate(DocumentEvent event)
{
DocumentListener[] listeners = getDocumentListeners();
@@ -136,6 +265,12 @@ public abstract class AbstractDocument
listeners[index].insertUpdate(event);
}
+ /**
+ * Notifies all registered listeners when content is removed from the
+ * document model.
+ *
+ * @param event the <code>DocumentEvent</code> to be fired
+ */
protected void fireRemoveUpdate(DocumentEvent event)
{
DocumentListener[] listeners = getDocumentListeners();
@@ -144,6 +279,12 @@ public abstract class AbstractDocument
listeners[index].removeUpdate(event);
}
+ /**
+ * Notifies all registered listeners when an <code>UndoableEdit</code> has
+ * been performed on this <code>Document</code>.
+ *
+ * @param event the <code>UndoableEditEvent</code> to be fired
+ */
protected void fireUndoableEditUpdate(UndoableEditEvent event)
{
UndoableEditListener[] listeners = getUndoableEditListeners();
@@ -152,31 +293,70 @@ public abstract class AbstractDocument
listeners[index].undoableEditHappened(event);
}
+ /**
+ * Returns the asynchronous loading priority. Returns <code>-1</code> if this
+ * document should not be loaded asynchronously.
+ *
+ * @return the asynchronous loading priority
+ */
public int getAsynchronousLoadPriority()
{
return 0;
}
+ /**
+ * Returns the {@link AttributeContext} used in this <code>Document</code>.
+ *
+ * @return the {@link AttributeContext} used in this <code>Document</code>
+ */
protected AttributeContext getAttributeContext()
{
return context;
}
+ /**
+ * Returns the root element for bidirectional content.
+ *
+ * @return the root element for bidirectional content
+ */
public Element getBidiRootElement()
{
return null;
}
+ /**
+ * Returns the {@link Content} model for this <code>Document</code>
+ *
+ * @return the {@link Content} model for this <code>Document</code>
+ *
+ * @see GapContent
+ * @see StringContent
+ */
protected Content getContent()
{
return content;
}
+ /**
+ * Returns the thread that currently modifies this <code>Document</code>
+ * if there is one, otherwise <code>null</code>. This can be used to
+ * distinguish between a method call that is part of an ongoing modification
+ * or if it is a separate modification for which a new lock must be aquired.
+ *
+ * @return the thread that currently modifies this <code>Document</code>
+ * if there is one, otherwise <code>null</code>
+ */
protected Thread getCurrentWriter()
{
+ // FIXME: Implement locking!
return null;
}
+ /**
+ * Returns the properties of this <code>Document</code>.
+ *
+ * @return the properties of this <code>Document</code>
+ */
public Dictionary getDocumentProperties()
{
// FIXME: make me thread-safe
@@ -186,8 +366,16 @@ public abstract class AbstractDocument
return properties;
}
+ /**
+ * Returns a {@link Position} which will always mark the end of the
+ * <code>Document</code>.
+ *
+ * @return a {@link Position} which will always mark the end of the
+ * <code>Document</code>
+ */
public Position getEndPosition()
{
+ // FIXME: Properly implement this by calling Content.createPosition().
return new Position()
{
public int getOffset()
@@ -197,16 +385,39 @@ public abstract class AbstractDocument
};
}
+ /**
+ * Returns the length of this <code>Document</code>'s content.
+ *
+ * @return the length of this <code>Document</code>'s content
+ */
public int getLength()
{
+ // We return Content.getLength() -1 here because there is always an
+ // implicit \n at the end of the Content which does count in Content
+ // but not in Document.
return content.length() - 1;
}
+ /**
+ * Returns all registered listeners of a given listener type.
+ *
+ * @param listenerType the type of the listeners to be queried
+ *
+ * @return all registered listeners of the specified type
+ */
public EventListener[] getListeners(Class listenerType)
{
return listenerList.getListeners(listenerType);
}
+ /**
+ * Returns a property from this <code>Document</code>'s property list.
+ *
+ * @param key the key of the property to be fetched
+ *
+ * @return the property for <code>key</code> or <code>null</code> if there
+ * is no such property stored
+ */
public Object getProperty(Object key)
{
// FIXME: make me thread-safe
@@ -217,6 +428,15 @@ public abstract class AbstractDocument
return value;
}
+ /**
+ * Returns all root elements of this <code>Document</code>. By default
+ * this just returns the single root element returned by
+ * {@link #getDefaultRootElement()}. <code>Document</code> implementations
+ * that support multiple roots must override this method and return all roots
+ * here.
+ *
+ * @return all root elements of this <code>Document</code>
+ */
public Element[] getRootElements()
{
Element[] elements = new Element[1];
@@ -224,8 +444,16 @@ public abstract class AbstractDocument
return elements;
}
+ /**
+ * Returns a {@link Position} which will always mark the beginning of the
+ * <code>Document</code>.
+ *
+ * @return a {@link Position} which will always mark the beginning of the
+ * <code>Document</code>
+ */
public Position getStartPosition()
{
+ // FIXME: Properly implement this using Content.createPosition().
return new Position()
{
public int getOffset()
@@ -235,17 +463,53 @@ public abstract class AbstractDocument
};
}
+ /**
+ * Returns a piece of this <code>Document</code>'s content.
+ *
+ * @param offset the start offset of the content
+ * @param length the length of the content
+ *
+ * @return the piece of content specified by <code>offset</code> and
+ * <code>length</code>
+ *
+ * @throws BadLocationException if <code>offset</code> or <code>offset +
+ * length</code> are invalid locations with this
+ * <code>Document</code>
+ */
public String getText(int offset, int length) throws BadLocationException
{
return content.getString(offset, length);
}
+ /**
+ * Fetches a piece of this <code>Document</code>'s content and stores
+ * it in the given {@link Segment}.
+ *
+ * @param offset the start offset of the content
+ * @param length the length of the content
+ * @param segment the <code>Segment</code> to store the content in
+ *
+ * @throws BadLocationException if <code>offset</code> or <code>offset +
+ * length</code> are invalid locations with this
+ * <code>Document</code>
+ */
public void getText(int offset, int length, Segment segment)
throws BadLocationException
{
content.getChars(offset, length, segment);
}
+ /**
+ * Inserts a String into this <code>Document</code> at the specified
+ * position and assigning the specified attributes to it.
+ *
+ * @param offset the location at which the string should be inserted
+ * @param text the content to be inserted
+ * @param attributes the text attributes to be assigned to that string
+ *
+ * @throws BadLocationException if <code>offset</code> is not a valid
+ * location in this <code>Document</code>
+ */
public void insertString(int offset, String text, AttributeSet attributes)
throws BadLocationException
{
@@ -261,14 +525,37 @@ public abstract class AbstractDocument
fireInsertUpdate(event);
}
+ /**
+ * Called to indicate that text has been inserted into this
+ * <code>Document</code>. The default implementation does nothing.
+ * This method is executed within a write lock.
+ *
+ * @param chng the <code>DefaultDocumentEvent</code> describing the change
+ * @param attr the attributes of the changed content
+ */
protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr)
{
+ // Do nothing here. Subclasses may want to override this.
}
+ /**
+ * Called after some content has been removed from this
+ * <code>Document</code>. The default implementation does nothing.
+ * This method is executed within a write lock.
+ *
+ * @param chng the <code>DefaultDocumentEvent</code> describing the change
+ */
protected void postRemoveUpdate(DefaultDocumentEvent chng)
{
+ // Do nothing here. Subclasses may want to override this.
}
+ /**
+ * Stores a property in this <code>Document</code>'s property list.
+ *
+ * @param key the key of the property to be stored
+ * @param value the value of the property to be stored
+ */
public void putProperty(Object key, Object value)
{
// FIXME: make me thread-safe
@@ -278,14 +565,31 @@ public abstract class AbstractDocument
properties.put(key, value);
}
+ /**
+ * Blocks until a read lock can be obtained.
+ */
public void readLock()
{
}
+ /**
+ * Releases the read lock. If this was the only reader on this
+ * <code>Document</code>, writing may begin now.
+ */
public void readUnlock()
{
}
+ /**
+ * Removes a piece of content from this <code>Document</code>.
+ *
+ * @param offset the start offset of the fragment to be removed
+ * @param length the length of the fragment to be removed
+ *
+ * @throws BadLocationException if <code>offset</code> or
+ * <code>offset + length</code> or invalid locations within this
+ * document
+ */
public void remove(int offset, int length) throws BadLocationException
{
DefaultDocumentEvent event =
@@ -298,7 +602,17 @@ public abstract class AbstractDocument
}
/**
- * Replaces some text in the document.
+ * Replaces a piece of content in this <code>Document</code> with
+ * another piece of content.
+ *
+ * @param offset the start offset of the fragment to be removed
+ * @param length the length of the fragment to be removed
+ * @param text the text to replace the content with
+ * @param attributes the text attributes to assign to the new content
+ *
+ * @throws BadLocationException if <code>offset</code> or
+ * <code>offset + length</code> or invalid locations within this
+ * document
*
* @since 1.4
*/
@@ -331,9 +645,9 @@ public abstract class AbstractDocument
}
/**
- * Returns add added <code>DocumentListener</code> objects.
+ * Returns all registered <code>DocumentListener</code>s.
*
- * @return an array of listeners
+ * @return all registered <code>DocumentListener</code>s
*/
public DocumentListener[] getDocumentListeners()
{
@@ -341,7 +655,7 @@ public abstract class AbstractDocument
}
/**
- * Adds a <code>UndoableEditListener</code> object to this document.
+ * Adds an {@link UndoableEditListener} to this <code>Document</code>.
*
* @param listener the listener to add
*/
@@ -351,7 +665,7 @@ public abstract class AbstractDocument
}
/**
- * Removes a <code>UndoableEditListener</code> object from this document.
+ * Removes an {@link UndoableEditListener} from this <code>Document</code>.
*
* @param listener the listener to remove
*/
@@ -361,42 +675,93 @@ public abstract class AbstractDocument
}
/**
- * Returns add added <code>UndoableEditListener</code> objects.
+ * Returns all registered {@link UndoableEditListener}s.
*
- * @return an array of listeners
+ * @return all registered {@link UndoableEditListener}s
*/
public UndoableEditListener[] getUndoableEditListeners()
{
return (UndoableEditListener[]) getListeners(UndoableEditListener.class);
}
+ /**
+ * Called before some content gets removed from this <code>Document</code>.
+ * The default implementation does nothing but may be overridden by
+ * subclasses to modify the <code>Document</code> structure in response
+ * to a remove request. The method is executed within a write lock.
+ *
+ * @param chng the <code>DefaultDocumentEvent</code> describing the change
+ */
protected void removeUpdate(DefaultDocumentEvent chng)
{
+ // Do nothing here. Subclasses may wish to override this.
}
- public void render(Runnable r)
+ /**
+ * Called to render this <code>Document</code> visually. It obtains a read
+ * lock, ensuring that no changes will be made to the <code>document</code>
+ * during the rendering process. It then calls the {@link Runnable#run()}
+ * method on <code>runnable</code>. This method <em>must not</em> attempt
+ * to modifiy the <code>Document</code>, since a deadlock will occur if it
+ * tries to obtain a write lock. When the {@link Runnable#run()} method
+ * completes (either naturally or by throwing an exception), the read lock
+ * is released. Note that there is nothing in this method related to
+ * the actual rendering. It could be used to execute arbitrary code within
+ * a read lock.
+ *
+ * @param runnable the {@link Runnable} to execute
+ */
+ public void render(Runnable runnable)
{
+ // FIXME: Implement me!
}
+ /**
+ * Sets the asynchronous loading priority for this <code>Document</code>.
+ * A value of <code>-1</code> indicates that this <code>Document</code>
+ * should be loaded synchronously.
+ *
+ * @param p the asynchronous loading priority to set
+ */
public void setAsynchronousLoadPriority(int p)
{
}
- public void setDocumentProperties(Dictionary x)
+ /**
+ * Sets the properties of this <code>Document</code>.
+ *
+ * @param p the document properties to set
+ */
+ public void setDocumentProperties(Dictionary p)
{
// FIXME: make me thread-safe
- properties = x;
+ properties = p;
}
+ /**
+ * Blocks until a write lock can be obtained.
+ */
protected void writeLock()
{
+ // FIXME: Implement me.
}
+ /**
+ * Releases the write lock. This allows waiting readers or writers to
+ * obtain the lock.
+ */
protected void writeUnlock()
{
+ // FIXME: Implement me.
}
/**
+ * Returns the currently installed {@link DocumentFilter} for this
+ * <code>Document</code>.
+ *
+ * @return the currently installed {@link DocumentFilter} for this
+ * <code>Document</code>
+ *
* @since 1.4
*/
public DocumentFilter getDocumentFilter()
@@ -405,6 +770,10 @@ public abstract class AbstractDocument
}
/**
+ * Sets the {@link DocumentFilter} for this <code>Document</code>.
+ *
+ * @param filter the <code>DocumentFilter</code> to set
+ *
* @since 1.4
*/
public void setDocumentFilter(DocumentFilter filter)
@@ -412,209 +781,592 @@ public abstract class AbstractDocument
this.documentFilter = filter;
}
+ /**
+ * Dumps diagnostic information to the specified <code>PrintStream</code>.
+ *
+ * @param out the stream to write the diagnostic information to
+ */
public void dump(PrintStream out)
{
((AbstractElement) getDefaultRootElement()).dump(out, 0);
}
+ /**
+ * Defines a set of methods for managing text attributes for one or more
+ * <code>Document</code>s.
+ *
+ * Replicating {@link AttributeSet}s throughout a <code>Document</code> can
+ * be very expensive. Implementations of this interface are intended to
+ * provide intelligent management of <code>AttributeSet</code>s, eliminating
+ * costly duplication.
+ *
+ * @see StyleContext
+ */
public interface AttributeContext
{
+ /**
+ * Returns an {@link AttributeSet} that contains the attributes
+ * of <code>old</code> plus the new attribute specified by
+ * <code>name</code> and <code>value</code>.
+ *
+ * @param old the attribute set to be merged with the new attribute
+ * @param name the name of the attribute to be added
+ * @param value the value of the attribute to be added
+ *
+ * @return the old attributes plus the new attribute
+ */
AttributeSet addAttribute(AttributeSet old, Object name, Object value);
+ /**
+ * Returns an {@link AttributeSet} that contains the attributes
+ * of <code>old</code> plus the new attributes in <code>attributes</code>.
+ *
+ * @param old the set of attributes where to add the new attributes
+ * @param attributes the attributes to be added
+ *
+ * @return an {@link AttributeSet} that contains the attributes
+ * of <code>old</code> plus the new attributes in
+ * <code>attributes</code>
+ */
AttributeSet addAttributes(AttributeSet old, AttributeSet attributes);
+ /**
+ * Returns an empty {@link AttributeSet}.
+ *
+ * @return an empty {@link AttributeSet}
+ */
AttributeSet getEmptySet();
+ /**
+ * Called to indicate that the attributes in <code>attributes</code> are
+ * no longer used.
+ *
+ * @param attributes the attributes are no longer used
+ */
void reclaim(AttributeSet attributes);
+ /**
+ * Returns a {@link AttributeSet} that has the attribute with the specified
+ * <code>name</code> removed from <code>old</code>.
+ *
+ * @param old the attribute set from which an attribute is removed
+ * @param name the name of the attribute to be removed
+ *
+ * @return the attributes of <code>old</code> minus the attribute
+ * specified by <code>name</code>
+ */
AttributeSet removeAttribute(AttributeSet old, Object name);
+ /**
+ * Removes all attributes in <code>attributes</code> from <code>old</code>
+ * and returns the resulting <code>AttributeSet</code>.
+ *
+ * @param old the set of attributes from which to remove attributes
+ * @param attributes the attributes to be removed from <code>old</code>
+ *
+ * @return the attributes of <code>old</code> minus the attributes in
+ * <code>attributes</code>
+ */
AttributeSet removeAttributes(AttributeSet old, AttributeSet attributes);
+ /**
+ * Removes all attributes specified by <code>names</code> from
+ * <code>old</code> and returns the resulting <code>AttributeSet</code>.
+ *
+ * @param old the set of attributes from which to remove attributes
+ * @param names the names of the attributes to be removed from
+ * <code>old</code>
+ *
+ * @return the attributes of <code>old</code> minus the attributes in
+ * <code>attributes</code>
+ */
AttributeSet removeAttributes(AttributeSet old, Enumeration names);
}
+ /**
+ * A sequence of data that can be edited. This is were the actual content
+ * in <code>AbstractDocument</code>'s is stored.
+ */
public interface Content
{
+ /**
+ * Creates a {@link Position} that keeps track of the location at
+ * <code>offset</code>.
+ *
+ * @return a {@link Position} that keeps track of the location at
+ * <code>offset</code>.
+ *
+ * @throw BadLocationException if <code>offset</code> is not a valid
+ * location in this <code>Content</code> model
+ */
Position createPosition(int offset) throws BadLocationException;
+ /**
+ * Returns the length of the content.
+ *
+ * @return the length of the content
+ */
int length();
+ /**
+ * Inserts a string into the content model.
+ *
+ * @param where the offset at which to insert the string
+ * @param str the string to be inserted
+ *
+ * @return an <code>UndoableEdit</code> or <code>null</code> if undo is
+ * not supported by this <code>Content</code> model
+ *
+ * @throws BadLocationException if <code>where</code> is not a valid
+ * location in this <code>Content</code> model
+ */
UndoableEdit insertString(int where, String str)
throws BadLocationException;
+ /**
+ * Removes a piece of content from the content model.
+ *
+ * @param where the offset at which to remove content
+ * @param nitems the number of characters to be removed
+ *
+ * @return an <code>UndoableEdit</code> or <code>null</code> if undo is
+ * not supported by this <code>Content</code> model
+ *
+ * @throws BadLocationException if <code>where</code> is not a valid
+ * location in this <code>Content</code> model
+ */
UndoableEdit remove(int where, int nitems) throws BadLocationException;
+ /**
+ * Returns a piece of content.
+ *
+ * @param where the start offset of the requested fragment
+ * @param len the length of the requested fragment
+ *
+ * @return the requested fragment
+ * @throws BadLocationException if <code>offset</code> or
+ * <code>offset + len</code>is not a valid
+ * location in this <code>Content</code> model
+ */
String getString(int where, int len) throws BadLocationException;
+ /**
+ * Fetches a piece of content and stores it in <code>txt</code>.
+ *
+ * @param where the start offset of the requested fragment
+ * @param len the length of the requested fragment
+ * @param txt the <code>Segment</code> where to fragment is stored into
+ *
+ * @throws BadLocationException if <code>offset</code> or
+ * <code>offset + len</code>is not a valid
+ * location in this <code>Content</code> model
+ */
void getChars(int where, int len, Segment txt) throws BadLocationException;
}
+ /**
+ * An abstract base implementation of the {@link Element} interface.
+ */
public abstract class AbstractElement
implements Element, MutableAttributeSet, TreeNode, Serializable
{
+ /** The serial version UID for AbstractElement. */
private static final long serialVersionUID = 1265312733007397733L;
+
+ /** The number of characters that this Element spans. */
int count;
+
+ /** The starting offset of this Element. */
int offset;
+ /** The attributes of this Element. */
AttributeSet attributes;
+ /** The parent element. */
Element element_parent;
+ /** The parent in the TreeNode interface. */
TreeNode tree_parent;
+
+ /** The children of this element. */
Vector tree_children;
+ /**
+ * Creates a new instance of <code>AbstractElement</code> with a
+ * specified parent <code>Element</code> and <code>AttributeSet</code>.
+ *
+ * @param p the parent of this <code>AbstractElement</code>
+ * @param s the attributes to be assigned to this
+ * <code>AbstractElement</code>
+ */
public AbstractElement(Element p, AttributeSet s)
{
element_parent = p;
- attributes = s;
+ AttributeContext ctx = getAttributeContext();
+ attributes = ctx.getEmptySet();
+ if (s != null)
+ attributes = ctx.addAttributes(attributes, s);
}
- // TreeNode implementation
-
+ /**
+ * Returns the child nodes of this <code>Element</code> as an
+ * <code>Enumeration</code> of {@link TreeNode}s.
+ *
+ * @return the child nodes of this <code>Element</code> as an
+ * <code>Enumeration</code> of {@link TreeNode}s
+ */
public abstract Enumeration children();
-
+
+ /**
+ * Returns <code>true</code> if this <code>AbstractElement</code>
+ * allows children.
+ *
+ * @return <code>true</code> if this <code>AbstractElement</code>
+ * allows children
+ */
public abstract boolean getAllowsChildren();
-
+
+ /**
+ * Returns the child of this <code>AbstractElement</code> at
+ * <code>index</code>.
+ *
+ * @param index the position in the child list of the child element to
+ * be returned
+ *
+ * @return the child of this <code>AbstractElement</code> at
+ * <code>index</code>
+ */
public TreeNode getChildAt(int index)
{
return (TreeNode) tree_children.get(index);
}
-
+
+ /**
+ * Returns the number of children of this <code>AbstractElement</code>.
+ *
+ * @return the number of children of this <code>AbstractElement</code>
+ */
public int getChildCount()
{
return tree_children.size();
}
-
+
+ /**
+ * Returns the index of a given child <code>TreeNode</code> or
+ * <code>-1</code> if <code>node</code> is not a child of this
+ * <code>AbstractElement</code>.
+ *
+ * @param node the node for which the index is requested
+ *
+ * @return the index of a given child <code>TreeNode</code> or
+ * <code>-1</code> if <code>node</code> is not a child of this
+ * <code>AbstractElement</code>
+ */
public int getIndex(TreeNode node)
{
return tree_children.indexOf(node);
}
+ /**
+ * Returns the parent <code>TreeNode</code> of this
+ * <code>AbstractElement</code> or <code>null</code> if this element
+ * has no parent.
+ *
+ * @return the parent <code>TreeNode</code> of this
+ * <code>AbstractElement</code> or <code>null</code> if this
+ * element has no parent
+ */
public TreeNode getParent()
{
return tree_parent;
}
+ /**
+ * Returns <code>true</code> if this <code>AbstractElement</code> is a
+ * leaf element, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if this <code>AbstractElement</code> is a
+ * leaf element, <code>false</code> otherwise
+ */
public abstract boolean isLeaf();
-
- // MutableAttributeSet support
-
+ /**
+ * Adds an attribute to this element.
+ *
+ * @param name the name of the attribute to be added
+ * @param value the value of the attribute to be added
+ */
public void addAttribute(Object name, Object value)
{
attributes = getAttributeContext().addAttribute(attributes, name, value);
}
+ /**
+ * Adds a set of attributes to this element.
+ *
+ * @param attrs the attributes to be added to this element
+ */
public void addAttributes(AttributeSet attrs)
{
attributes = getAttributeContext().addAttributes(attributes, attrs);
}
+ /**
+ * Removes an attribute from this element.
+ *
+ * @param name the name of the attribute to be removed
+ */
public void removeAttribute(Object name)
{
attributes = getAttributeContext().removeAttribute(attributes, name);
}
+ /**
+ * Removes a set of attributes from this element.
+ *
+ * @param attrs the attributes to be removed
+ */
public void removeAttributes(AttributeSet attrs)
{
attributes = getAttributeContext().removeAttributes(attributes, attrs);
}
+ /**
+ * Removes a set of attribute from this element.
+ *
+ * @param names the names of the attributes to be removed
+ */
public void removeAttributes(Enumeration names)
{
attributes = getAttributeContext().removeAttributes(attributes, names);
}
+ /**
+ * Sets the parent attribute set against which the element can resolve
+ * attributes that are not defined in itself.
+ *
+ * @param parent the resolve parent to set
+ */
public void setResolveParent(AttributeSet parent)
{
- attributes = getAttributeContext().addAttribute(attributes, ResolveAttribute, parent);
+ attributes = getAttributeContext().addAttribute(attributes,
+ ResolveAttribute,
+ parent);
}
-
- // AttributeSet interface support
-
+ /**
+ * Returns <code>true</code> if this element contains the specified
+ * attribute.
+ *
+ * @param name the name of the attribute to check
+ * @param value the value of the attribute to check
+ *
+ * @return <code>true</code> if this element contains the specified
+ * attribute
+ */
public boolean containsAttribute(Object name, Object value)
{
return attributes.containsAttribute(name, value);
}
+ /**
+ * Returns <code>true</code> if this element contains all of the
+ * specified attributes.
+ *
+ * @param attrs the attributes to check
+ *
+ * @return <code>true</code> if this element contains all of the
+ * specified attributes
+ */
public boolean containsAttributes(AttributeSet attrs)
{
return attributes.containsAttributes(attrs);
}
+ /**
+ * Returns a copy of the attributes of this element.
+ *
+ * @return a copy of the attributes of this element
+ */
public AttributeSet copyAttributes()
{
return attributes.copyAttributes();
}
+ /**
+ * Returns the attribute value with the specified key. If this attribute
+ * is not defined in this element and this element has a resolving
+ * parent, the search goes upward to the resolve parent chain.
+ *
+ * @param key the key of the requested attribute
+ *
+ * @return the attribute value for <code>key</code> of <code>null</code>
+ * if <code>key</code> is not found locally and cannot be resolved
+ * in this element's resolve parents
+ */
public Object getAttribute(Object key)
{
return attributes.getAttribute(key);
}
+ /**
+ * Returns the number of defined attributes in this element.
+ *
+ * @return the number of defined attributes in this element
+ */
public int getAttributeCount()
{
return attributes.getAttributeCount();
}
-
+
+ /**
+ * Returns the names of the attributes of this element.
+ *
+ * @return the names of the attributes of this element
+ */
public Enumeration getAttributeNames()
{
return attributes.getAttributeNames();
}
-
+
+ /**
+ * Returns the resolve parent of this element.
+ *
+ * @return the resolve parent of this element
+ *
+ * @see #setResolveParent(AttributeSet)
+ */
public AttributeSet getResolveParent()
{
return attributes.getResolveParent();
}
+ /**
+ * Returns <code>true</code> if an attribute with the specified name
+ * is defined in this element, <code>false</code> otherwise.
+ *
+ * @param attrName the name of the requested attributes
+ *
+ * @return <code>true</code> if an attribute with the specified name
+ * is defined in this element, <code>false</code> otherwise
+ */
public boolean isDefined(Object attrName)
{
return attributes.isDefined(attrName);
}
-
+
+ /**
+ * Returns <code>true</code> if the specified <code>AttributeSet</code>
+ * is equal to this element's <code>AttributeSet</code>, <code>false</code>
+ * otherwise.
+ *
+ * @param attrs the attributes to compare this element to
+ *
+ * @return <code>true</code> if the specified <code>AttributeSet</code>
+ * is equal to this element's <code>AttributeSet</code>,
+ * <code>false</code> otherwise
+ */
public boolean isEqual(AttributeSet attrs)
{
return attributes.isEqual(attrs);
}
- // Element interface support
-
+ /**
+ * Returns the attributes of this element.
+ *
+ * @return the attributes of this element
+ */
public AttributeSet getAttributes()
{
- return attributes;
+ return this;
}
+ /**
+ * Returns the {@link Document} to which this element belongs.
+ *
+ * @return the {@link Document} to which this element belongs
+ */
public Document getDocument()
{
return AbstractDocument.this;
}
-
+
+ /**
+ * Returns the child element at the specified <code>index</code>.
+ *
+ * @param index the index of the requested child element
+ *
+ * @return the requested element
+ */
public abstract Element getElement(int index);
-
+
+ /**
+ * Returns the name of this element.
+ *
+ * @return the name of this element
+ */
public String getName()
{
return (String) getAttribute(NameAttribute);
}
-
+
+ /**
+ * Returns the parent element of this element.
+ *
+ * @return the parent element of this element
+ */
public Element getParentElement()
{
return element_parent;
}
-
+
+ /**
+ * Returns the offset inside the document model that is after the last
+ * character of this element.
+ *
+ * @return the offset inside the document model that is after the last
+ * character of this element
+ */
public abstract int getEndOffset();
-
+
+ /**
+ * Returns the number of child elements of this element.
+ *
+ * @return the number of child elements of this element
+ */
public abstract int getElementCount();
-
+
+ /**
+ * Returns the index of the child element that spans the specified
+ * offset in the document model.
+ *
+ * @param offset the offset for which the responsible element is searched
+ *
+ * @return the index of the child element that spans the specified
+ * offset in the document model
+ */
public abstract int getElementIndex(int offset);
-
+
+ /**
+ * Returns the start offset if this element inside the document model.
+ *
+ * @return the start offset if this element inside the document model
+ */
public abstract int getStartOffset();
- private void dumpElement(PrintStream stream, String indent, Element element)
+ /**
+ * Prints diagnostic information to the specified stream.
+ *
+ * @param stream the stream to dump to
+ * @param indent the indentation level
+ * @param element the element to be dumped
+ */
+ private void dumpElement(PrintStream stream, String indent,
+ Element element)
{
+ // FIXME: Should the method be removed?
System.out.println(indent + "<" + element.getName() +">");
-
+
if (element.isLeaf())
{
int start = element.getStartOffset();
@@ -626,6 +1378,12 @@ public abstract class AbstractDocument
}
catch (BadLocationException e)
{
+ AssertionError error =
+ new AssertionError("BadLocationException should not be "
+ + "thrown here. start = " + start
+ + ", end = " + end);
+ error.initCause(e);
+ throw error;
}
System.out.println(indent + " ["
+ start + ","
@@ -638,7 +1396,13 @@ public abstract class AbstractDocument
dumpElement(stream, indent + " ", element.getElement(i));
}
}
-
+
+ /**
+ * Prints diagnostic output to the specified stream.
+ *
+ * @param stream the stream to write to
+ * @param indent the indentation level
+ */
public void dump(PrintStream stream, int indent)
{
String indentStr = "";
@@ -648,17 +1412,36 @@ public abstract class AbstractDocument
}
}
+ /**
+ * An implementation of {@link Element} to represent composite
+ * <code>Element</code>s that contain other <code>Element</code>s.
+ */
public class BranchElement extends AbstractElement
{
+ /** The serial version UID for BranchElement. */
private static final long serialVersionUID = -8595176318868717313L;
-
+
+ /** The child elements of this BranchElement. */
private Element[] children = new Element[0];
+ /**
+ * Creates a new <code>BranchElement</code> with the specified
+ * parent and attributes.
+ *
+ * @param parent the parent element of this <code>BranchElement</code>
+ * @param attributes the attributes to set on this
+ * <code>BranchElement</code>
+ */
public BranchElement(Element parent, AttributeSet attributes)
{
super(parent, attributes);
}
+ /**
+ * Returns the children of this <code>BranchElement</code>.
+ *
+ * @return the children of this <code>BranchElement</code>
+ */
public Enumeration children()
{
if (children.length == 0)
@@ -672,11 +1455,25 @@ public abstract class AbstractDocument
return tmp.elements();
}
+ /**
+ * Returns <code>true</code> since <code>BranchElements</code> allow
+ * child elements.
+ *
+ * @return <code>true</code> since <code>BranchElements</code> allow
+ * child elements
+ */
public boolean getAllowsChildren()
{
return true;
}
+ /**
+ * Returns the child element at the specified <code>index</code>.
+ *
+ * @param index the index of the requested child element
+ *
+ * @return the requested element
+ */
public Element getElement(int index)
{
if (index < 0 || index >= children.length)
@@ -685,47 +1482,113 @@ public abstract class AbstractDocument
return children[index];
}
+ /**
+ * Returns the number of child elements of this element.
+ *
+ * @return the number of child elements of this element
+ */
public int getElementCount()
{
return children.length;
}
+ /**
+ * Returns the index of the child element that spans the specified
+ * offset in the document model.
+ *
+ * @param offset the offset for which the responsible element is searched
+ *
+ * @return the index of the child element that spans the specified
+ * offset in the document model
+ */
public int getElementIndex(int offset)
{
+ // If we have no children, return -1.
+ if (getElementCount() == 0)
+ return - 1;
+
// XXX: There is surely a better algorithm
// as beginning from first element each time.
for (int index = 0; index < children.length; ++index)
{
- Element elem = children[index];
+ Element elem = children[index];
- if ((elem.getStartOffset() <= offset)
- && (offset < elem.getEndOffset()))
- return index;
+ if ((elem.getStartOffset() <= offset)
+ && (offset < elem.getEndOffset()))
+ return index;
}
- return 0;
+ // If offset is greater than the index of the last element, return
+ // the index of the last element.
+ return getElementCount() - 1;
}
+ /**
+ * Returns the offset inside the document model that is after the last
+ * character of this element.
+ * This is the end offset of the last child element. If this element
+ * has no children, this method throws a <code>NullPointerException</code>.
+ *
+ * @return the offset inside the document model that is after the last
+ * character of this element
+ *
+ * @throws NullPointerException if this branch element has no children
+ */
public int getEndOffset()
{
+ if (getElementCount() == 0)
+ throw new NullPointerException("This BranchElement has no children.");
return children[children.length - 1].getEndOffset();
}
+ /**
+ * Returns the name of this element. This is {@link #ParagraphElementName}
+ * in this case.
+ *
+ * @return the name of this element
+ */
public String getName()
{
return ParagraphElementName;
}
+ /**
+ * Returns the start offset of this element inside the document model.
+ * This is the start offset of the first child element. If this element
+ * has no children, this method throws a <code>NullPointerException</code>.
+ *
+ * @return the start offset of this element inside the document model
+ *
+ * @throws NullPointerException if this branch element has no children
+ */
public int getStartOffset()
{
+ if (getElementCount() == 0)
+ throw new NullPointerException("This BranchElement has no children.");
return children[0].getStartOffset();
}
+ /**
+ * Returns <code>false</code> since <code>BranchElement</code> are no
+ * leafes.
+ *
+ * @return <code>false</code> since <code>BranchElement</code> are no
+ * leafes
+ */
public boolean isLeaf()
{
return false;
}
+ /**
+ * Returns the <code>Element</code> at the specified <code>Document</code>
+ * offset.
+ *
+ * @return the <code>Element</code> at the specified <code>Document</code>
+ * offset
+ *
+ * @see #getElementIndex(int)
+ */
public Element positionToElement(int position)
{
// XXX: There is surely a better algorithm
@@ -742,6 +1605,13 @@ public abstract class AbstractDocument
return null;
}
+ /**
+ * Replaces a set of child elements with a new set of child elemens.
+ *
+ * @param offset the start index of the elements to be removed
+ * @param length the number of elements to be removed
+ * @param elements the new elements to be inserted
+ */
public void replace(int offset, int length, Element[] elements)
{
Element[] target = new Element[children.length - length
@@ -754,6 +1624,11 @@ public abstract class AbstractDocument
children = target;
}
+ /**
+ * Returns a string representation of this element.
+ *
+ * @return a string representation of this element
+ */
public String toString()
{
return ("BranchElement(" + getName() + ") "
@@ -761,59 +1636,157 @@ public abstract class AbstractDocument
}
}
+ /**
+ * Stores the changes when a <code>Document</code> is beeing modified.
+ */
public class DefaultDocumentEvent extends CompoundEdit
implements DocumentEvent
{
+ /** The serial version UID of DefaultDocumentEvent. */
private static final long serialVersionUID = -7406103236022413522L;
-
+
+ /** The starting offset of the change. */
private int offset;
+
+ /** The length of the change. */
private int length;
+
+ /** The type of change. */
private DocumentEvent.EventType type;
+ /**
+ * Maps <code>Element</code> to their change records.
+ */
+ Hashtable changes;
+
+ /**
+ * Creates a new <code>DefaultDocumentEvent</code>.
+ *
+ * @param offset the starting offset of the change
+ * @param length the length of the change
+ * @param type the type of change
+ */
public DefaultDocumentEvent(int offset, int length,
DocumentEvent.EventType type)
{
this.offset = offset;
this.length = length;
this.type = type;
+ changes = new Hashtable();
}
+ /**
+ * Adds an UndoableEdit to this <code>DocumentEvent</code>. If this
+ * edit is an instance of {@link ElementEdit}, then this record can
+ * later be fetched by calling {@link #getChange}.
+ *
+ * @param edit the undoable edit to add
+ */
+ public boolean addEdit(UndoableEdit edit)
+ {
+ // XXX - Fully qualify ElementChange to work around gcj bug #2499.
+ if (edit instanceof DocumentEvent.ElementChange)
+ {
+ DocumentEvent.ElementChange elEdit =
+ (DocumentEvent.ElementChange) edit;
+ changes.put(elEdit.getElement(), elEdit);
+ }
+ return super.addEdit(edit);
+ }
+
+ /**
+ * Returns the document that has been modified.
+ *
+ * @return the document that has been modified
+ */
public Document getDocument()
{
return AbstractDocument.this;
}
+ /**
+ * Returns the length of the modification.
+ *
+ * @return the length of the modification
+ */
public int getLength()
{
return length;
}
+ /**
+ * Returns the start offset of the modification.
+ *
+ * @return the start offset of the modification
+ */
public int getOffset()
{
return offset;
}
+ /**
+ * Returns the type of the modification.
+ *
+ * @return the type of the modification
+ */
public DocumentEvent.EventType getType()
{
return type;
}
+ /**
+ * Returns the changes for an element.
+ *
+ * @param elem the element for which the changes are requested
+ *
+ * @return the changes for <code>elem</code> or <code>null</code> if
+ * <code>elem</code> has not been changed
+ */
public DocumentEvent.ElementChange getChange(Element elem)
{
- return null;
+ // XXX - Fully qualify ElementChange to work around gcj bug #2499.
+ return (DocumentEvent.ElementChange) changes.get(elem);
}
}
+ /**
+ * An implementation of {@link DocumentEvent.ElementChange} to be added
+ * to {@link DefaultDocumentEvent}s.
+ */
public static class ElementEdit extends AbstractUndoableEdit
implements DocumentEvent.ElementChange
{
+ /** The serial version UID of ElementEdit. */
private static final long serialVersionUID = -1216620962142928304L;
+ /**
+ * The changed element.
+ */
private Element elem;
+
+ /**
+ * The index of the change.
+ */
private int index;
+
+ /**
+ * The removed elements.
+ */
private Element[] removed;
+
+ /**
+ * The added elements.
+ */
private Element[] added;
+ /**
+ * Creates a new <code>ElementEdit</code>.
+ *
+ * @param elem the changed element
+ * @param index the index of the change
+ * @param removed the removed elements
+ * @param added the added elements
+ */
public ElementEdit(Element elem, int index,
Element[] removed, Element[] added)
{
@@ -823,86 +1796,211 @@ public abstract class AbstractDocument
this.added = added;
}
+ /**
+ * Returns the added elements.
+ *
+ * @return the added elements
+ */
public Element[] getChildrenAdded()
{
return added;
}
-
+
+ /**
+ * Returns the removed elements.
+ *
+ * @return the removed elements
+ */
public Element[] getChildrenRemoved()
{
return removed;
}
+ /**
+ * Returns the changed element.
+ *
+ * @return the changed element
+ */
public Element getElement()
{
return elem;
}
+ /**
+ * Returns the index of the change.
+ *
+ * @return the index of the change
+ */
public int getIndex()
{
return index;
}
}
+ /**
+ * An implementation of {@link Element} that represents a leaf in the
+ * document structure. This is used to actually store content.
+ */
public class LeafElement extends AbstractElement
{
+ /** The serial version UID of LeafElement. */
private static final long serialVersionUID = 5115368706941283802L;
- int start;
- int end;
+ /** Manages the start offset of this element. */
+ Position startPos;
+
+ /** Manages the end offset of this element. */
+ Position endPos;
+
+ /**
+ * Creates a new <code>LeafElement</code>.
+ *
+ * @param parent the parent of this <code>LeafElement</code>
+ * @param attributes the attributes to be set
+ * @param start the start index of this element inside the document model
+ * @param end the end index of this element inside the document model
+ */
public LeafElement(Element parent, AttributeSet attributes, int start,
int end)
{
super(parent, attributes);
- this.start = start;
- this.end = end;
+ {
+ try
+ {
+ if (parent != null)
+ {
+ startPos = parent.getDocument().createPosition(start);
+ endPos = parent.getDocument().createPosition(end);
+ }
+ else
+ {
+ startPos = createPosition(start);
+ endPos = createPosition(end);
+ }
+ }
+ catch (BadLocationException ex)
+ {
+ AssertionError as;
+ as = new AssertionError("BadLocationException thrown "
+ + "here. start=" + start
+ + ", end=" + end
+ + ", length=" + getLength());
+ as.initCause(ex);
+ throw as;
+ }
+ }
}
+ /**
+ * Returns <code>null</code> since <code>LeafElement</code>s cannot have
+ * children.
+ *
+ * @return <code>null</code> since <code>LeafElement</code>s cannot have
+ * children
+ */
public Enumeration children()
{
return null;
}
+ /**
+ * Returns <code>false</code> since <code>LeafElement</code>s cannot have
+ * children.
+ *
+ * @return <code>false</code> since <code>LeafElement</code>s cannot have
+ * children
+ */
public boolean getAllowsChildren()
{
return false;
}
+ /**
+ * Returns <code>null</code> since <code>LeafElement</code>s cannot have
+ * children.
+ *
+ * @return <code>null</code> since <code>LeafElement</code>s cannot have
+ * children
+ */
public Element getElement(int index)
{
return null;
}
+ /**
+ * Returns <code>0</code> since <code>LeafElement</code>s cannot have
+ * children.
+ *
+ * @return <code>0</code> since <code>LeafElement</code>s cannot have
+ * children
+ */
public int getElementCount()
{
return 0;
}
+ /**
+ * Returns <code>-1</code> since <code>LeafElement</code>s cannot have
+ * children.
+ *
+ * @return <code>-1</code> since <code>LeafElement</code>s cannot have
+ * children
+ */
public int getElementIndex(int offset)
{
return -1;
}
+ /**
+ * Returns the end offset of this <code>Element</code> inside the
+ * document.
+ *
+ * @return the end offset of this <code>Element</code> inside the
+ * document
+ */
public int getEndOffset()
{
- return end;
+ return endPos.getOffset();
}
+ /**
+ * Returns the name of this <code>Element</code>. This is
+ * {@link #ContentElementName} in this case.
+ *
+ * @return the name of this <code>Element</code>
+ */
public String getName()
{
return ContentElementName;
}
+ /**
+ * Returns the start offset of this <code>Element</code> inside the
+ * document.
+ *
+ * @return the start offset of this <code>Element</code> inside the
+ * document
+ */
public int getStartOffset()
{
- return start;
+ return startPos.getOffset();
}
+ /**
+ * Returns <code>true</code>.
+ *
+ * @return <code>true</code>
+ */
public boolean isLeaf()
{
return true;
}
+ /**
+ * Returns a string representation of this <code>Element</code>.
+ *
+ * @return a string representation of this <code>Element</code>
+ */
public String toString()
{
return ("LeafElement(" + getName() + ") "