io.virtdata.libbasics.shared.from_long.to_string.Template Maven / Gradle / Ivy
package io.virtdata.libbasics.shared.from_long.to_string;
import io.virtdata.annotations.Example;
import io.virtdata.annotations.ThreadSafeMapper;
import java.util.ArrayList;
import java.util.List;
import java.util.function.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Creates a template function which will yield a string which fits the template
* provided, with all occurrences of {}
substituted pair-wise with the
* result of the provided functions. The number of {}
entries in the template
* must strictly match the number of functions or an error will be thrown.
*
* To provide differing values for similarly defined functions in the list, the input
* value used is automatically incremented by one for each function, starting with
* the initial input value.
*/
@ThreadSafeMapper
public class Template implements LongFunction {
private static final String EXPR_BEGIN = "[[";
private static final String EXPR_END = "]]";
private final static ThreadLocal sb = ThreadLocal.withInitial(StringBuilder::new);
private final String rawTemplate;
private LongUnaryOperator iterOp;
private String[] literals;
private LongFunction>[] adaptedFuncs;
@Example({"Template('{}-{}',Add(10),Hash())","concatenate input+10, '-', and a pseudo-random long"})
public Template(String template, LongFunction>... funcs) {
this.adaptedFuncs = funcs;
this.rawTemplate = template;
this.literals = parseTemplate(template, funcs);
}
public Template(String template, Function... funcs) {
this.adaptedFuncs = new LongFunction[funcs.length];
for (int i = 0; i < funcs.length; i++) {
int finalI = i;
adaptedFuncs[i]=(l) -> funcs[finalI].apply(l);
}
this.rawTemplate = template;
this.literals = parseTemplate(template,adaptedFuncs);
}
public Template(String template, LongUnaryOperator... funcs) {
this.adaptedFuncs = new LongFunction[funcs.length];
for (int i = 0; i < funcs.length; i++) {
int finalI = i;
adaptedFuncs[i]=(l) -> funcs[finalI].applyAsLong(l);
}
this.rawTemplate = template;
this.literals = parseTemplate(template,adaptedFuncs);
}
public Template(String template, IntUnaryOperator... funcs) {
this.adaptedFuncs = new LongFunction[funcs.length];
for (int i = 0; i < funcs.length; i++) {
int finalI = i;
adaptedFuncs[i]=(l) -> funcs[finalI].applyAsInt(Long.valueOf(l).intValue());
}
this.rawTemplate = template;
this.literals = parseTemplate(template,adaptedFuncs);
}
public Template(String template, DoubleUnaryOperator... funcs) {
this.adaptedFuncs = new LongFunction[funcs.length];
for (int i = 0; i < funcs.length; i++) {
int finalI = i;
adaptedFuncs[i]=(l) -> funcs[finalI].applyAsDouble(l);
}
this.rawTemplate = template;
this.literals = parseTemplate(template,adaptedFuncs);
}
public Template(String template, LongToDoubleFunction... funcs) {
this.adaptedFuncs = new LongFunction[funcs.length];
for (int i = 0; i < funcs.length; i++) {
int finalI = i;
adaptedFuncs[i]=(l) -> funcs[finalI].applyAsDouble(l);
}
this.rawTemplate = template;
this.literals = parseTemplate(template,adaptedFuncs);
}
public Template(String template, LongToIntFunction... funcs) {
this.adaptedFuncs = new LongFunction[funcs.length];
for (int i = 0; i < funcs.length; i++) {
int finalI = i;
adaptedFuncs[i]=(l) -> funcs[finalI].applyAsInt(l);
}
this.rawTemplate = template;
this.literals = parseTemplate(template,adaptedFuncs);
}
/**
* If an operator is provided, it is used to change the function input value in an additional way before each function.
*
* @param iterOp A pre-generation value mapping function
* @param template A string template containing {}
anchors
* @param funcs A varargs length of LongFunctions of any output type
*/
public Template(LongUnaryOperator iterOp, String template, LongFunction>... funcs) {
this(template, funcs);
this.iterOp = iterOp;
}
@SuppressWarnings("unchecked")
private String[] parseTemplate(String template, LongFunction>... funcs) {
try {
List literals = new ArrayList<>();
Pattern p = Pattern.compile("\\{}");
Matcher m = p.matcher(template);
int pos = 0;
while (m.find()) {
literals.add(template.substring(pos, m.start()));
pos = m.end();
}
literals.add(template.substring(pos));
if (literals.size() != funcs.length + 1) {
throw new RuntimeException("The number of {} place holders in '" + template + "' should equal the number of functions.");
}
return literals.toArray(new String[0]);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public String apply(long value) {
StringBuilder buffer = sb.get();
buffer.setLength(0);
buffer.append(literals[0]);
if (literals.length > 1) {
for (int i = 0; i < adaptedFuncs.length; i++) {
long input = iterOp != null ? iterOp.applyAsLong(value + i) : value + i;
String genString = String.valueOf(adaptedFuncs[i].apply(input));
buffer.append(genString);
buffer.append(literals[i + 1]);
}
}
return buffer.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy