/******************************************************************************* * Copyright (c) 2001, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jem.internal.proxy.initParser; /* */ import java.util.HashMap; public class Cast extends Expression { protected static final int BYTE_TYPE = 0; protected static final int SHORT_TYPE = 1; protected static final int INT_TYPE = 2; protected static final int LONG_TYPE = 3; protected static final int FLOAT_TYPE = 4; protected static final int DOUBLE_TYPE = 5; protected static final HashMap sTypeLookup; static { sTypeLookup = new HashMap(6); sTypeLookup.put(Byte.TYPE, new Integer(BYTE_TYPE)); sTypeLookup.put(Short.TYPE, new Integer(SHORT_TYPE)); sTypeLookup.put(Integer.TYPE, new Integer(INT_TYPE)); sTypeLookup.put(Long.TYPE, new Integer(LONG_TYPE)); sTypeLookup.put(Float.TYPE, new Integer(FLOAT_TYPE)); sTypeLookup.put(Double.TYPE, new Integer(DOUBLE_TYPE)); } protected Static fCastType; protected boolean fIsClosed = false; public Cast(Static castType, ClassLoader aClassLoader) { fCastType = castType; fClassLoader = aClassLoader; } public boolean isPrimitive() throws Exception { return getTypeClass().isPrimitive(); } /** * The type of a Cast expression is the type of the cast type. */ public Class getTypeClass() throws Exception { return fCastType.getTypeClass(); } public boolean isComplete() { return currentExpression != null && currentExpression.isComplete(); } /** * If the type is primitive, then we need to * convert the value, otherwise just pass * the value on. * * This is important for primitives because if your * entire initialization string was simply "(short) 3" * then a Short value must be returned so that the * correct kind of primitive proxy is created. */ public Object evaluate() throws Exception { if (getTypeClass() == currentExpression.getTypeClass()) return currentExpression.evaluate(); // They're the same, so just return it. if (getTypeClass().isPrimitive()) { // Can only cast a primitive to a primitive, except null can't be cast to a primitive. if (!currentExpression.getTypeClass().isPrimitive() || currentExpression.getTypeClass() == Void.TYPE) throw new EvaluationException(new ClassCastException(currentExpression.getTypeClass().getName())); // boolean only allows boolean cast. if (fCastType.getTypeClass() == Boolean.TYPE || currentExpression.getTypeClass() == Boolean.TYPE) throw new EvaluationException(new ClassCastException(currentExpression.getTypeClass().getName())); if (fCastType.getTypeClass() == Character.TYPE) { // So we have either a Character or a number as the value. Cast that. return new Character((char) ((Number) currentExpression.evaluate()).intValue()); } else { Number value = null; // See if the value is character or a number. if (currentExpression.getTypeClass() == Character.TYPE) value = new Integer(((Character) currentExpression.evaluate()).charValue()); else value = (Number) currentExpression.evaluate(); switch (((Integer) sTypeLookup.get(fCastType.getTypeClass())).intValue()) { case BYTE_TYPE: return new Byte(value.byteValue()); case SHORT_TYPE: return new Short(value.shortValue()); case INT_TYPE: return new Integer(value.intValue()); case LONG_TYPE: return new Long(value.longValue()); case FLOAT_TYPE: return new Float(value.floatValue()); case DOUBLE_TYPE: return new Double(value.doubleValue()); default: return null; // Shouldn't occur. Just satisifies compiler. } } } else return currentExpression.evaluate(); } /** * A cast expression always pushes onto the cast value */ public Expression push(char[] token , char tokenDelimiter) { // If we don't have a class yet then we are within the statement to try and deterine the type being cast to if(fCastType.getPrimitiveTypeClass() == null && !fIsClosed){ fCastType.push(token,tokenDelimiter); // If the type was completed and we have a ) then close us if(fCastType.getPrimitiveTypeClass() != null && tokenDelimiter == DelimiterCloseParen){ fIsClosed = true; } return this; } if (!fIsClosed) { // The cast is not closed, but we have a static class. This class must therefore keep processing the tokens as it could be a method or message send Expression result = fCastType.push(token,tokenDelimiter); result.parenthesisLevel++; return result; } // If we have no expression push onto the cast value if(currentExpression == null){ currentExpression = new Statement(fClassLoader); currentExpression = currentExpression.push(token,tokenDelimiter); return this; } Expression result = currentExpression.push(token, tokenDelimiter); // If the result if a push then push the stack if ( result.isComplete() ) { popExpressionStack(); } else if ( result != currentExpression ) { pushExpressionStack(result); } return this; } public String toString(){ StringBuffer buffer = new StringBuffer(); buffer.append("Cast("); //$NON-NLS-1$ if (fCastType != null){ buffer.append(fCastType.toString()); } else { buffer.append("???"); //$NON-NLS-1$ } buffer.append(") "); //$NON-NLS-1$ if ( currentExpression != null){ buffer.append(currentExpression.toString()); } else { buffer.append("???"); //$NON-NLS-1$ } return buffer.toString(); } /* (non-Javadoc) * @see org.eclipse.jem.internal.proxy.core.initParser.Expression#getTypeClassName() */ protected String getTypeClassName() { return fCastType.getTypeClassName(); } }