Parameter.java
/*
** Module : Parameter.java
** Abstract : internal entry parameter container
**
** Copyright (c) 2013-2019, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------Description---------------------------------
** 001 GES 20131124 Moved this code out of SourceNameMapper into its own class. This enables
** cleaner separation and modularity. Added synchronization and made changes
** for RETURN support.
** 002 ECF 20140913 Reduced memory footprint.
** 003 ECF 20160402 Reduced memory footprint again.
** 004 CA 20190219 Changes to allow parameter specs to be set via LegacyParameter annotations.
** 005 CA 20190614 DATETIMETZ and DATETIME-TZ are the same types.
*/
/*
** 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.util.*;
/**
* Container for all info related to an internal-entry's {@link InternalEntry} parameter.
*/
public class Parameter
{
/** The set of all valid modes. */
private static final Set<String> validModes = new HashSet<>();
/** Legacy 4GL name for this parameter. */
private final String pname;
/** The 4GL-style parameter type. */
private final String type;
/** The mode of this parameter, one of INPUT, OUTPUT or INPUT-OUTPUT or RETURN. */
private final String mode;
/**
* If this parameter's type is {@link object}, then this holds the qualified legacy class
* name.
*/
private String qualified = null;
/** A map containing all the parameter's attributes. */
private Map<String, String> attributes = new HashMap<>(8);
/**
* Extent setting of this parameter. If set to {@link SourceNameMapper#DYNAMIC_EXTENT},
* dynamic extent is used. If set to {@link SourceNameMapper#NO_EXTENT}, no extent is used.
*/
private int extent;
static
{
validModes.add("INPUT");
validModes.add("INPUT-OUTPUT");
validModes.add("OUTPUT");
validModes.add("RETURN");
}
/**
* Basic c'tor.
*
* @param pname
* Legacy 4GL name for this parameter.
* @param type
* The 4GL-style parameter type.
* @param mode
* The mode of this parameter, one of INPUT, OUTPUT or
* INPUT-OUTPUT.
*/
public Parameter(String pname, String type, String mode)
{
this.pname = pname.intern();
// disambiguate this...
this.type = "DATETIMETZ".equals(type) ? "DATETIME-TZ" : type.intern();
this.mode = mode.toUpperCase().intern();
if (!"BUFFER".equalsIgnoreCase(type) && !validModes.contains(this.mode))
{
String errmsg = "Malformed parameter mode " + mode + " for parameter " + pname;
throw new IllegalStateException(errmsg);
}
}
/**
* Get the legacy 4GL name.
*
* @return The legacy name.
*/
public String getLegacyName()
{
return pname;
}
/**
* Get the unmodified mode name.
*
* @return The raw mode name.
*/
public String getMode()
{
return mode;
}
/**
* Get the data type name.
*
* @return The data type name.
*/
public String getType()
{
return type;
}
/**
* Get the value of the given attribute. If the attribute is null or
* is not set, return <code>null</code>.
*
* @param attr
* The attribute's name.
*
* @return See above.
*/
public synchronized String getAttribute(String attr)
{
if (attr == null)
{
return null;
}
attr = attr.toLowerCase();
return attributes.get(attr);
}
/**
* Set the value of the given attribute.
*
* @param name
* The attribute's name.
* @param value
* The attribute's value.
*/
public synchronized void putAttribute(String name, String value)
{
attributes.put(name.toLowerCase().intern(), value.intern());
}
/**
* Get the value of the mode in a form that is acceptable for displaying in the
* internal entry's signature. In particular, any RETURN mode is reported as OUTPUT.
*
* @return The mode in a form that is compatible with the 4GL signature text.
*/
public String getSignatureMode()
{
return "RETURN".equals(mode) ? "OUTPUT" : mode;
}
/**
* Check if this parameter is dynamic extent (<code>true</code> only
* when the {@link #extent} field is set to {@link SourceNameMapper#DYNAMIC_EXTENT}.
*
* @return <code>true</code> if this is a dynamic-extent parameter.
*/
public synchronized boolean isDynamicExtent()
{
return extent == SourceNameMapper.DYNAMIC_EXTENT;
}
/**
* Check if this parameter is fixed-size extent (<code>true</code> only
* when the {@link #extent} field greater than 0}.
*
* @return <code>true</code> if this is a fixed-size extent parameter.
*/
public synchronized boolean isFixedExtent()
{
return extent > 0;
}
/**
* Check if this parameter is an extent parameter (fixed or dynamic).
*
* @return <code>true</code> if this is an extent parameter.
*/
public synchronized boolean isExtent()
{
return isDynamicExtent() || isFixedExtent();
}
/**
* Obtain the extent of this parameter.
*
* @return The extent.
*/
public synchronized int getExtent()
{
return isDynamicExtent() ? 0 : extent;
}
/**
* Initialize the extent member based on a text input.
*
* @param extent
* A valid integer specifying the extent or <code>null</code> to set the default
* to {@link SourceNameMapper#NO_EXTENT}.
*/
public synchronized void setExtent(String extent)
{
this.extent = (extent == null) ? SourceNameMapper.NO_EXTENT : Integer.parseInt(extent);
}
/**
* Initialize the {@link #qualified} member based on a text input.
*
* @param qualified
* The qualified legacy OO class name of this type, or <code>null</code> if it does
* not apply.
*/
public synchronized void setQualified(String qualified)
{
this.qualified = (qualified == null ? null : qualified.intern());
}
/**
* Get the {@link #qualified} member.
*
* @return See above.
*/
public synchronized String getQualified()
{
return qualified;
}
/**
* Check if the specified object matches this instance.
*
* @param obj
* The object to match.
*
* @return See above.
*/
@Override
public boolean equals(Object obj)
{
if (!(obj instanceof Parameter))
{
return false;
}
Parameter p = (Parameter) obj;
return extent == p.extent &&
Objects.equals(type, p.type) &&
Objects.equals(mode, p.mode) &&
Objects.equals(qualified, p.qualified);
}
}