Package net.sourceforge.chaperon.ant

Source Code of net.sourceforge.chaperon.ant.ExtendedParserTask

/*
*  Copyright (C) Chaperon. All rights reserved.
*  -------------------------------------------------------------------------
*  This software is published under the terms of the Apache Software License
*  version 1.1, a copy of which has been included  with this distribution in
*  the LICENSE file.
*/

package net.sourceforge.chaperon.ant;

import net.sourceforge.chaperon.model.extended.ExtendedGrammar;
import net.sourceforge.chaperon.process.extended.ExtendedDirectParserProcessor;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.Mapper;
import org.apache.tools.ant.types.XMLCatalog;
import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.ant.util.IdentityMapper;

import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Unmarshaller;

import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.LocatorImpl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.LineNumberReader;

import java.util.Properties;

import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;

/**
* A ant task for parsing text files
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels </a>
* @version CVS $Id: ExtendedParserTask.java,v 1.3 2004/01/09 10:48:06 benedikta Exp $
*/
public class ExtendedParserTask extends MatchingTask
{
  private File srcDir = null;
  private File destDir = null;
  private File baseDir = null;
  private Mapper mapper = null;

  /** for resolving entities such as dtds */
  private XMLCatalog xmlCatalog = new XMLCatalog();
  private File grammarFile = null;
  private String parserFactory = null;
  private SAXParserFactory parserFactoryImpl = null;
  private String transformerFactory = null;
  private SAXTransformerFactory transformerFactoryImpl = null;
  private String encoding = "ISO-8859-1";
  private boolean indent = false;
  private boolean flatten = false;
  private String inputtype = "text";
  private int msgLevel = Project.MSG_ERR;
  private AntLog log;
  private ExtendedGrammar grammar = null;
  private ExtendedDirectParserProcessor parser = null;

  /**
   * Constructs the task
   */
  public ExtendedParserTask() {}

  /**
   * Executes the task
   *
   * @throws BuildException
   */
  public void execute() throws BuildException
  {
    if (baseDir==null)
      baseDir = project.resolveFile(".");

    if (grammarFile==null)
      throw new BuildException("No grammar file is specified", location);

    if (!grammarFile.exists())
      throw new BuildException("Grammar file doesn't exists:"+grammarFile.getAbsolutePath(),
                               location);

    if (destDir==null)
      throw new BuildException("No destdir specified!", location);

    log = new AntLog(getProject(), msgLevel);

    buildAutomata(grammarFile);

    DirectoryScanner scanner = getDirectoryScanner(srcDir);

    FileNameMapper mapperImpl;

    if (mapper==null)
      mapperImpl = new IdentityMapper();
    else
      mapperImpl = mapper.getImplementation();

    String[] list = scanner.getIncludedFiles();

    for (int i = 0; i<list.length; i++)
    {
      String[] dest = mapperImpl.mapFileName(list[i]);

      if (dest!=null)
        for (int j = 0; j<dest.length; j++)
        {
          log("Transforming "+list[i]+" to "+dest[j], Project.MSG_DEBUG);
          process(new File(srcDir, list[i]), new File(destDir, dest[j]));
        }
    }
  }

  /**
   * Set the base directory.
   *
   * @param dir Base directory
   */
  public void setBasedir(File dir)
  {
    baseDir = dir;
  }

  /**
   * Set the source directory
   *
   * @param dir Source directory
   */
  public void setSrcdir(File dir)
  {
    srcDir = dir;
  }

  /**
   * Set the destination directory into which the result files should be copied to
   *
   * @param dir Destination directory
   */
  public void setDestdir(File dir)
  {
    destDir = dir;
  }

  /**
   * Creates a mapper.
   *
   * @return New mapper.
   *
   * @throws BuildException
   */
  public Mapper createMapper() throws BuildException
  {
    if (mapper!=null)
      throw new BuildException("Cannot define more than one mapper", location);

    mapper = new Mapper(project);
    return mapper;
  }

  /**
   * Set the grammar, which should be used.
   *
   * @param grammarFile Grammar file.
   */
  public void setGrammar(File grammarFile)
  {
    this.grammarFile = grammarFile;
  }

  /**
   * Sets the message level.
   *
   * @param msgLevel Message level.
   */
  public void setMsglevel(String msgLevel)
  {
    if (msgLevel.equalsIgnoreCase("debug"))
      this.msgLevel = Project.MSG_DEBUG;
    else if (msgLevel.equalsIgnoreCase("verbose"))
      this.msgLevel = Project.MSG_VERBOSE;
    else if (msgLevel.equalsIgnoreCase("info"))
      this.msgLevel = Project.MSG_INFO;
    else if (msgLevel.equalsIgnoreCase("warn"))
      this.msgLevel = Project.MSG_WARN;
    else if (msgLevel.equalsIgnoreCase("error"))
      this.msgLevel = Project.MSG_ERR;
  }

  /**
   * Sets the encoding for the input file
   *
   * @param encoding Encoding of the document
   */
  public void setEncoding(String encoding)
  {
    this.encoding = encoding;
  }

  /**
   * Set if the output document should be indented
   *
   * @param indent If the output should be indented
   */
  public void setIndent(boolean indent)
  {
    this.indent = indent;
  }

  /**
   * If the input document is a XML or a text document.
   *
   * @param inputtype Type of the input document.
   */
  public void setInputtype(String inputtype)
  {
    this.inputtype = inputtype;
  }

  /**
   * Name of the parser factory.
   *
   * @param parserFactory Name of the parser factory.
   */
  public void setParser(String parserFactory)
  {
    this.parserFactory = parserFactory;
  }

  /**
   * Name of the transformer factory.
   *
   * @param transformerFactory Name of the transformer factory.
   */
  public void setTransformer(String transformerFactory)
  {
    this.transformerFactory = transformerFactory;
  }

  /**
   * Add the catalog to our internal catalog
   *
   * @param xmlCatalog the XMLCatalog instance to use to look up DTDs
   */
  public void addConfiguredXMLCatalog(XMLCatalog xmlCatalog)
  {
    this.xmlCatalog.addConfiguredXMLCatalog(xmlCatalog);
  }

  /**
   * Initialize internal instance of XMLCatalog
   */
  public void init() throws BuildException
  {
    super.init();
    xmlCatalog.setProject(project);
  }

  /**
   * Processes the given input XML file and stores the result in the given resultFile.
   *
   * @param inFile The text file, which should parsed
   * @param outFile The output file
   *
   * @throws BuildException
   */
  private void process(File inFile, File outFile) throws BuildException
  {
    try
    {
      if (!inFile.exists())
        throw new BuildException("File "+inFile+" doesn't exists", location);

      if (inFile.lastModified()>outFile.lastModified())
      {
        ensureDirectoryFor(outFile);
        log("Parsing file "+inFile+" to "+outFile, Project.MSG_INFO);

        Properties format = new Properties();

        format.put(OutputKeys.ENCODING, encoding);
        if (indent)
          format.put(OutputKeys.INDENT, "yes");

        format.put(OutputKeys.METHOD, "xml");

        SAXTransformerFactory factory = getTransformerFactory();

        TransformerHandler serializer = factory.newTransformerHandler();
        serializer.getTransformer().setOutputProperties(format);
        serializer.setResult(new StreamResult(outFile));

        this.parser = new ExtendedDirectParserProcessor();
        this.parser.setLog(log);
        this.parser.setFlatten(this.flatten);

        this.parser.setExtendedGrammar(this.grammar);
        this.parser.setContentHandler(serializer);

        if (!inputtype.equalsIgnoreCase("xml"))
          pushTextFile(inFile);
        else
          pushXMLFile(inFile);
      }
    }
    catch (Exception ex)
    {
      if (outFile!=null)
        outFile.delete();

      if (ex instanceof BuildException)
        throw (BuildException)ex;

      throw new BuildException("Failed to process "+inFile+" : "+ex.getMessage(), ex);
    }
  }

