package net.sf.f3270;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.h3270.host.Field;
public class FieldIdentifier {
private static final MatchMode DEFAULT_MATCH_MODE = MatchMode.CONTAINS;
final String label;
final int skip;
final int matchNumber;
final MatchMode matchMode;
public FieldIdentifier(String label) {
this(label, 1, 1, DEFAULT_MATCH_MODE);
}
public FieldIdentifier(String label, int skip) {
this(label, skip, 1, DEFAULT_MATCH_MODE);
}
public FieldIdentifier(String label, MatchMode matchMode) {
this(label, 1, matchMode);
}
public FieldIdentifier(String label, int skip, int matchNumber) {
this(label, skip, matchNumber, DEFAULT_MATCH_MODE);
}
public FieldIdentifier(String label, int skip, MatchMode matchMode) {
this(label, skip, 1, matchMode);
}
public FieldIdentifier(String label, int skip, int matchNumber, MatchMode matchMode) {
this.label = label;
this.skip = skip;
this.matchNumber = matchNumber;
this.matchMode = matchMode;
}
Collection<Parameter> buildParameters() {
Collection<Parameter> parameters = new ArrayList<Parameter>();
parameters.add(new Parameter("label", label));
if (skip != 1) {
parameters.add(new Parameter("skip", skip));
}
if (matchNumber != 1) {
parameters.add(new Parameter("matchNumber", matchNumber));
}
if (matchMode != DEFAULT_MATCH_MODE) {
parameters.add(new Parameter("matchMode", matchMode));
}
return parameters;
}
Field find(List<Field> fields) {
int indexOfLabel = getFieldIndexOfLabel(fields);
if (indexOfLabel == -1) {
throw new RuntimeException(String.format("field [%s] could not be found using match mode [%s]", label,
matchMode));
}
final int indexOfField = indexOfLabel + skip;
if (indexOfField >= fields.size()) {
throw new RuntimeException(String.format("field [%s] at index [%i] plus skip [%i] exceed the number of available fields in the screen [%i]", label, indexOfLabel, skip, indexOfField));
}
return fields.get(indexOfField);
}
int getFieldIndexOfLabel(List<Field> fields) {
int matches = 0;
for (int i = 0; i < fields.size(); i++) {
String value = fields.get(i).getValue().toLowerCase();
if (matches(label.toLowerCase(), value)) {
matches++;
if (matches == matchNumber) {
return i;
}
}
}
return -1;
}
private boolean matches(String expected, String actual) {
return matchExact(expected, actual) || matchExactAfterTrim(expected, actual)
|| matchRegex(expected, actual) || matchContains(expected, actual);
}
private boolean matchExact(String expected, String actual) {
return matchMode == MatchMode.EXACT && actual.equals(expected);
}
private boolean matchExactAfterTrim(String expected, String actual) {
return matchMode == MatchMode.EXACT_AFTER_TRIM && actual.trim().equals(expected);
}
private boolean matchRegex(String expected, String actual) {
return matchMode == MatchMode.REGEX && actual.matches(expected);
}
private boolean matchContains(String expected, String actual) {
return matchMode == MatchMode.CONTAINS && actual.contains(expected);
}
}