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