Search code examples
javaitextwrapperparagraph

How to wrap multiple paragraphs in one element?


I'm creating a fairly complex PDF document in Java using iText 5. I add a bunch of Paragraph objects to my document. To improve readability of my code, I would like to create multiple methods to create different aspects of the document.

What type can I use to wrap multiple Paragraph objects in one unit, so I can return them from my sub-methods? The Element class does not have an add() method, nor does the Chunk class.

I tried Phrase, but then I lose all line breaks. Wrapping my Paragraph objects in another Paragraph object produces the desired output, but it feels odd, and I fear that the wrapping paragraph might introduce additional margins in the document.

So what is the best type for wrapping Paragraph objects in order to group them logically?


Code example

My current code:

Document doc = new Document(...);
doc.add(new Paragraph("Aspect A.1"));
doc.add(new Paragraph("Aspect A.2"));
doc.add(new Paragraph("Aspect A.3"));

doc.add(new Paragraph("Aspect B.1"));
doc.add(new Paragraph("Aspect B.2"));

What I'm striving for:

Document doc = new Document(...);
doc.add(createAspectA());
doc.add(createAspectB());

// ...

private WrapperElement createAspectA() {
  WrapperElement wrapper = new WrapperElement(...);

  wrapper.add(new Paragraph("Aspect A.1"));
  wrapper.add(new Paragraph("Aspect A.2"));
  wrapper.add(new Paragraph("Aspect A.3"));

  return wrapper;
}

private WrapperElement createAspectB() {
  WrapperElement wrapper = new WrapperElement(...);

  wrapper.add(new Paragraph("Aspect B.1"));
  wrapper.add(new Paragraph("Aspect B.2"));

  return wrapper;
}

Solution

  • Wrapping my Paragraph objects in another Paragraph object produces the desired output, but it feels odd

    While this indeed may feel odd, it does work and is a use case explicitly considered in the code. (For example look at the code of Paragraph.breakUp() and the inherited Phrase.process(ElementListener).)

    and I fear that the wrapping paragraph might introduce additional margins in the document

    It only does if you ask it to (using setIndentationLeft(float) / setIndentationRight(float) / setSpacingAfter(float) / setSpacingBefore(float)). Thus, you have the option to add extra indentation but you are not unwillingly subject to unwanted extra indentation.


    On the other hand, if you want to be 100% sure that there cannot be any unwanted influence, you can simply return an ordered Iterable<Element>, e.g. an ArrayList<Element>, and change the adding to the document to a forEach call:

    private Iterable<Element> createAspectA() {
        ArrayList<Element> wrapper = new ArrayList<>();
    
        wrapper.add(new Paragraph("Aspect A.1"));
        wrapper.add(new Paragraph("Aspect A.2"));
        wrapper.add(new Paragraph("Aspect A.3"));
    
        return wrapper;
    }
    

    and replace

    doc.add(createAspectA());
    

    by

    for (Element e : createAspectA())  doc.add(e);
    

    (Unfortunately doc.add throws tagged exceptions, otherwise it could have been createAspectA().forEach(doc::add).)