blob: 4a88fa5be4c404675eb3765ccea5f6afe6ca2458 [file] [log] [blame]
/*
* Copyright (c) 2006, 2020 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 v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// 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();
}
}