1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.lang3.text;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertFalse;
22 import static org.junit.jupiter.api.Assertions.assertNull;
23 import static org.junit.jupiter.api.Assertions.assertSame;
24 import static org.junit.jupiter.api.Assertions.assertThrows;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
26
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.Properties;
30
31 import org.apache.commons.lang3.AbstractLangTest;
32 import org.apache.commons.lang3.mutable.MutableObject;
33 import org.junit.jupiter.api.AfterEach;
34 import org.junit.jupiter.api.BeforeEach;
35 import org.junit.jupiter.api.Test;
36
37
38
39
40 @Deprecated
41 public class StrSubstitutorTest extends AbstractLangTest {
42
43 private Map<String, String> values;
44
45 private void doTestNoReplace(final String replaceTemplate) {
46 final StrSubstitutor sub = new StrSubstitutor(values);
47
48 if (replaceTemplate == null) {
49 assertNull(sub.replace((String) null));
50 assertNull(sub.replace((String) null, 0, 100));
51 assertNull(sub.replace((char[]) null));
52 assertNull(sub.replace((char[]) null, 0, 100));
53 assertNull(sub.replace((StringBuffer) null));
54 assertNull(sub.replace((StringBuffer) null, 0, 100));
55 assertNull(sub.replace((StrBuilder) null));
56 assertNull(sub.replace((StrBuilder) null, 0, 100));
57 assertNull(sub.replace((Object) null));
58 assertFalse(sub.replaceIn((StringBuffer) null));
59 assertFalse(sub.replaceIn((StringBuffer) null, 0, 100));
60 assertFalse(sub.replaceIn((StrBuilder) null));
61 assertFalse(sub.replaceIn((StrBuilder) null, 0, 100));
62 } else {
63 assertEquals(replaceTemplate, sub.replace(replaceTemplate));
64 final StrBuilder bld = new StrBuilder(replaceTemplate);
65 assertFalse(sub.replaceIn(bld));
66 assertEquals(replaceTemplate, bld.toString());
67 }
68 }
69
70 private void doTestReplace(final String expectedResult, final String replaceTemplate, final boolean substring) {
71 final String expectedShortResult = expectedResult.substring(1, expectedResult.length() - 1);
72 final StrSubstitutor sub = new StrSubstitutor(values);
73
74
75 assertEquals(expectedResult, sub.replace(replaceTemplate));
76 if (substring) {
77 assertEquals(expectedShortResult, sub.replace(replaceTemplate, 1, replaceTemplate.length() - 2));
78 }
79
80
81 final char[] chars = replaceTemplate.toCharArray();
82 assertEquals(expectedResult, sub.replace(chars));
83 if (substring) {
84 assertEquals(expectedShortResult, sub.replace(chars, 1, chars.length - 2));
85 }
86
87
88 StringBuffer buf = new StringBuffer(replaceTemplate);
89 assertEquals(expectedResult, sub.replace(buf));
90 if (substring) {
91 assertEquals(expectedShortResult, sub.replace(buf, 1, buf.length() - 2));
92 }
93
94
95 StringBuilder builder = new StringBuilder(replaceTemplate);
96 assertEquals(expectedResult, sub.replace(builder));
97 if (substring) {
98 assertEquals(expectedShortResult, sub.replace(builder, 1, builder.length() - 2));
99 }
100
101
102 StrBuilder bld = new StrBuilder(replaceTemplate);
103 assertEquals(expectedResult, sub.replace(bld));
104 if (substring) {
105 assertEquals(expectedShortResult, sub.replace(bld, 1, bld.length() - 2));
106 }
107
108
109 final MutableObject<String> obj = new MutableObject<>(replaceTemplate);
110 assertEquals(expectedResult, sub.replace(obj));
111
112
113 buf = new StringBuffer(replaceTemplate);
114 assertTrue(sub.replaceIn(buf));
115 assertEquals(expectedResult, buf.toString());
116 if (substring) {
117 buf = new StringBuffer(replaceTemplate);
118 assertTrue(sub.replaceIn(buf, 1, buf.length() - 2));
119 assertEquals(expectedResult, buf.toString());
120 }
121
122
123 builder = new StringBuilder(replaceTemplate);
124 assertTrue(sub.replaceIn(builder));
125 assertEquals(expectedResult, builder.toString());
126 if (substring) {
127 builder = new StringBuilder(replaceTemplate);
128 assertTrue(sub.replaceIn(builder, 1, builder.length() - 2));
129 assertEquals(expectedResult, builder.toString());
130 }
131
132
133 bld = new StrBuilder(replaceTemplate);
134 assertTrue(sub.replaceIn(bld));
135 assertEquals(expectedResult, bld.toString());
136 if (substring) {
137 bld = new StrBuilder(replaceTemplate);
138 assertTrue(sub.replaceIn(bld, 1, bld.length() - 2));
139 assertEquals(expectedResult, bld.toString());
140 }
141 }
142
143 @BeforeEach
144 public void setUp() {
145 values = new HashMap<>();
146 values.put("animal", "quick brown fox");
147 values.put("target", "lazy dog");
148 }
149
150 @AfterEach
151 public void tearDown() {
152 values = null;
153 }
154
155
156
157
158 @Test
159 public void testConstructorMapFull() {
160 final Map<String, String> map = new HashMap<>();
161 map.put("name", "commons");
162 StrSubstitutor sub = new StrSubstitutor(map, "<", ">", '!');
163 assertEquals("Hi < commons", sub.replace("Hi !< <name>"));
164 sub = new StrSubstitutor(map, "<", ">", '!', "||");
165 assertEquals("Hi < commons", sub.replace("Hi !< <name2||commons>"));
166 }
167
168
169
170
171 @Test
172 public void testConstructorMapPrefixSuffix() {
173 final Map<String, String> map = new HashMap<>();
174 map.put("name", "commons");
175 final StrSubstitutor sub = new StrSubstitutor(map, "<", ">");
176 assertEquals("Hi < commons", sub.replace("Hi $< <name>"));
177 }
178
179
180
181
182 @Test
183 public void testConstructorNoArgs() {
184 final StrSubstitutor sub = new StrSubstitutor();
185 assertEquals("Hi ${name}", sub.replace("Hi ${name}"));
186 }
187
188
189
190
191
192 @Test
193 public void testCyclicReplacement() {
194 final Map<String, String> map = new HashMap<>();
195 map.put("animal", "${critter}");
196 map.put("target", "${pet}");
197 map.put("pet", "${petCharacteristic} dog");
198 map.put("petCharacteristic", "lazy");
199 map.put("critter", "${critterSpeed} ${critterColor} ${critterType}");
200 map.put("critterSpeed", "quick");
201 map.put("critterColor", "brown");
202 map.put("critterType", "${animal}");
203 final StrSubstitutor sub = new StrSubstitutor(map);
204 assertThrows(
205 IllegalStateException.class,
206 () -> sub.replace("The ${animal} jumps over the ${target}."),
207 "Cyclic replacement was not detected!");
208
209
210 map.put("critterType", "${animal:-fox}");
211 final StrSubstitutor sub2 = new StrSubstitutor(map);
212 assertThrows(
213 IllegalStateException.class,
214 () -> sub2.replace("The ${animal} jumps over the ${target}."),
215 "Cyclic replacement was not detected!");
216 }
217
218 @Test
219 public void testDefaultValueDelimiters() {
220 final Map<String, String> map = new HashMap<>();
221 map.put("animal", "fox");
222 map.put("target", "dog");
223
224 StrSubstitutor sub = new StrSubstitutor(map, "${", "}", '$');
225 assertEquals("The fox jumps over the lazy dog. 1234567890.",
226 sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number:-1234567890}."));
227
228 sub = new StrSubstitutor(map, "${", "}", '$', "?:");
229 assertEquals("The fox jumps over the lazy dog. 1234567890.",
230 sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number?:1234567890}."));
231
232 sub = new StrSubstitutor(map, "${", "}", '$', "||");
233 assertEquals("The fox jumps over the lazy dog. 1234567890.",
234 sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number||1234567890}."));
235
236 sub = new StrSubstitutor(map, "${", "}", '$', "!");
237 assertEquals("The fox jumps over the lazy dog. 1234567890.",
238 sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number!1234567890}."));
239
240 sub = new StrSubstitutor(map, "${", "}", '$', "");
241 sub.setValueDelimiterMatcher(null);
242 assertEquals("The fox jumps over the lazy dog. ${undefined.number!1234567890}.",
243 sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number!1234567890}."));
244
245 sub = new StrSubstitutor(map, "${", "}", '$');
246 sub.setValueDelimiterMatcher(null);
247 assertEquals("The fox jumps over the lazy dog. ${undefined.number!1234567890}.",
248 sub.replace("The ${animal} jumps over the lazy ${target}. ${undefined.number!1234567890}."));
249 }
250
251
252
253
254 @Test
255 public void testGetSetEscape() {
256 final StrSubstitutor sub = new StrSubstitutor();
257 assertEquals('$', sub.getEscapeChar());
258 sub.setEscapeChar('<');
259 assertEquals('<', sub.getEscapeChar());
260 }
261
262
263
264
265 @Test
266 public void testGetSetPrefix() {
267 final StrSubstitutor sub = new StrSubstitutor();
268 assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.StringMatcher);
269 sub.setVariablePrefix('<');
270 assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.CharMatcher);
271
272 sub.setVariablePrefix("<<");
273 assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.StringMatcher);
274 assertThrows(NullPointerException.class, () -> sub.setVariablePrefix(null));
275 assertTrue(sub.getVariablePrefixMatcher() instanceof StrMatcher.StringMatcher);
276
277 final StrMatcher matcher = StrMatcher.commaMatcher();
278 sub.setVariablePrefixMatcher(matcher);
279 assertSame(matcher, sub.getVariablePrefixMatcher());
280 assertThrows(NullPointerException.class, () -> sub.setVariablePrefixMatcher(null));
281 assertSame(matcher, sub.getVariablePrefixMatcher());
282 }
283
284
285
286
287 @Test
288 public void testGetSetSuffix() {
289 final StrSubstitutor sub = new StrSubstitutor();
290 assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.StringMatcher);
291 sub.setVariableSuffix('<');
292 assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.CharMatcher);
293
294 sub.setVariableSuffix("<<");
295 assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.StringMatcher);
296 assertThrows(NullPointerException.class, () -> sub.setVariableSuffix(null));
297 assertTrue(sub.getVariableSuffixMatcher() instanceof StrMatcher.StringMatcher);
298
299 final StrMatcher matcher = StrMatcher.commaMatcher();
300 sub.setVariableSuffixMatcher(matcher);
301 assertSame(matcher, sub.getVariableSuffixMatcher());
302 assertThrows(NullPointerException.class, () -> sub.setVariableSuffixMatcher(null));
303 assertSame(matcher, sub.getVariableSuffixMatcher());
304 }
305
306
307
308
309 @Test
310 public void testGetSetValueDelimiter() {
311 final StrSubstitutor sub = new StrSubstitutor();
312 assertTrue(sub.getValueDelimiterMatcher() instanceof StrMatcher.StringMatcher);
313 sub.setValueDelimiter(':');
314 assertTrue(sub.getValueDelimiterMatcher() instanceof StrMatcher.CharMatcher);
315
316 sub.setValueDelimiter("||");
317 assertTrue(sub.getValueDelimiterMatcher() instanceof StrMatcher.StringMatcher);
318 sub.setValueDelimiter(null);
319 assertNull(sub.getValueDelimiterMatcher());
320
321 final StrMatcher matcher = StrMatcher.commaMatcher();
322 sub.setValueDelimiterMatcher(matcher);
323 assertSame(matcher, sub.getValueDelimiterMatcher());
324 sub.setValueDelimiterMatcher(null);
325 assertNull(sub.getValueDelimiterMatcher());
326 }
327
328
329
330
331 @Test
332 public void testLANG1055() {
333 System.setProperty("test_key", "test_value");
334
335 final String expected = StrSubstitutor.replace("test_key=${test_key}", System.getProperties());
336 final String actual = StrSubstitutor.replaceSystemProperties("test_key=${test_key}");
337 assertEquals(expected, actual);
338 }
339
340
341
342
343 @Test
344 public void testReplaceAdjacentAtEnd() {
345 values.put("code", "GBP");
346 values.put("amount", "12.50");
347 final StrSubstitutor sub = new StrSubstitutor(values);
348 assertEquals("Amount is GBP12.50", sub.replace("Amount is ${code}${amount}"));
349 }
350
351
352
353
354 @Test
355 public void testReplaceAdjacentAtStart() {
356 values.put("code", "GBP");
357 values.put("amount", "12.50");
358 final StrSubstitutor sub = new StrSubstitutor(values);
359 assertEquals("GBP12.50 charged", sub.replace("${code}${amount} charged"));
360 }
361
362
363
364
365 @Test
366 public void testReplaceChangedMap() {
367 final StrSubstitutor sub = new StrSubstitutor(values);
368 values.put("target", "moon");
369 assertEquals("The quick brown fox jumps over the moon.", sub.replace("The ${animal} jumps over the ${target}."));
370 }
371
372
373
374
375 @Test
376 public void testReplaceComplexEscaping() {
377 doTestReplace("The ${quick brown fox} jumps over the lazy dog.", "The $${${animal}} jumps over the ${target}.", true);
378 doTestReplace("The ${quick brown fox} jumps over the lazy dog. ${1234567890}.", "The $${${animal}} jumps over the ${target}. $${${undefined.number:-1234567890}}.", true);
379 }
380
381
382
383
384 @Test
385 public void testReplaceEmpty() {
386 doTestNoReplace("");
387 }
388
389
390
391
392 @Test
393 public void testReplaceEmptyKeys() {
394 doTestReplace("The ${} jumps over the lazy dog.", "The ${} jumps over the ${target}.", true);
395 doTestReplace("The animal jumps over the lazy dog.", "The ${:-animal} jumps over the ${target}.", true);
396 }
397
398
399
400
401 @Test
402 public void testReplaceEscaping() {
403 doTestReplace("The ${animal} jumps over the lazy dog.", "The $${animal} jumps over the ${target}.", true);
404 }
405
406
407
408
409 @Test
410 public void testReplaceIncompletePrefix() {
411 doTestReplace("The {animal} jumps over the lazy dog.", "The {animal} jumps over the ${target}.", true);
412 }
413
414
415
416
417 @Test
418 public void testReplaceInVariable() {
419 values.put("animal.1", "fox");
420 values.put("animal.2", "mouse");
421 values.put("species", "2");
422 final StrSubstitutor sub = new StrSubstitutor(values);
423 sub.setEnableSubstitutionInVariables(true);
424 assertEquals(
425 "The mouse jumps over the lazy dog.",
426 sub.replace("The ${animal.${species}} jumps over the ${target}."),
427 "Wrong result (1)");
428 values.put("species", "1");
429 assertEquals(
430 "The fox jumps over the lazy dog.",
431 sub.replace("The ${animal.${species}} jumps over the ${target}."),
432 "Wrong result (2)");
433 assertEquals(
434 "The fox jumps over the lazy dog.",
435 sub.replace("The ${unknown.animal.${unknown.species:-1}:-fox} jumps over the ${unknown.target:-lazy dog}."),
436 "Wrong result (3)");
437 }
438
439
440
441
442 @Test
443 public void testReplaceInVariableDisabled() {
444 values.put("animal.1", "fox");
445 values.put("animal.2", "mouse");
446 values.put("species", "2");
447 final StrSubstitutor sub = new StrSubstitutor(values);
448 assertEquals(
449 "The ${animal.${species}} jumps over the lazy dog.",
450 sub.replace("The ${animal.${species}} jumps over the ${target}."),
451 "Wrong result (1)");
452 assertEquals(
453 "The ${animal.${species:-1}} jumps over the lazy dog.",
454 sub.replace("The ${animal.${species:-1}} jumps over the ${target}."),
455 "Wrong result (2)");
456 }
457
458
459
460
461 @Test
462 public void testReplaceInVariableRecursive() {
463 values.put("animal.2", "brown fox");
464 values.put("animal.1", "white mouse");
465 values.put("color", "white");
466 values.put("species.white", "1");
467 values.put("species.brown", "2");
468 final StrSubstitutor sub = new StrSubstitutor(values);
469 sub.setEnableSubstitutionInVariables(true);
470 assertEquals(
471 "The white mouse jumps over the lazy dog.",
472 sub.replace("The ${animal.${species.${color}}} jumps over the ${target}."),
473 "Wrong result (1)");
474 assertEquals(
475 "The brown fox jumps over the lazy dog.",
476 sub.replace("The ${animal.${species.${unknownColor:-brown}}} jumps over the ${target}."),
477 "Wrong result (2)");
478 }
479
480
481
482
483 @Test
484 public void testReplaceNoPrefixNoSuffix() {
485 doTestReplace("The animal jumps over the lazy dog.", "The animal jumps over the ${target}.", true);
486 }
487
488
489
490
491 @Test
492 public void testReplaceNoPrefixSuffix() {
493 doTestReplace("The animal} jumps over the lazy dog.", "The animal} jumps over the ${target}.", true);
494 }
495
496
497
498
499 @Test
500 public void testReplaceNoVariables() {
501 doTestNoReplace("The balloon arrived.");
502 }
503
504
505
506
507 @Test
508 public void testReplaceNull() {
509 doTestNoReplace(null);
510 }
511
512
513
514
515 @Test
516 public void testReplacePartialString_noReplace() {
517 final StrSubstitutor sub = new StrSubstitutor();
518 assertEquals("${animal} jumps", sub.replace("The ${animal} jumps over the ${target}.", 4, 15));
519 }
520
521
522
523
524 @Test
525 public void testReplacePrefixNoSuffix() {
526 doTestReplace("The ${animal jumps over the ${target} lazy dog.", "The ${animal jumps over the ${target} ${target}.", true);
527 }
528
529
530
531
532 @Test
533 public void testReplaceRecursive() {
534 values.put("animal", "${critter}");
535 values.put("target", "${pet}");
536 values.put("pet", "${petCharacteristic} dog");
537 values.put("petCharacteristic", "lazy");
538 values.put("critter", "${critterSpeed} ${critterColor} ${critterType}");
539 values.put("critterSpeed", "quick");
540 values.put("critterColor", "brown");
541 values.put("critterType", "fox");
542 doTestReplace("The quick brown fox jumps over the lazy dog.", "The ${animal} jumps over the ${target}.", true);
543
544 values.put("pet", "${petCharacteristicUnknown:-lazy} dog");
545 doTestReplace("The quick brown fox jumps over the lazy dog.", "The ${animal} jumps over the ${target}.", true);
546 }
547
548
549
550
551 @Test
552 public void testReplaceSimple() {
553 doTestReplace("The quick brown fox jumps over the lazy dog.", "The ${animal} jumps over the ${target}.", true);
554 }
555
556
557
558
559 @Test
560 public void testReplaceSolo() {
561 doTestReplace("quick brown fox", "${animal}", false);
562 }
563
564
565
566
567 @Test
568 public void testReplaceSoloEscaping() {
569 doTestReplace("${animal}", "$${animal}", false);
570 }
571
572
573
574
575 @Test
576 public void testReplaceToIdentical() {
577 values.put("animal", "$${${thing}}");
578 values.put("thing", "animal");
579 doTestReplace("The ${animal} jumps.", "The ${animal} jumps.", true);
580 }
581
582
583
584
585 @Test
586 public void testReplaceUnknownKey() {
587 doTestReplace("The ${person} jumps over the lazy dog.", "The ${person} jumps over the ${target}.", true);
588 doTestReplace("The ${person} jumps over the lazy dog. 1234567890.", "The ${person} jumps over the ${target}. ${undefined.number:-1234567890}.", true);
589 }
590
591
592
593
594 @Test
595 public void testReplaceWeirdPattens() {
596 doTestNoReplace("");
597 doTestNoReplace("${}");
598 doTestNoReplace("${ }");
599 doTestNoReplace("${\t}");
600 doTestNoReplace("${\n}");
601 doTestNoReplace("${\b}");
602 doTestNoReplace("${");
603 doTestNoReplace("$}");
604 doTestNoReplace("}");
605 doTestNoReplace("${}$");
606 doTestNoReplace("${${");
607 doTestNoReplace("${${}}");
608 doTestNoReplace("${$${}}");
609 doTestNoReplace("${$$${}}");
610 doTestNoReplace("${$$${$}}");
611 doTestNoReplace("${${}}");
612 doTestNoReplace("${${ }}");
613 }
614
615
616
617
618 @Test
619 public void testResolveVariable() {
620 final StrBuilder builder = new StrBuilder("Hi ${name}!");
621 final Map<String, String> map = new HashMap<>();
622 map.put("name", "commons");
623 final StrSubstitutor sub = new StrSubstitutor(map) {
624 @Override
625 protected String resolveVariable(final String variableName, final StrBuilder buf, final int startPos, final int endPos) {
626 assertEquals("name", variableName);
627 assertSame(builder, buf);
628 assertEquals(3, startPos);
629 assertEquals(10, endPos);
630 return "jakarta";
631 }
632 };
633 sub.replaceIn(builder);
634 assertEquals("Hi jakarta!", builder.toString());
635 }
636
637 @Test
638 public void testSamePrefixAndSuffix() {
639 final Map<String, String> map = new HashMap<>();
640 map.put("greeting", "Hello");
641 map.put(" there ", "XXX");
642 map.put("name", "commons");
643 assertEquals("Hi commons!", StrSubstitutor.replace("Hi @name@!", map, "@", "@"));
644 assertEquals("Hello there commons!", StrSubstitutor.replace("@greeting@ there @name@!", map, "@", "@"));
645 }
646
647
648
649
650 @Test
651 public void testStaticReplace() {
652 final Map<String, String> map = new HashMap<>();
653 map.put("name", "commons");
654 assertEquals("Hi commons!", StrSubstitutor.replace("Hi ${name}!", map));
655 }
656
657
658
659
660 @Test
661 public void testStaticReplacePrefixSuffix() {
662 final Map<String, String> map = new HashMap<>();
663 map.put("name", "commons");
664 assertEquals("Hi commons!", StrSubstitutor.replace("Hi <name>!", map, "<", ">"));
665 }
666
667
668
669
670 @Test
671 public void testStaticReplaceSystemProperties() {
672 final StrBuilder buf = new StrBuilder();
673 buf.append("Hi ").append(System.getProperty("user.name"));
674 buf.append(", you are working with ");
675 buf.append(System.getProperty("os.name"));
676 buf.append(", your home directory is ");
677 buf.append(System.getProperty("user.home")).append('.');
678 assertEquals(buf.toString(), StrSubstitutor.replaceSystemProperties("Hi ${user.name}, you are "
679 + "working with ${os.name}, your home "
680 + "directory is ${user.home}."));
681 }
682
683
684
685
686 @Test
687 public void testSubstituteDefaultProperties() {
688 final String org = "${doesnotwork}";
689 System.setProperty("doesnotwork", "It works!");
690
691
692 final Properties props = new Properties(System.getProperties());
693
694 assertEquals("It works!", StrSubstitutor.replace(org, props));
695 }
696
697 @Test
698 public void testSubstitutePreserveEscape() {
699 final String org = "${not-escaped} $${escaped}";
700 final Map<String, String> map = new HashMap<>();
701 map.put("not-escaped", "value");
702
703 final StrSubstitutor sub = new StrSubstitutor(map, "${", "}", '$');
704 assertFalse(sub.isPreserveEscapes());
705 assertEquals("value ${escaped}", sub.replace(org));
706
707 sub.setPreserveEscapes(true);
708 assertTrue(sub.isPreserveEscapes());
709 assertEquals("value $${escaped}", sub.replace(org));
710 }
711
712 }