ProfilerUtils.java

/*
** Module   : Profiler.java
** Abstract : Defines APIs used to access the PROFILER attributes and methods.
**
** Copyright (c) 2018-2022, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
** 001 CA  20180510 Created initial version.
** 002 CA  20190423 Added DIRECTORY attribute and WRITE-DATA() method, stubs only.
** 003 CA  20200428 Added COVERAGE, TRACING, TRACE-FILTER and USER-DATA() stubs.
** 004 OM  20201030 Invalid attribute API support for getters/setters.
**     OM  20201203 Fixed handling of READ/ONLY attributes.
** 005 VVT 20221003 CommonHandle.getResourceType() method renamed to resourceType() to prevent conflicts
**                  with namesakes in DMO. See #6694.
*/

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

import com.goldencode.p2j.security.*;
import com.goldencode.proxy.*;

/**
 * This class provides implementation for PROFILER attributes and methods.
 * <p>
 * There is no behavior implemented for the PROFILER - the attributes values are saved and 
 * retrieved, and the methods are no-ops.
 */
public class ProfilerUtils
{
   /** Context local proxy that allows PROFILER attributes to be pushed from server to client. */
   private static final ContextLocal<WorkArea> work = new ContextLocal<WorkArea>()
   {
      /**
       * Initializes the work area, the first time it is requested within a new context.
       *
       * @return   The newly instantiated work area.
       */
      @Override
      protected WorkArea initialValue()
      {
         WorkArea wa = new WorkArea();

         return wa;
      }
   };

   /**
    * Get a the instance for the PROFILER system handle.  Is obtained using a call to the 
    * {@link StaticProxy#obtain(Class, Class[])}, using the {@link Profiler} interface and 
    * its methods implemented by these classes: {@link ProfilerUtils}.
    * 
    * @return   See above.
    */
   public static handle asHandle()
   {
      WorkArea wa = work.get();

      Class[] classes = 
      {
         ProfilerUtils.class
      };
      Profiler proxy = StaticProxy.obtain(Profiler.class, classes);

      if (wa.id == null)
      {
         wa.id = handle.resourceId(proxy);
      }

      return new handle(proxy);
   }
   
   /**
    * Get this resource's ID.
    * 
    * @return   The resource's ID.
    */
   public static Long id()
   {
      WorkArea wa = work.get();
      
      return wa.id;
   }
   
   /**
    * Set this resource's ID.
    * <p>
    * This is a no-op for system handles.
    *  
    * @param    id
    *           The resource's ID.
    */
   public static void id(long id)
   {
      // no-op
   }

   /**
    * Get the type of its associated handle.
    * 
    * @return   Always return the PSEUDO-WIDGET value.
    */
   public static character resourceType()
   {
      return new character(LegacyResource.PSEUDO_WIDGET);
   }
   
   /**
    * Implementation for the {@link WrappedResource#valid()} API.
    * 
    * @return   Always true.
    */
   public static boolean valid()
   {
      return true;
   }
   
   /**
    * Implementation for the {@link WrappedResource#unknown()} API.
    * 
    * @return   Always false.
    */
   public static boolean unknown()
   {
      return false;
   }
   
   /**
    * API needed to implement read-only attribute assignment (a 4GL "feature").
    * 
    * @param    attribute
    *           The attribute's name.
    *           
    * @see      handle#readOnlyError(handle, String)
    */
   public static void readOnlyError(String attribute)
   {
      ErrorManager.recordOrShowError(4052, attribute.toUpperCase(), "settable", LegacyResource.PSEUDO_WIDGET);
   }
   
   /**
    * API needed to implement read-only attribute assignment (a 4GL "feature").
    * 
    * @param    attribute
    *           The attribute's name.
    * @param    expr
    *           The value which is attempted to be assigned to the read-only attribute. 
    *
    * @see      handle#readOnlyError(handle, String, Object)
    */
   public static void readOnlyError(String attribute, Object expr)
   {
      ErrorManager.recordOrShowError(4052, attribute.toUpperCase(), "settable", LegacyResource.PSEUDO_WIDGET);
   }
   
