| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.bval.util; |
| |
| import java.lang.annotation.Annotation; |
| import java.lang.reflect.AnnotatedElement; |
| import java.lang.reflect.AnnotatedParameterizedType; |
| import java.lang.reflect.AnnotatedType; |
| import java.lang.reflect.AnnotatedTypeVariable; |
| import java.lang.reflect.AnnotatedWildcardType; |
| import java.lang.reflect.ParameterizedType; |
| import java.lang.reflect.Type; |
| import java.lang.reflect.TypeVariable; |
| import java.lang.reflect.WildcardType; |
| import java.util.Optional; |
| import java.util.stream.Stream; |
| |
| public class EmulatedAnnotatedType<T extends Type> implements AnnotatedType { |
| private static class Parameterized extends EmulatedAnnotatedType<ParameterizedType> |
| implements AnnotatedParameterizedType { |
| |
| Parameterized(ParameterizedType wrapped) { |
| super(wrapped); |
| } |
| |
| @Override |
| public AnnotatedType[] getAnnotatedActualTypeArguments() { |
| return wrapArray(wrapped.getActualTypeArguments()); |
| } |
| |
| //@Override - Java8 build compatibility |
| public AnnotatedType getAnnotatedOwnerType() { |
| return null; |
| } |
| } |
| |
| private static class Variable extends EmulatedAnnotatedType<TypeVariable<?>> implements AnnotatedTypeVariable { |
| |
| Variable(TypeVariable<?> wrapped) { |
| super(wrapped); |
| } |
| |
| @Override |
| public AnnotatedType[] getAnnotatedBounds() { |
| return wrapped.getAnnotatedBounds(); |
| } |
| |
| //@Override - Java8 build compatibility |
| public AnnotatedType getAnnotatedOwnerType() { |
| return null; |
| } |
| } |
| |
| private static class Wildcard extends EmulatedAnnotatedType<WildcardType> implements AnnotatedWildcardType { |
| |
| Wildcard(WildcardType wrapped) { |
| super(wrapped); |
| } |
| |
| @Override |
| public AnnotatedType[] getAnnotatedLowerBounds() { |
| return wrapArray(wrapped.getLowerBounds()); |
| } |
| |
| @Override |
| public AnnotatedType[] getAnnotatedUpperBounds() { |
| return wrapArray(wrapped.getUpperBounds()); |
| } |
| |
| //@Override - Java8 build compatibility |
| public AnnotatedType getAnnotatedOwnerType() { |
| return null; |
| } |
| } |
| |
| public static EmulatedAnnotatedType<?> wrap(Type type) { |
| if (type instanceof ParameterizedType) { |
| return new EmulatedAnnotatedType.Parameterized((ParameterizedType) type); |
| } |
| if (type instanceof TypeVariable<?>) { |
| return new EmulatedAnnotatedType.Variable((TypeVariable<?>) type); |
| } |
| if (type instanceof WildcardType) { |
| return new EmulatedAnnotatedType.Wildcard((WildcardType) type); |
| } |
| return new EmulatedAnnotatedType<>(type); |
| } |
| |
| private static EmulatedAnnotatedType<?>[] wrapArray(Type[] types) { |
| return Stream.of(types).map(EmulatedAnnotatedType::wrap).toArray(EmulatedAnnotatedType[]::new); |
| } |
| |
| private static final Annotation[] EMPTY_ANNOTATION_ARRAY = {}; |
| |
| protected final T wrapped; |
| private final Optional<AnnotatedElement> annotated; |
| |
| private EmulatedAnnotatedType(T wrapped) { |
| super(); |
| this.wrapped = Validate.notNull(wrapped); |
| this.annotated = |
| Optional.of(wrapped).filter(AnnotatedElement.class::isInstance).map(AnnotatedElement.class::cast); |
| } |
| |
| @Override |
| public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { |
| return annotated.map(e -> e.getAnnotation(annotationClass)).orElse(null); |
| } |
| |
| @Override |
| public Annotation[] getAnnotations() { |
| return annotated.map(AnnotatedElement::getAnnotations).orElse(EMPTY_ANNOTATION_ARRAY); |
| } |
| |
| @Override |
| public Annotation[] getDeclaredAnnotations() { |
| return annotated.map(AnnotatedElement::getDeclaredAnnotations).orElse(EMPTY_ANNOTATION_ARRAY); |
| } |
| |
| @Override |
| public Type getType() { |
| return wrapped; |
| } |
| } |