# integer.java

    /*
    ** Module   : integer.java
    ** Abstract : Progress 4GL compatible integer object
    **
    ** Copyright (c) 2005-2025, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- --JPRM-- ----------------------------Description----------------------------
    ** 001 GES 20050517   @21251 Created initial version with full support
    **                           for all Progress integer processing including
    **                           some functions like integer, minimum and
    **                           maximum.
    ** 002 GES 20050607   @21443 Minor additions for function support.
    ** 003 GES 20050614   @21489 Added increment and decrement methods.
    ** 004 GES 20050621   @21533 Added an assign() method to modify this
    **                           instance's state based on the result of
    **                           an expression of compatible type.
    ** 005 SVG 20050720   @21767 Cloning support for BaseDataType added.
    ** 006 GES 20050822   @22192 Added Undoable interface support.
    ** 007 GES 20050830   @22384 Added error condition processing.
    ** 008 ECF 20051004   @22970 Implement hashCode() method. Required to be
    **                           consistent with BaseDataType's implementation
    **                           of equals() method.
    ** 009 GES 20060123   @24024 Implemented support for decimal and group
    **                           separator overrides.
    ** 010 GES 20060206   @24301 Made compareTo() safe to process any object
    **                           type (avoids ClassCastException).
    ** 011 GES 20060405   @25368 Support any NumberType in lists for min/max.
    ** 012 GES 20060417   @25555 Added default value generation.
    ** 013 GES 20060530   @26665 Fixed issue with "hh:mm" formatting where the
    **                           hours could be returned with only 1 digit.
    ** 014 NVS 20060602   @26937 Fixed assign() method for unknown values.
    ** 015 GES 20060724   @28162 Added a forced assign() abstract method.
    ** 016 GES 20060807   @28474 Moved to externalizable interface to optimize
    **                           network performance.
    ** 017 ECF 20060812   @28588 Added methods needed for database server-side
    **                           function support.
    ** 018 GES 20060825   @28900 Added context local default format data.
    ** 019 SIY 20070405   @32825 Part of numbers conversion quirk handling.
    ** 020 GES 20080911   @39790 Added assign(int) and assign(double)
    **                           signatures.
    ** 021 ECF 20090212   @41299 Implemented a faster equals(). Handles most
    **                           common cases without having to invoke the
    **                           superclass' implementation. Also added
    **                           several assign() variants and optimized
    **                           compareTo() for the common case.
    ** 022 SVL 20090225   @41367 Make class not final.
    ** 023 SVL 20090824   @43722 "force" parameter should be false by default into
    **                           assign(integer).
    ** 024 SVL 20090908   @43845 Fixed handling of large integers.
    ** 025 GES 20091102   @44301 Time format string processing was incorrect when
    **                           the value is a large enough negative to cross
    **                           back over the DST boundary. Removed all J2SE
    **                           date/time processing and duplicated the Progress
    **                           result directly.
    ** 026 GES 20110303          Moved maximum/minimum to varargs.
    ** 027 OM  20121220          Added int64 support.
    ** 028 CA  20130123          Added c'tor which builds a new instance from a
    **                           BaseDataType value, if possible. This should be
    **                           used only when constructing an instance using the
    **                           value returned by a DYNAMIC-FUNCTION call; 4GL
    **                           does some special casting in this case, which is
    **                           not implemented yet.
    ** 029 CS  20130124          Added conversion support for memptr related
    **                           functions task #1635
    ** 030 GES 20130126          Changed some constructors to handle NumberType.
    ** 031 GES 20130322          Fixed the BDT c'tor and modified the assign(BDT,boolean) to be the
    **                           common location for the _POLY morphing. This is safe because all
    **                           current usage would have generated a ClassCastException if that
    **                           method was ever used with an invalid type. Now, instead of the CCE,
    **                           the code will morph the value as is possible. The morphing code
    **                           still needs to be implemented.
    ** 032 OM  20130328          Added missing runtime implementation. Changed the architecture so
    **                           that this class is derived from int64. All assignments will call
    **                           checkBounds in order to check if the new value fits inside 32 bit
    **                           bounds. Most of the duplicate code common with int64 was removed
    **                           and will be accessible through inheritance.
    ** 033 OM  20130710          Removed unneeded conversion from Date.
    ** 034 GES 20140115          Handle quirky out of bounds error message in an obscure case.
    ** 035 ECF 20150427          Override assign(NumberType, boolean) method to bypass the superclass'
    **                           much more expensive implementation for the most common use case.
    ** 036 OM  20150630          Converting a DATETIME to INT is an error.
    ** 037 CA  20151222          Added instantiateDefaultExtent.
    ** 038 IAS 20160331          Fixed potential NPE
    ** 039 ECF 20160614          Implemented faster copy constructor.
    ** 040 GES 20171207          Removed explicit bypass on pending error (new silent error mode).
    ** 041 GES 20200520          Added 4GL enum constructor.
    **     GES 20200603          The INTEGER() built-in must not set error-status:error on failures.
    ** 042 IAS 20201007          Added Type enum
    ** 043 CA  20210216          If a RETURN <expr>; in a functions returns a runtime int64 value and the function
    **                           is 'return integer', then the value must be set to unknown.  For this reason,
    **                           the 'isAssignDirect' protection was added in 'assign'.
    ** 044 AL2 20220328          Added proxy checks for BDT.
    ** 045 CA  20230215          'duplicate()' method returns the real type instead of BDT.
    ** 046 ICP 20250123          Added integer constant, static and dynamic cache support - these are immutable
    **                           instances which must not 'escape' from FWD runtime, and only used via
    **                           assignment or as read-only.
    */

    /*
    ** 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 java.io.*;
    import java.util.function.*;

    import com.goldencode.p2j.oo.lang.*;
    import com.goldencode.p2j.persist.*;
    import com.goldencode.p2j.util.logging.*;

    /**
     * A class that represents a Progress 4GL compatible integer object whose
     * data is mutable.  This class provides the basic wrappering of the
     * primitive data, instantiation, type conversion, <code>unknown value</code>
     * representation and the core comparison logic.
     * <p>
     * All Progress language features related to integer/decimal data
     * types are implemented in the {@link MathOps} class (except comparison
     * logic which is in {@link CompareOps}.  All Progress integer/decimal
     * features are supported including all functionality that can be accessed
     * via operators and built-in Progress functions.
     *
     * @author    GES
     */
    public class integer
    extends int64
    {
       /** Logger */
       private static final CentralLogger log = CentralLogger.get(integer.class);

       /** Default maximum number of cached integerConstant instances */
       private static final int DEFAULT_STATIC_CACHE_SIZE = 1024;

       /** Default size for the dynamic cache */
       private static final int DEFAULT_DYNAMIC_CACHE_SIZE = 512;

       /** Singleton and immutable for the integer UNKNOWN value. */
       public static final integerConstant UNKNOWN = new integerConstant();

       /** Cache for the singleton and immutable integer values. */
       private static integerConstant[] STATIC_CACHE;

       /** Dynamic integer cache. */
       private static volatile integerConstant[] DYNAMIC_CACHE;

       /**
        * Default constructor which creates an instance representing the <code>unknown value</code>.
        */
       public integer()
       {
       }

       /**
        * This is a special c'tor which should be used only when converting the
        * value returned by a function or method with polymorphic return type into the
        * expected type (i.e. DYNAMIC-FUNCTION()).  In such cases, the 4GL does some
        * automatic type conversion (see {@link #assign(BaseDataType)}).
        *
        * @param    value
        *           The value to be used for this instance.
        */
       public integer(BaseDataType value)
       {
          initialize(value);
       }

       /**
        * Constructs an instance wth the given enum's value. If the value is larger than
        * {@code Integer.MAX_VALUE} or smaller than {@code Integer.MIN_VALUE} (does not fit into the 32-bit
        * representation) it cannot be represented and a warning 15747 will be raised:
        * "Value too large to fit in INTEGER".
        * <p>
        * If the parameter is {@code unknown value} the resulting instance is the {@code unknown value}.
        * <p>
        * This constructor implements the {@code INTEGER(enum)} 4GL built-in function.  Any failure will
        * generate a warning instead of an error.
        *
        * @param    enm
        *           The enum whose value to be used for this instance.
        */
       public integer(object<? extends LegacyEnum> enm)
       {
          if (enm.isUnknown())
          {
             setUnknown();
          }
          else
          {
             // although the assign will call checkBounds() downstream, it will generate an error which we don't
             // want; we force the check here so that we can cause the failure to be a warning
             long num = enm.ref()._getValue();

             if (!checkBounds(num, true))
             {
                return;
             }

             super.setValue(num);
          }
       }

       /**
        * Constructs an instance after casting the parameter into the internal representation of this
        * class.  If the value is larger than <code>Integer.MAX_VALUE</code> or smaller than
        * <code>Integer.MIN_VALUE</code> (does not fit into the 32-bit representation) it
        * cannot be represented and error 15747 will be raised: "Value too large to fit in INTEGER"
        * <p>
        * It is not possible to yield an <code>unknown value</code> from this constructor without
        * calling the method {@link #setUnknown} separately.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(long value)
       {
          super.setValue(value);
       }

       /**
        * Constructs an instance after casting the parameter into the internal
        * representation of this class.  No loss of precision will occur.
        * <p>
        * It is not possible to yield an <code>unknown value</code> from this
        * constructor without calling the method {@link #setUnknown} separate.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(int value)
       {
          super.setValue(value);
       }

       /**
        * Constructs an instance after casting the parameter into the internal
        * representation of this class.  Loss of precision may occur in this
        * conversion (all digits to the right of the decimal point will be
        * truncated).
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(double value)
       {
          super.setValue(new decimal(value));
       }

       /**
        * Constructs an instance after copying the parameter's data into the
        * internal representation of this class.
        * <p>
        * When the parameter is <code>true</code> the resulting integer value
        * will be 1. Otherwise the value is 0.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(boolean value)
       {
          super.setValue(value);
       }

       /**
        * Constructs an instance after casting the parameter into the internal representation of this
        * class. Very large and very small values that do not fit into the 32 bit representation
        * cannot be represented.
        * <p>
        * If the parameter represents the <code>unknown value</code>, this instance will also
        * represent the <code>unknown value</code>.
        * <p>
        * This constructor implements the {@code INTEGER(int64)} 4GL built-in function.  Any failure will
        * generate a warning instead of an error.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(int64 value)
       {
          // the value may be a proxy; make sure to unwrap and work with the real value
          if (BaseDataType.isProxy(value))
          {
             if (value.val() instanceof int64)
             {
                value = (int64) value.val();
             }
             else
             {
                initialize(value.val());
                return;
             }
          }
          // although the assign will call checkBounds() downstream, it will generate an error which we don't
          // want; we force the check here so that we can cause the failure to be a warning
          if (value != null && !value.isUnknown())
          {
             long num = value.longValue();

             if (!checkBounds(num, true))
             {
                return;
             }
          }

          assign(value);
       }

       /**
        * Constructs an instance after casting the parameter into the internal representation of this
        * class. No loss of precision will occur.
        * <p>
        * If the parameter represents the <code>unknown value</code>, this instance will also
        * represent the <code>unknown value</code>.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(integer value)
       {
          super(value);
       }

       /**
        * Constructs an instance after casting the parameter into the internal representation of this
        * class. Loss of precision may occur in this conversion. All digits to the right of the
        * decimal point will be truncated. Very large and very small values cannot be represented.
        * <p>
        * If the parameter represents the <code>unknown value</code>, this instance will also
        * represent the <code>unknown value</code>.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(decimal value)
       {
          assign(value);
       }

       /**
        * Constructs an instance after copying the parameter's data into the
        * internal representation of this class.
        * <p>
        * If the parameter's represents the <code>unknown value</code>, this
        * instance will also represent the <code>unknown value</code>.
        * <p>
        * When the parameter is <code>true</code> the resulting integer value
        * will be 1. Otherwise the value is 0.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(logical value)
       {
          // the value may be a proxy; make sure to unwrap and work with the real value
          if (BaseDataType.isProxy(value))
          {
             if (value.val() instanceof logical)
             {
                value = (logical) value.val();
             }
             else
             {
                initialize(value.val());
                return;
             }
          }
          super.setValue(value);
       }

       /**
        * Constructs an instance after converting the string representation
        * of a number into an integer.  Due to rounding, a loss of precision
        * may occur in this conversion (all digits to the right of the decimal
        * point will be truncated).
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(String value)
       {
          setValue(value);
       }

       /**
        * Constructs an instance after converting the string representation
        * of a number into an integer.  Due to rounding, a loss of precision
        * may occur in this conversion (all digits to the right of the decimal
        * point will be truncated).
        * <p>
        * If the parameter is <code>unknown value</code> the resulting integer is
        * the <code>unknown value</code>.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(character value)
       {
          // the value may be a proxy; make sure to unwrap and work with the real value
          if (BaseDataType.isProxy(value))
          {
             if (value.val() instanceof character)
             {
                value = (character) value.val();
             }
             else
             {
                initialize(value.val());
                return;
             }
          }
          if (value.isUnknown())
          {
             setUnknown();
          }
          else
          {
             setValue(value.getValue());
          }
       }

       /**
        * Constructs an instance after copying the parameter's data into the
        * internal representation of this class.
        * <p>
        * If the parameter's represents the <code>unknown value</code>, this
        * instance will also represent the <code>unknown value</code>.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(date value)
       {
          // the value may be a proxy; make sure to unwrap and work with the real value
          if (BaseDataType.isProxy(value))
          {
             if (value.val() instanceof date)
             {
                value = (date) value.val();
             }
             else
             {
                initialize(value.val());
                return;
             }
          }
          if (value.isUnknown())
          {
             setUnknown();
          }
          else if (value instanceof datetime)
          {
             ErrorManager.recordOrShowError(
                5729, "Incompatible datatypes found during runtime conversion", false);
          }
          else
          {
             super.setValue(value.longValue());
          }
       }

       /**
        * Constructs an instance after copying the parameter's data into the
        * internal representation of this class.
        * <p>
        * If the parameter is <code>null</code>, this instance will represent
        * the <code>unknown value</code>.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(Number value)
       {
          if (value == null)
          {
             setUnknown();
          }
          else
          {
             super.setValue(value.intValue());
          }
       }

       /**
        * Constructs an instance after copying the parameter's data into the
        * internal representation of this class.
        * <p>
        * If the parameter is <code>null</code>, this instance will represent
        * the <code>unknown value</code>.
        *
        * @param   value
        *          The value to be used for this instance.
        */
       public integer(Boolean value)
       {
          if (value == null)
          {
             setUnknown();
             return;
          }
          super.setValue(value);
       }

       /**
        * Initializes the cache using CacheManager. The default value of the cache
        * is used when there is no size available from the configuration.
        */
       public static void initializeCache()
       {
          STATIC_CACHE = CacheManager.createArrayCache(integer.class,
                                                "static-cache",
                                                DEFAULT_STATIC_CACHE_SIZE,
                                                integerConstant.class);

          for (int i = 0; i < STATIC_CACHE.length; i++)
          {
             STATIC_CACHE[i] = new integerConstant(i);
          }

          DYNAMIC_CACHE = CacheManager.createArrayCache(integer.class,
                                                        "dynamic-cache",
                                                        DEFAULT_DYNAMIC_CACHE_SIZE,
                                                        integerConstant.class);
       }

       /**
        * Returns an integerConstant instance. Uses cached instances for the first n values, where n is the
        * cache size that can be configured in directory.xml.
        *
        * @param   value
        *          The value of the integer.
        * @return  An integerConstant instance.
        */
       public static integer of(Integer value)
       {
          if (value == null)
          {
             return UNKNOWN;
          }

          if (STATIC_CACHE == null)
          {
             return new integerConstant(value);
          }
          //Check static cache
          if (value >= 0 && value < STATIC_CACHE.length)
          {
             return STATIC_CACHE[value];
          }

          if (DYNAMIC_CACHE == null)
          {
             return new integerConstant(value);
          }
          // Check dynamic cache
          int index = Math.abs(value % DYNAMIC_CACHE.length);
          synchronized (DYNAMIC_CACHE)
          {
             integerConstant cachedInstance = DYNAMIC_CACHE[index];
             if (cachedInstance != null && cachedInstance.intValue() == value)
             {
                return cachedInstance;
             }

             // Cache miss - create and replace the entry in dynamic cache
             integerConstant newInstance = new integerConstant(value);
             DYNAMIC_CACHE[index] = newInstance;
             return newInstance;
          }
       }

       /**
        * Returns an integerConstant instance. Uses cached instances for the first n values, where n is the
        * cache size that can be configured in directory.xml.
        *
        * @param   value
        *          The value of the integer.
        * @return  An integerConstant instance.
        */
       public static integer of(integer value)
       {
          if (value == null || value.isUnknown())
          {
             return UNKNOWN;
          }

          return integer.of(value.intValue());
       }

       /**
        * Get the type
        * @return type
        */
       public Type getType()
       {
          return Type.INTEGER;
       }

       /**
        * Sets the state (data and unknown value) of this instance based on the state of the passed
        * instance.
        * <p>
        * Overrides the superclass' implementatoin to optimize for the most common use case of
        * copying an <code>integer</code> from another <code>integer</code> (vs. from a
        * non-<code>integer</code> <code>NumberType</code>). In bypassing the superclass' more general
        * implementation, we avoid a significantly slower implementation which performs unnecessarily
        * (for this case) a bounds check and <code>BigDecimal</code> instantiation.
        * <p>
        * In the event <code>value</code> is not an <code>integer</code> instance, delegate to the
        * superclass' implementation.
        *
        * @param    value
        *           The instance from which to copy state.
        */
       @Override
       public void assign(NumberType value)
       {
          // the value may be a proxy; make sure to unwrap and work with the real value
          if (BaseDataType.isProxy(value))
          {
             assign(value.val());
             return;
          }
          if (!(value instanceof integer))
          {
             super.assign(value);
             return;
          }

          if (value.isUnknown())
          {
             setUnknown();
             return;
          }

          if (((integer) value).isAssignDirect() && !checkBounds(value.longValue(), false))
          {
             // convert it to unknown...
             setUnknown();
             return;
          }

          setValue(value.intValue());
       }

       /**
        * Hash code implementation which is consistent with {@link BaseDataType#equals}.
        *
        * @return  Hash code value for this object instance.
        */
       public int hashCode()
       {
          return super.hashCode();
       }

       /**
        * Creates a new instance of the same type that represents the <code>unknown value</code>.
        *
        * @return  An instance that represents the <code>unknown value</code>.
        */
       public BaseDataType instantiateUnknown()
       {
          return new integer();
       }

       /**
        * Creates a new instance of the same type that represents the  default initialized value.
        *
        * @return  An instance that represents the default value.
        */
       public BaseDataType instantiateDefault()
       {
          return new integer(0);
       }

       /**
        * Does the same as standard <code>clone()</code> method but returns an instance of
        * <code>BaseDataType</code> and doesn't throw the <code>CloneNotSupportedException</code>.
        *
        * @return  A clone of this instance.
        */
       public integer duplicate()
       {
          return new integer(this);
       }

       /**
        * Sets the state (data and unknown value) of this instance based on the
        * state of the passed instance.
        *
        * @param    value
        *           The instance from which to copy state.
        */
       public void assign(Undoable value)
       {
          if (value instanceof BaseDataType)
          {
             assign((BaseDataType)value);
          }
          else
          {
             throw new RuntimeException("Assignement of " + value.getClass() +
                   " to integer not implemented.");
          }
       }

       /**
        * Replacement for the default object reading method. The latest state is read from the
        * input source.
        *
        * @param    in
        *           The input source from which fields will be restored.
        *
        * @throws   IOException
        *           In case of I/O errors.
        * @throws   ClassNotFoundException
        *           If payload can't be instantiated.
        */
       public void readExternal(ObjectInput in)
       throws IOException,
              ClassNotFoundException
       {
          int value       = in.readInt();
          boolean unknown = in.readBoolean();

          if (unknown)
          {
             setUnknown();
          }
          else
          {
             super.setValue(value);
          }
       }

       /**
        * Replacement for the default object writing method. The latest
        * state is written to the output destination.
        *
        * @param    out
        *           The output destination to which fields will be saved.
        *
        * @throws   IOException
        *           In case of I/O errors.
        */
       public void writeExternal(ObjectOutput out)
       throws IOException
       {
          out.writeInt((int)getValue());
          out.writeBoolean(isUnknown());
       }

       /**
        * Get the default initialization for an extent variable of this type.
        *
        * @return   See above.
        */
       @Override
       protected BaseDataType instantiateDefaultExtent()
       {
          return new integer(0);
       }

       /**
        * Checks if <code>value</code> can be assigned to this data type. This is important for
        * <code>integer</code> objects where the values must fit into 32 bit storage bounds.
        *
        * @param   value
        *          The value
        * @param   warn
        *          {@code true} if any generated error should actually be a warning (the
        *          {@code error-status:error} set to {@code false}.
        *
        * @return  <code>true</code> if value fits into 32 bit storage bounds.
        *
        * @throws  ErrorConditionException
        *          Thrown if the <code>value</code> do not fit within this data-type.
        */
       @Override
       protected boolean checkBounds(long value, boolean warn)
       throws ErrorConditionException
       {
          if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE)
          {
             int errno = 15747;

             // mimic the strange quirk of how the 4GL prints the smallest int64 value
             String txt = (value == Long.MIN_VALUE) ? "-(" : String.format("%d", value);
             String msg = "Value " + txt + " too large to fit in INTEGER";

             if (warn)
             {
                ErrorManager.recordOrShowError(errno, msg, false, true, false);
             }
             else
             {
                ErrorManager.recordOrThrowError(errno, msg, false);
             }

             return false;
          }

          return true;
       }

       /**
        * An immutable integer type, used for caching singleton instances for specific values.
        */
       public static class integerConstant
       extends integer
       implements BaseDataTypeConstant
       {
          /**
           * Default constructor, creates an instance that represents the unknown value.
           */
          public integerConstant()
          {
             this.unknown = true;
          }

          /**
           * Constructs an instance with a specific value.
           *
           * @param   value
           *          The value of the integerConstant instance.
           */
          public integerConstant(int value)
          {
             this.value = value;
             this.unknown = false;
          }

          /**
           * Operation not possible.
           *
           * @throws UnsupportedOperationException
           *         This is an immutable integer instance.
           */
          @Override
          public void setUnknown()
          {
             throw new UnsupportedOperationException("This is an immutable integer instance.");
          }

          /**
           * Operation not possible.
           *
           * @throws UnsupportedOperationException
           *         This is an immutable integer instance.
           */
          @Override
          public void setValue(long value)
          {
             throw new UnsupportedOperationException("This is an immutable integer instance.");
          }

          /**
           * Operation not possible.
           *
           * @throws   UnsupportedOperationException
           *           This is an immutable integer instance.
           */
          @Override
          public void assign(NumberType value)
          {
             throw new UnsupportedOperationException("This is an immutable integer instance.");
          }

          /**
           * Operation not possible.
           *
           * @throws   UnsupportedOperationException
           *           This is an immutable integer instance.
           */
          @Override
          public void assign(Undoable value)
          {
             throw new UnsupportedOperationException("This is an immutable integer instance.");
          }

          /**
           * Operation not possible.
           *
           * @throws   UnsupportedOperationException
           *           This is an immutable integer instance.
           */
          @Override
          public void assign(Object value)
          {
             throw new UnsupportedOperationException("This is an immutable integer instance.");
          }

          /**
           * Operation not possible.
           *
           * @throws   UnsupportedOperationException
           *           This is an immutable integer instance.
           */
          @Override
          Supplier<AbstractParameter> getAssigner()
          {
             throw new UnsupportedOperationException("This is an immutable integer instance.");
          }

       }
    }