Java-custom placeholder replacement tool class

Java-custom placeholder replacement tool class

MessageFormat: Provides a way to generate concatenated messages in a language-neutral way. Use it to construct messages that are displayed to the end user.
Matcher: Matcher parser performs matching operations on character sequences based on Pattern regular expressions.
Implementation code
maven dependencies

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

Tools

package com.tangsm.util;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Custom placeholder replacement tool class
 *
 * @author tangyb
 */
public class PlaceholderUtils {<!-- -->

    /**
     * Placeholder regular expression: $ + curly braces
     * <p>Placeholder example: {<!-- -->@code ${<!-- -->xxx}}</p>
     */
    public static final Pattern PATTERN_BRACE = Pattern.compile("\$\{(.*?)}");

    /**
     * Placeholder regular expression: $ + angle brackets
     * <p>Placeholder example: {<!-- -->@code $<xxx>}</p>
     */
    public static final Pattern PATTERN_ANGLE = Pattern.compile("\$<(.*?)>");

    /**
     * matcher
     */
    private static Matcher matcher;

    /**
     * Replace string placeholders, variable parameters, and use the order {<!-- -->0}{<!-- -->1}...{<!-- -->*} in the string subscript, indicating placeholder
     *
     * @param source The string to be matched, example: "Name: {0}, Age: {1}, School: {2}"
     * @param params variable parameters, dynamic parameters
     * @return replaced string
     */
    public static String replaceWithVarargs(String source, Object... params) {<!-- -->
        return MessageFormat.format(source, params);
    }

    /**
     * Replace string placeholders, Map parameters, use ${<!-- -->key} in strings to represent placeholders
     *
     * @param source The string to be matched, example: "Name: ${name}, age: ${age}, school: ${school}"
     * @param params parameter set, Map type
     * @return the replaced string
     */
    public static String replaceWithMap(String source, Map<String, Object> params) {<!-- -->
        if (StringUtils.isBlank(source) || CollectionUtils.isEmpty(params)) {<!-- -->
            return source;
        }
        String targetString = source;
        matcher = PATTERN_BRACE.matcher(source);
        while (matcher.find()) {<!-- -->
            try {<!-- -->
                String key = matcher.group();
                //If the placeholder is {<!-- -->} here is key.substring(1, key.length() - 1).trim()
                String keyClone = key.substring(2, key.length() - 1).trim();
                Object value = params.get(keyClone);
                if (value != null) {<!-- -->
                    targetString = targetString.replace(key, value.toString());
                }
            } catch (Exception e) {<!-- -->
                throw new RuntimeException("String formatter failed", e);
            }
        }
        return targetString;
    }

    /**
     * Replace the string placeholder, POJO pass parameters, use ${<!-- -->key} in the string to represent the placeholder
     *
     * <p>Note: Use reflection to automatically obtain object property values (must have a get method)</p>
     *
     * @param source The string to be matched
     * @param params parameter entity
     * @return the replaced string
     */
    public static String replaceWithObject(String source, Object params) {<!-- -->
        if (StringUtils.isBlank(source) || ObjectUtils.isEmpty(params)) {<!-- -->
            return source;
        }

        String targetString = source;

        PropertyDescriptor pd;
        Method getMethod;

        // Match the content in ${<!-- -->} including parentheses
        matcher = PATTERN_BRACE.matcher(source);
        while (matcher.find()) {<!-- -->
            String key = matcher.group();
            String holderName = key.substring(2, key.length() - 1).trim();
            try {<!-- -->
                pd = new PropertyDescriptor(holderName, params. getClass());
                // Get the get method
                getMethod = pd.getReadMethod();
                Object value = getMethod.invoke(params);
                if (value != null) {<!-- -->
                    targetString = targetString.replace(key, value.toString());
                }
            } catch (Exception e) {<!-- -->
                throw new RuntimeException("String formatter failed", e);
            }
        }
        return targetString;
    }