  /**
   * Build the automata for the lexicon and grammar.
   *
   * @param grammarFile Grammar file.
   *
   * @throws BuildException
   */
  private void buildAutomata(File grammarFile) throws BuildException
  {
    try
    {
      log("Building grammar from "+grammarFile, Project.MSG_INFO);

      SAXParserFactory factory = getParserFactory();

      factory.setNamespaceAware(true);

      XMLReader parser = factory.newSAXParser().getXMLReader();
      parser.setEntityResolver(xmlCatalog);

      Mapping mapping = new Mapping();
      mapping.loadMapping(new InputSource(ExtendedGrammar.class.getResource("mapping.xml")
                                                               .openStream()));

      Unmarshaller unmarshaller = new Unmarshaller(ExtendedGrammar.class);
      unmarshaller.setMapping(mapping);

      this.grammar = (ExtendedGrammar)unmarshaller.unmarshal(new FileReader(grammarFile));

      if (log.isDebugEnabled())
        log.debug("grammar:\n"+grammar);
    }
    catch (Exception ex)
    {
      if (ex instanceof BuildException)
        throw (BuildException)ex;

      throw new BuildException(ex);
    }
  }

  private void pushTextFile(File inFile) throws Exception
  {
    try
    {
      LocatorImpl locator = new LocatorImpl();

      locator.setSystemId(inFile.toURL().toString());
      locator.setLineNumber(1);
      locator.setColumnNumber(1);

      this.parser.setDocumentLocator(locator);
      this.parser.startDocument();
      this.parser.startElement("http://chaperon.sourceforge.net/schema/text/1.0", "text", "text",
                               new AttributesImpl());

      LineNumberReader reader =
        new LineNumberReader(new InputStreamReader(new FileInputStream(inFile)));

      String line;
      String newline = null;
      String separator = System.getProperty("line.separator");

      while (true)
      {
        if (newline==null)
          line = reader.readLine();
        else
          line = newline;

        if (line==null)
          break;

        newline = reader.readLine();

        line = (newline!=null) ? (line+separator) : line;

        locator.setLineNumber(reader.getLineNumber());
        locator.setColumnNumber(1);
        this.parser.characters(line.toCharArray(), 0, line.length());

        if (newline==null)
          break;
      }

      reader.close();

      this.parser.endElement("http://chaperon.sourceforge.net/schema/text/1.0", "text", "text");
      this.parser.endDocument();
    }
    catch (SAXParseException se)
    {
      throw new BuildException("Exception occurs during parsing file "+inFile+" at line "+
                               se.getLineNumber()+" column "+se.getColumnNumber(), se);
    }
  }

  private void pushXMLFile(File inFile) throws Exception
  {
    SAXParserFactory parserfactory = getParserFactory();

    parserfactory.setNamespaceAware(true);

    XMLReader parser = parserfactory.newSAXParser().getXMLReader();

    parser.setEntityResolver(xmlCatalog);

    parser.setContentHandler(this.parser);
    try
    {
      parser.parse(inFile.toString());
    }
    catch (SAXParseException se)
    {
      throw new BuildException("Exception occurs during parsing file "+inFile+" at line "+
                               se.getLineNumber()+" column "+se.getColumnNumber(), se);
    }
  }

  /**
   * Ensures the directory for the output
   *
   * @param targetFile The directory
   *
   * @throws BuildException
   */
  private void ensureDirectoryFor(File targetFile) throws BuildException
  {
    File directory = new File(targetFile.getParent());

    if ((!directory.exists()) && (!directory.mkdirs()))
      throw new BuildException("Unable to create directory: "+directory.getAbsolutePath());
  }

  private SAXParserFactory getParserFactory() throws BuildException
  {
    if (parserFactoryImpl==null)
    {
      try
      {
        if (parserFactory==null)
          parserFactoryImpl = SAXParserFactory.newInstance();
        else
          parserFactoryImpl = (SAXParserFactory)Class.forName(parserFactory).newInstance();
      }
      catch (Exception e)
      {
        throw new BuildException("Could not load parser factory", e);
      }
    }

    return parserFactoryImpl;
  }

  private SAXTransformerFactory getTransformerFactory()
    throws BuildException
  {
    if (transformerFactoryImpl==null)
    {
      try
      {
        if (transformerFactory==null)
          transformerFactoryImpl = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
        else
          transformerFactoryImpl =
            (SAXTransformerFactory)Class.forName(transformerFactory).newInstance();
      }
      catch (Exception e)
      {
        throw new BuildException("Could not load transformer factory", e);
      }
    }

    return transformerFactoryImpl;
  }
}
TOP

Related Classes of net.sourceforge.chaperon.ant.ExtendedParserTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.