package er.extensions.appserver; import org.apache.commons.lang3.builder.ToStringBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.webobjects.appserver.WOActionResults; import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WOContext; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.eocontrol.EOGlobalID; import com.webobjects.foundation.NSMutableDictionary; import er.extensions.eof.ERXEC; /** * A useful general purpose nextPage delegate that can be configured and passed into a {@link CCAjaxLongResponsePage} for handling a result * and returning the nextPage. * * A result key can be provided for passing the successful result into the next page. * * Note that if the result is a {@link EOGlobalID}, since only a crazy person would return an EOEnterpriseObject * from a background thread, then a new editing context is automatically created and * the global ID is converted to an EOEnterpriseObject. The EOEnterpriseObject is in then passed into the next * page via the nextPageResultKey. * * If a specific nextPage WOComponent is not set, the original page in which this controller was instantiated * will be returned by default. * * Since everyone implements their own error handling, you may want to make your own version of this that checks for * a result that is instanceof Throwable in {@link #performAction()} and handles it appropriately since, right now, * error results only logged by this delegate. * * @author kieran */ public class ERXNextPageForResultWOAction extends ERXAbstractPerformWOAction implements IERXPerformWOActionForResult { private static final Logger log = LoggerFactory.getLogger(ERXNextPageForResultWOAction.class); protected Object _result; protected final WOComponent _nextPage; private final String _nextPageResultKey; private NSMutableDictionary<String, ?> _nextPageValues; /** * Convenience constructor that calls {@link #ERXNextPageForResultWOAction(WOComponent, String)} */ public ERXNextPageForResultWOAction() { this(null, null); } /** * Convenience constructor that calls {@link #ERXNextPageForResultWOAction(WOComponent, String)} * * @param nextPage */ public ERXNextPageForResultWOAction(WOComponent nextPage) { this(nextPage, null); } /** * @param nextPage * The page that should be returned by {@link #performAction()}. * Defaults to the page in the {@link WOContext} in which this * class was created. * @param nextPageResultKey * The key in which to set the result in the nextPage */ public ERXNextPageForResultWOAction(WOComponent nextPage, String nextPageResultKey) { // We assume that this class is instantiated in the originating page and so we capture the // current page in context when this class is created and we will use that as the default // nextPage. _nextPage = ( nextPage == null ? ERXWOContext.currentContext().page() : nextPage ); _nextPageResultKey = nextPageResultKey; } /* (non-Javadoc) * @see er.extensions.appserver.IERXPerformWOActionForResult#setResult(java.lang.Object) */ public void setResult(Object result) { _result = result; } @Override public WOActionResults performAction() { log.debug("The result of the task was {}", _result); if (_nextPage != null && _nextPageResultKey != null) { if (_result instanceof EOGlobalID) { // Inflate it to a fault EOEditingContext ec = ERXEC.newEditingContext(); // Let's ensure fresh ec since we are likely coming out of a background task ec.setFetchTimestamp(System.currentTimeMillis()); _result = ec.faultForGlobalID((EOGlobalID) _result, ec); } _nextPage.takeValueForKey(_result, _nextPageResultKey); } if (_nextPage != null && _nextPageValues != null) { for (String key : nextPageValues().allKeys()) { Object value = nextPageValues().valueForKey(key); _nextPage.takeValueForKey(value, key); } } if (_nextPage != null && _nextPage instanceof IERXRefreshPage) { ((IERXRefreshPage)_nextPage).refresh(); } return _nextPage; } /** * * @return a mutable dictionary whose values will be pushed into keys in the destination page that is returned by performAction * * This can be useful for configuring the page that will be returned by this delegate after a long response page task * has completed. * * For example, if you create a key <code>isEditable</code> with a value <code>Boolean.TRUE</code> in this mutable * dictionary, then when performAction is called, the method setIsEditable( Boolean ) will be called with a parameter * of <code>Boolean.TRUE</code> on the destination page before that page is returned. * **/ public NSMutableDictionary<String, ?> nextPageValues() { if ( _nextPageValues == null ) { _nextPageValues = new NSMutableDictionary<>(); } return _nextPageValues; } @Override public String toString() { ToStringBuilder b = new ToStringBuilder(this); b.append("nextPage", _nextPage); b.append("nextPageResultKey", _nextPageResultKey); return b.toString(); } }