PageRenderTime 73ms CodeModel.GetById 21ms RepoModel.GetById 1ms 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
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. package org.gjt.sp.jedit.bsh;
  2. import java.util.*;
  3. /**
  4. A namespace which maintains an external map of values held in variables in
  5. its scope. This mechanism provides a standard collections based interface
  6. to the namespace as well as a convenient way to export and view values of
  7. the namespace without the ordinary BeanShell wrappers.
  8. </p>
  9. Variables are maintained internally in the normal fashion to support
  10. meta-information (such as variable type and visibility modifiers), but
  11. exported and imported in a synchronized way. Variables are exported each
  12. time they are written by BeanShell. Imported variables from the map appear
  13. in the BeanShell namespace as untyped variables with no modifiers and
  14. shadow any previously defined variables in the scope.
  15. <p/>
  16. Note: this class is inherentely dependent on Java 1.2, however it is not
  17. used directly by the core as other than type NameSpace, so no dependency is
  18. introduced.
  19. */
  20. /*
  21. Implementation notes: bsh methods are not currently expored to the
  22. external namespace. All that would be required to add this is to override
  23. setMethod() and provide a friendlier view than vector (currently used) for
  24. overloaded forms (perhaps a map by method SignatureKey).
  25. */
  26. public class ExternalNameSpace extends NameSpace
  27. {
  28. private Map externalMap;
  29. public ExternalNameSpace()
  30. {
  31. this( null, "External Map Namespace", null );
  32. }
  33. /**
  34. */
  35. public ExternalNameSpace( NameSpace parent, String name, Map externalMap )
  36. {
  37. super( parent, name );
  38. if ( externalMap == null )
  39. externalMap = new HashMap();
  40. this.externalMap = externalMap;
  41. }
  42. /**
  43. Get the map view of this namespace.
  44. */
  45. public Map getMap() { return externalMap; }
  46. /**
  47. Set the external Map which to which this namespace synchronizes.
  48. The previous external map is detached from this namespace. Previous
  49. map values are retained in the external map, but are removed from the
  50. BeanShell namespace.
  51. */
  52. public void setMap( Map map )
  53. {
  54. // Detach any existing namespace to preserve it, then clear this
  55. // namespace and set the new one
  56. this.externalMap = null;
  57. clear();
  58. this.externalMap = map ;
  59. }
  60. /**
  61. */
  62. void setVariable(
  63. String name, Object value, boolean strictJava, boolean recurse )
  64. throws UtilEvalError
  65. {
  66. super.setVariable( name, value, strictJava, recurse );
  67. putExternalMap( name, value );
  68. }
  69. /**
  70. */
  71. public void unsetVariable( String name )
  72. {
  73. super.unsetVariable( name );
  74. externalMap.remove( name );
  75. }
  76. /**
  77. */
  78. public String [] getVariableNames()
  79. {
  80. // union of the names in the internal namespace and external map
  81. Set nameSet = new HashSet();
  82. String [] nsNames = super.getVariableNames();
  83. nameSet.addAll( Arrays.asList( nsNames ) );
  84. nameSet.addAll( externalMap.keySet() );
  85. return (String [])nameSet.toArray( new String[0] );
  86. }
  87. /**
  88. */
  89. /*
  90. Notes: This implmenetation of getVariableImpl handles the following
  91. cases:
  92. 1) var in map not in local scope - var was added through map
  93. 2) var in map and in local scope - var was added through namespace
  94. 3) var not in map but in local scope - var was removed via map
  95. 4) var not in map and not in local scope - non-existent var
  96. */
  97. protected Variable getVariableImpl( String name, boolean recurse )
  98. throws UtilEvalError
  99. {
  100. // check the external map for the variable name
  101. Object value = externalMap.get( name );
  102. Variable var;
  103. if ( value == null )
  104. {
  105. // The var is not in external map and it should therefore not be
  106. // found in local scope (it may have been removed via the map).
  107. // Clear it prophalactically.
  108. super.unsetVariable( name );
  109. // Search parent for var if applicable.
  110. var = super.getVariableImpl( name, recurse );
  111. } else
  112. {
  113. // Var in external map may be found in local scope with type and
  114. // modifier info.
  115. Variable localVar = super.getVariableImpl( name, false );
  116. // If not in local scope then it was added via the external map,
  117. // we'll wrap it and pass it along. Else we'll use the local
  118. // version.
  119. if ( localVar == null )
  120. var = new Variable( name, (Class)null, value, (Modifiers)null );
  121. else
  122. var = localVar;
  123. }
  124. return var;
  125. }
  126. /**
  127. */
  128. /*
  129. Note: the meaning of getDeclaredVariables() is not entirely clear, but
  130. the name (and current usage in class generation support) suggests that
  131. untyped variables should not be inclueded. Therefore we do not
  132. currently have to add the external names here.
  133. */
  134. public Variable [] getDeclaredVariables()
  135. {
  136. return super.getDeclaredVariables();
  137. }
  138. /**
  139. */
  140. public void setTypedVariable(
  141. String name, Class type, Object value, Modifiers modifiers )
  142. throws UtilEvalError
  143. {
  144. super.setTypedVariable( name, type, value, modifiers );
  145. putExternalMap( name, value );
  146. }
  147. /*
  148. Note: we could override this method to allow bsh methods to appear in
  149. the external map.
  150. */
  151. public void setMethod( String name, BshMethod method )
  152. throws UtilEvalError
  153. {
  154. super.setMethod( name, method );
  155. }
  156. /*
  157. Note: kind of far-fetched, but... we could override this method to
  158. allow bsh methods to be inserted into this namespace via the map.
  159. */
  160. public BshMethod getMethod(
  161. String name, Class [] sig, boolean declaredOnly )
  162. throws UtilEvalError
  163. {
  164. return super.getMethod( name, sig, declaredOnly );
  165. }
  166. /*
  167. Note: this method should be overridden to add the names from the
  168. external map, as is done in getVariableNames();
  169. */
  170. protected void getAllNamesAux( Vector vec )
  171. {
  172. super.getAllNamesAux( vec );
  173. }
  174. /**
  175. Clear all variables, methods, and imports from this namespace and clear
  176. all values from the external map (via Map clear()).
  177. */
  178. public void clear()
  179. {
  180. super.clear();
  181. externalMap.clear();
  182. }
  183. /**
  184. Place an unwrapped value in the external map.
  185. BeanShell primitive types are represented by their object wrappers, so
  186. it is not possible to differentiate between wrapper types and primitive
  187. types via the external Map.
  188. */
  189. protected void putExternalMap( String name, Object value )
  190. {
  191. if ( value instanceof Variable )
  192. try {
  193. value = unwrapVariable( (Variable)value );
  194. } catch ( UtilEvalError ute ) {
  195. // There should be no case for this. unwrapVariable throws
  196. // UtilEvalError in some cases where it holds an LHS or array
  197. // index.
  198. throw new InterpreterError("unexpected UtilEvalError");
  199. }
  200. if ( value instanceof Primitive )
  201. value = Primitive.unwrap( (Primitive)value );
  202. externalMap.put( name, value );
  203. }
  204. }