org.sandev.basics.util
Class AbstractFormManager
java.lang.Object
org.sandev.basics.util.AbstractFormManager
- All Implemented Interfaces:
- UIFormManager
- Direct Known Subclasses:
- RootedFormManager, StandardFormManager
public abstract class AbstractFormManager
- extends java.lang.Object
- implements UIFormManager
Provides a root implementation of a UIFormManager delegating
data manipulation tasks to extending classes.
|
Field Summary |
static java.lang.String |
CLASS_DISAMBIGUATION_PROMPT
Default output text used when prompting the user to disambiguate
the message class. |
static java.lang.String |
FIELDVALIDATIONERRORCODE
An identifying code for all field validation level errors. |
static java.lang.String |
FIX_FIELDS_BEFORE_SAVE
Default output text added if field validation fails on ACTION_SAVE. |
static java.lang.String |
INVALID_FIELD_VALUE_PREFIX
Default output text used as a prefix when reporting any invalid
field values found. |
static int |
RC_CANCELLED
We asked the user to resolve the currClass, and they cancelled. |
static int |
RC_DONE
The currClass is unambiguous. |
static int |
RC_QUERYING
We are asking the user to resolve the currClass. |
protected UIFormAdaptor |
uifa
Our UIFormAdaptor reference set during initialization. |
|
Method Summary |
void |
disableUnsupportedActions(UIFormContext uifc)
Turn off actions that are not supported in the current mode. |
protected void |
doActionAdd(UIFormContext uifc,
UIFormOwner owner)
The user has selected to switch to ADDING mode. |
protected void |
doActionCancel(UIFormContext uifc,
UIFormOwner owner)
The user cancels the current operation. |
protected void |
doActionCollapse(UIFormContext uifc,
UIFormOwner owner)
The user has clicked to collapse a collapsible field. |
protected boolean |
doActionDelete(UIFormContext uifc,
UIFormOwner owner)
The user has selected to delete a contained object or a top
level object. |
protected void |
doActionDeref(UIFormContext uifc,
UIFormOwner owner)
The user has requested that the display shift to a referenced
object. |
protected void |
doActionDrilldown(UIFormContext uifc,
UIFormOwner owner)
The user has requested that the display drill down to a contained
object from our current location. |
protected void |
doActionEdit(UIFormContext uifc,
UIFormOwner owner)
The user has selected to switch to UPDATING mode. |
protected void |
doActionExpand(UIFormContext uifc,
UIFormOwner owner)
The user has clicked to expand a collapsible field. |
protected void |
doActionFind(UIFormContext uifc,
UIFormOwner owner)
The user has clicked "find", either to bring up a query form or
to execute the displayed query form. |
protected void |
doActionHelp(UIFormContext uifc,
UIFormOwner owner)
The user has asked for help. |
protected void |
doActionMove(UIFormContext uifc,
UIFormOwner owner,
int offset)
The user has selected to move a reference item up or down
within the reference array or contained object array. |
protected void |
doActionNew(UIFormContext uifc,
UIFormOwner owner)
The user has selected to add a reference to an instance that
they will now create. |
protected void |
doActionNext(UIFormContext uifc,
UIFormOwner owner)
The user has selected to move to the next page of elements. |
protected void |
doActionOk(UIFormContext uifc,
UIFormOwner owner)
The user has selected to complete their current action. |
protected void |
doActionPageTo(UIFormContext uifc,
UIFormOwner owner)
The user has selected to move to a specific page within the
collection display. |
protected void |
doActionParent(UIFormContext uifc,
UIFormOwner owner)
The user has requested that the display move up one level. |
protected void |
doActionPrevious(UIFormContext uifc,
UIFormOwner owner)
The user has selected to move to the previous page of elements. |
protected void |
doActionRemove(UIFormContext uifc,
UIFormOwner owner)
The user has selected to remove a reference to an object. |
protected boolean |
doActionSave(UIFormContext uifc,
UIFormOwner owner)
The user elects to save their outstanding work. |
protected void |
doActionSelect(UIFormContext uifc,
UIFormOwner owner)
The user has selected an instance from a collection of instances
that were displayed. |
protected boolean |
fieldValidateCurrentInstance(UIFormContext uifc)
Call the fieldValidate method of the currInst to make sure the
field values are reasonable. |
protected java.lang.String |
getClassDisambiguationPrompt()
Return the text for the UIFormQuery asking to disambiguate the
class type. |
protected java.lang.String |
getFieldValidationFailureText()
Accessor for field validation failure on save. |
protected java.lang.String |
getInvalidFieldMessagePrefix()
Accessor for invalid field value messages. |
protected boolean |
handleSummaryEditAdd(UIFormContext uifc,
UIFormOwner owner)
If we are adding an instance to a summaryedit display, then save
a new default instance directly without moving to another screen. |
void |
initFormAdaptor(UIFormAdaptor uifa)
Initialize the UIFormAdaptor. |
protected abstract boolean |
mergeChangesToParentBeforeAdd(UIFormContext uifc)
We are about to do a contained add, so make sure any outstanding
changes to the currInst are captured before it gets replaced with
a new instance for editing. |
protected void |
okContainedAdd(UIFormContext uifc,
UIFormOwner owner)
Add a new instance contained inside of a parent object. |
protected void |
okNewReference(UIFormContext uifc,
UIFormOwner owner)
Add a reference from the parent to a new instance. |
protected void |
okTopLevelAdd(UIFormContext uifc,
UIFormOwner owner)
Add a completely new instance. |
protected void |
okUpdate(UIFormContext uifc,
UIFormOwner owner)
Process the update operation, tracking the necessary updates. |
protected boolean |
outstandingChangesExist(UIFormContext uifc)
Returns true if there are outstanding changes to the currInst
which need to be captured, false otherwise. |
boolean |
processForm(UIFormContext uifc,
UIFormOwner owner)
A big control switch that calls the appropriate doActionXXX method. |
protected void |
processUpdate(SandInstanceMessage sim,
UIFormContext uifc,
int updateAction,
UIFormOwner owner)
Get the update message for this struct message, fill it out, and
call trackUpdates. |
protected int |
resolveClass(UIFormContext uifc)
Figure out what class we are dealing with. |
protected void |
resolveReferences(UIFormContext uifc,
UIFormOwner owner)
Check our references make sense, adding errors to the outputText
for any invalid references found. |
protected abstract boolean |
supportsTopLevelAdd()
Returns true if this form manager allows new top level object
instances to be created while in LISTING mode. |
protected abstract boolean |
supportsTopLevelFind()
Returns true if this form manager allows other top level object
instances to be found while in LISTING mode. |
protected void |
trace(int level,
java.lang.String text)
Debugging output statements. |
protected abstract void |
trackUpdates(SandUpdateMessage update,
UIFormContext uifc)
Track this update for save processing. |
protected void |
wrappedGenAdd(java.lang.String prefix,
UIFormContext uifc,
SandInstanceMessage parent,
SandInstanceMessage child)
Figures out SET/APPEND/INSERT action and calls wrappedGenMod. |
protected void |
wrappedGenMod(java.lang.String prefix,
SandInstanceMessage sim,
int action,
java.lang.String field,
int arrayIndex,
java.lang.Object opmsg)
Wrap the general modifier call. |
| Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
uifa
protected UIFormAdaptor uifa
- Our UIFormAdaptor reference set during initialization.
RC_QUERYING
public static final int RC_QUERYING
- We are asking the user to resolve the currClass. We have added
a UIFormQuery to the UIFormContext and need to go get an answer from
the user now.
- See Also:
- Constant Field Values
RC_CANCELLED
public static final int RC_CANCELLED
- We asked the user to resolve the currClass, and they cancelled.
The caller must now undo things to return appropriately. There
is no outstanding query.
- See Also:
- Constant Field Values
RC_DONE
public static final int RC_DONE
- The currClass is unambiguous.
- See Also:
- Constant Field Values
CLASS_DISAMBIGUATION_PROMPT
public static final java.lang.String CLASS_DISAMBIGUATION_PROMPT
- Default output text used when prompting the user to disambiguate
the message class.
- See Also:
- Constant Field Values
FIX_FIELDS_BEFORE_SAVE
public static final java.lang.String FIX_FIELDS_BEFORE_SAVE
- Default output text added if field validation fails on ACTION_SAVE.
- See Also:
- Constant Field Values
INVALID_FIELD_VALUE_PREFIX
public static final java.lang.String INVALID_FIELD_VALUE_PREFIX
- Default output text used as a prefix when reporting any invalid
field values found. This text is typically followed by the name
of the field, and one of the FIELDCHECK errors defined in the
SandInstanceMessage interface. The resulting message text can be
transformed as needed in the UIFormOwner.filterDisplayText method.
The text here is single spaced to avoid any extra space characters
being inserted for things like HTML displays.
- See Also:
- Constant Field Values
FIELDVALIDATIONERRORCODE
public static final java.lang.String FIELDVALIDATIONERRORCODE
- An identifying code for all field validation level errors.
- See Also:
- Constant Field Values
AbstractFormManager
public AbstractFormManager()
initFormAdaptor
public void initFormAdaptor(UIFormAdaptor uifa)
throws UIFormManagerException
- Initialize the UIFormAdaptor.
- Specified by:
initFormAdaptor in interface UIFormManager
- Throws:
UIFormManagerException
processForm
public boolean processForm(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- A big control switch that calls the appropriate doActionXXX method.
This method returns true if global data has potentially been changed
in processing the form, in other words after successfully processing
ACTION_SAVE or ACTION_DELETE. This allows a UIScreenAdaptor to know
when to refresh other forms in a screen with multiple forms.
- Specified by:
processForm in interface UIFormManager
- Throws:
UIFormManagerException
disableUnsupportedActions
public void disableUnsupportedActions(UIFormContext uifc)
- Turn off actions that are not supported in the current mode. This
method is typically called as part of procesing the form. In the
event of a form load error, a UI would typically not process the
form, but simply redisplay it with any error messages. Because
the form was not processed in that case, the UI would need to call
this method directly to turn off innapropriate actions.
These are the top level actions, not the reference or contained
field actions.
- Specified by:
disableUnsupportedActions in interface UIFormManager
doActionDrilldown
protected void doActionDrilldown(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has requested that the display drill down to a contained
object from our current location.
Examples:
- In the ConfigEditor, the user clicks on the selection button
to the left of an initial data element.
Preconditions:
- uifc.position has been updated to have the field (and possibly
an associated array index) appended to it.
actions:
- Throws:
UIFormManagerException
doActionParent
protected void doActionParent(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has requested that the display move up one level. This
may be after they drilled down into a contained object, or after
they selected a specific instance from a collection listing.
Examples:
- In the ConfigEditor, after drilling down into an initial data
definition, the user clicks the "parent" button.
- In TaskHeapDemo, after selecting one of the tasks in the task
screen, the user clicks the "parent" button.
Preconditions:
actions:
- if the position has one element in it, and the findCollection
is not null, then we clear the position, and set the currInst
and rootMsg to null. This returns us to the collection display.
- in all other cases we call uifc.upOneLevel
- Throws:
UIFormManagerException
doActionDeref
protected void doActionDeref(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has requested that the display shift to a referenced
object. Unlike a drilldown action, this is actually a shift
to a new object and there is no corresponding "parent" action.
To return to where they were, a user can use the back button
on their browser, or other stack navigation as supported by
the UI.
In a deref action, the user is typically viewing a listing
display, although a deref/drilldown button may also be presented
for a read-only field within an editing form. For example if a user
is editing a PlanComponentReport, there is a deref link to the
source PlanComponent. In this case if the user clicks the drilldown
then the editing mode is effectively cancelled.
Examples:
- In TaskHeapDemo, within the display of a single Task instance,
the user clicks on the selection button to the left of the
resourceID field value.
Preconditions:
- currInst contains a shell of the referenced class instance.
Specifically this is a newly allocated object of the correct
class, with the uniqueID set.
actions:
- we lookup the specified instance, and then essentially
re-initialize the form to display it.
- findQuery and findCollection are nulled out.
Notes:
- The ConfigEditor and UIEditor both override this method to
translate a dereferencing action into what is essentially
a move within the main object being edited. This seems
like it will probably be a common application-specific
override for implementations extending RootedFormManager.
- This method assumes we are dereferencing via uniqueID, since
that is the only guaranteed unique key. Name dereference
is supported in RootedFormManagers where it makes sense.
- Throws:
UIFormManagerException
doActionSelect
protected void doActionSelect(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has selected an instance from a collection of instances
that were displayed. This means we are either:
- LISTING a collection of instances, and the user has selected one
to work with. This is effectively a drilldown from the collection
to a specific instance.
- Adding a reference to this instance at the current position.
In this case we were UPDATING an object instance (or ADDING a
new top level instance), then we were FINDING the instance we
want to add a reference to, and now we are selecting that instance
from the LISTING. So we need to set the reference and return to
UPDATING or ADDING.
Examples:
- In TaskHeapDemo, within the collection of Tasks displayed in
the TasksDisplay, the user clicks on the selection button to
the left of a task listing.
- In TaskHeapDemo, while editing a task, the user clicks the
find button next to the resourceID field, then clicks the
ok button for the user query, then selects a resource from
the resulting collection display.
Preconditions:
- currInst contains the selected instance
- findCollection contains the results for display
- if we are ADDING or UPDATING, the position indicates which
reference field, or reference array element to be set in rootMsg.
actions:
- if the tail of the modePath is ...ADDING.FINDING.LISTING, or
...UPDATING.FINDING.LISTING, then the last two modes are popped
from the modePath and the currInst is modified to contain a
reference to the selected element at the given position. The
position is then moved up one level so we are back at the parent.
- otherwise, rootMsg is set to the selected object, and currInst,
currClass, and position are initialized. We stay in LISTING
mode.
- Throws:
UIFormManagerException
doActionEdit
protected void doActionEdit(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has selected to switch to UPDATING mode.
Examples:
- In TaskHeapDemo, within the display of a single Task instance,
the user clicks the "edit" button.
Preconditions:
actions:
- The UPDATING node is pushed onto the modePath.
The application may want to setLastModifiedReason in the
message being updated, in order to reflect actions that were
taken. For example an action button might setLastModifiedReason
to a value explaining that the update is coming from the button.
If control then passes through to edit (e.g. for final signoff by
the user), then we don't want to reset that value here. Under
most circumstances the application doActionEditHook will reset
the lastModifiedReason, but we can't do that here because there
is no workaround if we get in the way.
- Throws:
UIFormManagerException
doActionAdd
protected void doActionAdd(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has selected to switch to ADDING mode.
Examples:
- In TaskHeapDemo, within the top level TasksDisplay screen,
the user clicks the "add" button to add a new Task.
- In TaskHeapDemo, after selecting a single Task to view,
the user clicks the "add" button to add a new Task.
- In the UIEditor, the user drills down through a Screen to
a Link containing multiple actions. They click "edit" and
select a point to insert a new Action, then click "add".
Preconditions:
- currClass contains the class type to add
- for a contained add, the position has been updated to reflect
the field/index. For a top-level add, the position is empty.
- a UIFormQuery to disambiguate the class may optionally exist.
actions:
- if we need to disambiguate the class, then we query the user
- if the class disambiguation query was cancelled, then we pop
our position back to where we were.
- if we know what class we are adding, then we push the ADDING
mode and set up to edit a new instance.
Notes:
- The new instance will not show up as part of a collection of
instances until it is saved. Before that it doesn't actually
exist yet.
- Throws:
UIFormManagerException
doActionFind
protected void doActionFind(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has clicked "find", either to bring up a query form or
to execute the displayed query form.
Find is used both to bring up the initial query form (call this
Find1), and to execute the query form after it has been filled in
(call this Find2). We differentiate between whether we are in
Find1 or Find2 based on whether the modePath endsWith FINDING.
Examples:
- In TaskHeapDemo, while editing a Task, the user clicks the
find button to assign a resourceID. After filling out any
match information in the displayed query form, they click
find to retrieve a collection of resources to select from.
- In TaskHeapDemo, in the TasksDisplay screen collection view,
the user clicks "find" to retrieve an alternate collection.
Preconditions:
- currClass contains the class type to find
- a UIFormQuery to disambiguate the class may optionally exist.
- if the current mode is FINDING, then findQuery contains
the the query information
actions:
- call owner.doActionFindHook for any preprocessing that needs
to happen.
- If we are not already FINDING, then FINDING is pushed onto
the modePath.
- If currClass is an interface or superclass, and no UIFormQuery is
present to disambiguate the class, then the UIFormQuery is created
and displayed.
- If the UIFormQuery is present, and the user cancelled, then the
FINDING mode is popped off the modePath and the position is
popped up one level to remove the field location.
- If the currClass is either unambiguous or disambiguated via
UIFormQuery, then we call owner.formFind, setting findCollection
to the result and clearing any UIFormQuery info.
Notes:
- The currInst needs to be preserved since we may be ADDING
or UPDATING and in the process of trying to resolve a reference.
This means that FIND is not supported when an instance is being
displayed, since currInst will not be cleared.
- In the case of a top-level FIND action from a collection
display, the modePath before processing will be LISTING.FINDING
and we are about to replace the collection with the results of
the query. This would logically result in the modePath
becoming LISTING.FINDING.LISTING, with no cancel operation to
return to the previous mode. Rather than doing this we simply
pop the FINDING context so the modePath becomes LISTING. For
example consider the TasksDisplay in TaskHeapDemo. The user
clicks the top level "find" button, specifies a query and then
clicks "find" again, resulting in a new collection display.
The user can repeat this operation ad infinitum and without
the modePath becoming LISTING.FINDING.LISTING.FINDING....
- Doing a find will typically result in the findQuery and
findCollection fields being used. If a form had been initialized
with a collection, and a find is done while editing (such as
to locate a reference) then the intial collection may be lost
in the process. In this case the collection may need to be
reset by form init processing.
- Throws:
UIFormManagerException
doActionCancel
protected void doActionCancel(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user cancels the current operation. This method is called
anytime the user clicks the "cancel" button, except for in a
UIFormQuery (user queries are resolved by the method that asked).
Examples:
- In TaskHeapDemo, while editing an existing task, the user
clicks the "cancel" button.
- In TaskHeapDemo, while adding a new task instance, the user
clicks the "cancel" button.
- In TaskHeapDemo, while editing a new task instance, the user
clicks "find" to assign a resourceID. The user then clicks
"cancel" when the query form is displayed.
- In TaskHeapDemo, while editing a new task instance, the user
clicks "find" to assign a resourceID, then clicks "find" again
on the query form, then clicks "cancel" when the matching
instances are displayed.
Preconditions:
- the cancel button is not displayed unless there is a logical
mode to return to.
actions:
- if we are UPDATING, then drop any edits and return to LISTING.
- if we are ADDING, then return to the original LISTING.
- if we were FINDING, then return to the previous state and position
- if we were FINDING.LISTING, then return back to the originating
state and position.
Notes:
- In the case of a general top-level query display, there would
not be a cancel button since there is no previous mode to
return to. So if TaskHeapDemo had a general Task finding screen
with a query form on it, there wouldn't be a cancel button.
display rule: CANCEL is supported in FINDING mode only
if there is a previous mode to return to.
- If supporting a general FIND action from a LISTING display,
cancel is supported at the query form, but not after the
user clicks "find" the second time to retrieve a collection.
The original listing collection will have been replaced with
the results of the query. So if the user clicks "find" on
the TasksDisplay screen, then clicks "find" again after filling
out the query form, the resulting collection display will not
have a cancel button on it.
display rule: CANCEL is supported in LISTING mode only
if there is a previous ADDING or UPDATING mode to return to.
- Throws:
UIFormManagerException
doActionSave
protected boolean doActionSave(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user elects to save their outstanding work. This method calls
through to the UIFormOwner for processing. We return true if data
is changed, false otherwise.
Examples:
- In TaskHeapDemo, the user fills out a new Task and clicks
"save".
- In TaskHeapDemo, the user fills out a new Task, then clicks
"ok" to return to the listing display, then clicks "edit" to
make more changes, then clicks "save".
- In the ConfigEditor, the user makes changes to a node instance
and then clicks "save".
Preconditions:
- We are ADDING/UPDATING or pendingEdits is true.
actions:
- doActionOk is called, which does field validation. If this
results in any output text, then we assume there is a bad
field value and we return false.
- resolveReferences is called, which does local reference
validation if supported. If this results in any output text,
then we assume there is a bad reference value and return false.
- owner.formSave is called and if pendingEdits is cleared we
return true.
Notes:
- if we were ADDING or UPDATING, doActionOk handles the main form
resolution processing and sets pendingEdits to true.
- It is the responsibility of the UIFormOwner to clear the updates,
and set pendingEdits to false on successful conclusion of the
formSave call.
- Throws:
UIFormManagerException
doActionNext
protected void doActionNext(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has selected to move to the next page of elements.
Examples:
- In TaskHeapDemo, the user clicks the "next" button on the
TasksDisplay screen (after entering enough tasks to trigger
dataset pagination).
Preconditions:
- the mode is LISTING
- there are more items either in the collection or available via
query, or both.
actions:
- the findCollection is refreshed with the next page of items.
This may require the query to be updated and resent to the
UIFormOwner for processing. See the pagination documentation in
UIGen.html
for details.
- Throws:
UIFormManagerException
doActionPrevious
protected void doActionPrevious(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has selected to move to the previous page of elements.
Examples:
- In TaskHeapDemo, after clicking the "next" button on the
TasksDisplay screen, the user clicks on the "previous"
button to return to the previous page of data
Preconditions:
- the mode is LISTING
- there are collection elements before the current index, or
there is a previous collection query index.
actions:
- the findCollection is refreshed with the previous page of items.
This may require the query to be updated and resent to the
UIFormOwner for processing. See the pagination documentation in
UIGen.html
for details.
- Throws:
UIFormManagerException
doActionPageTo
protected void doActionPageTo(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has selected to move to a specific page within the
collection display.
This works like NEXT or PREVIOUS except the query paging values
have already been modified (like by javascript on the rendered
page or similar UI mechanism), so all we need to do is rerun the
query to get the updated results.
To support normal next/previous operations we push find keys
based on the paging info we have.
- Throws:
UIFormManagerException
doActionDelete
protected boolean doActionDelete(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has selected to delete a contained object or a top
level object. Return true if global data has changed, false
otherwise.
Examples:
- In TaskHeapDemo, after selecting a specific task from the
TasksDisplay, the user clicks the "delete" button.
- In TaskHeapDemo, while editing a Task, the user selects an
existing note and clicks the "delete" button.
- In the ConfigEditor, while editing the configuration, the
user selects an initialData element and clicks "delete".
- In TaskHeapDemo, after navigating to a particular item through
the reference links, the user clicks the "delete" button.
Preconditions:
- One of the following conditions is met:
- the position has one element in it, and currInst has the
instance to delete. In this case either:
- findCollection is not null and we return to the
collection view after deleting.
- findCollection is null and we reset the UIFormContext
to essentially start over from the top.
- the position describes the element to delete, and currInst
is the parent object to be modified.
actions:
- if position indicates a contained element, it is deleted from
the rootMsg and position is updated back to the parent. The
mode is unchanged and no updates are tracked (tracking occurs
when the the current editing session is confirmed or cancelled).
- if position indicates a top level element, then the currInst
is deleted via a UIFormOwner call, and we clear back to the
collection view or back to scratch.
Notes:
- When deleting a contained instance, we only need to update the
parent instance. When that update is confirmed, the contained
instance will be gone.
- Deleting a contained object (either a single field instance
or an element from an array of instances) is always possible.
- Throws:
UIFormManagerException
doActionRemove
protected void doActionRemove(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has selected to remove a reference to an object.
Examples:
- In TaskHeapDemo, while editing a task with an assigned resourceID,
the user clicks the remove button next to the resourceID field.
Preconditions:
- we are in UPDATING or ADDING mode
- the position indicates the contained element to remove
actions:
- the contained reference is removed from rootMsg and the position
is updated back to the parent. The mode is unchanged.
Notes:
- Since the user is removing a reference, they are currently
editing an instance. Changes will be tracked when the confirm
the edits.
- We have to work solely with the currInst (so we can't call
something like evalPosition) because the main references have
to be preserved in case the user cancels editing.
- Throws:
UIFormManagerException
doActionNew
protected void doActionNew(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has selected to add a reference to an instance that
they will now create.
Examples:
- In TaskHeapDemo, while editing a Plan, the user clicks the
"new" button next to the components field.
Preconditions:
- currClass contains the class type to create.
- a UIFormQuery to disambiguate the class may optionally exist.
- we are in UPDATING or ADDING mode
- the position indicates the index where the new instance
reference should be added.
actions:
- if we need to disambiguate the class, then we query the user
- if the class disambiguation query was cancelled, then we pop
our position back to where we were.
- if we know what class we are adding, then we push the ADDING
mode and set up to edit a new instance.
- Throws:
UIFormManagerException
doActionMove
protected void doActionMove(UIFormContext uifc,
UIFormOwner owner,
int offset)
throws UIFormManagerException
- The user has selected to move a reference item up or down
within the reference array or contained object array.
Examples:
- In TaskHeapDemo, while editing a Plan, the user selects one
of the referenced plan components and clicks the "move up"
or "move down" button to change its position relative to
the other references.
Preconditions:
- We are in UPDATING or ADDING mode
- The position indicates the contained element to be moved
actions:
- The contained reference is moved the specified number of
relative indices and the position is updated back to the
the parent. The mode is unchanged.
Notes:
- Since the user is moving something within the current instance
being edited, changes will be tracked when they save/ok.
- We have to work solely with the currInst (so we can't call
methods like evalPosition) because the main references have
to be preserved in case the user cancels editing.
- Throws:
UIFormManagerException
doActionOk
protected void doActionOk(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has selected to complete their current action. This method
is called anytime the user clicks the "ok" button, except for in a
UIFormQuery (user queries are handled by the method that asked).
Examples:
- In TaskHeapDemo, while adding a new Task, the user clicks the
"ok" button to add the new instance. [top-level add]
- In TaskHeapDemo, while adding or updating a Task, the user
clicks to add a note. After filling in the information, they
click "ok" to add the note and return to their adding/editing
the task. [contained add]
- In TaskHeapDemo, while editing an existing Task, the user
clicks "ok" to complete their edits. [top-level update]
- In TaskHeapDemo, while listing a task, the user drills down
into one of the notes. They click to edit the note, then
click "ok" to confirm the changes. [contained update]
- In the UIEditor, the user selects a Screen, then selects a
Link within the Screen and clicks "edit". They then click
"add" next to the actions field to add a new Action instance.
After filling out the values for the Action, they click "ok"
to enter their data. [contained add]
- In the UIEditor, the user selects a Screen, then selects a
Link within the Screen, then selects an Action within the
Link and clicks "edit". They make a change and then click
"ok" to enter their changes. [contained update]
- In TaskHeapDemo, while editing an existing Plan, the user
clicks "new" next to the components field to create a
reference to a new instance.
Preconditions:
- we are in UPDATING or ADDING mode
- there is a previous mode to return to
- currInst contains the edited message
actions:
- If we are ADDING, and if the position length <= 1, then we call
okTopLevelAdd. Otherwise we call okContainedAdd or okNewReference.
- If we are UPDATING, we call okUpdate
Notes:
- If we are ADDING, then
- We are doing a top-level add of a new independent instance.
- We are adding a dependent instance, and therefore either
ADDING or UPDATING it's parent. The changes will be merged
into the parent and saved when the parent is saved.
- We are adding a reference to a NEW independent instance,
and need to track the changes for the new instance before
setting the parent reference to it.
- If we are UPDATING, then we are ultimately modifying the rootMsg,
(either directly or by changing one of its contained instances).
In either case we merge the currInst back in, and then track
changes at the root level.
- In a RootedFormManager (such as the ConfigEditor or UIEditor),
every modification is a contained update.
- Throws:
UIFormManagerException
doActionExpand
protected void doActionExpand(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has clicked to expand a collapsible field.
Preconditions:
actions:
- If a UIDisplayDirective for the current instance and field
exists, then remove it to use the default expanded display.
- Throws:
UIFormManagerException
doActionCollapse
protected void doActionCollapse(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has clicked to collapse a collapsible field.
Preconditions:
actions:
- Add a UIDisplayDirective for the current instance and field
indicating it should be collapsed
- Throws:
UIFormManagerException
doActionHelp
protected void doActionHelp(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- The user has asked for help.
Examples:
- In TaskHeapDemo, the user clicks the "help" button on the
the TasksDisplay screen.
- In the ConfigEditor, the user clicks the "help" button on
the main screen.
Preconditions:
actions:
- Throws:
UIFormManagerException
outstandingChangesExist
protected boolean outstandingChangesExist(UIFormContext uifc)
- Returns true if there are outstanding changes to the currInst
which need to be captured, false otherwise.
Notes:
- If we are ADDING a new instance, then we need to capture that
information before doing anything else. Even if we have not
made any changes, there are potentially default values that
were set. And if we were appending or inserting into an array
of instances, then we need to deal with that operation before
moving deeper into the tree.
- If we are UPDATING an existing instance, and we have not made
changes (we just clicked the ADD button next to one of the
elements), then we don't need to capture our state. It's
important to let this case through, since you have to edit
something before adding elements to it. For example in the
UIEditor you first edit a Screen before adding a Link to it.
resolveClass
protected int resolveClass(UIFormContext uifc)
- Figure out what class we are dealing with. Return one of the RC_*
constants to let the caller know where we are.
resolveReferences
protected void resolveReferences(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- Check our references make sense, adding errors to the outputText
for any invalid references found. It is generally only practical
to resolve references when the known universe of potential IDs is
well contained. Single-object managers (such as those used in the
ConfigEditor or UIEditor) are based on a single object instance,
which can be traversed and checked for internal reference
consistency. Standard managers which are working off a small subset
of the overall data at any time (such as TaskHeapDemo) can't check
referential integrity without significant overhead.
The default implementation of this method does nothing. Override
if referential integrity checking has a manageable scope.
- Throws:
UIFormManagerException
fieldValidateCurrentInstance
protected boolean fieldValidateCurrentInstance(UIFormContext uifc)
- Call the fieldValidate method of the currInst to make sure the
field values are reasonable.
okTopLevelAdd
protected void okTopLevelAdd(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- Add a completely new instance. The rootMsg and position are updated
to the new object top level. The addition is tracked.
A top-level add is a button that is available while listing a
collection (or under similar circumstances). So the modePath is
LISTING.ADDING and we return to LISTING after the new instance
is OKed.
- Throws:
UIFormManagerException
okContainedAdd
protected void okContainedAdd(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- Add a new instance contained inside of a parent object. Since a
contained add is by definition a dependent object, there is no
need to do any tracking here. We simply modify the parent, and
when those updates are OKed, the contained objects will be handled
in the same operation.
The currInst contains the new instance. We can find the parent
off the rootMsg since any previous changes will have already been
merged in before we went to add the new instance. See doActionAdd
for details.
At conclusion of processing the currInst will be set to the
parent, and the mode will be either ADDING or UPDATING, depending
on what it was when we added the contained instance. Note that
pendingEdits is still false. We have merged our changes into the
updated currInst, which is either being ADDED or UPDATED. So the
tracking of updates (and setting pendingEdits to true) happens
either in okTopLevelAdd or okUpdate. If the user cancels,
pendingEdits remains whatever it was before.
- Throws:
UIFormManagerException
okNewReference
protected void okNewReference(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- Add a reference from the parent to a new instance. This is
kind of a mix between okContainedAdd, and okTopLevelAdd. We need
to track the update to the new object, and set the reference in
the object we were originally editing.
- Throws:
UIFormManagerException
okUpdate
protected void okUpdate(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- Process the update operation, tracking the necessary updates.
The user reaches the editing screen by first traversing to the
instance they want to work with (either via drilldown or selecting
from a collection). They then click "edit", possibly make changes,
and click "ok" (or they click "save", which calls the same "ok"
processing.
It is possible that processing may fail as part of the save
if application logic is violated by the update (invalid field
value or whatever). In that case the user will either fix their
update and save again, or cancel. If they cancel, then the
data they are working with needs to revert back to what it was
before, which means that the reference copy can't be modified
here. However if we are modifying a contained instance, then
we must merge those changes into the current parent so
they get recorded when the parent gets saved. Yet another reason
why contained objects should be used only for simple structures
requiring minimal validation.
Implementation notes:
- While it is a tempting optimization to compare uifc.getCurrInst()
against uifc.getCurrentObject() via isEquivalent() and skip the
update, this isn't valid. The reason is that the merge into the
rootMsg may have occurred during a previous ADD of a contained
object, and now we are updating the parent. In this case
isEquivalent would return true, even though the update still
needs to happen. It's intuitively probably better to always do
the update when the user clicks the button anyway.
- We may be adding an element to a contained field while updating
the object we are editing, so even through the default
GENMOD_ACTION is SET, we check to see if it should be APPEND.
- Throws:
UIFormManagerException
trace
protected void trace(int level,
java.lang.String text)
- Debugging output statements. Level 0 is some high level method
calls, level 1 is more details.
processUpdate
protected void processUpdate(SandInstanceMessage sim,
UIFormContext uifc,
int updateAction,
UIFormOwner owner)
throws UIFormManagerException
- Get the update message for this struct message, fill it out, and
call trackUpdates. If this is a DELETE action, then we need to
process it immediately, rather than waiting to do several updates
within a single transaction. Otherwise the display gets extremely
unintuitive.
- Throws:
UIFormManagerException
wrappedGenAdd
protected void wrappedGenAdd(java.lang.String prefix,
UIFormContext uifc,
SandInstanceMessage parent,
SandInstanceMessage child)
throws UIFormManagerException
- Figures out SET/APPEND/INSERT action and calls wrappedGenMod.
- Throws:
UIFormManagerException
wrappedGenMod
protected void wrappedGenMod(java.lang.String prefix,
SandInstanceMessage sim,
int action,
java.lang.String field,
int arrayIndex,
java.lang.Object opmsg)
throws UIFormManagerException
- Wrap the general modifier call. This catches any thrown
SandException and wraps it into a UIFormManagerException.
- Throws:
UIFormManagerException
handleSummaryEditAdd
protected boolean handleSummaryEditAdd(UIFormContext uifc,
UIFormOwner owner)
throws UIFormManagerException
- If we are adding an instance to a summaryedit display, then save
a new default instance directly without moving to another screen.
This method returns true if the ACTION_ADD was handled as a
summaryedit addition, false otherwise.
The implementation of this method first checks to see if this
is a summaryedit add. If not, then it immediately returns false,
otherwise it processes the summaryedit add and returns true or
throws.
- Throws:
UIFormManagerException
getClassDisambiguationPrompt
protected java.lang.String getClassDisambiguationPrompt()
- Return the text for the UIFormQuery asking to disambiguate the
class type. Defaults to CLASS_DISAMBIGUATION_PROMPT, override
to return custom text.
getFieldValidationFailureText
protected java.lang.String getFieldValidationFailureText()
- Accessor for field validation failure on save. Defaults to
FIX_FIELDS_BEFORE_SAVE, override to return custom text.
getInvalidFieldMessagePrefix
protected java.lang.String getInvalidFieldMessagePrefix()
- Accessor for invalid field value messages. Defaults to
INVALID_FIELD_VALUE_PREFIX, override to return custom text.
mergeChangesToParentBeforeAdd
protected abstract boolean mergeChangesToParentBeforeAdd(UIFormContext uifc)
throws UIFormManagerException
- We are about to do a contained add, so make sure any outstanding
changes to the currInst are captured before it gets replaced with
a new instance for editing. Return true if everything is ok, and
false if the add operation should be cancelled. If returning false,
set an outbound message to inform the user what happened.
The typical action here is to merge the changes back into the
rootMsg, since the user can always cancel work on the particular
message instance (it's only when they OK or CANCEL the rootMsg
work that the updates need to be tracked or thrown away). But an
editor that is working completely from a single object instance
(such as the ConfigEditor or UIEditor) and does not have any of
undo infrastructure (such as the webapp versions of these tools),
can't just modify the rootMsg and still support cancel. In these
instance this method should return false.
This method is only called if there are changes that need to
be captured.
- Throws:
UIFormManagerException
supportsTopLevelAdd
protected abstract boolean supportsTopLevelAdd()
- Returns true if this form manager allows new top level object
instances to be created while in LISTING mode. Typically a single
object editor would not support this, while a general persistent
object editor might.
supportsTopLevelFind
protected abstract boolean supportsTopLevelFind()
- Returns true if this form manager allows other top level object
instances to be found while in LISTING mode. Typically a single
object editor would not support this, while a general persistent
object editor might.
trackUpdates
protected abstract void trackUpdates(SandUpdateMessage update,
UIFormContext uifc)
throws UIFormManagerException
- Track this update for save processing. The update will already have
been merged into the rootMsg of the uifc. This given update message
is a part of the root message which has changed. It may be modified
multiple times before save is called.
The update is typically either added to the AggregateUpdate in
the uifc updates, or it is ignored because the rootMsg is written
directly. Note that if find or add is supported at the top level,
then the rootMsg may change and not be available at save time.
- Throws:
UIFormManagerException