//
// ERXNavigationMenuItem.java: Class file for WO Component 'ERXNavigationMenuItem'
// Project ERExtensions
//
// Created by max on Wed Oct 30 2002
//
package er.extensions.appserver.navigation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webobjects.appserver.WOComponent;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WORedirect;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSMutableDictionary;
import er.extensions.appserver.ERXDirectAction;
import er.extensions.appserver.ERXRequest;
import er.extensions.components.ERXStatelessComponent;
import er.extensions.foundation.ERXProperties;
import er.extensions.foundation.ERXStringUtilities;
import er.extensions.foundation.ERXValueUtilities;
import er.extensions.localization.ERXLocalizer;
/** Please read "Documentation/Navigation.html" to fnd out how to use the navigation components.*/
public class ERXNavigationMenuItem extends ERXStatelessComponent {
/**
* Do I need to update serialVersionUID?
* See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the
* <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a>
*/
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(ERXNavigationMenuItem.class);
protected ERXNavigationItem _navigationItem;
protected ERXNavigationState _navigationState;
protected boolean _linkDirectlyToDirectActions = true;
protected int _level=-1;
protected Boolean _isDisabled;
protected Boolean _meetsDisplayConditions;
protected Boolean _isSelected;
protected Boolean _hasActivity;
protected Boolean _omitLabelSpanTag;
protected WOComponent _redirect;
public ERXNavigationMenuItem(WOContext context) {
super(context);
}
public String navigationItemWidth() {
if(navigationItem().width() > 0) {
return "" + navigationItem().width();
}
return null;
}
public String navigationItemID() {
if(navigationItem().uniqueID() != null) {
return navigationItem().uniqueID();
}
return null;
}
@Override
public void reset() {
_navigationItem = null;
_navigationState = null;
_meetsDisplayConditions=null;
_level=-1;
_hasActivity=null;
_isDisabled=null;
_isSelected=null;
_omitLabelSpanTag=null;
super.reset();
}
public ERXNavigationState navigationState() {
if (_navigationState == null)
_navigationState = ERXNavigationManager.manager().navigationStateForSession(session());
return _navigationState;
}
/** AK This is only an experiment: when calling up a DA, we use a component action and redirect to the actual DA */
public WOComponent directActionRedirect() {
WOComponent page = pageWithName("WORedirect");
String url = context().directActionURLForActionNamed(navigationItem().directActionName(), navigationItem().queryBindings());
((WORedirect)page).setUrl(url);
return page;
}
public String contextComponentActionURL() {
String url = null;
// If the navigation should be disabled return null
if (navigationState().isDisabled() || meetsDisplayConditions() == false) {
return null;
}
// hrefs take precedence over actions.
if (navigationItem().href() != null && !"".equals(navigationItem().href().trim())) {
url = navigationItem().href();
}
// If the user specified an action or pageName, return the source URL
if (url == null && (navigationItem().action() != null) || (navigationItem().pageName() != null)) {
// Return the URL to the action or page placed in the context by invokeAction
url = context().componentActionURL();
}
if (url == null && navigationItem().directActionName() != null) {
if(_linkDirectlyToDirectActions) {
NSMutableDictionary bindings = navigationItem().queryBindings().mutableClone();
bindings.setObjectForKey(context().contextID(), "__cid");
url = context().directActionURLForActionNamed(navigationItem().directActionName(), bindings, ERXRequest.isRequestSecure(context().request()), false);
} else {
url = context().componentActionURL();
}
}
// If the user specified some javascript, put that into the HREF and return it
if (url == null && canGetValueForBinding("javascriptFunction")) {
// Make sure there are no extra quotations marks - replace them with apostrophes
String theFunction = (String)valueForBinding("javascriptFunction");
url = StringUtils.replace(theFunction, "\"", "'");
}
// force parent hierarchy to be computed, required for full state to be computed
children();
// store navigation state for this item
ERXNavigationManager.manager().storeInNavigationMap(context().session(), navigationItem(), url);
return url;
}
public WOComponent menuItemSelected() {
WOComponent anActionResult = null;
if (!ERXStringUtilities.stringIsNullOrEmpty(navigationItem().action())) {
anActionResult = (WOComponent)valueForKeyPath(navigationItem().action());
} else if (!ERXStringUtilities.stringIsNullOrEmpty(navigationItem().pageName())) {
anActionResult = pageWithName(navigationItem().pageName());
} else if (!ERXStringUtilities.stringIsNullOrEmpty(navigationItem().directActionName())) {
// FIXME: Need to support directAction classes
if(_linkDirectlyToDirectActions) {
ERXDirectAction da = new ERXDirectAction(context().request());
anActionResult = (WOComponent)(da.performActionNamed(navigationItem().directActionName()));
} else {
anActionResult = (WOComponent)valueForKeyPath("directActionRedirect");
}
}
return anActionResult;
}
public boolean meetsDisplayConditions() {
if (_meetsDisplayConditions == null) {
if(navigationItem() != null) {
_meetsDisplayConditions = navigationItem().meetsDisplayConditionsInComponent(this) ? Boolean.TRUE : Boolean.FALSE;
} else {
_meetsDisplayConditions = Boolean.FALSE;
}
}
return _meetsDisplayConditions.booleanValue();
}
public ERXNavigationItem navigationItem() {
if (_navigationItem==null) {
_navigationItem = (ERXNavigationItem)valueForBinding("navigationItem");
if(_navigationItem == null) {
String name = (String)valueForBinding("navigationItemName");
if(name != null) {
_navigationItem = ERXNavigationManager.manager().navigationItemForName(name);
} else {
log.warn("Navigation unset: {}", name);
_navigationItem = ERXNavigationManager.manager().newNavigationItem(new NSDictionary(name, "name"));
}
}
}
return _navigationItem;
}
public boolean isDisabled() {
if (_isDisabled == null) {
_isDisabled=navigationState().isDisabled() || !meetsDisplayConditions() ? Boolean.TRUE : Boolean.FALSE;
}
return _isDisabled.booleanValue();
}
public boolean isSelected() {
if (_isSelected == null) {
NSArray navigationState = navigationState().state();
_isSelected=!isDisabled() && navigationState != null && navigationState.containsObject(navigationItem().name()) ? Boolean.TRUE : Boolean.FALSE;
}
return _isSelected.booleanValue();
}
public int level() {
if (_level==-1) {
Integer l=(Integer)valueForBinding("level");
_level=l!=null ? l.intValue() : 0;
}
return _level;
}
public String linkClass() {
if(level() == 0) {
return "";
}
return "Nav" + level() + (isSelected() ? "Selected" : (isDisabled() ? "Disabled" : ""));
}
private final static String[] COLOR=new String[] { "", "#EEEEEE", "#111111", "#EEEEEE", "#111111" };
private final static String[] TD_BGCOLOR=new String[] { "", "#003366", "#d0d0d0", "#ff6600", "#ff6600" };
private final static String[] DISABLED_TD_BGCOLOR=new String[] { "", "#003366", "#EFEFEF", "#ff9966", "#ff9966" };
public String tdColor() {
return !isDisabled() ? TD_BGCOLOR[level()+(isSelected()? 1 : 0)] : DISABLED_TD_BGCOLOR[level()];
}
public Object resolveValue(String key) {
if(key != null && key.startsWith("^")) {
return valueForKeyPath(key.substring(1));
}
return key;
}
public boolean hasActivity() {
if (_hasActivity == null)
_hasActivity = ERXValueUtilities.booleanValue(resolveValue(navigationItem().hasActivity())) ?
Boolean.TRUE : Boolean.FALSE;
return _hasActivity.booleanValue();
}
public boolean hasActivityAndIsEnabled(){
return hasActivity() && !isDisabled();
}
public String displayName() {
String name = (String) resolveValue(navigationItem().displayName());
if(name != null) {
if(ERXProperties.booleanForKeyWithDefault("er.extensions.ERXNavigationManager.localizeDisplayKeys", false)) {
String localizerKey = "Nav." + name;
String localizedValue = ERXLocalizer.currentLocalizer().localizedStringForKey(localizerKey);
if(localizedValue == null) {
localizedValue = ERXLocalizer.currentLocalizer().localizedStringForKey(name);
if(localizedValue != null) {
log.info("Found old-style entry: {}->{}", localizerKey, localizedValue);
ERXLocalizer.currentLocalizer().takeValueForKey(localizedValue, localizerKey);
name = localizedValue;
}
} else {
name = localizedValue;
}
}
}
return name;
}
public boolean omitLabelSpanTag() {
if (_omitLabelSpanTag == null) {
_omitLabelSpanTag = Boolean.valueOf(!ERXProperties.booleanForKeyWithDefault("er.extensions.ERXNavigationManager.includeLabelSpanTag", false));
}
return _omitLabelSpanTag;
}
public NSArray children() {
return navigationItem().childItemsInContext(this);
}
}