/*******************************************************************************
* 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.table;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openlegacy.FieldFormatter;
import org.openlegacy.designtime.analyzer.TextTranslator;
import org.openlegacy.designtime.terminal.analyzer.ScreenFact;
import org.openlegacy.designtime.terminal.analyzer.ScreenFactProcessor;
import org.openlegacy.designtime.terminal.analyzer.support.ColumnComparator;
import org.openlegacy.designtime.terminal.model.ScreenEntityDesigntimeDefinition;
import org.openlegacy.modules.table.RecordSelectionEntity;
import org.openlegacy.terminal.TerminalField;
import org.openlegacy.terminal.definitions.ScreenTableDefinition.ScreenColumnDefinition;
import org.openlegacy.terminal.definitions.SimpleScreenColumnDefinition;
import org.openlegacy.terminal.definitions.SimpleScreenTableDefinition;
import org.openlegacy.utils.StringUtil;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
public class ScreenTableFactProcessor implements ScreenFactProcessor {
private static final String SELECTION_FIELD = "Selection";
private static final String COLUMN = "Column";
@Inject
private FieldFormatter fieldFormatter;
@Inject
private TextTranslator textTranslator;
private final static Log logger = LogFactory.getLog(ScreenTableFactProcessor.class);
public boolean accept(ScreenFact screenFact) {
return screenFact instanceof ScreenTableFact;
}
public void process(ScreenEntityDesigntimeDefinition screenEntityDefinition, ScreenFact screenFact) {
ScreenTableFact screenTableFact = (ScreenTableFact)screenFact;
addTableDefinition(screenEntityDefinition, screenTableFact.getTableColumns());
}
public void addTableDefinition(ScreenEntityDesigntimeDefinition screenEntityDefinition, List<TableColumnFact> TableColumnFacts) {
Collections.sort(TableColumnFacts, ColumnComparator.instance());
SimpleScreenTableDefinition tableDefinition = new SimpleScreenTableDefinition(null);
List<TerminalField> firstColumnFields = TableColumnFacts.get(0).getFields();
TerminalField topLeftTableCell = firstColumnFields.get(0);
// ignore the table if it's outside a defined window border
if (!screenEntityDefinition.getSnapshotBorders().contains(topLeftTableCell.getPosition(), false)) {
logger.info(MessageFormat.format("Table which starts at {0} found outside window. Ignoring it. Screen: {1}",
topLeftTableCell.getPosition(), screenEntityDefinition.getEntityName()));
return;
}
List<ScreenColumnDefinition> columnDefinitions = tableDefinition.getColumnDefinitions();
for (int i = 0; i < TableColumnFacts.size(); i++) {
TableColumnFact tableColumnFact = TableColumnFacts.get(i);
TerminalField headerField = getHeader(tableColumnFact);
// 1st column cell
TerminalField firstCellField = tableColumnFact.getFields().get(0);
String columnName = headerField != null ? headerField.getValue() : null;
columnName = fieldFormatter.format(columnName);
if (StringUtil.getLength(columnName) == 0) {
// if it is the 1st column and the field is editable in the size of 1-2, it's probably a selection field
if (isSelectionField(i, firstCellField)) {
columnName = SELECTION_FIELD;
} else {
columnName = COLUMN + (i + 1);
}
}
SimpleScreenColumnDefinition columnDefinition = initColumn(i, firstCellField, columnName, columnDefinitions);
// define the screen as record selection type if it has a selection field and it's NOT window
if (columnDefinition.isSelectionField() && !screenEntityDefinition.isWindow()) {
screenEntityDefinition.setType(RecordSelectionEntity.class);
screenEntityDefinition.getReferredClasses().add(RecordSelectionEntity.class.getName());
}
if (!isSelectionField(i, firstCellField) && tableDefinition.getKeyFieldNames().size() == 0) {
// mark the 1st non edit-able field as key (in design-time)
// TODO logic needs to be more rich to check for most populated column
columnDefinition.setKey(true);
}
if (tableDefinition.getKeyFieldNames().size() > 0 && tableDefinition.getMainDisplayField() == null) {
// assume (in design-time) the 2nd column followed by key column in the main display column
tableDefinition.setMainDisplayField(columnDefinition.getName());
}
columnDefinitions.add(columnDefinition);
// remove the fields from the snapshot to avoid re-recognize by other rules
screenEntityDefinition.getSnapshot().getFields().removeAll(tableColumnFact.getFields());
if (headerField != null) {
screenEntityDefinition.getSnapshot().getFields().remove(headerField);
}
}
// set the last field as main display field if non was set - may happen if there only 2 columns - 1 action field
if (tableDefinition.getMainDisplayField() == null) {
tableDefinition.setMainDisplayField(columnDefinitions.get(columnDefinitions.size() - 1).getName());
}
tableDefinition.setStartRow(topLeftTableCell.getPosition().getRow());
tableDefinition.setEndRow(firstColumnFields.get(firstColumnFields.size() - 1).getPosition().getRow());
// add table to the screen entity without a name, which will be given by the screen entity name at a later phase
screenEntityDefinition.addTemporaryTable(tableDefinition);
logger.info(MessageFormat.format("Added table {0} to screen entity {1}", tableDefinition.getTableEntityName(),
screenEntityDefinition.getEntityName()));
}
private static TerminalField getHeader(TableColumnFact TableColumnFact) {
List<TerminalField> headerFields = TableColumnFact.getHeaderFields();
// TODO handle multiple header line
TerminalField headerField = null;
if (headerFields.size() > 0) {
headerField = headerFields.get(0);
}
return headerField;
}
private static String findFreeColumnName(String columnName, List<ScreenColumnDefinition> columnsDefinitions) {
Map<String, ScreenColumnDefinition> columnsMap = new HashMap<String, ScreenColumnDefinition>();
for (ScreenColumnDefinition screenColumnDefinition : columnsDefinitions) {
columnsMap.put(screenColumnDefinition.getDisplayName(), screenColumnDefinition);
}
int fieldNameCount = 1;
String tempFieldName = columnName;
String baseFieldName = columnName;
while (columnsMap.get(tempFieldName) != null) {
tempFieldName = baseFieldName + fieldNameCount++;
}
return tempFieldName;
}
private SimpleScreenColumnDefinition initColumn(int coloumnIndex, TerminalField firstCellField, String columnName,
List<ScreenColumnDefinition> columnDefinitions) {
columnName = textTranslator.translate(columnName);
columnName = findFreeColumnName(columnName, columnDefinitions);
Integer i = 1;
for (ScreenColumnDefinition screenColumnDefinition : columnDefinitions) {
if (screenColumnDefinition.getName().equals(columnName)) {
columnName += i.toString();
}
}
SimpleScreenColumnDefinition columnDefinition = new SimpleScreenColumnDefinition(StringUtil.toJavaFieldName(columnName));
columnDefinition.setStartColumn(firstCellField.getPosition().getColumn());
columnDefinition.setEndColumn(columnDefinition.getStartColumn() + firstCellField.getLength() - 1);
columnDefinition.setDisplayName(StringUtil.toDisplayName(columnName));
columnDefinition.setSampleValue(StringUtil.toSampleValue(firstCellField.getValue()));
columnDefinition.setEditable(firstCellField.isEditable());
columnDefinition.setJavaType(firstCellField.getType());
columnDefinition.setSelectionField(isSelectionField(coloumnIndex, firstCellField));
return columnDefinition;
}
private static boolean isSelectionField(int columnIndex, TerminalField firstCellField) {
return columnIndex == 0 && firstCellField.isEditable() && firstCellField.getLength() <= 2;
}
}