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