20-Jul-04 (Created: 20-Jul-04) | More in 'OSCON-2004'

Generic Transformations Pattern: Code Examples

Consider the following URL definition

Defines data and transformation for this page


<url name="page1URL">
   <transform requestName="page1TransformRequest"/>
   <data requestName="page1DataRequest"/>
</url>

Specifying a page specific transform


<request name="page1TransformRequest" classname="com.ai.jsp.JSPTransform">
   <includeOrForward>include</includeOrForward>
   <jsp-url>/jsp/page1.jsp</jsp-url>
</request>

This is called page specific transform because a jsp page called "page1.jsp" is used. Without that it won't work.

How to specify a generic transform on the url

You can add an additional argument to the incoming url: aspire_output_format=classic-xml. The controller servlet will resolve this to a generic transform using the following look up


<generic-transform name="classic-xml">
   <request-name>GenClassicXMLRequest</request-name>
</generic-transform> 

<request name="GenClassicXMLRequest">
   <classname>com.ai.xml.GenericXMLTransform</classname>
   <content-type>text/xml</content-type>
</request>

How is generic transform defined


public interface IGenericTransform
{
    public void transform(ihds data, PrintWriter out) throws TransformException;
}

Given an "hds" provide a transformation and send it to the output stream. There is no template that is passed. Although this technique can be used to paint individual pages, the specific transform is more appropriate as the target page is not specified on the URL but in the configuration.

An excel generic transform


public class ExcelGenericTransform 
      extends AHttpGenericTransform 
      implements IFormHandlerTransform 
{
    private static String s_separator = "\t";
   
   //virtual method from AHttpGenericTransform
    protected String getDerivedHeaders(HttpServletRequest request)
    {
        return "Content-Type=application/vnd.ms-excel
		     |Content-Disposition=filename=aspire-hierarchical-dataset.xls";
    }
    public void transform(ihds data, PrintWriter out) 
	    throws TransformException
    {
        staticTransform(data,out);
    }
    public void transform(IFormHandler data, PrintWriter out) 
		throws TransformException
    {
        staticTransform((ihds)data,out);
    }
    public static void staticTransform(ihds data, PrintWriter out)
		throws TransformException
    {
        try
        {
            writeALoop("MainData",data,out,"");
        }
        catch(DataException x)
        {
            throw new TransformException(
				"Error: ExcelGenericTransform: Data Exception",x);
        }
    }
    private static void writeALoop(String loopname, 
						ihds data, PrintWriter out, String is)
            throws DataException
    {
        println(out,is, ">> Writing data for loop:" + loopname);

        // write metadata
        IMetaData m = data.getMetaData();
        IIterator columns = m.getIterator();

        StringBuffer colBuffer = new StringBuffer();
        for(columns.moveToFirst();!columns.isAtTheEnd();columns.moveToNext())
        {
            String columnName = (String)columns.getCurrentElement();
            colBuffer.append(columnName).append(s_separator);
        }
        println(out,is,colBuffer.toString());

        //write individual rows
        for(data.moveToFirst();!data.isAtTheEnd();data.moveToNext())
        {
            StringBuffer rowBuffer = new StringBuffer();
            for(columns.moveToFirst();!columns.isAtTheEnd();columns.moveToNext())
            {
                String columnName = (String)columns.getCurrentElement();
                rowBuffer.append(data.getValue(columnName));
                rowBuffer.append(s_separator);
            }
            println(out,is,rowBuffer.toString());

            // recursive call to print children
            IIterator children = data.getChildNames();
            for(children.moveToFirst();!children.isAtTheEnd();children.moveToNext())
            {
                //for each child
                String childName = (String)children.getCurrentElement();
                ihds child = data.getChild(childName);
                writeALoop(childName,child,out,is + "\t");
            }//for each child
        }// for each row

        data.close();
        println(out,is,">> Writing data for loop:" + loopname + " is complete");
    }//eofc
    private static void println(PrintWriter out, 
					String indentationString, String line)
    {
        out.print(indentationString);
        out.print(line);
        out.print("\n");
    }
}

A language transform


public class JavaClassGenericTransform 
      extends AHttpGenericTransform 
{
   //virtual method from AHttpGenericTransform
    protected String getDerivedHeaders(HttpServletRequest request)
    {
        return "Content-Type=html/text";
    }
    public void transform(ihds data, PrintWriter out) 
		throws TransformException
    {
      //Write out Java class definitions based on the metadata in "ihds"
    }
}

References

1. General Introduction to other Server side Patterns in this series

2. OSCON 2004 Summary page for Server side patterns session

3. Abstract Page Data Pattern: Code Examples