All Downloads are FREE. Search and download functionalities are using the official Maven repository.

graphql.kickstart.tools.util.ParameterizedTypeImpl Maven / Gradle / Ivy

/*
 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package graphql.kickstart.tools.util;

import java.lang.reflect.MalformedParameterizedTypeException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.Objects;
import java.util.StringJoiner;

/**
 * Implementing class for ParameterizedType interface.
 */
public class ParameterizedTypeImpl implements ParameterizedType {

    private final Type[] actualTypeArguments;
    private final Class rawType;
    private final Type ownerType;

    private ParameterizedTypeImpl(
        Class rawType, Type[] actualTypeArguments, Type ownerType
    ) {
        this.actualTypeArguments = actualTypeArguments;
        this.rawType = rawType;
        this.ownerType = (ownerType != null) ? ownerType : rawType.getDeclaringClass();
        validateConstructorArguments();
    }

    private void validateConstructorArguments() {
        TypeVariable[] formals = rawType.getTypeParameters();
        // check correct arity of actual type args
        if (formals.length != actualTypeArguments.length) {
            throw new MalformedParameterizedTypeException();
        }
        for (int i = 0; i < actualTypeArguments.length; i++) {
            // TODO check actual against formal bounds
        }
    }

    /**
     * Static factory. Given a (generic) class, actual type arguments and an owner type, creates a parameterized type. This
     * class can be instantiated with a raw type that does not represent a generic type, provided the list of actual type
     * arguments is empty. If the ownerType argument is null, the declaring class of the raw type is used as the owner type.
     * 

This method throws a MalformedParameterizedTypeException * under the following circumstances: If the number of actual type arguments (i.e., the size of the array {@code * typeArgs}) does not correspond to the number of formal type arguments. If any of the actual type arguments is not an * instance of the bounds on the corresponding formal. * * @param rawType the Class representing the generic type declaration being instantiated * @param actualTypeArguments a (possibly empty) array of types representing the actual type arguments to the * parameterized type * @param ownerType the enclosing type, if known. * @return An instance of {@code ParameterizedType} * @throws MalformedParameterizedTypeException if the instantiation is invalid */ public static ParameterizedTypeImpl make(Class rawType, Type[] actualTypeArguments, Type ownerType) { return new ParameterizedTypeImpl(rawType, actualTypeArguments, ownerType); } /** * Returns an array of {@code Type} objects representing the actual type arguments to this type. *

Note that in some cases, the returned array be empty. This can occur * if this type represents a non-parameterized type nested within a parameterized type. * * @return an array of {@code Type} objects representing the actual type arguments to this type * @throws TypeNotPresentException if any of the actual type arguments refers to a non-existent type * declaration * @throws MalformedParameterizedTypeException if any of the actual type parameters refer to a parameterized type that * cannot be instantiated for any reason * @since 1.5 */ public Type[] getActualTypeArguments() { return actualTypeArguments.clone(); } /** * Returns the {@code Type} object representing the class or interface that declared this type. * * @return the {@code Type} object representing the class or interface that declared this type */ public Class getRawType() { return rawType; } /** * Returns a {@code Type} object representing the type that this type is a member of. For example, if this type is * {@code O.I}, return a representation of {@code O}. *

If this type is a top-level type, {@code null} is returned. * * @return a {@code Type} object representing the type that this type is a member of. If this type is a top-level type, * {@code null} is returned * @throws TypeNotPresentException if the owner type refers to a non-existent type declaration * @throws MalformedParameterizedTypeException if the owner type refers to a parameterized type that cannot be * instantiated for any reason */ public Type getOwnerType() { return ownerType; } /* * From the JavaDoc for java.lang.reflect.ParameterizedType * "Instances of classes that implement this interface must * implement an equals() method that equates any two instances * that share the same generic type declaration and have equal * type parameters." */ @Override public boolean equals(Object o) { if (o instanceof ParameterizedType) { // Check that information is equivalent ParameterizedType that = (ParameterizedType) o; if (this == that) { return true; } Type thatOwner = that.getOwnerType(); Type thatRawType = that.getRawType(); if (false) { // Debugging boolean ownerEquality = (ownerType == null ? thatOwner == null : ownerType.equals(thatOwner)); boolean rawEquality = (rawType == null ? thatRawType == null : rawType.equals(thatRawType)); boolean typeArgEquality = Arrays.equals(actualTypeArguments, // avoid clone that.getActualTypeArguments()); for (Type t : actualTypeArguments) { System.out.printf("\t\t%s%s%n", t, t.getClass()); } System.out.printf("\towner %s\traw %s\ttypeArg %s%n", ownerEquality, rawEquality, typeArgEquality); return ownerEquality && rawEquality && typeArgEquality; } return Objects.equals(ownerType, thatOwner) && Objects.equals(rawType, thatRawType) && Arrays.equals(actualTypeArguments, // avoid clone that.getActualTypeArguments()); } else { return false; } } @Override public int hashCode() { return Arrays.hashCode(actualTypeArguments) ^ Objects.hashCode(ownerType) ^ Objects.hashCode(rawType); } public String toString() { StringBuilder sb = new StringBuilder(); if (ownerType != null) { sb.append(ownerType.getTypeName()); sb.append("$"); if (ownerType instanceof ParameterizedTypeImpl) { // Find simple name of nested type by removing the // shared prefix with owner. sb.append(rawType.getName().replace(((ParameterizedTypeImpl) ownerType).rawType.getName() + "$", "")); } else { sb.append(rawType.getSimpleName()); } } else { sb.append(rawType.getName()); } if (actualTypeArguments != null) { StringJoiner sj = new StringJoiner(", ", "<", ">"); sj.setEmptyValue(""); for (Type t : actualTypeArguments) { sj.add(t.getTypeName()); } sb.append(sj.toString()); } return sb.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy