/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.internal.navigation.ui.swt.handlers;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.ui.AbstractSourceProvider;
import org.eclipse.riena.core.util.ObjectUtils;
import org.eclipse.riena.navigation.ApplicationNodeManager;
import org.eclipse.riena.navigation.IApplicationNode;
import org.eclipse.riena.navigation.IModuleGroupNode;
import org.eclipse.riena.navigation.IModuleNode;
import org.eclipse.riena.navigation.INavigationNode;
import org.eclipse.riena.navigation.ISubApplicationNode;
import org.eclipse.riena.navigation.ISubModuleNode;
import org.eclipse.riena.navigation.model.NavigationModelFailure;
/**
* This class provides information about the active navigation node for updating the menus.
*/
public class NavigationSourceProvider extends AbstractSourceProvider {
private boolean isDisposed;
private Map<String, Object> lastState;
private static final String ACTIVE_SUB_APPLICATION_NODE = "activeSubApplicationNode"; //$NON-NLS-1$
private static final String ACTIVE_SUB_APPLICATION_NODE_ID = ACTIVE_SUB_APPLICATION_NODE + "Id"; //$NON-NLS-1$
private static final String ACTIVE_MODULE_GROUP_NODE = "activeModuleGroupNode"; //$NON-NLS-1$
private static final String ACTIVE_MODULE_GROUP_NODE_ID = ACTIVE_MODULE_GROUP_NODE + "Id"; //$NON-NLS-1$
private static final String ACTIVE_MODULE_NODE = "activeModuleNode"; //$NON-NLS-1$
private static final String ACTIVE_MODULE_NODE_ID = ACTIVE_MODULE_NODE + "Id"; //$NON-NLS-1$
private static final String ACTIVE_SUB_MODULE_NODE = "activeSubModuleNode"; //$NON-NLS-1$
private static final String ACTIVE_SUB_MODULE_NODE_ID = ACTIVE_SUB_MODULE_NODE + "Id"; //$NON-NLS-1$
private static final int EVENT_PRIORITY = 1 << 28;
private static final String[] PROVIDED_SOURCE_NAMES = new String[] { ACTIVE_SUB_APPLICATION_NODE_ID, ACTIVE_MODULE_GROUP_NODE_ID, ACTIVE_MODULE_NODE_ID,
ACTIVE_SUB_MODULE_NODE_ID, ACTIVE_MODULE_NODE };
public void dispose() {
isDisposed = true;
}
public boolean isDisposed() {
return isDisposed;
}
public final Map<String, Object> getCurrentState() {
final Map<String, Object> state = new HashMap<String, Object>();
final ISubApplicationNode subAppNode = ApplicationNodeManager.locateActiveSubApplicationNode();
final IModuleGroupNode moduleGroupNode = ApplicationNodeManager.locateActiveModuleGroupNode();
final IModuleNode moduleNode = ApplicationNodeManager.locateActiveModuleNode();
final ISubModuleNode subModuleNode = ApplicationNodeManager.locateActiveSubModuleNode();
state.put(ACTIVE_SUB_APPLICATION_NODE_ID, getTypeNodeId(subAppNode));
state.put(ACTIVE_MODULE_GROUP_NODE_ID, getTypeNodeId(moduleGroupNode));
state.put(ACTIVE_MODULE_NODE_ID, getTypeNodeId(moduleNode));
state.put(ACTIVE_SUB_MODULE_NODE_ID, getTypeNodeId(subModuleNode));
state.put(ACTIVE_SUB_APPLICATION_NODE, subAppNode);
state.put(ACTIVE_MODULE_GROUP_NODE, moduleGroupNode);
state.put(ACTIVE_MODULE_NODE, moduleNode);
state.put(ACTIVE_SUB_MODULE_NODE, subModuleNode);
return state;
}
public String[] getProvidedSourceNames() {
return PROVIDED_SOURCE_NAMES;
}
private void fireSourceChange(final INavigationNode<?> node) {
final String variable = getVariableNameForNode(node);
final String nodeId = getTypeNodeId(node);
if (changed(variable + "Id", nodeId)) { //$NON-NLS-1$
fireSourceChanged(EVENT_PRIORITY, variable + "Id", getTypeNodeId(node)); //$NON-NLS-1$
}
if (changed(variable, node)) {
fireSourceChanged(EVENT_PRIORITY, variable, node);
}
}
/**
* Returns the type ID of the given node. An empty string is returned if the node has no ID.
*
* @param node
* navigation node
* @return type ID of the given node
*/
private String getTypeNodeId(final INavigationNode<?> node) {
if (node != null && node.getNodeId() != null) {
return node.getNodeId().getTypeId();
} else {
return ""; //$NON-NLS-1$
}
}
private String getVariableNameForNode(final INavigationNode<?> node) {
if (node == null) {
return null;
}
if (node instanceof ISubApplicationNode) {
return ACTIVE_SUB_APPLICATION_NODE;
} else if (node instanceof IModuleGroupNode) {
return ACTIVE_MODULE_GROUP_NODE;
} else if (node instanceof IModuleNode) {
return ACTIVE_MODULE_NODE;
} else if (node instanceof ISubModuleNode) {
return ACTIVE_SUB_MODULE_NODE;
}
throw new NavigationModelFailure("Unsupported instance of INavigationNode: " + node); //$NON-NLS-1$
}
/**
* This method should be called if a node was activated so that the value of the source can be updated.
* <p>
* Also the sources of all parent nodes are updated.
*
* @param node
* node that was activated right now
*/
public void activeNodeChanged(final INavigationNode<?> node) {
activeNodesChanged(node);
lastState = new HashMap<String, Object>(getCurrentState());
}
private void activeNodesChanged(final INavigationNode<?> node) {
fireSourceChange(node);
if (node.getParent() != null && !(node.getParent() instanceof IApplicationNode)) {
activeNodeChanged(node.getParent());
}
}
private boolean changed(final String key, final Object value) {
if (lastState == null || lastState.isEmpty()) {
return true;
}
final Object lastValue = lastState.get(key);
return !ObjectUtils.equals(lastValue, value);
}
}