Subversion Repository Public Repository

litesoft

Diff Revisions 949 vs 950 for /trunk/Java/GWT/OldServer/src/org/litesoft/GWT/forms/server/support/nonpublic/AbstractFormServicePeer.java

Diff revisions: vs.
  @@ -1,628 +1,627 @@
1 - // This Source Code is in the Public Domain per: http://unlicense.org
2 - package org.litesoft.GWT.forms.server.support.nonpublic;
3 -
4 - import org.litesoft.GWT.forms.server.*;
5 - import org.litesoft.GWT.forms.server.support.*;
6 - import org.litesoft.*;
7 - import org.litesoft.changemanagement.*;
8 - import org.litesoft.commonfoundation.base.*;
9 - import org.litesoft.commonfoundation.exceptions.*;
10 - import org.litesoft.commonfoundation.typeutils.Objects;
11 - import org.litesoft.core.delayed.*;
12 - import org.litesoft.core.simpletypes.*;
13 - import org.litesoft.delayed.*;
14 - import org.litesoft.ui.def.*;
15 - import org.litesoft.ui.def.nonpublic.support.*;
16 - import org.litesoft.ui.support.*;
17 - import org.litesoft.ui_1_5.*;
18 -
19 - import java.io.*;
20 - import java.util.*;
21 -
22 - public abstract class AbstractFormServicePeer implements FormServicePeer,
23 - ServerStateChangedListener,
24 - FSPTypeHelperBackDoor {
25 - public static final String ERR_COMMIT_FAILED = "CommitFailed";
26 - public static final String ERR_COMMIT_OUT_OF_DATE_DATA = "OutOfDateDataCausedCommitFailure";
27 -
28 - private final MillisecTimeSource mMillisecTimeSource = MillisecTimeSource.INSTANCE;
29 -
30 - protected volatile PushInterface mPushInterface = null;
31 - protected ISystemUserResolver mSystemUserResolver = ISystemUserResolver.NULL;
32 - protected Serializable mInitializationPayload;
33 - protected volatile boolean mIsNewRootObject;
34 -
35 - private volatile boolean mDisposed = false;
36 - private final TypeHelperManager mTypeHelperManager = new TypeHelperManager();
37 - private final InstanceHelperManager mInstanceHelperManager = new InstanceHelperManager();
38 -
39 - private final FormInteractionHelper mInteractionHelper = new FormInteractionHelper();
40 -
41 - private ServicePeerToFormDataProxy mCollectorProxy = new ServicePeerToFormDataProxy();
42 -
43 - public ServicePeerToFormDataProxy getCollectorProxy() {
44 - return mCollectorProxy;
45 - }
46 -
47 - protected void rootObjectCommited() {
48 - FormInteractionStructure zFIS = mInteractionHelper.rootObjectCommited();
49 - if ( zFIS != null ) {
50 - publish( zFIS, ServerStateChange.Action.UPDATED );
51 - }
52 - }
53 -
54 - private void handle( FormInteractionChange pChange ) {
55 - if ( pChange != null ) {
56 - FormInteractionStructure zOldData = pChange.getOldData();
57 - FormInteractionStructure zNewData = pChange.getNewData();
58 -
59 - if ( zOldData.isPublishable() ) {
60 - // todo: Need Instance of: ChangeListenerManager.removeListener( this );
61 - publish( zOldData, ServerStateChange.Action.DELETED );
62 - }
63 - if ( zNewData.isPublishable() ) {
64 - // todo: Need Instance of: ChangeListenerManager.addListener( this, "FSP:" + zNewData.getRootType(), (Serializable) zNewData.getRootObjectKey() );
65 - publish( zNewData, ServerStateChange.Action.CREATED );
66 - }
67 -
68 - getCollectorProxy().update( zOldData, zNewData );
69 - }
70 - }
71 -
72 - protected void setOurData( FormInteractionStructure pNewData ) {
73 - handle( mInteractionHelper.setOurData( pNewData ) );
74 - }
75 -
76 - private void publish( FormInteractionStructure pData, ServerStateChange.Action pAction ) {
77 - ServerStateChange zChange = new ServerStateChange( pAction, "FSP:" + pData.getRootType(), pData.getRootObjectKey(), null, pData );
78 - Long zSourceUniqueID = pData.getUniqueFormServicePeerID();
79 - ServerStateChangeSet zChangeSet = new ServerStateChangeSet( zSourceUniqueID, null, zChange );
80 - // todo: Need Instance of: ChangeListenerManager.notifyAllListeners( zChangeSet );
81 - }
82 -
83 - public void serverStateChanged( ServerStateChangeSet pServerStateChangeSet ) {
84 - // event order?
85 - FormInteractionIntersection zFII = mInteractionHelper.createFormInteractionIntersection( pServerStateChangeSet );
86 - if ( zFII.getData().isPublishable() ) {
87 - if ( zFII.isNewOthers() ) {
88 - // New Others may not know about us, so we publish (again)
89 - publish( zFII.getData(), ServerStateChange.Action.CREATED );
90 - }
91 - if ( zFII.isUpdateOthers() || zFII.isNewOthers() || zFII.isDelOthers() ) {
92 - getCollectorProxy().forceReturn();
93 - mRunnable.runOnOrAfter( 2000 ); // 2 secs
94 - }
95 - }
96 - }
97 -
98 - private MyTimedRunnable mRunnable = new MyTimedRunnable();
99 -
100 - private class MyTimedRunnable implements TimedRunnable {
101 - private Long mSendWhen = null;
102 -
103 - public synchronized void runOnOrAfter( int pSendIn ) {
104 - boolean zNotLaunched = (mSendWhen == null);
105 -
106 - long zSendWhen = mMillisecTimeSource.now() + pSendIn;
107 -
108 - mSendWhen = zSendWhen;
109 -
110 - if ( zNotLaunched ) {
111 - TimedRunnableManager.INSTANCE.runOnOrAfter( this, zSendWhen );
112 - }
113 - }
114 -
115 - public Again runOnce() {
116 - synchronized ( this ) {
117 - if ( mSendWhen == null ) {
118 - return null;
119 - }
120 - if ( mMillisecTimeSource.now() < mSendWhen ) {
121 - return new RunAgainOnOrAfter( mSendWhen );
122 - }
123 - mSendWhen = null;
124 - }
125 - sendUnsolicitedData();
126 - return null;
127 - }
128 - }
129 -
130 - protected Long getUniqueFormID() {
131 - return mInteractionHelper.getOurUniqueFormServicePeerID();
132 - }
133 -
134 - public SerializableSystemUserRef getSystemUserRef() {
135 - return mInteractionHelper.getOurSystemUserRef();
136 - }
137 -
138 - protected String getRootType() {
139 - return mInteractionHelper.getOurRootType();
140 - }
141 -
142 - protected String getRootObjectKey() {
143 - return mInteractionHelper.getOurRootObjectKey();
144 - }
145 -
146 - protected void setRootObjectKey( String pRootObjectKey ) {
147 - handle( mInteractionHelper.setRootObjectKey( pRootObjectKey ) );
148 - }
149 -
150 - public TypeHelper getRootTypeHelper() {
151 - return mTypeHelperManager.getRootTypeHelper();
152 - }
153 -
154 - public InstanceHelper getRootInstanceHelper() {
155 - return mInstanceHelperManager.getRootInstanceHelper();
156 - }
157 -
158 - protected void setFullUpdate() {
159 - getCollectorProxy().setFullUpdate();
160 - }
161 -
162 - protected void setCloseRequested() {
163 - getCollectorProxy().setCloseRequested();
164 - }
165 -
166 - protected void addWarning( String pWarningID, Object... pParameters ) {
167 - getCollectorProxy().addWarning( rootTypeResolveError( pWarningID, pParameters ) );
168 - }
169 -
170 - protected void addError( String pErrorID, Object... pParameters ) {
171 - getCollectorProxy().addError( rootTypeResolveError( pErrorID, pParameters ) );
172 - }
173 -
174 - protected boolean hasErrors() {
175 - return getCollectorProxy().hasErrors();
176 - }
177 -
178 - protected void setSuccessfulTriggeringActionIDIfNotSet( String pSuccessfulTriggeringActionID ) {
179 - getCollectorProxy().setSuccessfulTriggeringActionIDIfNotSet( pSuccessfulTriggeringActionID );
180 - }
181 -
182 - private String rootTypeResolveError( String pErrorID, Object... pParameters ) {
183 - TypeHelper zTypeHelper = getRootTypeHelper();
184 - String resolved = (zTypeHelper != null) ? zTypeHelper.resolveError( pErrorID ) : pErrorID;
185 - return ExternalizationInterface.Helper.injectParameters( resolved, pParameters );
186 - }
187 -
188 - private ExternalizationInterface getRootTypeExternalizationInterface() {
189 - TypeHelper zTypeHelper = getRootTypeHelper();
190 - return (zTypeHelper != null) ? zTypeHelper.getExternalization() : null;
191 - }
192 -
193 - protected void sendUnsolicitedData() {
194 - PushInterface zPushInterface = mPushInterface;
195 - if ( zPushInterface != null ) {
196 - ServicePeerToFormData zData =
197 - getCollectorProxy().createReturnValueFromCollectorIfMatches( null, mInteractionHelper, getRootTypeExternalizationInterface() );
198 - if ( zData != null ) {
199 - zPushInterface.sendUnsolicitedData( zData );
200 - }
201 - }
202 - }
203 -
204 - // protects serializes FormServicePeer interface
205 - public synchronized final ServicePeerToFormCreationData initializeAndCreateFormMetaData( PushInterface pPushInterface,
206 - ISystemUserResolver pSystemUserResolver,
207 - Long pUniqueFormServicePeerID, ISystemUser pSystemUser,
208 - FormUsage pUsage, Serializable pInitializationPayload,
209 - ExternalizationInterface pExternalization,
210 - FormAccessControl pAccessControl ) {
211 - mPushInterface = pPushInterface;
212 -
213 - initializationPayloadAvailable( mInitializationPayload = pInitializationPayload );
214 -
215 - String zRT = getRootTypeFromUsage( pUsage );
216 -
217 - mSystemUserResolver = (pSystemUserResolver != null) ? pSystemUserResolver : ISystemUserResolver.NULL;
218 -
219 - handle( mInteractionHelper.setOurData( new FormInteractionStructure( pUniqueFormServicePeerID, pSystemUser, zRT ) ) );
220 -
221 - LOGGER.trace.log( zRT, "-initializeAndCreateFormMetaData:", getUniqueFormID(), " for ", pSystemUser );
222 -
223 - TypeHelper zRootTypeHelper = createTypeHelper( this, augment( pExternalization ), pAccessControl, null, zRT, pUsage );
224 -
225 - mTypeHelperManager.setRootTypeHelper( zRootTypeHelper );
226 - mInstanceHelperManager.setRootInstanceHelper( createRootInstanceHelper( zRootTypeHelper ) );
227 -
228 - FormMetaData zMetaData = zRootTypeHelper.initializeAndCreateFormMetaData( pUsage );
229 -
230 - return new ServicePeerToFormCreationData( zMetaData, getFormRenderedServicePeerXtra() );
231 - }
232 -
233 - protected String getRootTypeFromUsage( FormUsage pUsage ) {
234 - return pUsage.getRootType();
235 - }
236 -
237 - public void add( TypeHelper pTypeHelper ) {
238 - mTypeHelperManager.add( pTypeHelper );
239 - }
240 -
241 - public void add( InstanceHelper pInstanceHelper ) {
242 - mInstanceHelperManager.add( pInstanceHelper );
243 - }
244 -
245 - public void removeInstanceHelper( FormDataRowKey pFormDataRowKey ) {
246 - mInstanceHelperManager.remove( pFormDataRowKey );
247 - }
248 -
249 - public final boolean isDisposed() {
250 - return mDisposed;
251 - }
252 -
253 - // protects serializes FormServicePeer interface
254 - public synchronized final void dispose() {
255 - if ( !mDisposed ) {
256 - mDisposed = true;
257 - try {
258 - LLdispose();
259 - }
260 - catch ( RuntimeException e ) {
261 - LOGGER.error.log( e );
262 - }
263 -
264 - mInstanceHelperManager.dispose();
265 - mTypeHelperManager.dispose();
266 - handle( mInteractionHelper.setOurData( null ) );
267 - mPushInterface = null;
268 - mInitializationPayload = null;
269 - }
270 - }
271 -
272 - // protects serializes FormServicePeer interface
273 - public synchronized final ServicePeerToFormData setRootObjectTo( Integer pAsyncMessageNumber, String pKey ) {
274 - LOGGER.trace.log( getRootType(), "-setRootObjectTo, key:", pKey );
275 -
276 - getCollectorProxy().setCallFromClientForm( pAsyncMessageNumber );
277 -
278 - mInstanceHelperManager.resetAllInstanceHelpers();
279 -
280 - LLsetRootObjectTo( pKey );
281 -
282 - mInstanceHelperManager.loadAllAttributeValues();
283 -
284 - return getCollectorProxy().createReturnValueFromCollectorIfMatches( pAsyncMessageNumber, mInteractionHelper, getRootTypeExternalizationInterface() );
285 - }
286 -
287 - // protects serializes FormServicePeer interface
288 - public synchronized final AttributeResourceOptionsResponseData getResourceOptions( AttributeResourceOptionsRequestData pRequest ) {
289 - return getResourceOptions( pRequest.getFormDataRowKey(), pRequest.getUniqueID(), pRequest.getAttributeReference() );
290 - }
291 -
292 - // protects serializes FormServicePeer interface
293 - public synchronized final ServicePeerToFormData formEvent( FormToServicePeerData pToServicePeerData ) {
294 - Objects.assertNotNull( "ToServicePeerData", pToServicePeerData );
295 -
296 - Integer zAsyncMessageNumber = pToServicePeerData.getAsyncMessageNumber();
297 -
298 - getCollectorProxy().setCallFromClientForm( zAsyncMessageNumber );
299 -
300 - ValueUpdatedFormData[] zValueUpdates = pToServicePeerData.getAttributeUpdates();
301 - if ( zValueUpdates != null ) {
302 - for ( ValueUpdatedFormData update : zValueUpdates ) {
303 - processValueUpdated( update.getFormDataRowKey(), //
304 - update.getUniqueID(), update.getAttributeReference(), update.getCurrentValue() );
305 - }
306 - }
307 -
308 - ActionRequestFormData action = pToServicePeerData.getActionRequest();
309 - if ( action != null ) {
310 - processActionRequest( action.getFormDataRowKey(), action.getActionID(), action.isInputAction(), action.getParentFormDataRowKey() );
311 - }
312 -
313 - return getCollectorProxy().createReturnValueFromCollectorIfMatches( zAsyncMessageNumber, mInteractionHelper, getRootTypeExternalizationInterface() );
314 - }
315 -
316 - protected AttributeResourceOptionsResponseData getResourceOptions( FormDataRowKey pFormDataRowKey, Integer pUniqueID, String pAttributeReference ) {
317 - InstanceHelper zInstanceHelper = getInstanceHelper( pFormDataRowKey );
318 - if ( (zInstanceHelper != null) ) {
319 - AMDconverterPair changingPair = zInstanceHelper.findAttribute( pUniqueID );
320 - if ( changingPair != null ) {
321 - return zInstanceHelper.getTypeHelper().getResourceOptions( pAttributeReference, changingPair.getDataConverter() );
322 - }
323 - }
324 - return new AttributeResourceOptionsResponseData( ResourceOptionsErrorType.ErrorReferenceNotFound );
325 - }
326 -
327 - private void processValueUpdated( FormDataRowKey pFormDataRowKey, //
328 - Integer pUniqueID, String pAttributeReference, //
329 - Serializable pNewValue ) {
330 - //System.out.println( getRootType() + "-valueUpdated on (" + pFormDataRowKey + ") '" +
331 - // pAttributeReference + "' to '" + pNewValue + "' type:" +
332 - // ((pNewValue != null) ? pNewValue.getClass() : null) );
333 - //
334 - LOGGER.trace.log( getRootType(), "-valueUpdated on (", pFormDataRowKey, ") '", pAttributeReference, "' to '", pNewValue, "' type:",
335 - ((pNewValue != null) ? pNewValue.getClass() : null) );
336 -
337 - String zResolvedError = null;
338 - AMDconverterPair changingPair = null;
339 - boolean handled = false;
340 -
341 - try {
342 - handled = LLrawValueUpdated( pFormDataRowKey, pAttributeReference, pNewValue );
343 - }
344 - catch ( IllegalArgumentException e ) {
345 - addError( ERR_ILLEGAL_VALUE, "LLrawValueUpdated", e.getMessage() );
346 - }
347 - catch ( RuntimeException e ) {
348 - addError( ERR_UNEXPECTED, "LLrawValueUpdated", e.getMessage() );
349 - }
350 -
351 - if ( !handled && !hasErrors() ) {
352 - InstanceHelper zInstanceHelper = getInstanceHelper( pFormDataRowKey );
353 - if ( zInstanceHelper == null ) {
354 - addError( ERR_ATTR_NOT_FOUND );
355 - } else if ( (null == (changingPair = zInstanceHelper.findAttribute( pUniqueID ))) ) {
356 - addError( ERR_ATTR_NOT_FOUND );
357 - } else {
358 - Object zValueForAttribute = null;
359 - try {
360 - zValueForAttribute = changingPair.getDataConverter().convertFromPassable( pNewValue );
361 - }
362 - catch ( IllegalArgumentException e ) {
363 - zResolvedError = rootTypeResolveError( ERR_ILLEGAL_VALUE, "Converted", e.getMessage() );
364 - }
365 - catch ( RuntimeException e ) {
366 - zResolvedError = rootTypeResolveError( ERR_UNEXPECTED, "Converted", e.getMessage() );
367 - }
368 - if ( zResolvedError == null ) {
369 - try {
370 - if ( !(handled = LLvalueUpdated( zInstanceHelper, pAttributeReference, zValueForAttribute )) ) {
371 - zResolvedError = rootTypeResolveError( ERR_VALUE_UPDATE_NOT_HANDLED );
372 - }
373 - }
374 - catch ( IllegalArgumentException e ) {
375 - zResolvedError = rootTypeResolveError( ERR_ILLEGAL_VALUE, "Update", e.getMessage() );
376 - }
377 - catch ( NoSuchElementException e ) {
378 - zResolvedError = rootTypeResolveError( ERR_ATTR_NOT_FOUND, "Update", e.getMessage() );
379 - }
380 - catch ( RuntimeException e ) {
381 - zResolvedError = rootTypeResolveError( ERR_UNEXPECTED, "Update", e.getMessage() );
382 - }
383 - }
384 - }
385 - }
386 - if ( handled || (zResolvedError != null) ) {
387 - checkForChanges( changingPair, pNewValue, zResolvedError );
388 - }
389 - }
390 -
391 - protected boolean LLvalueUpdated( InstanceHelper pInstanceHelper, String pAttributeReference, Object pValueForAttribute ) {
392 - return pInstanceHelper.valueUpdated( pAttributeReference, pValueForAttribute );
393 - }
394 -
395 - private void processActionRequest( FormDataRowKey pFormDataRowKey, String pActionID, boolean pInputAction, FormDataRowKey pParentFormDataRowKey ) {
396 - LOGGER.trace.log( getRootType(), "-actionRequest, ", (pInputAction ? "Input" : "Reg"), " action:", pActionID );
397 -
398 - if ( actionRequest( pFormDataRowKey, pActionID, pInputAction, pParentFormDataRowKey ) ) {
399 - checkForChanges( null, null, null );
400 - } else if ( !pInputAction ) {
401 - addError( ERR_UNKNOWN_ACTION );
402 - }
403 - if ( !hasErrors() ) {
404 - setSuccessfulTriggeringActionIDIfNotSet( pActionID );
405 - }
406 - }
407 -
408 - protected void checkForChanges( AMDconverterPair pChangingPair, Serializable pNewValue, String pResolvedError ) {
409 - // Snag a list to avoid Concurrent Changes
410 - InstanceHelpersSnapShot zSnapShot = mInstanceHelperManager.getInstanceHelpers();
411 - InstanceHelper zRootHelper = zSnapShot.getRootInstanceHelper();
412 - zRootHelper.checkForChanges( pChangingPair, pNewValue, pResolvedError );
413 - for ( InstanceHelper helper : zSnapShot.getAllInstanceHelpers() ) {
414 - if ( helper != zRootHelper ) {
415 - helper.checkForChanges( pChangingPair, pNewValue, pResolvedError );
416 - }
417 - }
418 - }
419 -
420 - public boolean actionRequest( FormDataRowKey pFormDataRowKey, String pActionID, boolean pInputAction, FormDataRowKey pParentFormDataRowKey ) {
421 - if ( UiFormDef.ACTION_CLOSE.equals( pActionID ) ) {
422 - return actionClose( pActionID );
423 - }
424 - if ( UiFormDef.ACTION_DONE.equals( pActionID ) ) {
425 - return actionDone( pActionID );
426 - }
427 - if ( UiFormDef.ACTION_COMMIT.equals( pActionID ) ) {
428 - return actionCommit( pActionID );
429 - }
430 - if ( UiFormDef.ACTION_RELOAD.equals( pActionID ) ) {
431 - return actionReload( pActionID );
432 - }
433 - if ( UiFormDef.ACTION_NEW.equals( pActionID ) ) {
434 - return actionNew( pActionID );
435 - }
436 - InstanceHelper zInstanceHelper = getInstanceHelper( pFormDataRowKey );
437 - if ( zInstanceHelper != null ) {
438 - return zInstanceHelper.actionRequest( pActionID, pInputAction );
439 - }
440 - TypeHelper zTypeHelper = getTypeHelper( pFormDataRowKey );
441 - return (zTypeHelper != null) && //
442 - zTypeHelper.actionRequest( pActionID, pInputAction, getInstanceHelper( pParentFormDataRowKey ) );
443 - }
444 -
445 - public ArrayList<FormDataRowKey> getAllCurrentFormDataRowKeys() {
446 - return mInstanceHelperManager.getAllCurrentFormDataRowKeys();
447 - }
448 -
449 - public InstanceHelper getInstanceHelper( FormDataRowKey pFormDataRowKey ) {
450 - return mInstanceHelperManager.getInstanceHelper( pFormDataRowKey ); // null == Root
451 - }
452 -
453 - private TypeHelper getTypeHelper( FormDataRowKey pFormDataRowKey ) {
454 - return mTypeHelperManager.getTypeHelper( pFormDataRowKey ); // null == root
455 - }
456 -
457 - /**
458 - * @return true to indicate processing satisfied
459 - */
460 - protected boolean actionClose( String pSuccessfulTriggeringActionID ) {
461 - setCloseRequested();
462 - return true;
463 - }
464 -
465 - /**
466 - * Abandon any existing Root Object and create a new one
467 - *
468 - * @return true to indicate processing satisfied
469 - */
470 - protected boolean actionNew( String pSuccessfulTriggeringActionID ) {
471 - createNewRootObject();
472 - return initializeUpdates( pSuccessfulTriggeringActionID );
473 - }
474 -
475 - /**
476 - * Save current (mutated?) state of our backing Root Object and if successful
477 - * prepare the Root Object for future editing.
478 - *
479 - * @return true to indicate processing satisfied
480 - */
481 - protected boolean actionCommit( String pSuccessfulTriggeringActionID ) {
482 - commit();
483 - return hasErrors() || initializeUpdates( pSuccessfulTriggeringActionID );
484 - }
485 -
486 - /**
487 - * Save current (mutated?) state of our backing Root Object and if successful
488 - * request Close, and just in case Form is not closed then
489 - * prepare the Root Object for future editing.
490 - *
491 - * @return true to indicate processing satisfied
492 - */
493 - protected boolean actionDone( String pSuccessfulTriggeringActionID ) {
494 - commit();
495 - if ( hasErrors() ) {
496 - return true;
497 - }
498 - setCloseRequested();
499 - return initializeUpdates( pSuccessfulTriggeringActionID );
500 - }
501 -
502 - /**
503 - * Refresh the current Root Object with the latest version from its source (eg database)
504 - * (or a fresh new one if it was new and never committed)
505 - *
506 - * @return true to indicate processing satisfied
507 - */
508 - public boolean actionReload( String pSuccessfulTriggeringActionID ) {
509 - if ( !hasRootObject() ) {
510 - return true;
511 - }
512 - if ( mIsNewRootObject ) {
513 - createNewRootObject();
514 - } else {
515 - reloadExistingRootObject();
516 - }
517 - return initializeUpdates( pSuccessfulTriggeringActionID );
518 - }
519 -
520 - protected boolean initializeUpdates( String pSuccessfulTriggeringActionID ) {
521 - if ( hasRootObject() ) {
522 - setFullUpdate();
523 - setSuccessfulTriggeringActionIDIfNotSet( pSuccessfulTriggeringActionID );
524 - mInstanceHelperManager.resetAllInstanceHelpers();
525 - mInstanceHelperManager.loadAllAttributeValues();
526 - }
527 - return true;
528 - }
529 -
530 - protected void commit() {
531 - if ( hasRootObject() ) {
532 - try {
533 - LLcommit(); // commit what we've got
534 - }
535 - catch ( ConcurrentModificationException e ) {
536 - addError( ERR_COMMIT_OUT_OF_DATE_DATA );
537 - return;
538 - }
539 - catch ( RuntimeException e ) {
540 - LOGGER.warn.log( e, "Attempt to commit backing Root Object failed" );
541 - if ( e instanceof DisplayableException ) {
542 - DisplayableException zDE = (DisplayableException) e;
543 - String zParam = rootTypeResolveError( zDE.getToResolveIdentifier(), //
544 - (Object[]) zDE.getParams() );
545 - addError( ERR_COMMIT_FAILED, zParam );
546 - } else {
547 - addError( ERR_COMMIT_FAILED );
548 - }
549 - return;
550 - }
551 - rootObjectCommited();
552 - }
553 - }
554 -
555 - protected void createNewRootObject() {
556 - mIsNewRootObject = true;
557 - String zRootObjectKey = LLnewRootObject();
558 - setRootObjectKey( zRootObjectKey );
559 - }
560 -
561 - protected void reloadExistingRootObject() {
562 - mIsNewRootObject = false;
563 - LLreloadExistingRootObject();
564 - mInteractionHelper.clearUpdatedData();
565 - }
566 -
567 - protected void loadExistingRootObject( String pNewRootObjectKey ) {
568 - mIsNewRootObject = false;
569 - if ( LLloadExistingRootObject( pNewRootObjectKey ) ) {
570 - setRootObjectKey( pNewRootObjectKey );
571 - }
572 - }
573 -
574 - /**
575 - * Either load the appropriate Root Object based on pKey, or create one if pKey was null
576 - */
577 - protected void LLsetRootObjectTo( String pKey ) {
578 - if ( pKey == null ) {
579 - createNewRootObject();
580 - } else {
581 - loadExistingRootObject( pKey );
582 - }
583 - }
584 -
585 - protected void LLdispose() {
586 - }
587 -
588 - /**
589 - * @return true to indicate processing satisfied
590 - */
591 - protected boolean LLrawValueUpdated( FormDataRowKey pFormDataRowKey, String pAttributeReference, Serializable pNewValue ) {
592 - return false;
593 - }
594 -
595 - protected void initializationPayloadAvailable( Serializable pInitializationPayload ) {
596 - }
597 -
598 - protected ExternalizationInterface augment( ExternalizationInterface pExternalizationInterface ) {
599 - return pExternalizationInterface;
600 - }
601 -
602 - protected InterceptingProxyExternalization proxy( ExternalizationInterface pExternalizationInterface ) {
603 - return new InterceptingProxyExternalization( pExternalizationInterface );
604 - }
605 -
606 - protected Serializable getFormRenderedServicePeerXtra() {
607 - return null;
608 - }
609 -
610 - abstract protected void LLcommit();
611 -
612 - abstract protected boolean hasRootObject();
613 -
614 - /**
615 - * @return new Root Objects Key
616 - */
617 - abstract protected String LLnewRootObject();
618 -
619 - /**
620 - * @return true if succeeded
621 - */
622 - abstract protected boolean LLreloadExistingRootObject();
623 -
624 - /**
625 - * @return true if succeeded
626 - */
627 - abstract protected boolean LLloadExistingRootObject( String pNewRootObjectKey );
628 - }
1 + // This Source Code is in the Public Domain per: http://unlicense.org
2 + package org.litesoft.GWT.forms.server.support.nonpublic;
3 +
4 + import org.litesoft.GWT.forms.server.*;
5 + import org.litesoft.GWT.forms.server.support.*;
6 + import org.litesoft.*;
7 + import org.litesoft.changemanagement.*;
8 + import org.litesoft.commonfoundation.base.*;
9 + import org.litesoft.commonfoundation.exceptions.*;
10 + import org.litesoft.core.delayed.*;
11 + import org.litesoft.core.simpletypes.*;
12 + import org.litesoft.delayed.*;
13 + import org.litesoft.ui.def.*;
14 + import org.litesoft.ui.def.nonpublic.support.*;
15 + import org.litesoft.ui.support.*;
16 + import org.litesoft.ui_1_5.*;
17 +
18 + import java.io.*;
19 + import java.util.*;
20 +
21 + public abstract class AbstractFormServicePeer implements FormServicePeer,
22 + ServerStateChangedListener,
23 + FSPTypeHelperBackDoor {
24 + public static final String ERR_COMMIT_FAILED = "CommitFailed";
25 + public static final String ERR_COMMIT_OUT_OF_DATE_DATA = "OutOfDateDataCausedCommitFailure";
26 +
27 + private final MillisecTimeSource mMillisecTimeSource = MillisecTimeSource.INSTANCE;
28 +
29 + protected volatile PushInterface mPushInterface = null;
30 + protected ISystemUserResolver mSystemUserResolver = ISystemUserResolver.NULL;
31 + protected Serializable mInitializationPayload;
32 + protected volatile boolean mIsNewRootObject;
33 +
34 + private volatile boolean mDisposed = false;
35 + private final TypeHelperManager mTypeHelperManager = new TypeHelperManager();
36 + private final InstanceHelperManager mInstanceHelperManager = new InstanceHelperManager();
37 +
38 + private final FormInteractionHelper mInteractionHelper = new FormInteractionHelper();
39 +
40 + private ServicePeerToFormDataProxy mCollectorProxy = new ServicePeerToFormDataProxy();
41 +
42 + public ServicePeerToFormDataProxy getCollectorProxy() {
43 + return mCollectorProxy;
44 + }
45 +
46 + protected void rootObjectCommited() {
47 + FormInteractionStructure zFIS = mInteractionHelper.rootObjectCommited();
48 + if ( zFIS != null ) {
49 + publish( zFIS, ServerStateChange.Action.UPDATED );
50 + }
51 + }
52 +
53 + private void handle( FormInteractionChange pChange ) {
54 + if ( pChange != null ) {
55 + FormInteractionStructure zOldData = pChange.getOldData();
56 + FormInteractionStructure zNewData = pChange.getNewData();
57 +
58 + if ( zOldData.isPublishable() ) {
59 + // todo: Need Instance of: ChangeListenerManager.removeListener( this );
60 + publish( zOldData, ServerStateChange.Action.DELETED );
61 + }
62 + if ( zNewData.isPublishable() ) {
63 + // todo: Need Instance of: ChangeListenerManager.addListener( this, "FSP:" + zNewData.getRootType(), (Serializable) zNewData.getRootObjectKey() );
64 + publish( zNewData, ServerStateChange.Action.CREATED );
65 + }
66 +
67 + getCollectorProxy().update( zOldData, zNewData );
68 + }
69 + }
70 +
71 + protected void setOurData( FormInteractionStructure pNewData ) {
72 + handle( mInteractionHelper.setOurData( pNewData ) );
73 + }
74 +
75 + private void publish( FormInteractionStructure pData, ServerStateChange.Action pAction ) {
76 + ServerStateChange zChange = new ServerStateChange( pAction, "FSP:" + pData.getRootType(), pData.getRootObjectKey(), null, pData );
77 + Long zSourceUniqueID = pData.getUniqueFormServicePeerID();
78 + ServerStateChangeSet zChangeSet = new ServerStateChangeSet( zSourceUniqueID, null, zChange );
79 + // todo: Need Instance of: ChangeListenerManager.notifyAllListeners( zChangeSet );
80 + }
81 +
82 + public void serverStateChanged( ServerStateChangeSet pServerStateChangeSet ) {
83 + // event order?
84 + FormInteractionIntersection zFII = mInteractionHelper.createFormInteractionIntersection( pServerStateChangeSet );
85 + if ( zFII.getData().isPublishable() ) {
86 + if ( zFII.isNewOthers() ) {
87 + // New Others may not know about us, so we publish (again)
88 + publish( zFII.getData(), ServerStateChange.Action.CREATED );
89 + }
90 + if ( zFII.isUpdateOthers() || zFII.isNewOthers() || zFII.isDelOthers() ) {
91 + getCollectorProxy().forceReturn();
92 + mRunnable.runOnOrAfter( 2000 ); // 2 secs
93 + }
94 + }
95 + }
96 +
97 + private MyTimedRunnable mRunnable = new MyTimedRunnable();
98 +
99 + private class MyTimedRunnable implements TimedRunnable {
100 + private Long mSendWhen = null;
101 +
102 + public synchronized void runOnOrAfter( int pSendIn ) {
103 + boolean zNotLaunched = (mSendWhen == null);
104 +
105 + long zSendWhen = mMillisecTimeSource.now() + pSendIn;
106 +
107 + mSendWhen = zSendWhen;
108 +
109 + if ( zNotLaunched ) {
110 + TimedRunnableManager.INSTANCE.runOnOrAfter( this, zSendWhen );
111 + }
112 + }
113 +
114 + public Again runOnce() {
115 + synchronized ( this ) {
116 + if ( mSendWhen == null ) {
117 + return null;
118 + }
119 + if ( mMillisecTimeSource.now() < mSendWhen ) {
120 + return new RunAgainOnOrAfter( mSendWhen );
121 + }
122 + mSendWhen = null;
123 + }
124 + sendUnsolicitedData();
125 + return null;
126 + }
127 + }
128 +
129 + protected Long getUniqueFormID() {
130 + return mInteractionHelper.getOurUniqueFormServicePeerID();
131 + }
132 +
133 + public SerializableSystemUserRef getSystemUserRef() {
134 + return mInteractionHelper.getOurSystemUserRef();
135 + }
136 +
137 + protected String getRootType() {
138 + return mInteractionHelper.getOurRootType();
139 + }
140 +
141 + protected String getRootObjectKey() {
142 + return mInteractionHelper.getOurRootObjectKey();
143 + }
144 +
145 + protected void setRootObjectKey( String pRootObjectKey ) {
146 + handle( mInteractionHelper.setRootObjectKey( pRootObjectKey ) );
147 + }
148 +
149 + public TypeHelper getRootTypeHelper() {
150 + return mTypeHelperManager.getRootTypeHelper();
151 + }
152 +
153 + public InstanceHelper getRootInstanceHelper() {
154 + return mInstanceHelperManager.getRootInstanceHelper();
155 + }
156 +
157 + protected void setFullUpdate() {
158 + getCollectorProxy().setFullUpdate();
159 + }
160 +
161 + protected void setCloseRequested() {
162 + getCollectorProxy().setCloseRequested();
163 + }
164 +
165 + protected void addWarning( String pWarningID, Object... pParameters ) {
166 + getCollectorProxy().addWarning( rootTypeResolveError( pWarningID, pParameters ) );
167 + }
168 +
169 + protected void addError( String pErrorID, Object... pParameters ) {
170 + getCollectorProxy().addError( rootTypeResolveError( pErrorID, pParameters ) );
171 + }
172 +
173 + protected boolean hasErrors() {
174 + return getCollectorProxy().hasErrors();
175 + }
176 +
177 + protected void setSuccessfulTriggeringActionIDIfNotSet( String pSuccessfulTriggeringActionID ) {
178 + getCollectorProxy().setSuccessfulTriggeringActionIDIfNotSet( pSuccessfulTriggeringActionID );
179 + }
180 +
181 + private String rootTypeResolveError( String pErrorID, Object... pParameters ) {
182 + TypeHelper zTypeHelper = getRootTypeHelper();
183 + String resolved = (zTypeHelper != null) ? zTypeHelper.resolveError( pErrorID ) : pErrorID;
184 + return ExternalizationInterface.Helper.injectParameters( resolved, pParameters );
185 + }
186 +
187 + private ExternalizationInterface getRootTypeExternalizationInterface() {
188 + TypeHelper zTypeHelper = getRootTypeHelper();
189 + return (zTypeHelper != null) ? zTypeHelper.getExternalization() : null;
190 + }
191 +
192 + protected void sendUnsolicitedData() {
193 + PushInterface zPushInterface = mPushInterface;
194 + if ( zPushInterface != null ) {
195 + ServicePeerToFormData zData =
196 + getCollectorProxy().createReturnValueFromCollectorIfMatches( null, mInteractionHelper, getRootTypeExternalizationInterface() );
197 + if ( zData != null ) {
198 + zPushInterface.sendUnsolicitedData( zData );
199 + }
200 + }
201 + }
202 +
203 + // protects serializes FormServicePeer interface
204 + public synchronized final ServicePeerToFormCreationData initializeAndCreateFormMetaData( PushInterface pPushInterface,
205 + ISystemUserResolver pSystemUserResolver,
206 + Long pUniqueFormServicePeerID, ISystemUser pSystemUser,
207 + FormUsage pUsage, Serializable pInitializationPayload,
208 + ExternalizationInterface pExternalization,
209 + FormAccessControl pAccessControl ) {
210 + mPushInterface = pPushInterface;
211 +
212 + initializationPayloadAvailable( mInitializationPayload = pInitializationPayload );
213 +
214 + String zRT = getRootTypeFromUsage( pUsage );
215 +
216 + mSystemUserResolver = (pSystemUserResolver != null) ? pSystemUserResolver : ISystemUserResolver.NULL;
217 +
218 + handle( mInteractionHelper.setOurData( new FormInteractionStructure( pUniqueFormServicePeerID, pSystemUser, zRT ) ) );
219 +
220 + LOGGER.trace.log( zRT, "-initializeAndCreateFormMetaData:", getUniqueFormID(), " for ", pSystemUser );
221 +
222 + TypeHelper zRootTypeHelper = createTypeHelper( this, augment( pExternalization ), pAccessControl, null, zRT, pUsage );
223 +
224 + mTypeHelperManager.setRootTypeHelper( zRootTypeHelper );
225 + mInstanceHelperManager.setRootInstanceHelper( createRootInstanceHelper( zRootTypeHelper ) );
226 +
227 + FormMetaData zMetaData = zRootTypeHelper.initializeAndCreateFormMetaData( pUsage );
228 +
229 + return new ServicePeerToFormCreationData( zMetaData, getFormRenderedServicePeerXtra() );
230 + }
231 +
232 + protected String getRootTypeFromUsage( FormUsage pUsage ) {
233 + return pUsage.getRootType();
234 + }
235 +
236 + public void add( TypeHelper pTypeHelper ) {
237 + mTypeHelperManager.add( pTypeHelper );
238 + }
239 +
240 + public void add( InstanceHelper pInstanceHelper ) {
241 + mInstanceHelperManager.add( pInstanceHelper );
242 + }
243 +
244 + public void removeInstanceHelper( FormDataRowKey pFormDataRowKey ) {
245 + mInstanceHelperManager.remove( pFormDataRowKey );
246 + }
247 +
248 + public final boolean isDisposed() {
249 + return mDisposed;
250 + }
251 +
252 + // protects serializes FormServicePeer interface
253 + public synchronized final void dispose() {
254 + if ( !mDisposed ) {
255 + mDisposed = true;
256 + try {
257 + LLdispose();
258 + }
259 + catch ( RuntimeException e ) {
260 + LOGGER.error.log( e );
261 + }
262 +
263 + mInstanceHelperManager.dispose();
264 + mTypeHelperManager.dispose();
265 + handle( mInteractionHelper.setOurData( null ) );
266 + mPushInterface = null;
267 + mInitializationPayload = null;
268 + }
269 + }
270 +
271 + // protects serializes FormServicePeer interface
272 + public synchronized final ServicePeerToFormData setRootObjectTo( Integer pAsyncMessageNumber, String pKey ) {
273 + LOGGER.trace.log( getRootType(), "-setRootObjectTo, key:", pKey );
274 +
275 + getCollectorProxy().setCallFromClientForm( pAsyncMessageNumber );
276 +
277 + mInstanceHelperManager.resetAllInstanceHelpers();
278 +
279 + LLsetRootObjectTo( pKey );
280 +
281 + mInstanceHelperManager.loadAllAttributeValues();
282 +
283 + return getCollectorProxy().createReturnValueFromCollectorIfMatches( pAsyncMessageNumber, mInteractionHelper, getRootTypeExternalizationInterface() );
284 + }
285 +
286 + // protects serializes FormServicePeer interface
287 + public synchronized final AttributeResourceOptionsResponseData getResourceOptions( AttributeResourceOptionsRequestData pRequest ) {
288 + return getResourceOptions( pRequest.getFormDataRowKey(), pRequest.getUniqueID(), pRequest.getAttributeReference() );
289 + }
290 +
291 + // protects serializes FormServicePeer interface
292 + public synchronized final ServicePeerToFormData formEvent( FormToServicePeerData pToServicePeerData ) {
293 + Confirm.isNotNull( "ToServicePeerData", pToServicePeerData );
294 +
295 + Integer zAsyncMessageNumber = pToServicePeerData.getAsyncMessageNumber();
296 +
297 + getCollectorProxy().setCallFromClientForm( zAsyncMessageNumber );
298 +
299 + ValueUpdatedFormData[] zValueUpdates = pToServicePeerData.getAttributeUpdates();
300 + if ( zValueUpdates != null ) {
301 + for ( ValueUpdatedFormData update : zValueUpdates ) {
302 + processValueUpdated( update.getFormDataRowKey(), //
303 + update.getUniqueID(), update.getAttributeReference(), update.getCurrentValue() );
304 + }
305 + }
306 +
307 + ActionRequestFormData action = pToServicePeerData.getActionRequest();
308 + if ( action != null ) {
309 + processActionRequest( action.getFormDataRowKey(), action.getActionID(), action.isInputAction(), action.getParentFormDataRowKey() );
310 + }
311 +
312 + return getCollectorProxy().createReturnValueFromCollectorIfMatches( zAsyncMessageNumber, mInteractionHelper, getRootTypeExternalizationInterface() );
313 + }
314 +
315 + protected AttributeResourceOptionsResponseData getResourceOptions( FormDataRowKey pFormDataRowKey, Integer pUniqueID, String pAttributeReference ) {
316 + InstanceHelper zInstanceHelper = getInstanceHelper( pFormDataRowKey );
317 + if ( (zInstanceHelper != null) ) {
318 + AMDconverterPair changingPair = zInstanceHelper.findAttribute( pUniqueID );
319 + if ( changingPair != null ) {
320 + return zInstanceHelper.getTypeHelper().getResourceOptions( pAttributeReference, changingPair.getDataConverter() );
321 + }
322 + }
323 + return new AttributeResourceOptionsResponseData( ResourceOptionsErrorType.ErrorReferenceNotFound );
324 + }
325 +
326 + private void processValueUpdated( FormDataRowKey pFormDataRowKey, //
327 + Integer pUniqueID, String pAttributeReference, //
328 + Serializable pNewValue ) {
329 + //System.out.println( getRootType() + "-valueUpdated on (" + pFormDataRowKey + ") '" +
330 + // pAttributeReference + "' to '" + pNewValue + "' type:" +
331 + // ((pNewValue != null) ? pNewValue.getClass() : null) );
332 + //
333 + LOGGER.trace.log( getRootType(), "-valueUpdated on (", pFormDataRowKey, ") '", pAttributeReference, "' to '", pNewValue, "' type:",
334 + ((pNewValue != null) ? pNewValue.getClass() : null) );
335 +
336 + String zResolvedError = null;
337 + AMDconverterPair changingPair = null;
338 + boolean handled = false;
339 +
340 + try {
341 + handled = LLrawValueUpdated( pFormDataRowKey, pAttributeReference, pNewValue );
342 + }
343 + catch ( IllegalArgumentException e ) {
344 + addError( ERR_ILLEGAL_VALUE, "LLrawValueUpdated", e.getMessage() );
345 + }
346 + catch ( RuntimeException e ) {
347 + addError( ERR_UNEXPECTED, "LLrawValueUpdated", e.getMessage() );
348 + }
349 +
350 + if ( !handled && !hasErrors() ) {
351 + InstanceHelper zInstanceHelper = getInstanceHelper( pFormDataRowKey );
352 + if ( zInstanceHelper == null ) {
353 + addError( ERR_ATTR_NOT_FOUND );
354 + } else if ( (null == (changingPair = zInstanceHelper.findAttribute( pUniqueID ))) ) {
355 + addError( ERR_ATTR_NOT_FOUND );
356 + } else {
357 + Object zValueForAttribute = null;
358 + try {
359 + zValueForAttribute = changingPair.getDataConverter().convertFromPassable( pNewValue );
360 + }
361 + catch ( IllegalArgumentException e ) {
362 + zResolvedError = rootTypeResolveError( ERR_ILLEGAL_VALUE, "Converted", e.getMessage() );
363 + }
364 + catch ( RuntimeException e ) {
365 + zResolvedError = rootTypeResolveError( ERR_UNEXPECTED, "Converted", e.getMessage() );
366 + }
367 + if ( zResolvedError == null ) {
368 + try {
369 + if ( !(handled = LLvalueUpdated( zInstanceHelper, pAttributeReference, zValueForAttribute )) ) {
370 + zResolvedError = rootTypeResolveError( ERR_VALUE_UPDATE_NOT_HANDLED );
371 + }
372 + }
373 + catch ( IllegalArgumentException e ) {
374 + zResolvedError = rootTypeResolveError( ERR_ILLEGAL_VALUE, "Update", e.getMessage() );
375 + }
376 + catch ( NoSuchElementException e ) {
377 + zResolvedError = rootTypeResolveError( ERR_ATTR_NOT_FOUND, "Update", e.getMessage() );
378 + }
379 + catch ( RuntimeException e ) {
380 + zResolvedError = rootTypeResolveError( ERR_UNEXPECTED, "Update", e.getMessage() );
381 + }
382 + }
383 + }
384 + }
385 + if ( handled || (zResolvedError != null) ) {
386 + checkForChanges( changingPair, pNewValue, zResolvedError );
387 + }
388 + }
389 +
390 + protected boolean LLvalueUpdated( InstanceHelper pInstanceHelper, String pAttributeReference, Object pValueForAttribute ) {
391 + return pInstanceHelper.valueUpdated( pAttributeReference, pValueForAttribute );
392 + }
393 +
394 + private void processActionRequest( FormDataRowKey pFormDataRowKey, String pActionID, boolean pInputAction, FormDataRowKey pParentFormDataRowKey ) {
395 + LOGGER.trace.log( getRootType(), "-actionRequest, ", (pInputAction ? "Input" : "Reg"), " action:", pActionID );
396 +
397 + if ( actionRequest( pFormDataRowKey, pActionID, pInputAction, pParentFormDataRowKey ) ) {
398 + checkForChanges( null, null, null );
399 + } else if ( !pInputAction ) {
400 + addError( ERR_UNKNOWN_ACTION );
401 + }
402 + if ( !hasErrors() ) {
403 + setSuccessfulTriggeringActionIDIfNotSet( pActionID );
404 + }
405 + }
406 +
407 + protected void checkForChanges( AMDconverterPair pChangingPair, Serializable pNewValue, String pResolvedError ) {
408 + // Snag a list to avoid Concurrent Changes
409 + InstanceHelpersSnapShot zSnapShot = mInstanceHelperManager.getInstanceHelpers();
410 + InstanceHelper zRootHelper = zSnapShot.getRootInstanceHelper();
411 + zRootHelper.checkForChanges( pChangingPair, pNewValue, pResolvedError );
412 + for ( InstanceHelper helper : zSnapShot.getAllInstanceHelpers() ) {
413 + if ( helper != zRootHelper ) {
414 + helper.checkForChanges( pChangingPair, pNewValue, pResolvedError );
415 + }
416 + }
417 + }
418 +
419 + public boolean actionRequest( FormDataRowKey pFormDataRowKey, String pActionID, boolean pInputAction, FormDataRowKey pParentFormDataRowKey ) {
420 + if ( UiFormDef.ACTION_CLOSE.equals( pActionID ) ) {
421 + return actionClose( pActionID );
422 + }
423 + if ( UiFormDef.ACTION_DONE.equals( pActionID ) ) {
424 + return actionDone( pActionID );
425 + }
426 + if ( UiFormDef.ACTION_COMMIT.equals( pActionID ) ) {
427 + return actionCommit( pActionID );
428 + }
429 + if ( UiFormDef.ACTION_RELOAD.equals( pActionID ) ) {
430 + return actionReload( pActionID );
431 + }
432 + if ( UiFormDef.ACTION_NEW.equals( pActionID ) ) {
433 + return actionNew( pActionID );
434 + }
435 + InstanceHelper zInstanceHelper = getInstanceHelper( pFormDataRowKey );
436 + if ( zInstanceHelper != null ) {
437 + return zInstanceHelper.actionRequest( pActionID, pInputAction );
438 + }
439 + TypeHelper zTypeHelper = getTypeHelper( pFormDataRowKey );
440 + return (zTypeHelper != null) && //
441 + zTypeHelper.actionRequest( pActionID, pInputAction, getInstanceHelper( pParentFormDataRowKey ) );
442 + }
443 +
444 + public ArrayList<FormDataRowKey> getAllCurrentFormDataRowKeys() {
445 + return mInstanceHelperManager.getAllCurrentFormDataRowKeys();
446 + }
447 +
448 + public InstanceHelper getInstanceHelper( FormDataRowKey pFormDataRowKey ) {
449 + return mInstanceHelperManager.getInstanceHelper( pFormDataRowKey ); // null == Root
450 + }
451 +
452 + private TypeHelper getTypeHelper( FormDataRowKey pFormDataRowKey ) {
453 + return mTypeHelperManager.getTypeHelper( pFormDataRowKey ); // null == root
454 + }
455 +
456 + /**
457 + * @return true to indicate processing satisfied
458 + */
459 + protected boolean actionClose( String pSuccessfulTriggeringActionID ) {
460 + setCloseRequested();
461 + return true;
462 + }
463 +
464 + /**
465 + * Abandon any existing Root Object and create a new one
466 + *
467 + * @return true to indicate processing satisfied
468 + */
469 + protected boolean actionNew( String pSuccessfulTriggeringActionID ) {
470 + createNewRootObject();
471 + return initializeUpdates( pSuccessfulTriggeringActionID );
472 + }
473 +
474 + /**
475 + * Save current (mutated?) state of our backing Root Object and if successful
476 + * prepare the Root Object for future editing.
477 + *
478 + * @return true to indicate processing satisfied
479 + */
480 + protected boolean actionCommit( String pSuccessfulTriggeringActionID ) {
481 + commit();
482 + return hasErrors() || initializeUpdates( pSuccessfulTriggeringActionID );
483 + }
484 +
485 + /**
486 + * Save current (mutated?) state of our backing Root Object and if successful
487 + * request Close, and just in case Form is not closed then
488 + * prepare the Root Object for future editing.
489 + *
490 + * @return true to indicate processing satisfied
491 + */
492 + protected boolean actionDone( String pSuccessfulTriggeringActionID ) {
493 + commit();
494 + if ( hasErrors() ) {
495 + return true;
496 + }
497 + setCloseRequested();
498 + return initializeUpdates( pSuccessfulTriggeringActionID );
499 + }
500 +
501 + /**
502 + * Refresh the current Root Object with the latest version from its source (eg database)
503 + * (or a fresh new one if it was new and never committed)
504 + *
505 + * @return true to indicate processing satisfied
506 + */
507 + public boolean actionReload( String pSuccessfulTriggeringActionID ) {
508 + if ( !hasRootObject() ) {
509 + return true;
510 + }
511 + if ( mIsNewRootObject ) {
512 + createNewRootObject();
513 + } else {
514 + reloadExistingRootObject();
515 + }
516 + return initializeUpdates( pSuccessfulTriggeringActionID );
517 + }
518 +
519 + protected boolean initializeUpdates( String pSuccessfulTriggeringActionID ) {
520 + if ( hasRootObject() ) {
521 + setFullUpdate();
522 + setSuccessfulTriggeringActionIDIfNotSet( pSuccessfulTriggeringActionID );
523 + mInstanceHelperManager.resetAllInstanceHelpers();
524 + mInstanceHelperManager.loadAllAttributeValues();
525 + }
526 + return true;
527 + }
528 +
529 + protected void commit() {
530 + if ( hasRootObject() ) {
531 + try {
532 + LLcommit(); // commit what we've got
533 + }
534 + catch ( ConcurrentModificationException e ) {
535 + addError( ERR_COMMIT_OUT_OF_DATE_DATA );
536 + return;
537 + }
538 + catch ( RuntimeException e ) {
539 + LOGGER.warn.log( e, "Attempt to commit backing Root Object failed" );
540 + if ( e instanceof DisplayableException ) {
541 + DisplayableException zDE = (DisplayableException) e;
542 + String zParam = rootTypeResolveError( zDE.getToResolveIdentifier(), //
543 + (Object[]) zDE.getParams() );
544 + addError( ERR_COMMIT_FAILED, zParam );
545 + } else {
546 + addError( ERR_COMMIT_FAILED );
547 + }
548 + return;
549 + }
550 + rootObjectCommited();
551 + }
552 + }
553 +
554 + protected void createNewRootObject() {
555 + mIsNewRootObject = true;
556 + String zRootObjectKey = LLnewRootObject();
557 + setRootObjectKey( zRootObjectKey );
558 + }
559 +
560 + protected void reloadExistingRootObject() {
561 + mIsNewRootObject = false;
562 + LLreloadExistingRootObject();
563 + mInteractionHelper.clearUpdatedData();
564 + }
565 +
566 + protected void loadExistingRootObject( String pNewRootObjectKey ) {
567 + mIsNewRootObject = false;
568 + if ( LLloadExistingRootObject( pNewRootObjectKey ) ) {
569 + setRootObjectKey( pNewRootObjectKey );
570 + }
571 + }
572 +
573 + /**
574 + * Either load the appropriate Root Object based on pKey, or create one if pKey was null
575 + */
576 + protected void LLsetRootObjectTo( String pKey ) {
577 + if ( pKey == null ) {
578 + createNewRootObject();
579 + } else {
580 + loadExistingRootObject( pKey );
581 + }
582 + }
583 +
584 + protected void LLdispose() {
585 + }
586 +
587 + /**
588 + * @return true to indicate processing satisfied
589 + */
590 + protected boolean LLrawValueUpdated( FormDataRowKey pFormDataRowKey, String pAttributeReference, Serializable pNewValue ) {
591 + return false;
592 + }
593 +
594 + protected void initializationPayloadAvailable( Serializable pInitializationPayload ) {
595 + }
596 +
597 + protected ExternalizationInterface augment( ExternalizationInterface pExternalizationInterface ) {
598 + return pExternalizationInterface;
599 + }
600 +
601 + protected InterceptingProxyExternalization proxy( ExternalizationInterface pExternalizationInterface ) {
602 + return new InterceptingProxyExternalization( pExternalizationInterface );
603 + }
604 +
605 + protected Serializable getFormRenderedServicePeerXtra() {
606 + return null;
607 + }
608 +
609 + abstract protected void LLcommit();
610 +
611 + abstract protected boolean hasRootObject();
612 +
613 + /**
614 + * @return new Root Objects Key
615 + */
616 + abstract protected String LLnewRootObject();
617 +
618 + /**
619 + * @return true if succeeded
620 + */
621 + abstract protected boolean LLreloadExistingRootObject();
622 +
623 + /**
624 + * @return true if succeeded
625 + */
626 + abstract protected boolean LLloadExistingRootObject( String pNewRootObjectKey );
627 + }