# BufferList.java

    /*
    ** Module   : BufferList.java
    ** Abstract : stores the list of all buffers by the same name in a source file
    **
    ** Copyright (c) 2005-2019, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- --JPRM-- ----------------Description-----------------
    ** 001 GES 20050922   @22788 First version which provides a helper class to store the list of all
    **                           buffers by the same name in a source file.  This allows the complete
    **                           list of buffer scopes to be managed during pattern engine processing.
    ** 002 GES 20060417   @25565 Added zombie list support.
    ** 003 GES 20090518   @42375 Import change.
    ** 004 GES 20100819          Use a different map to provide a stable iteration order.
    ** 005 SVL 20130213          Added readOnly property.
    ** 006 SVL 20131115          Added forceDMOAlias and dynamicTable properties.
    ** 007 OM  20161007          Code maintenance (generified, typo fix, javadoc).
    ** 008 CA  20190128          Track buffer's static state (if OO).
    ** 009 CA  20190513          Fixed buffer usage from super-classes, in OO.
    */
    /*
    ** 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.convert;

    import java.util.*;
    import com.goldencode.ast.*;
    import com.goldencode.p2j.uast.*;

    /**
     * This class contains the data and helper methods to implement/manage the
     * buffer scoping process during conversion.  Each instance of a buffer list
     * corresponds with the list of all buffer scopes by that given name.  This
     * class also allows other state to be stored related to this given buffer
     * name.
     */
    public class BufferList
    {
       /** The Progress qualified buffer name being referenced. */
       private String uniqueName = null;

       /** The Progress buffer name being referenced. */
       private String bufName = null;

       /** Explicit DMO alias for the converted buffer. */
       private String forceDMOAlias = null;

       /** <code>true</code> if the buffer is for a dynamic table. */
       private boolean dynamicTable = false;

       /** The fully qualified Progress schema name being referenced. */
       private String schemaName = null;

       /** The explicit Progress buffer's Java name. */
       private String javaName = null;

       /** <code>true</code> if this is an explicit static buffer definition. */
       private boolean staticDef = false;

       /** The logical database name for the buffer. */
       private String dbName = null;

       /** <code>true</code> if the buffer was not explicitly defined. */
       private boolean implicit = false;

       /**
        * <code>true</code> if the buffer is read-only (like the OLD buffer of a
        * database WRITE trigger).
        */
       private boolean readOnly = false;

       /**
        * All <code>BufferScopeTracker</code> instances that use this buffer.
        * Provides a stable iteration order.
        */
       private Set<BufferScopeTracker> buffers = new LinkedHashSet<>();

       /** A staging area to temporarily hold a buffer until the block opens. */
       private BufferScopeTracker staged = null;

       /** A pending free reference for this buffer name. */
       private BufferScopeTracker pending = null;

       /** The current active buffer scope for this buffer name. */
       private BufferScopeTracker active = null;

       /** All non-scoping free references are stored in this special scope. */
       private BufferScopeTracker zombies = null;

       /** Flag indicating if this buffer is originating from a super-class. */
       private boolean inSuper = false;

       /**
        * Create an instance to track a buffer scope of a given buffer name
        * which is directly mapped to a specific fully-qualified schema name.
        *
        * @param    unique
        *           The buffer's qualified name.
        * @param    buf
        *           The buffer's Progress name.
        * @param    forceDMOAlias
        *           Explicit DMO alias for the converted buffer. Used for dynamic buffers.
        *           <code>null</code> if auto-converted alias should be used.
        * @param    schema
        *           The fully-qualified schema name referenced by this buffer.
        * @param    java
        *           The converted Java name for this buffer. <code>null</code>
        *           if this is an implicitly defined buffer.
        * @param    staticDef
        *           This is an explicit static buffer definition.
        * @param    dbname
        *           The logical database name for the buffer (this may be
        *           different from the database name in the schema parameter).
        * @param    implicit
        *           <code>true</code> if this buffer is being created due to
        *           an implicit record reference, <code>false</code> if the
        *           buffer was explicitly defined (e.g. with a DEFINE BUFFER
        *           statement).
        * @param    readOnly
        *           <code>true</code> if the buffer is read-only (like the OLD
        *           buffer of a database WRITE trigger).
        * @param    dynamicTable
        *           <code>true</code> if the buffer is for a dynamic table.
        */
       public BufferList(String  unique,
                         String  buf,
                         String  forceDMOAlias,
                         String  schema,
                         String  java,
                         boolean staticDef,
                         String  dbname,
                         boolean implicit,
                         boolean readOnly,
                         boolean dynamicTable)
       {
          uniqueName         = unique;
          bufName            = buf;
          this.forceDMOAlias = forceDMOAlias;
          schemaName         = schema;
          javaName           = java;
          this.staticDef     = staticDef;
          dbName             = dbname;
          this.implicit      = implicit;
          this.readOnly      = readOnly;
          this.dynamicTable  = dynamicTable;
       }

       /**
        * Set the {@link #inSuper} flag.
        *
        * @param    inSuper
        *           <code>true</code> if this buffer is inherited from a super-class.
        */
       public void setInSuper(boolean inSuper)
       {
          this.inSuper = true;
       }

       /**
        * Get the {@link #inSuper} flag.
        *
        * @return   <code>true</code> if this buffer is inherited from a super-class.
        */
       public boolean isInSuper()
       {
          return inSuper;
       }

       /**
        * Returns the buffer's qualified name.
        *
        * @return   The qualified buffer name.
        */
       public String getUniqueName()
       {
          return uniqueName;
       }

       /**
        * Returns the buffer's name.
        *
        * @return   The buffer name.
        */
       public String getBufName()
       {
          return bufName;
       }

       /**
        * Get the explicit DMO alias for the converted buffer.
        *
        * @return  the explicit DMO alias for the converted buffer or <code>null</code>
        *          if this buffer uses auto-converted alias.
        */
       public String getForceDMOAlias()
       {
          return forceDMOAlias;
       }

       /**
        * Returns the fully-qualified schema name which is referenced by this buffer.
        *
        * @return   The schema name referenced by this buffer.
        */
       public String getSchemaName()
       {
          return schemaName;
       }

       /**
        * Returns the explicitly defined buffer's Java name which is the
        * converted name for this buffer.
        *
        * @return   The Java name for this buffer or <code>null</code> if this
        *           is not an explicitly defined buffer.
        */
       public String getJavaName()
       {
          return javaName;
       }

       /**
        * Returns the logical database name for the buffer.  This may be
        * different from the database portion of the fully qualified schema
        * name.
        *
        * @return   The logical database for this buffer.
        */
       public String getDbName()
       {
          return dbName;
       }

       /**
        * Specifies if the buffer was created due to an implicit record reference
        * or due to an explicit definition (e.g. DEFINE BUFFER).
        *
        * @return   <code>true</code> if the buffer was created due to an
        *           implicit record reference, <code>false</code> otherwise.
        */
       public boolean getImplicit()
       {
          return implicit;
       }

       /**
        * Specifies if the buffer is explicitly defined as static.
        *
        * @return  <code>true</code> if the buffer is static.
        */
       public boolean isStaticDef()
       {
          return staticDef;
       }

       /**
        * Specifies if the buffer is read-only (like the OLD buffer of a database WRITE trigger).
        *
        * @return  <code>true</code> if the buffer is read-only.
        */
       public boolean isReadOnly()
       {
          return readOnly;
       }

       /**
        * Specifies if this instance tracks a buffer of a dynamic table.
        *
        * @return  {@code true} if this tracks a buffer of a dynamic table.
        */
       public boolean isDynamicTable()
       {
          return dynamicTable;
       }

       /**
        * Accesses the current staged strong or weak reference for this buffer name.
        *
        * @return   The staged strong or weak reference or <code>null</code> if
        *           there is no staged reference.
        */
       public BufferScopeTracker getStaged()
       {
          return staged;
       }

       /**
        * Sets the current staged strong or weak reference for this buffer name.
        *
        * @param    staged
        *           The strong or weak reference to stage or <code>null</code> to
        *           clear the staged reference.
        */
       public void setStaged(BufferScopeTracker staged)
       {
          this.staged = staged;
       }

       /**
        * Accesses the current pending (unbound) free reference for this buffer name.
        *
        * @return   The pending unbound free reference or <code>null</code> if
        *           there is no pending free reference.
        */
       public BufferScopeTracker getPending()
       {
          return pending;
       }

       /**
        * Sets the current pending (unbound) free reference for this buffer name.
        *
        * @param    pending
        *           The pending unbound free reference or <code>null</code> to
        *           clear the pending free reference.
        */
       public void setPending(BufferScopeTracker pending)
       {
          this.pending = pending;
       }

       /**
        * Accesses the current active buffer scope for this buffer name.
        *
        * @return   The active buffer scope or <code>null</code> if there is no
        *           active buffer scope.
        */
       public BufferScopeTracker getActive()
       {
          return active;
       }

       /**
        * Sets the current active buffer scope for this buffer name.
        *
        * @param    active
        *           The active buffer scope or <code>null</code> to
        *           clear the current active scope.
        */
       public void setActive(BufferScopeTracker active)
       {
          this.active = active;
       }

       /**
        * Accesses the list of zombie nodes for this buffer name.  A zombie node
        * is an AST that is marked as a <code>NO_REFERENCE</code> so that it
        * has no affect on buffer scoping calcuations BUT it is still tracked
        * and assigned a buffer such that the references can be resolved at
        * runtime since such references really do access data.
        *
        * @return   The list of zombie nodes or <code>null</code> if there were
        *           no such nodes for this buffer.
        */
       public BufferScopeTracker getZombies()
       {
          return zombies;
       }

       /**
        * Add a new buffer scope to the list of all buffer scopes for the current file.
        *
        * @param    bst
        *           The scope to add.
        */
       public void addBufferScope(BufferScopeTracker bst)
       {
          buffers.add(bst);
       }

       /**
        * Remove a buffer scope from the list of all buffer scopes for the current file.
        *
        * @param    bst
        *           The scope to remove.
        */
       public void removeBufferScope(BufferScopeTracker bst)
       {
          buffers.remove(bst);
       }

       /**
        * Returns an iterator to the list of buffer scopes associated with this buffer name.
        *
        * @return   An iterator to all {@link BufferScopeTracker} instances
        *           associated with this buffer name.
        */
       public Iterator getScopeList()
       {
          return buffers.iterator();
       }

       /**
        * Add a node to the zombie list, creating the zombie list first if needed.
        * <p>
        * A zombie node is an AST that is marked as a <code>NO_REFERENCE</code>
        * so that it has no affect on buffer scoping calcuations BUT it is still
        * tracked and assigned a buffer such that the references can be resolved
        * at runtime since such references really do access data.
        *
        * @param    node
        *           The zombie node to add.
        */
       public void addZombie(Aast node)
       {
          if (zombies == null)
          {
             int type = ProgressParserTokenTypes.FREE_REFERENCE;
             zombies = new BufferScopeTracker(type);
          }

          zombies.addReference(node);
       }
    }