@@ -247,7 +247,7 @@ private static void addText(String value, int start, int end, LinkedList<Part> p
247
247
if (!parts .isEmpty ()) {
248
248
Part current = parts .removeLast ();
249
249
if (current instanceof TextPart textPart ) {
250
- parts .add (new TextPart (textPart .text + text ));
250
+ parts .add (new TextPart (textPart .text () + text ));
251
251
}
252
252
else {
253
253
parts .add (current );
@@ -420,51 +420,42 @@ public String resolve(PartResolutionContext resolutionContext) {
420
420
421
421
422
422
/**
423
- * A {@link Part} implementation that does not contain a valid placeholder.
424
- * @param text the raw (and resolved) text
423
+ * A base {@link Part} implementation.
425
424
*/
426
- record TextPart (String text ) implements Part {
427
-
428
- @ Override
429
- public String resolve (PartResolutionContext resolutionContext ) {
430
- return this .text ;
431
- }
432
- }
425
+ abstract static class AbstractPart implements Part {
433
426
427
+ private final String text ;
434
428
435
- /**
436
- * A {@link Part} implementation that represents a single placeholder with
437
- * a hard-coded fallback.
438
- * @param text the raw text
439
- * @param key the key of the placeholder
440
- * @param fallback the fallback to use, if any
441
- */
442
- record SimplePlaceholderPart (String text , String key , @ Nullable String fallback ) implements Part {
429
+ protected AbstractPart (String text ) {
430
+ this .text = text ;
431
+ }
443
432
444
433
@ Override
445
- public String resolve (PartResolutionContext resolutionContext ) {
446
- String resolvedValue = resolveToText (resolutionContext , this .key );
447
- if (resolvedValue != null ) {
448
- return resolvedValue ;
449
- }
450
- else if (this .fallback != null ) {
451
- return this .fallback ;
452
- }
453
- return resolutionContext .handleUnresolvablePlaceholder (this .key , this .text );
434
+ public String text () {
435
+ return this .text ;
454
436
}
455
437
438
+ /**
439
+ * Resolve the placeholder with the given {@code key}. If the result of such
440
+ * resolution return other placeholders, those are resolved as well until the
441
+ * resolution no longer contains any placeholders.
442
+ * @param resolutionContext the resolution context to use
443
+ * @param key the initial placeholder
444
+ * @return the full resolution of the given {@code key} or {@code null} if
445
+ * the placeholder has no value to begin with
446
+ */
456
447
@ Nullable
457
- private String resolveToText (PartResolutionContext resolutionContext , String text ) {
458
- String resolvedValue = resolutionContext .resolvePlaceholder (text );
448
+ protected String resolveRecursively (PartResolutionContext resolutionContext , String key ) {
449
+ String resolvedValue = resolutionContext .resolvePlaceholder (key );
459
450
if (resolvedValue != null ) {
460
- resolutionContext .flagPlaceholderAsVisited (text );
451
+ resolutionContext .flagPlaceholderAsVisited (key );
461
452
// Let's check if we need to recursively resolve that value
462
453
List <Part > nestedParts = resolutionContext .parse (resolvedValue );
463
454
String value = toText (nestedParts );
464
455
if (!isTextOnly (nestedParts )) {
465
456
value = new ParsedValue (resolvedValue , nestedParts ).resolve (resolutionContext );
466
457
}
467
- resolutionContext .removePlaceholder (text );
458
+ resolutionContext .removePlaceholder (key );
468
459
return value ;
469
460
}
470
461
// Not found
@@ -483,26 +474,97 @@ private String toText(List<Part> parts) {
483
474
}
484
475
485
476
477
+ /**
478
+ * A {@link Part} implementation that does not contain a valid placeholder.
479
+ */
480
+ static class TextPart extends AbstractPart {
481
+
482
+ /**
483
+ * Create a new instance.
484
+ * @param text the raw (and resolved) text
485
+ */
486
+ public TextPart (String text ) {
487
+ super (text );
488
+ }
489
+
490
+ @ Override
491
+ public String resolve (PartResolutionContext resolutionContext ) {
492
+ return text ();
493
+ }
494
+ }
495
+
496
+
497
+ /**
498
+ * A {@link Part} implementation that represents a single placeholder with
499
+ * a hard-coded fallback.
500
+ */
501
+ static class SimplePlaceholderPart extends AbstractPart {
502
+
503
+ private final String key ;
504
+
505
+ @ Nullable
506
+ private final String fallback ;
507
+
508
+ /**
509
+ * Create a new instance.
510
+ * @param text the raw text
511
+ * @param key the key of the placeholder
512
+ * @param fallback the fallback to use, if any
513
+ */
514
+ public SimplePlaceholderPart (String text ,String key , @ Nullable String fallback ) {
515
+ super (text );
516
+ this .key = key ;
517
+ this .fallback = fallback ;
518
+ }
519
+
520
+ @ Override
521
+ public String resolve (PartResolutionContext resolutionContext ) {
522
+ String value = resolveRecursively (resolutionContext , this .key );
523
+ if (value != null ) {
524
+ return value ;
525
+ }
526
+ else if (this .fallback != null ) {
527
+ return this .fallback ;
528
+ }
529
+ return resolutionContext .handleUnresolvablePlaceholder (this .key , text ());
530
+ }
531
+ }
532
+
533
+
486
534
/**
487
535
* A {@link Part} implementation that represents a single placeholder
488
536
* containing nested placeholders.
489
- * @param text the raw text of the root placeholder
490
- * @param keyParts the parts of the key
491
- * @param defaultParts the parts of the fallback, if any
492
537
*/
493
- record NestedPlaceholderPart (String text , List <Part > keyParts , @ Nullable List <Part > defaultParts ) implements Part {
538
+ static class NestedPlaceholderPart extends AbstractPart {
539
+
540
+ private final List <Part > keyParts ;
541
+
542
+ @ Nullable
543
+ private final List <Part > defaultParts ;
544
+
545
+ /**
546
+ * Create a new instance.
547
+ * @param text the raw text of the root placeholder
548
+ * @param keyParts the parts of the key
549
+ * @param defaultParts the parts of the fallback, if any
550
+ */
551
+ NestedPlaceholderPart (String text , List <Part > keyParts , @ Nullable List <Part > defaultParts ) {
552
+ super (text );
553
+ this .keyParts = keyParts ;
554
+ this .defaultParts = defaultParts ;
555
+ }
494
556
495
557
@ Override
496
558
public String resolve (PartResolutionContext resolutionContext ) {
497
559
String resolvedKey = Part .resolveAll (this .keyParts , resolutionContext );
498
- String value = resolutionContext . resolvePlaceholder ( resolvedKey );
560
+ String value = resolveRecursively ( resolutionContext , resolvedKey );
499
561
if (value != null ) {
500
562
return value ;
501
563
}
502
564
else if (this .defaultParts != null ) {
503
565
return Part .resolveAll (this .defaultParts , resolutionContext );
504
566
}
505
- return resolutionContext .handleUnresolvablePlaceholder (resolvedKey , this . text );
567
+ return resolutionContext .handleUnresolvablePlaceholder (resolvedKey , text () );
506
568
}
507
569
}
508
570
0 commit comments