package org.jbpm.pvm.internal.script;
|
|
import javax.script.ScriptContext;
|
import java.util.*;
|
import static javax.script.ScriptContext.*;
|
|
/**
|
* This class implements an ENGINE_SCOPE centric Map view of the ScriptContext
|
* for engine implementations. This class can be used to simplify engine
|
* implementations which have the capability to bind their namespaces to Maps
|
* or other external interfaces.
|
*
|
* Get operations on this view delegate to the
|
* ScriptContext inheriting get() method that automatically traverses the
|
* binding scopes in order or precedence. Put operations on this view always
|
* store values in the ENGINE_SCOPE bindings. Other operations such as
|
* size() and contains() are implemented appropriately, but perhaps not as
|
* efficiently as possible.
|
*
|
*/
|
public class ScriptContextEngineView implements Map<String,Object>
|
{
|
ScriptContext context;
|
|
public ScriptContextEngineView( ScriptContext context )
|
{
|
this.context = context;
|
}
|
|
/**
|
* Returns the number of unique object bindings in all scopes.
|
* (duplicate, shadowed, bindings count as a single binging).
|
*/
|
public int size()
|
{
|
return totalKeySet().size();
|
}
|
|
/**
|
* Returns true if no bindings are present in any scope of the context.
|
*/
|
public boolean isEmpty()
|
{
|
return totalKeySet().size() == 0;
|
}
|
|
/**
|
* Returns true if the key name is bound in any scope in the context.
|
* The key must be a String.
|
*
|
* @param key key whose presence in this map is to be tested.
|
*
|
* @return <tt>true</tt> if this map contains a mapping for the specified key.
|
*
|
* @throws ClassCastException if the key is of an inappropriate type for this
|
* map (optional).
|
* @throws NullPointerException if the key is <tt>null</tt> and this map does
|
* not permit <tt>null</tt> keys (optional).
|
*/
|
// Why isn't the compiler allowing this?
|
//public boolean containsKey( String key )
|
public boolean containsKey( Object key )
|
{
|
return context.getAttribute( (String)key ) != null;
|
}
|
|
/**
|
* Returns <tt>true</tt> if this map maps one or more keys to the specified
|
* value. More formally, returns <tt>true</tt> if and only if this map
|
* contains at least one mapping to a value <tt>v</tt> such that
|
* <tt>(value==null ? v==null : value.equals(v))</tt>. This operation will
|
* probably require time linear in the map size for most implementations of the
|
* <tt>Map</tt> interface.
|
*
|
* @param value value whose presence in this map is to be tested.
|
*
|
* @return <tt>true</tt> if this map maps one or more keys to the specified
|
* value.
|
*
|
* @throws ClassCastException if the value is of an inappropriate type for this
|
* map (optional).
|
* @throws NullPointerException if the value is <tt>null</tt> and this map does
|
* not permit <tt>null</tt> values (optional).
|
*/
|
public boolean containsValue( Object value )
|
{
|
Set values = totalValueSet();
|
return values.contains( value );
|
}
|
|
/**
|
* Returns the value bound in the most specific (lowest numbered)
|
* bindings space for this key.
|
* key must be a String.
|
*
|
* @param key key whose associated value is to be returned.
|
*
|
* @return the value to which this map maps the specified key, or <tt>null</tt>
|
* if the map contains no mapping for this key.
|
*
|
* @throws ClassCastException if the key is of an inappropriate type for this
|
* map (optional).
|
* @throws NullPointerException if the key is <tt>null</tt> and this map does
|
* not permit <tt>null</tt> keys (optional).
|
* @see #containsKey(Object)
|
*/
|
public Object get( Object key )
|
{
|
return context.getAttribute( (String)key );
|
}
|
|
/**
|
* Set the key, value binding in the ENGINE_SCOPE of the context.
|
*
|
* @param key key with which the specified value is to be associated.
|
* @param value value to be associated with the specified key.
|
*
|
* @return previous value associated with specified key, or <tt>null</tt> if
|
* there was no mapping for key. A <tt>null</tt> return can also
|
* indicate that the map previously associated <tt>null</tt> with the
|
* specified key, if the implementation supports <tt>null</tt> values.
|
*
|
* @throws UnsupportedOperationException if the <tt>put</tt> operation is not
|
* supported by this map.
|
* @throws ClassCastException if the class of the specified key or value
|
* prevents it from being stored in this map.
|
* @throws IllegalArgumentException if some aspect of this key or value
|
* prevents it from being stored in this map.
|
* @throws NullPointerException if this map does not permit <tt>null</tt> keys
|
* or values, and the specified key or value is <tt>null</tt>.
|
*/
|
public Object put( String key, Object value )
|
{
|
Object oldValue =
|
context.getAttribute( key, ENGINE_SCOPE );
|
context.setAttribute( key, value, ENGINE_SCOPE );
|
return oldValue;
|
}
|
|
|
/**
|
* Put the bindings into the ENGINE_SCOPE of the context.
|
*
|
* @param t Mappings to be stored in this map.
|
*
|
* @throws UnsupportedOperationException if the <tt>putAll</tt> method is not
|
* supported by this map.
|
* @throws ClassCastException if the class of a key or value in the specified
|
* map prevents it from being stored in this map.
|
* @throws IllegalArgumentException some aspect of a key or value in the
|
* specified map prevents it from being stored in this map.
|
* @throws NullPointerException if the specified map is <tt>null</tt>, or if
|
* this map does not permit <tt>null</tt> keys or values, and the specified map
|
* contains <tt>null</tt> keys or values.
|
*/
|
public void putAll( Map<? extends String, ? extends Object> t )
|
{
|
context.getBindings( ENGINE_SCOPE ).putAll( t );
|
}
|
|
/**
|
* Removes the mapping from the engine scope.
|
* <p/>
|
* <p>Returns the value to which the map previously associated the key, or
|
* <tt>null</tt> if the map contained no mapping for this key. (A
|
* <tt>null</tt> return can also indicate that the map previously associated
|
* <tt>null</tt> with the specified key if the implementation supports
|
* <tt>null</tt> values.) The map will not contain a mapping for the specified
|
* key once the call returns.
|
*
|
* @param okey key whose mapping is to be removed from the map.
|
*
|
* @return previous value associated with specified key, or <tt>null</tt> if
|
* there was no mapping for key.
|
*
|
* @throws ClassCastException if the key is of an inappropriate type for this
|
* map (optional).
|
* @throws NullPointerException if the key is <tt>null</tt> and this map does
|
* not permit <tt>null</tt> keys (optional).
|
* @throws UnsupportedOperationException if the <tt>remove</tt> method is not
|
* supported by this map.
|
*/
|
// Why is the compiler complaining about this?
|
//public Object remove( String key )
|
public Object remove( Object okey )
|
{
|
// This shouldn't be necessary... we don't map Objects, Strings.
|
String key = (String)okey;
|
Object oldValue =
|
context.getAttribute( key, ENGINE_SCOPE );
|
context.removeAttribute( key, ENGINE_SCOPE );
|
return oldValue;
|
}
|
|
/**
|
* Removes all mappings from this map (optional operation).
|
*
|
* @throws UnsupportedOperationException clear is not supported by this map.
|
*/
|
public void clear()
|
{
|
context.getBindings( ENGINE_SCOPE ).clear();
|
}
|
|
/**
|
* Returns the total key set of all scopes.
|
* This method violates the Map contract by returning an unmodifiable set.
|
*
|
* @return a set view of the keys contained in this map.
|
*/
|
public Set keySet()
|
{
|
return totalKeySet();
|
}
|
|
/**
|
*
|
* Returns the total values set of all scopes.
|
* This method violates the Map contract by returning an unmodifiable set.
|
*
|
* @return a collection view of the values contained in this map.
|
*/
|
public Collection values()
|
{
|
return totalValueSet();
|
}
|
|
/**
|
* Returns a set view of the mappings contained in this map. Each element in
|
* the returned set is a {@link java.util.Map.Entry}. The set is backed by the
|
* map, so changes to the map are reflected in the set, and vice-versa. If the
|
* map is modified while an iteration over the set is in progress (except
|
* through the iterator's own <tt>remove</tt> operation, or through the
|
* <tt>setValue</tt> operation on a map entry returned by the iterator) the
|
* results of the iteration are undefined. The set supports element removal,
|
* which removes the corresponding mapping from the map, via the
|
* <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>,
|
* <tt>retainAll</tt> and <tt>clear</tt> operations. It does not support the
|
* <tt>add</tt> or <tt>addAll</tt> operations.
|
*
|
* @return a set view of the mappings contained in this map.
|
*/
|
public Set<Entry<String,Object>> entrySet()
|
{
|
throw new Error("unimplemented");
|
}
|
|
private Set totalKeySet()
|
{
|
Set keys = new HashSet();
|
List<Integer> scopes = context.getScopes();
|
for ( int i : scopes ) {
|
keys.addAll( context.getBindings( i ).keySet() );
|
}
|
return Collections.unmodifiableSet(keys);
|
}
|
private Set totalValueSet()
|
{
|
Set values = new HashSet();
|
List<Integer> scopes = context.getScopes();
|
for ( int i : scopes ) {
|
values.addAll( context.getBindings( i ).values() );
|
}
|
return Collections.unmodifiableSet(values);
|
}
|
|
}
|