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

javax0.jamal.assertions.AbstractAssert Maven / Gradle / Ivy

There is a newer version: 2.8.1
Show newest version
package javax0.jamal.assertions;

import javax0.jamal.api.BadSyntax;
import javax0.jamal.api.Input;
import javax0.jamal.api.Macro;
import javax0.jamal.api.Processor;
import javax0.jamal.tools.InputHandler;
import javax0.jamal.tools.Params;

/**
 * Abstract class implementing the common parts of all concrete assertions.
 * 

* All assertions work on a set of parameters and options. * The options are parsed using the {@link Params} class. * The parameters are parsed using the {@link InputHandler#getParts(Input)} parsing. *

* There are two options implemented in this class: *

    *
  • {@code trim} (alias {@code strip}), and
  • *
  • {@code not} (alias {@code negate})
  • *
* The option {@code trim} will trim the white space from around the parameters before performing the assertion {@link #test(String[])}. * The option {@code not} will invert the result of the test. */ abstract class AbstractAssert implements Macro { private final int N; private final String defaultMessage; private final String negatedDefaultMessage; /** * This constructor must be invoked by the constructor of the child class. * * @param N the maximum number of parameters the assertion needs. * Assertions can work with N or with N-1 parameters. * The last parameter is the error message, and it is optional. * @param defaultMessage the default message in case the message parameter is missing and there is no negation in the options. * @param negatedDefaultMessage the default message in case the message parameter is missing and there is negation in the options. */ protected AbstractAssert(int N, String defaultMessage, String negatedDefaultMessage) { this.N = N; this.defaultMessage = defaultMessage; this.negatedDefaultMessage = negatedDefaultMessage; } /** * Child classes have to implement this method. * * @param parts the parts that have at least {@code N-1} parts. * If there were not enough parts an exception was already thrown and this method is not invoked. * @return {@code true} if the assertion is okay and {@code false} otherwise. * This method should not care about trimming or negation, it is done before and after the method was executed. */ protected abstract boolean test(String[] parts) throws BadSyntax; static boolean negateIfNeeded(boolean b, Params.Param not) throws BadSyntax { return b == !not.is(); } @Override public String evaluate(Input input, Processor processor) throws BadSyntax { // snippet Assertion_params Params.Param trim = Params.holder("trim", "strip").asBoolean(); Params.Param not = Params.holder("not", "negate").asBoolean(); Params.Param test = Params.holder("test", "boolean", "bool").asBoolean(); //end snippet Params.using(processor).between("()").from(this).keys(trim, not, test).parse(input); String[] parts = getParts(input, N, trim, this); if (negateIfNeeded(test(parts), not)) { return test.is() ? "true" : ""; } else { if (test.is()) { return "false"; } else { final String format = not.is() ? negatedDefaultMessage : defaultMessage; if (parts.length >= N && parts[N - 1].trim().length() > 0) { throw new BadSyntax(String.format(parts[N - 1], (Object[]) parts)); } throw new BadSyntax(getId() + " has failed " + String.format(format, (Object[]) parts)); } } } /** * The implementation of the naming assumes that the name of the class looks like {@code AsserXXX} where * {@code Assert} is a six character prefix, usually it is literally {@code 'Assert'} and it is followed by * the name of the assertion. The name of the macro will be {@code assert:} followed by the rest of the name of * the class lowercasing the first characters. For example: *
{@code
     * AssertEquals -> assert:equals
     * AssertSomeFunnyName -> assert:somFunnyName
     * AssireAny -> assert:any
     * }
*

* If the naming of the class does not conform to this schema or the macro implemented needs some special name then * the method has to be overridden. * * @return the name of the macro */ @Override public String getId() { final var s = this.getClass().getSimpleName().substring(6); return "assert:" + s.substring(0, 1).toLowerCase() + s.substring(1); } private static String[] getParts(Input input, int N, Params.Param trim, Macro macro) throws BadSyntax { final var parts = InputHandler.getParts(input, N); if (parts.length < N - 1) { throw new BadSyntax(macro.getId() + " needs at least " + (N - 1) + " arguments"); } if (trim.is()) { for (int i = 0; i < parts.length; i++) { parts[i] = parts[i].strip(); } } return parts; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy