# TableResourceMap.java

    /*
    ** Module   : TableResourceMap.java
    ** Abstract : A mutable map to track table-level database resources
    **
    ** Copyright (c) 2018-2019, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- -------------------------------- Description --------------------------------
    ** 001 ECF 20180908 Created initial version.
    ** 002 CA  20190509 Changed remove() signature to return a boolean if something was removed or not.

    /*
    ** This program is free software: you can redistribute it and/or modify
    ** it under the terms of the GNU Affero General Public License as
    ** published by the Free Software Foundation, either version 3 of the
    ** License, or (at your option) any later version.
    **
    ** This program is distributed in the hope that it will be useful,
    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    ** GNU Affero General Public License for more details.
    **
    ** You may find a copy of the GNU Affero GPL version 3 at the following
    ** location: https://www.gnu.org/licenses/agpl-3.0.en.html
    **
    ** Additional terms under GNU Affero GPL version 3 section 7:
    **
    **   Under Section 7 of the GNU Affero GPL version 3, the following additional
    **   terms apply to the works covered under the License.  These additional terms
    **   are non-permissive additional terms allowed under Section 7 of the GNU
    **   Affero GPL version 3 and may not be removed by you.
    **
    **   0. Attribution Requirement.
    **
    **     You must preserve all legal notices or author attributions in the covered
    **     work or Appropriate Legal Notices displayed by works containing the covered
    **     work.  You may not remove from the covered work any author or developer
    **     credit already included within the covered work.
    **
    **   1. No License To Use Trademarks.
    **
    **     This license does not grant any license or rights to use the trademarks
    **     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
    **     of Golden Code Development Corporation. You are not authorized to use the
    **     name Golden Code, FWD, or the names of any author or contributor, for
    **     publicity purposes without written authorization.
    **
    **   2. No Misrepresentation of Affiliation.
    **
    **     You may not represent yourself as Golden Code Development Corporation or FWD.
    **
    **     You may not represent yourself for publicity purposes as associated with
    **     Golden Code Development Corporation, FWD, or any author or contributor to
    **     the covered work, without written authorization.
    **
    **   3. No Misrepresentation of Source or Origin.
    **
    **     You may not represent the covered work as solely your work.  All modified
    **     versions of the covered work must be marked in a reasonable way to make it
    **     clear that the modified work is not originating from Golden Code Development
    **     Corporation or FWD.  All modified versions must contain the notices of
    **     attribution required in this license.
    */

    package com.goldencode.p2j.schema;

    import java.io.*;
    import java.util.*;

    /**
     * A class to track table-level database resources (e.g., fields or indices), in order to support
     * reporting of unused resources during conversion. An instance is created and all such known
     * resources are added to it initially. As resources are identified as being referenced/used
     * during conversion, they are removed from the map. Those remaining in the map at the end of
     * conversion represent resources that are not referenced in static database code. The
     * {@link #writeContent(Writer, String)} method is used to write any remaining, unreferenced
     * resources into a lightly-formatted text stream.
     */
    public final class TableResourceMap
    {
       /** Map of qualified table names to sets of resource names within that table */
       private final SortedMap<String, SortedSet<String>> byTable = new TreeMap<>();

       /**
        * Default constructor.
        */
       public TableResourceMap()
       {
       }

       /**
        * Add a single resource to the map. Add a table entry to the map if this is the first
        * resource to be added which is associated with the given table.
        *
        * @param   table
        *          Qualified, normalized table name.
        * @param   resource
        *          Resource name.
        */
       public void add(String table, String resource)
       {
          SortedSet<String> resources = byTable.get(table);
          if (resources == null)
          {
             resources = new TreeSet<>();
             byTable.put(table, resources);
          }
          resources.add(resource);
       }

       /**
        * Remove a single resource from the map. Remove the table entry from the map if there are no
        * resources left in the set after the removal.
        *
        * @param   table
        *          Qualified, normalized table name.
        * @param   resource
        *          Resource name
        *
        * @return  If the table was removed.
        */
       public boolean remove(String table, String resource)
       {
          SortedSet<String> resources = byTable.get(table);
          if (resources != null && resources.remove(resource) && resources.isEmpty())
          {
             byTable.remove(table);

             return true;
          }

          return false;
       }

       /**
        * Indicate whether the resource map is empty.
        *
        * @return  {@code true} if empty, else {@code false}.
        */
       public boolean isEmpty()
       {
          return byTable.isEmpty();
       }

       /**
        * Write content for the remaining information, if any, in this resource map, once all
        * individual referenced resources have been removed.
        *
        * @param   writer
        *          Writer output stream.
        * @param   heading
        *          Heading for this resource map's section of the report.
        *
        * @throws  IOException
        *          if there is an error writing to the stream.
        */
       public void writeContent(Writer writer, String heading)
       throws IOException
       {
          if (isEmpty())
          {
             return;
          }

          String sep = System.lineSeparator();
          String dsep = sep + sep;
          String pad = "   ";
          String dpad = "      ";

          writer.write(heading + dsep);

          for (Map.Entry<String, SortedSet<String>> entry : byTable.entrySet())
          {
             String table = entry.getKey();
             SortedSet<String> resources = entry.getValue();

             writer.write(pad + "Table:  " + table + dsep);

             for (String resource : resources)
             {
                writer.write(dpad + resource + sep);
             }

             writer.write(sep);
          }

          writer.write(sep);
       }
    }