class PDFTextStripperByArea extends PDFTextStripper
{
    private final List<String> regions = new ArrayList<>();
    private final Map<String, Rectangle2D> regionArea = new HashMap<>();
    private final Map<String, ArrayList<List<TextPosition>>> regionCharacterList
            = new HashMap<>();
    private final Map<String, StringWriter> regionText = new HashMap<>();

    /**
     * Constructor.
     * @throws IOException If there is an error loading properties.
     */
    public PDFTextStripperByArea() throws IOException
    {
        super.setShouldSeparateByBeads(false);
    }

    /**
     * This method does nothing in this derived class, because beads and regions are incompatible. Beads are
     * ignored when stripping by area.
     *
     * @param aShouldSeparateByBeads The new grouping of beads.
     */
    @Override
    public final void setShouldSeparateByBeads(boolean aShouldSeparateByBeads)
    {
    }

   /**
     * Add a new region to group text by.
     *
     * @param regionName The name of the region.
     * @param rect The rectangle area to retrieve the text from. The y-coordinates are java
     * coordinates (y == 0 is top), not PDF coordinates (y == 0 is bottom).
     */
    public void addRegion( String regionName, Rectangle2D rect )
    {
        regions.add( regionName );
        regionArea.put( regionName, rect );
    }

    /**
     * Delete a region to group text by. If the region does not exist, this method does nothing.
     *
     * @param regionName The name of the region to delete.
     */
    public void removeRegion(String regionName)
    {
        regions.remove(regionName);
        regionArea.remove(regionName);
    }
    
    /**
     * Get the list of regions that have been setup.
     *
     * @return A list of java.lang.String objects to identify the region names.
     */
    public List<String> getRegions()
    {
        return regions;
    }

    /**
     * Get the text for the region, this should be called after extractRegions().
     *
     * @param regionName The name of the region to get the text from.
     * @return The text that was identified in that region.
     */
    public String getTextForRegion( String regionName )
    {
        StringWriter text = regionText.get( regionName );
        return text.toString();
    }

    /**
     * Process the page to extract the region text.
     *
     * @param page The page to extract the regions from.
     * @throws IOException If there is an error while extracting text.
     */
    public void extractRegions( PDPage page ) throws IOException
    {<FILL_FUNCTION_BODY>}

    
    /**
     * {@inheritDoc}
     */
    @Override
    protected void processTextPosition(TextPosition text)
    {
        regionArea.forEach((key, rect) ->
        {
            if (rect.contains(text.getX(), text.getY()))
            {
                charactersByArticle = regionCharacterList.get(key);
                super.processTextPosition(text);
            }
        });
    }

    
    /**
     * This will print the processed page text to the output stream.
     *
     * @throws IOException If there is an error writing the text.
     */
    @Override
    protected void writePage() throws IOException
    {
        for (String region : regionArea.keySet())
        {
            charactersByArticle = regionCharacterList.get( region );
            output = regionText.get( region );
            super.writePage();
        }
    }
}

        for (String regionName : regions)
        {
            setStartPage(getCurrentPageNo());
            setEndPage(getCurrentPageNo());
            // reset the stored text for the region so this class can be reused.
            ArrayList<List<TextPosition>> regionCharactersByArticle = new ArrayList<>();
            regionCharactersByArticle.add(new ArrayList<>());
            regionCharacterList.put( regionName, regionCharactersByArticle );
            regionText.put( regionName, new StringWriter() );
        }
        
        if( page.hasContents() )
        {
            processPage( page );
        }
    
<methods>public void <init>() ,public boolean getAddMoreFormatting() ,public java.lang.String getArticleEnd() ,public java.lang.String getArticleStart() ,public float getAverageCharTolerance() ,public float getDropThreshold() ,public org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem getEndBookmark() ,public int getEndPage() ,public float getIndentThreshold() ,public java.lang.String getLineSeparator() ,public java.lang.String getPageEnd() ,public java.lang.String getPageStart() ,public java.lang.String getParagraphEnd() ,public java.lang.String getParagraphStart() ,public boolean getSeparateByBeads() ,public boolean getSortByPosition() ,public float getSpacingTolerance() ,public org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem getStartBookmark() ,public int getStartPage() ,public boolean getSuppressDuplicateOverlappingText() ,public java.lang.String getText(org.apache.pdfbox.pdmodel.PDDocument) throws java.io.IOException,public java.lang.String getWordSeparator() ,public void processPage(org.apache.pdfbox.pdmodel.PDPage) throws java.io.IOException,public void setAddMoreFormatting(boolean) ,public void setArticleEnd(java.lang.String) ,public void setArticleStart(java.lang.String) ,public void setAverageCharTolerance(float) ,public void setDropThreshold(float) ,public void setEndBookmark(org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem) ,public void setEndPage(int) ,public void setIndentThreshold(float) ,public void setLineSeparator(java.lang.String) ,public void setPageEnd(java.lang.String) ,public void setPageStart(java.lang.String) ,public void setParagraphEnd(java.lang.String) ,public void setParagraphStart(java.lang.String) ,public void setShouldSeparateByBeads(boolean) ,public void setSortByPosition(boolean) ,public void setSpacingTolerance(float) ,public void setStartBookmark(org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem) ,public void setStartPage(int) ,public void setSuppressDuplicateOverlappingText(boolean) ,public void setWordSeparator(java.lang.String) ,public void writeText(org.apache.pdfbox.pdmodel.PDDocument, java.io.Writer) throws java.io.IOException<variables>private static final float END_OF_LAST_TEXT_X_RESET_VALUE,private static final float EXPECTED_START_OF_NEXT_WORD_X_RESET_VALUE,private static final float LAST_WORD_SPACING_RESET_VALUE,protected static final java.lang.String LINE_SEPARATOR,private static final java.lang.String[] LIST_ITEM_EXPRESSIONS,private static final Logger LOG,private static final float MAX_HEIGHT_FOR_LINE_RESET_VALUE,private static final float MAX_Y_FOR_LINE_RESET_VALUE,private static final float MIN_Y_TOP_FOR_LINE_RESET_VALUE,private static final Map<java.lang.Character,java.lang.Character> MIRRORING_CHAR_MAP,private boolean addMoreFormatting,private java.lang.String articleEnd,private java.lang.String articleStart,private float averageCharTolerance,private List<org.apache.pdfbox.pdmodel.common.PDRectangle> beadRectangles,private final Map<java.lang.String,TreeMap<java.lang.Float,TreeSet<java.lang.Float>>> characterListMapping,protected ArrayList<List<org.apache.pdfbox.text.TextPosition>> charactersByArticle,private int currentPageNo,private static float defaultDropThreshold,private static float defaultIndentThreshold,protected org.apache.pdfbox.pdmodel.PDDocument document,private float dropThreshold,private org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem endBookmark,private int endBookmarkPageNumber,private int endPage,private boolean inParagraph,private float indentThreshold,private java.lang.String lineSeparator,private List<java.util.regex.Pattern> listOfPatterns,protected java.io.Writer output,private java.lang.String pageEnd,private java.lang.String pageStart,private java.lang.String paragraphEnd,private java.lang.String paragraphStart,private boolean shouldSeparateByBeads,private boolean sortByPosition,private float spacingTolerance,private org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem startBookmark,private int startBookmarkPageNumber,private int startPage,private boolean suppressDuplicateOverlappingText,private java.lang.String wordSeparator