/******************************************************************************* * Copyright (c) 2006, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation * ******************************************************************************/ package org.eclipse.persistence.jpa.jpql.tools; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Timestamp; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.Map; import org.eclipse.persistence.jpa.jpql.tools.spi.IType; import org.eclipse.persistence.jpa.jpql.tools.spi.ITypeDeclaration; import org.eclipse.persistence.jpa.jpql.tools.spi.ITypeRepository; /** * This helper contains methods related to {@link IType} and can perform equivalency checks. * * @version 2.4 * @since 2.3 * @author Pascal Filion */ public final class TypeHelper { /** * The {@link IType} for the <code>Object</code> class. */ private IType objectType; /** * The {@link IType} for the <code>String</code> class. */ private IType stringType; /** * The external form of the provider of {@link IType ITypes}. */ private final ITypeRepository typeRepository; /** * The {@link IType} representing an unknown type. */ private IType unknownType; /** * Creates a new <code>TypeHelper</code>. * * @param typeRepository The repository used to retrieve the types */ public TypeHelper(ITypeRepository typeRepository) { super(); this.typeRepository = typeRepository; } /** * Retrieves the {@link IType} for {@link BigDecimal}. * * @return The external form of the <code>BigDecimal</code> class */ public IType bigDecimal() { return getType(BigDecimal.class); } /** * Retrieves the {@link IType} for {@link BigInteger}. * * @return The external form of the <code>BigInteger</code> class */ public IType bigInteger() { return getType(BigInteger.class); } /** * Retrieves the {@link IType} for {@link Boolean}. * * @return The external form of the <code>Boolean</code> class */ public IType booleanType() { return getType(Boolean.class); } /** * Retrieves the {@link IType} for {@link Byte}. * * @return The external form of the <code>Byte</code> class */ public IType byteType() { return getType(Byte.class); } /** * Retrieves the {@link IType} for {@link Character}. * * @return The external form of the <code>Character</code> class */ public IType characterType() { return getType(Character.class); } /** * Retrieves the {@link IType} for {@link Collection}. * * @return The external form of the <code>Collection</code> class */ public IType collectionType() { return getType(Collection.class); } /** * Converts the given {@link IType}, if it's representing a primitive type, into the class of the * same type. * * @param type Type to possibly convert from the primitive into the class * @return The given {@link IType} if it's not a primitive type otherwise the primitive type will * have been converted into the class of that primitive */ public IType convertPrimitive(IType type) { // byte IType newType = toByteType(type); if (newType != type) { return newType; } // short newType = toShortType(type); if (newType != type) { return newType; } // int newType = toIntegerType(type); if (newType != type) { return newType; } // long newType = longType(type); if (newType != type) { return newType; } // float newType = toFloatType(type); if (newType != type) { return newType; } // double newType = toDoubleType(type); if (newType != type) { return newType; } // boolean newType = toBooleanType(type); if (newType != type) { return newType; } return type; } /** * Retrieves the {@link IType} for {@link Date}. * * @return The external form of the <code>Date</code> class */ public IType dateType() { return getType(Date.class); } /** * Retrieves the {@link IType} for {@link Double}. * * @return The external form of the <code>Double</code> class */ public IType doubleType() { return getType(Double.class); } /** * Retrieves the {@link IType} for {@link Enum}. * * @return The external form of the <code>Enum</code> class */ public IType enumType() { return getType(Enum.class); } /** * Retrieves the {@link IType} for {@link Float}. * * @return The external form of the <code>Float</code> class */ public IType floatType() { return getType(Float.class); } /** * Returns the {@link IType} of the given Java type. * * @param type The Java type for which its external form will be returned * @return The {@link IType} representing the given Java type */ public IType getType(Class<?> type) { return typeRepository.getType(type); } /** * Retrieves the external class for the given fully qualified class name. * * @param typeName The fully qualified class name of the class to retrieve * @return The external form of the class to retrieve */ public IType getType(String typeName) { return typeRepository.getType(typeName); } /** * Returns the {@link ITypeRepository} used by this helper * * @return The external form of the provider of {@link IType ITypes}. */ public ITypeRepository getTypeRepository() { return typeRepository; } /** * Retrieves the {@link IType} for {@link Integer}. * * @return The external form of the <code>Integer</code> class */ public IType integerType() { return getType(Integer.class); } /** * Determines whether the given {@link IType} is a {@link Boolean}. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} is a {@link Boolean}; <code>false</code> * otherwise */ public boolean isBooleanType(IType type) { return type.equals(booleanType()); } /** * Determines whether the given {@link IType} is an instance of {@link Collection}. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} is an instance of {@link Collection}; * <code>false</code> otherwise */ public boolean isCollectionType(IType type) { return type.isAssignableTo(collectionType()); } /** * Determines whether the given {@link IType} is a {@link Date}, {@link Timestamp} or * {@link Calendar}. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} is a {@link Date}, {@link Timestamp} or * {@link Calendar} */ public boolean isDateType(IType type) { return type.equals(dateType()) || type.equals(timestampType()) || type.equals(getType(Calendar.class)); } /** * Determines whether the given {@link IType} is an instance of {@link Enum}. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} is an instance of {@link Enum}; * <code>false</code> otherwise */ public boolean isEnumType(IType type) { return type.isAssignableTo(enumType()); } /** * Determines whether the given {@link IType} is an instance of a floating type, which is either * <code>Float</code>, <code>Double</code>, float or double. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} is a floating type; <code>false</code> * otherwise */ public boolean isFloatingType(IType type) { return type.equals(floatType()) || type.equals(doubleType()) || type.equals(primitiveFloat()) || type.equals(primitiveDouble()); } /** * Determines whether the given {@link IType} is an instance of a floating type, which is either * <code>Integer</code>, <code>Long</code>, int or float. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} is a integral type; <code>false</code> * otherwise */ public boolean isIntegralType(IType type) { return type.equals(integerType()) || type.equals(longType()) || type.equals(shortType()) || type.equals(characterType()) || type.equals(primitiveInteger()) || type.equals(primitiveLong()) || type.equals(primitiveShort()) || type.equals(primitiveChar()); } /** * Determines whether the given {@link IType} is an instance of {@link Map}. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} is an instance of {@link Map}; * <code>false</code> otherwise */ public boolean isMapType(IType type) { return type.isAssignableTo(mapType()); } /** * Determines whether the given {@link IType} is an instance of {@link Number}. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} is an instance of {@link Number}; * <code>false</code> otherwise */ public boolean isNumericType(IType type) { return type.isAssignableTo(numberType()); } /** * Determines whether the given {@link IType} is the external form of {@link Object}. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} is the external form of {@link Object} */ public boolean isObjectType(IType type) { return type.equals(objectType()); } /** * Determines whether the given {@link IType} represents a primitive type. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} represents a primitive; <code>false</code> * otherwise */ public boolean isPrimitiveType(IType type) { return type == primitiveBoolean() || type == primitiveByte() || type == primitiveDouble() || type == primitiveFloat() || type == primitiveInteger() || type == primitiveLong() || type == primitiveShort(); } /** * Determines whether the given {@link IType} represents the <code>String</code> class. * * @param type The type to check it's assignability * @return <code>true</code> if the given {@link IType} represents the <code>String</code> class; * <code>false</code> otherwise */ public boolean isStringType(IType type) { return type.equals(stringType()); } /** * Retrieves the {@link IType} for {@link Long}. * * @return The external form of the <code>Long</code> class */ public IType longType() { return getType(Long.class); } /** * Converts the given {@link IType}, if it's the primitive long, into the <code>Long</code> type. * * @param type The {@link IType} to possibly convert * @return The given type if it's not the primitive long or the {@link IType} for the class * <code>Long</code> */ public IType longType(IType type) { if (type.equals(primitiveLong())) { return longType(); } return type; } /** * Retrieves the {@link IType} for {@link Map}. * * @return The external form of the <code>Map</code> class */ public IType mapType() { return getType(Map.class); } /** * Retrieves the {@link IType} for {@link Number}. * * @return The external form of the <code>Number</code> class */ public IType numberType() { return getType(Number.class); } /** * Retrieves the {@link IType} for {@link Object}. * * @return The external form of the <code>Object</code> class */ public IType objectType() { if (objectType == null) { objectType = getType(Object.class); } return objectType; } /** * Returns the {@link ITypeDeclaration} for the {@link IType} representing the <code>Object</code> * class. * * @return The {@link ITypeDeclaration} of the <code>Object</code> class */ public ITypeDeclaration objectTypeDeclaration() { return objectType().getTypeDeclaration(); } /** * Retrieves the {@link IType} for the primitive boolean. * * @return The external form of the primitive boolean */ public IType primitiveBoolean() { return getType(Boolean.TYPE); } /** * Retrieves the {@link IType} for the primitive byte. * * @return The external form of the primitive byte */ public IType primitiveByte() { return getType(Byte.TYPE); } /** * Retrieves the {@link IType} for the primitive char. * * @return The external form of the primitive char */ public IType primitiveChar() { return getType(Character.TYPE); } /** * Retrieves the {@link IType} for the primitive double. * * @return The external form of the primitive double */ public IType primitiveDouble() { return getType(Double.TYPE); } /** * Retrieves the {@link IType} for the primitive float. * * @return The external form of the primitive float */ public IType primitiveFloat() { return getType(Float.TYPE); } /** * Retrieves the {@link IType} for the primitive int. * * @return The external form of the primitive int */ public IType primitiveInteger() { return getType(Integer.TYPE); } /** * Retrieves the {@link IType} for the primitive long. * * @return The external form of the primitive long */ public IType primitiveLong() { return getType(Long.TYPE); } /** * Retrieves the {@link IType} for the primitive short. * * @return The external form of the primitive short */ public IType primitiveShort() { return getType(Short.TYPE); } /** * Retrieves the {@link IType} for {@link Short}. * * @return The external form of the <code>Short</code> class */ public IType shortType() { return getType(Short.class); } /** * Retrieves the {@link IType} for {@link String}. * * @return The external form of the <code>String</code> class */ public IType stringType() { if (stringType == null) { stringType = getType(String.class); } return stringType; } /** * Retrieves the {@link IType} for {@link Timestamp}. * * @return The external form of the <code>Timestamp</code> class */ public IType timestampType() { return getType(Timestamp.class); } /** * Converts the given {@link IType}, if it's the primitive boolean, into the <code>Boolean</code> * type. * * @param type The {@link IType} to possibly convert * @return The given type if it's not the primitive boolean or the {@link IType} for the class * <code>Boolean</code> */ public IType toBooleanType(IType type) { if (type.equals(primitiveBoolean())) { return booleanType(); } return type; } /** * Converts the given {@link IType}, if it's the primitive byte, into the <code>Byte</code> * type. * * @param type The {@link IType} to possibly convert * @return The given type if it's not the primitive byte or the {@link IType} for the class * <code>Byte</code> */ public IType toByteType(IType type) { if (type.equals(primitiveByte())) { return byteType(); } return type; } /** * Converts the given {@link IType}, if it's the primitive double, into the <code>Double</code> * type. * * @param type The {@link IType} to possibly convert * @return The given type if it's not the primitive double or the {@link IType} for the class * <code>Double</code> */ public IType toDoubleType(IType type) { if (type.equals(primitiveDouble())) { return doubleType(); } return type; } /** * Converts the given {@link IType}, if it's the primitive float, into the <code>Float</code> * type. * * @param type The {@link IType} to possibly convert * @return The given type if it's not the primitive float or the {@link IType} for the class * <code>Float</code> */ public IType toFloatType(IType type) { if (type.equals(primitiveFloat())) { return floatType(); } return type; } /** * Converts the given {@link IType}, if it's the primitive int, into the <code>Integer</code> * type. * * @param type The {@link IType} to possibly convert * @return The given type if it's not the primitive int or the {@link IType} for the class * <code>Integer</code> */ public IType toIntegerType(IType type) { if (type.equals(primitiveInteger())) { return integerType(); } return type; } /** * Converts the given {@link IType}, if it's the primitive short, into the <code>Short</code> * type. * * @param type The {@link IType} to possibly convert * @return The given type if it's not the primitive short or the {@link IType} for the class * <code>Short</code> */ public IType toShortType(IType type) { if (type.equals(primitiveShort())) { return shortType(); } return type; } /** * Retrieves the {@link IType} that represents an unknown type. * * @return The external form of an unknown type */ public IType unknownType() { if (unknownType == null) { unknownType = getType(IType.UNRESOLVABLE_TYPE); } return unknownType; } /** * Returns the {@link ITypeDeclaration} for the {@link IType} representing an unknown type. * * @return The {@link ITypeDeclaration} of the unknown type */ public ITypeDeclaration unknownTypeDeclaration() { return unknownType().getTypeDeclaration(); } }