XML support module allows text and tree editing of XML files, CSS2 editing etc.
Synchronization Issues
Overview
XML content can be modified by:
- text
- module text editor
- tree
- module tree editor
- API
- tree API (same as above)
- file
- external manipulation with file or DOM API manipulation
The modification can left the document valid or invalid.
Invalid content put extra requirement on tree editor
because round-trip symetry is required.
Change Conflict
External modification can be in conflict with synchronized internal content.
Therefore if a file change is detected a user is asked to replace
internal content with modified one:
- Reload document from file
- Let exist two versions/ do not report external modifications
- Save current state to file
If there are two versions while saving user is asked:
- Replace file
- Save as __________________
- Merge...
- Cancel
Representation
The representation means that actual state can be represented by several
models. For example: swing.Document, tree.TreeDocument or FileObject content.
A representation represents
a model and tahes care of its state.
Its interface provides:
- represents
- does the representation represent given model?
- update
- update the representation by given change. Note that extenal
representation typically do nothing since they are
updated by save operation.
- getChange
- get change describtion of changed/modified
- modified
- is the representation that does not represent current
change event modified?
Synchronizator
It manages relations between representation changes and updates.
It is accessed using a synchronization controller (typically a DataObject).
It has an entry method representationChanged(type[, context])
.
It also holds set of currently loaded/managed representations. When a
representation change event arrives the synchronizator responds with:
- locking itself
- check for recursive entry denying it
- scanning all current representations determining which representation
caused the change
- obtainig the change
- passing the change to representations update methods
- unlocking itself
External Representation Pitfalls
The content can be changed externaly by a third party (not save action). In such case
a dialog appears. A deletion case must be distigwished and used promted.
TODO it should not be called as result of Save action as org.openapi.loaders.... notifies it.
EditorSupport
The instance takes care about synchronizing swing.Document with
external file. If external file changes and there is no Document modification
it updates state of the Document. It also handles correctly bogus external
modification caused by saving the Document by SaveCookie. However as there are
two in memory representations (the Document and the Tree) then one in memory
representation must be primary in respect of managing SaveCookie and external
modification listening.
[PENDING]
Sychronization Inputs (Changes)
Synchronizator itself does not listen at modifications. It must be
explicitly excited by representationChanged()
method.
The method can be called from whenever thread.
Typical stimuli are (use find: "representationChanged"):
- focus lost at modified text document (FocusListener at component)
- timeout at modified text document (DocumentListener & a timer)
- Document API change //!!! explicit call or timeout
if Document opened in editor
- Tree API change (TreeListener at DataObject)
- Tree editor focus lost -- no listener, yet --
- external file modification (not caused by SaveCookie)
-- no listener, yet --
- save operation //!!! ???
Synchronization Related State Information
Sync state related fields
boolean externalyModified;
int JUST_SAVING = 2;
int JUST_SYNCHRONIZING = 1;
int NOP = 0;
int syncOperation;
Sync state manipulation methods. All of these finish setting operation to NOP.
init, reload {
syncOperation = NOP;
externalyModified = false;
}
treeChanged() {
if syncOperation == SYNC return;
syncOperation = SYNC;
}
textChanged() {
if syncOperation == SYNC return;
syncOperation = SYNC;
}
fileChanged() {
if syncOperation == SAVING return;
if externalyModified return;
query user "update state"
if "Let exist two versions"
externalyModified = true;
return;
.. update via text, because externa modifation can made it invalid ..
}
save() {
syncOperation = SAVING;
if externalyModified
query user "whether overwrite or save as"
.. save to particural location ..
externalyModified = false;
}
Indentation
Each getXMLString(deep, settings) could format current tree node. Formatting that apply just to current node consist of a formating prefix and substituted node value.