    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}