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

org.robovm.rt.annotation.Annotation Maven / Gradle / Ivy

/*
 * Copyright (C) 2014 Trillian Mobile AB
 *
 * Licensed 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.robovm.rt.annotation;

import java.lang.annotation.AnnotationTypeMismatchException;
import java.lang.annotation.IncompleteAnnotationException;
import java.util.Arrays;
import java.util.HashMap;

/**
 * Abstract base class of annotation implementation classes generated by the
 * compiler {@code AnnotationImplPlugin}.
 */
public abstract class Annotation implements java.lang.annotation.Annotation {
    private enum NoValue {NO_VALUE}

    /**
     * Singleton representing missing element value.
     */
    protected static final Object NO_VALUE = NoValue.NO_VALUE;
    
    private static HashMap, HashMap> 
        defaultValueCache = new HashMap<>();
    
    private final Class annotationType;

    protected Annotation(Class klass) {
        this.annotationType = klass;
    }

    @Override
    public Class annotationType() {
        return annotationType;
    }
    
    protected final Object validate(Object value, String memberName) {
        if (value instanceof Exception) {
            if (value instanceof TypeNotPresentException) {
                TypeNotPresentException e = (TypeNotPresentException) value;
                throw new TypeNotPresentException(e.typeName(), e.getCause());
            } else if (value instanceof EnumConstantNotPresentException) {
                EnumConstantNotPresentException e = (EnumConstantNotPresentException) value;
                throw new EnumConstantNotPresentException(e.enumType(), e.constantName());
            } else if (value instanceof AnnotationTypeMismatchException) {
                AnnotationTypeMismatchException e = (AnnotationTypeMismatchException) value;
                throw new AnnotationTypeMismatchException(e.element(), e.foundType());
            } else if (value instanceof ArrayStoreException) {
                ArrayStoreException e = (ArrayStoreException) value;
                throw new ArrayStoreException(e.getMessage());
            } else {
                // Unknown exception. Wrap and rethrow.
                throw new RuntimeException((Exception) value);
            }
        }
        
        if (value == NO_VALUE) {
            throw new IncompleteAnnotationException(annotationType, memberName);
        }
        
        Class type = value.getClass();
        if (type.isArray()) {
            if (type == int[].class) {
                return ((int[]) value).clone();
            } else if (type == byte[].class) {
                return ((byte[]) value).clone();
            } else if (type == short[].class) {
                return ((short[]) value).clone();
            } else if (type == long[].class) {
                return ((long[]) value).clone();
            } else if (type == char[].class) {
                return ((char[]) value).clone();
            } else if (type == boolean[].class) {
                return ((boolean[]) value).clone();
            } else if (type == float[].class) {
                return ((float[]) value).clone();
            } else if (type == double[].class) {
                return ((double[]) value).clone();
            }
            return ((Object[]) value).clone();
        }
        return value;
    }
    
    protected final Object getDefaultValue(String memberName) {
        synchronized (defaultValueCache) {
            HashMap cache = defaultValueCache.get(annotationType);
            if (cache != null) {
                Object value = cache.get(memberName);
                if (value != null) {
                    return value;
                }
            }
            
            Object value = null;
            try {
                value = annotationType.getMethod(memberName).getDefaultValue();
            } catch (Throwable t) {
                value = t;
            }
            if (value == null) {
                value = NO_VALUE;
            }
            
            if (cache == null) {
                cache = new HashMap();
                defaultValueCache.put(annotationType, cache);
            }
            
            cache.put(memberName, value);
            return value;
        }
    }
    
    protected final int hash(Object value, String memberName) {
        int hash = memberName.hashCode() * 127;
        Class type = value.getClass();
        if (type.isArray()) {
            if (type == int[].class) {
                return hash ^ Arrays.hashCode((int[]) value);
            } else if (type == byte[].class) {
                return hash ^ Arrays.hashCode((byte[]) value);
            } else if (type == short[].class) {
                return hash ^ Arrays.hashCode((short[]) value);
            } else if (type == long[].class) {
                return hash ^ Arrays.hashCode((long[]) value);
            } else if (type == char[].class) {
                return hash ^ Arrays.hashCode((char[]) value);
            } else if (type == boolean[].class) {
                return hash ^ Arrays.hashCode((boolean[]) value);
            } else if (type == float[].class) {
                return hash ^ Arrays.hashCode((float[]) value);
            } else if (type == double[].class) {
                return hash ^ Arrays.hashCode((double[]) value);
            }
            return hash ^ Arrays.hashCode((Object[]) value);
        } else {
            return hash ^ value.hashCode();
        }
    }
    
