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.commons.compress.harmony.unpack200.bytecode;
020
021import java.io.DataOutputStream;
022import java.io.IOException;
023import java.util.ArrayList;
024import java.util.List;
025
026/**
027 * Parameter annotations class file attribute, either a RuntimeVisibleParameterAnnotations attribute or a RuntimeInvisibleParameterAnnotations attribute.
028 */
029public class RuntimeVisibleorInvisibleParameterAnnotationsAttribute extends AnnotationsAttribute {
030
031    /**
032     * ParameterAnnotation represents the annotations on a single parameter.
033     */
034    public static class ParameterAnnotation {
035
036        private final Annotation[] annotations;
037
038        /**
039         * Constructs a new instance.
040         *
041         * @param annotations Annotation.
042         */
043        public ParameterAnnotation(final Annotation[] annotations) {
044            this.annotations = annotations;
045        }
046
047        /**
048         * Gets all annotation class file entries.
049         *
050         * @return all annotation class file entries.
051         */
052        public List<Object> getClassFileEntries() {
053            final List<Object> nested = new ArrayList<>();
054            for (final Annotation annotation : annotations) {
055                nested.addAll(annotation.getClassFileEntries());
056            }
057            return nested;
058        }
059
060        /**
061         * Gets the cumulative length of all annotations.
062         *
063         * @return the cumulative length of all annotations.
064         */
065        public int getLength() {
066            int length = 2;
067            for (final Annotation annotation : annotations) {
068                length += annotation.getLength();
069            }
070            return length;
071        }
072
073        /**
074         * Resolves all annotations in this instance against the given pool.
075         *
076         * @param pool A class constant pool.
077         */
078        public void resolve(final ClassConstantPool pool) {
079            for (final Annotation annotation : annotations) {
080                annotation.resolve(pool);
081            }
082        }
083
084        /**
085         * Writes this body to the given output stream.
086         *
087         * @param dos the output stream.
088         * @throws IOException if an I/O error occurs.
089         */
090        public void writeBody(final DataOutputStream dos) throws IOException {
091            dos.writeShort(annotations.length);
092            for (final Annotation annotation : annotations) {
093                annotation.writeBody(dos);
094            }
095        }
096
097    }
098
099    private final ParameterAnnotation[] parameterAnnotations;
100
101    /**
102     * Constructs a new instance for an attribute name.
103     *
104     * @param name an attribute name.
105     * @param parameterAnnotations Annotations.
106     */
107    public RuntimeVisibleorInvisibleParameterAnnotationsAttribute(final CPUTF8 name, final ParameterAnnotation[] parameterAnnotations) {
108        super(name);
109        this.parameterAnnotations = parameterAnnotations;
110    }
111
112    @Override
113    protected int getLength() {
114        int length = 1;
115        for (final ParameterAnnotation parameterAnnotation : parameterAnnotations) {
116            length += parameterAnnotation.getLength();
117        }
118        return length;
119    }
120
121    @Override
122    protected ClassFileEntry[] getNestedClassFileEntries() {
123        final List<Object> nested = new ArrayList<>();
124        nested.add(attributeName);
125        for (final ParameterAnnotation parameterAnnotation : parameterAnnotations) {
126            nested.addAll(parameterAnnotation.getClassFileEntries());
127        }
128        return nested.toArray(NONE);
129    }
130
131    @Override
132    protected void resolve(final ClassConstantPool pool) {
133        super.resolve(pool);
134        for (final ParameterAnnotation parameterAnnotation : parameterAnnotations) {
135            parameterAnnotation.resolve(pool);
136        }
137    }
138
139    @Override
140    public String toString() {
141        return attributeName.underlyingString() + ": " + parameterAnnotations.length + " parameter annotations";
142    }
143
144    @Override
145    protected void writeBody(final DataOutputStream dos) throws IOException {
146        dos.writeByte(parameterAnnotations.length);
147        for (final ParameterAnnotation parameterAnnotation : parameterAnnotations) {
148            parameterAnnotation.writeBody(dos);
149        }
150    }
151
152}