All Downloads are FREE. Search and download functionalities are using the official Maven repository.
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.
pl.fhframework.binding.AdHocIndexedModelBinding Maven / Gradle / Ivy
package pl.fhframework.binding;
import com.fasterxml.jackson.annotation.JsonIgnoreType;
import lombok.Getter;
import pl.fhframework.core.forms.iterators.IIndexedBindingOwner;
import pl.fhframework.core.forms.iterators.IRepeatableIteratorInfo;
import pl.fhframework.core.util.StringUtils;
import pl.fhframework.BindingResult;
import pl.fhframework.model.forms.Component;
import pl.fhframework.model.forms.Form;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Ad-hoc indexed model binding.
*/
@JsonIgnoreType
@Getter
public class AdHocIndexedModelBinding extends IndexedModelBinding {
private static final String TMP_INDEX_MARKER = "Z_________Z"; // cheap hack, but works
private String indexedBindingTemplate;
private IIndexedBindingOwner indexedBindingOwner;
private Form form;
public AdHocIndexedModelBinding(String bindingExpression, IIndexedBindingOwner indexedBindingOwner, Form form) {
super(bindingExpression);
this.indexedBindingOwner = indexedBindingOwner;
this.form = form;
}
@Override
public T getValue(int[] indices) {
if (getBindingExpression() != null && indexedBindingTemplate == null) {
Map replacementTemplates = buildIteratorReplacementTemplates(getIndexedBindingOwner().getIteratorInfos());
indexedBindingTemplate = replaceIteratorsInBinding(getBindingExpression(), replacementTemplates, true);
}
if (indexedBindingTemplate != null) {
BindingResult bindingResult = form.getBindingResult(
fillIteratorReplacementTemplate(indexedBindingTemplate, indices),
(Component) indexedBindingOwner);
if (bindingResult != null) {
return (T) bindingResult.getValue();
}
}
return null;
}
/**
* Creates iterator replacement templates for later filling.
* May be used in two ways:
* To replace given indices in many bindings: 1 x create replacement templates, 1 x fill templates with indices, n x replace in bindings.
* To prepare re-fillable single binding template: 1 x create replacement templates, 1 x replace in binding, n x fill binding with indices.
* @param currentIterators iterators
* @return map iterator name -> replacement template
*/
public static Map buildIteratorReplacementTemplates(List currentIterators) {
Map replacementMap = new LinkedHashMap<>();
for (IRepeatableIteratorInfo currentIterator : currentIterators) {
AtomicReference currentBinding = new AtomicReference<>(StringUtils.removeSurroundingBraces(currentIterator.getCollectionBinding())
+ "[" + TMP_INDEX_MARKER + replacementMap.size() + TMP_INDEX_MARKER + "]");
replacementMap.forEach((parentIter, replacement) -> {
// will match {iterator}, {iterator.prop}, {method(iterator)}, {method(iterator.prop)}, {method(iterator).prop}, {method(iterator[4])} and more
Pattern pattern = Pattern.compile("^(.*[\\(\\{\\s\\,])?(" + Matcher.quoteReplacement(parentIter) + ")([\\,\\s\\}\\)\\.\\[].*)$");
int counter = 0;
do {
Matcher bindingMatcher = pattern.matcher(currentBinding.get());
if (bindingMatcher.find()) {
// replace iterator to its replacement eg. iter => col[Z_________Z3Z_________Z]
// where Z_________Z3Z_________Z is temporaty holder of an index of 4th iterator (index is 0 based)
String prefix = StringUtils.nullToEmpty(bindingMatcher.group(1));
String suffix = StringUtils.nullToEmpty(bindingMatcher.group(3));
currentBinding.set(prefix + replacement + suffix);
} else {
break; // no more occurrences of iterator
}
} while (counter++ < 20); // infinite loop protection
});
replacementMap.put(currentIterator.getName(), currentBinding.get());
}
return replacementMap;
}
/**
* Fills template with given iterator indices.
* @param template template
* @param indices indices
* @return filled template
*/
public static String fillIteratorReplacementTemplate(String template, int[] indices) {
String replacement = template;
for (int i = 0; i < indices.length; i++) {
replacement = replacement.replace(TMP_INDEX_MARKER + i + TMP_INDEX_MARKER, String.valueOf(indices[i]));
}
return replacement;
}
/**
* Fills templates with given iterator indices.
* @param templates iterator template map
* @param indices indices
* @return filled iterator template map
*/
public static Map fillIteratorReplacementTemplates(Map templates, int[] indices) {
Map result = new LinkedHashMap<>();
templates.forEach((iter, template) -> {
result.put(iter, fillIteratorReplacementTemplate(template, indices));
});
return result;
}
/**
* Replaces iterators in binding with provided replacements.
* @param binding binding
* @param iteratorReplacements iterator replacement map (iterator name -> replacement)
* @param useCurlyBrackets if binding is using curly brackets
* @return replaces binding
*/
public static String replaceIteratorsInBinding(String binding, Map iteratorReplacements, boolean useCurlyBrackets) {
if (binding == null) {
return null;
}
if (!useCurlyBrackets || (binding.contains("{") && binding.contains("}"))) {
for (Map.Entry iteratorEntry : iteratorReplacements.entrySet()) {
String iteratorId = iteratorEntry.getKey();
String iteratorReplacement = iteratorEntry.getValue();
// will match {iterator}, {iterator.prop}, {method(iterator)}, {method(iterator.prop)}, {method(iterator).prop}, {method(iterator[4])} and more
Pattern pattern = Pattern.compile("^(.*[\\(\\{\\s\\,])?(" + Matcher.quoteReplacement(iteratorId) + ")([\\,\\s\\}\\)\\.\\[].*)$");
int counter = 0;
do {
Matcher bindingMatcher = pattern.matcher(binding);
if (bindingMatcher.find()) {
binding = bindingMatcher.group(1) + iteratorReplacement + bindingMatcher.group(3);
} else {
break; // no more occurrences of iterator
}
} while (counter++ < 20); // infinite loop protection
}
if (!useCurlyBrackets) {
binding = StringUtils.removeSurroundingBraces(binding);
}
return binding;
} else {
return binding;
}
}
}