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.classfile;
020
021import java.io.DataOutputStream;
022import java.io.IOException;
023
024import org.apache.bcel.Const;
025
026/**
027 * @since 6.0
028 */
029public class SimpleElementValue extends ElementValue {
030    private int index;
031
032    public SimpleElementValue(final int type, final int index, final ConstantPool cpool) {
033        super(type, cpool);
034        this.index = index;
035    }
036
037    @Override
038    public void dump(final DataOutputStream dos) throws IOException {
039        final int type = super.getType();
040        dos.writeByte(type); // u1 kind of value
041        switch (type) {
042        case PRIMITIVE_INT:
043        case PRIMITIVE_BYTE:
044        case PRIMITIVE_CHAR:
045        case PRIMITIVE_FLOAT:
046        case PRIMITIVE_LONG:
047        case PRIMITIVE_BOOLEAN:
048        case PRIMITIVE_SHORT:
049        case PRIMITIVE_DOUBLE:
050        case STRING:
051            dos.writeShort(getIndex());
052            break;
053        default:
054            throw new ClassFormatException("SimpleElementValue doesn't know how to write out type " + type);
055        }
056    }
057
058    /**
059     * @return Value entry index in the cpool
060     */
061    public int getIndex() {
062        return index;
063    }
064
065    public boolean getValueBoolean() {
066        if (super.getType() != PRIMITIVE_BOOLEAN) {
067            throw new IllegalStateException("Don't call getValueBoolean() on a non BOOLEAN ElementValue");
068        }
069        final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
070        return bo.getBytes() != 0;
071    }
072
073    public byte getValueByte() {
074        if (super.getType() != PRIMITIVE_BYTE) {
075            throw new IllegalStateException("Don't call getValueByte() on a non BYTE ElementValue");
076        }
077        return (byte) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
078    }
079
080    public char getValueChar() {
081        if (super.getType() != PRIMITIVE_CHAR) {
082            throw new IllegalStateException("Don't call getValueChar() on a non CHAR ElementValue");
083        }
084        return (char) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
085    }
086
087    public double getValueDouble() {
088        if (super.getType() != PRIMITIVE_DOUBLE) {
089            throw new IllegalStateException("Don't call getValueDouble() on a non DOUBLE ElementValue");
090        }
091        final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex());
092        return d.getBytes();
093    }
094
095    public float getValueFloat() {
096        if (super.getType() != PRIMITIVE_FLOAT) {
097            throw new IllegalStateException("Don't call getValueFloat() on a non FLOAT ElementValue");
098        }
099        final ConstantFloat f = (ConstantFloat) super.getConstantPool().getConstant(getIndex());
100        return f.getBytes();
101    }
102
103    public int getValueInt() {
104        if (super.getType() != PRIMITIVE_INT) {
105            throw new IllegalStateException("Don't call getValueInt() on a non INT ElementValue");
106        }
107        return super.getConstantPool().getConstantInteger(getIndex()).getBytes();
108    }
109
110    public long getValueLong() {
111        if (super.getType() != PRIMITIVE_LONG) {
112            throw new IllegalStateException("Don't call getValueLong() on a non LONG ElementValue");
113        }
114        final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex());
115        return j.getBytes();
116    }
117
118    public short getValueShort() {
119        if (super.getType() != PRIMITIVE_SHORT) {
120            throw new IllegalStateException("Don't call getValueShort() on a non SHORT ElementValue");
121        }
122        final ConstantInteger s = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
123        return (short) s.getBytes();
124    }
125
126    public String getValueString() {
127        if (super.getType() != STRING) {
128            throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
129        }
130        return super.getConstantPool().getConstantUtf8(getIndex()).getBytes();
131    }
132
133    public void setIndex(final int index) {
134        this.index = index;
135    }
136
137    // Whatever kind of value it is, return it as a string
138    @Override
139    public String stringifyValue() {
140        final ConstantPool cpool = super.getConstantPool();
141        final int type = super.getType();
142        switch (type) {
143        case PRIMITIVE_INT:
144            return Integer.toString(cpool.getConstantInteger(getIndex()).getBytes());
145        case PRIMITIVE_LONG:
146            final ConstantLong j = cpool.getConstant(getIndex(), Const.CONSTANT_Long, ConstantLong.class);
147            return Long.toString(j.getBytes());
148        case PRIMITIVE_DOUBLE:
149            final ConstantDouble d = cpool.getConstant(getIndex(), Const.CONSTANT_Double, ConstantDouble.class);
150            return Double.toString(d.getBytes());
151        case PRIMITIVE_FLOAT:
152            final ConstantFloat f = cpool.getConstant(getIndex(), Const.CONSTANT_Float, ConstantFloat.class);
153            return Float.toString(f.getBytes());
154        case PRIMITIVE_SHORT:
155            final ConstantInteger s = cpool.getConstantInteger(getIndex());
156            return Integer.toString(s.getBytes());
157        case PRIMITIVE_BYTE:
158            final ConstantInteger b = cpool.getConstantInteger(getIndex());
159            return Integer.toString(b.getBytes());
160        case PRIMITIVE_CHAR:
161            final ConstantInteger ch = cpool.getConstantInteger(getIndex());
162            return String.valueOf((char) ch.getBytes());
163        case PRIMITIVE_BOOLEAN:
164            final ConstantInteger bo = cpool.getConstantInteger(getIndex());
165            if (bo.getBytes() == 0) {
166                return "false";
167            }
168            return "true";
169        case STRING:
170            return cpool.getConstantUtf8(getIndex()).getBytes();
171        default:
172            throw new IllegalStateException("SimpleElementValue class does not know how to stringify type " + type);
173        }
174    }
175
176    @Override
177    public String toString() {
178        return stringifyValue();
179    }
180}