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