/*
* $Header: /cvsroot/webman-cms/source/webman/com/teamkonzept/web/TKForm.java,v 1.8 2001/06/11 09:14:10 alex Exp $
*
*/
package com.teamkonzept.web;
import java.io.*;
import java.util.*;
import com.teamkonzept.lib.*;
public class TKForm {
//------Unveraenderbare Konstanten------//
public static final String PARAM = "PAR";
public static final String REQUIRED = "REQ";
public static final String TYPE = "TYPE";
public static final String REQUIREDSELECTOR = "REQSEL";
public static final String SWAP = "SWAP";
public static final String CLASS_LIST [] = {
PARAM, REQUIRED, REQUIREDSELECTOR, TYPE, SWAP
};
public static final String ERRORCASE = "ERROR";
protected TKParams classes = new TKParams( null );
protected TKHTMLTemplate template;
protected TKFormTypes formTypes;
protected final Hashtable errors = new Hashtable();
/**
* Konstruktor1
* Keine Uebergabeparameter, Konstruktor3 wird aufgerufen.
* Ihm wird null uebergeben.
*/
public TKForm()
{
this( (TKParams)null );
}
/**
* Konstruktor2
* Keine Uebergabeparameter, Konstruktor4 wird aufgerufen.
* Ihm wird null uebergeben.
*
* @param TKFormTypes formTypes, Klasse zur Typberprfung
*/
public TKForm( final TKFormTypes formTypes )
{
this( null, formTypes );
}
/**
* Konstruktor3
* Konstruktor5 wird aufgerufen
*
* @param TKParams params, die Parameter des URL's werden uebergeben
*/
public TKForm( final TKParams params )
{
this( params, (TKHTMLTemplate)null );
}
/**
* Konstruktor4
* Konstruktor6 wird aufgerufen
*
* @param TKParams params, die Parameter des URL's werden uebergeben
* @param TKFormTypes formTypes, Klasse zur Typberprfung
*/
public TKForm( final TKParams params, final TKFormTypes formTypes )
{
this( params, null, formTypes );
}
/**
* Konstruktor5
* Konstruktor7 wird aufgerufen
*
* @param TKParams params, die Parameter des URL's werden uebergeben
* @param TKTemplate template, das Template-Objekt mit der Form
*/
public TKForm( final TKParams params, final TKHTMLTemplate template )
{
this( params, template, CLASS_LIST );
}
/**
* Konstruktor6
* Konstruktor8 wird aufgerufen
*
* @param TKParams params, die Parameter des URL's werden uebergeben
* @param TKTemplate template, das Template-Objekt mit der Form
* @param TKFormTypes formTypes, Klasse zur Typberprfung
*/
public TKForm( final TKParams params, final TKHTMLTemplate template, final TKFormTypes formTypes )
{
this( params, template, CLASS_LIST, formTypes );
}
/**
* Konstruktor7
* Ist das uebergebene TKParam-Objekt nicht null, so werden die Parameter
* in einem verschachtelten hash abgelegt.
*
* @param TKParams params, die Parameter des URL's werden uebergeben
* @param TKTemplate template, das Template-Objekt mit der Form
* @param String classList[], Konstanter String der Klasse TKForm
*/
public TKForm( final TKParams params, final TKHTMLTemplate template, final String classList[] )
{
this( params, template, classList, null );
}
/**
* Konstruktor8
* Ist das uebergebene TKParam-Objekt nicht null, so werden die Parameter
* in einem verschachtelten hash abgelegt.
*
* @param TKParams params, die Parameter des URL's werden uebergeben
* @param TKTemplate template, das Template-Objekt mit der Form
* @param String classList[], Konstanter String der Klasse TKForm
* @param TKFormTypes formTypes, Klasse zur Typberprfung
*/
public TKForm( final TKParams params, final TKHTMLTemplate template, final String classList[], final TKFormTypes formTypes )
{
if( params != null )
setClasses( params, classList );
this.template = template;
this.formTypes = ( formTypes == null ? new TKFormTypes() : formTypes );
}
/**
* das aktuelle Template wird zurueckgegeben.
*
* @return das aktuelle Template, welches dem konstruktor uebergeben wurde
*/
public TKTemplate getTemplate()
{
return template;
}
/**
* Zu jedem Element="className" der classList[] wird nachgeschaut, ob es dazu
* Werte gibt, welche die Methode getClass() in der Klasse TKParams
* als Hash zurueckgibt. Diese Key-Value-Parameter
* werden gann als Hash in einem Hash abgelegt.
*
*----------------------------------------------------------------------
* Syntax: TK_PARClassId[TKParameterName;
* TKParameterSubklassenName:TKParameterSubklassenWert]
* = URLParameterWert
*----------------------------------------------------------------------
*
* Beispiel:Es wurde folgender Parameter in einer Hashtabel abgelegt:
* TK_PAR[ALTER;TYPE:INT] = 33
*----------------------------------------------------------------------
*
* 1. Ein Hash der jeweiligen classId wird zurueckgegeben.
* Die classId ist ein Key der Klasse TKParam
*
* Beispiel: TKParam-Objekt.getClass("PAR")
* ---------------
* | ALTER | 33 |
* ==> |--------------|
* | .... | .. |
* |--------------|
*
* 2. Ein Hash der jeweiligen classId wird zurueckgegeben.
* Die classId ist ein Key der Klasse TKParam
*
* Beispiel: TKParam-Objekt.getClass("TYPE")
* ---------------
* | ALTER | INT |
* ==> |--------------|
* | .... | .. |
* |--------------|
*
* 3. Der className ist der Key des neuen Hashes, dessen Value
* ist wiederum der Hasg, den getClass() zurueckgeliefert hat.
* --------------------------
* | PARAM | --------------- |
* | | | ALTER| 33 | |
* | | | ... | ... | |
* | | -------------- |
* ---------------------------
* | TYPE | -------------- |
* | | | ALTER| INT | |
* | | --------------- |
* ---------------------------
*
* 4. Eine weitere Variante des zurueckgegebenen Hashes von
* TKParam-Objekt.getClass(classId)
*
* ---------------------------------------------
* | TKParameterName | TKVector.URLParameterWert |
* ==> |-----------------|---------------------------
* | .... | .. |
* |-----------------|----------------------------
*
* @param TKParams params, die Parameter des URL's werden uebergeben
* @param String classList[], Konstanter String der Klasse TKForm
*/
protected void setClasses( final TKParams params, final String classList[] )
{
for( int i=0; i<classList.length; i++ ) {
String className = classList[i];
TKHashtable classHash;
//------siehe Class TKForm------//
if( (classHash = params.getClass( className ) ) != null ) {
classes.put( className, classHash.clone() );
}
else {
classes.put( className, new TKHashtable() );
}
}
doSwapReqs();
}
/**
* Die Methode getClass() ruft die gleichnahmige Methode von der Klasse TKParam auf.
* Beispiel: TKParam-Objekt.getClass(classId)
*
* ---------------
* | key | val |
* ==> |--------------|
* | .... | .. |
* |--------------|
*
* @param String classId, ist ein Element aus CLASS_LIST[],
* zuvor auch className genannt
*
* @return TKHashtable, der alle Key-Value-Werte zu einer classId (Klassenname)
* enthaelt.
*/
protected final TKHashtable getClass( final String classId )
{
return classes.getClass( classId );
}
/**
* siehe: Methode getClass in TKParams
* Ein Hash der jeweiligen classId (PARAM)wird zurueckgegeben.
*
* Beispiel: TKParam-Objekt.getClass(PARAM)
* ---------------
* | ALTER | 33 |
* ==> |--------------|
* | .... | .. |
* |--------------|
*
* @return TKHashtable, der alle Key-Value-Werte zu einer classId (Klassenname)
* PARAM enthaelt.
*/
public final TKHashtable getParams()
{
return getClass( PARAM );
}
/**
* siehe: Methode getClass in TKParams
* Ein Hash der jeweiligen classId (REQUIRED)wird zurueckgegeben.
*
* @return TKHashtable, der alle Key-Value-Werte zu einer classId (Klassenname)
* REQUIRED enthaelt.
*/
public final TKHashtable getRequired()
{
return getClass( REQUIRED );
}
/**
* siehe: Methode getClass in TKParams
* Ein Hash der jeweiligen classId (REQUIREDSELECTOR)wird zurueckgegeben.
*
* @return TKHashtable, der alle Key-Value-Werte zu einer classId (Klassenname)
* REQUIREDSELECTOR enthaelt.
*/
public final TKHashtable getRequiredSelector()
{
return getClass( REQUIREDSELECTOR );
}
/**
* siehe: Methode getClass in TKParams
* Ein Hash der jeweiligen classId (SWAP)wird zurueckgegeben.
*
* @return TKHashtable, der alle Key-Value-Werte zu einer classId (Klassenname)
* SWAP enthaelt.
*/
public final TKHashtable getSwapReqs()
{
return getClass( SWAP );
}
/**
* doSwapReqs fhrt fr alle in der Klasse SWAP vorkommenden
* Parameter REQ gegen REQSEL vertaushungen durch.
*
* So erhlt z.B. bei folgendem
*
* <INPUT TYPE="RADIO" NAME="TK_PAR[ANREDE;REQ:1,2]" <TK_CHK:ANREDE=1>> Herr<P>
* <INPUT TYPE="RADIO" NAME="TK_PAR[ANREDE;REQ:1,2]" <TK_CHK:ANREDE=2>> Frau<P>
* <INPUT TYPE="RADIO" NAME="TK_PAR[ANREDE;REQ:1,2]" <TK_CHK:ANREDE=3>> Firma<P>
* <P>
* Name:<INPUT TYPE="NAME" NAME="TK_PAR[NAME;REQSEL:1;SWAP:ANREDE=1,2]" VALUE="<TK:NAME>">
* <P>
* Firma:<INPUT TYPE="NAME" NAME="TK_PAR[FIRMA;REQSEL:2;SWAP:ANREDE=3]" VALUE="<TK:FIRMA>">
*
* der Parameter ANREDE ein REQSEL:1, wenn ANREDE den Wert eins oder zwei hat,
* ansonsten REQSEL:2 . Gleichzeitig erhlt im Gegenzug der Parameter FIRMA bzw. NAME
* ein REQ:1,2
*
*/
public void doSwapReqs() {
final TKHashtable swap = getSwapReqs();
final TKHashtable req = getRequired();
final TKHashtable reqsel = getRequiredSelector();
final TKHashtable params = getParams();
final Enumeration swap_enum = swap.keys();
while ( swap_enum.hasMoreElements() ) {
final Object key = swap_enum.nextElement();
final Object swap_oval = swap.get( key );
if ( swap_oval == null
|| !( swap_oval instanceof String ) ) {
continue;
}
final String swap_val = (String)swap_oval;
final int eq_ndx = swap_val.indexOf( '=' );
if ( eq_ndx >= 0 ) {
final String dest = swap_val.substring( 0, eq_ndx );
final Object parm_oval = params.get( dest );
if ( parm_oval == null
|| !( parm_oval instanceof String ) ) {
continue;
}
final StringTokenizer tokenizer =
new StringTokenizer( swap_val.substring(
eq_ndx + 1,
swap_val.length()
), ","
);
final String parm_val = (String)parm_oval;
while ( tokenizer.hasMoreTokens() ) {
if ( parm_val.equals( tokenizer.nextToken() ) ) {
final Object reqsel_val = reqsel.get( key );
final Object req_val = req.get( dest );
if ( reqsel_val != null && req_val != null ) {
req.remove( dest );
reqsel.remove( key );
req.put( key, reqsel_val );
reqsel.put( dest, req_val );
}
break;
}
}
} else {
final String dest = swap_val;
final Object parm_oval = params.get( dest );
if ( parm_oval == null
|| !( parm_oval instanceof String ) ) {
continue;
}
final Object reqsel_val = reqsel.get( key );
final Object req_val = req.get( dest );
if ( reqsel_val != null && req_val != null ) {
req.remove( dest );
reqsel.remove( key );
req.put( key, reqsel_val );
reqsel.put( dest, req_val );
}
}
}
}
/**
* siehe: Methode getClass in TKParams
* Ein Hash der jeweiligen classId (TYPE)wird zurueckgegeben.
*
* Beispiel: TKParam-Objekt.getClass(TYPE)
* ---------------
* | ALTER | INT |
* ==> |--------------|
* | .... | .. |
* |--------------|
*
* @return TKHashtable, der alle Key-Value-Werte zu einer classId (Klassenname)
* TYPE enthaelt.
*/
public final TKHashtable getTypes()
{
return getClass( TYPE );
}
/**
* In dem aktuellen Template wird die Errorliste gesetzt
*
* @param TKVector errorList, eine spezielle Errorliste, die im Template
* in folgender Notation steht: <TK_LIST:ERROR_errorType> ... </TK_LIST:ERROR_errorType>
* @param String errorType ????
*/
public void addErrorParams( final TKVector errorList, final String errorType )
{
if( errorType != null ) {
errors.put( errorType, errorList );
if( errorType.length() > 0 ) {
template.set( ERRORCASE + "_" + errorType, Boolean.TRUE );
template.set( ERRORCASE, Boolean.TRUE );
}
}
}
/**
* 1. In dem aktuellen Template wird die Errorliste gesetzt
* 2. Die Tags im Template werden substituiert
* 3. Der Text des Templates wird aufbereitet
* 4. template.getText() gibt das Template als String zurueck, welcher
* auf STDOUT geschrieben werden kann.
*
* @param TKVector errorList
* @param String errorType
*/
public void printErrorParams( final PrintStream out ) throws TKTemplateSyntaxException
{
TKListIterator prev_iter = template.getListIterator();
final Enumeration error_enum = errors.keys();
while ( error_enum.hasMoreElements() ) {
final String errorType = (String) error_enum.nextElement();
prev_iter = new ErrorListIterator( errorType, (TKVector) errors.get( errorType ), prev_iter );
}
template.setListIterator( new ErrorListIterator( errors, prev_iter ) );
}
/**
* Liefert eine Liste aller Parameternamen, die nicht ausgefüllt
* wurden, obwohl dies als zwingend in der Form angegeben wurde.
*
* @param TKVector TKVector reqSelectors
* @return einen Vektor aller fehlenden Parameter
*/
public TKVector checkRequiredParams( final TKVector reqSelectors )
{
final TKHashtable paramHash = getParams();
final TKHashtable reqHash = getRequired();
final TKVector missing = new TKVector();
//reqEnum enthaelt ist ein Enumerations-Objekt, mit dem alle Schluessel der
//Tabelle reqHash durchlaufen werden koennen.
final Enumeration reqEnum = reqHash.keys();
while( reqEnum.hasMoreElements() ) {
final Object key = reqEnum.nextElement();
final Object reqVal = reqHash.get( key );
final Object parVal = paramHash.get( key );
if( reqVal == null || reqVal instanceof TKNull
|| ( reqVal instanceof String && isEmptyString( (String) reqVal ) ) ) {
if( parVal == null || parVal instanceof TKNull
|| ( parVal instanceof String && isEmptyString( (String) parVal ) ) ) {
missing.addElement( key );
}
}
else if( reqSelectors != null && !reqSelectors.isEmpty() ){
/* Flle reqConditions mit REQ-Bezeichner fr den
* Parameter key.
*/
final TKVector reqConditions = new TKVector();
if( reqVal instanceof TKVector ) {
final Enumeration reqValEnum = ((TKVector)reqVal).elements();
while( reqValEnum.hasMoreElements() ) {
reqConditions.fill( new StringTokenizer( reqValEnum.nextElement().toString(), "," ) );
}
}
else
reqConditions.fill( new StringTokenizer( reqVal.toString(), "," ) );
/* berprfe, ob fr jeden REQ-Bezeichner ein REQ-Selektor vorhanden ist;
* Und wenn ja, diesem einem Wert zugewiesen wurde.
*/
final Enumeration condEnum = reqConditions.unique().elements();
boolean noError = true;
while( condEnum.hasMoreElements() && noError ) {
final Enumeration selEnum = reqSelectors.elements();
final String currCond = condEnum.nextElement().toString();
while( selEnum.hasMoreElements() && noError ) {
final String selCond = selEnum.nextElement().toString();
if( selCond.equalsIgnoreCase( currCond ) ) {
if( parVal == null || parVal instanceof TKNull
|| ( parVal instanceof String && ((String) parVal).length() == 0 ) ) {
missing.addElement( key );
noError = false;
}
}
}
}
}
}
return missing;
}
/**
* &Uuuml;berprüft, inwiefern alle, als erforderlich gekennzeichneten
* Parameter auch in der Form ausgefüllt wurden.
* Im Fehlerfall wird die Form neu gefüllt und nochmals ausgegeben.
*
* @return true, falls alle als benötigt gekennzeichneten Formularfelder
* auch gefüllt wurden; false sonst.
*/
public boolean checkRequired( final PrintStream out )
throws TKTemplateSyntaxException {
if ( !checkRequired() ) {
printForm( out );
return false;
}
return true;
}
/**
* &Uuuml;berprüft, inwiefern alle, als erforderlich gekennzeichneten
* Parameter auch in der Form ausgefüllt wurden.
*
* @return true, falls alle als benötigt gekennzeichneten Formularfelder
* auch gefüllt wurden; false sonst.
*/
public boolean checkRequired() throws TKTemplateSyntaxException
{
final TKHashtable reqSelectors = getRequiredSelector();
final TKHashtable par = getParams();
final TKVector reqList = new TKVector();
final Enumeration reqKeys = reqSelectors.keys();
while( reqKeys.hasMoreElements() ) {
final Object key = reqKeys.nextElement();
final Object parVal = par.get( key );
if( ! (parVal == null || parVal instanceof TKNull ) ) {
final StringTokenizer selEnum = new StringTokenizer( reqSelectors.get( key ).toString(), "," );
while ( selEnum.hasMoreElements() ) {
reqList.addElement( selEnum.nextElement().toString() );
}
}
}
return checkRequired( reqList.unique() );
}
/**
* &Uuuml;berprüft, inwiefern alle, als erforderlich gekennzeichneten
* Parameter auch in der Form ausgefüllt wurden.
*
* @return true, falls alle als benötigt gekennzeichneten Formularfelder
* auch gefüllt wurden; false sonst.
*/
public boolean checkRequired( TKVector reqSelector ) throws TKTemplateSyntaxException
{
final TKVector missing = checkRequiredParams( reqSelector );
if( !missing.isEmpty() ) {
addErrorParams( missing, REQUIRED );
return false;
}
return true;
}
/**
* Überprüft, ob alle Formularparameter den korrekten Typ
* besitzen. Im Fehlerfall wird die Form neu gefüllt und nochmals ausgegeben.
*
* @return true, falls alle Parameter vom Typ her korrekt sind;
* false, sonst.
*/
public boolean checkType( final PrintStream out )
throws TKTemplateSyntaxException {
if ( !checkType() ) {
printForm( out );
return false;
}
return true;
}
/**
* Überprüft, ob alle Formularparameter den korrekten Typ
* besitzen.
*
* @return true, falls alle Parameter vom Typ her korrekt sind;
* false, sonst.
*/
public boolean checkType()
{
final Hashtable typeHash = getTypes();
final Hashtable valHash = getParams();
final Enumeration parEnum = typeHash.keys();
final TKVector errors = new TKVector();
while ( parEnum.hasMoreElements() ) {
final String parName = (String) parEnum.nextElement();
final String type = (String) typeHash.get( parName );
final Object value = valHash.get( parName );
if ( value == null
|| !( value instanceof String )
|| !formTypes.checkType( (String) value, type ) ) {
errors.addElement( parName );
}
}
if ( !errors.isEmpty() ) {
addErrorParams( errors, TYPE );
return false;
} else {
return true;
}
}
/**
* Werden in der Applikation die Parameter einer Form eingelesen,
* so kann zuerst auf die Korrektheit der Form geprueft werden.
*
* @return true, wenn die Form korrekt ist.
*/
public boolean checkForm( PrintStream out ) throws TKTemplateSyntaxException
{
final boolean req = checkRequired();
final boolean type = checkType();
if ( !( req && type ) ) {
printForm( out );
return false;
} else {
return true;
}
}
/**
* Die leere Form wird ausgegeben, d.h es werden keine
* Parameter zum Template mehr hinzugefgt.
*/
public void printEmptyForm( final PrintStream out ) throws TKTemplateSyntaxException
{
template.doTagSubstitution();
template.doCleanup();
template.printTemplate( out );
}
/**
* Die Form wird samt der Listiteratoren (ERROR, ERROR_TYPE, ERROR_REQ) ausgegeben
*/
public void printForm( final PrintStream out ) throws TKTemplateSyntaxException
{
final TKHashtable params = getParams();
printErrorParams( out );
template.set( params );
printEmptyForm( out );
}
/**
* @see com.teamkonzept.web.TKFormTypes#setLocale
*/
public final void setLocale( final Locale locale ) {
formTypes.setLocale( locale );
}
/**
* @see com.teamkonzept.web.TKFormTypes#setLocale
* @see com.teamkonzept.web.TKFormTypes#setStyle
*/
public final void setLocale( final int style, final Locale locale ) {
formTypes.setLocale( locale );
formTypes.setStyle( style );
}
/**
* setzen einer eignen TKFormTypes-Klasse
*/
public final void setFormTypes( final TKFormTypes formTypes ) {
this.formTypes = formTypes;
}
/**
* @see com.teamkonzept.web.TKFormTypes#setStyle
*/
public final void setStyle( final int style ) {
formTypes.setStyle( style );
}
public final static boolean isEmptyString( final String text ) {
if ( text == null ) {
return true;
}
final int len = text.length();
for ( int i = 0; i < len; i++ ) {
if ( !Character.isWhitespace( text.charAt( i ) ) ) {
return false;
}
}
return true;
}
}
/**
* Implementierung des Interfaces TKListIterator
* In einem Template kann <TK_LIST:ERROR> ... </TK_LIST:ERROR> verwendet
* werden. Zwischen diesen Tags koennen verschiedenen Errormeldungen stehen,
* die in eine Liste aufgenommen werden.
*/
class ErrorListIterator implements TKListIterator {
public static final String ERRORLIST = "ERROR";
protected String listName;
protected Enumeration typeEnum;
protected Hashtable errorList;
protected Enumeration errorEnum;
protected String errorType;
protected TKListIterator primaryIterator;
public ErrorListIterator( final Hashtable errorList, final TKListIterator primaryIterator )
{
this( ERRORLIST, errorList, primaryIterator );
}
public ErrorListIterator( final String errorType,
final Vector errorList, final TKListIterator primaryIterator )
{
this( ERRORLIST + "_" + errorType, buildHash( errorType, errorList ), primaryIterator );
}
private ErrorListIterator( final String listName,
final Hashtable errorList, final TKListIterator primaryIterator )
{
this.listName = listName;
this.primaryIterator = primaryIterator;
this.errorList = errorList;
this.typeEnum = errorList.keys();
this.errorType = (String) typeEnum.nextElement();
this.errorEnum = ((Vector) errorList.get( errorType )).elements();
}
private static final Hashtable buildHash( final String errorType, final Vector errorList )
{
final Hashtable typeList = new Hashtable( 1 );
typeList.put( errorType, errorList );
return typeList;
}
public boolean apply( final TKTemplate template, final int count, final String listName)
{
if( this.listName.equalsIgnoreCase( listName ) ) {
return substitute( template );
} else if( primaryIterator == null ) {
return false;
} else {
return primaryIterator.apply( template, count, listName );
}
}
protected boolean substitute( final TKTemplate template ) {
if ( errorEnum.hasMoreElements() ) {
final String par = (String) errorEnum.nextElement();
template.set( errorType + '_' + par, Boolean.TRUE );
template.set( errorType, par );
return true;
} else if ( typeEnum.hasMoreElements() ) {
errorType = (String) typeEnum.nextElement();
errorEnum = ((Vector) errorList.get( errorType )).elements();
return substitute( template );
} else {
return false;
}
}
}
|