Listing 1: DocumentBuilder

package mypackage;


import java.util.StringTokenizer;

public abstract class DocumentBuilder {
    
    private String template;
    private String openDelim = "{";
    private String closeDelim = "}";
    
    public DocumentBuilder(String template){
        this.template = template;
    }
    
    /**
     * returns String value representing data associated with field code
     **/
    protected abstract String getValue(String fieldCode);
    
    /**
     * returns the String that represents the start of a field
     * code in a document template (default is '{')
     **/
    protected String getOpenDelimiter(){
        return openDelim;
    }
    
    /**
     * returns the String that represents the end of a field
     * code in a document template (default is '}')
     **/
    protected String getCloseDelimiter(){
        return closeDelim;
    }
    

    /**
     * allows sub-class to modify the open Delimiter
     * @see getOpenDelimiter
     **/
    protected void setOpenDelimiter(String openDelim){
        this.openDelim = openDelim;   
    }
    
    /**
     * allows sub-class to modify the close Delimiter
     * @see getCloseDelimiter
     **/
    protected void setCloseDelimiter(String closeDelim){
        this.closeDelim = closeDelim;   
    }
    
    /**
     * Invokes the construction of the document based on the
     * template provided, and the current values that are
     * returned from the <code>getValue(String code)</code> method
     * @see getValue()
     **/
    public String buildDocument(){
        StringBuffer ret = new StringBuffer();
        String delimiters = getOpenDelimiter() + getCloseDelimiter();
        StringTokenizer tkn = new StringTokenizer(template, delimiters,
                                                  true);
        String token;
        String value;
        boolean fieldPending = false;
       
       
        // we use a StringTokenizer to parse our template into
        // chunks of text, and field codes.  let's iterate through it
        // in replace the field codes with data.
        while(tkn.hasMoreTokens()){
            token = tkn.nextToken();            
                        
            if(delimiters.indexOf(token)==-1){
                // not a delimiter - are we expecting a field?
                if(fieldPending){
                    // hold value in temp String variable
                    value = getValue(token);
                    if(value!=null){
                        // found value - put in StringBuffer
                        ret.append(value);
                    } else {
                        // couldn't find value - put field code back in 
                        // String the way we found it
                        ret.append(getOpenDelimiter());
                        ret.append(token);
                        ret.append(getCloseDelimiter());
                    }
                } else {
                    // this token contains non field code text.  
                    // put back in String
                    ret.append(token);
                }
                
            } else {
                // we are either at an open Delimiter
                // or a close delimiter.  toggle fieldPending flag.
                fieldPending = !fieldPending;
            }
        }
        return ret.toString();
    }
}
— End of Listing —