net.sf.jett.util.AttributeUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jett-core Show documentation
Show all versions of jett-core Show documentation
JETT is a Java API that reads an Excel spreadsheet as a template, takes your data, and
creates a new Excel spreadsheet that contains your data, formatted as in the template. It
works with .xls and .xlsx template spreadsheets.
The newest version!
package net.sf.jett.util;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.CreationHelper;
import net.sf.jett.exception.AttributeExpressionException;
import net.sf.jett.expression.Expression;
import net.sf.jett.tag.Tag;
/**
* The AttributeUtil
class provides methods for
* evaluating Expressions
that are expected to result in a
* specific type.
*
* @author Randy Gettman
* @since 0.3.0
*/
public class AttributeUtil
{
/**
* Separates expressions in attributes that take multiple values. This was
* originally defined as the same value in multiple sub-classes, but was
* moved to BaseTag/AttributeUtil for 0.3.0.
*
* @since 0.3.0
*/
public static final String SPEC_SEP = ";";
/**
* Separates expressions in attributes that take multiple values at a second
* level. I.e. this is possible: "0,1;2,3" which would be interpreted as a
* 2D array: [[0, 1], [2, 3]]
.
*
* @since 0.4.0
*/
public static final String SPEC_SEP_2 = ",";
/**
* Regex to validate a JEXL
* variable name.
*
* @since 0.11.0
*/
private static final String REGEX_JEXL_VARNAME = "[A-Za-z_][A-Za-z0-9_]*";
/**
* List of
* JEXL reserved words.
*
* @since 0.11.0
*/
private static final List JEXL_RESERVED_WORDS = Arrays.asList(
"or", "and", "eq", "ne", "lt", "gt", "le", "ge", "div", "mod", "not", "null",
"true", "false", "new", "var", "return"
);
/**
* Don't allow instances.
*
* @since 0.8.0
*/
private AttributeUtil()
{
}
/**
* Helper method to throw an AttributeExpressionException
with
* a common message indicating that a null value resulted, or an expected
* variable was missing when attempting to evaluate an expression inside an
* attribute value.
*
* @param tag The Tag
.
* @param expression The original expression.
* @return AttributeExpressionException
with a standard message.
*/
private static AttributeExpressionException nullValueOrExpectedVariableMissing(Tag tag, String expression)
{
return attributeValidationFailure(tag, expression,
"Null value or expected variable missing in expression");
}
/**
* Helper method to throw an AttributeExpressionException
with
* a custom validation message.
*
* @param tag The Tag
.
* @param expression The original expression.
* @param message The custom message.
* @return AttributeExpressionException
with a custom message.
* @since 0.9.0
*/
private static AttributeExpressionException attributeValidationFailure(Tag tag,
String expression, String message)
{
return new AttributeExpressionException(message + " \"" +
expression + "\"." + SheetUtil.getTagLocationWithHierarchy(tag));
}
/**
* Helper method to throw an AttributeExpressionException
with
* a custom validation message.
*
* @param tag The Tag
.
* @param expression The original expression.
* @param message The custom message.
* @param cause The Exception
that caused the validation failure.
* @return AttributeExpressionException
with a custom message.
* @since 0.9.0
*/
private static AttributeExpressionException attributeValidationFailure(Tag tag,
String expression, String message, Exception cause)
{
return new AttributeExpressionException(message + " \"" +
expression + "\"." + SheetUtil.getTagLocationWithHierarchy(tag), cause);
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a boolean value from
* the result, calling Boolean.parseBoolean()
on the result if
* necessary. If the text is null, then the result defaults to the given
* default boolean value.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param def The default value if the text is null.
* @return The boolean result.
*/
public static boolean evaluateBoolean(Tag tag,
RichTextString text, Map beans, boolean def)
{
boolean result;
if (text == null)
return def;
Object obj = Expression.evaluateString(text.toString(), tag.getWorkbookContext().getExpressionFactory(), beans);
if (obj == null)
throw nullValueOrExpectedVariableMissing(tag, text.toString());
if (obj instanceof Boolean)
result = (Boolean) obj;
else
result = Boolean.parseBoolean(obj.toString());
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract an integer value from
* the result, calling toString()
on the result and parsing it
* if necessary. If the text is null, then the result defaults to the given
* default integer value.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param def The default value if the text is null.
* @return The integer result.
* @throws AttributeExpressionException If the result of the evaluation of the text is
* not a number.
*/
public static int evaluateInt(Tag tag,
RichTextString text, Map beans, String attrName, int def)
{
int result;
if (text == null)
return def;
Object obj = Expression.evaluateString(text.toString(), tag.getWorkbookContext().getExpressionFactory(), beans);
if (obj == null)
throw nullValueOrExpectedVariableMissing(tag, text.toString());
if (obj instanceof Number)
{
result = ((Number) obj).intValue();
}
else
{
try
{
result = Integer.parseInt(obj.toString());
}
catch (NumberFormatException e)
{
throw attributeValidationFailure(tag, text.toString(),
"The \"" + attrName + "\" attribute must be an integer");
}
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract an integer value from
* the result, calling toString()
on the result and parsing it
* if necessary. Enforce the result to be non-negative.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param def The default value if the text is null.
* @return The integer result.
* @throws AttributeExpressionException If the result of the evaluation of the text is
* not a number, or if the result is negative.
*/
public static int evaluateNonNegativeInt(Tag tag,
RichTextString text, Map beans, String attrName, int def)
{
int result = evaluateInt(tag, text, beans, attrName, def);
if (result < 0)
{
throw attributeValidationFailure(tag, text.toString(),
"The \"" + attrName + "\" attribute must be non-negative");
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract an integer value from
* the result, calling toString()
on the result and parsing it
* if necessary. Enforce the result to be positive.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param def The default value if the text is null.
* @return The integer result.
* @throws AttributeExpressionException If the result of the evaluation of the text is
* not a number, or if the result is not positive.
*/
public static int evaluatePositiveInt(Tag tag,
RichTextString text, Map beans, String attrName, int def)
{
int result = evaluateInt(tag, text, beans, attrName, def);
if (result <= 0)
{
throw attributeValidationFailure(tag, text.toString(),
"The \"" + attrName + "\" attribute must be positive");
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract an integer value from
* the result, calling toString()
on the result and parsing it
* if necessary. Enforce the result to be not zero.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param def The default value if the text is null.
* @return The integer result.
* @throws AttributeExpressionException If the result of the evaluation of the text is
* not a number, or if the result is zero.
*/
public static int evaluateNonZeroInt(Tag tag,
RichTextString text, Map beans, String attrName, int def)
{
int result = evaluateInt(tag, text, beans, attrName, def);
if (result == 0)
{
throw attributeValidationFailure(tag, text.toString(),
"The \"" + attrName + "\" attribute must not be zero");
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a double value from
* the result, calling toString()
on the result and parsing it
* if necessary.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param def The default value if the text is null.
* @return The double result.
* @throws AttributeExpressionException If the result of the evaluation of the text is
* not a number.
*/
public static double evaluateDouble(Tag tag,
RichTextString text, Map beans, String attrName, double def)
{
double result;
if (text == null)
return def;
Object obj = Expression.evaluateString(text.toString(), tag.getWorkbookContext().getExpressionFactory(), beans);
if (obj == null)
throw nullValueOrExpectedVariableMissing(tag, text.toString());
if (obj instanceof Number)
{
result = ((Number) obj).doubleValue();
}
else
{
try
{
result = Double.parseDouble(obj.toString());
}
catch (NumberFormatException e)
{
throw attributeValidationFailure(tag, text.toString(),
"The \"" + attrName + "\" attribute must be a number");
}
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a double value from
* the result, calling toString()
on the result and parsing it
* if necessary. Enforce the result to be non-negative.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param def The default value if the text is null.
* @return The double result.
* @throws AttributeExpressionException If the result of the evaluation of the text is
* not a number, or if the result is negative.
* @since 0.11.0
*/
public static double evaluateNonNegativeDouble(Tag tag,
RichTextString text, Map beans, String attrName, double def)
{
double result = evaluateDouble(tag, text, beans, attrName, def);
if (result < 0)
{
throw attributeValidationFailure(tag, text.toString(),
"The \"" + attrName + "\" attribute must be non-negative");
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a double value from
* the result, calling toString()
on the result and parsing it
* if necessary. Enforce the result to be positive.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param def The default value if the text is null.
* @return The double result.
* @throws AttributeExpressionException If the result of the evaluation of the text is
* not a number, or if the result is not positive.
* @since 0.11.0
*/
public static double evaluatePositiveDouble(Tag tag,
RichTextString text, Map beans, String attrName, double def)
{
double result = evaluateDouble(tag, text, beans, attrName, def);
if (result <= 0)
{
throw attributeValidationFailure(tag, text.toString(),
"The \"" + attrName + "\" attribute must be positive");
}
return result;
}
/**
* Evaluates the given rich text, which may have embedded
* Expressions
, and attempts to extract the result, which may
* be either a RichTextString
or a String
.
*
* @param tag The Tag
.
* @param text Rich text which may have embedded Expressions
.
* @param helper A CreationHelper
(for creating
* RichTextStrings
).
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param def The default value if the text is null.
* @return The String
or RichTextString
result.
* @since 0.9.0
*/
public static Object evaluateRichTextStringNotNull(Tag tag,
RichTextString text, CreationHelper helper, Map beans, String attrName, String def)
{
if (text == null)
return def;
Object result = Expression.evaluateString(text, helper, tag.getWorkbookContext().getExpressionFactory(), beans);
if (result == null || result.toString().length() == 0)
{
throw attributeValidationFailure(tag, text.toString(),
"Value for \"" + attrName + "\" must not be null or empty");
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a String
* result, calling toString()
on the result.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param def The default value if the text is null.
* @return The String
result.
*/
public static String evaluateString(Tag tag,
RichTextString text, Map beans, String def)
{
if (text == null)
return def;
Object obj = Expression.evaluateString(text.toString(), tag.getWorkbookContext().getExpressionFactory(), beans);
return (obj == null) ? null : obj.toString();
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a String
* result, calling toString()
on the result.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param def The default value if the text is null.
* @return The String
result.
*/
public static String evaluateStringNotNull(Tag tag,
RichTextString text, Map beans, String attrName, String def)
{
String result = evaluateString(tag, text, beans, def);
if (result == null || result.length() == 0)
{
throw attributeValidationFailure(tag, text.toString(),
"Value for \"" + attrName + "\" must not be null or empty");
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a String
* result, calling toString()
on the result. Enforces that the
* result is one of the given expected values, ignoring case.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param legalValues A List
of expected values.
* @param def The default value if the text is null.
* @return The String
result.
* @throws AttributeExpressionException If the result isn't one of the expected legal
* values.
*/
public static String evaluateStringSpecificValues(Tag tag,
RichTextString text, Map beans, String attrName, List legalValues, String def)
{
String result = evaluateString(tag, text, beans, def);
for (String legalValue : legalValues)
{
if (legalValue.equalsIgnoreCase(result))
return result;
}
throw attributeValidationFailure(tag, text.toString(),
"Unknown value for \"" + attrName + "\": " + result +
" (expected one of " + legalValues.toString() + ").");
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a String
* result, calling toString()
on the result. Enforces that the
* result is a valid JEXL variable name, which contains only the following
* characters: [A-Z][a-z][0-9][_]
, and not starting with a
* number.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @return The String
result.
* @throws AttributeExpressionException If the result isn't a legal JEXL
* variable name.
* @since 0.11.0
*/
public static String evaluateStringVarName(Tag tag,
RichTextString text, Map beans, String attrName)
{
String result = evaluateStringNotNull(tag, text, beans, attrName, null);
if (!result.matches(REGEX_JEXL_VARNAME))
{
throw attributeValidationFailure(tag, text.toString(),
"Not a valid JEXL variable name: " + result);
}
if (JEXL_RESERVED_WORDS.contains(result))
{
throw attributeValidationFailure(tag, text.toString(),
"Can't use a JEXL reserved word: " + result);
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a result, and cast it
* to the same class as the given expected class.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param expectedClass The result is expected to be of the given class or
* of a subclass.
* @param def The default value if the text is null.
* @param The Class
of the expected return type.
* @return The result.
* @throws AttributeExpressionException If the result is not of the expected class or
* of a subclass.
*/
@SuppressWarnings("unchecked")
public static T evaluateObject(Tag tag,
RichTextString text, Map beans, String attrName, Class expectedClass, T def)
{
if (text == null)
return def;
return evaluateObject(tag, text.toString(), beans, attrName, expectedClass, def);
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a result, and cast it
* to the same class as the given expected class.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param attrName The attribute name. This is only used when constructing
* an exception message.
* @param expectedClass The result is expected to be of the given class or
* of a subclass.
* @param def The default value if the text is null.
* @param The Class
of the expected return type.
* @return The result.
* @throws AttributeExpressionException If the result is not of the expected class or
* of a subclass.
*/
@SuppressWarnings("unchecked")
public static T evaluateObject(Tag tag,
String text, Map beans, String attrName, Class expectedClass, T def)
{
T result;
if (text == null)
return def;
Object obj = Expression.evaluateString(text, tag.getWorkbookContext().getExpressionFactory(), beans);
if (obj == null)
throw nullValueOrExpectedVariableMissing(tag, text);
Class objClass = obj.getClass();
if (expectedClass.isAssignableFrom(objClass))
{
// Don't expect a ClassCastException after the above test.
result = expectedClass.cast(obj);
}
else if (obj instanceof String)
{
String className = (String) obj;
// Treat as a class name to instantiate.
try
{
Class actualClass = (Class) Class.forName(className);
result = actualClass.newInstance();
if (!expectedClass.isInstance(result))
{
throw attributeValidationFailure(tag, text, "Expected a \"" + expectedClass.getName() + "\" for \"" +
attrName + "\", but instantiated a \"" + className + "\".");
}
}
catch (ClassNotFoundException e)
{
throw attributeValidationFailure(tag, text, "Expected a \"" + expectedClass.getName() + "\" for \"" +
attrName + "\", could not find class \"" + className + "\"", e);
}
catch (InstantiationException | IllegalAccessException | ClassCastException e)
{
throw attributeValidationFailure(tag, text, "Expected a \"" + expectedClass.getName() + "\" for \"" +
attrName + "\", could not instantiate class \"" + className + "\": ", e);
}
}
else
{
throw attributeValidationFailure(tag, text, "Expected a \"" + expectedClass.getName() + "\" for \"" +
attrName + "\", got a \"" + obj.getClass().getName() + "\": ");
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a List
out
* of the result, parsing a delimited list to create a list if necessary.
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param def The default value if the text is null.
* @return A List
.
*/
public static List evaluateList(Tag tag,
RichTextString text, Map beans, List def)
{
List result;
if (text == null)
return def;
Object obj = Expression.evaluateString(text.toString(), tag.getWorkbookContext().getExpressionFactory(), beans);
if (obj == null)
throw nullValueOrExpectedVariableMissing(tag, text.toString());
if (obj instanceof List)
{
List list = (List) obj;
result = new ArrayList<>(list.size());
for (Object item : list)
result.add(item.toString());
}
else
{
String[] items = obj.toString().split(SPEC_SEP);
result = Arrays.asList(items);
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a List
of
* Integers
from the result, accepting an int
* array or a Collection
or delimited list of numbers.
* Examples of proper input:
*
* - [0, 1, 2]
*
- (ArrayList){0, 1, 2}
*
- "0; 1; 2"
*
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param def The default value if the text is null.
* @return A List
of Integers
.
*/
public static List evaluateIntegerArray(Tag tag,
RichTextString text, Map beans, List def)
{
List result = new ArrayList<>();
if (text == null)
return def;
Object obj = Expression.evaluateString(text.toString(), tag.getWorkbookContext().getExpressionFactory(), beans);
if (obj == null)
throw nullValueOrExpectedVariableMissing(tag, text.toString());
if (obj instanceof int[])
{
int[] intArray = (int[]) obj;
for (int i : intArray)
result.add(i);
}
else if (obj instanceof Integer[])
{
Integer[] intArray = (Integer[]) obj;
result.addAll(Arrays.asList(intArray));
}
else if (obj instanceof Collection)
{
Collection c = (Collection) obj;
for (Object o : c)
{
if (o instanceof Number)
{
result.add(((Number) o).intValue());
}
else
{
try
{
result.add(Integer.parseInt(o.toString()));
}
catch (NumberFormatException e)
{
throw attributeValidationFailure(tag, text.toString(),
"Expected an integer, got " + o.toString(), e);
}
}
}
}
else
{
String[] items = obj.toString().split(SPEC_SEP);
for (String item : items)
{
try
{
result.add(Integer.parseInt(item));
}
catch (NumberFormatException e)
{
throw attributeValidationFailure(tag, text.toString(),
"Expected an integer, got " + item, e);
}
}
}
return result;
}
/**
* Evaluates the given text, which may have embedded
* Expressions
, and attempts to extract a List
of
* Lists
of Integers
from the result, accepting a
* 2D int
array or a Collection
of
* Collections
or delimited list of numbers.
* Examples of proper input:
*
* - [[0, 1], [2]]
*
- (ArrayList){(ArrayList){0, 1}, (ArrayList){2}}
*
- "0, 1; 2"
*
*
* @param tag The Tag
.
* @param text Text which may have embedded Expressions
.
* @param beans A Map
of bean names to bean values.
* @param def The default value if the text is null.
* @return A List
of Lists
of
* Integers
.
*/
public static List> evaluateIntegerArrayArray(Tag tag,
RichTextString text, Map beans, List> def)
{
List> result = new ArrayList<>();
if (text == null)
return def;
Object obj = Expression.evaluateString(text.toString(), tag.getWorkbookContext().getExpressionFactory(), beans);
if (obj == null)
throw nullValueOrExpectedVariableMissing(tag, text.toString());
if (obj instanceof int[][])
{
int[][] intArray = (int[][]) obj;
for (int[] array : intArray)
{
List innerList = new ArrayList<>();
for (int i : array)
innerList.add(i);
result.add(innerList);
}
}
else if (obj instanceof Integer[][])
{
Integer[][] intArray = (Integer[][]) obj;
for (Integer[] array : intArray)
{
List innerList = new ArrayList<>();
innerList.addAll(Arrays.asList(array));
result.add(innerList);
}
}
else if (obj instanceof Collection)
{
Collection c = (Collection) obj;
for (Object o : c)
{
List innerList = new ArrayList<>();
if (o instanceof Collection)
{
Collection inner = (Collection) o;
for (Object innerObj : inner)
{
if (innerObj instanceof Number)
{
innerList.add(((Number) innerObj).intValue());
}
else
{
try
{
innerList.add(Integer.parseInt(innerObj.toString()));
}
catch (NumberFormatException e)
{
throw attributeValidationFailure(tag, text.toString(),
"Expected an integer, got " + o.toString(), e);
}
}
}
}
result.add(innerList);
}
}
else
{
String[] items = obj.toString().split(SPEC_SEP);
for (String item : items)
{
List innerList = new ArrayList<>();
String[] innerItems = item.split(SPEC_SEP_2);
for (String innerItem : innerItems)
{
try
{
innerList.add(Integer.parseInt(innerItem));
}
catch (NumberFormatException e)
{
throw attributeValidationFailure(tag, text.toString(),
"Expected an integer, got " + item, e);
}
}
result.add(innerList);
}
}
return result;
}
/**
* Ensures that exactly one of the given attribute values exists.
*
* @param tag The Tag
.
* @param attrValues A List
of attribute values.
* @param attrNames A List
of attribute names.
* @throws AttributeExpressionException If none of the attribute values is not null, or
* if more than one attribute value is not null.
*/
public static void ensureExactlyOneExists(Tag tag,
List attrValues, List attrNames)
{
int exists = 0;
for (RichTextString text : attrValues)
{
if (text != null)
{
exists++;
if (exists > 1)
{
throw attributeValidationFailure(tag, attrNames.toString(),
"Exactly one attribute must be specified");
}
}
}
if (exists != 1)
{
throw attributeValidationFailure(tag, attrNames.toString(),
"Exactly one attribute must be specified");
}
}
/**
* Ensures that at most one of the given attribute values exists.
*
* @param tag The Tag
.
* @param attrValues A List
of attribute values.
* @param attrNames A List
of attribute names.
* @throws AttributeExpressionException If more than one of the attribute values is not
* null.
* @since 0.4.0
*/
public static void ensureAtMostOneExists(Tag tag,
List attrValues, List attrNames)
{
int exists = 0;
for (RichTextString text : attrValues)
{
if (text != null)
{
exists++;
if (exists > 1)
{
throw attributeValidationFailure(tag, attrNames.toString(),
"At most one attribute must be specified");
}
}
}
if (exists != 1 && exists != 0)
{
throw attributeValidationFailure(tag, attrNames.toString(),
"At most one attribute must be specified");
}
}
/**
* Ensures that at least one of the given attribute values exists.
*
* @param tag The Tag
.
* @param attrValues A List
of attribute values.
* @param attrNames A List
of attribute names.
* @throws AttributeExpressionException If all of the attribute values are null.
* @since 0.4.0
*/
public static void ensureAtLeastOneExists(Tag tag,
List attrValues, List attrNames)
{
for (RichTextString text : attrValues)
{
if (text != null)
return;
}
throw attributeValidationFailure(tag, attrNames.toString(), "At least one attribute must be specified");
}
}