I personall do not see why this is needed.
With current impl. loops are not possible simply because you can only set
inner Context in the constructor, so there is no need to detect loops.
And I am not sure what is the need to be able to change chaining after the
context is created. At least I can not think of a good scenario. I also
believe we should stay with only using Context inteface on the outside to
allow maximum flexibility.
dixi.
Fedor.
On Friday 27 April 2001 18:58, you wrote:
> Hey fellas,
>
> I did some stuff to enchance the Context chaining. This is my first
> submission, so let me know if I'm way out of line...
>
> There are some ugly bits in here due to the fact that the innerContext
> is defined as a Context, not an AbstractContext. Does anyone object to
> making the innerContext an AbstractContext? If not, I can take the
> exceptions out of this code...
>
>
> Index: src/java/org/apache/velocity/context/AbstractContext.java
> ===================================================================
> RCS file:
> /home/cvspublic/jakarta-velocity/src/java/org/apache/velocity/context/Abstr
>actContext.java,v retrieving revision 1.4
> diff -u -r1.4 AbstractContext.java
> --- src/java/org/apache/velocity/context/AbstractContext.java 2001/03/28
> 03:01:04 1.4 +++
> src/java/org/apache/velocity/context/AbstractContext.java 2001/04/28
> 01:50:43 @@ -298,7 +298,115 @@
> return innerContext;
> }
>
> -}
> + /**
> + * Sets the chained Context.
> + * Note: using this method can potentially cause a loop in the
> Context chain.
> + * The preferred method of dealing with the Context chain is
> through the addChainedContext() and removeChainedContext() methods, as
> those methods do checks to prevent a closed chain.
> + *
> + * @param context The context to be chained.
> + * @return The old chained Context if one existed,
> <code>null</code> if not.
> + */
> + public Context setChainedContext(Context c)
> + {
> + Context oldContext = innerContext;
> + innerContext = c;
> + return oldContext;
> + }
> +
> + /**
> + * Adds a Context to the end of the Context chain.
> + * If the provided context is already on the Context chain, it is
> not added again.
> + *
> + * @param context The context to be added to the chain.
> + * @return <code>true</code> is the context was added,
> <code>false</code> otherwise.
> + * @throws UnsupportedOperationException if a context on the chain
> does not support this action.
> + */
> + public boolean addChainedContext(Context c)
> + {
> + // Make sure adding this context will not create an infinite loop
> + Context con = c;
> + while(con != null)
> + {
> + if(con == this)
> + {
> + return false;
> + }
> +
> + if(!(con instanceof AbstractContext))
> + {
> + throw new UnsupportedOperationException("It could not
> be determined if adding the supplied Context would cause a loop in the
> Context chain.");
> + }
> + else
> + {
> + con = ((AbstractContext)con).getChainedContext();
> + }
> + }
> +
> + if(innerContext == null)
> + {
> + innerContext = c;
> + return true;
> + }
>
> + if(!(innerContext instanceof AbstractContext))
> + {
> + throw new UnsupportedOperationException("Some Context on
> the chain does not support this operation.");
> + }
>
> + return ((AbstractContext)innerContext).addChainedContext(c);
> + }
>
> + /**
> + * Removes a Context from the Context chain.
> + * All Contexts following the removed context are moved one step
> closer to the head of the chain.
> + *
> + * @param context The context to be removed from the chain.
> + * @param severChain
> + * @return <code>true</code> is the context was removed,
> <code>false</code> otherwise.
> + * @throws UnsupportedOperationException if a context on the chain
> does not support this action.
> + */
> + public boolean removeChainedContext(Context c)
> + {
> + return removeChainedContext(c, true);
> + }
> +
> + /**
> + * Removes a Context from the Context chain.
> + *
> + * @param context The context to be removed from the chain.
> + * @param severChain
> + * If true, the chain is severed at the removed context.
> + * If false, all Contexts following the removed context are moved
> one step closer to the head of the chain.
> + * @return <code>true</code> is the context was found and removed,
> <code>false</code> otherwise.
> + * @throws UnsupportedOperationException if a context on the chain
> does not support this action.
> + */
> + public boolean removeChainedContext(Context c, boolean severChain)
> + {
> + if(innerContext == null)
> + {
> + return false;
> + }
> +
> + if(innerContext == c)
> + {
> + if(severChain)
> + {
> + innerContext = null;
> + }
> + else
> + {
> + if(!(innerContext instanceof AbstractContext))
> + {
> + throw new UnsupportedOperationException("Some
> Context on the chain does not support this operation.");
> + }
> + innerContext =
> ((AbstractContext)innerContext).getChainedContext();
> + }
> + return true;
> + }
> + else
> + {
> + return
> ((AbstractContext)innerContext).removeChainedContext(c, severChain);
> + }
> + }
> +
> +}