package er.directtoweb.assignments.delayed; import org.apache.log4j.Logger; import com.webobjects.appserver.WOSession; import com.webobjects.directtoweb.D2WContext; import com.webobjects.eocontrol.EOKeyValueUnarchiver; import er.extensions.appserver.navigation.ERXNavigationItem; import er.extensions.appserver.navigation.ERXNavigationManager; /** * When using ERXNavigationMenu, this automatically sets the current navigation * state via a low priority rule. If the user clicked a link in the navigation * menu, the URL can be reliably matched via a dictionary of navigation states * and URLs. When another link was clicked (e.g. "Find" on a query page, * "Cancel" while editing), it looks at the current task and entity name in * order to find a matching navigation item. It assumes your navigation elements * are named according to the following conventions: * <ul> * <li>task=list, entity.name=Movie => 'ListMovie' or 'SearchMovie' * <li>task=query, entity.name=Movie => 'SearchMovie' * </ul> * You may still have to define a rule for the initial navigation state after * login, if it cannot be resolved with the simple conventions above. * <br> * While it should set the vast majority of navigation states correctly, you can * override the default choice via a rule such as: * <pre> * 100 : pageConfiguration = 'ListMovie' => navigationState = "Movies.ListMovie" [com.webobjects.directtoweb.Assignment] * </pre> * * In the same way, you can disable it entirely, e.g. via: * <pre> * 50 : *true* => navigationState = (null) [com.webobjects.directtoweb.Assignment] * </pre> * * @author fpeters */ public class ERDDelayedNavigationStateAssignment extends ERDDelayedAssignment { private static final long serialVersionUID = 1L; /** logging support */ static final Logger log = Logger.getLogger(ERDDelayedNavigationStateAssignment.class); /** * Static constructor required by the EOKeyValueUnarchiver interface. If * this isn't implemented then the default behavior is to construct the * first super class that does implement this method. Very lame. * * @param eokeyvalueunarchiver * to be unarchived * @return decoded assignment of this class */ public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver eokeyvalueunarchiver) { return new ERDDelayedNavigationStateAssignment(eokeyvalueunarchiver); } /** * Public constructor * * @param u * key-value unarchiver used when unarchiving from rule files. */ public ERDDelayedNavigationStateAssignment(EOKeyValueUnarchiver u) { super(u); } /** * Public constructor * * @param key * context key * @param value * of the assignment */ public ERDDelayedNavigationStateAssignment(String key, Object value) { super(key, value); } @Override public Object fireNow(D2WContext c) { String navigationState = ERXNavigationManager.manager().navigationStateFromMap( (WOSession) c.valueForKey("session")); if (navigationState == null) { if (log.isDebugEnabled()) { log.debug("Could not determine navigation state from menu action dictionary. " + "We'll now try to find a matching default."); } if ("list".equals(c.task())) { // we try to set a sensible default for a list page navigationState = "List" + c.entity().name(); ERXNavigationItem item = ERXNavigationManager.manager() .navigationItemForName(navigationState); // ListFoo not defined, let's try SearchFoo if (item == null) { navigationState = "Search" + c.entity().name(); item = ERXNavigationManager.manager().navigationItemForName( navigationState); } if (item != null) { navigationState = item.navigationPath().replace('/', '.'); } } else if ("query".equals(c.task())) { // we try to set a sensible default for a query page navigationState = "Search" + c.entity().name(); ERXNavigationItem item = ERXNavigationManager.manager() .navigationItemForName(navigationState); if (item != null) { navigationState = item.navigationPath().replace('/', '.'); } } } if (log.isDebugEnabled()) { if (navigationState == null) { log.debug("Failed to resolve navigation state for task " + c.task() + " and entity name " + c.entity().name() + "."); } else { log.debug("Resolved navigation state to " + navigationState); } } return navigationState; } }