title: iText add Watermark to selected pages
body: <p>I need to add a watermark to every page that has certain text, such as "PROCEDURE DELETED".</p>
  
  <p>Based on Bruno Lowagie's suggestion in <a href="https://stackoverflow.com/questions/21575630/adding-watermark-directly-to-the-stream/21577767#comment44808982_21577767">Adding watermark directly to the stream</a></p>
  
  <p>So far have the PdfWatermark Class with:</p>
  
  <pre><code>protected Phrase watermark = new Phrase("DELETED", new Font(FontFamily.HELVETICA, 60, Font.NORMAL, BaseColor.PINK));
  ArrayList&lt;Integer&gt; arrPages = new ArrayList&lt;Integer&gt;();
  boolean pdfChecked = false;
  
  @Override
  public void onEndPage(PdfWriter writer, Document document) {
  
      if(pdfChecked == false) {
          detectPages(writer, document);
          pdfChecked = true;
      } 
      int pageNum = writer.getPageNumber();
  
      if(arrPages.contains(pageNum)) {
          PdfContentByte canvas = writer.getDirectContentUnder();
          ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, watermark, 298, 421, 45);
      }
  }
  </code></pre>
  
  <p>And this works fine if I add, say, the number 3 to the arrPages ArrayList in my custom detectPages method - it shows the desired watermark on page 3.</p>
  
  <p>What I am having trouble with is how to search through the document for the text string, which I have access to here, only from the PdfWriter writer or the com.itextpdf.text.Document document sent to onEndPage method.</p>
  
  <p>Here is what I have tried, unsuccessfully:</p>
  
  <pre><code> private void detectPages(PdfWriter writer, Document document) {
      try {
  
          //arrPages.add(3);
  
          ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
          PdfWriter.getInstance(document, byteArrayOutputStream);
          //following code no work
          PdfReader reader = new PdfReader(writer.getDirectContent().getPdfDocument());
          PdfContentByte canvas = writer.getDirectContent();
          PdfImportedPage page;
  
          for (int i = 0; i &lt; reader.getNumberOfPages(); ) {    
              page = writer.getImportedPage(reader, ++i);
              canvas.addTemplate(page, 1f, 0, 0.4f, 0.4f, 72, 50 * i);
              canvas.beginText();
              canvas.showTextAligned(Element.ALIGN_CENTER,
  
                      //search String
                      String.valueOf((char)(181 + i)), 496, 150 + 50 * i, 0);
  
                      //if(detected) arrPages.add(i);
  
              canvas.endText();
          }
  </code></pre>
  
  <p>Am I on the right track with this as a solution or do I need to back out?</p>
  
  <p>Can anyone supply the missing link needed to scan the doc and pick out "PROCEDURE DELETED" pages?</p>
  
  <p>EDIT: I am using iText 5.0.4 - cannot upgrade to 5.5.X at this time, but could probably upgrade to latest version below that.</p>
  
  <p>EDIT2: More information: This is approach to adding text to the document (<code>doc</code>):</p>
  
  <pre><code>        String processed = processText(template);
          List&lt;Element&gt; objects = HTMLWorker.parseToListLog(new StringReader(processed),
                  styles, interfaceProps, errors);
          for (Element elem : objects) {
              doc.add(elem);
  
          }
  </code></pre>
  
  <p>That is called in an <code>addText</code> method I control. The <code>template</code> is simply html from a database LOB. The <code>processText</code> checks the html for custom markers contained by curlies as in <code>${replaceMe}</code>.</p>
  
  <p>This seems to be the place to identify the "PROCEDURE DELETED" string during generation of the document, but I don't see the path to Chunk.setGenericTags().</p>
  
  <p>EDIT3: Table difficulties</p>
  
  <pre><code>        List&lt;Element&gt; objects = HTMLWorker.parseToListLog(new StringReader(processed),
                  styles, interfaceProps, errors);
          for (Element elem : objects) { 
              //Code below no work
              if (elem instanceof PdfPTable) {
                  PdfPTable table = (PdfPTable) elem;
                  ArrayList&lt;Chunk&gt; chks = table.getChunks();
                  for(Chunk chk : chks){
                      if(chk.toString().contains("TEST DELETED")) {
                          chk.setGenericTag("delete_tag");
                      }
                  }                       
              }
  
              doc.add(elem);
          }
  </code></pre>
  
  <p>Commenters mlk and Bruno suggested to detect the "PROCEDURE DELETED" keywords at the time they are added to the doc. However, since the keywords are necessarily inside a table, they have to be detected through PdfPTable rather than the simpler Element. </p>
  
  <p>I could not do it with the code above. Any suggestions exactly how to find text inside a table cell and do a string comparison on it?</p>
  
  <p>EDIT4: Based on some experimentation, I would like to make some assertions and please show me the way through them:</p>
  
  <ol>
  <li>Using <code>Chunk.setGenericTag()</code> is required to trigger the handler <code>onGenericTag</code></li>
  <li>For some reason <code>(PdfPTable) table.getChunks()</code> does not return chunks, at least that my system picks up. This is counterintuitive and possibly there is a setup, version, or code bug causing this behavior.</li>
  <li>Therefore, a selection text string inside a table cannot be used to trigger a watermark.</li>
  </ol>