package net.sf.f3270; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.h3270.host.Field; import org.h3270.host.InputField; import org.h3270.host.S3270; import org.h3270.host.Screen; import org.h3270.host.S3270.TerminalMode; import org.h3270.host.S3270.TerminalType; import org.h3270.render.TextRenderer; public class Terminal { private static final int SCREEN_WIDTH_IN_CHARS = 80; private S3270 s3270; private final Collection<TerminalObserver> observers = new ArrayList<TerminalObserver>(); private final String s3270Path; private final String hostname; private final int port; private final TerminalType type; private final TerminalMode mode; private final boolean showTerminalWindow; private static final char MAINFRAME_BLANK_CHAR = '\u0000'; private static final char SINGLE_SPACE = ' '; public Terminal(final String s3270Path, final String hostname, final int port, final TerminalType type, final TerminalMode mode, final boolean showTerminalWindow) { this.s3270Path = s3270Path; this.hostname = hostname; this.port = port; this.type = type; this.mode = mode; this.showTerminalWindow = showTerminalWindow; addDefaultObservers(); } private void addDefaultObservers() { addObserver(new TerminalScreenToConsoleObserver(this)); if (showTerminalWindow) { addObserver(new TerminalWindowObserver()); } } public void addObserver(TerminalObserver observer) { observers.add(observer); } public void removeObserver(TerminalObserver observer) { observers.remove(observer); } public Terminal connect() { s3270 = new S3270(s3270Path, hostname, port, type, mode); updateScreen(); for (TerminalObserver observer : observers) { observer.connect(s3270); } commandIssued("connect", null); return this; } public void disconnect() { assertConnected(); s3270.disconnect(); for (TerminalObserver observer : observers) { observer.disconnect(); } } private void assertConnected() { if (s3270 == null) { throw new RuntimeException("not connected"); } } private void commandIssued(String command, String returned, Parameter... parameters) { for (TerminalObserver observer : observers) { observer.commandIssued(command, returned, parameters); } } private void updateScreen() { s3270.updateScreen(); for (TerminalObserver observer : observers) { observer.screenUpdated(); } } public String getScreenText() { assertConnected(); return new TextRenderer().render(s3270.getScreen()); } public String getLine(final int line) { assertConnected(); final Screen screen = s3270.getScreen(); final StringBuilder sb = new StringBuilder(); for (int col = 0; col < screen.getWidth(); col++) { sb.append(replaceNull(screen.charAt(col, line))); } return sb.toString(); } public int getWidth() { return s3270.getScreen().getWidth(); } public int getHeight() { return s3270.getScreen().getHeight(); } public void enter() { assertConnected(); s3270.submitScreen(); s3270.enter(); updateScreen(); commandIssued("enter", null); } public void pf(final int n) { assertConnected(); s3270.submitScreen(); s3270.pf(n); updateScreen(); commandIssued("pf", null, new Parameter("n", n)); } public void pa(final int n) { assertConnected(); s3270.pa(n); updateScreen(); commandIssued("pa", null, new Parameter("n", n)); } public void clear() { assertConnected(); s3270.clear(); updateScreen(); commandIssued("clear", null); } public void type(final String text) { assertConnected(); InputField field = s3270.getScreen().getFocusedField(); field.setValue(text); commandIssued("type", null, new Parameter("text", text)); } public void clearScreen() { assertConnected(); s3270.eraseEOF(); updateScreen(); commandIssued("clearScreen", null); } /** * @deprecated Use {@link @link Terminal#write (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public void write(final String label, final String value) { write(new FieldIdentifier(label), value); } /** * @deprecated Use {@link @link Terminal#write (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public void write(final String label, final String value, final MatchMode matchMode) { write(new FieldIdentifier(label, matchMode), value); } /** * @deprecated Use {@link @link Terminal#write (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public void write(final String label, final String value, final int skip) { write(new FieldIdentifier(label, skip), value); } /** * @deprecated Use {@link @link Terminal#write (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public void write(final String label, final String value, final int skip, final MatchMode matchMode) { write(new FieldIdentifier(label, skip, matchMode), value); } /** * @deprecated Use {@link @link Terminal#write (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public void write(String label, String value, int skip, int matchNumber, MatchMode matchMode) { write(new FieldIdentifier(label, skip, matchNumber, matchMode), value); } public void write(FieldIdentifier fieldIdentifier, String value) { assertConnected(); getInputField(fieldIdentifier).setValue(value); commandIssued("write", null, buildParameters(fieldIdentifier, value)); } /** * @deprecated Use {@link @link Terminal#read (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public String read(final String label) { return read(new FieldIdentifier(label)); } /** * @deprecated Use {@link @link Terminal#read (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public String read(final String label, final int skip) { return read(new FieldIdentifier(label, skip)); } /** * @deprecated Use {@link @link Terminal#read (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public String read(final String label, final MatchMode matchMode) { return read(new FieldIdentifier(label, matchMode)); } /** * @deprecated Use {@link @link Terminal#read (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public String read(final String label, final int skip, final MatchMode matchMode) { return read(new FieldIdentifier(label, skip, matchMode)); } /** * @deprecated Use {@link @link Terminal#read (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public String read(final String label, final int skip, final int matchNumber, final MatchMode matchMode) { return read(new FieldIdentifier(label, skip, matchNumber, matchMode)); } public String read(FieldIdentifier fieldIdentifier) { assertConnected(); Field field = getField(fieldIdentifier); String value = read(field); commandIssued("read", value, buildParameters(fieldIdentifier, null)); return value; } private InputField getInputField(FieldIdentifier fieldIdentifier) { Field field = getField(fieldIdentifier); if (!(field instanceof InputField)) { throw new RuntimeException( String.format("field [%s] after match [%d] for [%s] with skip [%d] found with match mode [%s] is not an input field", read(field), fieldIdentifier.matchNumber, fieldIdentifier.label, fieldIdentifier.skip, fieldIdentifier.matchMode)); } return (InputField) field; } private String read(Field field) { return replaceNulls(field.getValue()).trim(); } private String replaceNulls(String value) { return value.replace(MAINFRAME_BLANK_CHAR, SINGLE_SPACE); } private char replaceNull(char c) { return c == MAINFRAME_BLANK_CHAR ? SINGLE_SPACE : c; } private Parameter[] buildParameters(FieldIdentifier fieldIdentifier, String value) { Collection<Parameter> parameters = fieldIdentifier.buildParameters(); if (value != null) { parameters.add(new Parameter("value", value)); } return parameters.toArray(new Parameter[parameters.size()]); } /** * @deprecated Use {@link @link Terminal#getField (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public Field fieldAfterLabel(String label) { return getField(new FieldIdentifier(label)); } /** * @deprecated Use {@link @link Terminal#getField (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public Field fieldAfterLabel(String label, int skip) { return getField(new FieldIdentifier(label, skip)); } /** * @deprecated Use {@link @link Terminal#getField (FieldIdentifier)} instead */ // TODO : delete method (deprecated on 2010-04-15) public Field fieldAfterLabel(String label, int skip, int matchNumber) { return getField(new FieldIdentifier(label, skip, matchNumber)); } /** * @deprecated Use {@link @link Terminal#getField (FieldIdentifier)} instead */ // TODO : Inline into Terminal#getField (FieldIdentifier) (deprecated on 2010-04-15) public Field fieldAfterLabel(final String label, final int skip, final int matchNumber, final MatchMode matchMode) { return getField(new FieldIdentifier(label, skip, matchNumber, matchMode)); } public Field getField(FieldIdentifier fieldIdentifier) { assertConnected(); List<Field> fields = s3270.getScreen().getFields(); return fieldIdentifier.find(fields); } /** * @deprecated Should not be using field indexes use other methods on {@link @link Terminal} to achieve desired behaviour */ // TODO : delete method (deprecated on 2010-04-15) public int getFieldIndex(final String label, final int matchNumber, final MatchMode matchMode) { assertConnected(); return new FieldIdentifier(label, matchNumber, matchMode).getFieldIndexOfLabel(s3270.getScreen().getFields()); } public boolean screenHasLabel(FieldIdentifier fieldIdentifier) { return fieldIdentifier.getFieldIndexOfLabel(s3270.getScreen().getFields()) != -1; } public void printFields() { printFields(System.out); } public void printFields(PrintStream stream) { assertConnected(); List<Field> fields = s3270.getScreen().getFields(); for (int i = 0; i < fields.size(); i++) { String value = replaceNulls(fields.get(i).getValue()); stream.println(String.format("%d=[%s]", i, value)); } } private static final String SCREEN_SEPARATOR = "+--------------------------------------------------------------------------------+"; public void printScreen() { printScreen(System.out); } public void printScreen(PrintStream stream) { assertConnected(); final String[] lines = getScreenText().split("\n"); final String blanks = " "; stream.println(SCREEN_SEPARATOR); for (String line : lines) { final String fixedLine = (line + blanks).substring(0, SCREEN_WIDTH_IN_CHARS); stream.println(String.format("|%s|", fixedLine)); } stream.println(SCREEN_SEPARATOR); } }