Package net.java.textilej.parser.builder

Source Code of net.java.textilej.parser.builder.DocBookDocumentBuilder$ContentEmitter

package net.java.textilej.parser.builder;

import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.TreeMap;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import net.java.textilej.parser.Attributes;
import net.java.textilej.util.FormattingXMLStreamWriter;
import net.java.textilej.util.XmlStreamWriter;

public class DocBookDocumentBuilder extends AbstractXmlDocumentBuilder {

  private static final Pattern CSS_CLASS_INLINE = Pattern.compile("(^|\\s+)inline(\\s+|$)");
  private static Set<Integer> entityReferenceToUnicode = new HashSet<Integer>();
  static {
    entityReferenceToUnicode.add(215);
    entityReferenceToUnicode.add(8211);
    entityReferenceToUnicode.add(8212);
    entityReferenceToUnicode.add(8220);
    entityReferenceToUnicode.add(8221);
    entityReferenceToUnicode.add(8216);
    entityReferenceToUnicode.add(8217);

  }
 
  private String bookTitle;
  private String doctype = "<!DOCTYPE book PUBLIC \"-//OASIS//DTD DocBook XML V4.5//EN\" \"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd\">";
 
 
  private Map<String,String> acronyms = new HashMap<String, String>();
 
  private int headingLevel = 0;
 
  private Stack<Integer> blockSize = new Stack<Integer>();
 
  public DocBookDocumentBuilder(Writer out) {
    super(out);
  }

  public DocBookDocumentBuilder(XmlStreamWriter writer) {
    super(writer);
  }


  protected XmlStreamWriter createFormattingXmlStreamWriter(Writer out) {
    XmlStreamWriter writer = super.createXmlStreamWriter(out);
    return new FormattingXMLStreamWriter(writer) {
      @Override
      protected boolean preserveWhitespace(String elementName) {
        return elementName.equals("code") || elementName.startsWith("literal");
      }
    };
  }
 
  public String getDoctype() {
    return doctype;
  }

  public void setDoctype(String doctype) {
    this.doctype = doctype;
  }

  public String getBookTitle() {
    return bookTitle;
  }

  public void setBookTitle(String bookTitle) {
    this.bookTitle = bookTitle;
  }

 
  @Override
  public void acronym(String text, String definition) {
    String previousDef = acronyms.put(text, definition);
    if (previousDef != null && previousDef.length() > definition.length()) {
      acronyms.put(text,previousDef);
    }
    writer.writeStartElement("glossterm");
    characters(text);
    writer.writeEndElement();
  }

  @Override
  public void link(String href,final String text) {
    link(href,new ContentEmitter() {
      public void emit() {
        writer.writeCharacters(text);
      }
    });
  }

  private void link(String href, ContentEmitter emitter) {
    if (href.startsWith("#")) {
      if (href.length() > 1) {
        writer.writeStartElement("link");
        writer.writeAttribute("linkend", href.substring(1));
        emitter.emit();
        writer.writeEndElement(); // link
      } else {
        emitter.emit();
      }
    } else {
      writer.writeStartElement("ulink");
      writer.writeAttribute("url", href);
      emitter.emit();
      writer.writeEndElement(); // ulink
    }
  }
 
  private interface ContentEmitter {
    public void emit();
  }
 
  @Override
  public void beginBlock(BlockType type, Attributes attributes) {
    if (headingLevel == 0) {
      beginHeading(1,new Attributes());
      endHeading();
    }

    String elementName;
    String[] elementNames = null;
    boolean allowTitle = false;
    switch (type) {
    case BULLETED_LIST:
      elementName = "itemizedlist";
      break;
    case NUMERIC_LIST:
      elementName = "orderedlist";
      break;
    case FOOTNOTE:
    case PARAGRAPH:
      elementName = "para";
      break;
    case CODE:
      elementName = "code";
      break;
    case PREFORMATTED:
      elementName = "literallayout";
      break;
    case QUOTE:
      elementName = "blockquote";
      break;
    case LIST_ITEM:
      elementName = "listitem";
      elementNames = new String[] { "para" };
      break;
    case TABLE:
      elementName = "informaltable";
      break;
    case TABLE_CELL_HEADER:
      elementName = "th";
      break;
    case TABLE_CELL_NORMAL:
      elementName = "td";
      break;
    case TABLE_ROW:
      elementName = "tr";
      break;
    case INFORMATION:
      elementName = "important";
      allowTitle = true;
      break;
    case NOTE:
      elementName = "note";
      allowTitle = true;
      break;
    case WARNING:
      elementName = "warning";
      allowTitle = true;
      break;
    case TIP:
      elementName = "tip";
      allowTitle = true;
      break;
    default:
      throw new IllegalStateException(type.name());
    }
    int blockSize = 1;
    writer.writeStartElement(elementName);
    applyAttributes(attributes);
   
    if (elementNames != null) {
      for (String name: elementNames) {
        ++blockSize;
        writer.writeStartElement(name);
      }
    }
   
    if (allowTitle && attributes.getTitle() != null) {
      writer.writeStartElement("title");
      writer.writeCharacters(attributes.getTitle());
      writer.writeEndElement();
    }
   
    this.blockSize.push(blockSize);
  }

  @Override
  public void endBlock() {
    int size = blockSize.pop();
    for (int x = 0;x<size;++x) {
      writer.writeEndElement();
    }
  }

  @Override
  public void beginHeading(int level, Attributes attributes) {
    closeSections(Math.max(level-1,0));
   
    while (headingLevel < level) {
      headingLevel++;
     
      writer.writeStartElement(headingLevel==1?"chapter":"section");
      if (attributes != null) {
        applyAttributes(attributes);
        attributes = null;
      }
    }
   
    writer.writeStartElement("title");
 
  }
 
