KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > bsh > ExternalNameSpace


1 package bsh;
2
3 import java.util.*;
4
5 /**
6     A namespace which maintains an external map of values held in variables in
7     its scope. This mechanism provides a standard collections based interface
8     to the namespace as well as a convenient way to export and view values of
9     the namespace without the ordinary BeanShell wrappers.
10     </p>
11
12     Variables are maintained internally in the normal fashion to support
13     meta-information (such as variable type and visibility modifiers), but
14     exported and imported in a synchronized way. Variables are exported each
15     time they are written by BeanShell. Imported variables from the map appear
16     in the BeanShell namespace as untyped variables with no modifiers and
17     shadow any previously defined variables in the scope.
18     <p/>
19
20     Note: this class is inherentely dependent on Java 1.2, however it is not
21     used directly by the core as other than type NameSpace, so no dependency is
22     introduced.
23 */

24 /*
25     Implementation notes: bsh methods are not currently expored to the
26     external namespace. All that would be required to add this is to override
27     setMethod() and provide a friendlier view than vector (currently used) for
28     overloaded forms (perhaps a map by method SignatureKey).
29 */

30 public class ExternalNameSpace extends NameSpace
31 {
32     private Map externalMap;
33
34     public ExternalNameSpace()
35     {
36         this( null, "External Map Namespace", null );
37     }
38
39     /**
40     */

41     public ExternalNameSpace( NameSpace parent, String JavaDoc name, Map externalMap )
42     {
43         super( parent, name );
44
45         if ( externalMap == null )
46             externalMap = new HashMap();
47             
48         this.externalMap = externalMap;
49
50     }
51
52     /**
53         Get the map view of this namespace.
54     */

55     public Map getMap() { return externalMap; }
56
57     /**
58         Set the external Map which to which this namespace synchronizes.
59         The previous external map is detached from this namespace. Previous
60         map values are retained in the external map, but are removed from the
61         BeanShell namespace.
62     */

63     public void setMap( Map map )
64     {
65         // Detach any existing namespace to preserve it, then clear this
66
// namespace and set the new one
67
this.externalMap = null;
68         clear();
69         this.externalMap = map ;
70     }
71
72     /**
73     */

74     void setVariable(
75         String JavaDoc name, Object JavaDoc value, boolean strictJava, boolean recurse )
76         throws UtilEvalError
77     {
78         super.setVariable( name, value, strictJava, recurse );
79         putExternalMap( name, value );
80     }
81
82     /**
83     */

84     public void unsetVariable( String JavaDoc name )
85     {
86         super.unsetVariable( name );
87         externalMap.remove( name );
88     }
89
90     /**
91     */

92     public String JavaDoc [] getVariableNames()
93     {
94         // union of the names in the internal namespace and external map
95
Set nameSet = new HashSet();
96         String JavaDoc [] nsNames = super.getVariableNames();
97         nameSet.addAll( Arrays.asList( nsNames ) );
98         nameSet.addAll( externalMap.keySet() );
99         return (String JavaDoc [])nameSet.toArray( new String JavaDoc[0] );
100     }
101
102     /**
103     */

104     /*
105         Notes: This implmenetation of getVariableImpl handles the following
106         cases:
107         1) var in map not in local scope - var was added through map
108         2) var in map and in local scope - var was added through namespace
109         3) var not in map but in local scope - var was removed via map
110         4) var not in map and not in local scope - non-existent var
111     */

112     protected Variable getVariableImpl( String JavaDoc name, boolean recurse )
113         throws UtilEvalError
114     {
115         // check the external map for the variable name
116
Object JavaDoc value = externalMap.get( name );
117
118         Variable var;
119         if ( value == null )
120         {
121             // The var is not in external map and it should therefore not be
122
// found in local scope (it may have been removed via the map).
123
// Clear it prophalactically.
124
super.unsetVariable( name );
125
126             // Search parent for var if applicable.
127
var = super.getVariableImpl( name, recurse );
128         } else
129         {
130             // Var in external map may be found in local scope with type and
131
// modifier info.
132
Variable localVar = super.getVariableImpl( name, false );
133
134             // If not in local scope then it was added via the external map,
135
// we'll wrap it and pass it along. Else we'll use the local
136
// version.
137
if ( localVar == null )
138                 var = new Variable( name, (Class JavaDoc)null, value, (Modifiers)null );
139             else
140                 var = localVar;
141         }
142
143         return var;
144     }
145     
146     /**
147     */

148     /*
149         Note: the meaning of getDeclaredVariables() is not entirely clear, but
150         the name (and current usage in class generation support) suggests that
151         untyped variables should not be inclueded. Therefore we do not
152         currently have to add the external names here.
153     */

154     public Variable [] getDeclaredVariables()
155     {
156         return super.getDeclaredVariables();
157     }
158
159     /**
160     */

161     public void setTypedVariable(
162         String JavaDoc name, Class JavaDoc type, Object JavaDoc value, Modifiers modifiers )
163         throws UtilEvalError
164     {
165         super.setTypedVariable( name, type, value, modifiers );
166         putExternalMap( name, value );
167     }
168
169     /*
170         Note: we could override this method to allow bsh methods to appear in
171         the external map.
172     */

173     public void setMethod( String JavaDoc name, BshMethod method )
174         throws UtilEvalError
175     {
176         super.setMethod( name, method );
177     }
178
179     /*
180         Note: kind of far-fetched, but... we could override this method to
181         allow bsh methods to be inserted into this namespace via the map.
182     */

183     public BshMethod getMethod(
184         String JavaDoc name, Class JavaDoc [] sig, boolean declaredOnly )
185         throws UtilEvalError
186     {
187         return super.getMethod( name, sig, declaredOnly );
188     }
189
190
191     /*
192         Note: this method should be overridden to add the names from the
193         external map, as is done in getVariableNames();
194     */

195     protected void getAllNamesAux( Vector vec )
196     {
197         super.getAllNamesAux( vec );
198     }
199
200     /**
201         Clear all variables, methods, and imports from this namespace and clear
202         all values from the external map (via Map clear()).
203     */

204     public void clear()
205     {
206         super.clear();
207         externalMap.clear();
208     }
209
210     /**
211         Place an unwrapped value in the external map.
212         BeanShell primitive types are represented by their object wrappers, so
213         it is not possible to differentiate between wrapper types and primitive
214         types via the external Map.
215     */

216     protected void putExternalMap( String JavaDoc name, Object JavaDoc value )
217     {
218         if ( value instanceof Variable )
219             try {
220                 value = unwrapVariable( (Variable)value );
221             } catch ( UtilEvalError ute ) {
222                 // There should be no case for this. unwrapVariable throws
223
// UtilEvalError in some cases where it holds an LHS or array
224
// index.
225
throw new InterpreterError("unexpected UtilEvalError");
226             }
227
228         if ( value instanceof Primitive )
229             value = Primitive.unwrap( (Primitive)value );
230
231         externalMap.put( name, value );
232     }
233 }
234
235
Popular Tags