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; 023import java.util.ArrayList; 024import java.util.List; 025import java.util.stream.Collectors; 026 027import org.apache.bcel.classfile.ArrayElementValue; 028import org.apache.bcel.classfile.ElementValue; 029import org.apache.commons.lang3.stream.Streams; 030 031/** 032 * Generates array element values in annotations. 033 * 034 * @since 6.0 035 */ 036public class ArrayElementValueGen extends ElementValueGen { 037 // J5TODO: Should we make this an array or a list? A list would be easier to 038 // modify ... 039 private final List<ElementValueGen> evalues; 040 041 /** 042 * Constructs an ArrayElementValueGen. 043 * 044 * @param value the array element value. 045 * @param cpool the constant pool generator. 046 * @param copyPoolEntries whether to copy pool entries. 047 */ 048 public ArrayElementValueGen(final ArrayElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { 049 super(ARRAY, cpool); 050 evalues = new ArrayList<>(); 051 final ElementValue[] in = value.getElementValuesArray(); 052 for (final ElementValue element : in) { 053 evalues.add(copy(element, cpool, copyPoolEntries)); 054 } 055 } 056 057 /** 058 * Constructs an ArrayElementValueGen. 059 * 060 * @param cp the constant pool generator. 061 */ 062 public ArrayElementValueGen(final ConstantPoolGen cp) { 063 super(ARRAY, cp); 064 evalues = new ArrayList<>(); 065 } 066 067 /** 068 * Constructs an ArrayElementValueGen. 069 * 070 * @param type the type. 071 * @param elementValues the element values. 072 * @param cpool the constant pool generator. 073 */ 074 public ArrayElementValueGen(final int type, final ElementValue[] elementValues, final ConstantPoolGen cpool) { 075 super(type, cpool); 076 if (type != ARRAY) { 077 throw new IllegalArgumentException("Only element values of type array can be built with this ctor - type specified: " + type); 078 } 079 this.evalues = Streams.of(elementValues).map(e -> copy(e, cpool, true)).collect(Collectors.toList()); 080 } 081 082 /** 083 * Adds an element. 084 * 085 * @param gen the element value generator. 086 */ 087 public void addElement(final ElementValueGen gen) { 088 evalues.add(gen); 089 } 090 091 @Override 092 public void dump(final DataOutputStream dos) throws IOException { 093 dos.writeByte(super.getElementValueType()); // u1 type of value (ARRAY == '[') 094 dos.writeShort(evalues.size()); 095 for (final ElementValueGen element : evalues) { 096 element.dump(dos); 097 } 098 } 099 100 /** 101 * Return immutable variant of this ArrayElementValueGen. 102 * 103 * @return immutable variant of this ArrayElementValueGen. 104 */ 105 @Override 106 public ElementValue getElementValue() { 107 final ElementValue[] immutableData = new ElementValue[evalues.size()]; 108 int i = 0; 109 for (final ElementValueGen element : evalues) { 110 immutableData[i++] = element.getElementValue(); 111 } 112 return new ArrayElementValue(super.getElementValueType(), immutableData, getConstantPool().getConstantPool()); 113 } 114 115 /** 116 * Gets the element values. 117 * 118 * @return the element values. 119 */ 120 public List<ElementValueGen> getElementValues() { 121 return evalues; 122 } 123 124 /** 125 * Gets the element values size. 126 * 127 * @return the element values size. 128 */ 129 public int getElementValuesSize() { 130 return evalues.size(); 131 } 132 133 @Override 134 public String stringifyValue() { 135 final StringBuilder sb = new StringBuilder(); 136 sb.append("["); 137 String comma = ""; 138 for (final ElementValueGen element : evalues) { 139 sb.append(comma); 140 comma = ","; 141 sb.append(element.stringifyValue()); 142 } 143 sb.append("]"); 144 return sb.toString(); 145 } 146}