1 /* 2 * Copyright (c) 2017, 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 24 import java.lang.reflect.Type; 25 import java.util.Random; 26 27 public class ValueTypeGenerator { 28 29 static class FieldDescriptor { 30 31 final public String name; 32 final public Type type; 33 34 public FieldDescriptor(String name, Type type) { 35 this.name = name; 36 this.type = type; 37 } 38 } 39 40 static Type[] typeArray; 41 static String[] defaultArray; 42 static int NB_TYPES = 9; 43 44 static { 45 typeArray = new Type[NB_TYPES]; 46 typeArray[0] = byte.class; 47 typeArray[1] = short.class; 48 typeArray[2] = int.class; 49 typeArray[3] = long.class; 50 typeArray[4] = char.class; 51 typeArray[5] = float.class; 52 typeArray[6] = double.class; 53 typeArray[7] = boolean.class; 54 typeArray[8] = Object.class; 55 56 } 57 58 static String defaultValue(Type t) { 59 switch(t.getTypeName()) { 60 case "byte": return "(byte)123"; 61 case "short": return "(short)32056"; 62 case "int": return "483647"; 63 case "long": return "922337203685477L"; 64 case "char": return "(char)65456"; 65 case "float": return "2.71828f"; 66 case "double": return "3.14159d"; 67 case "boolean": return "true"; 68 case "java.lang.Object": return "null"; 69 default: 70 throw new RuntimeException(); 71 } 72 } 73 static private String generateValueTypeInternal(Random random, String name, int nfields, int typeLimit) { 74 // generate the fields 75 FieldDescriptor[] fieldDescArray = new FieldDescriptor[nfields]; 76 for (int i = 0; i < nfields; i++) { 77 int idx = random.nextInt(typeLimit); 78 String fieldName = typeArray[idx].getTypeName()+"Field"+i; 79 fieldDescArray[i] = new FieldDescriptor(fieldName, typeArray[idx]); 80 } 81 82 String source = generateSource(name, fieldDescArray); 83 return source; 84 } 85 86 static public String generateValueType(Random random, String name, int nfields) { 87 return generateValueTypeInternal(random, name, nfields, NB_TYPES); 88 } 89 90 static public String generateValueTypeNoObjectRef(Random random, String name, int nfields) { 91 return generateValueTypeInternal(random, name, nfields, NB_TYPES - 1); 92 } 93 94 static String fieldsAsArgs(FieldDescriptor[] fields) { 95 StringBuilder sb = new StringBuilder(); 96 for (int i = 0; i < fields.length; i++) { 97 sb.append(fields[i].type).append(" ").append(fields[i].name); 98 if (i != fields.length - 1) { 99 sb.append(", "); 100 } 101 } 102 return sb.toString(); 103 } 104 105 static String generateSource(String name, FieldDescriptor[] fields) { 106 StringBuilder sb = new StringBuilder(); 107 108 // imports 109 sb.append("import java.io.PrintStream;\n\n"); 110 111 // class declaration 112 sb.append("public __ByValue final class ").append(name).append(" {\n"); 113 114 // field declarations 115 for (FieldDescriptor f : fields) { 116 sb.append("\tfinal public ").append(f.type).append(" "); 117 sb.append(f.name).append(";\n"); 118 } 119 sb.append("\n"); 120 121 // private constructor 122 sb.append("\tprivate ").append(name).append("() {\n"); 123 for (int i = 0 ; i < fields.length; i++) { 124 sb.append("\t\tthis.").append(fields[i].name).append(" = ").append(defaultValue(fields[i].type)).append(";\n"); 125 } 126 sb.append("\t}\n"); 127 sb.append("\n"); 128 129 // factory 130 sb.append("\t__ValueFactory static public ").append(name).append(" ").append("make").append(name).append("("); 131 sb.append(fieldsAsArgs(fields)); 132 sb.append(") {\n"); 133 sb.append("\t\t").append(name).append(" v = ").append("__MakeDefault ").append(name).append("();\n"); 134 for (int i = 0 ; i < fields.length; i++) { 135 sb.append("\t\tv.").append(fields[i].name).append(" = ").append(fields[i].name).append(";\n"); 136 } 137 sb.append("\t\treturn v;\n"); 138 sb.append("\t};\n"); 139 sb.append("\n"); 140 141 // default factory 142 sb.append("\t__ValueFactory static public ").append(name).append(" ").append("make").append(name).append("() {\n"); 143 sb.append("\t\t").append(name).append(" v = ").append("__MakeDefault ").append(name).append("();\n"); 144 for (int i = 0 ; i < fields.length; i++) { 145 sb.append("\t\tv.").append(fields[i].name).append(" = ").append(defaultValue(fields[i].type)).append(";\n"); 146 } 147 sb.append("\t\treturn v;\n"); 148 sb.append("\t}\n"); 149 sb.append("\n"); 150 151 // verify method 152 sb.append("\tstatic public boolean verify(").append(name).append(" value) {\n"); 153 for (FieldDescriptor f : fields) { 154 sb.append("\t\tif (value.").append(f.name).append(" != ").append(defaultValue(f.type)).append(") return false;\n"); 155 } 156 sb.append("\t\treturn true;\n"); 157 sb.append("\t}\n"); 158 159 // printLayout method 160 sb.append("\tstatic public void printLayout(PrintStream out) {\n"); 161 sb.append("\t\tout.println(\"").append(name).append(" fields: "); 162 for (int i = 0; i < fields.length; i++) { 163 sb.append(fields[i].type); 164 if (i != fields.length - 1) { 165 sb.append(", "); 166 } 167 } 168 sb.append("\");\n"); 169 sb.append("\t}\n"); 170 171 sb.append("}\n"); 172 173 return sb.toString(); 174 } 175 }