   /**
    * Set the value of PROFILER:PROFILING attribute. 
    * 
    * @param   profiling 
    *          The new value of PROFILER:PROFILING attribute.
    */
   public static void setProfiling(logical profiling)
   {
      work.get().profiling = profiling != null && profiling.booleanValue();
   }

   /**
    * Get the value of PROFILER:PROFILING attribute. 
    * 
    * @return  the value of PROFILER:PROFILING attribute.
    */
   public static logical isProfiling()
   {
      return new logical(work.get().profiling);
   }

   /**
    * Set the value of PROFILER:ENABLED attribute. 
    * 
    * @param   enabled 
    *          The new value of PROFILER:ENABLED attribute.
    */
   public static void setEnabled(logical enabled)
   {
      work.get().enabled = enabled != null && enabled.booleanValue();
   }

   /**
    * Set the value of PROFILER:ENABLED attribute. 
    * 
    * @param   enabled 
    *          The new value of PROFILER:ENABLED attribute.
    */
   public static void setEnabled(boolean enabled)
   {
      work.get().enabled = enabled;
   }

   /**
    * Get the value of PROFILER:ENABLED attribute. 
    * 
    * @return  the value of PROFILER:ENABLED attribute.
    */
   public static logical isEnabled()
   {
      return new logical(work.get().enabled);
   }

   /**
    * Set the value of PROFILER:DESCRIPTION attribute. 
    * 
    * @param   description 
    *          The new value of PROFILER:DESCRIPTION attribute.
    */
   public static void setDescription(character description)
   {
      work.get().description = description == null || description.isUnknown() 
                                 ? null
                                 : description.toStringMessage();
   }

   /**
    * Get the value of PROFILER:DESCRIPTION attribute. 
    * 
    * @return  the value of PROFILER:DESCRIPTION attribute.
    */
   public static character getDescription()
   {
      return new character(work.get().description);
   }

   /**
    * Set the value of PROFILER:DIRECTORY attribute. 
    * 
    * @param   directory
    *          The new value of PROFILER:DIRECTORY attribute.
    */
   public static void setDirectory(character directory)
   {
      UnimplementedFeature.missing("PROFILER:DIRECTORY");
   }

   /**
    * Get the value of PROFILER:DIRECTORY attribute. 
    * 
    * @return  the value of PROFILER:DIRECTORY attribute.
    */
   public static character getDirectory()
   {
      UnimplementedFeature.missing("PROFILER:DIRECTORY");
      return new character();
   }

   /**
    * Set the value of PROFILER:LISTINGS attribute. 
    * 
    * @param   listings 
    *          The new value of PROFILER:LISTINGS attribute.
    */
   public static void setListings(logical listings)
   {
      work.get().listings = listings != null && listings.booleanValue();
   }

   /**
    * Get the value of PROFILER:LISTINGS attribute. 
    * 
    * @return  the value of PROFILER:LISTINGS attribute.
    */
   public static logical isListings()
   {
      return new logical(work.get().listings);
   }

   /**
    * Get the value of PROFILER:FILENAME attribute. 
    * 
    * @return  the value of PROFILER:FILENAME attribute.
    */
   public static character getFileName()
   {
      return new character(work.get().filename);
   }

   /**
    * Set the value of PROFILER:FILENAME attribute. 
    * 
    * @param   filename 
    *          The new value of PROFILER:FILENAME attribute.
    */
   public static void initFileInfo(character filename)
   {
      work.get().filename = filename == null || filename.isUnknown() 
                               ? null
                               : filename.toStringMessage();
   }

   /**
    * Set the value of PROFILER:FILENAME attribute. 
    * 
    * @param   filename 
    *          The new value of PROFILER:FILENAME attribute.
    */
   public static void initFileInfo(String filename)
   {
      work.get().filename = filename;
   }
   
   /**
    * Definition of the PROFILER:USER-DATA() method. 
    * 
    * @param    data
    *           The data.
    *           
    * @return   <code>true</code> if the data was written.
    */
   public static logical userData(String data)
   {
      UnimplementedFeature.missing("PROFILER:USER-DATA()");
      return new logical(false);
   }
   
   /**
    * Definition of the PROFILER:USER-DATA() method. 
    * 
    * @param    data
    *           The data.
    *           
    * @return   <code>true</code> if the data was written.
    */
   public static logical userData(character data)
   {
      UnimplementedFeature.missing("PROFILER:USER-DATA()");
      return new logical(false);
   }

   /**
    * Definition of the PROFILER:WRITE-DATA() method. 
    * 
    * @return   <code>true</code> if the data was written.
    */
   public static logical writeData()
   {
      UnimplementedFeature.missing("PROFILER:WRITE-DATA()");
      return new logical();
   }
   
   /**
    * Get the PROFILER:TRACE-FILTER attribute.
    * 
    * @return  the value of PROFILER:TRACE-FILTER attribute.
    */
   public static character getTraceFilter()
   {
      UnimplementedFeature.missing("PROFILER:TRACE-FILTER");
      return new character();
   }
   
   /**
    * Set the PROFILER:TRACE-FILTER attribute.
    * 
    * @param    filter
    *           The filter value.
    */
   public static void setTraceFilter(String filter)
   {
      UnimplementedFeature.missing("PROFILER:TRACE-FILTER");
   }
   
   /**
    * Set the PROFILER:TRACE-FILTER attribute.
    * 
    * @param    filter
    *           The filter value.
    */
   public static void setTraceFilter(character filter)
   {
      UnimplementedFeature.missing("PROFILER:TRACE-FILTER");
   }
   
   
   /**
    * Get the PROFILER:TRACING attribute.
    * 
    * @return  the value of PROFILER:TRACING attribute.
    */
   public static character getTracing()
   {
      UnimplementedFeature.missing("PROFILER:TRACING");
      return new character();
   }
   
   /**
    * Set the PROFILER:TRACING attribute.
    * 
    * @param    procs
    *           The comma-separated list of procedures.
    */
   public static void setTracing(String procs)
   {
      UnimplementedFeature.missing("PROFILER:TRACING");
   }
   
   /**
    * Set the PROFILER:TRACING attribute.
    * 
    * @param    procs
    *           The comma-separated list of procedures.
    */
   public static void setTracing(character procs)
   {
      UnimplementedFeature.missing("PROFILER:TRACING");
   }
   
   
   /**
    * Get the PROFILER:COVERAGE attribute.
    * 
    * @return  the value of PROFILER:COVERAGE attribute.
    */
   public static logical isCoverage()
   {
      UnimplementedFeature.missing("PROFILER:COVERAGE");
      return new logical(false);
   }
   
   /**
    * Set the PROFILER:COVERAGE attribute.
    * 
    * @param    coverage
    *           The flag state.
    */
   public static void setCoverage(boolean coverage)
   {
      UnimplementedFeature.missing("PROFILER:COVERAGE");
   }
   
   /**
    * Set the PROFILER:COVERAGE attribute.
    * 
    * @param    coverage
    *           The flag state.
    */
   public static void setCoverage(logical coverage)
   {
      UnimplementedFeature.missing("PROFILER:COVERAGE");
   }
   /**
    * Stores global data relating to the state of the current context.
    */
   private static class WorkArea
   {
      /** The resource's ID. */
      private Long id = null;
      
      /** The state of the PROFILER:ENABLED attribute. */
      private boolean enabled = false;
      
      /** The state of the PROFILER:LISTINGS attribute. */
      private boolean listings = false;
      
      /** The state of the PROFILER:PROFILING attribute. */
      private boolean profiling = false;
      
      /** The value of the PROFILER:DESCRIPTION attribute. */
      private String description = null;
      
      /** The value of the PROFILER:FILENAME attribute. */
      private String filename = null;
   }
}