1 /*
2  * Copyright (c) 2009, 2016, 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 package jdk.vm.ci.meta;
24 
25 import java.util.IllegalFormatException;
26 import java.util.UnknownFormatConversionException;
27 
28 /**
29  * Represents a reference to a Java field, either resolved or unresolved fields. Fields, like
30  * methods and types, are resolved through {@link ConstantPool constant pools}.
31  */
32 public interface JavaField {
33 
34     /**
35      * Returns the name of this field.
36      */
getName()37     String getName();
38 
39     /**
40      * Returns a {@link JavaType} object that identifies the declared type for this field.
41      */
getType()42     JavaType getType();
43 
44     /**
45      * Returns the kind of this field. This is the same as calling {@link #getType}.
46      * {@link JavaType#getJavaKind getJavaKind}.
47      */
getJavaKind()48     default JavaKind getJavaKind() {
49         return getType().getJavaKind();
50     }
51 
52     /**
53      * Returns the {@link JavaType} object representing the class or interface that declares this
54      * field.
55      */
getDeclaringClass()56     JavaType getDeclaringClass();
57 
58     /**
59      * Gets a string for this field formatted according to a given format specification. A format
60      * specification is composed of characters that are to be copied verbatim to the result and
61      * specifiers that denote an attribute of this field that is to be copied to the result. A
62      * specifier is a single character preceded by a '%' character. The accepted specifiers and the
63      * field attributes they denote are described below:
64      *
65      * <pre>
66      *     Specifier | Description                                          | Example(s)
67      *     ----------+------------------------------------------------------------------------------------------
68      *     'T'       | Qualified type                                       | "int" "java.lang.String"
69      *     't'       | Unqualified type                                     | "int" "String"
70      *     'H'       | Qualified holder                                     | "java.util.Map.Entry"
71      *     'h'       | Unqualified holder                                   | "Entry"
72      *     'n'       | Field name                                           | "age"
73      *     'f'       | Indicator if field is unresolved, static or instance | "unresolved" "static" "instance"
74      *     '%'       | A '%' character                                      | "%"
75      * </pre>
76      *
77      * @param format a format specification
78      * @return the result of formatting this field according to {@code format}
79      * @throws IllegalFormatException if an illegal specifier is encountered in {@code format}
80      */
format(String format)81     default String format(String format) throws IllegalFormatException {
82         StringBuilder sb = new StringBuilder();
83         int index = 0;
84         JavaType type = getType();
85         while (index < format.length()) {
86             char ch = format.charAt(index++);
87             if (ch == '%') {
88                 if (index >= format.length()) {
89                     throw new UnknownFormatConversionException("An unquoted '%' character cannot terminate a field format specification");
90                 }
91                 char specifier = format.charAt(index++);
92                 switch (specifier) {
93                     case 'T':
94                     case 't': {
95                         sb.append(type.toJavaName(specifier == 'T'));
96                         break;
97                     }
98                     case 'H':
99                     case 'h': {
100                         sb.append(getDeclaringClass().toJavaName(specifier == 'H'));
101                         break;
102                     }
103                     case 'n': {
104                         sb.append(getName());
105                         break;
106                     }
107                     case 'f': {
108                         sb.append(!(this instanceof ResolvedJavaField) ? "unresolved" : ((ResolvedJavaField) this).isStatic() ? "static" : "instance");
109                         break;
110                     }
111                     case '%': {
112                         sb.append('%');
113                         break;
114                     }
115                     default: {
116                         throw new UnknownFormatConversionException(String.valueOf(specifier));
117                     }
118                 }
119             } else {
120                 sb.append(ch);
121             }
122         }
123         return sb.toString();
124     }
125 }
126