1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.migration;
17
18 import java.util.Arrays;
19 import java.util.Collections;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Objects;
23 import java.util.stream.Collectors;
24
25
26
27
28 public class VariableReplacer {
29
30 private static final String OPEN_TOKEN = "${";
31 private static final String CLOSE_TOKEN = "}";
32 private final List<Map<? extends Object, ? extends Object>> variablesList;
33
34 public VariableReplacer(Map<? extends Object, ? extends Object> variablesList) {
35 this(Arrays.asList(variablesList));
36 }
37
38 public VariableReplacer(List<Map<? extends Object, ? extends Object>> variablesList) {
39 this.variablesList = variablesList == null ? Collections.emptyList()
40 : variablesList.stream().filter(Objects::nonNull).collect(Collectors.toList());
41 }
42
43 public String replace(String text) {
44 if (text == null || text.isEmpty()) {
45 return "";
46 }
47
48 int start = text.indexOf(OPEN_TOKEN);
49 if (start == -1) {
50 return text;
51 }
52 char[] src = text.toCharArray();
53 int offset = 0;
54 final StringBuilder builder = new StringBuilder();
55 StringBuilder expression = null;
56 while (start > -1) {
57 if (start > 0 && src[start - 1] == '\\') {
58
59 builder.append(src, offset, start - offset - 1).append(OPEN_TOKEN);
60 offset = start + OPEN_TOKEN.length();
61 } else {
62
63 if (expression == null) {
64 expression = new StringBuilder();
65 } else {
66 expression.setLength(0);
67 }
68 builder.append(src, offset, start - offset);
69 offset = start + OPEN_TOKEN.length();
70 int end = text.indexOf(CLOSE_TOKEN, offset);
71 while (end > -1) {
72 if (end <= offset || src[end - 1] != '\\') {
73 expression.append(src, offset, end - offset);
74 break;
75 }
76
77 expression.append(src, offset, end - offset - 1).append(CLOSE_TOKEN);
78 offset = end + CLOSE_TOKEN.length();
79 end = text.indexOf(CLOSE_TOKEN, offset);
80 }
81 if (end == -1) {
82
83 builder.append(src, start, src.length - start);
84 offset = src.length;
85 } else {
86 appendWithReplace(builder, expression.toString());
87 offset = end + CLOSE_TOKEN.length();
88 }
89 }
90 start = text.indexOf(OPEN_TOKEN, offset);
91 }
92 if (offset < src.length) {
93 builder.append(src, offset, src.length - offset);
94 }
95 return builder.toString();
96 }
97
98 private StringBuilder appendWithReplace(StringBuilder builder, String key) {
99 String value = null;
100 for (Map<? extends Object, ? extends Object> variables : variablesList) {
101 value = (String) variables.get(key);
102 if (value != null) {
103 builder.append(value);
104 break;
105 }
106 }
107 if (value == null) {
108 builder.append(OPEN_TOKEN).append(key).append(CLOSE_TOKEN);
109 }
110 return builder;
111 }
112 }