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