All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.ultreia.java4all.validation.spi.field.generator.ExpressionResolver Maven / Gradle / Ivy

The newest version!
package io.ultreia.java4all.validation.spi.field.generator;

/*-
 * #%L
 * Validation :: SPI
 * %%
 * Copyright (C) 2021 - 2024 Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static io.ultreia.java4all.validation.spi.field.generator.FieldValidationGenerator.doCast;
import static io.ultreia.java4all.validation.spi.field.generator.FieldValidationGenerator.escapeString;
import static io.ultreia.java4all.validation.spi.field.generator.FieldValidationGenerator.guessGetter;
import static io.ultreia.java4all.validation.spi.field.generator.FieldValidationGenerator.guessGetterName;

/**
 * Object that can transform an expression to a java code.
 * 

* Created at 02/02/2024. * * @author Tony Chemit - [email protected] * @since 2.0.0 */ public class ExpressionResolver { private static final Logger log = LogManager.getLogger(ExpressionResolver.class); private final List config; public ExpressionResolver(List config) { this.config = config; } public static ExpressionResolver of(Config... config) { return new ExpressionResolver(List.of(config)); } public String resolve(String expression) throws NoSuchMethodException { String result = expression; for (Config config : this.config) { result = resolve(result, config); } return result; } private String resolve(String result, Config config) throws NoSuchMethodException { String variablePrefix = config.getVariablePrefix(); String variableName = config.getVariableName(); Class variableType = config.getVariableType(); boolean needCast = config.isNeedCast(); return resolve(result, variablePrefix, variableName, variableType, needCast); } public String resolve(String expression, String variablePrefix, String variableName, Class variableType, boolean needCast) throws NoSuchMethodException { log.info("Resolving '{}' (using '{}' → '{}' : {})", expression, variablePrefix, variableName, variableType.getName()); int lastIndex = 0; int index = expression.indexOf(variablePrefix); List parts = new ArrayList<>(); while (index != -1) { String variableExpression = expression.substring(lastIndex, index); log.info(">> next token '{}'", variableExpression); String resolvedExpression = resolveExpression(variableExpression, variablePrefix, variableName, variableType, needCast); log.info("<< next token '{}' → '{}'", variableExpression, resolvedExpression); parts.add(resolvedExpression); lastIndex = index; index = expression.indexOf(variablePrefix, lastIndex + 1); } String variableExpression = expression.substring(lastIndex); log.info(">> last token '{}'", variableExpression); String resolvedExpression = resolveExpression(variableExpression, variablePrefix, variableName, variableType, needCast); log.info("<< last token '{}' → '{}'", variableExpression, resolvedExpression); parts.add(resolvedExpression); String result = String.join("", parts); log.info("Resolved '{}' to '{}' (using '{}' → '{}' : {})", expression, result, variablePrefix, variableName, variableType.getName()); return result; } protected String resolveExpression(String variableExpression, String variablePrefix, String variableName, Class variableType, boolean needCast) throws NoSuchMethodException { if (!variableExpression.startsWith(variablePrefix)) { // No variable here return variableExpression; } variableExpression = variableExpression.substring(variablePrefix.length() + 1); StringBuilder result = new StringBuilder(needCast ? doCast(variableType, variableName) : variableName); String resultEnd = ""; int index; if ((index = variableExpression.indexOf(' ')) > -1) { resultEnd = variableExpression.substring(index); variableExpression = variableExpression.substring(0, index); } if ((index = variableExpression.indexOf(',')) > -1) { resultEnd = variableExpression.substring(index) + resultEnd; variableExpression = variableExpression.substring(0, index); } if ((index = variableExpression.indexOf(')')) > -1) { resultEnd = variableExpression.substring(index) + resultEnd; variableExpression = variableExpression.substring(0, index); } String[] nestedParts = variableExpression.split("\\."); if (nestedParts.length == 1) { // no nested if (nestedParts[0].contains("(")) { // not a getter result.append('.').append(nestedParts[0]); return result + resultEnd; } if (Map.class.isAssignableFrom(variableType)) { return String.format("%s.get(%s)%s", result, escapeString(nestedParts[0]), resultEnd); } else { String getterName = guessGetterName(variableType, nestedParts[0]); return String.format("%s.%s()%s", result, getterName, resultEnd); } } Class type = variableType; for (String nestedPart : nestedParts) { if (nestedPart.contains("(")) { // not a getter result.append('.').append(nestedPart); continue; } if (Map.class.isAssignableFrom(type)) { type = (Class) type.getTypeParameters()[1].getBounds()[0]; result.append(String.format(".get(%s)", escapeString(nestedPart))); } else { Method method = guessGetter(type, nestedPart); type = method.getReturnType(); result.append(String.format(".%s()", method.getName())); } } result.append(resultEnd); return result.toString(); } public static class Config { private final String variablePrefix; private final String variableName; private final Class variableType; private final boolean needCast; public Config(String variablePrefix, String variableName, Class variableType, boolean needCast) { this.variablePrefix = variablePrefix; this.variableName = variableName; this.variableType = variableType; this.needCast = needCast; } public String getVariablePrefix() { return variablePrefix; } public String getVariableName() { return variableName; } public Class getVariableType() { return variableType; } public boolean isNeedCast() { return needCast; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy