/******************************************************************************* * 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.designtime.terminal.analyzer.modules.navigation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openlegacy.EntityDefinition; import org.openlegacy.definitions.ActionDefinition; import org.openlegacy.designtime.terminal.analyzer.ScreenFact; import org.openlegacy.designtime.terminal.analyzer.ScreenFactProcessor; import org.openlegacy.designtime.terminal.model.ScreenEntityDesigntimeDefinition; import org.openlegacy.modules.login.Login.LoginEntity; import org.openlegacy.modules.menu.Menu.MenuEntity; import org.openlegacy.modules.messages.Messages.MessagesEntity; import org.openlegacy.modules.table.RecordSelectionEntity; import org.openlegacy.terminal.TerminalActionMapper; import org.openlegacy.terminal.TerminalField; import org.openlegacy.terminal.TerminalSnapshot; import org.openlegacy.terminal.actions.CombinedTerminalAction; import org.openlegacy.terminal.actions.TerminalAction; import org.openlegacy.terminal.actions.TerminalAction.AdditionalKey; import org.openlegacy.terminal.actions.TerminalActions.ENTER; import org.openlegacy.terminal.definitions.FieldAssignDefinition; import org.openlegacy.terminal.definitions.ScreenEntityDefinition; import org.openlegacy.terminal.definitions.ScreenFieldDefinition; import org.openlegacy.terminal.definitions.ScreenTableDefinition; import org.openlegacy.terminal.definitions.SimpleFieldAssignDefinition; import org.openlegacy.terminal.definitions.SimpleTerminalActionDefinition; import org.openlegacy.terminal.table.TerminalDrilldownAction; import org.openlegacy.terminal.utils.FieldsQuery; import org.openlegacy.terminal.utils.FieldsQuery.FieldsCriteria; import org.openlegacy.utils.StringUtil; import java.text.MessageFormat; import java.util.Collection; import java.util.List; import javax.inject.Inject; /** * Analyze a navigation fact compound of the previous snapshot, and it's definitions * */ public class NavigationFactProcessor implements ScreenFactProcessor { @Inject private TerminalActionMapper terminalActionMapper; private final static Log logger = LogFactory.getLog(NavigationFactProcessor.class); public void process(ScreenEntityDesigntimeDefinition screenEntityDefinition, ScreenFact screenFact) { NavigationFact navigationFact = (NavigationFact)screenFact; ScreenEntityDesigntimeDefinition accessedFromScreenEntityDefinition = navigationFact.getAccessedFromScreenEntityDefinition(); TerminalSnapshot accessedFromSnapshot = navigationFact.getAccessedFromSnapshot(); boolean abort = isAbortNavigationDefinitions(accessedFromScreenEntityDefinition, accessedFromSnapshot, screenEntityDefinition); if (abort) { return; } screenEntityDefinition.setAccessedFromSnapshot(accessedFromSnapshot); screenEntityDefinition.setAccessedFromScreenDefinition(accessedFromScreenEntityDefinition); ScreenNavigationDesignTimeDefinition navigationDefinition = new ScreenNavigationDesignTimeDefinition(); screenEntityDefinition.setNavigationDefinition(navigationDefinition); navigationDefinition.setAccessedFromEntityDefinition(accessedFromScreenEntityDefinition); TerminalAction action = terminalActionMapper.getAction(navigationFact.getAccessedFromSnapshot().getCommand()); if (action instanceof CombinedTerminalAction) { CombinedTerminalAction combinedAction = (CombinedTerminalAction)action; // add action definition only if it's not ENTER (ENTER is the default) if (combinedAction.getTerminalAction() != ENTER.class || combinedAction.getAdditionalKey() != AdditionalKey.NONE) { navigationDefinition.setTerminalAction(action); } } // build assigned fields for menu screens only if (accessedFromScreenEntityDefinition.getType() == MenuEntity.class) { buildAssignedFields(screenEntityDefinition, navigationDefinition, accessedFromScreenEntityDefinition, accessedFromSnapshot); } else if (accessedFromScreenEntityDefinition.getType() == RecordSelectionEntity.class) { List<TerminalField> modifiedFields = FieldsQuery.queryFields(accessedFromSnapshot, FieldsQuery.ModifiedFieldsCriteria.instance()); if (modifiedFields.size() > 0) { // pick the 1st modified field value for record selection String modifiedValue = modifiedFields.get(0).getValue(); if (!StringUtil.isEmpty(modifiedValue)) { navigationDefinition.setDrilldownValue(modifiedValue); navigationDefinition.setRequiresParameters(true); // find the table action which matches the modified value, and set current screen definition as the target // entity fot the table action if (accessedFromScreenEntityDefinition.getTableDefinitions().size() == 1) { ScreenTableDefinition tableDefinition = accessedFromScreenEntityDefinition.getTableDefinitions().values().iterator().next(); List<ActionDefinition> tableActions = tableDefinition.getActions(); for (ActionDefinition actionDefinition : tableActions) { if (actionDefinition.getAction() instanceof TerminalDrilldownAction) { TerminalDrilldownAction drilldownAction = (TerminalDrilldownAction)actionDefinition.getAction(); if (modifiedValue.equals(drilldownAction.getActionValue())) { SimpleTerminalActionDefinition terminalActionDefinition = (SimpleTerminalActionDefinition)actionDefinition; terminalActionDefinition.setTargetEntityDefinition(screenEntityDefinition); } } } } } } } // add assign fields when setting cursor is set on editable field if (accessedFromSnapshot.getCursorPosition() != null) { TerminalField terminalField = accessedFromSnapshot.getField(accessedFromSnapshot.getCursorPosition()); if (terminalField != null && terminalField.isEditable()) { ScreenFieldDefinition fieldDefinition = getFieldDefinitionByPosition(accessedFromScreenEntityDefinition, terminalField); if (fieldDefinition != null) { FieldAssignDefinition assignCursorFieldDefinition = new SimpleFieldAssignDefinition( fieldDefinition.getName(), null); List<FieldAssignDefinition> assignedFields = navigationDefinition.getAssignedFields(); // don't assign cursor if only 1 field exists and it has value if (assignedFields.size() == 1) { if (!assignedFields.get(0).getName().equals(assignCursorFieldDefinition.getName())) { assignedFields.add(assignCursorFieldDefinition); } } else { assignedFields.add(assignCursorFieldDefinition); } } } } } private static boolean isAbortNavigationDefinitions( EntityDefinition<ScreenFieldDefinition> accessedFromScreenEntityDefinition, TerminalSnapshot accessedFromSnapshot, EntityDefinition<ScreenFieldDefinition> screenEntityDefinition) { // do not define navigation from login screen for example if (accessedFromScreenEntityDefinition.getType() == LoginEntity.class) { logger.info(MessageFormat.format("Not adding navigation step for {0} .Accessed from login screen", screenEntityDefinition.getEntityName())); return true; } if (accessedFromScreenEntityDefinition.getType() == MessagesEntity.class) { logger.info(MessageFormat.format("Not adding navigation step for {0} .Accessed from snapshot a messages screen {1}", screenEntityDefinition.getEntityName(), accessedFromScreenEntityDefinition.getEntityName())); return true; } if (abortWhenHasPasswordFields(accessedFromSnapshot)) { logger.info(MessageFormat.format("Not adding navigation step for {0} .Accessed from snapshot has password field", screenEntityDefinition.getEntityName())); return true; } return false; } private static boolean abortWhenHasPasswordFields(TerminalSnapshot accessedFromSnapshot) { List<TerminalField> passwordFields = FieldsQuery.queryFields(accessedFromSnapshot, new FieldsCriteria() { public boolean match(TerminalField terminalField) { return terminalField.isPassword(); } }); if (passwordFields.size() > 0) { return true; } return false; } private static void buildAssignedFields(ScreenEntityDesigntimeDefinition screenEntityDefinition, ScreenNavigationDesignTimeDefinition navigationDefinition, ScreenEntityDesigntimeDefinition accessedFromScreenEntityDefinition, TerminalSnapshot accessedFromSnapshot) { List<TerminalField> modifiedFields = FieldsQuery.queryFields(accessedFromSnapshot, FieldsQuery.ModifiedFieldsCriteria.instance()); for (TerminalField terminalField : modifiedFields) { // look for field name on the access-from entity definition ScreenFieldDefinition fieldDefinition = getFieldDefinitionByPosition(accessedFromScreenEntityDefinition, terminalField); if (fieldDefinition == null) { logger.warn(MessageFormat.format( "Field {0} was modified, and wasn''t found on screen definition {1}. Required for declaring screen navigation for {2}", terminalField, accessedFromScreenEntityDefinition.getEntityName(), screenEntityDefinition.getEntityName())); // clear the assigned fields to avoid problematic navigation by the generated code navigationDefinition.getAssignedFields().clear(); continue; } FieldAssignDefinition assignFieldDefinition = new SimpleFieldAssignDefinition(fieldDefinition.getName(), terminalField.getValue()); navigationDefinition.getAssignedFields().add(assignFieldDefinition); } } private static ScreenFieldDefinition getFieldDefinitionByPosition(ScreenEntityDefinition accessedFromScreenEntityDefinition, TerminalField terminalField) { Collection<ScreenFieldDefinition> fieldDefinitions = accessedFromScreenEntityDefinition.getFieldsDefinitions().values(); for (ScreenFieldDefinition screenFieldDefinition : fieldDefinitions) { if (screenFieldDefinition.getPosition().equals(terminalField.getPosition())) { return screenFieldDefinition; } } return null; } public boolean accept(ScreenFact screenFact) { return (screenFact instanceof NavigationFact); } }