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);
   }   
}