/******************************************************************************* * 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.render; import org.apache.commons.lang.CharEncoding; import org.apache.commons.lang.SystemUtils; import org.openlegacy.exceptions.OpenLegacyRuntimeException; import org.openlegacy.terminal.ScreenSize; import org.openlegacy.terminal.TerminalField; import org.openlegacy.terminal.TerminalPosition; import org.openlegacy.terminal.TerminalSendAction; import org.openlegacy.terminal.TerminalSnapshot; import org.openlegacy.terminal.utils.FieldsQuery; import org.openlegacy.terminal.utils.FieldsQuery.EditableFieldsCriteria; import java.io.IOException; import java.io.OutputStream; import java.util.Collection; import java.util.List; /** * A textual utility which format terminal snapshot in to a preventable text which is very comfort for debugging purposes * */ public class DefaultTerminalSnapshotTextRenderer implements TerminalSnapshotTextRenderer { private static DefaultTerminalSnapshotTextRenderer instance = new DefaultTerminalSnapshotTextRenderer(); private boolean hidePasswordFields = true; public static DefaultTerminalSnapshotTextRenderer instance() { return instance; } public void render(TerminalSnapshot terminalSnapshot, OutputStream outputStream) { boolean decorated = true; String text = terminalSnapshot.getText(); String newline = SystemUtils.LINE_SEPARATOR; int rows = terminalSnapshot.getSize().getRows(); StringBuilder out = new StringBuilder(); if (decorated) { generateColumnNumbers(terminalSnapshot, newline, out); } for (int i = 0; i < rows; i++) { int beginIndex = i * terminalSnapshot.getSize().getColumns(); if (decorated) { out.append(i + 1); if (decorated) { if ((i + 1) < 10) { out.append(" "); } out.append("|"); } } if (decorated) { out.append(text.substring(beginIndex, beginIndex + terminalSnapshot.getSize().getColumns())); out.append("|"); } out.append(newline); } if (decorated) { out.append("___________________________________________________________________________________"); } if (decorated) { out.append(newline); generateColumnNumbers(terminalSnapshot, newline, out); } drawFieldsSeperators(terminalSnapshot, out); drawEditableFields(terminalSnapshot, out, FieldsQuery.queryFields(terminalSnapshot, EditableFieldsCriteria.instance())); try { // append new line so snapshot will be rendered from start of line in logs outputStream.write(SystemUtils.LINE_SEPARATOR.getBytes()); outputStream.write(out.toString().getBytes(CharEncoding.UTF_8)); } catch (IOException e) { throw (new OpenLegacyRuntimeException(e)); } } @SuppressWarnings("unused") private static void drawCursor(TerminalSnapshot terminalSnapshot, StringBuilder out, TerminalSendAction terminalSendAction) { if (terminalSendAction.getCursorPosition() == null) { return; } int cursorPainterLocation = calculatePositionOnPainter(terminalSendAction.getCursorPosition(), terminalSnapshot.getSize()); if (out.charAt(cursorPainterLocation) == ' ') { out.setCharAt(cursorPainterLocation, '#'); } } private static void drawFieldsSeperators(TerminalSnapshot terminalSnapshot, StringBuilder out) { List<TerminalPosition> attributes = terminalSnapshot.getFieldSeperators(); for (TerminalPosition position : attributes) { if (position.getColumn() > 0) { int bufferLocation = calculatePositionOnPainter(position, terminalSnapshot.getSize()); out.setCharAt(bufferLocation, '^'); } } } private static void generateColumnNumbers(TerminalSnapshot terminalSnapshot, String newline, StringBuilder out) { StringBuilder headerLine1 = new StringBuilder(" "); StringBuilder headerLine2 = new StringBuilder(" "); for (int i = 2; i <= terminalSnapshot.getSize().getColumns(); i++) { if (i % 2 == 0) { headerLine1.append(i % 10); if ((i / 10) > 0) { headerLine2.append(i / 10); } else { headerLine2.append(" "); } } else { headerLine1.append(" "); headerLine2.append(" "); } } out.append(headerLine1 + newline); out.append(headerLine2 + newline); out.append("___________________________________________________________________________________"); out.append(newline); } private void drawEditableFields(TerminalSnapshot terminalSnapshot, StringBuilder out, Collection<TerminalField> fields) { char leftMark; char rightMark; for (TerminalField terminalField : fields) { // +6 - line numbers + | int beforeInputBufferLocation = calculatePositionOnPainter(terminalField.getPosition(), terminalSnapshot.getSize()) - 1; if (terminalField.isModified()) { leftMark = '*'; rightMark = '*'; } else { leftMark = '['; rightMark = ']'; } out.setCharAt(beforeInputBufferLocation, leftMark); int afterInputBufferLocation = beforeInputBufferLocation + terminalField.getLength() + 1; out.setCharAt(afterInputBufferLocation, rightMark); String value = terminalField.getValue(); for (int i = 0; i < terminalField.getLength(); i++) { int inputBufferLocation = beforeInputBufferLocation + 1; if (i < value.length()) { char ch = value.charAt(i); if (hidePasswordFields && terminalField.isPassword()) { ch = '*'; } out.setCharAt(inputBufferLocation + i, ch); } else { out.setCharAt(inputBufferLocation + i, ' '); } } } } private static int calculatePositionOnPainter(TerminalPosition position, ScreenSize screenSize) { int fieldStartBufferLocation = (screenSize.getColumns() + 4 + SystemUtils.LINE_SEPARATOR.length()) // 6- line numbers + | // + NL // -1 - 0 base, +3 - header * (position.getRow() - 1 + 3) + position.getColumn() - 1; return fieldStartBufferLocation; } public String getFileFormat() { return "txt"; } public void setHidePasswordFields(boolean hidePasswordFields) { this.hidePasswordFields = hidePasswordFields; } }