001    package serp.bytecode;
002    
003    import serp.bytecode.lowlevel.*;
004    import serp.bytecode.visitor.*;
005    import serp.util.*;
006    
007    /**
008     * A field of a class.
009     *
010     * @author Abe White
011     */
012    public 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    }