001    package serp.bytecode;
002    
003    import java.io.*;
004    
005    import serp.bytecode.lowlevel.*;
006    import serp.bytecode.visitor.*;
007    
008    /**
009     * A constant value for a member field.
010     *
011     * @author Abe White
012     */
013    public class ConstantValue extends Attribute {
014        int _valueIndex = 0;
015    
016        ConstantValue(int nameIndex, Attributes owner) {
017            super(nameIndex, owner);
018        }
019    
020        int getLength() {
021            return 2;
022        }
023    
024        /**
025         * Return the owning field.
026         */
027        public BCField getField() {
028            return (BCField) getOwner();
029        }
030    
031        /**
032         * Return the {@link ConstantPool} index of the {@link ConstantEntry}
033         * holding the value of this constant. Defaults to 0.
034         */
035        public int getValueIndex() {
036            return _valueIndex;
037        }
038    
039        /**
040         * Set the {@link ConstantPool} of the {@link ConstantEntry}
041         * holding the value of this constant.
042         */
043        public void setValueIndex(int valueIndex) {
044            _valueIndex = valueIndex;
045        }
046    
047        /**
048         * Return the type of constant this attribute represents, or null if
049         * not set.
050         */
051        public String getTypeName() {
052            Class type = getType();
053            if (type == null)
054                return null;
055            return type.getName();
056        }
057    
058        /**
059         * Return the type of constant this attribute represents (String.class,
060         * int.class, etc), or null if not set.
061         */
062        public Class getType() {
063            Object value = getValue();
064            if (value == null)
065                return null;
066    
067            Class type = value.getClass();
068            if (type == Integer.class)
069                return int.class;
070            if (type == Float.class)
071                return float.class;
072            if (type == Double.class)
073                return double.class;
074            if (type == Long.class)
075                return long.class;
076            return String.class;
077        }
078    
079        /**
080         * Return the bytecode for the type of constant this attribute represents.
081         */
082        public BCClass getTypeBC() {
083            return getProject().loadClass(getType());
084        }
085    
086        /**
087         * Return the value of this constant as an Object of the appropriate
088         * type (String, Integer, Double, etc), or null if not set.
089         */
090        public Object getValue() {
091            if (_valueIndex <= 0)
092                return null;
093            return ((ConstantEntry) getPool().getEntry(_valueIndex)).getConstant();
094        }
095    
096        /**
097         * Set the value of this constant using the appropriate wrapper Object
098         * type (String, Integer, Double, etc). Types that are not directly
099         * supported will be converted accordingly if possible.
100         */
101        public void setValue(Object value) {
102            Class type = value.getClass();
103            if (type == Boolean.class)
104                setIntValue((((Boolean) value).booleanValue()) ? 1 : 0);
105            else if (type == Character.class)
106                setIntValue((int) ((Character) value).charValue());
107            else if (type == Byte.class || type == Integer.class 
108                || type == Short.class)
109                setIntValue(((Number) value).intValue());
110            else if (type == Float.class)
111                setFloatValue(((Number) value).floatValue());
112            else if (type == Double.class)
113                setDoubleValue(((Number) value).doubleValue());
114            else if (type == Long.class)
115                setLongValue(((Number) value).longValue());
116            else
117                setStringValue(value.toString());
118        }
119    
120        /**
121         * Get the value of this int constant, or 0 if not set.
122         */
123        public int getIntValue() {
124            if (getValueIndex() <= 0)
125                return 0;
126            return ((IntEntry) getPool().getEntry(getValueIndex())).getValue();
127        }
128    
129        /**
130         * Set the value of this int constant.
131         */
132        public void setIntValue(int value) {
133            setValueIndex(getPool().findIntEntry(value, true));
134        }
135    
136        /**
137         * Get the value of this float constant.
138         */
139        public float getFloatValue() {
140            if (getValueIndex() <= 0)
141                return 0F;
142            return ((FloatEntry) getPool().getEntry(getValueIndex())).getValue();
143        }
144    
145        /**
146         * Set the value of this float constant.
147         */
148        public void setFloatValue(float value) {
149            setValueIndex(getPool().findFloatEntry(value, true));
150        }
151    
152        /**
153         * Get the value of this double constant.
154         */
155        public double getDoubleValue() {
156            if (getValueIndex() <= 0)
157                return 0D;
158            return ((DoubleEntry) getPool().getEntry(getValueIndex())).getValue();
159        }
160    
161        /**
162         * Set the value of this double constant.
163         */
164        public void setDoubleValue(double value) {
165            setValueIndex(getPool().findDoubleEntry(value, true));
166        }
167    
168        /**
169         * Get the value of this long constant.
170         */
171        public long getLongValue() {
172            if (getValueIndex() <= 0)
173                return 0L;
174            return ((LongEntry) getPool().getEntry(getValueIndex())).getValue();
175        }
176    
177        /**
178         * Set the value of this long constant.
179         */
180        public void setLongValue(long value) {
181            setValueIndex(getPool().findLongEntry(value, true));
182        }
183    
184        /**
185         * Get the value of this string constant.
186         */
187        public String getStringValue() {
188            if (getValueIndex() <= 0)
189                return null;
190            return ((StringEntry) getPool().getEntry(getValueIndex())).
191                getStringEntry().getValue();
192        }
193    
194        /**
195         * Set the value of this string constant.
196         */
197        public void setStringValue(String value) {
198            setValueIndex(getPool().findStringEntry(value, true));
199        }
200    
201        public void acceptVisit(BCVisitor visit) {
202            visit.enterConstantValue(this);
203            visit.exitConstantValue(this);
204        }
205    
206        void read(Attribute other) {
207            setValue(((ConstantValue) other).getValue());
208        }
209    
210        void read(DataInput in, int length) throws IOException {
211            setValueIndex(in.readUnsignedShort());
212        }
213    
214        void write(DataOutput out, int length) throws IOException {
215            out.writeShort(getValueIndex());
216        }
217    }