  @Override
  public void endHeading() {
    writer.writeEndElement(); // title
  }
 
  @Override
  public void beginDocument() {
    baseInHead = false;
    writer.writeStartDocument();
    writer.writeDTD(doctype);
   
    writer.writeStartElement("book");
    writer.writeStartElement("title");
    if (bookTitle != null) {
      writer.writeCharacters(bookTitle);
    }
    writer.writeEndElement();
  }

  @Override
  public void beginSpan(SpanType type, Attributes attributes) {
    switch (type) {
    case BOLD:
    case STRONG:
      writer.writeStartElement("emphasis");
      writer.writeAttribute("role", "bold");
      break;
    case CITATION:
      writer.writeStartElement("citation");
      break;
    case CODE:
      writer.writeStartElement("code");
      break;
    case DELETED:
      writer.writeStartElement("emphasis");
      writer.writeAttribute("role", "del");
      break;
    case EMPHASIS:
      writer.writeStartElement("emphasis");
      break;
    case INSERTED:
      writer.writeStartElement("emphasis");
      writer.writeAttribute("role", "ins");
      break;
    case ITALIC:
      writer.writeStartElement("emphasis");
      writer.writeAttribute("role", "italic");
      break;
    case SPAN:
      writer.writeStartElement("phrase");
      break;
    case SUBSCRIPT:
      writer.writeStartElement("subscript");
      break;
    case SUPERSCRIPT:
      writer.writeStartElement("superscript");
      break;
    case MONOSPACE:
      writer.writeStartElement("literal");
      break;
    default:
      Logger.getLogger(DocBookDocumentBuilder.class.getName()).warning("No docbook mapping for "+type);
      writer.writeStartElement("phrase");
      break;
    }
    applyAttributes(attributes);
  }

  private void applyAttributes(Attributes attributes) {
    if (attributes.getId() != null) {
      writer.writeAttribute("id", attributes.getId());
    }
  }
 
  @Override
  public void endDocument() {
    closeSections(0);
   
    writeGlossaryAppendix();
   
    writer.writeEndElement(); // book
    writer.writeEndDocument();
   
    acronyms.clear();
  }

  private void closeSections(int toLevel) {
    if (toLevel < 0) {
      toLevel = 0;
    }
    while (headingLevel > toLevel) {
      writer.writeEndElement();
      --headingLevel;
    }
  }

  private void writeGlossaryAppendix() {
    if (!acronyms.isEmpty()) {
      writer.writeStartElement("appendix");
      writer.writeAttribute("id", "glossary");
      writer.writeStartElement("title");
      writer.writeAttribute("id", "glossary-end");
      writer.writeCharacters("Glossary");
      writer.writeEndElement(); // title
      writer.writeStartElement("glosslist");

      for (Map.Entry<String, String> glossEntry : new TreeMap<String,String>(acronyms).entrySet()) {

        writer.writeStartElement("glossentry");

        writer.writeStartElement("glossterm");
        writer.writeCharacters(glossEntry.getKey());
        writer.writeEndElement(); // glossterm

        writer.writeStartElement("glossdef");
        writer.writeStartElement("para");
        writer.writeCharacters(glossEntry.getValue());
        writer.writeEndElement(); // para
        writer.writeEndElement(); // glossdef
       
        writer.writeEndElement(); // glossentry
      }
      writer.writeEndElement(); // glosslist
      writer.writeEndElement(); // appendix
    }
  }

  @Override
  public void endSpan() {
    writer.writeEndElement();
  }
 
  @Override
  public void charactersUnescaped(String literal) {
    // note: this *may* have HTML tags in it
    writer.writeLiteral(literal);
//    Logger.getLogger(DocBookDocumentBuilder.class.getName()).warning("HTML literal not supported in DocBook");
  }

  @Override
  public void entityReference(String entity) {
    if (entity.startsWith("#")) {
      String numeric = entity.substring(1);
      int base = 10;
      if (numeric.startsWith("x")) {
        numeric = entity.substring(1);
        base = 16;
      }
      int unicodeValue = Integer.parseInt(numeric,base);
      if (entityReferenceToUnicode.contains(unicodeValue)) {
        writer.writeCharacters(""+((char)unicodeValue));
        return;
      }
    }
    writer.writeEntityRef(entity);
  }

  @Override
  public void image(Attributes attributes, String url) {
    String cssClass = attributes.getCssClass();
    boolean inlined = false;
    if (cssClass != null && CSS_CLASS_INLINE.matcher(cssClass).find()) {
      inlined = true;
    }
    emitImage(attributes, url,inlined);
  }

  private void emitImage(Attributes attributes, String url,boolean inline) {
    writer.writeStartElement(inline?"inlinemediaobject":"mediaobject");
    applyAttributes(attributes);
    writer.writeStartElement("imageobject");
    writer.writeEmptyElement("imagedata");
    writer.writeAttribute("fileref", makeUrlAbsolute(url));
    writer.writeEndElement(); // imageobject
    writer.writeEndElement(); // inlinemediaobject or mediaobject
  }

  @Override
  public void imageLink(String href, final String imageUrl) {
    link(href,new ContentEmitter() {
      public void emit() {
        emitImage(new Attributes(),imageUrl,true);
      }
    });
  }

  @Override
  public void lineBreak() {
    // no equivalent in DocBook.
    characters("\n");
  }

}
TOP

Related Classes of net.java.textilej.parser.builder.DocBookDocumentBuilder$ContentEmitter

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.