田源
2024-03-07 4b4083fd73dc27ece42f4835483565eef0e4f608
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
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);
    }
 
}