001package serp.bytecode;
002
003import serp.bytecode.lowlevel.*;
004import serp.bytecode.visitor.*;
005import serp.util.*;
006
007/**
008 * A field of a class.
009 *
010 * @author Abe White
011 */
012public class BCField extends BCMember implements VisitAcceptor {
013    BCField(BCClass owner) {
014        super(owner);
015        if (owner.isEnum())
016            setEnum(true);
017    }
018
019    /**
020     * Manipulate the field access flags.
021     */
022    public boolean isVolatile() {
023        return (getAccessFlags() & Constants.ACCESS_VOLATILE) > 0;
024    }
025
026    /**
027     * Manipulate the field access flags.
028     */
029    public void setVolatile(boolean on) {
030        if (on)
031            setAccessFlags(getAccessFlags() | Constants.ACCESS_VOLATILE);
032        else
033            setAccessFlags(getAccessFlags() & ~Constants.ACCESS_VOLATILE);
034    }
035
036    /**
037     * Manipulate the field access flags.
038     */
039    public boolean isTransient() {
040        return (getAccessFlags() & Constants.ACCESS_TRANSIENT) > 0;
041    }
042
043    /**
044     * Manipulate the field access flags.
045     */
046    public void setTransient(boolean on) {
047        if (on)
048            setAccessFlags(getAccessFlags() | Constants.ACCESS_TRANSIENT);
049        else
050            setAccessFlags(getAccessFlags() & ~Constants.ACCESS_TRANSIENT);
051    }
052
053    /**
054     * Manipulate the field access flags. Defaults to true for fields added
055     * to enum classes.
056     */
057    public boolean isEnum() {
058        return (getAccessFlags() & Constants.ACCESS_ENUM) > 0;
059    }
060
061    /**
062     * Manipulate the field access flags. Defaults to true for fields added
063     * to enum classes.
064     */
065    public void setEnum(boolean on) {
066        if (on)
067            setAccessFlags(getAccessFlags() | Constants.ACCESS_ENUM);
068        else
069            setAccessFlags(getAccessFlags() & ~Constants.ACCESS_ENUM);
070    }
071
072    /**
073     * Return the name of the type of this field. The name will be given in
074     * a form suitable for a {@link Class#forName} call.
075     *
076     * @see BCMember#getDescriptor
077     */
078    public String getTypeName() {
079        return getProject().getNameCache().getExternalForm
080            (getDescriptor(), false);
081    }
082
083    /**
084     * Return the {@link Class} object for the type of this field.
085     */
086    public Class getType() {
087        return Strings.toClass(getTypeName(), getClassLoader());
088    }
089
090    /**
091     * Return the bytecode for the type of this field.
092     */
093    public BCClass getTypeBC() {
094        return getProject().loadClass(getTypeName(), getClassLoader());
095    }
096
097    /**
098     * Set the name of the type of this field.
099     *
100     * @see BCMember#setDescriptor
101     */
102    public void setType(String type) {
103        setDescriptor(type);
104    }
105
106    /**
107     * Set the type of this field.
108     *
109     * @see BCMember#setDescriptor
110     */
111    public void setType(Class type) {
112        setType(type.getName());
113    }
114
115    /**
116     * Set the type of this field.
117     *
118     * @see BCMember#setDescriptor
119     */
120    public void setType(BCClass type) {
121        setType(type.getName());
122    }
123
124    /**
125     * Return the constant value information for the field.
126     * Acts internally through the {@link Attributes} interface.
127     *
128     * @param add if true, a new constant value attribute will be added
129     * if not already present
130     * @return the constant value information, or null if none and the
131     * <code>add</code> param is set to false
132     */
133    public ConstantValue getConstantValue(boolean add) {
134        ConstantValue constant = (ConstantValue) getAttribute
135            (Constants.ATTR_CONST);
136        if (!add || (constant != null))
137            return constant;
138        if (constant == null)
139            constant = (ConstantValue) addAttribute(Constants.ATTR_CONST);
140        return constant;
141    }
142
143    /**
144     * Remove the constant value attribute for the field.
145     * Acts internally through the {@link Attributes} interface.
146     *
147     * @return true if there was a value to remove
148     */
149    public boolean removeConstantValue() {
150        return removeAttribute(Constants.ATTR_CONST);
151    }
152
153    public void acceptVisit(BCVisitor visit) {
154        visit.enterBCField(this);
155        visitAttributes(visit);
156        visit.exitBCField(this);
157    }
158
159    void initialize(String name, String descriptor) {
160        super.initialize(name, descriptor);
161        makePrivate();
162    }
163}