Skip to content

how to implement a new element

Leonardo Correa edited this page Feb 7, 2014 · 2 revisions

#How to Implement a New Element/Component#

##Introduction##

This document gives you the guidelines how to implement a new element/component for Java2word. Consider this only a simple demonstration how to implement something new in this framework.

##The new element##

Imagine you want to use one component and this component hasn't been implememnted yet. A good example could be the "Lists", which hasn't been done yet (07-Feb-2014). But for this exercise we will use "Paragraph".

Lets define steps how to implement this "Paragraph"(or any other) component.

##Set up your Development Environment## please refer to: https://github.com/leonardoanalista/java2word/wiki/Set-up-your-Development-Environment

##Implementation of the new element##

Now you will see that there is no mystery behind Java2word library.

  • Create your class called Paragraph.java implementing the interface IElement.java.
  • Also create a test class called ParagraphTest.java
  • Preferable, first write your unit test against getContent() method.
  • Write the implementation of the method is getContent(). This method has to return the XML contend ready to be added to the document.

I assume you have no idea how to write in your getContent() right?

Ok... here goes the most important sentence/steps in the whole documentation: Now it is time to do the reverse engineering and figure out how to implement the code to generate a Paragraph block.

Don't worry about the huge generated XML. The important right now bit is between:

and

At this point you can see something like:

//... more stuff, don't worry now...    
<w:body>
        <w:p wsp:rsidR="00D711DA" wsp:rsidRDefault="00FE5527">
                <w:r>
                        <w:t>Leonardo Correa</w:t>
                </w:r>
        </w:p>
<w:body>
//... more stuff, don't worry now...

Now we know how to implement the Paragraph component!!!

Following the development guidelines, you will use implement the interface IFluentElement<paragraph>. This interface will force you to implement a method called "create()".

In order to start the fluent flow, you will have to create another static method called with(String). It doesn't have to be "with" but something that I think starts the flow or conversation.

public static Paragraph with(String value) {
    this.value = value //actual paragraph content
    return new Paragraph();
}

Notice that the method is very simple and only returns a new reference to the Paragraph object. You should also make the constructor private in order to force the use of the fluent interface.

After, I could have a variable with the place holder.

    String PARAGRAPH_TEMPLATE = 
            "<w:r wsp:rsidRPr=\"00FE5527\">"
            +"\n            <w:r>"
            +"\n                    {styleText}"
            +"\n                    <w:t>{value}</w:t>"
            +"\n            </w:r>";
            "</w:r>";

For convention, we use a place holder for the actual paragraph content ({value}).

We will talk about the other place holder ({styleText}) later.

Time to replace the place holder and return the getContent();

      public String getContent() {
         return PARAGRAPH_TEMPLATE.replace("{value}", this.value);   
      }

And I would utilize like that:

   IDocument myDoc = new Document2004();
   myDoc.addEle(Paragraph.with("Leonardo").create()) );

##Time to create your Unit Tests (or TDD, up to you).##

Create a class ParagraphTest.java and extend Assert. This is one example of unit test:

    @Test
    public void sanityTestParagraph() {
        IElement par = Paragraph.with("par01").withStyle().align(Align.CENTER).create();

       assertEquals(1, TestUtils.regexCount(par.getContent(), <w:t>par01</w:t>"));
       assertEquals(1, TestUtils.regexCount(par.getContent(), "<w:p wsp:rsidR="));
       assertEquals(2, TestUtils.regexCount(par.getContent(), "<*w:r>"));
       assertEquals(1, TestUtils.regexCount(par.getContent(), "</w:p>"));
       assertEquals(2, TestUtils.regexCount(par.getContent(), "<*w:pPr>"));
    }

Not finished yet, you need to know if your new element really works in a real Microsoft Word document. Create another dummy and temporary test in Document2004Test.java. Eg.:

    @Test
    public void testParagraph() {
        IDocument myDoc = new Document2004();
        myDoc.addEle(Paragraph.with("Leonardo").create()) );
        
    }

##You have two options now##

  • Option 2 - Generate Document (don't need j2w-webtest at all) * in your unit test, add the method: TestUtils.createLocalDoc(myDoc.getContent()); * Open build.properties and change the property "tmp.docs.dir" to any directory in your machine (Desktop or whatever) * This should create the test document in your directory of choice. * Open the file and see if makes sense and the paragraph is there. * don't commit this test as this is only to test end result in a real MS Word. Am still thinking in a better way to handle this.

  • Option 2 - j2w-webtest * Print out the XML content of the document from your unit test: System.out.println(myDoc.getContent()); * Copy this value to clip board * Deploy j2w-webtest in your tomcat * access the url localhost:8080/j2w-webtest * paste the content and click in "get Word Document" * Open the file and see if makes sense.

I use option 1 and set "tmp.docs.dir" to my desktop to quickly open the document.

##Important thing in Java2word##

There is no pressure or dead line to meet. We can try to use the latest technologies and the best of everything.

##Code Metrics##

Take a look at the ANT file or run ```ant -p```   to see the list of tasks. I add the *build.xml* to my eclipse and run it in one click.
  • Cobertura: Coverage test should be something decent.
  • Cyclomatic Complexity: You can see that all methods are small. The highest CC was 7. I don't recommend anything higher than 7 in this API.
  • PMD, CPD, Findbugs: you should occasionally have a look if there is any issue.
  • Checkstyle: I don't care too much about this one.

##Develpment patterns in Java2word##

  • don't use any deprecated method in the API.
  • always create code examples or unit tests using fluent API.
  • look at other elements to have an idea about the pattern in the project,
  • unit tests, cyclomatic complexity matter here!
  • Don't rely only in unit tests. Open in a real document.
  • always write style code in a separate class. ParagraphStyle.java would be the one here. Test the paragraph content and style in the class ParagraphTest , by write unit test against Paragraph.java element. This way you show other devs how to use the element.
Clone this wiki locally