Options.java
/*
** Module : Options.java
** Abstract : stores E4GL options specified in meta/wsmeta elements
**
** Copyright (c) 2007-2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- ---------------------------------Description-----------------------------------
** 001 GES 20070822 @34967 Store all options parsed from an E4GL file.
** 002 GES 20241123 Added default wsoptions if none are manually specified and there is no meta tag.
*/
/*
** 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.e4gl;
import java.util.*;
import com.goldencode.p2j.util.*;
/**
* Provides a simple mechanism to store all options parsed from an E4GL file.
* <p>
* These options can be manipulated and set externally as well.
*/
public class Options
implements E4GLConstants
{
/** Compatibility mode (see {@link E4GLConstants}). */
private int mode = DEFAULT_MODE;
/** Flag controlling whether this emits as a procedure or include file. */
private boolean include = false;
/** Content-Type meta element is left alone (not commented out). */
private boolean keepContentType = false;
/** Encoded content type found in meta element. */
private String contentType = "text/html";
/** Encoded wsoptions found in meta element. */
private Set<String> wsoptions = new LinkedHashSet<String>();
/** Input HTML filename. */
private String input = null;
/** Output HTML filename. */
private String output = null;
/** Operating system name for which preprocessing must account. */
private String opsys = null;
/** Helper to emit text that exactly matches a given implementation. */
private CompatibilityHelper hlp = null;
/**
* Create an instance that processes options with <code>WEBSPEED</code>
* compatibility.
*/
public Options()
{
}
/**
* Create an instance that processes options with the specified
* compatibility.
*
* @param mode
* Compatibility mode (see {@link E4GLConstants}).
*/
public Options(int mode)
{
this.mode = mode;
}
/**
* Access the compatibility mode (see {@link E4GLConstants}).
*
* @return The compatibility mode for this HTML file.
*/
public int getMode()
{
return mode;
}
/**
* Set the compatibility mode (see {@link E4GLConstants}). If this mode
* is different from the previously set value, the compatibility helper
* reference is set to <code>null</code>. Any following call to
* {@link #getCompatibilityHelper} will subsequently return a new instance
* that matches the new mode.
*
* @param mode
* The compatibility mode for this HTML file.
*/
public void setMode(int mode)
{
if (this.mode != mode)
{
hlp = null;
}
this.mode = mode;
}
/**
* Access the specified input filename.
*
* @return A filename.
*/
public String getInput()
{
return input;
}
/**
* Set the specified input filename.
*
* @param input
* A filename.
*/
public void setInput(String input)
{
this.input = input;
}
/**
* Access the output filename.
*
* @return A filename.
*/
public String getOutput()
{
return output;
}
/**
* Set the specified output filename. WARNING: this will override any
* previously calculated/specified output filename.
*
* @param output
* A filename.
*/
public void setOutput(String output)
{
this.output = output;
}
/**
* Gets the operating system name which must be used to determine how
* escape characters are treated.
*
* @return The operating system name.
*/
public String getOpsys()
{
if (opsys == null)
opsys = EnvironmentOps.getOperatingSystem().toStringMessage();
return opsys;
}
/**
* Sets the operating system name which must be used to determine how
* escape characters are treated.
*
* @param opsys
* The new operating system name.
*/
public void setOpsys(String opsys)
{
this.opsys = opsys;
}
/**
* Parse the options string (as found in a meta element) and set the flags
* and state variables as needed based on the options specified. This
* string is normally a comma-separated list of options and this list
* will be cleaned up, merged and stored as a master options string in
* addition to the flags that will be set.
* <p>
* Since this code safely merges options with any that were previously
* stored, this is suitable for handling multiple meta elements in the
* same file (and additionally, any number of manual calls to add
* options).
* <p>
* This can be used to manually add a list of options (as opposed to
* reading these options from the meta element of an HTML file).
* <p>
* Processing is always additive. There is no way to delete options once
* set.
*
* @param options
* A comma-separated list of options.
* @param html
* <code>true</code> if <code>wsoptions</code> was read from an
* HTML file meta element. In that case, the "wsoptions-found"
* will be appended to the options string if it is not already
* present in the options.
*/
public void processWSOptions(String options, boolean html)
{
String[] list = options.split(",", 0);
for (int i = 0; i < list.length; i++)
{
list[i] = list[i].trim();
if (list[i].length() > 0)
wsoptions.add(list[i].toLowerCase());
}
if (html)
{
wsoptions.add(OPT_FOUND);
}
// read our resulting set of options (must be done here to honor the
// cumulative options)
boolean incl = wsoptions.contains(OPT_INCLUDE);
boolean webo = wsoptions.contains(OPT_WEB_OBJ);
if (html && mode != BLUE_DIAMOND)
{
wsoptions.add(OPT_FOUND);
}
keepContentType = wsoptions.contains(OPT_KEEP);
// process OPT_INCLUDE and OPT_WEB_OBJ options
if (mode != BLUE_DIAMOND)
{
// if neither are specified or if web-object is present, then
// generate a web-object, if only include is specified then generate
// an include
include = ((!incl && !webo) || webo) ? false : true;
if (!incl && !webo)
{
wsoptions.add(OPT_WEB_OBJ);
}
}
else
{
// the presence of the include option sets include mode
if (incl)
include = true;
}
}
/**
* Access the <code>wsoptions</code> string.
* <p>
* Try to call this only once (or at least infrequently) since it
* dynamically builds the options string off an internal collection
* of options. This is much more expensive than just returning a
* string member.
*
* @return The complete set of options as a comma-separated list.
*/
public String getWSOptions()
{
// for webspeed, set some defaults if there were no manually set options or a meta tag
if (wsoptions.size() == 0 && mode != BLUE_DIAMOND)
{
wsoptions.add(output);
wsoptions.add(OPT_WEB_OBJ);
}
Iterator<String> iter = wsoptions.iterator();
StringBuilder sb = new StringBuilder();
// iterate through the list and build a single options string
while (iter.hasNext())
{
// add our separator if needed
if (sb.length() > 0)
sb.append(',');
// add the next option
sb.append(iter.next());
}
return sb.toString();
}
/**
* Access the <code>content-type</code> string.
*
* @return The content-type for this HTML file.
*/
public String getContentType()
{
return contentType;
}
/**
* Set the <code>content-type</code> string.
*
* @param contentType
* The content-type for this HTML file.
*/
public void setContentType(String contentType)
{
this.contentType = contentType;
}
/**
* Determine if the generated 4GL code should be an include file or a
* procedure file ("web-object").
*
* @return <code>true</code> if this is an include file.
*/
public boolean isInclude()
{
return include;
}
/**
* Set the flag for whether the generated 4GL code should be an include
* file or a procedure file ("web-object").
*
* @param include
* <code>true</code> if this is an include file.
*/
public void setInclude(boolean include)
{
this.include = include;
}
/**
* Determine if the generated 4GL code should have the content-type meta
* element left behind.
*
* @return <code>true</code> if the content-type meta element is to be
* left uncommented in the generated code.
*/
public boolean isKeepContentType()
{
return keepContentType;
}
/**
* Set the flag for whether the generated 4GL code should have the
* content-type meta element left behind.
*
* @param keepContentType
* <code>true</code> if the content-type meta element is to be
* left uncommented in the generated code.
*/
public void setKeepContentType(boolean keepContentType)
{
this.keepContentType = keepContentType;
}
/**
* Obtain the current compatibility helper instance based on the mode
* that was specified. The helper will be instantiated and initialized
* the first time this is called and the same helper instance will be
* returned thereafter unless the compatibility mode is changed. See
* {@link #setMode}.
*
* @return The helper to use for emitting compatible text.
*/
public CompatibilityHelper getCompatibilityHelper()
{
if (hlp == null)
{
if (mode == WEBSPEED)
{
hlp = new WebSpeedHelper();
}
else if (mode == WEBSPEED_STRICT)
{
hlp = new WebSpeedStrictHelper();
}
else if (mode == BLUE_DIAMOND)
{
hlp = new BlueDiamondHelper();
}
else
{
hlp = new BaseHelper();
}
hlp.initialize(this);
}
return hlp;
}
/**
* Create a text representation of the state of this instance.
*
* @return Text representation of all state.
*/
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append(String.format("Options instance (0x%08X); ", hashCode()));
sb.append(String.format("compat mode = %s; ", MODE_NAMES[mode]));
sb.append(String.format("include = %b; ", include));
sb.append(String.format("input file = %s; ", input));
sb.append(String.format("output file = %s; ", output));
sb.append(String.format("keep content type = %b; ", keepContentType));
sb.append(String.format("content-type = '%s'; ", contentType));
sb.append(String.format("wsoptions = '%s'; ", getWSOptions()));
return sb.toString();
}
}