[stringtemplate-interest] best way to expose xml in template
Nate
misc at n4te.com
Wed Dec 6 17:12:24 PST 2006
Below is my workaround to be able to use a Set as StringTemplate
attribute and use an expression like "$if(set.key)$". It was either this
or maintain my own ST distro.
-Nate
/**
* A Map that wraps a Set where the values come from the Set and the keys
are the result of Object#toString() on the values.
*/
public abstract class SetMap implements Map {
private final Set set;
public SetMap (Set set) {
this.set = set;
}
abstract protected Object keyToValue (Object key);
/**
* Default implementation returns the String representation of the value.
*/
protected Object valueToKey (Object value) {
return value.toString();
}
public void clear () {
set.clear();
}
public boolean containsKey (Object key) {
return containsValue(keyToValue(key));
}
public boolean containsValue (Object value) {
return set.contains(value);
}
/**
* The Map.Entry objects in the returned Set do not support the {@link
Map.Entry#setValue(Object)} method.
*/
public Set entrySet () {
return new AbstractSet() {
public int size () {
return set.size();
}
public Iterator iterator () {
return new SetMapEntryIterator(set);
}
};
}
public Object get (Object key) {
return keyToValue(key);
}
public boolean isEmpty () {
return set.isEmpty();
}
public Set keySet () {
return new AbstractSet() {
public int size () {
return set.size();
}
public Iterator iterator () {
return new SetMapKeyIterator(set);
}
};
}
public Object put (Object key, Object value) {
return set.add(value) ? null : value;
}
public void putAll (Map map) {
for (Iterator iter = map.values().iterator(); iter.hasNext();)
set.add(iter.next());
}
public Object remove (Object key) {
Object value = keyToValue(key);
if (value != null) set.remove(value);
return value;
}
public int size () {
return set.size();
}
public Collection values () {
return set;
}
private class SetMapEntryIterator implements Iterator {
private final Iterator iter;
public SetMapEntryIterator (Set set) {
this.iter = set.iterator();
}
public boolean hasNext () {
return iter.hasNext();
}
public Object next () {
return new Map.Entry() {
private Object value = iter.next();
public Object setValue (Object value) {
throw new UnsupportedOperationException();
}
public Object getValue () {
return value;
}
public Object getKey () {
return valueToKey(value);
}
};
}
public void remove () {
iter.remove();
}
}
private class SetMapKeyIterator implements Iterator {
private final Iterator iter;
public SetMapKeyIterator (Set set) {
this.iter = set.iterator();
}
public boolean hasNext () {
return iter.hasNext();
}
public Object next () {
return valueToKey(iter.next());
}
public void remove () {
iter.remove();
}
}
}
Nate wrote:
> Terence Parr wrote:
>
>> On Dec 5, 2006, at 5:24 PM, Nate wrote:
>>
>>> Thanks for the reply.
>>>
>>> It would be great if there were an interface that could be implemented
>>> that had simply #get(String).
>>>
>>>
>> That is probably too flexible, leading a bigger hole I want.
>> Allowing the map interface took a lot of convincing from other people
>> before I did it. ;)
>>
>>
> Maybe true, but the hole is there either way.
>
>
>>> Also Collection could be supported... $if (someSet.moo)$ would be
>>> equivalent to the Java: if (someSet.contains("moo"))
>>>
>>>
>> That is too much like logic I think.
>>
>>
> While this message has the subject "best way to expose xml in a
> template", the actual problem I encountered that prompted support for
> Collection#contains is this... I have a user object with a Set<String>
> of "capabilities". I would like to check in my templates if the user has
> a given capability. Eg, the template should show an "admin tools" link
> if the user has the capability "can view admin tools". I could manually
> add the capabilities that the template needs to know about as
> attributes, but if a different set of templates is used to display the
> page then they may require knowledge of different capabilities. Eg, the
> "admin tools" link may be in a different template. The easiest solution
> I think is to add an attribute for every template called "capabilities"
> that contains the Set, then use...
> $if(capabilities.("can view admin tools"))$<a href=...>admin
> tools</a>$endif$
>
> -Nate
>
More information about the stringtemplate-interest
mailing list