/* * Copyright 2012 Chris Pheby * * 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.jadira.scanner.classpath.types; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import javassist.bytecode.AnnotationsAttribute; import javassist.bytecode.FieldInfo; import javassist.bytecode.annotation.Annotation; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.jadira.scanner.classpath.ClasspathResolver; import org.jadira.scanner.classpath.visitor.IntrospectionVisitor; import org.jadira.scanner.core.exception.ClasspathAccessException; public class JField extends JVariable { private FieldInfo fieldInfo; private JClass jClass; protected JField(FieldInfo fieldInfo, JClass jClass, ClasspathResolver resolver) { super(fieldInfo.getName(), resolver); this.fieldInfo = fieldInfo; this.jClass = jClass; } public static JField getJField(FieldInfo fieldInfo, JClass jClass, ClasspathResolver resolver) { return new JField(fieldInfo, jClass, resolver); } @Override public JType getEnclosingType() { return jClass; } @Override public JType getType() throws ClasspathAccessException { final JType retVal; Class<?> clazz; try { Field field = getActualField(); clazz = field.getType(); } catch (SecurityException e) { throw new ClasspathAccessException("Problem finding enclosing type: " + e.getMessage(), e); } if (clazz.isInterface()) { retVal = JInterface.getJInterface(clazz.getName(), getResolver()); } else if (clazz.isPrimitive()) { retVal = JPrimitiveClass.getJClass(clazz.getName(), getResolver()); } else if (clazz.isArray()) { retVal = JArrayClass.getJClass(clazz, getResolver()); } else { retVal = JClass.getJClass(clazz.getName(), getResolver()); } return retVal; } public Class<?> decodeFieldType(String componentType) throws ClassNotFoundException { char type = componentType.charAt(0); String fieldContent = componentType.substring(1); switch (type) { // L<classname>; reference an instance of class <classname> case 'L': return getResolver().loadClass(fieldContent.replace('/', '.')); // B byte signed byte case 'B': return Byte.class; // C char Unicode character case 'C': return Character.class; // D double double-precision floating-point value case 'D': return Double.class; // F float single-precision floating-point value case 'F': return Float.class; // I int integer case 'I': return Integer.class; // J long long integer case 'J': return Long.class; // S short signed short case 'S': return Short.class; // Z boolean true or false case 'Z': return Boolean.class; // [ reference one array dimension case '[': return getResolver().loadClass(componentType.replace('/', '.') + ";"); } return null; } @Override public Set<JAnnotation<?>> getAnnotations() { AnnotationsAttribute visible = (AnnotationsAttribute) fieldInfo.getAttribute(AnnotationsAttribute.visibleTag); AnnotationsAttribute invisible = (AnnotationsAttribute) fieldInfo.getAttribute(AnnotationsAttribute.invisibleTag); Set<JAnnotation<?>> annotations = new HashSet<JAnnotation<?>>(); List<Annotation> annotationsList = new ArrayList<Annotation>(); if (visible != null) { annotationsList.addAll(Arrays.asList(visible.getAnnotations())); } if (invisible != null) { annotationsList.addAll(Arrays.asList(invisible.getAnnotations())); } for (Annotation nextAnnotation : annotationsList) { annotations.add(JAnnotation.getJAnnotation(nextAnnotation, this, getResolver())); } return annotations; } @Override public void acceptVisitor(IntrospectionVisitor visitor) { visitor.visit(this); for (JAnnotation<?> next : getAnnotations()) { next.acceptVisitor(visitor); } } public Field getActualField() { try { return getEnclosingType().getActualClass().getDeclaredField(getName()); } catch (SecurityException e) { throw new ClasspathAccessException("Problem obtaining field: " + e.getMessage(), e); } catch (NoSuchFieldException e) { throw new ClasspathAccessException("Problem finding field: " + this.toString(), e); } } public FieldInfo getFieldInfo() { return fieldInfo; } @Override public JClass getEnclosingElement() { return jClass; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (obj == this) { return true; } if (obj.getClass() != getClass()) { return false; } JField rhs = (JField) obj; return new EqualsBuilder() .appendSuper(super.equals(obj)) .append(jClass, rhs.jClass).isEquals(); } @Override public int hashCode() { return new HashCodeBuilder(11, 47).append(super.hashCode()) .append(jClass.getName()).toHashCode(); } }