@Test
  public void testHeaderByUsingDefaultHeadingStyle() throws Exception {
    IContext context = new MockContext();
    // Add default style (in real context, this DefaultStyle is added by DocxStylesPreprocessor
    // which search
    // heading style from the word/styles.xml entry of the docx)
    DefaultStyle defaultStyle = new DefaultStyle();
    defaultStyle.addHeaderStyle(1, "Heading1");
    defaultStyle.addHeaderStyle(2, "Heading2");
    DocxContextHelper.putDefaultStyle(context, defaultStyle);

    BufferedElement parent = null;

    ITextStylingTransformer formatter = HTMLTextStylingTransformer.INSTANCE;
    IDocumentHandler handler = new DocxDocumentHandler(parent, context, "word/document.xml");
    formatter.transform(
        "xxx<h1>Title1</h1><h2>Title2</h2><h3>Title3</h3><h4>Title4</h4><h5>Title5</h5><h6>Title6</h6>",
        handler);

    Assert.assertEquals("", handler.getTextBefore());
    Assert.assertEquals("<w:r><w:t xml:space=\"preserve\" >xxx</w:t></w:r>", handler.getTextBody());
    Assert.assertEquals(
        "<w:p><w:pPr><w:pStyle w:val=\"Heading1\" /></w:pPr><w:r><w:t>Title1</w:t></w:r></w:p>"
            + "<w:p><w:pPr><w:pStyle w:val=\"Heading2\" /></w:pPr><w:r><w:t>Title2</w:t></w:r></w:p>"
            + "<w:p><w:pPr><w:pStyle w:val=\"XDocReport_Heading_3\" /></w:pPr><w:r><w:t>Title3</w:t></w:r></w:p>"
            + "<w:p><w:pPr><w:pStyle w:val=\"XDocReport_Heading_4\" /></w:pPr><w:r><w:t>Title4</w:t></w:r></w:p>"
            + "<w:p><w:pPr><w:pStyle w:val=\"XDocReport_Heading_5\" /></w:pPr><w:r><w:t>Title5</w:t></w:r></w:p>"
            + "<w:p><w:pPr><w:pStyle w:val=\"XDocReport_Heading_6\" /></w:pPr><w:r><w:t>Title6</w:t></w:r></w:p>",
        handler.getTextEnd());
  }
  @Test
  public void testHyperlinkByUsingDefaultHyperlinkStyle() throws Exception {
    IContext context = new MockContext();
    // Add default style (in real context, this DefaultStyle is added by DocxStylesPreprocessor
    // which search
    // hyperlink style from the word/styles.xml entry of the docx)
    DefaultStyle defaultStyle = new DefaultStyle();
    defaultStyle.setHyperLinkStyleId("DefaultHyperlink");
    DocxContextHelper.putDefaultStyle(context, defaultStyle);

    BufferedElement parent = null;

    ITextStylingTransformer formatter = HTMLTextStylingTransformer.INSTANCE;
    IDocumentHandler handler = new DocxDocumentHandler(parent, context, "word/document.xml");
    formatter.transform(
        "<a href=\"http://code.google.com/p/xdocreport/\" >XDocReport</a>", handler);

    Assert.assertEquals("", handler.getTextBefore());
    Assert.assertEquals(
        "<w:hyperlink r:id=\"___rId0\" w:history=\"1\"> <w:proofErr w:type=\"spellStart\" /><w:r w:rsidRPr=\"001D30B5\"><w:rPr><w:rStyle w:val=\"DefaultHyperlink\" /></w:rPr><w:t>XDocReport</w:t></w:r><w:proofErr w:type=\"spellEnd\" /></w:hyperlink>",
        handler.getTextBody());
    Assert.assertEquals("", handler.getTextEnd());

    HyperlinkRegistry registry =
        DocxContextHelper.getHyperlinkRegistry(context, "word/document.xml");
    Assert.assertNotNull(registry);
    Assert.assertEquals(1, registry.getHyperlinks().size());

    HyperlinkInfo hyperlinkInfo = registry.getHyperlinks().get(0);
    Assert.assertEquals("___rId0", hyperlinkInfo.getId());
    Assert.assertEquals("http://code.google.com/p/xdocreport/", hyperlinkInfo.getTarget());
    Assert.assertEquals("External", hyperlinkInfo.getTargetMode());
  }
  @Test
  public void testNumberingNoneAbstractNumber() throws Exception {
    DocxNumberingPreprocessor preprocessor = new DocxNumberingPreprocessor();
    InputStream stream =
        IOUtils.toInputStream(
            "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
                + "<w:numbering"
                + " xmlns:ve=\"http://schemas.openxmlformats.org/markup-compatibility/2006\""
                + " xmlns:o=\"urn:schemas-microsoft-com:office:office\""
                + " xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\""
                + " xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\""
                + " xmlns:v=\"urn:schemas-microsoft-com:vml\""
                + " xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\""
                + " xmlns:w10=\"urn:schemas-microsoft-com:office:word\""
                + " xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\""
                + " xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\">"
                + " </w:numbering>");

    StringWriter writer = new StringWriter();
    IDocumentFormatter formatter = new FreemarkerDocumentFormatter();
    Map<String, Object> sharedContext = new HashMap<String, Object>();
    preprocessor.preprocess("word/numbering.xml", stream, writer, null, formatter, sharedContext);

    Assert.assertEquals(
        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
            + "<w:numbering"
            + " xmlns:ve=\"http://schemas.openxmlformats.org/markup-compatibility/2006\""
            + " xmlns:o=\"urn:schemas-microsoft-com:office:office\""
            + " xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\""
            + " xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\""
            + " xmlns:v=\"urn:schemas-microsoft-com:vml\""
            + " xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\""
            + " xmlns:w10=\"urn:schemas-microsoft-com:office:word\""
            + " xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\""
            + " xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\"> "
            + "${___NoEscapeStylesGenerator.generateAbstractNumBullet(___DefaultStyle)}"
            + "[#if ___NumberingRegistry??]"
            + "[#list ___NumberingRegistry.numbers as ___NumberInfo]"
            + "[#if ___NumberInfo.ordered??]"
            + "${___NoEscapeStylesGenerator.generateAbstractNumDecimal(___DefaultStyle,___NumberInfo.abstractNumId)}"
            + "[/#if]"
            + "[/#list]"
            + "[/#if]"
            + "[#if ___NumberingRegistry??]"
            + "[#list ___NumberingRegistry.numbers as ___NumberInfo]"
            + "<w:num w:numId=\"${___NumberInfo.numId}\">"
            + "<w:abstractNumId w:val=\"${___NumberInfo.abstractNumId}\"/>"
            + "</w:num>"
            + "[/#list]"
            + "[/#if]"
            + "</w:numbering>",
        writer.toString());

    DefaultStyle defaultStyle = DocxContextHelper.getDefaultStyle(sharedContext);
    Assert.assertNotNull(defaultStyle);
    Assert.assertNull(defaultStyle.getAbstractNumIdForOrdererList());
    Assert.assertNull(defaultStyle.getAbstractNumIdForUnordererList());
  }
 private void generateDynamicAbstractNumIfNeeded() {
   if (hasDynamicAbstractNum) {
     return;
   }
   IBufferedRegion region = getCurrentElement();
   DefaultStyle defaultStyle = DocxContextHelper.getDefaultStyle(sharedContext);
   if (defaultStyle.getAbstractNumIdForUnordererList() == null) {
     region.append(
         formatter.getFunctionDirective(
             DocxContextHelper.STYLES_GENERATOR_KEY,
             IDocxStylesGenerator.generateAbstractNumBullet,
             DocxContextHelper.DEFAULT_STYLE_KEY));
   }
   region.append(generateScriptsForDynamicOrderedNumbers());
   hasDynamicAbstractNum = true;
 }
  @Override
  public boolean doStartElement(String uri, String localName, String name, Attributes attributes)
      throws SAXException {
    /**
     * <w:abstractNum w:abstractNumId="1"> <w:nsid w:val="68EC0125" /> <w:multiLevelType
     * w:val="hybridMultilevel" /> <w:tmpl w:val="3D16DCB8" /> <w:lvl w:ilvl="0" w:tplc="040C0001">
     * <w:start w:val="1" /> <w:numFmt w:val="bullet" />
     */
    if (DocxUtils.isAbstractNum(uri, localName, name)) {
      // w:abstractNumId
      this.currentAbstractNumId = attributes.getValue(W_ABSTRACT_NUM_ID_ATTR);
    } else if (DocxUtils.isNumFmt(uri, localName, name)) {
      String firstNumFmt = attributes.getValue(W_VAL_ATTR);
      if (StringUtils.isNotEmpty(firstNumFmt)) {
        if (BULLET.equals(firstNumFmt)) {
          DefaultStyle defaultStyle = DocxContextHelper.getDefaultStyle(sharedContext);
          if (defaultStyle.getAbstractNumIdForUnordererList() == null) {
            defaultStyle.setAbstractNumIdForUnordererList(
                StringUtils.asInteger(currentAbstractNumId));
          }
        } else if (DECIMAL.equals(firstNumFmt)) {
          DefaultStyle defaultStyle = DocxContextHelper.getDefaultStyle(sharedContext);
          if (defaultStyle.getAbstractNumIdForOrdererList() == null) {
            defaultStyle.setAbstractNumIdForOrdererList(
                StringUtils.asInteger(currentAbstractNumId));
          }
        }
      }
    } else if (DocxUtils.isNum(uri, localName, name)) {
      Integer numId = StringUtils.asInteger(attributes.getValue(W_NUM_ID_ATTR));
      if (numId != null) {
        DefaultStyle defaultStyle = DocxContextHelper.getDefaultStyle(sharedContext);
        if (defaultStyle.getMaxNumId() == null || numId > defaultStyle.getMaxNumId()) {
          defaultStyle.setMaxNumId(numId);
        }
      }

      generateDynamicAbstractNumIfNeeded();
    }
    return super.doStartElement(uri, localName, name, attributes);
  }