tapestry-user@jakarta.apache.org
[Top] [All Lists]

CSV Renderer Link thingy.. CSV Component donation...

Subject: CSV Renderer Link thingy.. CSV Component donation...
From: Joshua Long
Date: Sat, 05 Mar 2005 03:41:09 -0800
Hi guys

I am donating a CSV component if anyone wants it... when used, it allows
you to render a link that when clicked will return a CSV
(comma-seperated value) dump of a 2 dimensional array that you pass in. 

Interesting sidebar: csv dumps whose first row, and first cell, contain
'ID' (without quotes, in capital letters) will cause Excel on OS X to
freak out and die. 'Id','id',  all work fine.. 

ANYWAY! 

I'll post it somewhere like Tacos eventually,but I'm sure it might stand
some improvement/feedback and I'm somewhat pressed for time.


I'm licensing it under the do-whatever-you-want-with-it-but-remember
your-old-pal-Josh-when-you-win-the-lottery-or-make-cool-changes-to-it
license.


Joshua Long 
josh@xxxxxxxxxxxx 




Code, documentation follow




to get it working int he application, of course, put the following in
the application specification 

    <service name="com.roartechnologies.ap.view.services.csv-service"
class="com.roartechnologies.ap.view.services.CSVService"/>


Anyway, here are the various cogs of the machine... 


/// first the component class.... 

package com.roartechnologies.ap.view.components.csv;

import com.roartechnologies.ap.view.services.CSVService;
import org.apache.tapestry.AbstractComponent;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.engine.IEngineService;
import org.apache.tapestry.engine.ILink;


 /**
  * @author Joshua Long (josh@xxxxxxxxxxxx)
  *
  * Builds a request to our CSVService, which in turn
  * does the heavy lifting of generating
  * the actual dump.
  *
  * This follows a pretty standard idiom 
  * as set forth in <i>Tapestry In Action</i>
  *     
  */
public abstract class CSVComponent extends AbstractComponent {

    public abstract Object getMap();

    public abstract void setMap(Object mp);

    public abstract Boolean getDisabled();

    public abstract void setDisabled(Boolean mp);


    protected void renderComponent(IMarkupWriter writer,
                                   IRequestCycle cycle) {

        if (cycle.isRewinding())
            return;

        Boolean disabled = getDisabled();
        if (disabled != null) {
            if (disabled.booleanValue()) {
                writer.begin("span");
                writer.attribute("class", "csv_disabled");
                renderInformalParameters(writer, cycle);
                writer.printRaw("CSV");
                 writer.end();
                return ;
            }
        }

        Object map = getMap();
        if (null == map)
            Tapestry.createRequiredParameterException(this, "map");


        String key = Long.toString(System.currentTimeMillis());
        cycle.getRequestContext().getSession().setAttribute(key, map);
        IEngineService service =
cycle.getEngine().getService(CSVService.SERVICE_NAME);
        ILink link = service.getLink(cycle, this, new Object[]{key});
        String url = link.getURL();
        writer.begin("a");
        writer.attribute("class", "csv_enabled");
        writer.attribute("href", url);
        renderInformalParameters(writer, cycle);
        writer.printRaw("CSV");

        writer.end();

    }
}











// next the backend service

package com.roartechnologies.ap.view.services;

import com.generationjava.io.CsvWriter;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.engine.AbstractService;
import org.apache.tapestry.engine.IEngineServiceView;
import org.apache.tapestry.engine.ILink;
import org.apache.tapestry.request.RequestContext;
import org.apache.tapestry.request.ResponseOutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.MessageFormat;
import java.util.Date;


/**
 * @author Joshua Long (josh@xxxxxxxxxxxx)
 *         <p/>
 *         The service takes the key passed in from
 *         the component and uses it to lookup the dump
 *         in a known place and then it generates the actual dump.
 *         <p/>
 *         This component uses the <i>Generation Java CSV </i>
 *         component to generate the CSV response stream.
 *         <p/>
 *         I am not too sure where to find it,
 *         but it's worked wonders for me and I completely recommend it.
 */
public class CSVService extends AbstractService {

    public static final String SERVICE_NAME =
            "com.roartechnologies.ap.view.services.csv-service";


    public String getName() {
        return SERVICE_NAME;
    }


    public void service(IEngineServiceView service_view,
                        IRequestCycle cycle,
                        ResponseOutputStream os) throws
ServletException, IOException {
        Object[] params = getParameters(cycle);
        String key = (String) params[0];
        HttpSession session = cycle.getRequestContext().getSession();
        Object mp = session.getAttribute(key);
        if (null == mp) {
            System.out.println(MessageFormat.format("There is no key
with value {0} exiting @ {1,date,long}", new Object[]{key, new
Date()}));
        }
        Object[][] rows_array = (Object[][]) mp;
        RequestContext context = cycle.getRequestContext();
        HttpServletResponse response = context.getResponse();
        String dispositionHeader =
MessageFormat.format("attachment;filename=report_{0}.csv",
                                                        new
Object[]{Long.toString(System.currentTimeMillis())});
        response.setHeader("Content-Disposition", dispositionHeader);
        os.setContentType("application/vnd.ms-excel");
        /* "text/comma-separated-values");*/
        CsvWriter csv_writer = new CsvWriter(new
OutputStreamWriter(os));
        for (int i = 0; i < rows_array.length; i++) {
            Object row [] = rows_array[i];
            String[] string_row = new String[row.length];
            for (int a = 0; a < row.length; a++) {
                string_row[a] = row[a] == null ? "" : row[a].toString();
            }
            csv_writer.writeLine(string_row);
        }
        csv_writer.close();
    }

    public ILink getLink(IRequestCycle iRequestCycle, IComponent
iComponent, Object[] objects) {
        return constructLink(iRequestCycle, SERVICE_NAME, null, objects,
false);
    }
}



















/// now, finally, the specification.. 


<!DOCTYPE component-specification PUBLIC
  "-//Apache Software Foundation//Tapestry Specification 3.0//EN"
  "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd";>

<component-specification
    class="com.roartechnologies.ap.view.components.csv.CSVComponent"
    allow-body="yes"
    allow-informal-parameters="yes">

    <parameter name="map"
        direction="in"
        required="yes"
        type="java.lang.Object"/>
    <parameter name="disabled"
        direction="in"
        required="no"
        type="java.lang.Boolean"/>

    <reserved-parameter name="href"/>
</component-specification>


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@xxxxxxxxxxxxxxxxxx
For additional commands, e-mail: tapestry-user-help@xxxxxxxxxxxxxxxxxx

<Prev in Thread] Current Thread [Next in Thread>