ExtentTracker.java

/*
** Module   : ExtentTracker.java
** Abstract : Helper object to track extents during temp-table data import.
**
** Copyright (c) 2017-2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
** 001 ECF 20190123 Extracted from XmlImport.
** 002 OM  20201120 Small fix in constructor.
** 003 CA  20210510 Fixed JSON and XML serialization when XML-NODE-NAME/SERIALIZE-NAME field options are set.
** 004 CA  20240320 Avoid BDTs within internal FWD runtime.  Replaced iterators with Java 'for', where it 
**                  applies.
*/

/*
** 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.persist.serial;

import java.util.*;

/**
 * Helper object which tracks current and maximum index values for extent fields. This is
 * used to get the next index value needed for a setter method invocation when reading and
 * setting elements into an extent field in the current DMO. A range check is performed to
 * ensure too many array elements are not set.
 */
class ExtentTracker
{
   /** Extent index trackers mapped to XML content names for columns */
   private final Map<String, ExtentTracker.Tracker> trackers = new HashMap<>();
   
   /**
    * Constructor. Initializes a map for extent fields, if any, in a temp-table.
    * 
    * @param   schema
    *          Schema information for the temp-table.
    * @param   json
    *          Flag indicating if this is for JSON (when <code>true</code>) or XML (when <code>false</code>).
    */
   ExtentTracker(TempTableSchema schema, boolean json)
   {
      ArrayList<TempTableSchema.Column> columns = schema.columns();
      for (int k = 0; k < columns.size(); k++)
      {
         TempTableSchema.Column column = columns.get(k);

         Integer extent = column.getExtent();
         if (extent != null && extent > 0)
         {
            String name = json ? column.getSerializeName() : column.getXmlNodeName();
            ExtentTracker.Tracker tracker = new Tracker(extent);
            trackers.put(name, tracker);
         }
      }
   }
   
   /**
    * Reset the current index values to 0 for all extent fields being tracked.
    */
   void reset()
   {
      for (ExtentTracker.Tracker tracker : trackers.values())
      {
         tracker.reset();
      }
   }
   
   /**
    * Get the index value to be used to set the next element in the extent field associated
    * with the given name.
    * 
    * @param   name
    *          Name associated with column data in XML content.
    * 
    * @return  Next index value for extent field setter call.
    * 
    * @throws  ArrayIndexOutOfBoundsException
    *          if the current index value reaches the size of the extent field.
    */
   Integer getNext(String name)
   {
      ExtentTracker.Tracker tracker = trackers.get(name);
      
      return (tracker == null ? null : tracker.getNext());
   }
   
   /**
    * Helper which tracks current and maximum index values for a single extent field.
    */
   private static class Tracker
   {
      /** Size of extent field */
      private final int max;
      
      /** Current index value */
      private int current = 0;
      
      /**
       * Constructor.
       * 
       * @param   max
       *          Size of extent field.
       */
      Tracker(int max)
      {
         this.max = max;
      }
      
      /**
       * Get the index value to be used to set the next element in the extent field.
       * 
       * @return  Next index value for extent field setter call.
       * 
       * @throws  ArrayIndexOutOfBoundsException
       *          if the current index value reaches the size of the extent field.
       */
      Integer getNext()
      {
         if (current >= max)
         {
            throw new ArrayIndexOutOfBoundsException();
         }
         
         return current++;
      }
      
      /**
       * Reset the current value to 0.
       */
      void reset()
      {
         current = 0;
      }
   }
}