BeanShell: Patch to do it work with enum in switch/case statements
I really like BeanShell. But it is based in pre-Java1.5. So, there is some new Java language features, like enumerations and generics, that it doesn't allow to use. I have made a plugin to use it with Netbeans and I have included it in several projects that I develop, since 2006/2007, I think. I use it into my applications like I use VBA into Microsoft Office stuffs. With BeanShell is easy to do several things without recompile or shutdown your application. You can query, prototype, test, simulate, plugin, plugout, automate and do many things with it. I really like it. I know that Java have has officially incorporated support to scripting, but BeanShell is Java... so if I need to reuse my code later in Java, is simple as to do: nothing! Yeah, it's true. 'cause bsh can load .java file sources, also. So, the sky isn't the limit; the limit is you!
Now, if you want the entire file:
Using the patch, you can use codes like this:
Where the method
BeanShell Patch to work with enums in switch statements
The patch is to be applied into the file classBSHSwitchStatement
. See bellow just the lines affected by it:62 //marciowb 2010-12-11 patch to allows the Bsh to works with enum with switchs statements. 63 //it breaks the compatibility versions of Java older than 1.5, but it works. 64 final Class switchValClass = switchVal.getClass(); //What's the class of the value of this switch? 65 final boolean switchValIsEnumType = switchValClass.isEnum(); //Is it a enum type? 66 67 // while more labels or blocks and haven't hit return control 68 while (child < numchild && returnControl == null) { 69 70 Object labelValue = label.isDefault ? null 71 : (switchValIsEnumType //If it is a enum type, 72 ? Enum.valueOf(switchValClass, label.getChild(0).getText().trim()) //then get the enum value 73 : label.eval(callstack, interpreter)); //otherwise, gonna default evaluation... 74 75 // if label is default or equals switchVal 76 if (label.isDefault || primitiveEquals(switchVal, labelValue, callstack, switchExp)) {
Now, if you want the entire file:
1 /***************************************************************************** 2 * * 3 * This file is part of the BeanShell Java Scripting distribution. * 4 * Documentation and updates may be found at http://www.beanshell.org/ * 5 * * 6 * Sun Public License Notice: * 7 * * 8 * The contents of this file are subject to the Sun Public License Version * 9 * 1.0 (the "License"); you may not use this file except in compliance with * 10 * the License. A copy of the License is available at http://www.sun.com * 11 * * 12 * The Original Code is BeanShell. The Initial Developer of the Original * 13 * Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright * 14 * (C) 2000. All Rights Reserved. * 15 * * 16 * GNU Public License Notice: * 17 * * 18 * Alternatively, the contents of this file may be used under the terms of * 19 * the GNU Lesser General Public License (the "LGPL"), in which case the * 20 * provisions of LGPL are applicable instead of those above. If you wish to * 21 * allow use of your version of this file only under the terms of the LGPL * 22 * and not to allow others to use your version of this file under the SPL, * 23 * indicate your decision by deleting the provisions above and replace * 24 * them with the notice and other provisions required by the LGPL. If you * 25 * do not delete the provisions above, a recipient may use your version of * 26 * this file under either the SPL or the LGPL. * 27 * * 28 * Patrick Niemeyer (pat@pat.net) * 29 * Author of Learning Java, O'Reilly & Associates * 30 * http://www.pat.net/~pat/ * 31 * * 32 *****************************************************************************/ 33 package bsh; 34 35 public class BSHSwitchStatement extends SimpleNode implements ParserConstants { 36 37 public BSHSwitchStatement(int id) { 38 super(id); 39 } 40 41 public Object eval(CallStack callstack, Interpreter interpreter) throws EvalError { 42 int numchild = jjtGetNumChildren(); 43 int child = 0; 44 SimpleNode switchExp = ((SimpleNode) jjtGetChild(child++)); 45 Object switchVal = switchExp.eval(callstack, interpreter); 46 47 /* 48 Note: this could be made clearer by adding an inner class for the 49 cases and an object context for the child traversal. 50 */ 51 // first label 52 BSHSwitchLabel label; 53 Object node; 54 ReturnControl returnControl = null; 55 56 // get the first label 57 if (child >= numchild) { 58 throw new EvalError("Empty switch statement.", this, callstack); 59 } 60 label = ((BSHSwitchLabel) jjtGetChild(child++)); 61 62 //marciowb 2010-12-11 patch to allows the Bsh to works with enum with switchs statements. 63 //it breaks the compatibility versions of Java older than 1.5, but it works. 64 final Class switchValClass = switchVal.getClass(); //What's the class of the value of this switch? 65 final boolean switchValIsEnumType = switchValClass.isEnum(); //Is it a enum type? 66 67 // while more labels or blocks and haven't hit return control 68 while (child < numchild && returnControl == null) { 69 70 Object labelValue = label.isDefault ? null 71 : (switchValIsEnumType //If it is a enum type, 72 ? Enum.valueOf(switchValClass, label.getChild(0).getText().trim()) //then get the enum value 73 : label.eval(callstack, interpreter)); //otherwise, gonna default evaluation... 74 75 // if label is default or equals switchVal 76 if (label.isDefault || primitiveEquals(switchVal, labelValue, callstack, switchExp)) { 77 // execute nodes, skipping labels, until a break or return 78 while (child < numchild) { 79 node = jjtGetChild(child++); 80 if (node instanceof BSHSwitchLabel) { 81 continue; 82 } 83 // eval it 84 Object value = ((SimpleNode) node).eval(callstack, interpreter); 85 86 // should check to disallow continue here? 87 if (value instanceof ReturnControl) { 88 returnControl = (ReturnControl) value; 89 break; 90 } 91 } 92 } else { 93 // skip nodes until next label 94 while (child < numchild) { 95 node = jjtGetChild(child++); 96 if (node instanceof BSHSwitchLabel) { 97 label = (BSHSwitchLabel) node; 98 break; 99 } 100 } 101 } 102 } 103 104 if (returnControl != null && returnControl.kind == RETURN) { 105 return returnControl; 106 } else { 107 return Primitive.VOID; 108 } 109 } 110 111 /** 112 Helper method for testing equals on two primitive or boxable objects. 113 yuck: factor this out into Primitive.java 114 */ 115 private boolean primitiveEquals(Object switchVal, Object targetVal, CallStack callstack, 116 SimpleNode switchExp) 117 throws EvalError { 118 if (switchVal instanceof Primitive || targetVal instanceof Primitive) { 119 try { 120 // binaryOperation can return Primitive or wrapper type 121 Object result = Primitive.binaryOperation( 122 switchVal, targetVal, ParserConstants.EQ); 123 result = Primitive.unwrap(result); 124 return result.equals(Boolean.TRUE); 125 } catch (UtilEvalError e) { 126 throw e.toEvalError( 127 "Switch value: " + switchExp.getText() + ": ", 128 this, callstack); 129 } 130 } else { 131 return switchVal.equals(targetVal); 132 } 133 } 134 } 135 136
Using the patch, you can use codes like this:
for (S52DrawInstruction ins : drawIns) { switch (ins.getType()) { case AC: final S52DrawAreaColor ac = (S52DrawAreaColor) ins; poly.setFillPaint(ac.color.color); break; case LS: final S52DrawLineStyle ls = (S52DrawLineStyle) ins; poly.setLinePaint(ls.color.color); BasicStroke stroke; stroke = helper.getStroke(ls.width, ls.style); poly.setStroke(stroke); break; case CS: final S52DrawComplex cs = (S52DrawComplex) ins; final String simpleInstructions = getDrawInstructionsFromComplex(fe, cs); if (simpleInstructions == null) { info("Não obtívemos as instruções de desenho simplificadas para a instrução complexa: " + cs + " de " + fe); return; } final S52DrawInstructions simpleDrawIns = scat.parseDrawInstructions(simpleInstructions); configGraphic(poly, fe, co, symb, sp, simpleDrawIns); break; default: info("Simbologia não tratada: " + ins); } }
Where the method
getType()
returns a enum value from the enumeration bellow:1 package com.solvoj.S52Library; 2 3 /** 4 * List of S52 Symbolization Instruction. 5 * 6 * @author Marcio Wesley Borges, 2010-12-07 Niterói-RJ 7 */ 8 public enum S52DrawInstructionEnum { 9 10 /** line drawing styles (simple ones (LS) for variable width coloured lines */ 11 LS(new S52DrawLineStyle.Factory()), 12 /** complex line-styles (LC), where line is visualized by a repetitive pattern) */ 13 LC(new S52DrawLineComplex.Factory()), 14 /** area fill instructions, either with one color (AC, four levels of transparency) */ 15 AC(new S52DrawAreaColor.Factory()), 16 /** area with repetition of pattern symbols (AP). */ 17 AP(new S52DrawAreaPattern.Factory()), 18 /** symbols for point locations—SY. */ 19 SY(new S52DrawSymbol.Factory()), 20 /** text drawing instructions with selectable font family, size, and justification */ 21 TX(new S52DrawText.Factory()), 22 /** text drawing instructions with selectable font family, size, and justification */ 23 TE(new S52DrawTextExtended.Factory()), 24 /** 25 * complex symbolization primitives (CS) provide hooks for external functions (from a 26 * dynamically loadable library) that can provide more complicated symbolizations than 27 * the look-up tables of the presentation library. Complex symbolization procedures can 28 * also take advantage on the user-changeable presentation parameters for providing more 29 * dynamic visualization. 30 */ 31 CS(new S52DrawComplex.Factory()); 32 33 final S52DrawInstruction.Factory<?> factory; 34 35 private S52DrawInstructionEnum(S52DrawInstruction.Factory<?> instructionParser) { 36 this.factory = instructionParser; 37 } 38 39 public S52DrawInstruction.Factory<?> getFactory() { 40 return factory; 41 } 42 43 @Override 44 public String toString() { 45 return name() + " class " + getFactory().getClass().getEnclosingClass().getSimpleName(); 46 } 47 }//end of enum S52DrawInstructionEnum 48 49
Labels: development, it, java
0 Comments:
Post a Comment
<< Home