1 /*
   2  * Copyright (c) 2009, 2015, 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 extends TrustedInterface {
  33 
  34     /**
  35      * Returns the name of this field.
  36      */
  37     String getName();
  38 
  39     /**
  40      * Returns a {@link JavaType} object that identifies the declared type for this field.
  41      */
  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      */
  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      */
  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      */
  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 }