Listing of Source ../source/GOF/GofMainFrameSplitHostFieldIdentifier.javapackage se.entra.phantom.server;
import java.util.Enumeration;
import java.util.Vector;
import java.util.NoSuchElementException;
/**
* This class takes all the host fields and creates GofHostFields from them. When creating the
* GofHostFields, it will not take into account if the area to identify is smaller than the
* actual screen, or if there is a popup window on the screen. These limitations will be taken
* into account when fetching the GofHostFields with one of the two methods for fetching.
* @author J. Bergström
*/
public class GofMainFrameSplitHostFieldIdentifier extends GofHostFieldIdentifierAdapter
{
// ---------------
// CLASS VARIABLES
// ---------------
/**
* The characters that are accepted as a numeric characters.
*/
private static final String NUM_CHARS = "0123456789-+,. ";
// ------------------
// INSTANCE VARIABLES
// ------------------
private GofHostField[][] sortGofHostField;
// ----------------
// INSTANCE METHODS
// ----------------
/**
* This method must create the GofHostFields from the HostScreen's HostFields. It is up this
* method to decide if a HostField should be split up to several GofHostFields. The newly
* created GofHostFields must be stored internally in the class, since the method GetHostFields
* must be able to return them.
* @param screen The host screen to process.
*/
@Override
public void identifyHostFields( HostScreen screen )
{
gofHostFields = new Vector<GofHostField>( );
Vector<GofHostField> tempGofHostFields = new Vector<GofHostField>( );
int w = screen.getWidth( );
int h = screen.getHeight( );
sortGofHostField = new GofHostField[h][w];
for( int i = 0; i < h; i++ )
{
for( int j = 0; j < w; j++ )
{
sortGofHostField[i][j] = null;
}
}
int hfX, hfY, restLen;
String hfText;
for( HostField hf = screen.getFirstFieldAbsolute( 0 ); hf != null; hf = hf.getNextField( ) )
{
hfX = hf.x;
hfY = hf.y;
restLen = hf.length;
hfText = screen.getStringAbsolute( hfX, hfY, restLen );
while( restLen > 0 )
{
int startpos = hf.length - restLen;
int hfCx = restLen;
if( hfX + restLen > w )
hfCx = w - hfX;
restLen = restLen - hfCx;
GofHostField gofHostField = new GofHostField( hf,
hfX,
hfY,
hfCx,
hfText.substring( startpos, startpos + hfCx ),
hf.isEmpty( screen ) );
tempGofHostFields.addElement( gofHostField );
if( restLen > 0 )
{
hfX = 0;
// Must be the host screen height (e.g. 80x24), not screen height (e.g. 80x25).
// Fix this later!
hfY = ( hfY + 1 ) % h;
}
}
}
Vector<GofColumnElement>[] columnElements = createColumnElements( tempGofHostFields, w );
for( int i = 0, s = columnElements.length; i < s; i++ )
{
for( Enumeration<GofColumnElement> e1 = columnElements[i].elements( ); e1.hasMoreElements( ); )
{
GofColumnElement gce = e1.nextElement( );
if( gce.colsGofHostFields.size( ) == 1 )
{
GofHostField gofHostField = gce.colsGofHostFields.elementAt( 0 );
if( gofHostField.isProtected( ) == false )
addToSorter( gofHostField );
else
splitGofHostField( screen, gofHostField );
}
else
{
if( gce.isEditable( ) == true )
{
for( Enumeration<GofHostField> e2 = gce.colsGofHostFields.elements( ); e2.hasMoreElements( ); )
{
GofHostField gofHostField = e2.nextElement( );
addToSorter( gofHostField );
}
}
else
{
splitColumnElement( gce );
}
}
}
}
for( int i = 0; i < h; i++ )
{
for( int j = 0; j < w; j++ )
{
if( sortGofHostField[i][j] != null )
{
gofHostFields.addElement( sortGofHostField[i][j] );
}
}
}
}
/**
* Creates column elements from GofHostFields. These column elements will later be analyzed to
* find logical words that spans over all the lines in the column.
* @param gofHostFields The GofHostFields to create column elements from.
* @param w The width of the screen in characters.
* @return An array of Vectors containing the column elements.
*/
@SuppressWarnings("unchecked")
private Vector<GofColumnElement>[] createColumnElements( Vector<GofHostField> gofHostFields, int w )
{
Vector<GofColumnElement>[] gceList = new Vector [w];
for( int x = 0; x < w; x++ )
gceList[x] = new Vector<GofColumnElement>( );
for( int i = 0, s = gofHostFields.size( ); i < s; i++ )
{
GofHostField ghf = gofHostFields.elementAt( i );
int x = ghf.getX( );
int y = ghf.getY( );
GofColumnElement prevGce;
try
{
prevGce = gceList[x].lastElement( );
}
catch( NoSuchElementException e )
{
prevGce = null;
}
int cx = ghf.getCx( );
if( prevGce != null && ( prevGce.startLine + prevGce.height ) == y && prevGce.width == cx )
{
prevGce.addGofHostField( y, ghf );
}
else
{
GofColumnElement gce = new GofColumnElement( x, y, ghf );
gceList[x].addElement( gce );
}
}
return gceList;
}
/**
* Splits a single GofHostField into several GofHostFields.
* @param screen The HostScreen to which the GofHostField belongs to.
* @param gofHostField The GofHostField that should be split.
*/
private void splitGofHostField( HostScreen screen, GofHostField gofHostField )
{
String text = gofHostField.getText( );
int hfStart = gofHostField.getX( );
Vector<GofHostFieldWord> words = getWords( text );
boolean doSplit;
for( int i = 0, s = words.size( ); i < s; i++ )
{
doSplit = false;
GofHostFieldWord ghfw1 = words.elementAt( i );
int startCol = hfStart + ghfw1.startpos;
if( i == s - 1 )
{
// Last word.
doSplit = true;
}
else
{
GofHostFieldWord ghfw2 = words.elementAt( i + 1 );
if( ghfw2.startpos - ( ghfw1.startpos + ghfw1.text.length( ) ) > 1 )
{
doSplit = true;
}
else
{
if( ( ghfw1.isNumeric( ) && !ghfw2.isNumeric( ) ) ||
( !ghfw1.isNumeric( ) && ghfw2.isNumeric( ) ) ||
( ghfw1.isNumeric( ) && ghfw2.isNumeric( ) ) )
{
doSplit = true;
}
else
{
ghfw2.text = ghfw1.text + " " + ghfw2.text;
ghfw2.startpos = ghfw1.startpos;
}
}
}
if( doSplit == true )
{
GofHostField ghf = new GofHostField( gofHostField.getHostField( ),
startCol,
gofHostField.getY( ),
ghfw1.text.length( ),
ghfw1.text,
gofHostField.isEmpty( ) );
addToSorter( ghf );
}
}
}
/**
* Splits the GofHostFields that belongs to a column element into several GofHostFields.
* @param gce The GofColumnElement to split up.
*/
private void splitColumnElement( GofColumnElement gce )
{
int w = gce.width;
int[] c = new int[w];
for( int i = 0; i < w; i++ )
c[i] = 0;
for( int i = 0, s1 = gce.colsGofHostFields.size( ); i < s1; i++ )
{
GofHostField ghf = gce.colsGofHostFields.elementAt( i );
String text = ghf.getText( );
for( int j = 0, s2 = text.length( ); j < s2; j++ )
{
if( text.charAt( j ) != ' ' )
c[j] = 1;
}
}
for( int i = 0, s1 = gce.colsGofHostFields.size( ); i < s1; i++ )
{
GofHostField ghf = gce.colsGofHostFields.elementAt( i );
int start = getNextStart( c, 0 );
int oldStart = start;
int end = 0;
boolean doSplit;
while( start > -1 )
{
end = getNextEnd( c, start );
start = oldStart;
String text = ghf.getText( ).substring( start, end/* + 1*/ );
doSplit = false;
int nextStart = getNextStart( c, end + 1);
if( nextStart != -1 )
{
int nextEnd = getNextEnd( c, nextStart );
String nextText = ghf.getText( ).substring( nextStart, nextEnd/* + 1*/ );
if( nextStart - end > 1 )
doSplit = true;
else
{
boolean isTextNumeric = isNumeric( text );
boolean isNextTextNumeric = isNumeric( nextText );
if( ( isTextNumeric && !isNextTextNumeric ) ||
( !isTextNumeric && isNextTextNumeric ) ||
( isTextNumeric && isNextTextNumeric ) )
doSplit = true;
}
}
else
doSplit = true;
if( doSplit == true )
{
GofHostField gofHostField = new GofHostField( ghf.getHostField( ),
gce.startCol + start,
ghf.getY( ),
end - start + 1,
ghf.getText( ).substring( start, end + 1 ),
ghf.isEmpty( ) );
addToSorter( gofHostField );
oldStart = nextStart;
}
else
{
oldStart = start;
}
start = nextStart;
}
}
}
/**
*
*/
private int getNextStart( int[] c, int p )
{
int start = -1;
for( int i = p; i < c.length; i++ )
{
if( c[i] == 1 )
{
start = i;
break;
}
}
return start;
}
/**
*
*/
private int getNextEnd( int[] c, int p )
{
int end = c.length - 1;
for( int i = p; i < c.length; i++ )
{
if( c[i] == 0 )
{
end = i;
break;
}
}
return end;
}
/**
* Checks if a string is numeric.
* @param text The text to check.
* @return <code>true</code> if the string is numeric, <code>false</code> otherwise.
*/
private boolean isNumeric( String text )
{
for( int i = 0, s = text.length( ); i < s; i++ )
{
char c = text.charAt( i );
if( NUM_CHARS.indexOf( c ) == -1 )
return false;
}
return true;
}
/**
* Splits up a string into GofHostFieldWords.
* @param text The string to split up.
* @return A Vector containing the GofHostWords.
*/
private Vector<GofHostFieldWord> getWords( String text )
{
Vector<GofHostFieldWord> words = new Vector<GofHostFieldWord>( );
int wordStart = -1;
for( int i = 0, s = text.length( ); i < s; i++ )
{
if( text.charAt( i ) == ' ' )
{
if( wordStart > -1 )
{
GofHostFieldWord ghfw = new GofHostFieldWord( text.substring( wordStart, i ), wordStart );
words.addElement( ghfw );
wordStart = -1;
}
}
else
{
if( wordStart == -1 )
wordStart = i;
}
}
if( wordStart > -1 && wordStart < text.length( ) )
{
GofHostFieldWord ghfw = new GofHostFieldWord( text.substring( wordStart ), wordStart );
words.addElement( ghfw );
}
return words;
}
/**
*
*/
private void addToSorter( GofHostField ghf )
{
int y = ghf.getY( );
int x = ghf.getX( );
sortGofHostField[y][x] = ghf;
}
// ==================================================================
// GofHostFieldWord subclass
// ==================================================================
/**
* A private inner class representing a single word in a host field.
*/
private class GofHostFieldWord
{
/**
* The words text.
*/
private String text = "";
/**
* The start position within the host fields text.
*/
private int startpos = -1;
// -----------
// CONSTRUCTOR
// -----------
private GofHostFieldWord( String text, int startpos )
{
this.text = text;
this.startpos = startpos;
}
// ----------------
// INSTANCE METHODS
// ----------------
/**
* Checks if the word is numeric or not.
* @return <code>true</code> if the word is numeric,
* <code>false</code> otherwise.
*/
private boolean isNumeric( )
{
for( int i = 0, s = text.length( ); i < s; i++ )
{
char c = text.charAt( i );
if( NUM_CHARS.indexOf( c ) == -1 )
return false;
}
return true;
}
}
// ==================================================================
// GofColumnElement subclass
// ==================================================================
/**
* The GofColumnElement is a private inner class that is used to store information
* about the column elements created during the identification process of the list
* box. A column element is a column of one or more GofHostFields that starts in
* the same x-position, and has the same width.
* <p>
* The used GofColumnElements will be deleted when a new host screen is processed.
*/
private class GofColumnElement
{
// ------------------
// INSTANCE VARIABLES
// ------------------
/**
* A Vector containing all GofHostFields that is part of this column element.
*/
private Vector<GofHostField> colsGofHostFields;
/**
* The column elements start column on the host screen.
*/
private int startCol;
/**
* The column elements start line on the host screen.
*/
private int startLine;
/**
* The width of the column element in characters.
*/
private int width;
/**
* The height of the column element in lines.
*/
private int height;
// -----------
// CONSTRUCTOR
// -----------
/**
* Creates a new Gof column element.
* @param x The column element's start column on the host screen.
* @param y The column element's start line on the host screen.
* @param ghf The first GofHostField that belongs to this column element.
*/
private GofColumnElement( int x, int y, GofHostField ghf )
{
startCol = x;
startLine = y;
width = ghf.getCx( );
height = 1;
colsGofHostFields = new Vector<GofHostField>( );
colsGofHostFields.addElement( ghf );
}
// ----------------
// INSTANCE METHODS
// ----------------
/**
* Adds a GofHostField to this column element. The new GofHostField must be on
* the line following the last line in this column element.
* @param y The line on which this column element is located.
* @param ghf The GofHostField to add.
*/
private void addGofHostField( int y, GofHostField ghf )
{
height = y - startLine + 1;
colsGofHostFields.addElement( ghf );
}
/**
* Checks if the column is editable. The column is considered editable if it has one
* ore more fields that is not protected.
* @return <code>true</code> if the column is editable, <code>false</code> otherwise.
*/
private boolean isEditable( )
{
boolean isEditable = false;
for( int i = 0, s = colsGofHostFields.size( ); i < s; i++ )
{
GofHostField ghf = colsGofHostFields.elementAt( i );
if( ghf.isProtected( ) == false )
isEditable = true;
}
return isEditable;
}
}
}