com.adobe.xfa.Option Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2005 Adobe Systems Incorporated All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual and
* technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or copyright
* law. Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained from
* Adobe Systems Incorporated.
*/
package com.adobe.xfa;
import com.adobe.xfa.ut.ExFull;
import com.adobe.xfa.ut.MsgFormatPos;
import com.adobe.xfa.ut.ResId;
import com.adobe.xfa.ut.StringUtils;
/**
* Represents an option such as those passed to
* XFAModelFactory::setOption()
. This class shouldn't be part of
* the published XFA DOM API.
*
*
*
*
* Usage: an Option is generally stored as a member of the object
* to which the option pertains. An Option is created with
* two strings: the name of the option, and a string
* representing all of the possible values to which the option
* can be set. The format of the validation string is as
* follows:
*
* "option1|option2|...|optionN"
*
* Each section of the string represents one possible value.
* It can be one of the following:
*
* "literal" - a literal string that must match exactly
* (i.e. a keyword)
* "%d" - an integer
* "%lf" - a double (%lf is long-float scanf notation)
* "%b" - a boolean (i.e. a "1" or a "0")
* "%s" - a string
*
* Example: "default|%d|%s" represents that an option can be
* either the word "default", or an integer, or a string.
* Note that the order is important. Possible matches are
* considered from left to right.
*
* The caller passes the option into setValue(), which matches
* the option against the validation string. In the example
* above, if setValue were called with "default", then
* getMatchingIndex() would return 0. If instead setValue()
* were called with "5", then getMatchingIndex() would return
* 1, and the caller could retrieve the value 5 from
* getInteger(). Finally if a string other than "default"
* were passed in, then getMatchingIndex() would return 2, and
* the string could be retrieved via getString().
*
* An exception is thrown if setValue is called with an
* invalid option.
*
* If the option has never been set (ie. setValue() has not
* been called) then getMatchingIndex() returns -1.
*
*
*
*
* @exclude from published api.
*/
public final class Option {
private static final int BOOL = 1;
// "flatten"
private static final int DOUBLE = 3;
/**
* OptionType is an enumeration of all the possible types of Options
*/
private static final int EMPTY = 0;
private static final int INTEGER = 2;
private static final int LITERAL = 5;
private static final int STRING = 4;
/**
* Static routine: given a null-terminated list of pointers to Option, this
* routine will look up the option called optionName in the list, and call
* setValue on that option (passing optionValue and bCritical).
*
* If the option name contains a package name (such as "data_flatten"), this
* routine will verify that it matches packageName. If it doesn't match, an
* exception will be thrown.
*
* If the optionName is an empty string, then all the options are reset. In
* this case, -1 is returned. All other parameters except for the option
* list are ignored when resetting options.
*
* @param packageName
* the name of the package that the options belong to (eg.
* "data").
* @param options
* the list of pointers to options.
* @param optionName
* the name of the option.
* @param optionValue
* the value of the option.
* @param bCritical
* disallow further modification of this option.
*
* @return the index into the array of the option that was set, or -1 if
* optionName is an empty string.
* @exception OptionWrongPackageException
* @exception InvalidOptionException
*/
public static int setOptionByArray(String packageName, Option[] options,
String optionName, String optionValue, boolean bCritical) {
// validate package name, and trim it off if specified.
String name;
name = optionName;
Option option;
int index;
// reset all the options if optionName is empty
if (StringUtils.isEmpty(optionName)) {
for (index = 0; (option = options[index]) != null; index++) {
option.reset();
}
return -1;
}
int nPackageSeparatorOffset = optionName.indexOf('_');
if (nPackageSeparatorOffset != -1) {
if (nPackageSeparatorOffset == 0)
throw new ExFull(ResId.OptionWrongPackageException, optionName);
// package specified; verify that it's the right one
if (!optionName.substring(nPackageSeparatorOffset).equals(
packageName))
// wrong package
throw new ExFull(ResId.OptionWrongPackageException, optionName);
// package is OK; remove it from the option name
name = optionName.substring(nPackageSeparatorOffset + 1);
}
for (index = 0; (option = options[index]) != null; index++) {
if (option.getName().equals(name)) {
option.setValue(optionValue, bCritical);
return index;
}
}
throw new ExFull(ResId.InvalidOptionException, optionName);
}
private boolean mbLocked; // true if this option is locked
private int mnMatchingIndex; // index of matching section of mValidValues
private String mOptionName; // name of option without package name, eg.
private String mString;
private int mType;
private String mValidValues; // list of possible values, eg "1|0"
private Object mValue; // One of: Boolean / Integer / Double
/**
* Copy constructor
*
* @param src
* the Option to copy
*/
public Option(Option src) {
mType = src.mType;
mValue = src.mValue;
mString = src.mString;
mOptionName = src.mOptionName;
mValidValues = src.mValidValues;
mnMatchingIndex = src.mnMatchingIndex;
mbLocked = src.mbLocked;
}
/**
* Constructor for Option.
*
* @param name
* the name of the new option
* @param validValues
* the value of the new option.
*/
public Option(String name, String validValues) {
mOptionName = name;
mValidValues = validValues;
mType = EMPTY;
mnMatchingIndex = -1;
mbLocked = false;
mValue = null;
}
/**
* Set an option to be empty. This doesn't affect the locked flag.
*
*/
private void empty() {
mnMatchingIndex = -1;
if (mType == STRING)
mString = "";
mType = EMPTY;
mValue = null;
}
/**
* Compare this option object to another for equality.
*
* @param object
* the other option
* @return true if the two options are equal in value, false otherwise
*/
public boolean equals(Object object) {
if (this == object)
return true;
// This overrides Object.equals(boolean) directly, so...
if (object == null)
return false;
if (object.getClass() != getClass())
return false;
Option right = (Option) object;
if (mType != right.mType)
return false;
switch (mType) {
case EMPTY:
return true;
case LITERAL:
return mnMatchingIndex == right.mnMatchingIndex;
case BOOL:
return getBool() == right.getBool();
case INTEGER:
return getInteger() == right.getInteger();
case DOUBLE:
return getDouble() == right.getDouble();
case STRING:
return getString().equals(right.getString());
default:
assert false;
return false;
}
}
public int hashCode() {
int hash = 17;
hash = (hash * 31) ^ mType;
switch (mType) {
case EMPTY:
break;
case LITERAL:
hash = (hash * 31) ^ getMatchingIndex();
break;
case BOOL:
hash = (hash * 31) ^ Boolean.valueOf(getBool()).hashCode();
break;
case INTEGER:
hash = (hash * 31) ^ getInteger();
break;
case DOUBLE: {
long bits = Double.doubleToLongBits(getDouble());
hash = (hash * 31) ^ (int) (bits ^ (bits >>> 32));
break;
}
case STRING:
hash = (hash * 31) ^ getString().hashCode();
break;
}
return hash;
}
/**
* Return the option type
*
* @return our option type. This is EMPTY if this option has not been set.
* If this option has been set, the return type of getArgType will
* be one of types represented by the validation string in the
* constructor.
*/
public int getArgType() {
return mType;
}
/**
* Return the boolean value held by this option
*
* @return our boolean value
* @exception OptionMisuseException
*/
public boolean getBool() {
if (mType != BOOL)
throw new ExFull(ResId.OptionMisuseException, getName());
// force true return value to be the usual value of true, as opposed to
// the
// scripting-style -1
Boolean b = (Boolean) mValue;
return b.booleanValue();
}
/**
* Return the double value held by this option
*
* @return our double value
* @exception OptionMisuseException
*/
public double getDouble() {
if (mType != DOUBLE) {
if (mType == INTEGER)
return getInteger();
throw new ExFull(ResId.OptionMisuseException, getName());
}
Double d = (Double) mValue;
return d.doubleValue();
}
/**
* Return the integer held by this option
*
* @return our integer value.
* @exception OptionMisuseException
*/
public int getInteger() {
if (mType != INTEGER)
throw new ExFull(ResId.OptionMisuseException, getName());
Integer i = (Integer) mValue;
return i.intValue();
}
/**
* Return the integer held by this option
*
* @return the 0-based index (into validValues specified in the ructor) that
* this option has been set to via setValue. Returns -1 if option
* has not been set.
*/
public int getMatchingIndex() {
return mnMatchingIndex;
}
/**
* Return the name of this option
*
* @return our name (set in the ructor)
*/
public String getName() {
return mOptionName;
}
/**
* Return the string value held by this option
*
* @return our string value
* @exception OptionMisuseException
*/
public String getString() {
if (mType != STRING)
throw new ExFull(ResId.OptionMisuseException, getName());
return mString;
}
// /**
// * Find out if the option is empty
// *
// * @return true if the option is empty, false otherwise
// */
// private boolean isEmpty() {
// return mType == EMPTY;
// }
/**
* Return whether this option has been set via setValue
*
* @return true if the option has been set, false if it has not. (isSet() is
* equivalent to getMatchingIndex != -1).
*/
public boolean isSet() {
return getMatchingIndex() != -1;
}
/**
* Reset an option. This empties it and clears the locked flag.
*
*/
public void reset() {
empty();
mbLocked = false;
}
/**
* Assign this option to a boolean
*
* @param b
* the boolean value to take on
*/
private void setBool(boolean b) {
empty();
mType = BOOL;
mValue = Boolean.valueOf(b);
}
/**
* Assign this option to a double
*
* @param d
* the double value to take on
*/
private void setDouble(double d) {
empty();
mType = DOUBLE;
mValue = new Double(d);
}
/**
* Assign this option to an integer
*
* @param i
* the integer value to take on
*/
private void setInteger(int i) {
empty();
mType = INTEGER;
mValue = Integer.valueOf(i);
}
/**
* Assign this option to a string
*
* @param s
* the string value to take on
*/
private void setString(String s) {
empty();
mType = STRING;
mString = s;
}
/**
* Set the value of this option (value is validated against validValues
* specified in ructor).
*
* After setting the value, the parsed value may be read via
* getInteger(), getString(), getMatchingIndex()
etc.
*
* @param value
* the value to take on
* @param bCritical
* disallow further modification of this option.
* @exception OptionLockedException
*/
public void setValue(String value, boolean bCritical) {
if (mbLocked) {
// Value is locked; ignore request, unless the caller has specified
// that they want to lock it, in which case throw an exception if
// the values are not the same.
if (bCritical) {
Option oCheck = new Option(this);
oCheck.mbLocked = false;
oCheck.setValue(value, true);
if (!this.equals(oCheck))
throw new ExFull(ResId.OptionLockedException, getName());
}
return;
}
empty();
int nIndex = 0;
mbLocked = bCritical;
String[] tokens = mValidValues.split("\\|");
for (int i = 0; i < tokens.length; i++) {
String token = tokens[i];
if (token.equals("%d")) {
try {
int long_value = Integer.parseInt(value);
setInteger(long_value);
mnMatchingIndex = nIndex;
return;
} catch (NumberFormatException n) {
// It's not a number. continue...
}
}
else if (token.equals("%lf")) {
double double_value = Double.parseDouble(value);
if (!Double.isInfinite(double_value))
setDouble(double_value);
mnMatchingIndex = nIndex;
return;
}
else if (token.equals("%s")) {
setString(value);
mnMatchingIndex = nIndex;
return;
}
else if (token.equals("%b")) {
// match on 1 or 0
char c = 0;
if (value.length() == 1)
c = value.charAt(0);
if ((c == '1') || (c == '0')) {
setBool(c == '1');
mnMatchingIndex = nIndex;
return;
}
}
else if (token.equals(value)) {
// A literal match of a keyword.
mType = LITERAL;
mnMatchingIndex = nIndex;
return;
}
nIndex++;
}
// Invalid value passed in; unable to match one of the valid values.
mbLocked = false;
MsgFormatPos oMessage = new MsgFormatPos(
ResId.InvalidOptionValueException);
oMessage.format(getName());
oMessage.format(value);
throw new ExFull(oMessage);
}
}