/******************************************************************************* * 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.binders; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openlegacy.FieldFormatter; import org.openlegacy.terminal.FieldComparator; import org.openlegacy.terminal.ScreenEntity; import org.openlegacy.terminal.ScreenPojoFieldAccessor; import org.openlegacy.terminal.TerminalField; import org.openlegacy.terminal.TerminalPosition; import org.openlegacy.terminal.TerminalRow; import org.openlegacy.terminal.TerminalSendAction; import org.openlegacy.terminal.TerminalSnapshot; import org.openlegacy.terminal.definitions.ScreenFieldDefinition; import org.openlegacy.terminal.exceptions.TerminalActionException; import org.openlegacy.terminal.utils.SimpleScreenPojoFieldAccessor; import org.openlegacy.utils.ProxyUtil; import org.openlegacy.utils.TypesUtil; import org.springframework.stereotype.Component; import java.io.Serializable; import java.text.MessageFormat; import java.util.Collection; import java.util.List; import javax.inject.Inject; @Component public class ScreenBinderLogic implements Serializable { private static final long serialVersionUID = 1L; @Inject private FieldFormatter fieldFormatter; @Inject private FieldComparator fieldComparator; private final static Log logger = LogFactory.getLog(ScreenBinderLogic.class); public void populatedFields(ScreenPojoFieldAccessor fieldAccessor, TerminalSnapshot terminalSnapshot, Collection<ScreenFieldDefinition> fieldMappingDefinitions) { for (ScreenFieldDefinition fieldMappingDefinition : fieldMappingDefinitions) { TerminalPosition position = fieldMappingDefinition.getPosition(); TerminalField terminalField = terminalSnapshot.getField(position); if (terminalField == null) { continue; } String text = getText(fieldMappingDefinition, terminalSnapshot); String fieldName = fieldMappingDefinition.getName(); if (fieldAccessor.isWritable(fieldName)) { Class<?> javaType = fieldMappingDefinition.getJavaType(); if (TypesUtil.isNumberOrString(javaType)) { String content = fieldFormatter.format(text); fieldAccessor.setFieldValue(fieldName, content); } fieldAccessor.setTerminalField(fieldName, terminalField); } TerminalPosition cursorPosition = terminalSnapshot.getCursorPosition(); if (cursorPosition != null && cursorPosition.equals(position)) { fieldAccessor.setFocusField(fieldMappingDefinition.getName()); } } } /** * Grab text from the snapshot according to the field definition Considers multy-line field as rectangle/line breakings * * @param fieldMappingDefinition * @param terminalSnapshot * @return */ private String getText(ScreenFieldDefinition fieldMappingDefinition, TerminalSnapshot terminalSnapshot) { int startRow = fieldMappingDefinition.getPosition().getRow(); int endRow = fieldMappingDefinition.getEndPosition().getRow(); int startColumn = fieldMappingDefinition.getPosition().getColumn(); int endColumn = fieldMappingDefinition.getEndPosition().getColumn(); int fieldColumnLength = (endColumn - startColumn) + 1; if (endRow == 0) { endRow = startRow; } String text = ""; for (int currentRow = startRow; currentRow <= endRow; currentRow++) { TerminalRow row = terminalSnapshot.getRow(currentRow); TerminalField terminalField = null; // multy line if (currentRow > startRow) { String newLine = "\n"; if (fieldMappingDefinition.isRectangle()) { terminalField = terminalSnapshot.getField(currentRow, startColumn); if (fieldMappingDefinition.getLength() > 0 && fieldColumnLength != terminalField.getLength()) { text = text + newLine + fieldFormatter.format(row.getText(startColumn, fieldColumnLength)); } else { text = text + newLine + fieldFormatter.format(terminalField.getValue()); } // breaking lines } else { // 1st row = grab until the end of the row if (currentRow == startRow) { text = text + newLine + fieldFormatter.format(row.getText(startColumn, terminalSnapshot.getSize().getColumns() - fieldColumnLength)); // last row - grab until end column } else if (currentRow == endRow) { text = text + newLine + fieldFormatter.format(row.getText(1, endColumn)); // middle row - grab all line } else { text = text + newLine + fieldFormatter.format(row.getText()); } } // single line } else { terminalField = terminalSnapshot.getField(currentRow, startColumn); if (fieldMappingDefinition.getLength() > 0 && fieldColumnLength != terminalField.getLength()) { text += row.getText(startColumn, fieldColumnLength); } else { text += fieldFormatter.format(terminalField.getValue()); } } } return text; } /** * Convert a pojo to a sendAction modified fields. Main complexity is around breaking multy line fields to single terminal * fields * * @param sendAction * @param terminalSnapshot * @param screenPojo * @param fieldMappingsDefinitions */ public void populateSendAction(TerminalSendAction sendAction, TerminalSnapshot terminalSnapshot, Object screenPojo, Collection<ScreenFieldDefinition> fieldMappingsDefinitions) { ScreenPojoFieldAccessor fieldAccessor = new SimpleScreenPojoFieldAccessor(screenPojo); List<TerminalField> modifiedfields = sendAction.getModifiedFields(); for (ScreenFieldDefinition fieldMappingDefinition : fieldMappingsDefinitions) { TerminalPosition fieldPosition = fieldMappingDefinition.getPosition(); String fieldName = fieldMappingDefinition.getName(); if (!fieldAccessor.isExists(fieldName)) { continue; } if (screenPojo instanceof ScreenEntity) { ScreenEntity screenEntity = (ScreenEntity)screenPojo; if (fieldName.equalsIgnoreCase(screenEntity.getFocusField())) { sendAction.setCursorPosition(fieldPosition); if (logger.isDebugEnabled()) { logger.debug(MessageFormat.format("Cursor was set at position {0} from field {1}", fieldPosition, screenEntity.getFocusField())); } } } if (!fieldMappingDefinition.isEditable()) { continue; } Object fieldValue = fieldAccessor.getFieldValue(fieldName); // null - skip field assignment if (fieldValue == null) { continue; } // don't handle none string or number if (!TypesUtil.isNumberOrString(fieldValue.getClass())) { continue; } String initalValue = String.valueOf(fieldValue); // short-cuts.. int startRow = fieldMappingDefinition.getPosition().getRow(); int endRow = fieldMappingDefinition.getEndPosition().getRow(); if (endRow == 0) { endRow = startRow; } int startColumn = fieldMappingDefinition.getPosition().getColumn(); int endColumn = fieldMappingDefinition.getEndPosition().getColumn(); int currentColumn = startColumn; int screenColumns = terminalSnapshot.getSize().getColumns(); String leftoverValue = initalValue; // iterate through the field rows - typically 1 round (endRow = startRow) for (int currentRow = startRow; currentRow <= endRow; currentRow++) { String value = leftoverValue; if (endRow != startRow) { if (fieldMappingDefinition.isRectangle()) { value = leftoverValue.substring(0, endColumn - startColumn); leftoverValue = leftoverValue.substring(endColumn - startColumn); } else { // 1st row if (currentRow == startRow) { value = leftoverValue.substring(0, screenColumns - startColumn + 2); leftoverValue = leftoverValue.substring(screenColumns - startColumn + 2); } // last row else if (currentRow == endRow) { value = leftoverValue; currentColumn = 1; } // middle row else { value = leftoverValue.substring(0, screenColumns); leftoverValue = leftoverValue.substring(screenColumns); currentColumn = 1; } } } // find the terminal field in this position TerminalField terminalField = terminalSnapshot.getField(currentRow, currentColumn); if (terminalField == null) { if (logger.isDebugEnabled()) { logger.debug(MessageFormat.format( "Unable to find terminal field in position {0},{1} which matchees field {2} in {3}", currentRow, currentColumn, fieldName, ProxyUtil.getObjectRealClass(screenPojo))); } continue; } if (terminalField.isEditable() && value != null) { boolean fieldModified = fieldComparator.isFieldModified(screenPojo, fieldName, terminalField.getValue(), value); if (fieldModified) { if (fieldMappingDefinition.isEditable()) { terminalField.setValue(value); modifiedfields.add(terminalField); if (logger.isDebugEnabled()) { logger.debug(MessageFormat.format( "Field {0} was set with value \"{1}\" to send fields for screen {2}", fieldName, value, screenPojo.getClass())); } } else { throw (new TerminalActionException(MessageFormat.format( "Field {0} in screen {1} was modified with value {2}, but is not defined as editable", fieldName, screenPojo, value))); } } } } } } }