View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.bcel.generic;
20  
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.stream.Collectors;
26  
27  import org.apache.bcel.classfile.ArrayElementValue;
28  import org.apache.bcel.classfile.ElementValue;
29  import org.apache.commons.lang3.stream.Streams;
30  
31  /**
32   * Generates array element values in annotations.
33   *
34   * @since 6.0
35   */
36  public class ArrayElementValueGen extends ElementValueGen {
37      // J5TODO: Should we make this an array or a list? A list would be easier to
38      // modify ...
39      private final List<ElementValueGen> evalues;
40  
41      /**
42       * Constructs an ArrayElementValueGen.
43       *
44       * @param value the array element value.
45       * @param cpool the constant pool generator.
46       * @param copyPoolEntries whether to copy pool entries.
47       */
48      public ArrayElementValueGen(final ArrayElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
49          super(ARRAY, cpool);
50          evalues = new ArrayList<>();
51          final ElementValue[] in = value.getElementValuesArray();
52          for (final ElementValue element : in) {
53              evalues.add(copy(element, cpool, copyPoolEntries));
54          }
55      }
56  
57      /**
58       * Constructs an ArrayElementValueGen.
59       *
60       * @param cp the constant pool generator.
61       */
62      public ArrayElementValueGen(final ConstantPoolGen cp) {
63          super(ARRAY, cp);
64          evalues = new ArrayList<>();
65      }
66  
67      /**
68       * Constructs an ArrayElementValueGen.
69       *
70       * @param type the type.
71       * @param elementValues the element values.
72       * @param cpool the constant pool generator.
73       */
74      public ArrayElementValueGen(final int type, final ElementValue[] elementValues, final ConstantPoolGen cpool) {
75          super(type, cpool);
76          if (type != ARRAY) {
77              throw new IllegalArgumentException("Only element values of type array can be built with this ctor - type specified: " + type);
78          }
79          this.evalues = Streams.of(elementValues).map(e -> copy(e, cpool, true)).collect(Collectors.toList());
80      }
81  
82      /**
83       * Adds an element.
84       *
85       * @param gen the element value generator.
86       */
87      public void addElement(final ElementValueGen gen) {
88          evalues.add(gen);
89      }
90  
91      @Override
92      public void dump(final DataOutputStream dos) throws IOException {
93          dos.writeByte(super.getElementValueType()); // u1 type of value (ARRAY == '[')
94          dos.writeShort(evalues.size());
95          for (final ElementValueGen element : evalues) {
96              element.dump(dos);
97          }
98      }
99  
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 }