blob: 2a1d54e8c98320cf0fb928898fe43c7c52dcedb7 [file] [log] [blame]
/*******************************************************************************
* 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;
/*
* $RCSfile: Cast.java,v $
* $Revision: 1.3 $ $Date: 2005/08/24 20:39:08 $
*/
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();
}
}