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 { 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 true 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 null and this map does * not permit null 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 true if this map maps one or more keys to the specified * value. More formally, returns true if and only if this map * contains at least one mapping to a value v such that * (value==null ? v==null : value.equals(v)). This operation will * probably require time linear in the map size for most implementations of the * Map interface. * * @param value value whose presence in this map is to be tested. * * @return true 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 null and this map does * not permit null 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 null * 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 null and this map does * not permit null 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 null if * there was no mapping for key. A null return can also * indicate that the map previously associated null with the * specified key, if the implementation supports null values. * * @throws UnsupportedOperationException if the put 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 null keys * or values, and the specified key or value is null. */ 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 putAll 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 null, or if * this map does not permit null keys or values, and the specified map * contains null keys or values. */ public void putAll( Map t ) { context.getBindings( ENGINE_SCOPE ).putAll( t ); } /** * Removes the mapping from the engine scope. *

*

Returns the value to which the map previously associated the key, or * null if the map contained no mapping for this key. (A * null return can also indicate that the map previously associated * null with the specified key if the implementation supports * null 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 null 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 null and this map does * not permit null keys (optional). * @throws UnsupportedOperationException if the remove 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 remove operation, or through the * setValue 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 * Iterator.remove, Set.remove, removeAll, * retainAll and clear operations. It does not support the * add or addAll operations. * * @return a set view of the mappings contained in this map. */ public Set> entrySet() { throw new Error("unimplemented"); } private Set totalKeySet() { Set keys = new HashSet(); List 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 scopes = context.getScopes(); for ( int i : scopes ) { values.addAll( context.getBindings( i ).values() ); } return Collections.unmodifiableSet(values); } }