/*
* Created on Jul 21, 2004
*/
package com.openedit.generators;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openedit.repository.ReaderItem;
import com.openedit.Generator;
import com.openedit.OpenEditException;
import com.openedit.OpenEditRuntimeException;
import com.openedit.WebPageRequest;
import com.openedit.page.Page;
import com.openedit.page.PageStreamer;
/**
* TODO: Just make this track a list of generators
* @author Matthew Avery, mavery@einnovation.com
*/
public class CompositeGenerator extends BaseGenerator implements Generator
{
protected List fieldAllGenerators;
private static final Log log = LogFactory.getLog(CompositeGenerator.class);
public CompositeGenerator( )
{
}
protected List getGenerators()
{
if ( fieldAllGenerators == null)
{
fieldAllGenerators =new ArrayList(2);
}
return fieldAllGenerators;
}
public void addGenerator(Generator inGen)
{
if ( inGen == null)
{
throw new OpenEditRuntimeException("No such generator");
}
getGenerators().add(inGen);
}
public void generate( WebPageRequest inContext, Page inPage, Output inOut ) throws OpenEditException
{
PageStreamer pages = inContext.getPageStreamer();
Output old = pages.getOutput(); //They might write out the streamer so we need to capture this
Page resultsThuFar = inPage;
//This class only support String composite generation. No byte[] stuff allowed
Reader content = null;
for (Iterator iter = getGenerators().iterator(); iter.hasNext();)
{
Generator gen = (Generator) iter.next();
content = captureAllOutput(inContext, gen, resultsThuFar);
//make fake page and keep processing
resultsThuFar = new Page( resultsThuFar );
resultsThuFar.setContentItem( new ReaderItem( inPage.getPath(), content, inPage.getCharacterEncoding() ) );
}
try
{
pages.setOutput(old);
getOutputFiller().fill(content,inOut.getWriter());
// inOut.getWriter().write(content);
inOut.getWriter().flush();
}
catch (IOException ex)
{
log.error( ex );
}
}
protected Reader captureAllOutput(WebPageRequest inContext, Generator inGen, Page inResultsThuFar ) throws OpenEditException
{
//We have to replace the streamer with one that has our context and writer
//Cant copy because the action are editing the parent version
WebPageRequest copy = inContext.copy();
//This allows the $pages.stream method to keep working with our fake output
PageStreamer streamer = inContext.getPageStreamer().copy();
//allows capture of any output on our tmp streamer
ByteArrayOutputStream scapture = new ByteArrayOutputStream();
Writer capture = null;
try
{
capture = new OutputStreamWriter(scapture, inResultsThuFar.getCharacterEncoding() );
Output out = new Output(capture, scapture );
streamer.setOutput(out);
copy.putPageStreamer(streamer);
streamer.setWebPageRequest(copy);
//kicks the proces off without running any actions again
inGen.generate( copy, inResultsThuFar , out);
capture.flush();
//String value = scapture.toString(inResultsThuFar.getCharacterEncoding());
//return value;
//Need a way to pull data from generators?
return new InputStreamReader(new ByteArrayInputStream(scapture.toByteArray()),inResultsThuFar.getCharacterEncoding());
}
catch (IOException ex)
{
throw new OpenEditException(ex);
}
}
public boolean canGenerate(WebPageRequest inReq)
{
for (Iterator iter = getGenerators().iterator(); iter.hasNext();)
{
Generator gen = (Generator) iter.next();
if ( !gen.canGenerate( inReq ))
{
return false;
}
}
return true;
}
public void setGenerators(List inMorefound)
{
fieldAllGenerators = inMorefound;
}
public boolean contains(Generator inClass)
{
return getGenerators().contains(inClass);
}
public boolean hasGenerator(Generator inChild)
{
if( inChild == this )
{
return true;
}
for (Iterator iter = getGenerators().iterator(); iter.hasNext();)
{
Generator gen = (Generator) iter.next();
if ( gen.hasGenerator(inChild))
{
return true;
}
}
return false;
}
}