/******************************************************************************* * Copyright (c) 2012 OpenLegacy Inc. * 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: * OpenLegacy Inc. - initial API and implementation *******************************************************************************/ package org.openlegacy.terminal.support.navigation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openlegacy.modules.navigation.Navigation; import org.openlegacy.modules.table.Table; import org.openlegacy.modules.table.drilldown.DrilldownAction; import org.openlegacy.terminal.ScreenEntity; import org.openlegacy.terminal.ScreenPojoFieldAccessor; import org.openlegacy.terminal.TerminalSession; import org.openlegacy.terminal.actions.TerminalAction; import org.openlegacy.terminal.definitions.FieldAssignDefinition; import org.openlegacy.terminal.definitions.NavigationDefinition; import org.openlegacy.terminal.definitions.ScreenEntityDefinition; import org.openlegacy.terminal.exceptions.ScreenEntityNotAccessibleException; import org.openlegacy.terminal.services.ScreenEntitiesRegistry; import org.openlegacy.terminal.services.SessionNavigator; import org.openlegacy.terminal.table.TerminalDrilldownAction; import org.openlegacy.terminal.utils.ScreenEntityUtils; import org.openlegacy.terminal.utils.ScreenNavigationUtil; import org.openlegacy.terminal.utils.SimpleScreenPojoFieldAccessor; import org.openlegacy.utils.ProxyUtil; import java.io.Serializable; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.inject.Inject; public class DefaultSessionNavigator implements SessionNavigator, Serializable { private static final long serialVersionUID = 1L; @Inject private ScreenEntitiesRegistry screenEntitiesRegistry; @Inject private NavigationMetadata navigationMetadata; @Inject private ScreenEntityUtils screenEntityUtils; private final static Log logger = LogFactory.getLog(DefaultSessionNavigator.class); public void navigate(TerminalSession terminalSession, Class<?> targetScreenEntityClass, Object... keys) throws ScreenEntityNotAccessibleException { ScreenEntity currentEntity = terminalSession.getEntity(); if (currentEntity == null) { return; } if (screenEntityUtils.isEntitiesEquals(currentEntity, targetScreenEntityClass, keys)) { return; } Class<?> currentEntityClass = currentEntity.getClass(); ScreenEntityDefinition currentEntityDefinition = screenEntitiesRegistry.get(currentEntityClass); ScreenEntityDefinition targetEntityDefinition = screenEntitiesRegistry.get(targetScreenEntityClass); List<NavigationDefinition> navigationSteps = navigationMetadata.get(currentEntityDefinition, targetEntityDefinition); while (navigationSteps == null) { if (screenEntityUtils.isEntitiesEquals(currentEntity, targetScreenEntityClass, keys)) { return; } navigationSteps = findDirectNavigationPath(currentEntityDefinition, targetEntityDefinition); if (navigationSteps == null) { NavigationDefinition currentScreenNavigationDefinition = currentEntityDefinition.getNavigationDefinition(); TerminalAction defaultExitAction = terminalSession.getModule(Navigation.class).getDefaultExitAction(); TerminalAction exitAction; if (currentScreenNavigationDefinition != null) { exitAction = currentScreenNavigationDefinition.getExitAction(); } else { exitAction = defaultExitAction; if (logger.isDebugEnabled()) { logger.debug(MessageFormat.format("Using default exit action {0} to step back of screen {1}", exitAction, currentEntityClass)); } } Class<?> beforeEntityClass = currentEntityClass; exitCurrentScreen(terminalSession, currentEntityClass, exitAction); currentEntity = terminalSession.getEntity(); currentEntityClass = currentEntity.getClass(); currentEntityDefinition = screenEntitiesRegistry.get(currentEntityClass); if (ProxyUtil.isClassesMatch(beforeEntityClass, currentEntityClass)) { logger.error(MessageFormat.format( "Exiting from screen {0} using {1} was not effective. Existing navigation attempt to {2}", currentEntityClass, exitAction, targetScreenEntityClass)); ScreenNavigationUtil.validateCurrentScreen(targetScreenEntityClass, currentEntityClass); break; } } } if (navigationSteps != null) { navigationMetadata.add(currentEntityDefinition, targetEntityDefinition, navigationSteps); performDirectNavigation(terminalSession, currentEntityClass, navigationSteps, keys); } } private static void exitCurrentScreen(TerminalSession terminalSession, Class<?> currentEntityClass, TerminalAction exitAction) { if (logger.isDebugEnabled()) { logger.debug(MessageFormat.format("Steping back of screen {0} using {1}", currentEntityClass, exitAction)); } terminalSession.doAction(exitAction); } private static void performDirectNavigation(TerminalSession terminalSession, Class<?> currentEntityClass, List<NavigationDefinition> navigationSteps, Object... keys) { Collections.reverse(navigationSteps); ScreenEntity currentEntity = terminalSession.getEntity(); for (NavigationDefinition navigationDefinition : navigationSteps) { ScreenPojoFieldAccessor fieldAccessor = new SimpleScreenPojoFieldAccessor(currentEntity); List<FieldAssignDefinition> assignedFields = navigationDefinition.getAssignedFields(); if (logger.isDebugEnabled()) { currentEntityClass = ProxyUtil.getOriginalClass(currentEntity.getClass()); logger.debug("Performing navigation actions from screen " + currentEntityClass); } for (FieldAssignDefinition fieldAssignDefinition : assignedFields) { String value = fieldAssignDefinition.getValue(); if (value != null) { fieldAccessor.setFieldValue(fieldAssignDefinition.getName(), value); } fieldAccessor.setFocusField(fieldAssignDefinition.getName()); } if (assignedFields.size() == 0) { currentEntity = null; } TerminalAction terminalAction = navigationDefinition.getTerminalAction(); if (terminalAction instanceof DrilldownAction) { terminalSession.getModule(Table.class).drillDown(navigationDefinition.getTargetEntity(), (TerminalDrilldownAction)terminalAction, keys); } else { terminalSession.doAction(terminalAction, currentEntity); } currentEntity = terminalSession.getEntity(); } } /** * Look for a direct path from the target screen back to the current screen */ private List<NavigationDefinition> findDirectNavigationPath(ScreenEntityDefinition sourceEntityDefinition, ScreenEntityDefinition targetEntityDefinition) { Class<?> currentNavigationNode = targetEntityDefinition.getEntityClass(); NavigationDefinition navigationDefinition = targetEntityDefinition.getNavigationDefinition(); if (navigationDefinition == null) { return null; } List<NavigationDefinition> navigationSteps = new ArrayList<NavigationDefinition>(); navigationSteps.add(navigationDefinition); while (currentNavigationNode != null) { currentNavigationNode = navigationDefinition.getAccessedFrom(); ScreenEntityDefinition screenEntityDefinition = screenEntitiesRegistry.get(currentNavigationNode); navigationDefinition = screenEntityDefinition.getNavigationDefinition(); if (screenEntityDefinition.getEntityClass() == sourceEntityDefinition.getEntityClass()) { // target reached break; } // no navigation definition found, exit if (navigationDefinition == null) { return null; } navigationSteps.add(navigationDefinition); } if (currentNavigationNode != null) { return navigationSteps; } return null; } }