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

org.apache.bval.jsr.util.AnnotationProxy 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.util;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;

import javax.validation.Valid;

import org.apache.bval.jsr.metadata.Signature;
import org.apache.bval.util.Exceptions;
import org.apache.bval.util.ObjectUtils;
import org.apache.bval.util.StringUtils;
import org.apache.bval.util.reflection.Reflection;

/**
 * Description: 
* InvocationHandler implementation of Annotation that pretends it is a "real" source code annotation. *

*/ class AnnotationProxy implements Annotation, InvocationHandler, Serializable { /** Serialization version */ private static final long serialVersionUID = 1L; private final Class annotationType; private final SortedMap values; /** * Create a new AnnotationProxy instance. * * @param * @param descriptor */ AnnotationProxy(AnnotationProxyBuilder descriptor) { this.annotationType = descriptor.getType(); values = new TreeMap<>(); int processedValuesFromDescriptor = 0; for (final Method m : descriptor.getMethods()) { if (descriptor.contains(m.getName())) { values.put(m.getName(), descriptor.getValue(m.getName())); processedValuesFromDescriptor++; } else { if (m.getDefaultValue() == null) { Exceptions.raise(IllegalArgumentException::new, "No value provided for %s", m.getName()); } values.put(m.getName(), m.getDefaultValue()); } } Exceptions.raiseUnless(processedValuesFromDescriptor == descriptor.size() || Valid.class.equals(annotationType), IllegalArgumentException::new, "Trying to instantiate %s with unknown parameters.", f -> f.args(annotationType.getName())); } /** * {@inheritDoc} */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { final Object value = values.get(method.getName()); if (value != null) { return value; } if (method.getName().equals("equals")) { // this is an annotation, no need to be more fancy (and slower) return equalTo(args[0]); } return method.invoke(this, args); } /** * {@inheritDoc} */ @Override public Class annotationType() { return annotationType; } /** * {@inheritDoc} */ @Override public String toString() { return values.entrySet().stream() .map(e -> String.format("%s=%s", e.getKey(), StringUtils.valueOf(e.getValue()))) .collect(Collectors.joining(", ", String.format("@%s(", annotationType().getName()), ")")); } @Override public int hashCode() { return values.entrySet().stream().mapToInt(e -> { return (127 * e.getKey().hashCode()) ^ ObjectUtils.hashCode(e.getValue()); }).sum(); } private boolean equalTo(Object obj) { if (obj == this) { return true; } if (obj instanceof Annotation) { final Annotation other = (Annotation) obj; return other.annotationType().equals(annotationType) && values.entrySet().stream().allMatch(e -> memberEquals(other, e.getKey(), e.getValue())); } return false; } private boolean memberEquals(Annotation other, String name, Object value) { final Method member = Reflection.getDeclaredMethod(annotationType, name); final Object otherValue; try { otherValue = member.invoke(other); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new IllegalStateException(e); } Exceptions.raiseIf(otherValue == null || !otherValue.getClass().equals(value.getClass()), IllegalStateException::new, "Unexpected value %s for member %s of %s", otherValue, name, other); if (value instanceof Object[]) { return Arrays.equals((Object[]) value, (Object[]) otherValue); } if (value instanceof byte[]) { return Arrays.equals((byte[]) value, (byte[]) otherValue); } if (value instanceof short[]) { return Arrays.equals((short[]) value, (short[]) otherValue); } if (value instanceof int[]) { return Arrays.equals((int[]) value, (int[]) otherValue); } if (value instanceof char[]) { return Arrays.equals((char[]) value, (char[]) otherValue); } if (value instanceof long[]) { return Arrays.equals((long[]) value, (long[]) otherValue); } if (value instanceof float[]) { return Arrays.equals((float[]) value, (float[]) otherValue); } if (value instanceof double[]) { return Arrays.equals((double[]) value, (double[]) otherValue); } if (value instanceof boolean[]) { return Arrays.equals((boolean[]) value, (boolean[]) otherValue); } return value.equals(otherValue); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy