MaskBuilder.java
// Copyright (C) 2017 Benoît Moreau (ben.12)
//
// This software may be modified and distributed under the terms
// of the MIT license. See the LICENSE file for details.
package com.ben12.infxnity.control.text;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import com.ben12.infxnity.control.text.MaskTextFilter.MaskCharacter;
import javafx.util.Builder;
/**
* Mask builder use to create a mask for {@link MaskTextFilter}.
*
* @author Benoît Moreau (ben.12)
* @see MaskTextFilter
*/
public class MaskBuilder implements Builder<MaskCharacter[]>
{
private final List<MaskCharacter> mask = new ArrayList<>();
public static MaskBuilder newBuilder()
{
return new MaskBuilder();
}
/**
* Appends an unmodifiable text.
*
* @param value
* the literal string to append
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLiteral(final String value)
{
for (final char c : value.toCharArray())
{
mask.add(new LiteralMaskCharacter(c));
}
return this;
}
/**
* Appends a character where only digit are allowed.
* Default value is '0'.
*
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendDigit()
{
return appendDigit(1);
}
/**
* Appends a character where only digit are allowed.
*
* @param defaultValue
* the default value
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendDigit(final char defaultValue)
{
return appendDigit(1, defaultValue);
}
/**
* Appends some characters where only digit are allowed.
* Default value is '0'.
*
* @param repeat
* number of character to append
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendDigit(final int repeat)
{
return appendDigit(repeat, '0');
}
/**
* Appends some characters where only digit are allowed.
*
* @param repeat
* number of character to append
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendDigit(final int repeat, final char defaultValue)
{
return append(repeat, Character::isDigit, defaultValue);
}
/**
* Appends a character where only upper case letter are allowed.
* Typing lower case character will set an upper case character.
* Default value is 'A'.
*
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendUpperCase()
{
return appendUpperCase(1);
}
/**
* Appends a character where only upper case letter are allowed.
* Typing lower case character will set an upper case character.
*
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendUpperCase(final char defaultValue)
{
return appendUpperCase(1, defaultValue);
}
/**
* Appends some characters where only upper case letter are allowed.
* Typing lower case character will set an upper case character.
* Default value is 'A'.
*
* @param repeat
* number of character to append
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendUpperCase(final int repeat)
{
return appendUpperCase(repeat, 'A');
}
/**
* Appends some characters where only upper case letter are allowed.
* Typing lower case character will set an upper case character.
*
* @param repeat
* number of character to append
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendUpperCase(final int repeat, final char defaultValue)
{
return append(repeat, Character::isLetter, Character::toUpperCase, defaultValue);
}
/**
* Appends a character where only lower case letter are allowed.
* Typing upper case character will set a lower case character.
* Default value is 'a'.
*
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLowerCase()
{
return appendLowerCase(1);
}
/**
* Appends a character where only lower case letter are allowed.
* Typing upper case character will set a lower case character.
*
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLowerCase(final char defaultValue)
{
return appendLowerCase(1, defaultValue);
}
/**
* Appends some characters where only lower case letter are allowed.
* Typing upper case character will set a lower case character.
* Default value is 'a'.
*
* @param repeat
* number of character to append
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLowerCase(final int repeat)
{
return appendLowerCase(repeat, 'a');
}
/**
* Appends some characters where only lower case letter are allowed.
* Typing upper case character will set a lower case character.
*
* @param repeat
* number of character to append
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLowerCase(final int repeat, final char defaultValue)
{
return append(repeat, Character::isLetter, Character::toLowerCase, defaultValue);
}
/**
* Appends a character where only letter are allowed.
* Default value is 'a'.
*
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLetter()
{
return appendLetter(1);
}
/**
* Appends a character where only letter are allowed.
*
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLetter(final char defaultValue)
{
return appendLetter(1, defaultValue);
}
/**
* Appends some characters where only letter are allowed.
* Default value is 'a'.
*
* @param repeat
* number of character to append
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLetter(final int repeat)
{
return appendLetter(repeat, 'a');
}
/**
* Appends some characters where only letter are allowed.
*
* @param repeat
* number of character to append
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLetter(final int repeat, final char defaultValue)
{
return append(repeat, Character::isLetter, defaultValue);
}
/**
* Appends a character where only letter or digit are allowed.
* Default value is 'a'.
*
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLetterOrDigit()
{
return appendLetterOrDigit(1);
}
/**
* Appends a character where only letter or digit are allowed.
*
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLetterOrDigit(final char defaultValue)
{
return appendLetterOrDigit(1, defaultValue);
}
/**
* Appends some characters where only letter or digit are allowed.
* Default value is 'a'.
*
* @param repeat
* number of character to append
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLetterOrDigit(final int repeat)
{
return appendLetterOrDigit(repeat, 'a');
}
/**
* Appends some characters where only letter or digit are allowed.
*
* @param repeat
* number of character to append
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendLetterOrDigit(final int repeat, final char defaultValue)
{
return append(repeat, Character::isLetterOrDigit, defaultValue);
}
/**
* Appends a character where only hexadecimal are allowed.
* Typing lower case hexadecimal letter will set an upper case hexadecimal letter.
* Default value is 'a'.
*
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendHexa()
{
return appendHexa(1);
}
/**
* Appends a character where only hexadecimal are allowed.
* Typing lower case hexadecimal letter will set an upper case hexadecimal letter.
*
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendHexa(final char defaultValue)
{
return appendHexa(1, defaultValue);
}
/**
* Appends some characters where only hexadecimal are allowed.
* Typing lower case hexadecimal letter will set an upper case hexadecimal letter.
* Default value is 'a'.
*
* @param repeat
* number of character to append
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendHexa(final int repeat)
{
return appendHexa(repeat, '0');
}
/**
* Appends some characters where only hexadecimal are allowed.
* Typing lower case hexadecimal letter will set an upper case hexadecimal letter.
*
* @param repeat
* number of character to append
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendHexa(final int repeat, final char defaultValue)
{
return append(repeat,
c -> (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7'
|| c == '8' || c == '9' || c == 'a' || c == 'A' || c == 'b' || c == 'B' || c == 'c'
|| c == 'C' || c == 'd' || c == 'D' || c == 'e' || c == 'E' || c == 'f' || c == 'F'),
Character::toUpperCase, defaultValue);
}
/**
* Appends a character where any character are allowed.
* Default value is ' '.
*
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendAny()
{
return appendAny(1);
}
/**
* Appends a character where any character are allowed.
*
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendAny(final char defaultValue)
{
return appendAny(1, defaultValue);
}
/**
* Appends some characters where any character are allowed.
* Default value is ' '.
*
* @param repeat
* number of character to append
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendAny(final int repeat)
{
return appendAny(repeat, ' ');
}
/**
* Appends some characters where any character are allowed.
*
* @param repeat
* number of character to append
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder appendAny(final int repeat, final char defaultValue)
{
return append(repeat, c -> true, defaultValue);
}
/**
* Appends some characters where allowing only character defined by the <code>allowed</code> predicate.
*
* @param repeat
* number of character to append
* @param allowed
* {@link Predicate} called to allow characters
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder append(final int repeat, final Predicate<Character> allowed, final char defaultValue)
{
return append(repeat, new DefaultMaskCharacter(allowed, defaultValue));
}
/**
* Appends some characters where allowing only character defined by the <code>allowed</code> predicate.
*
* @param repeat
* number of character to append
* @param allowed
* {@link Predicate} called to allow characters
* @param transformation
* transformation to apply to the input characters
* @param defaultValue
* the default value for each character
* @return this {@link MaskBuilder}
*/
public MaskBuilder append(final int repeat, final Predicate<Character> allowed,
final UnaryOperator<Character> transformation, final char defaultValue)
{
return append(repeat, new DefaultMaskCharacter(allowed, transformation, defaultValue));
}
/**
* Appends a {@link MaskCharacter}.
*
* @param maskCharacter
* the {@link MaskCharacter} to append
* @return this {@link MaskBuilder}
*/
public MaskBuilder append(final MaskCharacter maskCharacter)
{
return append(1, maskCharacter);
}
/**
* Appends some {@link MaskCharacter}.
*
* @param repeat
* number of character to append
* @param maskCharacter
* the {@link MaskCharacter} to append
* @return this {@link MaskBuilder}
*/
public MaskBuilder append(final int repeat, final MaskCharacter maskCharacter)
{
for (int i = 0; i < repeat; i++)
{
mask.add(maskCharacter);
}
return this;
}
@Override
public MaskCharacter[] build()
{
return mask.toArray(new MaskCharacter[mask.size()]);
}
private static final class DefaultMaskCharacter implements MaskCharacter
{
private final char defaultValue;
private final Predicate<Character> allowed;
private final UnaryOperator<Character> transformation;
public DefaultMaskCharacter(final Predicate<Character> pAllowed, final char pDefaultValue)
{
this(pAllowed, UnaryOperator.identity(), pDefaultValue);
}
public DefaultMaskCharacter(final Predicate<Character> pAllowed, final UnaryOperator<Character> pTransformation,
final char pDefaultValue)
{
allowed = pAllowed;
defaultValue = pDefaultValue;
transformation = pTransformation;
}
@Override
public boolean isAllowed(final char c)
{
return allowed.test(c);
}
@Override
public char tranform(final char c)
{
return transformation.apply(c);
}
@Override
public char getDefault()
{
return defaultValue;
}
@Override
public boolean isNavigable()
{
return true;
}
}
private static final class LiteralMaskCharacter implements MaskCharacter
{
private final char constant;
public LiteralMaskCharacter(final char pConstant)
{
constant = pConstant;
}
@Override
public boolean isAllowed(final char c)
{
return constant == c;
}
@Override
public char tranform(final char c)
{
return constant;
}
@Override
public char getDefault()
{
return constant;
}
@Override
public boolean isNavigable()
{
return false;
}
}
}