Package org.eclipse.persistence.jpa.jpql.spi.java

Source Code of org.eclipse.persistence.jpa.jpql.spi.java.JavaTypeDeclaration

/*******************************************************************************
* Copyright (c) 2006, 2013 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.spi.java;

import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.spi.IType;
import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
import org.eclipse.persistence.jpa.jpql.spi.ITypeRepository;

/**
* The concrete implementation of {@link ITypeDeclaration} that is wrapping the representation
* of the declaration description of a type.
*
* @see org.eclipse.persistence.jpa.jpql.spi.IMapping IMapping
* @see IType
*
* @version 2.4
* @since 2.3
* @author Pascal Filion
*/
@SuppressWarnings("nls")
public class JavaTypeDeclaration implements ITypeDeclaration {

  /**
   * Determines whether the type declaration represents an array.
   */
  private boolean array;

  /**
   * The actual type that contains the generics, if any is present.
   */
  private Object genericType;

  /**
   * The cached {@link ITypeDeclaration ITypeDeclarations} representing the generics of the {@link
   * Type}.
   */
  private ITypeDeclaration[] genericTypes;

  /**
   * The external form of the Java type.
   */
  private final IType type;

  /**
   * The repository of {@link IType ITypes}.
   */
  private ITypeRepository typeRepository;

  /**
   * Creates a new <code>JavaTypeDeclaration</code>.
   *
   * @param typeRepository The repository of {@link IType ITypes}
   * @param type The external form of the Java type
   * @param genericType The actual type that contains the generics, if any is present
   * @param array Determines whether the type declaration represents an array
   */
  public JavaTypeDeclaration(ITypeRepository typeRepository,
                             IType type,
                             Object genericType,
                             boolean array) {

    super();
    this.type           = type;
    this.array          = array;
    this.genericType    = genericType;
    this.typeRepository = typeRepository;
  }

  protected String buildArrayTypeName(String arrayTypeName) {

    StringBuilder sb = new StringBuilder();
    int index = arrayTypeName.indexOf('[');
    int dimensionality = (arrayTypeName.length() - index) / 2;
    String typeName = arrayTypeName.substring(0, index);

    while (--dimensionality >= 0) {
      sb.append("[");
    }

    String elementType = elementType(typeName);

    sb.append(elementType);
    sb.append(typeName);

    if (elementType.equals("L")) {
      sb.append(";");
    }

    return sb.toString();
  }

  protected ITypeDeclaration[] buildParameterTypes() {

    List<ITypeDeclaration> parameterTypes = new ArrayList<ITypeDeclaration>();

    // Example: Class<T>
    if (genericType instanceof ParameterizedType) {
      ParameterizedType parameterizedType = (ParameterizedType) genericType;
      for (Type type : parameterizedType.getActualTypeArguments()) {
        ITypeDeclaration typeParameter = buildTypeDeclaration(type);
        parameterTypes.add(typeParameter);
      }
    }
    // T[]
    else if (genericType instanceof GenericArrayType) {
      GenericArrayType genericArrayType = (GenericArrayType) genericType;
      parameterTypes.add(buildTypeDeclaration(genericArrayType.getGenericComponentType()));
    }
    // Example: Class
    else if (genericType.getClass() == Class.class) {
      ITypeDeclaration typeParameter = buildTypeDeclaration((Class<?>) genericType);
      parameterTypes.add(typeParameter);
    }
    // Example: <K, V>
    else if (genericType.getClass() == Class[].class) {
      for (Class<?> javaType : ((Class<?>[]) genericType)) {
        ITypeDeclaration typeParameter = buildTypeDeclaration(javaType);
        parameterTypes.add(typeParameter);
      }
    }
    // Example: <K, V>
    else if (genericType.getClass() == IType[].class) {
      for (IType type : ((IType[]) genericType)) {
        ITypeDeclaration typeParameter = new JavaTypeDeclaration(typeRepository, type, null, false);
        parameterTypes.add(typeParameter);
      }
    }

    return parameterTypes.toArray(new ITypeDeclaration[parameterTypes.size()]);
  }

  protected JavaTypeDeclaration buildTypeDeclaration(Class<?> javaType) {
    return new JavaTypeDeclaration(
      typeRepository,
      getType(javaType),
      null,
      javaType.isArray()
    );
  }

  protected JavaTypeDeclaration buildTypeDeclaration(Object genericType) {

    // <T1, ..., Tn>
    if (genericType instanceof ParameterizedType) {
      ParameterizedType parameterizedType = (ParameterizedType) genericType;
      return buildTypeDeclaration(parameterizedType.getRawType());
    }

    // <T>
    if (genericType instanceof TypeVariable) {
      TypeVariable<?> typeVariable = (TypeVariable<?>) genericType;
      for (Type type : typeVariable.getBounds()) {
        return buildTypeDeclaration(type);
      }
      return buildTypeDeclaration(Object.class);
    }

    // ?
    if (genericType instanceof WildcardType) {
      WildcardType wildcardType = (WildcardType) genericType;
      for (Type type : wildcardType.getUpperBounds()) {
        return buildTypeDeclaration(type);
      }
      return buildTypeDeclaration(Object.class);
    }

    // T[]
    if (genericType instanceof GenericArrayType) {
      GenericArrayType genericArrayType = (GenericArrayType) genericType;
      String arrayTypeName = buildArrayTypeName(genericArrayType.toString());
      IType arrayType = typeRepository.getType(arrayTypeName);

      return new JavaTypeDeclaration(
        typeRepository,
        arrayType,
        genericArrayType.getGenericComponentType(),
        true
      );
    }

    return buildTypeDeclaration((Class<?>) genericType);
  }

  protected String elementType(String typeName) {

    if (typeName.equals("boolean")) return "Z";
    if (typeName.equals("byte"))    return "B";
    if (typeName.equals("char"))    return "C";
    if (typeName.equals("double"))  return "D";
    if (typeName.equals("float"))   return "F";
    if (typeName.equals("int"))     return "I";
    if (typeName.equals("long"))    return "J";
    if (typeName.equals("short"))   return "S";

    return "L";
  }

  /**
   * {@inheritDoc}
   */
  public int getDimensionality() {
    if (array) {
      String name = type.getName();
      int index = 0;
      while (name.charAt(index) == '[') {
        index++;
      }
      return index;
    }
    return 0;
  }

  /**
   * {@inheritDoc}
   */
  public IType getType() {
    return type;
  }

  protected IType getType(Class<?> type) {
    return typeRepository.getType(type);
  }

  /**
   * {@inheritDoc}
   */
  public ITypeDeclaration[] getTypeParameters() {
    if (genericTypes == null) {
      if (genericType == null) {
        genericTypes = new ITypeDeclaration[0];
      }
      else {
        genericTypes = buildParameterTypes();
      }
    }
    return genericTypes;
  }

  /**
   * {@inheritDoc}
   */
  public boolean isArray() {
    return array;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    return (genericType != null) ? genericType.toString() : type.toString();
  }
}
TOP

Related Classes of org.eclipse.persistence.jpa.jpql.spi.java.JavaTypeDeclaration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.