001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.utils.bytecode; 022 023/** 024 * A template type. 025 * 026 * <p>Template types are resolved at code-generation type rather than at 027 * Instruction generation type. They let you bind the concrete type for opcodes 028 * at the last minute, so the same max conditional could be used for all 029 * primative types, with the type only being bound at the last moment.</p> 030 * 031 * <p>Two ParametricType instances are the same if they are the same object, 032 * regardless of their names.</p> 033 * 034 * @author Matthew Pocock 035 */ 036 037public class ParametricType { 038 private static CodeClass[] OBJECT_CC; 039 040 static { 041 OBJECT_CC = new CodeClass[] { IntrospectedCodeClass.forClass(Object.class) }; 042 } 043 044 /** 045 * Create a new ParametricType that claims nothing. 046 * 047 * @param name the name given to this type 048 * @return a new ParametricType instance with that name 049 */ 050 public static ParametricType createType(String name) { 051 return new ParametricType(name, false, false, false); 052 } 053 054 /** 055 * Create a new ParametricType that claims to resolve to a primative type. 056 * 057 * @param name the name given to this type 058 * @return a new ParametricType instance with that name 059 */ 060 public static ParametricType createPrimitiveType(String name) { 061 return new ParametricType(name, true, false, false); 062 } 063 064 /** 065 * Create a new ParametricType that claims to resolve to an object type. 066 * 067 * @param name the name given to this type 068 * @return a new ParametricType instance with that name 069 */ 070 public static ParametricType createObjectType(String name) { 071 return new ParametricType(name, false, true, false); 072 } 073 074 /** 075 * Create a new ParametricType that claims to resolve to an array type. All 076 * array types are object types. 077 * 078 * @param name the name given to this type 079 * @return a new ParametricType instance with that name 080 */ 081 public static ParametricType createArrayType(String name) { 082 return new ParametricType(name, false, true, true); 083 } 084 085 /** 086 * Create a new ParametricType that claims to be castable to all the classes 087 * in a list. Since neither Java nor bytecode support multiple inheritance, 088 * the classes must either be interfaces, or classes that fall into an 089 * inheritance path. 090 * 091 * @param name the name given to this type 092 * @param classes an array of Class objects that any bound type must be 093 * castable to 094 * @return a new ParametricType that can bind to classes with these properties 095 */ 096 public static ParametricType createType( 097 String name, 098 CodeClass[] classes 099 ) { 100 return new ParametricType(name, classes); 101 } 102 103 private final String name; 104 private final boolean isPrimitive; 105 private final boolean isObject; 106 private final boolean isArray; 107 private final CodeClass[] classes; 108 109 private ParametricType( 110 String name, 111 boolean isPrimitive, 112 boolean isObject, 113 boolean isArray 114 ) { 115 this.name = name; 116 this.isPrimitive = isPrimitive; 117 this.isObject = isObject; 118 this.isArray = isArray; 119 if(isObject) { 120 this.classes = OBJECT_CC; 121 } else { 122 this.classes = CodeUtils.EMPTY_LIST; 123 } 124 } 125 126 private ParametricType( 127 String name, 128 CodeClass[] classes 129 ) { 130 this.name = name; 131 this.classes = classes; 132 this.isObject = true; 133 this.isPrimitive = false; 134 this.isArray = false; 135 } 136 137 /** 138 * Get the name of this type. 139 * 140 * Names are not unique. 141 * 142 * @return the name given to this type 143 */ 144 public String getName() { 145 return name; 146 } 147 148 /** 149 * Discover if this type must resolve to a primative. 150 * 151 * <p>It is an error for a parametric type to resolve to a non-primative if 152 * this flag is set.</p> 153 * 154 * @return true if this is guaranteed to resolve to a primative 155 */ 156 public boolean isPrimitive() { 157 return isPrimitive; 158 } 159 160 public boolean isObject() { 161 return isObject; 162 } 163 164 public boolean isArray() { 165 return isArray; 166 } 167 168 public boolean canAccept(CodeClass cc) { 169 if(cc.isArray() && this.isArray()) { 170 return true; 171 } 172 173 if(!cc.isPrimitive() && this.isObject()) { 174 return true; 175 } 176 177 if(cc.isPrimitive() && this.isPrimitive()) { 178 return true; 179 } 180 181 return false; 182 } 183 184 public CodeClass[] getClasses() { 185 return classes; 186 } 187 188 public String toString() { 189 return "GenericType:" + name; 190 } 191}