PageRenderTime 106ms CodeModel.GetById 90ms app.highlight 12ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/bsh/ExternalNameSpace.java

#
Java | 234 lines | 106 code | 28 blank | 100 comment | 8 complexity | 24ee88d282a7891fc01d28a11b98d294 MD5 | raw file
  1package org.gjt.sp.jedit.bsh;
  2
  3import 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*/
 30public 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 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 name, Object 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 name )
 85	{
 86		super.unsetVariable( name );
 87		externalMap.remove( name );
 88	}
 89
 90	/**
 91	*/
 92	public String [] getVariableNames() 
 93	{
 94		// union of the names in the internal namespace and external map
 95		Set nameSet = new HashSet();
 96		String [] nsNames = super.getVariableNames();
 97		nameSet.addAll( Arrays.asList( nsNames ) );
 98		nameSet.addAll( externalMap.keySet() );
 99		return (String [])nameSet.toArray( new String[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 name, boolean recurse ) 
113		throws UtilEvalError
114	{
115		// check the external map for the variable name
116		Object 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)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	name, Class type, Object 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 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 name, Class [] 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 name, Object 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