package nl.ipo.cds.validation.string;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;
import nl.ipo.cds.validation.AbstractBinaryTestExpression;
import nl.ipo.cds.validation.AbstractExpression;
import nl.ipo.cds.validation.AbstractUnaryTestExpression;
import nl.ipo.cds.validation.BinaryExpression;
import nl.ipo.cds.validation.Expression;
import nl.ipo.cds.validation.UnaryExpression;
import nl.ipo.cds.validation.ValidationMessage;
import nl.ipo.cds.validation.ValidatorContext;
import nl.ipo.cds.validation.execute.Compiler;
import nl.ipo.cds.validation.execute.CompilerException;
import nl.ipo.cds.validation.execute.ExpressionExecutor;
import org.apache.commons.lang.StringUtils;
public class Strings {
public static class IsBlank<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>> extends AbstractUnaryTestExpression<K, C, String> {
public IsBlank (final Expression<K, C, String> input) {
super(input, "Strings.IsBlank");
}
@Override
public boolean test (String value, C context) {
return value == null || StringUtils.isBlank (value);
}
}
public static class IsUrl<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>> extends AbstractUnaryTestExpression<K, C, String> {
public IsUrl (final Expression<K, C, String> input) {
super(input, "Strings.IsUrl");
}
@Override
public boolean test (String value, C context) {
try {
new URL (value);
return true;
} catch (MalformedURLException e) {
return false;
}
}
}
public static class IsUUID<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>> extends AbstractUnaryTestExpression<K, C, String> {
public IsUUID (final Expression<K, C, String> input) {
super (input, "Strings.IsUUID");
}
@Override
public boolean test (final String value, final C context) {
try {
UUID.fromString (value);
} catch(IllegalArgumentException e) {
return false;
}
return true;
}
}
public static class Matches<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>> extends AbstractBinaryTestExpression<K, C, String, String> {
public Matches (final Expression<K, C, String> input, final Expression<K, C, String> pattern) {
super (input, pattern, "Strings.Matches");
}
@Override
public boolean test (final String input, String pattern, final C context) {
if (input == null || pattern == null) {
return false;
}
return input.matches (pattern);
}
}
public static class Length<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>> extends AbstractExpression<K, C, Integer> implements UnaryExpression<K, C, Integer, String> {
final Expression<K, C, String> input;
public Length (final Expression<K, C, String> input) {
this.input = input;
}
@Override
public Class<Integer> getResultType () {
return Integer.class;
}
@Override
public ExpressionExecutor<C> getExecutor (final Compiler<C> compiler) throws CompilerException {
try {
return ExpressionExecutor.create (
this,
input,
false,
true,
MethodHandles.lookup ().findVirtual (String.class, "length", MethodType.methodType (Integer.TYPE)),
false
);
} catch (NoSuchMethodException | IllegalAccessException e) {
throw new CompilerException (e);
}
}
@Override
public Class<String> getInputType () {
return input.getResultType ();
}
}
public static class Join<K extends Enum<K> & ValidationMessage<K, C>, C extends ValidatorContext<K, C>> extends AbstractExpression<K, C, String> implements BinaryExpression<K, C, String, String[], String> {
final Expression<K, C, String[]> input;
final Expression<K, C, String> separator;
public Join (final Expression<K, C, String[]> input, final Expression<K, C, String> separator) {
if (input == null) {
throw new NullPointerException ("input cannot be null");
}
if (separator == null) {
throw new NullPointerException ("separator cannot be null");
}
this.input = input;
this.separator = separator;
}
@Override
public Class<String> getResultType () {
return String.class;
}
public String evaluate (final ValidatorContext<K, C> context, final String[] input, final String rawSeparator) {
final String[] list = input;
final String separator = rawSeparator == null ? "" : rawSeparator;
if (list == null) {
return "";
}
final StringBuilder builder = new StringBuilder ();
for (final String s: list) {
if (builder.length () > 0) {
builder.append (separator);
}
builder.append (s);
}
return builder.toString ();
}
@Override
public Class<String[]> getTypeA () {
return String[].class;
}
@Override
public Class<String> getTypeB () {
return String.class;
}
private final static MethodHandle evaluateHandle = Compiler
.findMethod (
Join.class,
"evaluate",
MethodType.methodType (String.class, ValidatorContext.class, String[].class, String.class)
);
@Override
public ExpressionExecutor<C> getExecutor(final Compiler<C> compiler) throws CompilerException {
return ExpressionExecutor.create (
this,
input,
separator,
false,
true,
evaluateHandle.bindTo (this),
false
);
}
}
}