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 }