1 /*
  2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 package jdk.experimental.bytecode;
 25 
 26 import java.util.function.Consumer;
 27 
 28 /**
 29  * Declaration (class, class member, ...) builder.
 30  *
 31  * @param <S> the type of symbol representation
 32  * @param <T> the type of type descriptors representation
 33  * @param <E> the type of pool entries
 34  * @param <D> the type of this builder
 35  */
 36 public class DeclBuilder<S, T, E, D extends DeclBuilder<S, T, E, D>>
 37         extends AttributeBuilder<S, T, E, D> {
 38 
 39     /**
 40      * The access flags of the declaration, as bit flags.
 41      */
 42     protected int flags;
 43 
 44     AnnotationsBuilder<S, T, E> runtimeInvisibleAnnotations;
 45     AnnotationsBuilder<S, T, E> runtimeVisibleAnnotations;
 46 
 47     /**
 48      * Create a declaration builder,
 49      *
 50      * @param poolHelper the helper to build the constant pool
 51      * @param typeHelper the helper to use to manipulate type descriptors
 52      */
 53     DeclBuilder(PoolHelper<S, T, E> poolHelper, TypeHelper<S, T> typeHelper) {
 54         super(poolHelper, typeHelper);
 55     }
 56 
 57     /**
 58      * Specify the class file flags for this declaration.
 59      *
 60      * @param flags the flags as {@code Flag} objects
 61      * @return this builder, for chained calls
 62      */
 63     public D withFlags(Flag... flags) {
 64         for (Flag f : flags) {
 65             this.flags |= f.flag;
 66         }
 67         return thisBuilder();
 68     }
 69 
 70     /**
 71      * Specify, via bits, the class file flags for this declaration.
 72      *
 73      * @param flags the flags as bit settings
 74      * @return this builder, for chained calls
 75      */
 76     public D withFlags(int flags) {
 77         withFlags(Flag.parse(flags));
 78         return thisBuilder();
 79     }
 80 
 81     public D withAnnotation(AnnotationsBuilder.Kind kind, T annoType) {
 82         getAnnotations(kind).withAnnotation(annoType, null);
 83         return thisBuilder();
 84     }
 85 
 86     public D withAnnotation(AnnotationsBuilder.Kind kind, T annoType, Consumer<? super AnnotationsBuilder<S, T, E>.AnnotationElementBuilder> annotations) {
 87         getAnnotations(kind).withAnnotation(annoType, annotations);
 88         return thisBuilder();
 89     }
 90 
 91     private AnnotationsBuilder<S, T, E> getAnnotations(AnnotationsBuilder.Kind kind) {
 92         switch (kind) {
 93             case RUNTIME_INVISIBLE:
 94                 if (runtimeInvisibleAnnotations == null) {
 95                     runtimeInvisibleAnnotations = new AnnotationsBuilder<>(poolHelper, typeHelper);
 96                 }
 97                 return runtimeInvisibleAnnotations;
 98             case RUNTIME_VISIBLE:
 99                 if (runtimeVisibleAnnotations == null) {
100                     runtimeVisibleAnnotations = new AnnotationsBuilder<>(poolHelper, typeHelper);
101                 }
102                 return runtimeVisibleAnnotations;
103         }
104         throw new IllegalStateException();
105     }
106 
107     void addAnnotations() {
108         if (runtimeVisibleAnnotations != null) {
109             withAttribute("RuntimeVisibleAnnotations", runtimeVisibleAnnotations.build());
110         }
111         if (runtimeInvisibleAnnotations != null) {
112             withAttribute("RuntimeInvisibleAnnotations", runtimeVisibleAnnotations.build());
113         }
114     }
115 }