    /**
     * Get the placeholder keys in String
     * <p>Example: name: ${<!-- -->name}, age: ${<!-- -->age}, school: ${<!-- -->school}, return: Set[name, age, school]</p>
     *
     * @param source source string
     * @param pattern regular expression, pattern example: <pre> {<!-- -->@code
     * // Angle brackets: <placeHolder> is represented as a placeholder
     * Pattern pattern = Pattern.compile("\$<(.*?)>");
     *
     * // Braces: {<!-- -->placeHolder} is represented as a placeholder, and {<!-- -->} is used as a placeholder in the above example
     * Pattern pattern = Pattern.compile("\$\{(.*?)}");
     * } 

* @return Set collection
*/
public static Set getPlaceholderKeys(String source, Pattern pattern) {
Set placeHolderSet = new HashSet<>();

// If the parameters are incorrect, an empty collection will be returned.
if (StringUtils.isBlank(source) || ObjectUtils.isEmpty(pattern)) {
return placeHolderSet;
}

// Initial matcher based on regular expression
matcher = pattern.matcher(source);
while (matcher.find()) {
//Example: {name}
String key = matcher.group();
//Example: name
String placeHolder = key.substring(2, key.length() – 1).trim();
placeHolderSet.add(placeHolder);
}

return placeHolderSet;
}
}

entity
package com.tangsm.domain;

/**
* User Info
*
* @author tangsm
*/
public class UserInfo {
/**
* Name
*/
private String name;

/**
* age
*/
private Integer age;

/**
* School
*/
private String school;

/**
* No parameter construction
*/
public UserInfo() {
}

/**
* Full parameter structure
*
* @param name name
* @param age age
* @param school school
*/
public UserInfo(String name, Integer age, String school) {
this.name = name;
this.age = age;
this.school = school;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public String getSchool() {
return to school;
}

public void setSchool(String school) {
this.school = school;
}
}

test class
package com.tangsm.util;

import com.tangsm.domain.UserInfo;
import com.tangsm.util.PlaceholderUtils;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;

/**
* Custom placeholder replacement tool class test class
*
* @author tangsm
*/
public class PlaceholderUtilsTest {
private final Logger log = LoggerFactory. getLogger(PlaceholderUtilsTest. class);

private static final String SOURCE0 = “Name: {0}, Age: {1}, School: {2}”;
private static final String SOURCE1 = “Name: ${name}, age: ${age}, school: ${school}”;
private static final String SOURCE2 = “Name: $, age: $, school: $“;

/**
* Replace string placeholders, dynamic parameters, use {0}{1}…{*} order in the string mark, indicating placeholder, test method
*/
@Test
void replaceWithVarargs() {
log.info(“replaceWithVarargs, processing result: {}”, PlaceholderUtils.replaceWithVarargs(SOURCE0, “Xiaomei”, 18, “Female High School”));
}

/**
* Replace string placeholders, map parameters, use ${key} in strings to represent placeholders, test methods
*/
@Test
void replaceWithMap() {
HashMap params = new HashMap<>();
params.put(“name”, “Xiaomei”);
params.put(“age”, 18);
params.put(“school”, “Female Senior High School”);
log.info(“replaceWithMap, processing result: {}”, PlaceholderUtils.replaceWithMap(SOURCE1, params));
}

/**
* Replace the string placeholder, POJO parameter passing, use ${key} in the string to represent the placeholder, test method
*/
@Test
void replaceWithObject() {
UserInfo userInfo = new UserInfo(“Xiaomei”, 18, “Female High School No. 1”);
log.info(“replaceWithObject, processing result: {}”, PlaceholderUtils.replaceWithObject(SOURCE1, userInfo));
}

/**
* Get the placeholder keys in String
*/
@Test
void getPlaceholderKeys() {
log.info(“getPlaceholderKeys-PATTERN_BRACE, processing result: {}”, PlaceholderUtils.getPlaceholderKeys(SOURCE1, PlaceholderUtils.PATTERN_BRACE));
log.info(“getPlaceholderKeys-PATTERN_ANGLE, processing result: {}”, PlaceholderUtils.getPlaceholderKeys(SOURCE2, PlaceholderUtils.PATTERN_ANGLE));
}
}

Test Results
PlaceholderUtilsTest – replaceWithObject, processing results: Name: Xiaomei, Age: 18, School: Girls’ High School No. 1
PlaceholderUtilsTest – getPlaceholderKeys-PATTERN_BRACE, processing result: [school, name, age]
PlaceholderUtilsTest – getPlaceholderKeys-PATTERN_ANGLE, processing result: [school, name, age]
PlaceholderUtilsTest – replaceWithVarargs, processing results: Name: Xiaomei, Age: 18, School: Girls’ High School No. 1
PlaceholderUtilsTest – replaceWithMap, processing results: Name: Xiaomei, Age: 18, School: Girls’ High School No. 1