| /******************************************************************************* |
| * 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; |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.eclipse.jdt.core.Signature; |
| |
| /** |
| * Transforms one CompositeType to another according to particular |
| * transform rules. |
| * |
| * In general, every transformation should be of the form: |
| * |
| * CompositeType transform(CompositeType original, other inputs...); |
| * |
| * @author cbateman |
| * |
| */ |
| public class TypeTransformer |
| { |
| private final static Map boxConversions = new HashMap(); |
| private final static Map unBoxConversions = new HashMap(); |
| |
| static |
| { |
| // see jdt.core.Signature or JVM link spec for more details |
| boxConversions.put("B", "Ljava.lang.Byte;"); //$NON-NLS-1$//$NON-NLS-2$ |
| boxConversions.put("C", "Ljava.lang.Character;"); //$NON-NLS-1$ //$NON-NLS-2$ |
| boxConversions.put("D", "Ljava.lang.Double;"); //$NON-NLS-1$ //$NON-NLS-2$ |
| boxConversions.put("F", "Ljava.lang.Float;"); //$NON-NLS-1$ //$NON-NLS-2$ |
| boxConversions.put("I", "Ljava.lang.Integer;"); //$NON-NLS-1$ //$NON-NLS-2$ |
| boxConversions.put("J", "Ljava.lang.Long;"); //$NON-NLS-1$ //$NON-NLS-2$ |
| boxConversions.put("S", "Ljava.lang.Short;"); //$NON-NLS-1$ //$NON-NLS-2$ |
| boxConversions.put("Z", "Ljava.lang.Boolean;"); //$NON-NLS-1$ //$NON-NLS-2$ |
| // don't box V |
| boxConversions.put("V", "V"); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| // invert hte box conversions |
| for (final Iterator it = boxConversions.keySet().iterator(); it.hasNext();) |
| { |
| final String newValue = (String) it.next(); |
| final String newKey = (String) boxConversions.get(newValue); |
| if (unBoxConversions.put(newKey, newValue) != null) |
| { |
| // if put returns non-null then we have replaced a key |
| // added on a previous iteration. This implies |
| // that box mappings are no longer one-to-one |
| throw new AssertionError("Duplicated boxing value"); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| /** |
| * @param compositeType |
| * @return an equivilent form of compositeType with all primitive type |
| * signatures converted to their fully qualified boxed equivilent but |
| * otherwise unchanged. |
| * |
| * Example: J -> Ljava.lang.Long; |
| */ |
| public static CompositeType transformBoxPrimitives(CompositeType compositeType) |
| { |
| String[] signatures = compositeType.getSignatures(); |
| String[] newsignatures = new String[signatures.length]; |
| |
| for (int i = 0; i < signatures.length; i++) |
| { |
| newsignatures[i] = transformBoxPrimitives(signatures[i]); |
| } |
| |
| return new CompositeType(newsignatures, compositeType.getAssignmentTypeMask()); |
| } |
| |
| /** |
| * Performs boxing for a single typeSignature string |
| * @param curSignature |
| * @return the boxed signature |
| */ |
| public static String transformBoxPrimitives(final String curSignature) |
| { |
| String newSignature = curSignature; |
| |
| // first determine if we have a type or method signature |
| try |
| { |
| int kind = Signature.getTypeSignatureKind(curSignature); |
| |
| // interested in base types, since these need boxing |
| if (kind == Signature.BASE_TYPE_SIGNATURE) |
| { |
| // grab the box for the primitive |
| newSignature = (String) boxConversions.get(curSignature); |
| } |
| else if (kind == Signature.ARRAY_TYPE_SIGNATURE) |
| { |
| // check if it's array of primitives |
| final String baseType = Signature.getElementType(curSignature); |
| |
| if (Signature.getTypeSignatureKind(baseType) == Signature.BASE_TYPE_SIGNATURE) |
| { |
| // it is, so box it |
| final String newBaseType = (String) boxConversions.get(baseType); |
| final int numBraces = Signature.getArrayCount(curSignature); |
| newSignature = ""; //$NON-NLS-1$ |
| for (int j = 0; j < numBraces; j++) |
| { |
| newSignature += "["; //$NON-NLS-1$ |
| } |
| |
| newSignature += newBaseType; |
| } |
| } |
| } |
| catch (IllegalArgumentException e) |
| { |
| // signature was not a type signature, so must be a method sig |
| // do nothing: don't box method types |
| } |
| |
| return newSignature; |
| } |
| |
| /** |
| * Performs the exact inverse of transformBoxPrimitives -- takes all |
| * boxing type signatures and replaces them with their primitive equivilent |
| * @param compositeType |
| * @return a new composite with all boxed primitives unboxed |
| */ |
| public static CompositeType transformUnboxPrimitives(CompositeType compositeType) |
| { |
| String[] signatures = compositeType.getSignatures(); |
| String[] newsignatures = new String[signatures.length]; |
| |
| for (int i = 0; i < signatures.length; i++) |
| { |
| newsignatures[i] = transformUnboxPrimitives(signatures[i]); |
| } |
| |
| return new CompositeType(newsignatures, compositeType.getAssignmentTypeMask()); |
| } |
| |
| /** |
| * Performs unboxing for a single typeSignature string |
| * |
| * @param typeSignature |
| * @return the transformed signature |
| */ |
| public static String transformUnboxPrimitives(final String typeSignature) |
| { |
| String newSignature = typeSignature; |
| |
| // first determine if we have a type or method signature |
| try |
| { |
| int kind = Signature.getTypeSignatureKind(typeSignature); |
| |
| // interested in class types, since these need boxing |
| if (kind == Signature.CLASS_TYPE_SIGNATURE) |
| { |
| // grab the box for the primitive |
| String checkForUnbox = (String) unBoxConversions.get(typeSignature); |
| |
| if (checkForUnbox != null) |
| { |
| newSignature = checkForUnbox; |
| } |
| } |
| else if (kind == Signature.ARRAY_TYPE_SIGNATURE) |
| { |
| // check if it's array of objects |
| final String baseType = Signature.getElementType(typeSignature); |
| |
| if (Signature.getTypeSignatureKind(baseType) == Signature.CLASS_TYPE_SIGNATURE) |
| { |
| // it is, so unbox it |
| final String newBaseTypeCandidate = (String) unBoxConversions.get(baseType); |
| |
| if (newBaseTypeCandidate != null) |
| { |
| final int numBraces = Signature.getArrayCount(typeSignature); |
| newSignature = ""; //$NON-NLS-1$ |
| for (int j = 0; j < numBraces; j++) |
| { |
| newSignature += "["; //$NON-NLS-1$ |
| } |
| |
| newSignature += newBaseTypeCandidate; |
| } |
| } |
| } |
| } |
| catch (IllegalArgumentException e) |
| { |
| // signature was not a type signature, so must be a method sig |
| // do nothing: don't box method types |
| } |
| |
| return newSignature; |
| } |
| } |