org.apache.bval.jsr.metadata.Meta Maven / Gradle / Ivy
/*
* 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.jsr.metadata;
import java.lang.annotation.ElementType;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Map;
import java.util.Objects;
import org.apache.bval.util.EmulatedAnnotatedType;
import org.apache.bval.util.Lazy;
import org.apache.bval.util.Validate;
import org.apache.bval.util.reflection.TypeUtils;
/**
* Validation class model.
*
* @param
*/
public abstract class Meta {
public static class ForClass extends Meta> {
private final AnnotatedType annotatedType;
public ForClass(Class host) {
super(host, ElementType.TYPE);
this.annotatedType = EmulatedAnnotatedType.wrap(host);
}
@Override
public final Class getDeclaringClass() {
return getHost();
}
@Override
public Type getType() {
return getHost();
}
@Override
public AnnotatedType getAnnotatedType() {
return annotatedType;
}
@Override
public String getName() {
return getHost().getName();
}
@Override
public Meta> getParent() {
return null;
}
}
public static abstract class ForMember extends Meta {
@SuppressWarnings({ "rawtypes", "unchecked" })
private final Lazy>> parent = new Lazy<>(() -> new Meta.ForClass(getDeclaringClass()));
protected ForMember(M host, ElementType elementType) {
super(host, elementType);
}
@Override
public Class> getDeclaringClass() {
return getHost().getDeclaringClass();
}
@Override
public Meta> getParent() {
return parent.get();
}
}
public static class ForField extends ForMember {
public ForField(Field host) {
super(host, ElementType.FIELD);
}
@Override
public Type getType() {
return getHost().getGenericType();
}
@Override
public AnnotatedType getAnnotatedType() {
return getHost().getAnnotatedType();
}
@Override
public String getName() {
return getHost().getName();
}
}
public static abstract class ForExecutable extends ForMember {
protected ForExecutable(E host, ElementType elementType) {
super(host, elementType);
}
@Override
public AnnotatedType getAnnotatedType() {
return getHost().getAnnotatedReturnType();
}
}
public static class ForConstructor extends ForExecutable> {
public ForConstructor(Constructor extends T> host) {
super(host, ElementType.CONSTRUCTOR);
}
@Override
public Type getType() {
return getHost().getDeclaringClass();
}
@Override
public String getName() {
return getHost().getDeclaringClass().getSimpleName();
}
}
public static class ForMethod extends ForExecutable {
public ForMethod(Method host) {
super(host, ElementType.METHOD);
}
@Override
public Type getType() {
return getHost().getGenericReturnType();
}
@Override
public String getName() {
return getHost().getName();
}
}
public static class ForCrossParameter extends Meta {
private final Meta parent;
public ForCrossParameter(Meta parent) {
super(parent.getHost(), parent.getElementType());
this.parent = parent;
}
@Override
public Type getType() {
return Object[].class;
}
@Override
public String getName() {
return "";
}
@Override
public String describeHost() {
return String.format("%s of %s", getName(), getHost());
}
@Override
public Meta getParent() {
return parent;
}
@Override
public Class> getDeclaringClass() {
return getHost().getDeclaringClass();
}
@Override
public AnnotatedType getAnnotatedType() {
return getHost().getAnnotatedReturnType();
}
}
public static class ForParameter extends Meta {
private final String name;
private final Lazy> parent = new Lazy<>(this::computeParent);
public ForParameter(Parameter host, String name) {
super(host, ElementType.PARAMETER);
this.name = Validate.notNull(name, "name");
}
@Override
public Type getType() {
return getHost().getParameterizedType();
}
@Override
public Class> getDeclaringClass() {
return getHost().getDeclaringExecutable().getDeclaringClass();
}
@Override
public AnnotatedType getAnnotatedType() {
return getHost().getAnnotatedType();
}
@Override
public String getName() {
return name;
}
@Override
public String describeHost() {
return String.format("%s of %s", getName(), getHost().getDeclaringExecutable());
}
@Override
public Meta extends Executable> getParent() {
return parent.get();
}
private Meta extends Executable> computeParent() {
final Executable exe = getHost().getDeclaringExecutable();
return exe instanceof Method ? new Meta.ForMethod((Method) exe)
: new Meta.ForConstructor<>((Constructor>) exe);
}
}
public static class ForContainerElement extends Meta {
private final Meta> parent;
private final ContainerElementKey key;
public ForContainerElement(Meta> parent, ContainerElementKey key) {
super(key.getAnnotatedType(), ElementType.TYPE_USE);
this.parent = Validate.notNull(parent, "parent");
this.key = Validate.notNull(key, "key");
}
@Override
public Type getType() {
Type result = getHost().getType();
if (result instanceof TypeVariable>) {
final Type parentType = parent.getType();
if (parentType instanceof ParameterizedType) {
final Map, Type> typeArguments =
TypeUtils.getTypeArguments((ParameterizedType) parentType);
if (typeArguments.containsKey(result)) {
return typeArguments.get(result);
}
}
}
return result;
}
@Override
public Class> getDeclaringClass() {
return parent.getDeclaringClass();
}
@Override
public AnnotatedType getAnnotatedType() {
return key.getAnnotatedType();
}
public Integer getTypeArgumentIndex() {
return key.getTypeArgumentIndex();
}
@Override
public String getName() {
return key.toString();
}
@Override
public String describeHost() {
return String.format("%s of %s", key, parent);
}
@Override
public Meta> getParent() {
return parent;
}
}
private final E host;
private final ElementType elementType;
protected Meta(E host, ElementType elementType) {
super();
this.host = Validate.notNull(host, "host");
this.elementType = Validate.notNull(elementType, "elementType");
}
public E getHost() {
return host;
}
public ElementType getElementType() {
return elementType;
}
public abstract Type getType();
public abstract Class> getDeclaringClass();
public abstract AnnotatedType getAnnotatedType();
public abstract String getName();
public abstract Meta> getParent();
@Override
public final String toString() {
return String.format("%s.%s(%s)", Meta.class.getSimpleName(), getClass().getSimpleName(), describeHost());
}
public String describeHost() {
return host.toString();
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!obj.getClass().equals(getClass())) {
return false;
}
return Objects.equals(((Meta>) obj).getHost(), getHost());
}
@Override
public int hashCode() {
return Objects.hash(getHost());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy