I am tinkering with the way the FO tree is constructed.  I thought I 
would post what I am doing for Karen to look at, as she mentioned the 
possibility of doing some property resolution as the FO tree was built.

As I mentioned in an earlier post, I am looking at the possibility of 
opening up the construction phase of the FO parse.  I am uncomfortable 
with the black-box approach to parsing that tends to come with the 
call-back model.  The input tree must have certain structural 
constraints which have to be recognized in the code somewhere, so why 
not at the point of FO tree construction?

To accommodate this, I have serialized the parse events.  The parser is 
run in a thread with its own ContentHandler, which simply generates 
instances of Q&D data class XMLEvent.  Q&D because the simple internal 
data elements of XMLEvent are visible.  The tree builder then asks for 
events and reacts accordingly.  There is no actual tree builder as yet - 
just the beginnings of a skeleton.  I am looking at the property 
handling now to see how much of it I need to be able to build the tree.

I have been chopping away at the startup code to get an experimental 
harness together, and I attach the mangled bits.  I have a copy of the 
CVS tree which I have been butchering, so I am not even sure of how big 
a subset of the tree I need to compile the harness.  If anyone is 
interested I can isolate it from the bulk of the code.

It is all very procedural, I'm afraid.  But then, near as I can make 
out, Java is a procedural language.

Peter
-- 
Peter B. West  [EMAIL PROTECTED]  http://powerup.com.au/~pbwest
"Lord, to whom shall we go?"
/** * XMLEventSource.java * * * Created: Sat Aug 11 17:18:55 2001 * * @author * @version $Id: XMLEventSource.java,v 1.4 2001-08-19 04:48:58+10 pbw Exp pbw $ */ package org.apache.fop.fo; import org.apache.fop.apps.FOPException; import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.XMLReader; import org.xml.sax.InputSource; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import java.io.IOException; import java.lang.IllegalArgumentException; import java.util.NoSuchElementException; /** * XMLEventSource serializes a stream of XML parser events. It * sets up an XMLReader, and provides a ContentHandler which * buffers the parse events arriving at each of the callback methods of the * ContentHandler. * * The XMLReader is run in a separate thread, which blocks when the * buffer for the stream of parse events is full. Draining the events from the * buffer releases the block on the XMLReader. */ public class XMLEventSource implements Runnable { public static final int NOEVENT = 0; public static final int STARTDOCUMENT = 1; public static final int ENDDOCUMENT = 2; public static final int STARTELEMENT = 3; public static final int ENDELEMENT = 4; public static final int CHARACTERS = 5; private static final int MIN_XML_EV_TYPE = NOEVENT; private static final int MAX_XML_EV_TYPE = CHARACTERS; private CircularBuffer events; private XMLReader parser; private InputSource document; private XMLSerialHandler serialHandler; private Thread parserThread; public XMLEventSource (XMLReader parser, InputSource document) { Thread sourceThread = Thread.currentThread(); this.parser = parser; this.document = document; events = new CircularBuffer(); // Set up the content handler serialHandler = new XMLSerialHandler(events); parser.setContentHandler(serialHandler); parserThread = new Thread(this, "XMLCallbackHandler"); parserThread.setDaemon(true); parserThread.start(); // Start the callback parser thread } /** * This is the run method for the callback parser thread. */ public void run() { // I''m in the thread - run the parser try { parser.parse(document); } catch (SAXException e) { throw new RuntimeException(e.getMessage()); } catch (IOException e) { throw new RuntimeException(e.getMessage()); } } /* * Methods to return XML parse events on demand */ /** * getevent returns the next XML parser event. * @return XMLEvent the next event from the XML parser. */ public XMLEvent getEvent() { synchronized (events) { XMLEvent ev; //System.out.println("getEvent "+Thread.currentThread().getName()); while (parserThread.isAlive() && events.isEmpty()) { try { events.wait(); } catch (InterruptedException e) { } } try { ev = (XMLEvent)events.get(); } catch (NoSuchElementException e) { // Something has gone wrong with the parser - // return a null event ev = null; } // end of try-catch if (events.isEmpty()) events.notifyAll(); //System.out.println(ev.type+" "+ev.qName); return ev; } } public boolean getEndDocument(XMLEvent ev) throws FOPException { ev = getEvent(); while (ev != null && ev.type != ENDDOCUMENT) { ev = getEvent(); } if (ev == null) { throw new FOPException("EndDocument not found."); } return true; } public boolean getStartElement(XMLEvent ev) throws FOPException { ev = getEvent(); while (ev != null && ev.type != STARTELEMENT) { ev = getEvent(); } if (ev == null) { throw new FOPException("StartElement not found."); } return true; } public boolean getStartElement(XMLEvent ev, String qName) throws FOPException { ev = getEvent(); while (ev != null && ! (ev.type == STARTELEMENT && ev.qName.equals(qName))) { ev = getEvent(); } if (ev == null) { throw new FOPException("StartElement "+ qName + " not found."); } return true; } public boolean getEndElement(XMLEvent ev, String qName) throws FOPException { ev = getEvent(); while (ev != null && ! (ev.type == ENDELEMENT && ev.qName.equals(qName))) { ev = getEvent(); } if (ev == null) { throw new FOPException("EndElement "+ qName + " not found."); } return true; } /** * XMLSerialHandler is the ContentHandler for the * background XMLReader thread. */ public class XMLSerialHandler extends DefaultHandler { private CircularBuffer events; private XMLEvent event; /** * XMLSerialHandler constructor requires one argument. * @param events a CircularBuffer object. */ public XMLSerialHandler(CircularBuffer events) { this.events = events; synchronized (events) { event = (XMLEvent) events.oldest(); if (event == null) { event = new XMLEvent(); } } } /** * drainEvent is the common method used by all of the * XMLSerialHandler callback methods to secrete the * new event into the CircularBuffer and to manage the * synchronization with the buffer reader. * @exception NoSuchElementException is thrown if the * CircularBuffer is full. */ private void drainEvent() throws NoSuchElementException { events.put((Object) event); // If the buffer is full, or if this is a terminating event, // notify the serial event reader that something is available if (events.isFull() || event.type == ENDDOCUMENT) { events.notifyAll(); // All of the callback methods call this internally to block // until the events they have buffered have been read while ( ! events.isEmpty()) { try { // Wait for the consumer events.wait(); } catch (InterruptedException e) { } } } // end of if (events.isFull() || event.type == ENDDOCUMENT) event = (XMLEvent) events.oldest(); if (event == null) { event = new XMLEvent(); } } public void startDocument() throws NoSuchElementException { synchronized (events) { //System.out.println("StartDocument thread " //+ Thread.currentThread().getName()); event.type = STARTDOCUMENT; drainEvent(); } } public void endDocument() throws NoSuchElementException { synchronized (events) { //System.out.println("EndDocument thread " //+ Thread.currentThread().getName()); event.type = ENDDOCUMENT; drainEvent(); } } public void startElement(String uri, String localName, String qName, Attributes attributes) throws NoSuchElementException { synchronized (events) { //System.out.println("StartElement thread " //+ Thread.currentThread().getName()); event.type = STARTELEMENT; event.uri = uri; event.localName = localName; event.qName = qName; event.attributes = attributes; drainEvent(); } } public void endElement(String uri, String localName, String qName) throws NoSuchElementException { synchronized (events) { //System.out.println("EndElement thread " //+ Thread.currentThread().getName()); event.type = ENDELEMENT; event.uri = uri; event.localName = localName; event.qName = qName; drainEvent(); } } public synchronized void characters(char[] ch, int start, int length) throws NoSuchElementException { synchronized (events) { //System.out.println("characters thread " //+ Thread.currentThread().getName()); event.type = CHARACTERS; event.chars = new String(ch, start, length); drainEvent(); } } } /** * This is a data class to encapsulate the data of an individual XML * parse event. The current version, while defining accessor methods, * leaves the component data of the event as public. The * XMLSerialHandler methods set the values directly. I''m * sure this is Very Bad. */ public static class XMLEvent { // These are made public specifically so the the values of individual // XMLEvent instances can be changed directly, on the assumption that // the basic XML events are unlikely to change. public int type = NOEVENT; public String chars; public String uri; public String localName; public String qName; public Attributes attributes; /** * The no-argument constructor uses the default initialization values * of the data members: NOEVENT for the event type, and null references * for all others. */ public XMLEvent() {} /** * The fully defined constructor takes values for each of the data * elements. */ public XMLEvent(int type, String chars, String uri, String localName, String qName, Attributes attributes) { this.type = type; this.chars = chars; this.uri = uri; this.localName = localName; this.qName = qName; this.attributes = attributes; } /** * The cloning constructor takes a reference to an existing * XMLEvent object. */ public XMLEvent(XMLEvent ev) { type = ev.type; chars = ev.chars; uri = ev.uri; localName = ev.localName; qName = ev.qName; attributes = ev.attributes; } public int getType() { return type; } public void setType(int type) { if (type < MIN_XML_EV_TYPE || type > MAX_XML_EV_TYPE) { throw new IllegalArgumentException( "XML event type out of range."); } this.type = type; } public String getChars() { return chars; } public void setChars(String chars) { this.chars = chars; } public void setChars(char[] ch, int start, int length) { chars = new String(ch, start, length); } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public String getLocalName() { return localName; } public void setLocalName(String localName) { this.localName = localName; } public String getQName() { return qName; } public void setQName(String QName) { this.qName = qName; } public Attributes getAttributes() { return attributes; } public void setAttributes(Attributes attributes) { this.attributes = attributes; } } /** * A general circular buffer class. It stores and returns Object * references. */ public static class CircularBuffer { private final static int DEFAULTBUFSIZE = 32; private Object[] buf; private int size = 0; private int getptr = 0; private int putptr = 0; /** * Constructor taking a single argument; the size of the buffer. * The size must be a power of 2, and the constructor throws an * IllegalArgumentException if this condition is violated. */ public CircularBuffer(int size) throws IllegalArgumentException { // Ensure this is a power of 2 if (size < 2 || ((size & (size - 1)) != 0)) { throw new IllegalArgumentException( "CircularBuffer size must be power of 2"); } buf = new Object[size]; this.size = size; } /** * No-argument constructor sets up a buffer with the default number of * elements (32). */ public CircularBuffer() throws IllegalArgumentException { this(DEFAULTBUFSIZE); } public boolean isFull() { return (putptr + 1 & size - 1) == getptr; } public boolean isEmpty() { return putptr == getptr; } /** * get returns the next object from the buffer. * Throws a NoSuchElementException if the buffer is empty. */ public Object get() throws NoSuchElementException { if (isEmpty()) { throw new NoSuchElementException( "CircularBuffer is empty."); } int tmpptr = getptr++; getptr &= size - 1; return buf[tmpptr]; } /** * put adds an object to the buffer. * Throws a NoSuchElementException if the buffer is full. */ public void put(Object thing) { if (isFull()) { throw new NoSuchElementException( "CircularBuffer is full."); } buf[putptr++] = thing; putptr &= size - 1; } /** * oldest returns the next object that will be overwritten * by a put. If the buffer is full, returns null. */ public Object oldest() { if (isFull()) { return null; } return buf[putptr]; } } }// XMLEventSource
/*
 * $Id: Driver.java,v 1.5 2001-08-19 04:42:54+10 pbw Exp pbw $
 * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
 * For details on use and redistribution please refer to the
 * LICENSE file included with these sources.
 */

package org.apache.fop.apps;

// FOP
import org.apache.fop.fo.FOTreeBuilder;
import org.apache.fop.fo.XMLEventSource;
import org.apache.fop.fo.XMLEventSource.XMLEvent;

import org.apache.fop.fo.ElementMapping;
import org.apache.fop.layout.AreaTree;
import org.apache.fop.render.Renderer;
import org.apache.fop.messaging.MessageHandler;
import org.apache.fop.configuration.ConfigurationReader;
import org.apache.fop.configuration.Configuration;
import org.apache.fop.tools.DocumentInputSource;
import org.apache.fop.tools.DocumentReader;

import org.apache.fop.render.pdf.PDFRenderer;

import org.apache.fop.system.BufferManager;

// DOM
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Attr;

// SAX
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

// Java
import java.io.*;
import java.util.*;

public class Driver {

    /**
     * Render to PDF. OutputStream must be set
     */
    public static final int RENDER_PDF = 1;

    /**
     * the FO tree builder
     */
    private FOTreeBuilder _treeBuilder;

    /**
     * the renderer to use to output the area tree
     */
    private Renderer _renderer;

    /**
     * the source of the FO file
     */
    private InputSource _source;

    /**
     * the stream to use to output the results of the renderer
     */
    private OutputStream _stream;

    /**
     * The XML parser to use when building the FO tree
     */
    private XMLReader _reader;

    XMLEventSource eventSource;
    XMLEvent event;

    /**
     * If true, full error stacks are reported
     */
    private boolean _errorDump = false;

    public static final String getParserClassName() {
        String parserClassName = null;
        try {
            parserClassName = System.getProperty("org.xml.sax.parser");
        } catch (SecurityException se) {}

        if (parserClassName == null) {
            parserClassName = "org.apache.xerces.parsers.SAXParser";
        }
        return parserClassName;
    }

    /**
     * create a new Driver
     */
    public Driver() {
        _stream = null;
        ///_bufferManager = new BufferManager();
        _treeBuilder = new FOTreeBuilder();
        ///_treeBuilder.setBufferManager(_bufferManager);
        ///setupDefaultMappings();
    }

    public Driver(InputSource source, OutputStream stream) {
        this();
        _source = source;
        _stream = stream;
    }


    /**
     * Set the error dump option
     * @param dump if true, full stacks will be reported to the error log
     */
    public void setErrorDump(boolean dump) {
        _errorDump = dump;
    }

    /**
     * Set the OutputStream to use to output the result of the Renderer
     * (if applicable)
     * @param stream the stream to output the result of rendering to
     *
     */
    public void setOutputStream(OutputStream stream) {
        _stream = stream;
    }

    /**
     * Set the source for the FO document. This can be a normal SAX
     * InputSource, or an DocumentInputSource containing a DOM document.
     * @see DocumentInputSource
     */
    public void setInputSource(InputSource source) {
        _source = source;
    }

    /**
     * Sets the reader used when reading in the source. If not set,
     * this defaults to a basic SAX parser.
     */
    public void setXMLReader(XMLReader reader) {
        _reader = reader;
    }


    /**
     * Set the rendering type to use. Must be one of
     * <ul>
     * <li>RENDER_PDF
     * <li>RENDER_AWT
     * <li>RENDER_MIF
     * <li>RENDER_XML
     * <li>RENDER_PCL
     * <li>RENDER_PS
     * <li>RENDER_TXT
     * </ul>
     * @param renderer the type of renderer to use
     */
    public void setRenderer(int renderer) throws IllegalArgumentException {
        switch (renderer) {
        case RENDER_PDF:
            setRenderer(new org.apache.fop.render.pdf.PDFRenderer());
            break;
        default:
            throw new IllegalArgumentException("Unknown renderer type");
        }

    }

    /**
     * Set the Renderer to use
     * @param renderer the renderer instance to use
     */
    public void setRenderer(Renderer renderer) {
        _renderer = renderer;
    }

    public Renderer getRenderer() {
        return _renderer;
    }

    /**
     * @deprecated use renderer.setProducer(version) + setRenderer(renderer) or just 
setRenderer(renderer_type) which will use the default producer string.
     * @see #setRenderer(int)
     * @see #setRenderer(Renderer)
     */
    public void setRenderer(String rendererClassName, String version) {
        setRenderer(rendererClassName);
    }

    /**
     * Set the class name of the Renderer to use as well as the
     * producer string for those renderers that can make use of it.
     * @param rendererClassName classname of the renderer to use such as
     * "org.apache.fop.render.pdf.PDFRenderer"
     * @exception IllegalArgumentException if the classname was invalid.
     * @see #setRenderer(int)
     */
    public void setRenderer(String rendererClassName)
    throws IllegalArgumentException {
        try {
            _renderer =
                (Renderer)Class.forName(rendererClassName).newInstance();
            _renderer.setProducer(Version.getVersion());
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("Could not find "
                                               + rendererClassName);
        }
        catch (InstantiationException e) {
            throw new IllegalArgumentException("Could not instantiate "
                                               + rendererClassName);
        }
        catch (IllegalAccessException e) {
            throw new IllegalArgumentException("Could not access "
                                               + rendererClassName);
        }
        catch (ClassCastException e) {
            throw new IllegalArgumentException(rendererClassName
                                               + " is not a renderer");
        }
    }


    /**
     * Returns the tree builder (a SAX ContentHandler).
     *
     * Used in situations where SAX is used but not via a FOP-invoked
     * SAX parser. A good example is an XSLT engine that fires SAX
     * events but isn't a SAX Parser itself.
     */
    public ContentHandler getContentHandler() {
        return _treeBuilder;
    }


    /**
     * Dumps an error
     */
    public void dumpError(Exception e) {
        if (_errorDump) {
            if (e instanceof SAXException) {
                e.printStackTrace();
                if (((SAXException)e).getException() != null) {
                    ((SAXException)e).getException().printStackTrace();
                }
            } else if (e instanceof FOPException) {
                e.printStackTrace();
                if (((FOPException)e).getException() != null) {
                    ((FOPException)e).getException().printStackTrace();
                }
            } else {
                e.printStackTrace();
            }
        }
    }


    /**
     * Runs the formatting and renderering process using the previously set
     * inputsource and outputstream
     */
    public synchronized void run() throws IOException, FOPException {
        if (_renderer == null) {
            setRenderer(RENDER_PDF);
        }

        if (_source == null) {
            throw new FOPException("InputSource is not set.");
        }

        if (_reader == null) {
            if (!(_source instanceof DocumentInputSource)) {
                _reader = ConfigurationReader.createParser();
            }
        }
        /* ---
        if (_source instanceof DocumentInputSource) {
            render(((DocumentInputSource)_source).getDocument());
        } else {
            render(_reader, _source);
        }
        */ /* --- */
    }

    public void parseFO(XMLReader parser, InputSource source) 
                        throws FOPException {
        eventSource = new XMLEventSource(parser, source);

        //event = eventSource.getEvent();
        //System.out.println("Got the first event");
        
        // Flush the STARTDOCUMENT event
        // if this is not present the parser will throw an exception
        eventSource.getStartElement(event, "fo:root");

        processRoot();
        eventSource.getEndDocument(event);
    }

    public void processRoot() throws FOPException {
        System.out.println("processRoot");
        processLayoutMasterSet();
        processFODeclarations();
        // while pagesequences remain
        // processPageSequence();
    }

    public void processLayoutMasterSet() {
        
    }

    public void processFODeclarations() {
    }
}

/*
 * $Id: CommandLineStarter.java,v 1.4 2001-08-19 04:51:45+10 pbw Exp pbw $
 * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
 * For details on use and redistribution please refer to the
 * LICENSE file included with these sources.
 */

package org.apache.fop.apps;

// SAX
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

// Java
import java.io.*;
import java.net.URL;


// FOP
import org.apache.fop.messaging.MessageHandler;
import org.apache.fop.configuration.Configuration;

/**
 * super class for all classes which start Fop from the commandline
 *
 * Modified to use new streaming API by Mark Lillywhite, [EMAIL PROTECTED]
 */

public class CommandLineStarter extends Starter {

    CommandLineOptions commandLineOptions;
    boolean errorDump;

    public CommandLineStarter(CommandLineOptions commandLineOptions)
    throws FOPException {
        this.commandLineOptions = commandLineOptions;
        options.setCommandLineOptions(commandLineOptions);
        errorDump = Configuration.getBooleanValue("debugMode").booleanValue();
        super.setInputHandler(commandLineOptions.getInputHandler());
    }

    /**
     * Run the format.
     * @exception FOPException if there is an error during processing
     */
    public void run() throws FOPException {
        String version = Version.getVersion();
        MessageHandler.logln(version);

        XMLReader parser = inputHandler.getParser();
        setParserFeatures(parser);

        Driver driver = new Driver();
        ///driver.setBufferFile(commandLineOptions.getBufferFile());

        if (errorDump) {
            driver.setErrorDump(true);
        }

        try {
            driver.setRenderer(commandLineOptions.getRenderer());
            driver.setOutputStream(new 
FileOutputStream(commandLineOptions.getOutputFile()));
            driver.parseFO(parser, inputHandler.getInputSource());
            System.exit(0);
        } catch (Exception e) {
            if (e instanceof FOPException) {
                throw (FOPException)e;
            }
            throw new FOPException(e);
        }
    }

}

/*
 * $Id: CommandLineOptions.java,v 1.4 2001-08-19 05:00:16+10 pbw Exp pbw $
 * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
 * For details on use and redistribution please refer to the
 * LICENSE file included with these sources.
 */

package org.apache.fop.apps;

// java
import java.util.Vector;
import java.io.File;
import java.io.FileNotFoundException;

// FOP
import org.apache.fop.messaging.MessageHandler;
import org.apache.fop.configuration.Configuration;
import org.apache.fop.apps.FOPException;

/**
 * Options parses the commandline arguments
 */
public class CommandLineOptions {

    /* input / output not set */
    private static final int NOT_SET = 0;
    /* input: fo file */
    private static final int FO_INPUT = 1;
    /* input: xml+xsl file */
    private static final int XSLT_INPUT = 2;
    /* output: pdf file */
    private static final int PDF_OUTPUT = 1;

    /* use debug mode */
    Boolean errorDump = new Boolean(false);
    /* show configuration information */
    Boolean dumpConfiguration = new Boolean(false);
    /* suppress any progress information */
    Boolean quiet = new Boolean(false);
    /* for area tree XML output, only down to block area level */
    Boolean suppressLowLevelAreas = new Boolean(false);
    /* name of user configuration file */
    File userConfigFile = null;
    /* name of input fo file */
    File fofile = null;
    /* name of xsltfile (xslt transformation as input) */
    File xsltfile = null;
    /* name of xml file (xslt transformation as input) */
    File xmlfile = null;
    /* name of output file */
    File outfile = null;
    /* name of buffer file */
    File bufferFile = null;
    /* input mode */
    int inputmode = NOT_SET;
    /* output mode */
    int outputmode = NOT_SET;
    /* buffer mode */
    int buffermode = NOT_SET;
    /* language for user information */
    String language = null;

    private java.util.Hashtable rendererOptions;

    public CommandLineOptions(String[] args)
            throws FOPException, FileNotFoundException {
        rendererOptions = new java.util.Hashtable();
        try {
            parseOptions(args);
            checkSettings();
            if (errorDump != null && errorDump.booleanValue()) {
                debug();
            }
        } catch (FOPException e) {
            printUsage();
            throw e;
        } catch (java.io.FileNotFoundException e) {
            printUsage();
            throw e;
        }

    }

    /**
     * parses the commandline arguments
     * @return true if parse was successful and procesing can continue, false if 
processing should stop
     * @exception FOPException if there was an error in the format of the options
     */
    private void parseOptions(String args[]) throws FOPException {
        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-d") || args[i].equals("--full-error-dump")) {
                errorDump = new Boolean(true);
            } else if (args[i].equals("-fo")) {
                inputmode = FO_INPUT;
                if ((i + 1 == args.length)
                        || (args[i + 1].charAt(0) == '-')) {
                    throw new FOPException("you must specify the fo file for the '-fo' 
option");
                } else {
                    fofile = new File(args[i + 1]);
                    i++;
                }
            } else if (args[i].equals("-pdf")) {
                setOutputMode(PDF_OUTPUT);
                if ((i + 1 == args.length)
                        || (args[i + 1].charAt(0) == '-')) {
                    throw new FOPException("you must specify the pdf output file");
                } else {
                    outfile = new File(args[i + 1]);
                    i++;
                }
            } else if (args[i].charAt(0) != '-') {
                if (inputmode == NOT_SET) {
                    inputmode = FO_INPUT;
                    fofile = new File(args[i]);
                } else if (outputmode == NOT_SET) {
                    outputmode = PDF_OUTPUT;
                    outfile = new File(args[i]);
                } else {
                    throw new FOPException("Don't know what to do with "
                                           + args[i]);
                }
            } else {
                throw new FOPException("Don't know what to do with "
                                       + args[i]);
            }
        }
    }    // end parseOptions

    private void setOutputMode(int mode) throws FOPException {
        if (outputmode == NOT_SET) {
            outputmode = mode;
        } else {
            throw new FOPException("you can only set one output method");
        }
    }

    /**
     * checks whether all necessary information has been given in a consistent way
     */
    private void checkSettings() throws FOPException, FileNotFoundException {
        if (inputmode == NOT_SET) {
            throw new FOPException("No input file specified");
        }

        if (outputmode == NOT_SET) {
            throw new FOPException("No output file specified");
        }

        if (inputmode == XSLT_INPUT) {
            // check whether xml *and* xslt file have been set
            if (xmlfile == null) {
                throw new FOPException("XML file must be specified for the tranform 
mode");
            }
            if (xsltfile == null) {
                throw new FOPException("XSLT file must be specified for the tranform 
mode");
            }

            // warning if fofile has been set in xslt mode
            if (fofile != null) {
                MessageHandler.errorln("WARNING: Can't use fo file with transform 
mode! Ignoring.\n"
                                       + "Your input is " + "\n xmlfile: "
                                       + xmlfile.getAbsolutePath()
                                       + "\nxsltfile: "
                                       + xsltfile.getAbsolutePath()
                                       + "\n  fofile: "
                                       + fofile.getAbsolutePath());
            }
            if (!xmlfile.exists()) {
                throw new FileNotFoundException("xml file "
                                                + xmlfile.getAbsolutePath()
                                                + " not found ");
            }
            if (!xsltfile.exists()) {
                throw new FileNotFoundException("xsl file "
                                                + xsltfile.getAbsolutePath()
                                                + " not found ");
            }

        } else if (inputmode == FO_INPUT) {
            if (xmlfile != null || xsltfile != null) {
                MessageHandler.errorln("WARNING: fo input mode, but xmlfile or xslt 
file are set:");
                MessageHandler.errorln("xml file: " + xmlfile.toString());
                MessageHandler.errorln("xslt file: " + xsltfile.toString());
            }
            if (!fofile.exists()) {
                throw new FileNotFoundException("fo file "
                                                + fofile.getAbsolutePath()
                                                + " not found ");
            }

        }
    }    // end checkSettings

    /**
     * returns the chosen renderer, throws FOPException
     */
    public int getRenderer() throws FOPException {
        switch (outputmode) {
        case NOT_SET:
            throw new FOPException("Renderer has not been set!");
        case PDF_OUTPUT:
            return Driver.RENDER_PDF;
        default:
            throw new FOPException("Invalid Renderer setting!");
        }
    }

    /**
     *
     */
    public InputHandler getInputHandler() {
        switch (inputmode) {
        case FO_INPUT:
            return new FOInputHandler(fofile);
        default:
            return new FOInputHandler(fofile);
        }
    }

    public java.util.Hashtable getRendererOptions() {
        return rendererOptions;
    }

    public Starter getStarter() throws FOPException {
        switch (outputmode) {

        default:
            return new CommandLineStarter(this);
        }
    }

    public int getInputMode() {
        return inputmode;
    }

    public int getOutputMode() {
        return outputmode;
    }

    public File getFOFile() {
        return fofile;
    }

    public File getXMLFile() {
        return xmlfile;
    }

    public File getXSLFile() {
        return xsltfile;
    }

    public File getOutputFile() {
        return outfile;
    }

    public File getUserConfigFile() {
        return userConfigFile;
    }

    public String getLanguage() {
        return language;
    }

    public File getBufferFile() {
        return bufferFile;
    }

    public Boolean isQuiet() {
        return quiet;
    }

    public Boolean dumpConfiguration() {
        return dumpConfiguration;
    }

    public Boolean isDebugMode() {
        return errorDump;
    }

    public Boolean isCoarseAreaXml() {
        return suppressLowLevelAreas;
    }

    /**
     * return either the fofile or the xmlfile
     */
    public File getInputFile() {
        switch (inputmode) {
        case FO_INPUT:
            return fofile;
        default:
            return fofile;
        }
    }

    /**
     * shows the commandline syntax including a summary of all available options and 
some examples
     */
    public static void printUsage() {
        MessageHandler.errorln("\nUSAGE\nFop [options] [-fo|-xml] infile [-xsl file] 
[-awt|-pdf|-mif|-pcl|-ps|-txt|-at|-print] <outfile>\n"
                               + " [OPTIONS]  \n"
                               + "  -d          debug mode   \n"
                               + "  -x          dump configuration settings  \n"
                               + "  -q          quiet mode  \n"
                               + "  -c cfg.xml  use additional configuration file 
cfg.xml\n"
                               + "  -l lang     the language to use for user 
information \n"
                               + "  -s          for area tree XML, down to block areas 
only\n\n"
                               + " [INPUT]  \n"
                               + "  infile            xsl:fo input file (the same as 
the next) \n"
                               + "  -fo  infile       xsl:fo input file  \n"
                               + "  -xml infile       xml input file, must be used 
together with -xsl \n"
                               + "  -xsl stylesheet   xslt stylesheet \n \n"
                               + " [OUTPUT] \n"
                               + "  outfile           input will be rendered as pdf 
file into outfile \n"
                               + "  -pdf outfile      input will be rendered as pdf 
file (outfile req'd) \n"
                               + "  -awt              input will be displayed on 
screen \n"
                               + "  -mif outfile      input will be rendered as mif 
file (outfile req'd)\n"
                               + "  -pcl outfile      input will be rendered as pcl 
file (outfile req'd) \n"
                               + "  -ps outfile       input will be rendered as 
PostScript file (outfile req'd) \n"
                               + "  -txt outfile      input will be rendered as text 
file (outfile req'd) \n"
                               + "  -at outfile       representation of area tree as 
XML (outfile req'd) \n"
                               + "  -print            input file will be rendered and 
sent to the printer \n"
                               + "                    see options with \"-print help\" 
\n\n"
                               + " [Examples]\n" + "  Fop foo.fo foo.pdf \n"
                               + "  Fop -fo foo.fo -pdf foo.pdf (does the same as the 
previous line)\n"
                               + "  Fop -xsl foo.xsl -xml foo.xml -pdf foo.pdf\n"
                               + "  Fop foo.fo -mif foo.mif\n"
                               + "  Fop foo.fo -print or Fop -print foo.fo \n"
                               + "  Fop foo.fo -awt \n");
    }

    /**
     * shows the options for print output
     */
    public void printUsagePrintOutput() {
        MessageHandler.errorln("USAGE: -print [-Dstart=i] [-Dend=i] [-Dcopies=i] 
[-Deven=true|false] "
                               + " org.apache.fop.apps.Fop (..) -print \n"
                               + "Example:\n"
                               + "java -Dstart=1 -Dend=2 org.apache.Fop.apps.Fop 
infile.fo -print ");
    }


    /**
     * debug mode. outputs all commandline settings
     */
    private void debug() {
        System.out.print("Input mode: ");
        switch (inputmode) {
        case NOT_SET:
            MessageHandler.logln("not set");
            break;
        case FO_INPUT:
            MessageHandler.logln("FO ");
            MessageHandler.logln("fo input file: " + fofile.toString());
            break;
        default:
            MessageHandler.logln("unknown input type");
        }
        System.out.print("Output mode: ");
        switch (outputmode) {
        case NOT_SET:
            MessageHandler.logln("not set");
            break;
        case PDF_OUTPUT:
            MessageHandler.logln("pdf");
            MessageHandler.logln("output file: " + outfile.toString());
            break;
        default:
            MessageHandler.logln("unknown input type");
        }


        MessageHandler.logln("OPTIONS");
        if (userConfigFile != null) {
            MessageHandler.logln("user configuration file: "
                                 + userConfigFile.toString());
        } else {
            MessageHandler.logln("no user configuration file is used [default]");
        }
        if (errorDump != null) {
            MessageHandler.logln("debug mode on");
        } else {
            MessageHandler.logln("debug mode off [default]");
        }
        if (dumpConfiguration != null) {
            MessageHandler.logln("dump configuration");
        } else {
            MessageHandler.logln("don't dump configuration [default]");
        }
        if (quiet != null) {
            MessageHandler.logln("quiet mode on");
        } else {
            MessageHandler.logln("quiet mode off [default]");
        }

    }

    // debug: create class and output all settings
    public static void main(String args[]) {
        /*
         * for (int i = 0; i < args.length; i++) {
         * MessageHandler.logln(">"+args[i]+"<");
         * }
         */
        try {
            CommandLineOptions options = new CommandLineOptions(args);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // options.debug();
    }

}


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, email: [EMAIL PROTECTED]

Reply via email to