@@ -75,6 +75,7 @@ protected BlockParam(final Context parent, final Map<String, Object> hash) {
7575 this .extendedContext .resolver = parent .resolver ;
7676 this .parent = parent ;
7777 this .data = parent .data ;
78+ this .internalData = parent .internalData ;
7879 this .resolver = parent .resolver ;
7980 }
8081
@@ -152,6 +153,7 @@ protected PartialCtx(final Context parent, final Object model, final Map<String,
152153 this .extendedContext .extendedContext = new Context (Collections .emptyMap ());
153154 this .parent = parent ;
154155 this .data = parent .data ;
156+ this .internalData = parent .internalData ;
155157 this .resolver = parent .resolver ;
156158 }
157159
@@ -432,6 +434,11 @@ public Object eval(final ValueResolver resolver, final Context context, final Ob
432434 */
433435 protected Map <String , Object > data ;
434436
437+ /**
438+ * Functions similarly to data, but not resolved during rendering.
439+ */
440+ protected Map <String , Object > internalData ;
441+
435442 /**
436443 * Additional, data can be stored here.
437444 */
@@ -470,6 +477,7 @@ private static Context root(final Object model) {
470477 root .data .put (INLINE_PARTIALS , partials );
471478 root .data .put (INVOCATION_STACK , new LinkedList <TemplateSource >());
472479 root .data .put ("root" , model );
480+ root .internalData = new HashMap <>();
473481 return root ;
474482 }
475483
@@ -535,6 +543,41 @@ public Context data(final Map<String, ?> attributes) {
535543 return this ;
536544 }
537545
546+ /**
547+ * Read the attribute from the internal data storage.
548+ *
549+ * @param name The attribute's name.
550+ * @param <T> Data type.
551+ * @return The attribute value or null.
552+ */
553+ @ SuppressWarnings ("unchecked" )
554+ public <T > T internalData (final String name ) {
555+ return (T ) internalData .get (name );
556+ }
557+
558+ /**
559+ * Set an attribute in the internal data storage.
560+ *
561+ * @param name The attribute's name. Required.
562+ * @param value The attribute's value. Required.
563+ * @return This context.
564+ */
565+ public Context internalData (final String name , final Object value ) {
566+ internalData .put (name , value );
567+ return this ;
568+ }
569+
570+ /**
571+ * Store the map in the internal data storage.
572+ *
573+ * @param attributes The attributes to add. Required.
574+ * @return This context.
575+ */
576+ public Context internalData (final Map <String , ?> attributes ) {
577+ internalData .putAll (attributes );
578+ return this ;
579+ }
580+
538581 /**
539582 * Resolved as '.' or 'this' inside templates.
540583 *
@@ -692,6 +735,9 @@ public void destroy() {
692735 if (data != null ) {
693736 data .clear ();
694737 }
738+ if (internalData != null ) {
739+ internalData .clear ();
740+ }
695741 }
696742 if (extendedContext != null ) {
697743 extendedContext .destroy ();
@@ -790,6 +836,7 @@ private Context newChild(final Object model) {
790836 child .setResolver (this .resolver );
791837 child .parent = this ;
792838 child .data = this .data ;
839+ child .internalData = this .internalData ;
793840 return child ;
794841 }
795842
@@ -813,6 +860,7 @@ protected Context newChildContext(final Object model) {
813860 public static Context copy (final Context context , final Object model ) {
814861 Context ctx = Context .newContext (model );
815862 ctx .data = context .data ;
863+ ctx .internalData = context .internalData ;
816864 ctx .resolver = context .resolver ;
817865 return ctx ;
818866 }
0 commit comments