@SuppressWarnings({ "unchecked"})
    @Nullable
    protected <T> T newInstance(Class<T> type, Type genericType, Object parent, Object propKey,
            PathMetadata metadata) {
        Expression<?> path;
        Object rv;

        if (String.class.equals(type)) {
            path = pathFactory.createStringPath(metadata);
            // null is used as a return value to block method invocations on Strings
            rv = null;

        } else if (Integer.class.equals(type) || int.class.equals(type)) {
            path = pathFactory.createNumberPath(Integer.class, metadata);
            rv = RETURN_VALUE;

        } else if (Byte.class.equals(type) || byte.class.equals(type)) {
            path = pathFactory.createNumberPath(Byte.class, metadata);
            rv = (byte) RETURN_VALUE;

        } else if (java.util.Date.class.equals(type)) {
            path = pathFactory.createDateTimePath((Class) type, metadata);
            rv = new Date();

        } else if (java.sql.Timestamp.class.equals(type)) {
            path = pathFactory.createDateTimePath((Class) type, metadata);
            rv = new Timestamp(System.currentTimeMillis());

        } else if (java.sql.Date.class.equals(type)) {
            path = pathFactory.createDatePath((Class) type, metadata);
            rv = new java.sql.Date(System.currentTimeMillis());

        } else if (java.sql.Time.class.equals(type)) {
            path = pathFactory.createTimePath((Class) type, metadata);
            rv = new java.sql.Time(System.currentTimeMillis());

        } else if (Long.class.equals(type) || long.class.equals(type)) {
            path = pathFactory.createNumberPath(Long.class, metadata);
            rv = (long) RETURN_VALUE;

        } else if (Short.class.equals(type) || short.class.equals(type)) {
            path = pathFactory.createNumberPath(Short.class, metadata);
            rv = (short) RETURN_VALUE;

        } else if (Double.class.equals(type) || double.class.equals(type)) {
            path = pathFactory.createNumberPath(Double.class, metadata);
            rv = (double) RETURN_VALUE;

        } else if (Float.class.equals(type) || float.class.equals(type)) {
            path = pathFactory.createNumberPath(Float.class, metadata);
            rv = (float) RETURN_VALUE;

        } else if (BigInteger.class.equals(type)) {
            path = pathFactory.createNumberPath((Class) type, metadata);
            rv = BigInteger.valueOf(RETURN_VALUE);

        } else if (BigDecimal.class.equals(type)) {
            path = pathFactory.createNumberPath((Class) type, metadata);
            rv = BigDecimal.valueOf(RETURN_VALUE);

        } else if (Boolean.class.equals(type) || boolean.class.equals(type)) {
            path = pathFactory.createBooleanPath(metadata);
            rv = Boolean.TRUE;

        } else if (typeSystem.isMapType(type)) {
            Class<Object> keyType = (Class) ReflectionUtils.getTypeParameter(genericType, 0);
            Class<Object> valueType = (Class) ReflectionUtils.getTypeParameter(genericType, 1);
            path = pathFactory.createMapPath(keyType, valueType, metadata);
            rv = aliasFactory.createAliasForProperty(type, path);

        } else if (typeSystem.isListType(type)) {
            Class<Object> elementType = (Class) ReflectionUtils.getTypeParameter(genericType, 0);
            path = pathFactory.createListPath(elementType, metadata);
            rv = aliasFactory.createAliasForProperty(type, path);

        } else if (typeSystem.isSetType(type)) {
            Class<?> elementType = ReflectionUtils.getTypeParameterAsClass(genericType, 0);
            path = pathFactory.createSetPath(elementType, metadata);
            rv = aliasFactory.createAliasForProperty(type, path);

        } else if (typeSystem.isCollectionType(type)) {
            Class<?> elementType = ReflectionUtils.getTypeParameterAsClass(genericType, 0);
            path = pathFactory.createCollectionPath(elementType, metadata);
            rv = aliasFactory.createAliasForProperty(type, path);

        } else if (Enum.class.isAssignableFrom(type)) {
            path = pathFactory.createEnumPath((Class) type, metadata);
            rv = type.getEnumConstants()[0];

        } else if (type.isArray()) {
            path = pathFactory.createArrayPath((Class) type, metadata);
            rv = Array.newInstance(type.getComponentType(), 5);

        } else {
            if (Number.class.isAssignableFrom(type)) {
                path = pathFactory.createNumberPath((Class) type, metadata);
            } else if (Comparable.class.isAssignableFrom(type)) {
                path = pathFactory.createComparablePath((Class) type, metadata);
            } else {
                path = pathFactory.createEntityPath(type, metadata);
            }
            if (!Modifier.isFinal(type.getModifiers())) {
                rv = aliasFactory.createAliasForProperty(type, path);
            } else {
                rv = null;
            }
        }

        if (rv == null) {
            propToObj.remove(propKey);
        } else {
            propToObj.put(propKey, rv);
        }
        propToExpr.put(propKey, path);
        return (T) rv;
    }
{@code PropertyAccessInvocationHandler} is the main InvocationHandler class for the
CGLIB alias proxies

@author tiwe
querydsl-core/src/main/java/com/querydsl/core/alias/PropertyAccessInvocationHandler.java