0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.schema2beansdev.gen;
0043:
0044: import java.util.*;
0045: import java.io.*;
0046:
0047: /**
0048: * Various utility methods dealing with Java
0049: */
0050: public class JavaUtil {
0051: // This class is not for instantiating.
0052: private JavaUtil() {
0053: }
0054:
0055: /**
0056: * Convert primitives into Objects and leave objects as is.
0057: * @param expr the text expression representing some value
0058: * @param classType the current type of @param expr
0059: * ('age', 'int') -> 'new java.lang.Integer(age)'
0060: * ('age', 'Integer') -> 'age'
0061: */
0062: static public String toObject(String expr, String classType) {
0063: classType = classType.intern();
0064: if ("boolean" == classType)
0065: return "("
0066: + expr
0067: + " ? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE)";
0068: else {
0069: String objClass = (String) toObjectType.get(classType);
0070: if (objClass == null) {
0071: return expr;
0072: }
0073: return "new " + objClass + "(" + expr + ")";
0074: }
0075: }
0076:
0077: static public String toObject(String expr, String classType,
0078: boolean j2me) {
0079: if (j2me) {
0080: if ("boolean".equals(classType))
0081: return "new java.lang.Boolean(" + expr + ")";
0082: }
0083: return toObject(expr, classType);
0084: }
0085:
0086: static private Map toObjectType;
0087: static {
0088: toObjectType = new HashMap();
0089: toObjectType.put("int", "java.lang.Integer");
0090: toObjectType.put("char", "java.lang.Character");
0091: toObjectType.put("long", "java.lang.Long");
0092: toObjectType.put("short", "java.lang.Short");
0093: toObjectType.put("byte", "java.lang.Byte");
0094: toObjectType.put("float", "java.lang.Float");
0095: toObjectType.put("double", "java.lang.Double");
0096: toObjectType.put("boolean", "java.lang.Boolean");
0097: }
0098:
0099: /**
0100: * Take a Java primitive and return it's object type.
0101: * Return the same type if there isn't an object version.
0102: */
0103: static public String toObjectType(String classType) {
0104: String objClass = (String) toObjectType.get(classType);
0105: if (objClass == null)
0106: return classType;
0107: return objClass;
0108: }
0109:
0110: static private Map fromObjectType;
0111: static {
0112: fromObjectType = new HashMap();
0113: fromObjectType.put("java.lang.Integer", "int");
0114: fromObjectType.put("java.lang.Character", "char");
0115: fromObjectType.put("java.lang.Long", "long");
0116: fromObjectType.put("java.lang.Short", "short");
0117: fromObjectType.put("java.lang.Byte", "byte");
0118: fromObjectType.put("java.lang.Float", "float");
0119: fromObjectType.put("java.lang.Double", "double");
0120: fromObjectType.put("java.lang.Boolean", "boolean");
0121: fromObjectType.put("Integer", "int");
0122: fromObjectType.put("Character", "char");
0123: fromObjectType.put("Long", "long");
0124: fromObjectType.put("Short", "short");
0125: fromObjectType.put("Byte", "byte");
0126: fromObjectType.put("Float", "float");
0127: fromObjectType.put("Double", "double");
0128: fromObjectType.put("Boolean", "boolean");
0129: }
0130:
0131: /**
0132: * Take a Java boxed object (like Integer) and return it's primitive type.
0133: * Return the same type if there isn't a primitive version.
0134: */
0135: static public String fromObjectType(String classType) {
0136: String objClass = (String) fromObjectType.get(classType);
0137: if (objClass == null)
0138: return classType;
0139: return objClass;
0140: }
0141:
0142: /**
0143: * Convert expr into a String. Similar to toObject.
0144: * @param expr the value to convert into a String
0145: * @param type is the name of the current type
0146: * ('String', 'value') -> 'value'
0147: * ('int', '42') -> '""+42'
0148: * ('Integer', 'age') -> 'age.toString()'
0149: */
0150: static public String typeToString(String type, String expr) {
0151: type = (type == null) ? null : type.intern();
0152: if ("String" == type || "java.lang.String" == type)
0153: return expr;
0154: if (type == "java.util.Calendar")
0155: return "java.text.DateFormat.getInstance().format(" + expr
0156: + ".getTime())"; // See JavaBeansUtil for correctly printing out XML Schema format
0157: if (type == "boolean")
0158: return expr + " ? \"true\" : \"false\"";
0159: if (isPrimitiveType(type))
0160: return "\"\"+" + expr;
0161: return expr + ".toString()";
0162: }
0163:
0164: /**
0165: * @param expr is an Object type, and we will convert it
0166: * to a primitive.
0167: * eg: ('java.lang.Double', expr) -> '(java.lang.Double) expr'
0168: * eg: ('int', 'obj') -> '((java.lang.Integer)obj).intValue()'
0169: */
0170: static public String fromObject(String type, String expr) {
0171: type = type.intern();
0172: if (type == "int")
0173: return "((java.lang.Integer)" + expr + ").intValue()";
0174: if (type == "long")
0175: return "((java.lang.Long)" + expr + ").longValue()";
0176: if (type == "short")
0177: return "((java.lang.Short)" + expr + ").shortValue()";
0178: if (type == "byte")
0179: return "((java.lang.Byte)" + expr + ").byteValue()";
0180: if (type == "float")
0181: return "((java.lang.Float)" + expr + ").floatValue()";
0182: if (type == "double")
0183: return "((java.lang.Double)" + expr + ").doubleValue()";
0184: if (type == "char")
0185: return "((java.lang.Character)" + expr + ").charValue()";
0186: if (type == "boolean")
0187: return "((java.lang.Boolean)" + expr + ").booleanValue()";
0188: return "(" + type + ")" + expr;
0189: }
0190:
0191: /**
0192: * Is @param className immutable? An immutable object can hold state,
0193: * but after it's been constructed that state cannot change.
0194: */
0195: static public boolean isImmutable(String className) {
0196: className = className.intern();
0197: return immutableTable.containsKey(className);
0198: }
0199:
0200: static private Map immutableTable;
0201: static {
0202: immutableTable = new HashMap();
0203: immutableTable.put("String", null);
0204: immutableTable.put("java.lang.String", null);
0205: immutableTable.put("int", null);
0206: immutableTable.put("short", null);
0207: immutableTable.put("long", null);
0208: immutableTable.put("boolean", null);
0209: immutableTable.put("char", null);
0210: immutableTable.put("float", null);
0211: immutableTable.put("double", null);
0212: immutableTable.put("byte", null);
0213: immutableTable.put("java.lang.Boolean", null);
0214: immutableTable.put("java.lang.Byte", null);
0215: immutableTable.put("java.lang.Character", null);
0216: immutableTable.put("java.lang.Double", null);
0217: immutableTable.put("java.lang.Float", null);
0218: immutableTable.put("java.lang.Integer", null);
0219: immutableTable.put("java.lang.Long", null);
0220: immutableTable.put("java.lang.Short", null);
0221: immutableTable.put("Boolean", null);
0222: immutableTable.put("Byte", null);
0223: immutableTable.put("Character", null);
0224: immutableTable.put("Double", null);
0225: immutableTable.put("Float", null);
0226: immutableTable.put("Integer", null);
0227: immutableTable.put("Long", null);
0228: immutableTable.put("Short", null);
0229: immutableTable.put("java.math.BigInteger", null);
0230: immutableTable.put("java.math.BigDecimal", null);
0231: immutableTable.put("javax.xml.namespace.QName", null);
0232: immutableTable.put("org.netbeans.modules.schema2beans.QName",
0233: null);
0234: immutableTable.put("java.net.URI", null);
0235: }
0236:
0237: /**
0238: * Take a String (@param value) and generate Java code to coerce it.
0239: * eg: ('String', "Hello") -> '"Hello"'
0240: * ('int', '10') -> '10'
0241: * ('Integer', '43') -> 'new Integer(43)'
0242: * ('java.util.Locale', 'Locale.US') -> 'Locale.US'
0243: */
0244: public static String instanceFrom(String type, String value) {
0245: if (type == null)
0246: return value;
0247: type = type.intern();
0248: if (type == "java.lang.String" || type == "String") {
0249: StringBuffer buf = new StringBuffer("\"");
0250: for (int i = 0; i < value.length(); ++i) {
0251: char c = value.charAt(i);
0252: buf.append(escapeCharForInstance(c, '"'));
0253: }
0254: buf.append("\"");
0255: return buf.toString();
0256: }
0257: if (type == "java.lang.Character" || type == "Character") {
0258: return "new " + type + "(" + instanceFrom("char", value)
0259: + ")";
0260: }
0261: if (type == "Double" || type == "java.lang.Double"
0262: || type == "Integer" || type == "java.lang.Integer"
0263: || type == "Boolean" || type == "java.lang.Boolean"
0264: || type == "Float" || type == "java.lang.Float"
0265: || type == "Short" || type == "java.lang.Short"
0266: || type == "Long" || type == "java.lang.Long")
0267: return "new " + type + "(" + value + ")";
0268: if (type == "char[]" || type == "char []")
0269: return instanceFrom("java.lang.String", value)
0270: + ".toCharArray()";
0271: if (type == "char") {
0272: char c = value.charAt(0);
0273: return "'" + escapeCharForInstance(c, '\'') + "'";
0274: }
0275: if (type == "float")
0276: return value + "f";
0277: if (type == "java.math.BigDecimal"
0278: || type == "java.math.BigInteger") {
0279: // We will never need to escape anything inside value here.
0280: return "new " + type + "(\"" + value + "\")";
0281: }
0282: return value;
0283: }
0284:
0285: /**
0286: * A helper method for instanceFrom. We escape 1 char at a time here.
0287: */
0288: public static String escapeCharForInstance(char c, char illegalChar) {
0289: if (c == illegalChar)
0290: return "\\" + illegalChar;
0291: if (c == '\\')
0292: return "\\\\";
0293: if (c == '\b')
0294: return "\\b";
0295: if (c == '\t')
0296: return "\\t";
0297: if (c == '\n')
0298: return "\\n";
0299: if (c == '\f')
0300: return "\\f";
0301: if (c == '\r')
0302: return "\\r";
0303: if (c < ' ' || c > '\177')
0304: return uencode(c);
0305: return "" + c;
0306: }
0307:
0308: /**
0309: * Convert @param value2 (a literal) to @param type1 and then
0310: * compare that to @param value1.
0311: * @return Java code in a String, that returns negative, 0, or positive
0312: * if value1 < value2, value1 == value2, or value1 > value2.
0313: *
0314: * ("foo", "java.math.BigDecimal", "1") -> 'foo.compareTo(new java.math.BigDecimal("1"))'
0315: */
0316: public static String compareTo(String value1, String type1,
0317: String value2) {
0318: type1 = type1.intern();
0319: String value2Instance = genParseText(type1, value2);
0320: if (isPrimitiveType(type1)) {
0321: if ("\"0\"".equals(value2))
0322: return value1;
0323: return value1 + " - " + value2Instance;
0324: }
0325: return value1 + ".compareTo(" + value2Instance + ")";
0326: }
0327:
0328: /**
0329: * Just like compareTo, but the second value (@param value2Text) is
0330: * unquoted text.
0331: */
0332: public static String compareToText(String value1, String type1,
0333: String value2Text) {
0334: type1 = type1.intern();
0335: if (type1 == "int" || type1 == "short")
0336: return value1 + " - " + value2Text;
0337: if (type1 == "long")
0338: return value1 + " - " + value2Text + "L";
0339: if (type1 == "float")
0340: return value1 + " - " + value2Text + "f";
0341: if (type1 == "double")
0342: return value1 + " - " + value2Text + "d";
0343: return compareTo(value1, type1, instanceFrom(
0344: "java.lang.String", value2Text));
0345: }
0346:
0347: public static String genParseText(String type, String expr,
0348: boolean j2me) {
0349: if (j2me)
0350: return genParseTextME(type, expr);
0351: else
0352: return genParseText(type, expr);
0353: }
0354:
0355: /**
0356: * Take a particular @param type (eg: "java.lang.Integer") and return a
0357: * String that will parse the @param expr and make it into that type.
0358: * The value of @param expr should be a String.
0359: * eg: ('java.lang.Integer', 'node.getNodeValue()')
0360: * -> 'new java.lang.Integer(node.getNodeValue())'
0361: */
0362: public static String genParseText(String type, String expr) {
0363: if (type == null)
0364: return expr;
0365: type = type.intern();
0366: if (type == "java.lang.String" || type == "String")
0367: return expr;
0368: if (type == "boolean") {
0369: // The XML Schema spec part 2, section 3.2.2 says a boolean can
0370: // have any of these literal values: true, false, 1, 0.
0371: return "(\"true\".equalsIgnoreCase(" + expr
0372: + ") || \"1\".equals(" + expr + "))";
0373: //return "java.lang.Boolean.valueOf("+expr+").booleanValue()";
0374: }
0375: if (type == "java.lang.Boolean" || type == "Boolean")
0376: return genParseText("boolean", expr)
0377: + "? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE";
0378: if (type == "java.lang.Integer" || type == "Integer"
0379: || type == "java.lang.Long" || type == "Long"
0380: || type == "java.lang.Short" || type == "Short"
0381: || type == "java.lang.Float" || type == "Float"
0382: || type == "java.lang.Double" || type == "Double"
0383: || type == "java.lang.Byte" || type == "Byte"
0384: || type == "java.math.BigDecimal"
0385: || type == "BigDecimal"
0386: || type == "java.math.BigInteger"
0387: || type == "BigInteger"
0388: || type == "java.lang.StringBuffer"
0389: || type == "StringBuffer"
0390: || type == "java.text.MessageFormat"
0391: || type == "java.text.AttributedString"
0392: || type == "java.util.StringTokenizer"
0393: || type == "java.net.URI"
0394: || type == "javax.xml.namespace.QName"
0395: || type == "org.netbeans.modules.schema2beans.QName"
0396: || type == "java.io.File") { // NOI18N
0397: return "new " + type + "(" + expr + ")"; // NOI18N
0398: }
0399: if (type == "java.lang.Character")
0400: return "new java.lang.Character((" + expr + ").charAt(0))";
0401: if (type == "char[]" || type == "char []")
0402: return "(" + expr + ").toCharArray()";
0403: if (type == "long")
0404: return "Long.parseLong(" + expr + ")";
0405: if (type == "int")
0406: return "Integer.parseInt(" + expr + ")";
0407: if (type == "byte")
0408: return "Byte.parseByte(" + expr + ")";
0409: if (type == "short")
0410: return "Short.parseShort(" + expr + ")";
0411: if (type == "float")
0412: return "Float.parseFloat(" + expr + ")";
0413: if (type == "double")
0414: return "Double.parseDouble(" + expr + ")";
0415: if (type == "char")
0416: return "(" + expr + ").charAt(0)";
0417: if ("java.util.Date" == type)
0418: return "java.text.DateFormat.getInstance().parse(" + expr
0419: + ")";
0420: if ("javax.xml.soap.SOAPElement" == type)
0421: return "javax.xml.soap.SOAPElementFactory.newInstance().create("
0422: + expr + ").addTextNode(" + expr + ")"; // The parameter to create probably isn't quite correct.
0423: // See JavaBeansUtil for correctly printing out XML Schema format of java.util.Calendar
0424: return "/* UNKNOWN type for parsing:" + type + "*/ " + expr;
0425: }
0426:
0427: /**
0428: * Take a particular @param type (eg: "java.lang.Integer") and return a
0429: * String that will parse the @param expr and make it into that type.
0430: * The value of @param expr should be a String.
0431: * These work in *MIDP/J2ME*.
0432: * eg: ('java.lang.Integer', 'node.getNodeValue()')
0433: * -> 'new java.lang.Integer(node.getNodeValue())'
0434: */
0435: static public String genParseTextME(String type, String name) {
0436: String parm = name;
0437: type = type.intern();
0438: if (type == "String" || type == "java.lang.String")
0439: return parm;
0440: else if (type == "int")
0441: parm = "java.lang.Integer.parseInt(" + name + ")";
0442: else if (type == "short")
0443: parm = "java.lang.Short.parseShort(" + name + ")";
0444: else if (type == "long")
0445: parm = "java.lang.Long.parseLong(" + name + ")";
0446: else if (type == "boolean")
0447: parm = "(\"true\".equals(" + name + ") || \"1\".equals("
0448: + name + ") || \"TRUE\".equals(" + name
0449: + ") || \"True\".equals(" + name + "))";
0450: else if (type == "char")
0451: parm = name + ".charAt(0)";
0452: else if ("char[]" == type)
0453: parm = name + ".toCharArray()";
0454: else if ("java.lang.Integer" == type)
0455: parm = "new java.lang.Integer("
0456: + genParseTextME("int", name) + ")";
0457: else if ("java.lang.Long" == type)
0458: parm = "new java.lang.Long(" + genParseTextME("long", name)
0459: + ")";
0460: else if ("java.lang.Boolean" == type) {
0461: // The .TRUE or .FALSE trick doesn't seem to compile.
0462: //parm = "("+genParseTextME("boolean", name)+") ? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE";
0463: parm = "new java.lang.Boolean("
0464: + genParseTextME("boolean", name) + ")";
0465: } else if (type == "double")
0466: parm = "java.lang.Double.parseDouble(" + name + ")";
0467: else if (type == "float")
0468: parm = "java.lang.Float.parseFloat(" + name + ")";
0469: else if (type == "byte")
0470: parm = "java.lang.Byte.parseByte(" + name + ")";
0471: else if ("java.lang.Short" == type)
0472: parm = "new " + type + "(" + genParseTextME("short", name)
0473: + ")";
0474: else if ("java.lang.Byte" == type)
0475: parm = "new " + type + "(" + genParseTextME("byte", name)
0476: + ")";
0477: else if ("java.lang.Double" == type
0478: || "java.lang.Float" == type
0479: || "java.lang.StringBuffer" == type
0480: || "java.math.BigInteger" == type
0481: || "java.math.BigDecimal" == type)
0482: parm = "new " + type + "(" + name + ")";
0483: /*
0484: else if ("java.util.Date" == type)
0485: parm = "???";
0486: */
0487: else if ("java.lang.Character" == type)
0488: parm = "new " + type + "(" + name + ".charAt(0))";
0489: return parm;
0490: }
0491:
0492: /**
0493: * Take a particular @param type (eg: "java.lang.Integer") and return a
0494: * String that will parse the @param expr, making it into that type,
0495: * and storing the value into @param var.
0496: * The value of @param expr should be a String.
0497: */
0498: public static String genParseText(String type, String expr,
0499: String var) {
0500: return genParseText(type, expr, var, false);
0501: }
0502:
0503: public static String genParseText(String type, String expr,
0504: String var, boolean j2me) {
0505: if (type == null)
0506: return expr;
0507: type = type.intern();
0508: StringBuffer out = new StringBuffer();
0509: if (type == "java.util.Calendar") {
0510: // See JavaBeansUtil for correctly printing out XML Schema format of java.util.Calendar
0511: out.append(var);
0512: out.append(" = ");
0513: out.append("java.util.Calendar.getInstance(); ");
0514: out.append(var);
0515: out
0516: .append(".setTime(java.text.DateFormat.getInstance().parse(");
0517: out.append(expr);
0518: out.append("));");
0519: } else {
0520: out.append(var);
0521: out.append(" = ");
0522: out.append(genParseText(type, expr, j2me));
0523: out.append(";");
0524: }
0525: return out.toString();
0526: }
0527:
0528: /**
0529: * What exceptions might we encounter from doing the result of
0530: * genParseText. These exceptions are ones that we'd have to declare.
0531: */
0532: public static List exceptionsFromParsingText(String type) {
0533: return exceptionsFromParsingText(type, true);
0534: }
0535:
0536: public static List exceptionsFromParsingText(String type,
0537: boolean fromParsing) {
0538: List result = new ArrayList();
0539: if (type == null)
0540: return result;
0541: type = type.intern();
0542: if (type == "java.net.URI")
0543: result.add("java.net.URISyntaxException");
0544: if (fromParsing && type == "java.util.Calendar")
0545: result.add("java.text.ParseException");
0546: return result;
0547: }
0548:
0549: public static boolean isPrimitiveType(String className) {
0550: if (className == null)
0551: return false;
0552: className = className.intern();
0553: return ("long" == className || "int" == className
0554: || "char" == className || "short" == className
0555: || "double" == className || "float" == className
0556: || "byte" == className || "boolean" == className);
0557: }
0558:
0559: public static Class getPrimitive(String className) {
0560: className = className.intern();
0561: if (className == "int")
0562: return Integer.TYPE;
0563: if (className == "long")
0564: return Long.TYPE;
0565: if (className == "float")
0566: return Float.TYPE;
0567: if (className == "double")
0568: return Double.TYPE;
0569: if (className == "byte")
0570: return Byte.TYPE;
0571: if (className == "boolean")
0572: return Boolean.TYPE;
0573: if (className == "char")
0574: return Character.TYPE;
0575: if (className == "short")
0576: return Short.TYPE;
0577: if (className == "void")
0578: return Void.TYPE;
0579: return null;
0580: }
0581:
0582: public static boolean canProduceNoXMLMetaChars(String className) {
0583: className = fromObjectType(className).intern();
0584: return ("long" == className || "int" == className
0585: || "short" == className || "double" == className
0586: || "float" == className || "byte" == className
0587: || "boolean" == className
0588: || "java.math.BigDecimal" == className || "java.math.BigInteger" == className);
0589: }
0590:
0591: public static String nullValueForType(String type) {
0592: type = type.intern();
0593: if (type == "long" || type == "int" || type == "short"
0594: || type == "char" || type == "byte")
0595: return "0";
0596: if (type == "double")
0597: return "0.0";
0598: if (type == "float")
0599: return "0.0f";
0600: if (type == "boolean")
0601: return "false";
0602: return "null";
0603: }
0604:
0605: /**
0606: * @param type is the name of a class
0607: * @return a default value for that type.
0608: * eg: X -> new X()
0609: * java.math.BigDecimal -> new java.math.BigDecimal("0")
0610: * Integer -> new Integer("0")
0611: */
0612: public static String genNewDefault(String type) {
0613: type = type.intern();
0614: if ("java.lang.String" == type || "String" == type)
0615: return "\"\"";
0616: if (isPrimitiveType(type))
0617: return nullValueForType(type);
0618: if (type == "java.lang.Boolean" || type == "Boolean")
0619: return "java.lang.Boolean.FALSE";
0620: if (type == "java.lang.Integer" || type == "Integer"
0621: || type == "java.lang.Long" || type == "Long"
0622: || type == "java.lang.Short" || type == "Short"
0623: || type == "java.lang.Float" || type == "Float"
0624: || type == "java.lang.Double" || type == "Double"
0625: || type == "java.lang.Byte" || type == "Byte"
0626: || type == "java.math.BigInteger"
0627: || type == "BigInteger"
0628: || type == "java.math.BigDecimal"
0629: || type == "BigDecimal") { // NOI18N
0630: return "new " + type + "(\"0\")"; // NOI18N
0631: }
0632: if (type == "java.net.URI"
0633: || type == "javax.xml.namespace.QName"
0634: || type == "org.netbeans.modules.schema2beans.QName")
0635: return "new " + type + "(\"\")"; // NOI18N
0636: if (type == "java.lang.Character")
0637: return "new java.lang.Character('0')";
0638: if (type == "java.util.Calendar")
0639: return "java.util.Calendar.getInstance()";
0640: if (type == "byte[]")
0641: return "new byte[0]";
0642: if (type == "org.w3c.dom.Element")
0643: return "null"; // No default value
0644: return "new " + type + "()";
0645: }
0646:
0647: /**
0648: * Given a scalar type, figure out how to make it into an int
0649: * (ie, hash code).
0650: */
0651: static public String exprToInt(String type, String expr) {
0652: type = type.intern();
0653: if (type == "boolean")
0654: return expr + " ? 0 : 1";
0655: else if (type == "byte" || type == "char" || type == "short")
0656: return "(int) " + expr;
0657: else if (type == "int")
0658: return expr;
0659: else if (type == "long")
0660: return "(int)(" + expr + "^(" + expr + ">>>32))";
0661: else if (type == "float")
0662: return "Float.floatToIntBits(" + expr + ")";
0663: else if (type == "double")
0664: return exprToInt("long", "Double.doubleToLongBits(" + expr
0665: + ")");
0666: else
0667: return "(" + expr + ").hashCode()";
0668: }
0669:
0670: /**
0671: * @return an expression to compare to expressions; this can be put right
0672: * into an if statement.
0673: * ('int', 'var1', 'var2') -> 'var1 == var2'
0674: * ('String', 'word', '"hello"') -> 'word == null ? "hello" == null : word.equals("hello")'
0675: * ('float', 'var1', 'var2') -> 'Float.floatToIntBits(var1) == Float.floatToIntBits(var2)'
0676: */
0677: static public String genEquals(String type, String attr1,
0678: String attr2) {
0679: return genEquals(type, attr1, attr2, true);
0680: }
0681:
0682: /**
0683: * @param attr1CanBeNull whether or not attr1 could be null.
0684: */
0685: static public String genEquals(String type, String attr1,
0686: String attr2, boolean attr1CanBeNull) {
0687: type = type.intern();
0688: if (type == "float") {
0689: return "Float.floatToIntBits(" + attr1
0690: + ") == Float.floatToIntBits(" + attr2 + ")";
0691: } else if (type == "double") {
0692: return "Double.doubleToLongBits(" + attr1
0693: + ") == Double.doubleToLongBits(" + attr2 + ")";
0694: } else if (isPrimitiveType(type)) {
0695: return attr1 + " == " + attr2;
0696: } else if (attr1CanBeNull) {
0697: return attr1 + " == null ? " + attr2 + " == null : "
0698: + attr1 + ".equals(" + attr2 + ")";
0699: } else {
0700: return attr1 + ".equals(" + attr2 + ")";
0701: }
0702: }
0703:
0704: /**
0705: * Looks for the class and sees if it's cloneable.
0706: */
0707: public static boolean isCloneable(String className) {
0708: if (className == null)
0709: return false;
0710: className = className.intern();
0711: if (className == "java.util.Calendar")
0712: return true;
0713: try {
0714: //System.out.println("Looking for class: "+className);
0715: Class cls = Class.forName(className);
0716: if (cls == null)
0717: return false;
0718: //System.out.println("Found it");
0719: if (Cloneable.class.isAssignableFrom(cls)) {
0720: System.out.println(className + " is cloneable.");
0721: return true;
0722: }
0723: return false;
0724: } catch (ClassNotFoundException e) {
0725: return false;
0726: }
0727: }
0728:
0729: /**
0730: * Is the class not an interface and not abstract; i.e., it's possible
0731: * to call a constructor on this class. (Note that primitives fail.)
0732: */
0733: public static boolean isInstantiable(String className) {
0734: if (className == null)
0735: return false;
0736: className = className.intern();
0737: if (className == "String" || className == "java.lang.String")
0738: return true;
0739: try {
0740: //System.out.println("Looking for class: "+className);
0741: Class cls = Class.forName(className);
0742: if (cls == null)
0743: return false;
0744: //System.out.println("Found it: result="+cls.isInterface());
0745: if (cls.isInterface())
0746: return false;
0747: if (java.lang.reflect.Modifier.isAbstract(cls
0748: .getModifiers()))
0749: return false;
0750: return true;
0751: } catch (ClassNotFoundException e) {
0752: if (className.indexOf('.') < 0)
0753: return isInstantiable("java.lang." + className);
0754: return false;
0755: }
0756: }
0757:
0758: /**
0759: * checkValueToType will make sure that a given value is
0760: * acceptable for a given type. To make the problem more
0761: * tractable, this is limited to simple types.
0762: * eg:
0763: * ("java.lang.Integer", "1") -> true
0764: * ("java.lang.Integer", "1.5") -> false
0765: * ("java.lang.String", "ksadjflkjas24#@") -> true
0766: * ("short", "12345") -> true
0767: * ("short", "123456") -> false
0768: * Note that the 'tostr' template in javaGenLibrary.xsl has very
0769: * similar code and any changes should be made there too.
0770: */
0771: public static boolean checkValueToType(String type, String value) {
0772: //System.out.println("checkValueToType: type="+type+" value='"+value+"'");
0773: // We try to convert it (just like how javaGenLibrary.xsl
0774: // would generate code for). If an IllegalArgumentException
0775: // is thrown, then it's the wrong value for that type.
0776: try { // BEGIN_NOI18N
0777: if ("java.lang.String".equals(type)
0778: || "char[]".equals(type) || "char []".equals(type)
0779: || "char".equals(type) || "Character".equals(type)
0780: || "String".equals(type)
0781: || "java.lang.Character".equals(type))
0782: return true;
0783: else if ("long".equals(type))
0784: Long.parseLong(value);
0785: else if ("int".equals(type))
0786: Integer.parseInt(value);
0787: else if ("byte".equals(type))
0788: Byte.parseByte(value);
0789: else if ("short".equals(type))
0790: Short.parseShort(value);
0791: else if ("float".equals(type))
0792: Float.parseFloat(value);
0793: else if ("double".equals(type))
0794: Double.parseDouble(value);
0795: else if ("boolean".equals(type))
0796: Boolean.valueOf(value).booleanValue();
0797: else if ("java.lang.Double".equals(type))
0798: new java.lang.Double(value);
0799: else if ("java.lang.Integer".equals(type))
0800: new java.lang.Integer(value);
0801: else if ("java.lang.Boolean".equals(type))
0802: Boolean.valueOf(value);
0803: else if ("java.lang.Float".equals(type))
0804: new java.lang.Float(value);
0805: else if ("java.lang.Short".equals(type))
0806: new java.lang.Short(value);
0807: else if ("java.lang.Long".equals(type))
0808: new java.lang.Long(value);
0809: else if ("java.math.BigDecimal".equals(type))
0810: new java.math.BigDecimal(value);
0811: else if ("java.math.BigInteger".equals(type))
0812: new java.math.BigInteger(value);
0813: else if ("java.lang.StringBuffer".equals(type))
0814: new java.lang.StringBuffer(value);
0815: else if ("java.text.MessageFormat".equals(type))
0816: new java.text.MessageFormat(value);
0817: else if ("java.text.AttributedString".equals(type))
0818: new java.text.AttributedString(value);
0819: else if ("java.util.StringTokenizer".equals(type))
0820: new java.util.StringTokenizer(value);
0821: else { // END_NOI18N
0822: /*
0823: // Should do some reflection and see if a valueOf method
0824: // exists and takes a single String as an argument.
0825: Class clz = getClass(type);
0826: if (clz != null) {
0827: java.lang.reflect.Method meth =
0828: clz.getMethod("valueOf", new Class[] {String.class});
0829: if (meth == null || !Modifier.isStatic(meth.getModifiers())) {
0830: return false;
0831: }
0832: } else {
0833: return false;
0834: }
0835: // Could try to invoke the method too, but do we
0836: // really want to invoke a method from some random class.
0837: */
0838: if ("".equals(value)) // NOI18N
0839: return false; // Hack, should check value
0840: return true; // for now
0841: }
0842: } catch (IllegalArgumentException e) {
0843: return false;
0844: /*
0845: } catch (java.lang.ClassNotFoundException e) {
0846: LogFlags.lgr.println(LogFlags.DEBUG, LogFlags.module,
0847: LogFlags.DBG_VALIDATE, 100,
0848: "checkValueToType got ClassNotFoundException for type='"+type+"' value='"+value+"'");
0849: return false;
0850: } catch (NoSuchMethodException e) {
0851: LogFlags.lgr.println(LogFlags.DEBUG, LogFlags.module,
0852: LogFlags.DBG_VALIDATE, 100,
0853: "checkValueToType got NoSuchMethodException for type='"+type+"' value='"+value+"'");
0854: return false;
0855: */
0856: }
0857: return true;
0858: }
0859:
0860: static public String baseClassOfArray(String className) {
0861: // Does this handle more than 1 dimensional arrays correctly
0862: if (className.startsWith("[L") && className.endsWith(";")) { // NOI18N
0863: return className.substring(2, className.length() - 1);
0864: }
0865: return className.substring(0, className.length() - 2);
0866: }
0867:
0868: /**
0869: * This will return a name from @param fullClassName where everything upto
0870: * and including the last '.' is removed.
0871: * eg: "java.lang.String[]" -> "String[]"
0872: * "java.util.ArrayList" -> "ArrayList"
0873: */
0874: static public String baseName(String fullClassName) {
0875: int pos = fullClassName.lastIndexOf('.');
0876: if (pos == -1)
0877: return fullClassName;
0878: return fullClassName.substring(pos + 1, fullClassName.length());
0879: }
0880:
0881: private static final Class charArrayClass = java.lang.reflect.Array
0882: .newInstance(java.lang.Character.TYPE, 0).getClass();
0883:
0884: static public String getCanonicalClassName(Class cls) {
0885: if (charArrayClass.isAssignableFrom(cls))
0886: return "char[]"; // NOI18N
0887: if (cls.isArray())
0888: return baseClassOfArray(cls.getName()) + "[]";
0889: return cls.getName();
0890: }
0891:
0892: static public int getOptimialHashMapSize(Object[] keys) {
0893: return getOptimialHashMapSize(keys, keys.length * 8);
0894: }
0895:
0896: /**
0897: * Using reflection figure out the optimal initial capacity for a
0898: * HashMap given some keys. This uses a load factor of 1.0f.
0899: * By optimal, the table does not need resizing and there are
0900: * no lists (or chaining) being done in a HashMap.Entry.
0901: *
0902: * @param maxSize the point at which to give up (the maximum size to try)
0903: */
0904: static public int getOptimialHashMapSize(Object[] keys, int maxSize) {
0905: int keyLength = keys.length;
0906: int defaultAnswer = keyLength + 1;
0907: try {
0908: java.lang.reflect.Field tableField = HashMap.class
0909: .getDeclaredField("table");
0910: tableField.setAccessible(true);
0911: for (int tableSize = keyLength + 1; tableSize <= maxSize; tableSize <<= 1) {
0912: //System.out.println("tableSize="+tableSize);
0913: HashMap map = new HashMap(tableSize, 1.0f);
0914: for (int k = 0; k < keyLength; ++k) {
0915: map.put(keys[k], null);
0916: }
0917: Object[] table = (Object[]) tableField.get(map);
0918: int nullCount = 0;
0919: for (int i = 0; i < table.length; ++i) {
0920: //System.out.println("table["+i+"]="+table[i]);
0921: if (table[i] == null)
0922: ++nullCount;
0923: }
0924: //System.out.println("nullCount="+nullCount);
0925: if (table.length - nullCount != keyLength) {
0926: //System.out.println("A list had begun.");
0927: continue;
0928: }
0929: return table.length;
0930: }
0931: } catch (java.lang.IllegalAccessException e) {
0932: return defaultAnswer;
0933: } catch (java.lang.NoSuchFieldException e) {
0934: return defaultAnswer;
0935: }
0936: return defaultAnswer;
0937: }
0938:
0939: // Convert the @param in stream using native2ascii, assuming it's already
0940: // UTF-8 encoded.
0941: static public void native2ascii(Writer out, Reader in)
0942: throws java.io.IOException {
0943: FilterWriter n2afilter = new N2AFilter(out);
0944: copyStream(n2afilter, in);
0945: }
0946:
0947: static public class N2AFilter extends FilterWriter {
0948: public N2AFilter(Writer writer) {
0949: super (writer);
0950: }
0951:
0952: public void write(char[] cbuf) throws IOException {
0953: write(cbuf, 0, cbuf.length);
0954: }
0955:
0956: public void write(int c) throws IOException {
0957: write((char) c);
0958: }
0959:
0960: public void write(char c) throws IOException {
0961: //System.out.println("c="+c);
0962: if (c > '\177') {
0963: out.write(uencode(c));
0964: } else {
0965: out.write(c);
0966: }
0967: }
0968:
0969: public void write(char ac[], int off, int len)
0970: throws IOException {
0971: int end = off + len;
0972: for (int k = off; k < end; k++) {
0973: write(ac[k]);
0974: }
0975: }
0976:
0977: public void write(String str) throws IOException {
0978: write(str.toCharArray(), 0, str.length());
0979: }
0980:
0981: public void write(String str, int off, int len)
0982: throws IOException {
0983: write(str.toCharArray(), off, len);
0984: }
0985: }
0986:
0987: /**
0988: * Take a character and return the \ u (Unicode) representation of it.
0989: */
0990: public static String uencode(char c) {
0991: StringBuffer result = new StringBuffer("\\u");
0992: String s1 = Integer.toHexString(c);
0993: StringBuffer stringbuffer = new StringBuffer(s1);
0994: stringbuffer.reverse();
0995: int l = 4 - stringbuffer.length();
0996: for (int i1 = 0; i1 < l; i1++)
0997: stringbuffer.append('0');
0998:
0999: for (int j1 = 0; j1 < 4; j1++)
1000: result.append(stringbuffer.charAt(3 - j1));
1001: return result.toString();
1002: }
1003:
1004: public static final int BUFFER_SIZE = 4096;
1005:
1006: /**
1007: * copyStream is not really a Java Utility method, but it's needed by
1008: * one of them, and so is here.
1009: * @return the total length of the stream (in char's) copied.
1010: */
1011: public static int copyStream(Writer out, Reader in)
1012: throws java.io.IOException {
1013: int len;
1014: int totalLength = 0;
1015: char[] buf = new char[BUFFER_SIZE];
1016: while ((len = in.read(buf, 0, BUFFER_SIZE)) != -1) {
1017: out.write(buf, 0, len);
1018: totalLength += len;
1019: }
1020: out.flush();
1021: return totalLength;
1022: }
1023:
1024: /**
1025: * copyStream is not really a Java Utility method, but it's needed by
1026: * one of them, and so is here.
1027: * @return the total length of the stream (in char's) copied.
1028: */
1029: public static int copyStream(OutputStream out, InputStream in)
1030: throws java.io.IOException {
1031: int len;
1032: int totalLength = 0;
1033: byte[] buf = new byte[BUFFER_SIZE];
1034: while ((len = in.read(buf, 0, BUFFER_SIZE)) != -1) {
1035: out.write(buf, 0, len);
1036: totalLength += len;
1037: }
1038: out.flush();
1039: return totalLength;
1040: }
1041:
1042: static public class InputMonitor implements Runnable {
1043: private InputStream is;
1044: private OutputStream out;
1045:
1046: public InputMonitor(InputStream is, OutputStream out) {
1047: this .is = is;
1048: this .out = out;
1049: }
1050:
1051: /**
1052: * Copy the contents of the InputStream to the Writer.
1053: * Remember to close the InputStream or else this Thread will
1054: * never end.
1055: */
1056: public void run() {
1057: //System.out.println("Starting InputMonitor thread");
1058: try {
1059: int c;
1060: while ((c = is.read()) != -1) {
1061: byte ch = (byte) c;
1062: out.write(ch);
1063: }
1064: out.flush();
1065: } catch (java.io.IOException e) {
1066: try {
1067: out.write(e.getMessage().getBytes());
1068: } catch (java.io.IOException e2) {
1069: // try only once.
1070: }
1071: }
1072: //System.out.println("Finished InputMonitor thread");
1073: }
1074: }
1075:
1076: private static Map reservedWords;
1077: static {
1078: reservedWords = new HashMap();
1079: reservedWords.put("abstract", "_abstract");
1080: reservedWords.put("assert", "_assert");
1081: reservedWords.put("boolean", "_boolean");
1082: reservedWords.put("break", "_break");
1083: reservedWords.put("byte", "_byte");
1084: reservedWords.put("case", "_case");
1085: reservedWords.put("catch", "_catch");
1086: reservedWords.put("char", "_char");
1087: reservedWords.put("class", "_class");
1088: reservedWords.put("const", "_const");
1089: reservedWords.put("continue", "_continue");
1090: reservedWords.put("default", "_default");
1091: reservedWords.put("do", "_do");
1092: reservedWords.put("double", "_double");
1093: reservedWords.put("else", "_else");
1094: reservedWords.put("extends", "_extends");
1095: reservedWords.put("false", "_false");
1096: reservedWords.put("final", "_final");
1097: reservedWords.put("finally", "_finally");
1098: reservedWords.put("float", "_float");
1099: reservedWords.put("for", "_for");
1100: reservedWords.put("goto", "_goto");
1101: reservedWords.put("if", "_if");
1102: reservedWords.put("implements", "_implements");
1103: reservedWords.put("import", "_import");
1104: reservedWords.put("instanceof", "_instanceof");
1105: reservedWords.put("int", "_int");
1106: reservedWords.put("interface", "_interface");
1107: reservedWords.put("long", "_long");
1108: reservedWords.put("native", "_native");
1109: reservedWords.put("new", "_new");
1110: reservedWords.put("null", "_null");
1111: reservedWords.put("package", "_package");
1112: reservedWords.put("private", "_private");
1113: reservedWords.put("protected", "_protected");
1114: reservedWords.put("public", "_public");
1115: reservedWords.put("return", "_return");
1116: reservedWords.put("short", "_short");
1117: reservedWords.put("static", "_static");
1118: reservedWords.put("strictfp", "_strictfp");
1119: reservedWords.put("super", "_super");
1120: reservedWords.put("switch", "_switch");
1121: reservedWords.put("synchronized", "_synchronized");
1122: reservedWords.put("this", "_this");
1123: reservedWords.put("throw", "_throw");
1124: reservedWords.put("throws", "_throws");
1125: reservedWords.put("transient", "_transient");
1126: reservedWords.put("true", "_true");
1127: reservedWords.put("try", "_try");
1128: reservedWords.put("void", "_void");
1129: reservedWords.put("volatile", "_volatile");
1130: reservedWords.put("while", "_while");
1131: }
1132:
1133: public static boolean reservedWord(String name) {
1134: return reservedWords.containsKey(name);
1135: }
1136: }
|