Package net.sourceforge.javautil.bytecode.api

Source Code of net.sourceforge.javautil.bytecode.api.TypeDescriptor

package net.sourceforge.javautil.bytecode.api;

import net.sourceforge.javautil.bytecode.BytecodeException;

/**
* This represents a type descriptor.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public class TypeDescriptor implements Comparable<TypeDescriptor> {
 
  public static final TypeDescriptor BOOLEAN = new TypeDescriptor("Z", true);
 
  public static final TypeDescriptor CHAR = new TypeDescriptor("C", true);
 
  public static final TypeDescriptor BYTE = new TypeDescriptor("B", true);
 
  public static final TypeDescriptor SHORT = new TypeDescriptor("S", true);
 
  public static final TypeDescriptor INTEGER = new TypeDescriptor("I", true);
 
  public static final TypeDescriptor FLOAT = new TypeDescriptor("F", true);
 
  public static final TypeDescriptor LONG = new TypeDescriptor("J", true);
 
  public static final TypeDescriptor DOUBLE = new TypeDescriptor("D", true);
 
  public static final TypeDescriptor VOID = new TypeDescriptor("V", true);
 
  public static final TypeDescriptor OBJECT = TypeDescriptor.getFor(Object.class);
 
  public static final TypeDescriptor STRING = TypeDescriptor.getFor(String.class);
 
  public static TypeDescriptor getFor (Class clazz) {
    if (clazz.isPrimitive()) {
      if (clazz == boolean.class) return BOOLEAN;
      if (clazz == char.class) return CHAR;
      if (clazz == byte.class) return BYTE;
      if (clazz == short.class) return SHORT;
      if (clazz == int.class) return INTEGER;
      if (clazz == float.class) return FLOAT;
      if (clazz == long.class) return LONG;
      if (clazz == double.class) return DOUBLE;
      if (clazz == void.class) return VOID;
    }
    if (clazz.isArray()) {
      int indices = 0;
      while (clazz.getComponentType() != null) { indices++; clazz = clazz.getComponentType(); }
      return getFor(getFor(clazz.getName()), indices);
    }
    return getFor(clazz.getName());
  }
 
  public static TypeDescriptor[] getFor (Class... classes) {
    TypeDescriptor[] types = new TypeDescriptor[classes.length];
    for (int i=0; i<classes.length; i++)
      types[i] = getFor(classes[i]);
    return types;
  }
 
  public static TypeDescriptor getFor (String className) {
    return new TypeDescriptor(className.replace('.', '/'));
  }
 
  public static TypeDescriptor[] getFor (String... classNames) {
    TypeDescriptor[] types = new TypeDescriptor[classNames.length];
    for (int i=0; i<classNames.length; i++)
      types[i] = getFor(classNames[i]);
    return types;
  }
 
  public static TypeDescriptor getFor (TypeDescriptor rootType, int indices) {
    return new TypeDescriptor(rootType, indices);
  }
 
  public static String toMethodDescriptor (TypeDescriptor returnType, TypeDescriptor... parameters) {
    StringBuilder sb = new StringBuilder();
   
    sb.append("(");
   
    for (int i=0; i<parameters.length; i++) {
      parameters[i].appendDescriptorString(sb);
    }
   
    sb.append(")");
   
    if (returnType == null)
      TypeDescriptor.VOID.appendDescriptorString(sb);
    else
      returnType.appendDescriptorString(sb);
   
    return sb.toString();
  }
 
  protected final String name;
  protected final boolean primitive;
  protected final int arrayIndices;
 
  protected final TypeDescriptor rootComponentType;
 
  protected String descriptor;
 
  private TypeDescriptor(String name) {
    this.name = name;
    this.primitive = false;
    this.arrayIndices = -1;
    this.rootComponentType = this;
  }
 
  private TypeDescriptor(TypeDescriptor rootType, int arrayIndices) {
    while (rootType.isArray()) {
      arrayIndices += rootType.arrayIndices;
      rootType = rootType.rootComponentType;
    }
    this.rootComponentType = rootType;
    this.name = rootType.name;
    this.primitive = false;
    this.arrayIndices = arrayIndices;
  }

  private TypeDescriptor(String name, boolean primitive) {
    this.name = name;
    this.primitive = primitive;
    this.arrayIndices = -1;
    this.rootComponentType = this;
  }
 
  /**
   * @param indices The indices
   * @return The array version of the basic component type
   */
  public TypeDescriptor getArrayType (int indices) {
    return new TypeDescriptor(rootComponentType, indices + this.arrayIndices);
  }
 
  /**
   * @return The valid java class name
   */
  public String getClassName () {
    if (this.primitive) {
      if (this == TypeDescriptor.BOOLEAN) return boolean.class.getName();
      else if (this == TypeDescriptor.BYTE) return byte.class.getName();
      else if (this == TypeDescriptor.CHAR) return char.class.getName();
      else if (this == TypeDescriptor.DOUBLE) return double.class.getName();
      else if (this == TypeDescriptor.FLOAT) return float.class.getName();
      else if (this == TypeDescriptor.INTEGER) return int.class.getName();
      else if (this == TypeDescriptor.LONG) return long.class.getName();
      else if (this == TypeDescriptor.SHORT) return short.class.getName();
      else if (this == TypeDescriptor.VOID) return void.class.getName();
    }
   
    return this.name.replace('/', '.');
  }

  /**
   * @return The internal JVM name of this type.
   */
  public String getName() { return name; }

  /**
   * @return True if this type represents a primitive
   */
  public boolean isPrimitive() { return primitive; }
 
  /**
   * @return If {@link #isPrimitive()} is true, the boxed type, otherwise an exception is thrown
   */
  public TypeDescriptor getBoxedType () {
    if (this.primitive) {
      if (this == INTEGER) return getFor(Integer.class);
      if (this == LONG) return getFor(Long.class);
      if (this == FLOAT) return getFor(Float.class);
      if (this == DOUBLE) return getFor(Double.class);
      if (this == SHORT) return getFor(Short.class);
      if (this == BYTE) return getFor(Byte.class);
      if (this == BOOLEAN) return getFor(Boolean.class);
      if (this == CHAR) return getFor(Character.class);
    }
    throw new BytecodeException("Cannot get a boxed type for a non-primitive");
  }
 
  /**
   * @return If {@link #isPrimitive()} is false and the type is a boxed type the unboxed type is returned, otherwise an exception is thrown
   */
  public TypeDescriptor getUnboxedType () {
    if (!this.primitive) {
      if (this.name.equals("java/lang/Integer")) return INTEGER;
      if (this.name.equals("java/lang/Long")) return LONG;
      if (this.name.equals("java/lang/Float")) return FLOAT;
      if (this.name.equals("java/lang/Double")) return DOUBLE;
      if (this.name.equals("java/lang/Short")) return SHORT;
      if (this.name.equals("java/lang/Byte")) return BYTE;
      if (this.name.equals("java/lang/Boolean")) return BOOLEAN;
      if (this.name.equals("java/lang/Character")) return CHAR;
    }
    throw new BytecodeException("Cannot get an unboxed type for a non primitive boxed type");
  }

  /**
   * @return True if this is an array, otherwise false
   */
  public boolean isArray() { return arrayIndices > 0; }

  /**
   * @return The indices of the array, or -1 if this is not an array
   */
  public int getIndices() { return arrayIndices; }
 
  /**
   * @return The component type descriptor if this is an array, otherwise null
   */
  public TypeDescriptor getComponentType () {
    if (this.arrayIndices < 1) return null;
    return this.arrayIndices == 1 ? new TypeDescriptor(name) : new TypeDescriptor(this.rootComponentType, arrayIndices - 1);
  }
 
  @Override public boolean equals(Object obj) {
    return obj instanceof TypeDescriptor ? this.compareTo((TypeDescriptor)obj) == 0 : false;
  }

  public int compareTo(TypeDescriptor o) {
    return name.compareTo(o.name);
  }

  /**
   * @return A valid internal JVM descriptor for this type
   */
  public String toDescriptorString () {
    if (this.primitive) { return this.name; }
    if (this.descriptor == null) {
      this.descriptor = this.appendDescriptorString(new StringBuilder()).toString();
    }
    return descriptor;
  }
 
  /**
   * This allows for efficiency when this descriptor is part of a larger
   * appending operation.
   *
   * @param sb The builder to append this descriptor to
   * @return The same builder for chaining
   */
  public StringBuilder appendDescriptorString (StringBuilder sb) {
    if (this.descriptor != null) { return sb.append(descriptor); }
    if (this.primitive) { sb.append(name); }
    else {
      if (this.arrayIndices > 0) {
        for (int i=0; i<this.arrayIndices; i++)
          sb.append("[");
      }
     
      if (this.rootComponentType.isPrimitive()) sb.append(this.rootComponentType.name);
      else sb.append("L").append(this.rootComponentType.name);
     
      sb.append(";");
    }
    return sb;
  }

}
TOP

Related Classes of net.sourceforge.javautil.bytecode.api.TypeDescriptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.