All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.jett.util.AttributeUtil Maven / Gradle / Ivy

Go to download

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"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy