001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.bcel.classfile;
020
021import java.io.DataOutputStream;
022import java.io.IOException;
023
024import org.apache.bcel.Const;
025
026/**
027 * Represents a simple element value in an annotation.
028 *
029 * @since 6.0
030 */
031public class SimpleElementValue extends ElementValue {
032    private int index;
033
034    /**
035     * Constructs a SimpleElementValue.
036     *
037     * @param type The element value type.
038     * @param index The index into the constant pool.
039     * @param cpool The constant pool.
040     */
041    public SimpleElementValue(final int type, final int index, final ConstantPool cpool) {
042        super(type, cpool);
043        this.index = index;
044    }
045
046    @Override
047    public void dump(final DataOutputStream dos) throws IOException {
048        final int type = super.getType();
049        dos.writeByte(type); // u1 kind of value
050        switch (type) {
051        case PRIMITIVE_INT:
052        case PRIMITIVE_BYTE:
053        case PRIMITIVE_CHAR:
054        case PRIMITIVE_FLOAT:
055        case PRIMITIVE_LONG:
056        case PRIMITIVE_BOOLEAN:
057        case PRIMITIVE_SHORT:
058        case PRIMITIVE_DOUBLE:
059        case STRING:
060            dos.writeShort(getIndex());
061            break;
062        default:
063            throw new ClassFormatException("SimpleElementValue doesn't know how to write out type " + type);
064        }
065    }
066
067    /**
068     * Gets the value entry index in the constant pool.
069     *
070     * @return Value entry index in the constant pool.
071     */
072    public int getIndex() {
073        return index;
074    }
075
076    /**
077     * Gets the boolean value.
078     *
079     * @return The boolean value.
080     */
081    public boolean getValueBoolean() {
082        if (super.getType() != PRIMITIVE_BOOLEAN) {
083            throw new IllegalStateException("Don't call getValueBoolean() on a non BOOLEAN ElementValue");
084        }
085        final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
086        return bo.getBytes() != 0;
087    }
088
089    /**
090     * Gets the byte value.
091     *
092     * @return The byte value.
093     */
094    public byte getValueByte() {
095        if (super.getType() != PRIMITIVE_BYTE) {
096            throw new IllegalStateException("Don't call getValueByte() on a non BYTE ElementValue");
097        }
098        return (byte) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
099    }
100
101    /**
102     * Gets the char value.
103     *
104     * @return The char value.
105     */
106    public char getValueChar() {
107        if (super.getType() != PRIMITIVE_CHAR) {
108            throw new IllegalStateException("Don't call getValueChar() on a non CHAR ElementValue");
109        }
110        return (char) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
111    }
112
113    /**
114     * Gets the double value.
115     *
116     * @return The double value.
117     */
118    public double getValueDouble() {
119        if (super.getType() != PRIMITIVE_DOUBLE) {
120            throw new IllegalStateException("Don't call getValueDouble() on a non DOUBLE ElementValue");
121        }
122        final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex());
123        return d.getBytes();
124    }
125
126    /**
127     * Gets the float value.
128     *
129     * @return The float value.
130     */
131    public float getValueFloat() {
132        if (super.getType() != PRIMITIVE_FLOAT) {
133            throw new IllegalStateException("Don't call getValueFloat() on a non FLOAT ElementValue");
134        }
135        final ConstantFloat f = (ConstantFloat) super.getConstantPool().getConstant(getIndex());
136        return f.getBytes();
137    }
138
139    /**
140     * Gets the int value.
141     *
142     * @return The int value.
143     */
144    public int getValueInt() {
145        if (super.getType() != PRIMITIVE_INT) {
146            throw new IllegalStateException("Don't call getValueInt() on a non INT ElementValue");
147        }
148        return super.getConstantPool().getConstantInteger(getIndex()).getBytes();
149    }
150
151    /**
152     * Gets the long value.
153     *
154     * @return The long value.
155     */
156    public long getValueLong() {
157        if (super.getType() != PRIMITIVE_LONG) {
158            throw new IllegalStateException("Don't call getValueLong() on a non LONG ElementValue");
159        }
160        final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex());
161        return j.getBytes();
162    }
163
164    /**
165     * Gets the short value.
166     *
167     * @return The short value.
168     */
169    public short getValueShort() {
170        if (super.getType() != PRIMITIVE_SHORT) {
171            throw new IllegalStateException("Don't call getValueShort() on a non SHORT ElementValue");
172        }
173        final ConstantInteger s = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
174        return (short) s.getBytes();
175    }
176
177    /**
178     * Gets the string value.
179     *
180     * @return The string value.
181     */
182    public String getValueString() {
183        if (super.getType() != STRING) {
184            throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
185        }
186        return super.getConstantPool().getConstantUtf8(getIndex()).getBytes();
187    }
188
189    /**
190     * Sets the index into the constant pool.
191     *
192     * @param index The index.
193     */
194    public void setIndex(final int index) {
195        this.index = index;
196    }
197
198    // Whatever kind of value it is, return it as a string
199    @Override
200    public String stringifyValue() {
201        final ConstantPool cpool = super.getConstantPool();
202        final int type = super.getType();
203        switch (type) {
204        case PRIMITIVE_INT:
205            return Integer.toString(cpool.getConstantInteger(getIndex()).getBytes());
206        case PRIMITIVE_LONG:
207            final ConstantLong j = cpool.getConstant(getIndex(), Const.CONSTANT_Long, ConstantLong.class);
208            return Long.toString(j.getBytes());
209        case PRIMITIVE_DOUBLE:
210            final ConstantDouble d = cpool.getConstant(getIndex(), Const.CONSTANT_Double, ConstantDouble.class);
211            return Double.toString(d.getBytes());
212        case PRIMITIVE_FLOAT:
213            final ConstantFloat f = cpool.getConstant(getIndex(), Const.CONSTANT_Float, ConstantFloat.class);
214            return Float.toString(f.getBytes());
215        case PRIMITIVE_SHORT:
216            final ConstantInteger s = cpool.getConstantInteger(getIndex());
217            return Integer.toString(s.getBytes());
218        case PRIMITIVE_BYTE:
219            final ConstantInteger b = cpool.getConstantInteger(getIndex());
220            return Integer.toString(b.getBytes());
221        case PRIMITIVE_CHAR:
222            final ConstantInteger ch = cpool.getConstantInteger(getIndex());
223            return String.valueOf((char) ch.getBytes());
224        case PRIMITIVE_BOOLEAN:
225            final ConstantInteger bo = cpool.getConstantInteger(getIndex());
226            if (bo.getBytes() == 0) {
227                return "false";
228            }
229            return "true";
230        case STRING:
231            return cpool.getConstantUtf8(getIndex()).getBytes();
232        default:
233            throw new IllegalStateException("SimpleElementValue class does not know how to stringify type " + type);
234        }
235    }
236
237    @Override
238    public String toString() {
239        return stringifyValue();
240    }
241}