001/*******************************************************************************
002 * Copyright (C) 2009-2011 FuseSource Corp.
003 * Copyright (c) 2004, 2008 IBM Corporation and others.
004 *
005 * All rights reserved. This program and the accompanying materials
006 * are made available under the terms of the Eclipse Public License v1.0
007 * which accompanies this distribution, and is available at
008 * http://www.eclipse.org/legal/epl-v10.html
009 *
010 *******************************************************************************/
011package org.fusesource.hawtjni.generator.model;
012
013import java.lang.reflect.Field;
014import java.util.Arrays;
015import java.util.HashSet;
016
017import org.apache.commons.lang3.StringUtils;
018import org.fusesource.hawtjni.runtime.FieldFlag;
019import org.fusesource.hawtjni.runtime.JniField;
020import org.fusesource.hawtjni.runtime.T32;
021
022import static org.fusesource.hawtjni.generator.util.TextSupport.*;
023import static org.fusesource.hawtjni.runtime.FieldFlag.*;
024
025/**
026 * 
027 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
028 */
029public class ReflectField implements JNIField {
030    
031    private ReflectClass parent;
032    private Field field;
033    private ReflectType type;
034    private JniField annotation;
035    private HashSet<FieldFlag> flags;
036    private boolean allowConversion;
037    private ReflectFieldAccessor accessor;
038
039    public ReflectField(ReflectClass parent, Field field) {
040        this.parent = parent;
041        this.field = field;
042        lazyLoad();
043    }
044
045    public int hashCode() {
046        return field.hashCode();
047    }
048
049    public boolean equals(Object obj) {
050        if (!(obj instanceof ReflectField))
051            return false;
052        return ((ReflectField) obj).field.equals(field);
053    }
054    
055    public String toString() {
056        return field.toString();
057    }
058
059    ///////////////////////////////////////////////////////////////////
060    // JNIField interface methods
061    ///////////////////////////////////////////////////////////////////
062
063    public JNIClass getDeclaringClass() {
064        return parent;
065    }
066
067    public int getModifiers() {
068        return field.getModifiers();
069    }
070
071    public String getName() {
072        return field.getName();
073    }
074
075    public JNIType getType() {
076        return type.asType32(allowConversion);
077    }
078
079    public JNIType getType64() {
080        return type.asType64(allowConversion);
081    }
082
083    public JNIFieldAccessor getAccessor() {
084        return accessor;
085    }
086
087    public String getCast() {
088        String rc = annotation == null ? "" : annotation.cast().trim();
089        return cast(rc);
090    }
091
092    public boolean ignore() {
093        return getFlag(FieldFlag.FIELD_SKIP);
094    }
095
096    public boolean isPointer() {
097        if( annotation == null ) {
098            return false;
099        }
100        return getFlag(POINTER_FIELD) || ( type.getWrappedClass() == Long.TYPE && getCast().endsWith("*") );
101    }
102
103    public String getConditional() {
104        String parentConditional = getDeclaringClass().getConditional();
105        String myConditional = annotation == null ? null : emptyFilter(annotation.conditional());
106        if( parentConditional!=null ) {
107            if( myConditional!=null ) {
108                return parentConditional+" && "+myConditional;
109            } else {
110                return parentConditional;
111            }
112        }
113        return myConditional;
114    }
115
116    public boolean getFlag(FieldFlag flag) {
117        return flags.contains(flag);
118    }
119
120    ///////////////////////////////////////////////////////////////////
121    // Helper methods
122    ///////////////////////////////////////////////////////////////////
123    static public String emptyFilter(String value) {
124        if( value==null || value.length()==0 )
125            return null;
126        return value;
127    }
128    
129    private void lazyLoad() {
130        this.type = new ReflectType(field.getType());
131        this.annotation = this.field.getAnnotation(JniField.class);
132        this.flags = new HashSet<FieldFlag>();
133        this.accessor = new ReflectFieldAccessor(this.field.getName());
134        if( this.annotation!=null ) {
135            this.flags.addAll(Arrays.asList(this.annotation.flags()));
136            if (!StringUtils.isEmpty(this.annotation.accessor())) {
137                this.accessor = new ReflectFieldAccessor(this.annotation.accessor());
138            } else if (!StringUtils.isEmpty(this.annotation.getter()) &&
139                    !StringUtils.isEmpty(this.annotation.setter())) {
140                this.accessor = new ReflectFieldAccessor(
141                        this.annotation.getter(),
142                        this.flags.contains(GETTER_NONMEMBER),
143                        this.annotation.setter(),
144                        this.flags.contains(SETTER_NONMEMBER));
145            }
146        }
147        
148        allowConversion = this.field.getAnnotation(T32.class)!=null;
149    }
150
151}