- All Implemented Interfaces:
Serializable
,Document
- Direct Known Subclasses:
DefaultStyledDocument
,PlainDocument
public abstract class AbstractDocument extends Object implements Document, Serializable
This class implements a locking mechanism for the document. It
allows multiple readers or one writer, and writers must wait until
all observers of the document have been notified of a previous
change before beginning another mutation to the document. The
read lock is acquired and released using the render
method. A write lock is acquired by the methods that mutate the
document, and are held for the duration of the method call.
Notification is done on the thread that produced the mutation,
and the thread has full read access to the document for the
duration of the notification, but other readers are kept out
until the notification has finished. The notification is a
beans event notification which does not allow any further
mutations until all listeners have been notified.
Any models subclassed from this class and used in conjunction
with a text component that has a look and feel implementation
that is derived from BasicTextUI may be safely updated
asynchronously, because all access to the View hierarchy
is serialized by BasicTextUI if the document is of type
AbstractDocument
. The locking assumes that an
independent thread will access the View hierarchy only from
the DocumentListener methods, and that there will be only
one event thread active at a time.
If concurrency support is desired, there are the following
additional implications. The code path for any DocumentListener
implementation and any UndoListener implementation must be threadsafe,
and not access the component lock if trying to be safe from deadlocks.
The repaint
and revalidate
methods
on JComponent are safe.
AbstractDocument models an implied break at the end of the document.
Among other things this allows you to position the caret after the last
character. As a result of this, getLength
returns one less
than the length of the Content. If you create your own Content, be
sure and initialize it to have an additional character. Refer to
StringContent and GapContent for examples of this. Another implication
of this is that Elements that model the implied end character will have
an endOffset == (getLength() + 1). For example, in DefaultStyledDocument
getParagraphElement(getLength()).getEndOffset() == getLength() + 1
.
Warning:
Serialized objects of this class will not be compatible with
future Swing releases. The current serialization support is
appropriate for short term storage or RMI between applications running
the same version of Swing. As of 1.4, support for long term storage
of all JavaBeans™
has been added to the java.beans
package.
Please see XMLEncoder
.
-
Nested Class Summary
Nested Classes Modifier and Type Class Description class
AbstractDocument.AbstractElement
Implements the abstract part of an element.static interface
AbstractDocument.AttributeContext
An interface that can be used to allow MutableAttributeSet implementations to use pluggable attribute compression techniques.class
AbstractDocument.BranchElement
Implements a composite element that contains other elements.static interface
AbstractDocument.Content
Interface to describe a sequence of character content that can be edited.class
AbstractDocument.DefaultDocumentEvent
Stores document changes as the document is being modified.static class
AbstractDocument.ElementEdit
An implementation of ElementChange that can be added to the document event.class
AbstractDocument.LeafElement
Implements an element that directly represents content of some kind. -
Field Summary
Fields Modifier and Type Field Description protected static String
BAD_LOCATION
Error message to indicate a bad location.static String
BidiElementName
Name of elements used to hold a unidirectional runstatic String
ContentElementName
Name of elements used to represent contentstatic String
ElementNameAttribute
Name of the attribute used to specify element names.protected EventListenerList
listenerList
The event listener list for the document.static String
ParagraphElementName
Name of elements used to represent paragraphsstatic String
SectionElementName
Name of elements used to hold sections (lines/paragraphs). -
Constructor Summary
Constructors Modifier Constructor Description protected
AbstractDocument(AbstractDocument.Content data)
Constructs a newAbstractDocument
, wrapped around some specified content storage mechanism.protected
AbstractDocument(AbstractDocument.Content data, AbstractDocument.AttributeContext context)
Constructs a newAbstractDocument
, wrapped around some specified content storage mechanism. -
Method Summary
Modifier and Type Method Description void
addDocumentListener(DocumentListener listener)
Adds a document listener for notification of any changes.void
addUndoableEditListener(UndoableEditListener listener)
Adds an undo listener for notification of any changes.protected Element
createBranchElement(Element parent, AttributeSet a)
Creates a document branch element, that can contain other elements.protected Element
createLeafElement(Element parent, AttributeSet a, int p0, int p1)
Creates a document leaf element.Position
createPosition(int offs)
Returns a position that will track change as the document is altered.void
dump(PrintStream out)
Gives a diagnostic dump.protected void
fireChangedUpdate(DocumentEvent e)
Notifies all listeners that have registered interest for notification on this event type.protected void
fireInsertUpdate(DocumentEvent e)
Notifies all listeners that have registered interest for notification on this event type.protected void
fireRemoveUpdate(DocumentEvent e)
Notifies all listeners that have registered interest for notification on this event type.protected void
fireUndoableEditUpdate(UndoableEditEvent e)
Notifies all listeners that have registered interest for notification on this event type.int
getAsynchronousLoadPriority()
Gets the asynchronous loading priority.protected AbstractDocument.AttributeContext
getAttributeContext()
Fetches the context for managing attributes.Element
getBidiRootElement()
Returns the root element of the bidirectional structure for this document.protected AbstractDocument.Content
getContent()
Gets the content for the document.protected Thread
getCurrentWriter()
Fetches the current writing thread if there is one.abstract Element
getDefaultRootElement()
Returns the root element that views should be based upon unless some other mechanism for assigning views to element structures is provided.DocumentFilter
getDocumentFilter()
Returns theDocumentFilter
that is responsible for filtering of insertion/removal.DocumentListener[]
getDocumentListeners()
Returns an array of all the document listeners registered on this document.Dictionary<Object,Object>
getDocumentProperties()
Supports managing a set of properties.Position
getEndPosition()
Returns a position that represents the end of the document.int
getLength()
Returns the length of the data.<T extends EventListener>
T[]getListeners(Class<T> listenerType)
Returns an array of all the objects currently registered asFooListener
s upon this document.abstract Element
getParagraphElement(int pos)
Get the paragraph element containing the given position.Object
getProperty(Object key)
A convenience method for looking up a property value.Element[]
getRootElements()
Gets all root elements defined.Position
getStartPosition()
Returns a position that represents the start of the document.String
getText(int offset, int length)
Gets a sequence of text from the document.void
getText(int offset, int length, Segment txt)
Fetches the text contained within the given portion of the document.UndoableEditListener[]
getUndoableEditListeners()
Returns an array of all the undoable edit listeners registered on this document.void
insertString(int offs, String str, AttributeSet a)
Inserts some content into the document.protected void
insertUpdate(AbstractDocument.DefaultDocumentEvent chng, AttributeSet attr)
Updates document structure as a result of text insertion.protected void
postRemoveUpdate(AbstractDocument.DefaultDocumentEvent chng)
Updates any document structure as a result of text removal.void
putProperty(Object key, Object value)
A convenience method for storing up a property value.void
readLock()
Acquires a lock to begin reading some state from the document.void
readUnlock()
Does a read unlock.void
remove(int offs, int len)
Removes some content from the document.void
removeDocumentListener(DocumentListener listener)
Removes a document listener.void
removeUndoableEditListener(UndoableEditListener listener)
Removes an undo listener.protected void
removeUpdate(AbstractDocument.DefaultDocumentEvent chng)
Updates any document structure as a result of text removal.void
render(Runnable r)
This allows the model to be safely rendered in the presence of currency, if the model supports being updated asynchronously.void
replace(int offset, int length, String text, AttributeSet attrs)
Deletes the region of text fromoffset
tooffset + length
, and replaces it withtext
.void
setAsynchronousLoadPriority(int p)
Sets the asynchronous loading priority.void
setDocumentFilter(DocumentFilter filter)
Sets theDocumentFilter
.void
setDocumentProperties(Dictionary<Object,Object> x)
Replaces the document properties dictionary for this document.protected void
writeLock()
Acquires a lock to begin mutating the document this lock protects.protected void
writeUnlock()
Releases a write lock previously obtained viawriteLock
.
-
Field Details
-
listenerList
The event listener list for the document. -
BAD_LOCATION
Error message to indicate a bad location.- See Also:
- Constant Field Values
-
ParagraphElementName
Name of elements used to represent paragraphs- See Also:
- Constant Field Values
-
ContentElementName
Name of elements used to represent content- See Also:
- Constant Field Values
-
SectionElementName
Name of elements used to hold sections (lines/paragraphs).- See Also:
- Constant Field Values
-
BidiElementName
Name of elements used to hold a unidirectional run- See Also:
- Constant Field Values
-
ElementNameAttribute
Name of the attribute used to specify element names.- See Also:
- Constant Field Values
-
-
Constructor Details
-
AbstractDocument
Constructs a newAbstractDocument
, wrapped around some specified content storage mechanism.- Parameters:
data
- the content
-
AbstractDocument
protected AbstractDocument(AbstractDocument.Content data, AbstractDocument.AttributeContext context)Constructs a newAbstractDocument
, wrapped around some specified content storage mechanism.- Parameters:
data
- the contentcontext
- the attribute context
-
-
Method Details
-
getDocumentProperties
Supports managing a set of properties. Callers can use thedocumentProperties
dictionary to annotate the document with document-wide properties.- Returns:
- a non-
null
Dictionary
- See Also:
setDocumentProperties(java.util.Dictionary<java.lang.Object, java.lang.Object>)
-
setDocumentProperties
Replaces the document properties dictionary for this document.- Parameters:
x
- the new dictionary- See Also:
getDocumentProperties()
-
fireInsertUpdate
Notifies all listeners that have registered interest for notification on this event type. The event instance is lazily created using the parameters passed into the fire method.- Parameters:
e
- the event- See Also:
EventListenerList
-
fireChangedUpdate
Notifies all listeners that have registered interest for notification on this event type. The event instance is lazily created using the parameters passed into the fire method.- Parameters:
e
- the event- See Also:
EventListenerList
-
fireRemoveUpdate
Notifies all listeners that have registered interest for notification on this event type. The event instance is lazily created using the parameters passed into the fire method.- Parameters:
e
- the event- See Also:
EventListenerList
-
fireUndoableEditUpdate
Notifies all listeners that have registered interest for notification on this event type. The event instance is lazily created using the parameters passed into the fire method.- Parameters:
e
- the event- See Also:
EventListenerList
-
getListeners
Returns an array of all the objects currently registered asFooListener
s upon this document.FooListener
s are registered using theaddFooListener
method.You can specify the
listenerType
argument with a class literal, such asFooListener.class
. For example, you can query a documentd
for its document listeners with the following code:DocumentListener[] mls = (DocumentListener[])(d.getListeners(DocumentListener.class));
If no such listeners exist, this method returns an empty array.- Type Parameters:
T
- the listener type- Parameters:
listenerType
- the type of listeners requested- Returns:
- an array of all objects registered as
FooListener
s on this component, or an empty array if no such listeners have been added - Throws:
ClassCastException
- iflistenerType
doesn't specify a class or interface that implementsjava.util.EventListener
- Since:
- 1.3
- See Also:
getDocumentListeners()
,getUndoableEditListeners()
-
getAsynchronousLoadPriority
public int getAsynchronousLoadPriority()Gets the asynchronous loading priority. If less than zero, the document should not be loaded asynchronously.- Returns:
- the asynchronous loading priority, or
-1
if the document should not be loaded asynchronously
-
setAsynchronousLoadPriority
public void setAsynchronousLoadPriority(int p)Sets the asynchronous loading priority.- Parameters:
p
- the new asynchronous loading priority; a value less than zero indicates that the document should not be loaded asynchronously
-
setDocumentFilter
Sets theDocumentFilter
. TheDocumentFilter
is passedinsert
andremove
to conditionally allow inserting/deleting of the text. Anull
value indicates that no filtering will occur.- Parameters:
filter
- theDocumentFilter
used to constrain text- Since:
- 1.4
- See Also:
getDocumentFilter()
-
getDocumentFilter
Returns theDocumentFilter
that is responsible for filtering of insertion/removal. Anull
return value implies no filtering is to occur.- Returns:
- the DocumentFilter
- Since:
- 1.4
- See Also:
setDocumentFilter(javax.swing.text.DocumentFilter)
-
render
This allows the model to be safely rendered in the presence of currency, if the model supports being updated asynchronously. The given runnable will be executed in a way that allows it to safely read the model with no changes while the runnable is being executed. The runnable itself may not make any mutations.This is implemented to acquire a read lock for the duration of the runnables execution. There may be multiple runnables executing at the same time, and all writers will be blocked while there are active rendering runnables. If the runnable throws an exception, its lock will be safely released. There is no protection against a runnable that never exits, which will effectively leave the document locked for it's lifetime.
If the given runnable attempts to make any mutations in this implementation, a deadlock will occur. There is no tracking of individual rendering threads to enable detecting this situation, but a subclass could incur the overhead of tracking them and throwing an error.
This method is thread safe, although most Swing methods are not. Please see Concurrency in Swing for more information.
-
getLength
public int getLength()Returns the length of the data. This is the number of characters of content that represents the users data.- Specified by:
getLength
in interfaceDocument
- Returns:
- the length >= 0
- See Also:
Document.getLength()
-
addDocumentListener
Adds a document listener for notification of any changes.- Specified by:
addDocumentListener
in interfaceDocument
- Parameters:
listener
- theDocumentListener
to add- See Also:
Document.addDocumentListener(javax.swing.event.DocumentListener)
-
removeDocumentListener
Removes a document listener.- Specified by:
removeDocumentListener
in interfaceDocument
- Parameters:
listener
- theDocumentListener
to remove- See Also:
Document.removeDocumentListener(javax.swing.event.DocumentListener)
-
getDocumentListeners
Returns an array of all the document listeners registered on this document.- Returns:
- all of this document's
DocumentListener
s or an empty array if no document listeners are currently registered - Since:
- 1.4
- See Also:
addDocumentListener(javax.swing.event.DocumentListener)
,removeDocumentListener(javax.swing.event.DocumentListener)
-
addUndoableEditListener
Adds an undo listener for notification of any changes. Undo/Redo operations performed on theUndoableEdit
will cause the appropriate DocumentEvent to be fired to keep the view(s) in sync with the model.- Specified by:
addUndoableEditListener
in interfaceDocument
- Parameters:
listener
- theUndoableEditListener
to add- See Also:
Document.addUndoableEditListener(javax.swing.event.UndoableEditListener)
-
removeUndoableEditListener
Removes an undo listener.- Specified by:
removeUndoableEditListener
in interfaceDocument
- Parameters:
listener
- theUndoableEditListener
to remove- See Also:
Document.removeDocumentListener(javax.swing.event.DocumentListener)
-
getUndoableEditListeners
Returns an array of all the undoable edit listeners registered on this document.- Returns:
- all of this document's
UndoableEditListener
s or an empty array if no undoable edit listeners are currently registered - Since:
- 1.4
- See Also:
addUndoableEditListener(javax.swing.event.UndoableEditListener)
,removeUndoableEditListener(javax.swing.event.UndoableEditListener)
-
getProperty
A convenience method for looking up a property value. It is equivalent to:getDocumentProperties().get(key);
- Specified by:
getProperty
in interfaceDocument
- Parameters:
key
- the non-null
property key- Returns:
- the value of this property or
null
- See Also:
getDocumentProperties()
-
putProperty
A convenience method for storing up a property value. It is equivalent to:getDocumentProperties().put(key, value);
Ifvalue
isnull
this method will remove the property.- Specified by:
putProperty
in interfaceDocument
- Parameters:
key
- the non-null
keyvalue
- the property value- See Also:
getDocumentProperties()
-
remove
Removes some content from the document. Removing content causes a write lock to be held while the actual changes are taking place. Observers are notified of the change on the thread that called this method.This method is thread safe, although most Swing methods are not. Please see Concurrency in Swing for more information.
- Specified by:
remove
in interfaceDocument
- Parameters:
offs
- the starting offset >= 0len
- the number of characters to remove >= 0- Throws:
BadLocationException
- the given remove position is not a valid position within the document- See Also:
Document.remove(int, int)
-
replace
public void replace(int offset, int length, String text, AttributeSet attrs) throws BadLocationExceptionDeletes the region of text fromoffset
tooffset + length
, and replaces it withtext
. It is up to the implementation as to how this is implemented, some implementations may treat this as two distinct operations: a remove followed by an insert, others may treat the replace as one atomic operation.- Parameters:
offset
- index of child elementlength
- length of text to delete, may be 0 indicating don't delete anythingtext
- text to insert,null
indicates no text to insertattrs
- AttributeSet indicating attributes of inserted text,null
is legal, and typically treated as an empty attributeset, but exact interpretation is left to the subclass- Throws:
BadLocationException
- the given position is not a valid position within the document- Since:
- 1.4
-
insertString
Inserts some content into the document. Inserting content causes a write lock to be held while the actual changes are taking place, followed by notification to the observers on the thread that grabbed the write lock.This method is thread safe, although most Swing methods are not. Please see Concurrency in Swing for more information.
- Specified by:
insertString
in interfaceDocument
- Parameters:
offs
- the starting offset >= 0str
- the string to insert; does nothing with null/empty stringsa
- the attributes for the inserted content- Throws:
BadLocationException
- the given insert position is not a valid position within the document- See Also:
Document.insertString(int, java.lang.String, javax.swing.text.AttributeSet)
-
getText
Gets a sequence of text from the document.- Specified by:
getText
in interfaceDocument
- Parameters:
offset
- the starting offset >= 0length
- the number of characters to retrieve >= 0- Returns:
- the text
- Throws:
BadLocationException
- the range given includes a position that is not a valid position within the document- See Also:
Document.getText(int, int)
-
getText
Fetches the text contained within the given portion of the document.If the partialReturn property on the txt parameter is false, the data returned in the Segment will be the entire length requested and may or may not be a copy depending upon how the data was stored. If the partialReturn property is true, only the amount of text that can be returned without creating a copy is returned. Using partial returns will give better performance for situations where large parts of the document are being scanned. The following is an example of using the partial return to access the entire document:
int nleft = doc.getDocumentLength(); Segment text = new Segment(); int offs = 0; text.setPartialReturn(true); while (nleft > 0) { doc.getText(offs, nleft, text); // do something with text nleft -= text.count; offs += text.count; }
- Specified by:
getText
in interfaceDocument
- Parameters:
offset
- the starting offset >= 0length
- the number of characters to retrieve >= 0txt
- the Segment object to retrieve the text into- Throws:
BadLocationException
- the range given includes a position that is not a valid position within the document
-
createPosition
Returns a position that will track change as the document is altered.This method is thread safe, although most Swing methods are not. Please see Concurrency in Swing for more information.
- Specified by:
createPosition
in interfaceDocument
- Parameters:
offs
- the position in the model >= 0- Returns:
- the position
- Throws:
BadLocationException
- if the given position does not represent a valid location in the associated document- See Also:
Document.createPosition(int)
-
getStartPosition
Returns a position that represents the start of the document. The position returned can be counted on to track change and stay located at the beginning of the document.- Specified by:
getStartPosition
in interfaceDocument
- Returns:
- the position
-
getEndPosition
Returns a position that represents the end of the document. The position returned can be counted on to track change and stay located at the end of the document.- Specified by:
getEndPosition
in interfaceDocument
- Returns:
- the position
-
getRootElements
Gets all root elements defined. Typically, there will only be one so the default implementation is to return the default root element.- Specified by:
getRootElements
in interfaceDocument
- Returns:
- the root element
-
getDefaultRootElement
Returns the root element that views should be based upon unless some other mechanism for assigning views to element structures is provided.- Specified by:
getDefaultRootElement
in interfaceDocument
- Returns:
- the root element
- See Also:
Document.getDefaultRootElement()
-
getBidiRootElement
Returns the root element of the bidirectional structure for this document. Its children represent character runs with a given Unicode bidi level.- Returns:
- the root element of the bidirectional structure for this document
-
getParagraphElement
Get the paragraph element containing the given position. Sub-classes must define for themselves what exactly constitutes a paragraph. They should keep in mind however that a paragraph should at least be the unit of text over which to run the Unicode bidirectional algorithm.- Parameters:
pos
- the starting offset >= 0- Returns:
- the element
-
getAttributeContext
Fetches the context for managing attributes. This method effectively establishes the strategy used for compressing AttributeSet information.- Returns:
- the context
-
insertUpdate
Updates document structure as a result of text insertion. This will happen within a write lock. If a subclass of this class reimplements this method, it should delegate to the superclass as well.- Parameters:
chng
- a description of the changeattr
- the attributes for the change
-
removeUpdate
Updates any document structure as a result of text removal. This method is called before the text is actually removed from the Content. This will happen within a write lock. If a subclass of this class reimplements this method, it should delegate to the superclass as well.- Parameters:
chng
- a description of the change
-
postRemoveUpdate
Updates any document structure as a result of text removal. This method is called after the text has been removed from the Content. This will happen within a write lock. If a subclass of this class reimplements this method, it should delegate to the superclass as well.- Parameters:
chng
- a description of the change
-
dump
Gives a diagnostic dump.- Parameters:
out
- the output stream
-
getContent
Gets the content for the document.- Returns:
- the content
-
createLeafElement
Creates a document leaf element. Hook through which elements are created to represent the document structure. Because this implementation keeps structure and content separate, elements grow automatically when content is extended so splits of existing elements follow. The document itself gets to decide how to generate elements to give flexibility in the type of elements used.- Parameters:
parent
- the parent elementa
- the attributes for the elementp0
- the beginning of the range >= 0p1
- the end of the range >= p0- Returns:
- the new element
-
createBranchElement
Creates a document branch element, that can contain other elements.- Parameters:
parent
- the parent elementa
- the attributes- Returns:
- the element
-
getCurrentWriter
Fetches the current writing thread if there is one. This can be used to distinguish whether a method is being called as part of an existing modification or if a lock needs to be acquired and a new transaction started.- Returns:
- the thread actively modifying the document
or
null
if there are no modifications in progress
-
writeLock
protected final void writeLock()Acquires a lock to begin mutating the document this lock protects. There can be no writing, notification of changes, or reading going on in order to gain the lock. Additionally a thread is allowed to gain more than onewriteLock
, as long as it doesn't attempt to gain additionalwriteLock
s from within document notification. Attempting to gain awriteLock
from within a DocumentListener notification will result in anIllegalStateException
. The ability to obtain more than onewriteLock
per thread allows subclasses to gain a writeLock, perform a number of operations, then release the lock.Calls to
writeLock
must be balanced with calls towriteUnlock
, else theDocument
will be left in a locked state so that no reading or writing can be done.- Throws:
IllegalStateException
- thrown on illegal lock attempt. If the document is implemented properly, this can only happen if a document listener attempts to mutate the document. This situation violates the bean event model where order of delivery is not guaranteed and all listeners should be notified before further mutations are allowed.
-
writeUnlock
protected final void writeUnlock()Releases a write lock previously obtained viawriteLock
. After decrementing the lock count if there are no outstanding locks this will allow a new writer, or readers.- See Also:
writeLock()
-
readLock
public final void readLock()Acquires a lock to begin reading some state from the document. There can be multiple readers at the same time. Writing blocks the readers until notification of the change to the listeners has been completed. This method should be used very carefully to avoid unintended compromise of the document. It should always be balanced with areadUnlock
.- See Also:
readUnlock()
-
readUnlock
public final void readUnlock()Does a read unlock. This signals that one of the readers is done. If there are no more readers then writing can begin again. This should be balanced with a readLock, and should occur in a finally statement so that the balance is guaranteed. The following is an example.readLock(); try { // do something } finally { readUnlock(); }
- See Also:
readLock()
-