blob: 5f2aff49212dd825a51015394f55cf699210608e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 Oracle Corporation.
* 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:
* Cameron Bateman/Oracle - initial API and implementation
*
********************************************************************************/
package org.eclipse.jst.jsf.common.internal.types;
/**
* Follows type coercion rules codified in section JSP.2.8 of the
* JSP 2.0 Specification.
*
* This class operates on CompositeType's and returns raw
* Java signatures for the single resulting type coercion.
*
* The rules are stretched a little bit since JSP.2.8 defines how to
* coerce an *instance* A to a type T. But since we have no runtime instances,
* only their types, we approximate by taking what we know about the type of A
* and coercing it T as best we can.
*
* Also, whereas the spec says to throw errors when coercion is not possible,
* we have two cases:
*
* 1) We can determine definitively that there is no coercion
* 2) We cannot determine whether there is or isn't a coercion
*
* In case 1, we always throw an exception. In case 2, we return null to indicate
* "indeterminate" result, rather than error.
*
* @author cbateman
*
*/
public class CompositeTypeCoercer
{
/**
* This method follows JSP.2.8.3 except that rather than returning a specific
* type that has been coerced to, it determines the most exact possible type
* that typeOfA can be coerced to, to be number compatible. The caller must
* decide what do with the return value compared to the type (N in the spec)
* that they want to coerce to.
*
* @param typeOfA
* @return a new signature for the type of A after being coerced to a Number
* @throws TypeCoercionException if A can definitively not be coerced to
* a number
*/
public static String coerceToNumber(final CompositeType typeOfA)
throws TypeCoercionException
{
String coercedType = null;
boolean errorDetected = true; // assume error: only false if we
// find a member of typeOfA that
// coerces to number
// JSP.2.8.1 -- auto-box primitives
final CompositeType boxedTypeOfA =
TypeTransformer.transformBoxPrimitives(typeOfA);
final boolean[] typesigs = boxedTypeOfA.getIsTypeSignature();
// iterate through all of the signatures that represent types
// and find at least one that can be coerced to a number
for (int i = 0; i < typesigs.length; i++)
{
if (typesigs[i])
{
try
{
final String testType =
TypeCoercer.coerceToNumber(boxedTypeOfA.getSignatures()[i]);
if (testType != null)
{
// if we have already found a coercible type, then
// we need to return null, since we have a conflict that
// we don't know how to resolve to a type??????
if (coercedType != null)
{
return null;
}
coercedType = testType;
}
errorDetected = false; // we have found a number coercion or indeterminate
}
catch (TypeCoercionException tce)
{
// do nothing: so far error still detected
}
}
}
// we have three choices:
// 1: if errorDetected was never cleared, we definitely never found
// a coerceable type, so throw exception
if (errorDetected)
{
throw new TypeCoercionException();
}
// otherwise the flag was cleared return what we found
if (coercedType != null)
{
// need to unbox per JSP.2.8.1
coercedType =
TypeTransformer.transformUnboxPrimitives(coercedType);
}
return coercedType;
}
// public static String coerceToBoolean(CompositeType compositeType)
// {
//
// }
}