| /******************************************************************************* |
| * 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) |
| // { |
| // |
| // } |
| |
| } |