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    public SimpleElementValue(final int type, final int index, final ConstantPool cpool) {
035        super(type, cpool);
036        this.index = index;
037    }
038
039    @Override
040    public void dump(final DataOutputStream dos) throws IOException {
041        final int type = super.getType();
042        dos.writeByte(type); // u1 kind of value
043        switch (type) {
044        case PRIMITIVE_INT:
045        case PRIMITIVE_BYTE:
046        case PRIMITIVE_CHAR:
047        case PRIMITIVE_FLOAT:
048        case PRIMITIVE_LONG:
049        case PRIMITIVE_BOOLEAN:
050        case PRIMITIVE_SHORT:
051        case PRIMITIVE_DOUBLE:
052        case STRING:
053            dos.writeShort(getIndex());
054            break;
055        default:
056            throw new ClassFormatException("SimpleElementValue doesn't know how to write out type " + type);
057        }
058    }
059
060    /**
061     * @return Value entry index in the constant pool.
062     */
063    public int getIndex() {
064        return index;
065    }
066
067    public boolean getValueBoolean() {
068        if (super.getType() != PRIMITIVE_BOOLEAN) {
069            throw new IllegalStateException("Don't call getValueBoolean() on a non BOOLEAN ElementValue");
070        }
071        final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
072        return bo.getBytes() != 0;
073    }
074
075    public byte getValueByte() {
076        if (super.getType() != PRIMITIVE_BYTE) {
077            throw new IllegalStateException("Don't call getValueByte() on a non BYTE ElementValue");
078        }
079        return (byte) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
080    }
081
082    public char getValueChar() {
083        if (super.getType() != PRIMITIVE_CHAR) {
084            throw new IllegalStateException("Don't call getValueChar() on a non CHAR ElementValue");
085        }
086        return (char) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
087    }
088
089    public double getValueDouble() {
090        if (super.getType() != PRIMITIVE_DOUBLE) {
091            throw new IllegalStateException("Don't call getValueDouble() on a non DOUBLE ElementValue");
092        }
093        final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex());
094        return d.getBytes();
095    }
096
097    public float getValueFloat() {
098        if (super.getType() != PRIMITIVE_FLOAT) {
099            throw new IllegalStateException("Don't call getValueFloat() on a non FLOAT ElementValue");
100        }
101        final ConstantFloat f = (ConstantFloat) super.getConstantPool().getConstant(getIndex());
102        return f.getBytes();
103    }
104
105    public int getValueInt() {
106        if (super.getType() != PRIMITIVE_INT) {
107            throw new IllegalStateException("Don't call getValueInt() on a non INT ElementValue");
108        }
109        return super.getConstantPool().getConstantInteger(getIndex()).getBytes();
110    }
111
112    public long getValueLong() {
113        if (super.getType() != PRIMITIVE_LONG) {
114            throw new IllegalStateException("Don't call getValueLong() on a non LONG ElementValue");
115        }
116        final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex());
117        return j.getBytes();
118    }
119
120    public short getValueShort() {
121        if (super.getType() != PRIMITIVE_SHORT) {
122            throw new IllegalStateException("Don't call getValueShort() on a non SHORT ElementValue");
123        }
124        final ConstantInteger s = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
125        return (short) s.getBytes();
126    }
127
128    public String getValueString() {
129        if (super.getType() != STRING) {
130            throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
131        }
132        return super.getConstantPool().getConstantUtf8(getIndex()).getBytes();
133    }
134
135    public void setIndex(final int index) {
136        this.index = index;
137    }
138
139    // Whatever kind of value it is, return it as a string
140    @Override
141    public String stringifyValue() {
142        final ConstantPool cpool = super.getConstantPool();
143        final int type = super.getType();
144        switch (type) {
145        case PRIMITIVE_INT:
146            return Integer.toString(cpool.getConstantInteger(getIndex()).getBytes());
147        case PRIMITIVE_LONG:
148            final ConstantLong j = cpool.getConstant(getIndex(), Const.CONSTANT_Long, ConstantLong.class);
149            return Long.toString(j.getBytes());
150        case PRIMITIVE_DOUBLE:
151            final ConstantDouble d = cpool.getConstant(getIndex(), Const.CONSTANT_Double, ConstantDouble.class);
152            return Double.toString(d.getBytes());
153        case PRIMITIVE_FLOAT:
154            final ConstantFloat f = cpool.getConstant(getIndex(), Const.CONSTANT_Float, ConstantFloat.class);
155            return Float.toString(f.getBytes());
156        case PRIMITIVE_SHORT:
157            final ConstantInteger s = cpool.getConstantInteger(getIndex());
158            return Integer.toString(s.getBytes());
159        case PRIMITIVE_BYTE:
160            final ConstantInteger b = cpool.getConstantInteger(getIndex());
161            return Integer.toString(b.getBytes());
162        case PRIMITIVE_CHAR:
163            final ConstantInteger ch = cpool.getConstantInteger(getIndex());
164            return String.valueOf((char) ch.getBytes());
165        case PRIMITIVE_BOOLEAN:
166            final ConstantInteger bo = cpool.getConstantInteger(getIndex());
167            if (bo.getBytes() == 0) {
168                return "false";
169            }
170            return "true";
171        case STRING:
172            return cpool.getConstantUtf8(getIndex()).getBytes();
173        default:
174            throw new IllegalStateException("SimpleElementValue class does not know how to stringify type " + type);
175        }
176    }
177
178    @Override
179    public String toString() {
180        return stringifyValue();
181    }
182}