[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[cp-patches] FYI: API docs for AbstractDocument
From: |
Roman Kennke |
Subject: |
[cp-patches] FYI: API docs for AbstractDocument |
Date: |
Mon, 01 Aug 2005 14:03:24 +0200 |
User-agent: |
Mozilla Thunderbird 1.0.2 (X11/20050317) |
I added API comments all over javax.swing.text.AbstractDocument
2005-08-01 Roman Kennke <address@hidden>
* javax/swing/text/AbstractDocument.java: Added API comments
all over.
/Roman
Index: javax/swing/text/AbstractDocument.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/text/AbstractDocument.java,v
retrieving revision 1.20
diff -u -r1.20 AbstractDocument.java
--- javax/swing/text/AbstractDocument.java 29 Jul 2005 10:47:16 -0000
1.20
+++ javax/swing/text/AbstractDocument.java 1 Aug 2005 11:58:09 -0000
@@ -56,61 +56,193 @@
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoableEdit;
+/**
+ * An abstract base implementation for the address@hidden 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 (address@hidden)
+ */
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
+ * address@hidden LeafElement}s.
+ */
public static final String ContentElementName = "content";
+
+ /**
+ * Standard name for paragraph <code>Element</code>s. These are usually
+ * address@hidden BranchElement}s.
+ */
public static final String ParagraphElementName = "paragraph";
+
+ /**
+ * Standard name for section <code>Element</code>s. These are usually
+ * address@hidden 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
+ * address@hidden Content} model.
+ *
+ * @param doc the <code>Content</code> model to be used in this
+ * <code>Document<code>
+ *
+ * @see address@hidden GapContent}
+ * @see address@hidden StringContent}
+ */
protected AbstractDocument(Content doc)
{
this(doc, StyleContext.getDefaultStyleContext());
}
+ /**
+ * Creates a new <code>AbstractDocument</code> with the specified
+ * address@hidden Content} model and address@hidden 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 address@hidden GapContent}
+ * @see address@hidden StringContent}
+ */
protected AbstractDocument(Content doc, AttributeContext ctx)
{
content = doc;
context = ctx;
}
- // These still need to be implemented by a derived class:
+ /**
+ * Returns the paragraph address@hidden Element} that holds the specified
position.
+ *
+ * @param pos the position for which to get the paragraph element
+ *
+ * @return the paragraph address@hidden Element} that holds the specified
position
+ */
public abstract Element getParagraphElement(int pos);
+ /**
+ * Returns the default root address@hidden 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 address@hidden 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 address@hidden 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 address@hidden 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 address@hidden 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 address@hidden LeafElement}
+ */
protected Element createLeafElement(Element parent, AttributeSet attributes,
int start, int end)
{
return new LeafElement(parent, attributes, start, end);
}
+ /**
+ * Creates a address@hidden 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
{
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();
@@ -119,6 +251,12 @@
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();
@@ -127,6 +265,12 @@
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();
@@ -135,6 +279,12 @@
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();
@@ -143,31 +293,70 @@
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 address@hidden AttributeContext} used in this
<code>Document</code>.
+ *
+ * @return the address@hidden 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 address@hidden Content} model for this <code>Document</code>
+ *
+ * @return the address@hidden Content} model for this <code>Document</code>
+ *
+ * @see address@hidden GapContent}
+ * @see address@hidden 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
@@ -177,8 +366,16 @@
return properties;
}
+ /**
+ * Returns a address@hidden Position} which will always mark the end of the
+ * <code>Document</code>.
+ *
+ * @return a address@hidden 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()
@@ -188,16 +385,39 @@
};
}
+ /**
+ * 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.
+ *
+ * @return 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
@@ -208,6 +428,15 @@
return value;
}
+ /**
+ * Returns all root elements of this <code>Document</code>. By default
+ * this just returns the single root element returned by
+ * address@hidden #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];
@@ -215,8 +444,16 @@
return elements;
}
+ /**
+ * Returns a address@hidden Position} which will always mark the beginning
of the
+ * <code>Document</code>.
+ *
+ * @return a address@hidden 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()
@@ -226,17 +463,53 @@
};
}
+ /**
+ * 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 address@hidden 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
{
@@ -252,14 +525,37 @@
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
@@ -269,14 +565,31 @@
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 =
@@ -289,7 +602,17 @@
}
/**
- * 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
*/
@@ -322,9 +645,9 @@
}
/**
- * 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()
{
@@ -332,7 +655,7 @@
}
/**
- * Adds a <code>UndoableEditListener</code> object to this document.
+ * Adds an address@hidden UndoableEditListener} to this
<code>Document</code>.
*
* @param listener the listener to add
*/
@@ -342,7 +665,7 @@
}
/**
- * Removes a <code>UndoableEditListener</code> object from this document.
+ * Removes an address@hidden UndoableEditListener} from this
<code>Document</code>.
*
* @param listener the listener to remove
*/
@@ -352,42 +675,93 @@
}
/**
- * Returns add added <code>UndoableEditListener</code> objects.
+ * Returns all registered address@hidden UndoableEditListener}s.
*
- * @return an array of listeners
+ * @return all registered address@hidden 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 address@hidden
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 address@hidden 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 address@hidden 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 address@hidden DocumentFilter} for this
+ * <code>Document</code>.
+ *
+ * @return the currently installed address@hidden DocumentFilter} for this
+ * <code>Document</code>
+ *
* @since 1.4
*/
public DocumentFilter getDocumentFilter()
@@ -396,6 +770,10 @@
}
/**
+ * Sets the address@hidden DocumentFilter} for this <code>Document</code>.
+ *
+ * @param filter the <code>DocumentFilter</code> to set
+ *
* @since 1.4
*/
public void setDocumentFilter(DocumentFilter filter)
@@ -403,207 +781,587 @@
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 address@hidden 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 address@hidden StyleContext}
+ */
public interface AttributeContext
{
+ /**
+ * Returns an address@hidden 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 address@hidden 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 address@hidden 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 address@hidden AttributeSet}.
+ *
+ * @return an empty address@hidden 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 address@hidden 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 address@hidden Position} that keeps track of the location at
+ * <code>offset</code>.
+ *
+ * @return a address@hidden 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 address@hidden 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;
}
- // TreeNode implementation
-
+ /**
+ * Returns the child nodes of this <code>Element</code> as an
+ * <code>Enumeration</code> of address@hidden TreeNode}s.
+ *
+ * @return the child nodes of this <code>Element</code> as an
+ * <code>Enumeration</code> of address@hidden 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 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 address@hidden #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;
}
+ /**
+ * Returns the address@hidden Document} to which this element belongs.
+ *
+ * @return the address@hidden 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())
@@ -629,7 +1387,13 @@
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 = "";
@@ -639,17 +1403,36 @@
}
}
+ /**
+ * An implementation of address@hidden 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)
@@ -663,11 +1446,25 @@
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)
@@ -676,11 +1473,25 @@
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)
{
// XXX: There is surely a better algorithm
@@ -697,26 +1508,60 @@
return 0;
}
+ /**
+ * 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 int getEndOffset()
{
return children[children.length - 1].getEndOffset();
}
+ /**
+ * Returns the name of this element. This is address@hidden
#ParagraphElementName}
+ * in this case.
+ *
+ * @return the name of this element
+ */
public String getName()
{
return ParagraphElementName;
}
+ /**
+ * Returns the start offset if this element inside the document model.
+ *
+ * @return the start offset if this element inside the document model
+ */
public int getStartOffset()
{
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 address@hidden #getElementIndex(int)}
+ */
public Element positionToElement(int position)
{
// XXX: There is surely a better algorithm
@@ -733,6 +1578,13 @@
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
@@ -745,6 +1597,11 @@
children = target;
}
+ /**
+ * Returns a string representation of this element.
+ *
+ * @return a string representation of this element
+ */
public String toString()
{
return ("BranchElement(" + getName() + ") "
@@ -752,15 +1609,31 @@
}
}
+ /**
+ * 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;
+ /**
+ * 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)
{
@@ -769,42 +1642,98 @@
this.type = type;
}
+ /**
+ * 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;
}
}
+ /**
+ * An implementation of address@hidden DocumentEvent.ElementChange} to be
added
+ * to address@hidden 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)
{
@@ -814,29 +1743,54 @@
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 address@hidden 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;
/** Manages the start offset of this element. */
@@ -845,6 +1799,14 @@
/** 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)
{
@@ -862,51 +1824,116 @@
}
}
+ /**
+ * 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 endPos.getOffset();
}
+ /**
+ * Returns the name of this <code>Element</code>. This is
+ * address@hidden #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 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() + ") "
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [cp-patches] FYI: API docs for AbstractDocument,
Roman Kennke <=