/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.utility.classfile.descriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import org.eclipse.persistence.tools.workbench.utility.ClassTools;
import org.eclipse.persistence.tools.workbench.utility.classfile.Visitor;
/**
* This class models a class file Descriptor Field Type.
*
* See "The Java Virtual Machine Specification" Chapter 4.
*/
public abstract class FieldType {
// ********** static factory methods **********
public static FieldType createFieldType(String fieldDescriptor) {
try {
return createFieldType(new StringReader(fieldDescriptor));
} catch (IOException ex) {
// highly unlikely when using a StringReader...
throw new RuntimeException(ex);
}
}
public static FieldType createFieldType(Reader reader) throws IOException {
int c = reader.read();
switch (c) {
case 'L': return new ObjectType(reader);
case '[': return new ArrayType(reader);
default: return new BaseType(c);
}
}
/**
* Array classes are stored like descriptors; while non-array
* classes are simply stored as a name (without the surrounding
* "L ;").
*/
public static FieldType createFieldTypeForClassConstant(String internalName) {
if (internalName.charAt(0) == '[') {
return FieldType.createFieldType(internalName);
}
return new ObjectType(internalName);
}
// ********** public API **********
/**
* Accept the specified visitor.
*/
public abstract void accept(Visitor visitor);
/**
* Return the field type's "array depth".
*/
public abstract int arrayDepth();
/**
* Return the field type's "element type name".
*/
public abstract String elementTypeName();
/**
* Return the name that matches the name returned by
* java.lang.Class.getName().
*/
public abstract String javaName();
/**
* Return the Java class corresponding to the
* type declaration, if possible.
*/
public abstract Class javaClass() throws ClassNotFoundException;
/**
* Return the declaration used to define the field type in Java
* source code.
*/
public String declaration() {
StringBuffer sb = new StringBuffer(200);
this.appendDeclarationTo(sb);
return sb.toString();
}
/**
* Append the Java source code that would define
* the field type on the specified string buffer.
*/
public abstract void appendDeclarationTo(StringBuffer sb);
/**
* Print the Java source code that would define
* the field type on the specified writer.
*/
public abstract void printDeclarationOn(PrintWriter writer);
/**
* Return the name that matches the name used internally by the JVM.
*/
public abstract String internalName();
public String toString() {
StringBuffer sb = new StringBuffer(200);
sb.append(ClassTools.shortClassNameForObject(this));
sb.append('(');
this.appendDeclarationTo(sb);
sb.append(')');
return sb.toString();
}
// ********** internal API **********
FieldType() {
super();
}
abstract void appendArrayJavaNameTo(StringBuffer sb);
abstract void appendArrayInternalNameTo(StringBuffer sb);
}