    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}