    @Override
    public final boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null) {
            return false;
        }
        if (this.getClass() == o.getClass()) {
            return fastEquals(o);
        }
        if (annotationType.isInstance(o)) {
            try {
                return slowEquals(o);
            } catch (Throwable t) {
                return false;
            }
        }
        return false;
    }
    
    protected abstract boolean fastEquals(Object that);

    protected abstract boolean slowEquals(Object that);

    protected final boolean memberEquals(Object ours, Object theirs) {
        if (ours == theirs) {
            return true;
        }
        if (ours instanceof Exception) {
            return false;
        }
        Class type = ours.getClass();
        if (type != theirs.getClass()) {
            return false;
        }
        if (type.isArray()) {
            if (ours instanceof Object[]) {
                return Arrays.equals((Object[]) ours, (Object[]) theirs);
            } else if (type == int[].class) {
                return Arrays.equals((int[]) ours, (int[]) theirs);
            } else if (type == byte[].class) {
                return Arrays.equals((byte[]) ours, (byte[]) theirs);
            } else if (type == short[].class) {
                return Arrays.equals((short[]) ours, (short[]) theirs);
            } else if (type == long[].class) {
                return Arrays.equals((long[]) ours, (long[]) theirs);
            } else if (type == char[].class) {
                return Arrays.equals((char[]) ours, (char[]) theirs);
            } else if (type == boolean[].class) {
                return Arrays.equals((boolean[]) ours, (boolean[]) theirs);
            } else if (type == float[].class) {
                return Arrays.equals((float[]) ours, (float[]) theirs);
            } else if (type == double[].class) {
                return Arrays.equals((double[]) ours, (double[]) theirs);
            }
            return false;
        } else {
            return ours.equals(theirs);
        }
    }

    @Override
    public final String toString() {
        StringBuilder sb = new StringBuilder(128);
        sb.append('@');
        sb.append(annotationType.getName());
        sb.append('(');
        membersToString(sb);
        sb.append(')');
        return sb.toString();
    }
    
    protected abstract void membersToString(StringBuilder sb);
    
    protected final void memberToString(StringBuilder sb, Object value, String memberName, boolean first) {
        if (!first) {
            sb.append(", ");
        }
        sb.append(memberName);
        sb.append('=');
        sb.append(memberValueToString(value));
    }

    private final String memberValueToString(Object value) {
        Class type = value.getClass();
        if (type.isArray()) {
            if (type == int[].class) {
                return Arrays.toString((int[]) value);
            } else if (type == byte[].class) {
                return Arrays.toString((byte[]) value);
            } else if (type == short[].class) {
                return Arrays.toString((short[]) value);
            } else if (type == long[].class) {
                return Arrays.toString((long[]) value);
            } else if (type == char[].class) {
                return Arrays.toString((char[]) value);
            } else if (type == boolean[].class) {
                return Arrays.toString((boolean[]) value);
            } else if (type == float[].class) {
                return Arrays.toString((float[]) value);
            } else if (type == double[].class) {
                return Arrays.toString((double[]) value);
            }
            return Arrays.toString((Object[]) value);
        }
        return value.toString();
    }

    protected static Boolean box(boolean v) {
        return Boolean.valueOf(v);
    }
    protected static Byte box(byte v) {
        return Byte.valueOf(v);
    }
    protected static Short box(short v) {
        return Short.valueOf(v);
    }
    protected static Character box(char v) {
        return Character.valueOf(v);
    }
    protected static Integer box(int v) {
        return Integer.valueOf(v);
    }
    protected static Long box(long v) {
        return Long.valueOf(v);
    }
    protected static Float box(float v) {
        return Float.valueOf(v);
    }
    protected static Double box(double v) {
        return Double.valueOf(v);
    }
    protected static boolean unbox(Boolean v) {
        return v.booleanValue();
    }
    protected static byte unbox(Byte v) {
        return v.byteValue();
    }
    protected static short unbox(Short v) {
        return v.shortValue();
    }
    protected static char unbox(Character v) {
        return v.charValue();
    }
    protected static int unbox(Integer v) {
        return v.intValue();
    }
    protected static long unbox(Long v) {
        return v.longValue();
    }
    protected static float unbox(Float v) {
        return v.floatValue();
    }
    protected static double unbox(Double v) {
        return v.doubleValue();
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy