Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
functionalj.lens.lenses.StringAccess Maven / Gradle / Ivy
// ============================================================================
// Copyright (c) 2017-2021 Nawapunth Manusitthipol (NawaMan - http://nawaman.net).
// ----------------------------------------------------------------------------
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ============================================================================
package functionalj.lens.lenses;
import static functionalj.functions.StrFuncs.toStr;
import static functionalj.lens.lenses.StringAccessHelper.fromString;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.ToIntFunction;
import java.util.stream.Stream;
import functionalj.function.Func1;
import functionalj.lens.lenses.java.time.LocalDateAccess;
import functionalj.lens.lenses.java.time.LocalDateTimeAccess;
import functionalj.list.FuncList;
import functionalj.result.Result;
import lombok.val;
class StringAccessHelper {
static StringAccess $(Object ... objs) {
return str -> {
val eachToString = stringFrom(str);
return Stream.of(objs).map(eachToString).collect(joining());
};
}
static Func1 stringFrom(String str) {
return each -> stringFrom(each, str);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private static String stringFrom(Object each, String str) {
if (each instanceof Supplier) {
Supplier supplier = (Supplier)each;
Object newValue = supplier.get();
return toStr(newValue);
}
if (each instanceof Function) {
Function function = (Function)each;
Object newValue = function.apply(str);
return toStr(newValue);
}
return toStr(each);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
static Function fromString(Object object) {
if (object instanceof AnyAccess) {
return str -> ((AnyAccess) object).apply(str);
}
return __ -> object;
}
}
/**
* Classes implementing this interface know how to access to a String value.
**/
@FunctionalInterface
public interface StringAccess
extends
ObjectAccess,
ConcreteAccess> {
public static StringAccess of(Function accessToValue) {
requireNonNull(accessToValue);
if (accessToValue instanceof StringAccess) {
return (StringAccess)accessToValue;
}
if (accessToValue instanceof Func1) {
val func1 = (Func1)accessToValue;
val access = (StringAccess)func1::applyUnsafe;
return access;
}
val func = (Function)accessToValue;
val access = (StringAccess)(host -> func.apply(host));
return access;
}
@Override
public default StringAccess newAccess(Function access) {
return access::apply;
}
//== functionalities ==
public default CharacterAccessPrimitive charAt(int index) {
return host -> {
val strValue = apply(host);
val charValue = strValue.charAt(index);
return charValue;
};
}
// Extra
public default BooleanAccess thatIsBlank() {
return booleanAccess(true, str->str.trim().isEmpty());
}
public default BooleanAccess thatIsNotBlank() {
return booleanAccess(true, str->!str.trim().isEmpty());
}
// java.lang.String
public default IntegerAccess compareToIgnoreCase(String anotherString) {
return IntegerAccess.of(host -> {
if (host == null)
return (anotherString == null) ? 0 : -1;
val value = apply(host);
if (value == null)
return (anotherString == null) ? 0 : -1;
return value.compareToIgnoreCase(anotherString);
});
}
public default IntegerAccess compareToIgnoreCase(Function anotherStringFunction) {
return IntegerAccess.of(host -> {
if (host == null)
return 0;
val value = apply(host);
val another = anotherStringFunction.apply(host);
if (value == another)
return 0;
if (value == null)
return -1;
return value.compareToIgnoreCase(another);
});
}
public default StringAccess concat(Object ... suffixes) {
return stringAccess("", str -> {
val eachToString = StringAccessHelper.stringFrom(str);
String suffix = Stream.of(suffixes).map(eachToString).collect(joining());
return str + suffix;
});
}
public default StringAccess withPrefix(Object ... prefixes) {
return stringAccess("", str -> {
val eachToString = StringAccessHelper.stringFrom(str);
String prefix = Stream.of(prefixes).map(eachToString).collect(joining());
return prefix + str;
});
}
public default StringAccess withSuffix(Object ... suffixes) {
return stringAccess("", str -> {
val eachToString = StringAccessHelper.stringFrom(str);
String prefix = Stream.of(suffixes).map(eachToString).collect(joining());
return str + prefix;
});
}
public default StringAccess wrapBy(Object prefix, Object suffix) {
return stringAccess("", str -> {
val eachToString = StringAccessHelper.stringFrom(str);
String prefixStr = eachToString.apply(prefix);
String suffixStr = eachToString.apply(suffix);
return prefixStr + str + suffixStr;
});
}
public default BooleanAccess thatEqualsIgnoreCase(String anotherString) {
boolean isAnotherStringEmpty = (anotherString == null) || anotherString.isEmpty();
return BooleanAccess.of(host -> {
if (host == null)
return isAnotherStringEmpty;
val value = apply(host);
if (value == null)
return isAnotherStringEmpty;
return value.equalsIgnoreCase(anotherString);
});
}
public default BooleanAccess thatEqualsIgnoreCase(Function anotherStringFunction) {
return BooleanAccess.of(host -> {
val anotherString = anotherStringFunction.apply(host);
boolean isAnotherStringEmpty = (anotherString == null) || anotherString.isEmpty();
if (host == null)
return isAnotherStringEmpty;
val value = apply(host);
if (value == null)
return isAnotherStringEmpty;
return value.equalsIgnoreCase(anotherString);
});
}
public default BooleanAccess thatContentEquals(CharSequence charSequence) {
return BooleanAccess.of(host -> {
if (host == null)
return (charSequence == null);
val value = apply(host);
if (value == null)
return (charSequence == null);
return value.contentEquals(charSequence);
});
}
public default BooleanAccess thatContentEquals(Function anotherStringFunction) {
return BooleanAccess.of(host -> {
if (host == null)
return false;
val value = apply(host);
val another = anotherStringFunction.apply(host);
if (value == another)
return true;
if (value == null)
return false;
return value.contentEquals(another);
});
}
public default BooleanAccess thatContains(CharSequence charSequence) {
return BooleanAccess.of(host -> {
if (host == null)
return false;
val value = apply(host);
if (value == null)
return false;
return value.contains(charSequence);
});
}
public default BooleanAccess thatContains(Function anotherStringFunction) {
return BooleanAccess.of(host -> {
if (host == null)
return false;
val value = apply(host);
val another = anotherStringFunction.apply(host);
if (value == another)
return true;
if (value == null)
return false;
return value.contains(another);
});
}
public default BooleanAccess thatNotContains(CharSequence charSequence) {
return BooleanAccess.of(host -> {
if (host == null)
return true;
val value = apply(host);
if (value == null)
return true;
return !value.contains(charSequence);
});
}
public default BooleanAccess thatNotContains(Function anotherStringFunction) {
return BooleanAccess.of(host -> {
if (host == null)
return true;
val value = apply(host);
if (value == null)
return true;
val another = anotherStringFunction.apply(host);
return !value.contains(another);
});
}
public default BooleanAccess thatContainsIgnoreCase(CharSequence charSequence) {
return BooleanAccess.of(host -> {
if (host == null)
return false;
val value = apply(host);
if (value == null)
return false;
return value.toLowerCase().contains(charSequence.toString().toLowerCase());
});
}
public default BooleanAccess thatContainsIgnoreCase(Function anotherStringFunction) {
return BooleanAccess.of(host -> {
if (host == null)
return false;
val value = apply(host);
if (value == null)
return false;
val another = anotherStringFunction.apply(host);
return value.toLowerCase().contains(another.toString().toLowerCase());
});
}
public default BooleanAccess thatNotContainsIgnoreCase(CharSequence charSequence) {
return BooleanAccess.of(host -> {
if (host == null)
return false;
val value = apply(host);
if (value == null)
return false;
return !value.toLowerCase().contains(charSequence.toString().toLowerCase());
});
}
public default BooleanAccess thatNotContainsIgnoreCase(Function anotherStringFunction) {
return BooleanAccess.of(host -> {
if (host == null)
return true;
val value = apply(host);
if (value == null)
return true;
val another = anotherStringFunction.apply(host);
return !value.toLowerCase().contains(another.toString().toLowerCase());
});
}
public default BooleanAccess thatEndsWith(String suffix) {
boolean isSuffixEmpty = (suffix == null) || suffix.isEmpty();
return BooleanAccess.of(host -> {
if (host == null)
return isSuffixEmpty;
val value = apply(host);
if (value == null)
return isSuffixEmpty;
return value.endsWith(suffix);
});
}
public default BooleanAccess thatEndsWith(Function suffixFunction) {
return BooleanAccess.of(host -> {
val suffix = suffixFunction.apply(host);
boolean isSuffixEmpty = (suffix == null) || suffix.isEmpty();
if (host == null)
return isSuffixEmpty;
val value = apply(host);
if (value == null)
return isSuffixEmpty;
return value.endsWith(suffix);
});
}
/**
* Giving the format create a final string using {@link String#format(String, Object...)}.
* The string value from this access will be the first parameter for the formatting.
* The given otherArgs will be the subsequence parameters for the formatting.
* If any of the otherArgs is a Access, it will be applied with the string value.
*
* Examples:
*
* Simple: "Hello".formatWith("Word: %s"); will returns "Word: Hello"
* More args: "Hello".formatWith("Word: %s %s.", "there"); will returns "Word: Hello there."
* Access: "Hello".formatWith("Word: %s (%s).", $S.length()); will returns "Word: Hello (5)."
*
**/
public default StringAccess formatWith(String format, Object... otherArgs) {
return StringAccess.of(host -> {
val value = (host == null) ? null : apply(host);
val argStrs = FuncList.of(otherArgs).map(arg -> fromString(arg).apply(value)).prepend(value).toArray();
return String.format(format, argStrs);
});
}
/**
* Similar to another formatWith method but the format is derived from the string value.
**/
public default StringAccess formatWith(Function formatFunction, Object... otherArgs) {
return StringAccess.of(host -> {
val value = (host == null) ? null : apply(host);
val format = formatFunction.apply(host);
val argStrs = FuncList.of(otherArgs).map(arg -> fromString(arg).apply(value)).prepend(value).toArray();
return String.format(format, argStrs);
});
}
public default IntegerAccess indexOf(int chr) {
return IntegerAccess.of(host -> {
if (host == null) return -1;
val value = apply(host);
if (value == null) return -1;
return value.indexOf(chr);
});
}
public default IntegerAccess indexOf(ToIntFunction chrFunction) {
return IntegerAccess.of(host -> {
if (host == null) return -1;
val value = apply(host);
if (value == null) return -1;
val chr = chrFunction.applyAsInt(host);
return value.indexOf(chr);
});
}
public default IntegerAccess indexOf(int ch, int fromIndex) {
return intPrimitiveAccess(-1, str->str.indexOf(ch, fromIndex));
}
public default IntegerAccess indexOf(String needle) {
return IntegerAccess.of(host -> {
if (host == null) return -1;
val value = apply(host);
if (value == null) return -1;
return value.indexOf(needle);
});
}
public default IntegerAccess indexOf(Function needleFunction) {
return IntegerAccess.of(host -> {
if (host == null) return -1;
val value = apply(host);
if (value == null) return -1;
val needle = needleFunction.apply(host);
return value.indexOf(needle);
});
}
public default IntegerAccess indexOf(String needle, int fromIndex) {
return intPrimitiveAccess(-1, str->str.indexOf(needle, fromIndex));
}
public default BooleanAccess thatIsEmpty() {
return booleanAccess(true, str->str.isEmpty());
}
public default BooleanAccess thatIsNotEmpty() {
return booleanAccess(true, str->!str.isEmpty());
}
public default IntegerAccess lastIndexOf(int ch) {
return IntegerAccess.of(host -> {
if (host == null) return -1;
val value = apply(host);
if (value == null) return -1;
return value.indexOf(ch);
});
}
public default IntegerAccess lastIndexOf(ToIntFunction chrFunction) {
return IntegerAccess.of(host -> {
if (host == null) return -1;
val value = apply(host);
if (value == null) return -1;
val chr = chrFunction.applyAsInt(host);
return value.lastIndexOf(chr);
});
}
public default IntegerAccess lastIndexOf(int ch, int fromIndex) {
return intPrimitiveAccess(-1, str->str.lastIndexOf(ch, fromIndex));
}
public default IntegerAccess lastIndexOf(String needle) {
return IntegerAccess.of(host -> {
if (host == null) return -1;
val value = apply(host);
if (value == null) return -1;
return value.lastIndexOf(needle);
});
}
public default IntegerAccess lastIndexOf(Function needleFunction) {
return IntegerAccess.of(host -> {
if (host == null) return -1;
val value = apply(host);
if (value == null) return -1;
val needle = needleFunction.apply(host);
return value.lastIndexOf(needle);
});
}
public default IntegerAccess lastIndexOf(String needle, int fromIndex) {
return intPrimitiveAccess(-1, str->str.lastIndexOf(needle, fromIndex));
}
public default IntegerAccess length() {
return IntegerAccess.of(host -> {
if (host == null) return 0;
val value = apply(host);
if (value == null) return 0;
return value.length();
});
}
public default BooleanAccess thatMatches(String regex) {
return BooleanAccess.of(host -> {
if (host == null) return "".matches(regex);
val value = apply(host);
if (value == null) return "".matches(regex);
return value.matches(regex);
});
}
public default BooleanAccess thatMatches(Function regexFunction) {
return BooleanAccess.of(host -> {
val regex = regexFunction.apply(host);
if (host == null) return "".matches(regex);
val value = apply(host);
if (value == null) return "".matches(regex);
return value.matches(regex);
});
}
public default BooleanAccess thatMatchesIgnoreCase(String regex) {
return BooleanAccess.of(host -> {
val lowerCaseRegEx = regex.toLowerCase();
if (host == null) return "".matches(lowerCaseRegEx);
val value = apply(host);
if (value == null) return "".matches(lowerCaseRegEx);
return value.toLowerCase().matches(lowerCaseRegEx);
});
}
public default BooleanAccess thatMatchesIgnoreCase(Function regexFunction) {
return BooleanAccess.of(host -> {
val regex = regexFunction.apply(host);
val lowerCaseRegEx = regex.toLowerCase();
if (host == null) return "".matches(lowerCaseRegEx);
val value = apply(host);
if (value == null) return "".matches(lowerCaseRegEx);
return value.toLowerCase().matches(lowerCaseRegEx);
});
}
public default StringAccess replace(char oldChar, char newChar) {
return stringAccess(null, str->str.replace(oldChar, newChar));
}
public default StringAccess replace(CharSequence target, CharSequence replacement) {
return stringAccess(null, str->str.replace(target, replacement));
}
public default StringAccess replaceAll(String regEx, String replacement) {
return StringAccess.of(host -> {
if (host == null) return null;
val value = apply(host);
if (value == null) return null;
return value.replaceAll(regEx, replacement);
});
}
public default StringAccess replaceAll(Function regexFunction, Function replacementFunction) {
return StringAccess.of(host -> {
if (host == null) return null;
val value = apply(host);
if (value == null) return null;
val regex = regexFunction .apply(host);
val replacement = replacementFunction.apply(host);
return value.replaceAll(regex, replacement);
});
}
public default StringAccess replaceFirst(String regEx, String replacement) {
return StringAccess.of(host -> {
if (host == null) return null;
val value = apply(host);
if (value == null) return null;
return value.replaceFirst(regEx, replacement);
});
}
public default StringAccess replaceFirst(Function regexFunction, Function replacementFunction) {
return StringAccess.of(host -> {
if (host == null) return null;
val value = apply(host);
if (value == null) return null;
val regex = regexFunction .apply(host);
val replacement = replacementFunction.apply(host);
return value.replaceFirst(regex, replacement);
});
}
public default FuncListAccess> split(String regex) {
return FuncListAccess.of(host -> {
val strValue = StringAccess.this.apply(host);
return FuncList.from(strValue.split(regex));
}, func -> StringAccess.this.newAccess(func));
}
public default FuncListAccess> split(Function regexFunction) {
return FuncListAccess.of(host -> {
val strValue = StringAccess.this.apply(host);
val regex = regexFunction.apply(host);
return FuncList.from(strValue.split(regex));
}, func -> StringAccess.this.newAccess(func));
}
public default BooleanAccess thatStartsWith(String prefix) {
return BooleanAccess.of(host -> {
if (host == null) return false;
val value = apply(host);
if (value == null) return false;
return value.startsWith(prefix);
});
}
public default BooleanAccess thatStartsWith(Function prefixFunction) {
return BooleanAccess.of(host -> {
if (host == null) return false;
val value = apply(host);
if (value == null) return false;
val prefix = prefixFunction.apply(host);
return value.startsWith(prefix);
});
}
public default BooleanAccess thatStartsWith(String prefix, int offset) {
return booleanAccess(false, str->str.startsWith(prefix, offset));
}
public default StringAccess substring(int beginIndex) {
return StringAccess.of(host -> {
if (host == null) return null;
val value = apply(host);
if (value == null) return null;
return value.substring(beginIndex);
});
}
public default StringAccess substring(ToIntFunction beginIndexFunction) {
return StringAccess.of(host -> {
if (host == null) return null;
val value = apply(host);
if (value == null) return null;
val beginIndex = beginIndexFunction.applyAsInt(host);
return value.substring(beginIndex);
});
}
public default StringAccess substring(int beginIndex, int endIndex) {
return stringAccess(null, str->str.substring(beginIndex, endIndex));
}
public default StringAccess toLowerCase() {
return stringAccess(null, str->str.toLowerCase());
}
public default StringAccess toLowerCase(Locale locale) {
return stringAccess(null, str->str.toLowerCase(locale));
}
public default StringAccess toUpperCase() {
return stringAccess(null, str->str.toUpperCase());
}
public default StringAccess toUpperCase(Locale locale) {
return stringAccess(null, str->str.toUpperCase(locale));
}
public default StringAccess trim() {
return stringAccess(null, str->str.trim());
}
//== parse ==
//-- integer --
public default IntegerAccessPrimitive asInteger() {
return host -> {
val valueStr = apply(host);
return Integer.parseInt(valueStr);
};
}
public default IntegerAccessPrimitive asInteger(int radix) {
return host -> {
val valueStr = apply(host);
return Integer.parseInt(valueStr, radix);
};
}
public default ResultAccess> parseInteger() {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->Integer.parseInt(valueStr));
}, func -> (IntegerAccessBoxed)(func::apply));
}
public default ResultAccess> parseInteger(int radix) {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->Integer.parseInt(valueStr, radix));
}, func -> (IntegerAccessBoxed)(func::apply));
}
//-- long --
public default LongAccessPrimitive asLong() {
return host -> {
val valueStr = apply(host);
return Long.parseLong(valueStr);
};
}
public default LongAccessPrimitive asLong(int radix) {
return host -> {
val valueStr = apply(host);
return Long.parseLong(valueStr, radix);
};
}
public default ResultAccess> parseLong() {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->Long.parseLong(valueStr));
}, func -> (LongAccessBoxed)(func::apply));
}
public default ResultAccess> parseLong(int radix) {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->Long.parseLong(valueStr, radix));
}, func -> (LongAccessBoxed)(func::apply));
}
//-- double --
public default DoubleAccessPrimitive asDouble() {
return host -> {
val valueStr = apply(host);
return Double.parseDouble(valueStr);
};
}
public default ResultAccess> parseDouble() {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->Double.parseDouble(valueStr));
}, func -> (DoubleAccessBoxed)(func::apply));
}
//-- big integer --
public default BigIntegerAccess asBigInteger() {
return host -> {
val valueStr = apply(host);
return new BigInteger(valueStr);
};
}
public default ResultAccess> parseBigInteger() {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->new BigInteger(valueStr));
}, func -> (BigIntegerAccess)(func::apply));
}
//-- big decimal --
public default BigDecimalAccess asBigDecimal() {
return host -> {
val valueStr = apply(host);
return new BigDecimal(valueStr);
};
}
public default ResultAccess> parseBigDecimal() {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->new BigDecimal(valueStr));
}, func -> (BigDecimalAccess)(func::apply));
}
//-- local date --
public default LocalDateAccess asLocalDate() {
return host -> {
val valueStr = apply(host);
return LocalDate.parse(valueStr);
};
}
public default LocalDateAccess asLocalDate(DateTimeFormatter formatter) {
return host -> {
val valueStr = apply(host);
return LocalDate.parse(valueStr, formatter);
};
}
public default LocalDateAccess asLocalDate(String formatterPattern) {
val formatter = DateTimeFormatter.ofPattern(formatterPattern);
return asLocalDate(formatter);
}
public default ResultAccess> parseLocalDate() {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->LocalDate.parse(valueStr));
}, func -> (LocalDateAccess)(func::apply));
}
public default ResultAccess> parseLocalDate(DateTimeFormatter formatter) {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->LocalDate.parse(valueStr, formatter));
}, func -> (LocalDateAccess)(func::apply));
}
public default ResultAccess> parseLocalDate(String formatterPattern) {
val formatter = DateTimeFormatter.ofPattern(formatterPattern);
return parseLocalDate(formatter);
}
//-- local date time --
public default LocalDateTimeAccess asLocalDateTime() {
return host -> {
val valueStr = apply(host);
return LocalDateTime.parse(valueStr);
};
}
public default LocalDateTimeAccess asLocalDateTime(DateTimeFormatter formatter) {
return host -> {
val valueStr = apply(host);
return LocalDateTime.parse(valueStr, formatter);
};
}
public default LocalDateTimeAccess asLocalDateTime(String formatterPattern) {
val formatter = DateTimeFormatter.ofPattern(formatterPattern);
return asLocalDateTime(formatter);
}
public default ResultAccess> parseLocalDateTime() {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->LocalDateTime.parse(valueStr));
}, func -> (LocalDateTimeAccess)(func::apply));
}
public default ResultAccess> parseLocalDateTime(DateTimeFormatter formatter) {
return ResultAccess.of(host -> {
val valueStr = apply(host);
return Result.from(()->LocalDateTime.parse(valueStr, formatter));
}, func -> (LocalDateTimeAccess)(func::apply));
}
public default ResultAccess> parseLocalDateTime(String formatterPattern) {
val formatter = DateTimeFormatter.ofPattern(formatterPattern);
return parseLocalDateTime(formatter);
}
//-- TODO Add Zoned date and stuff.
}