/**
* <copyright>
*
* Copyright (c) 2002-2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Martin Taal - Simplified specific methods
*
* </copyright>
*
* $Id: Literals.java,v 1.7 2011/08/25 12:35:07 mtaal Exp $
*/
package org.eclipse.emf.texo.modelgenerator.annotator;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.eclipse.emf.ecore.EAttribute;
/**
* Utility class for converting primitive values, strings, and classes to literals that could appear in code.
*
* NOTE: partially copied from org.eclipse.emf.codegen.ecore.genmodel.impl.Literals, simplified version of that class.
* Copyright and credits to the authors of that specific class.
*/
public class Literals {
// Suppress default constructor for non-instantiability.
private Literals() {
super();
}
private static final SimpleDateFormat xmlDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S'Z'"); //$NON-NLS-1$
/**
* Returns a valid String representation of a value. This String can be placed in the source code to initialize a java
* member.
*
* @param value
* the value which is converted to a valid string member-initializing String
* @return a String which can be placed inside a template to initialize the source.
*/
public static String toLiteral(final Class<?> clz, final Object value) {
if (!clz.isArray()) {
return toLiteral(clz, value.toString());
}
final Class<?> componentType = clz.getComponentType();
final StringBuilder sb = new StringBuilder();
sb.append("new " + componentType.getName() + //$NON-NLS-1$
"[]{"); //$NON-NLS-1$
// convert the values
for (int i = 0; i < Array.getLength(value); i++) {
final Object o = Array.get(value, i);
if (sb.length() > 0) {
sb.append(","); //$NON-NLS-1$
}
sb.append(toLiteral(componentType, o));
}
sb.append("}"); //$NON-NLS-1$
return sb.toString();
}
/**
* Method which can create a type-safe (to-be-used-in-a-template) version of the default value. It can handle all java
* lang types and Date, BigDecimal and BigInteger. If the method can not handle a class then null is returned.
*
* The method automatically adds types to the import names set of the GenContext.
*
* @param clz
* the result should be valid for this class
* @param literalValue
* the value as specified in the EAttribute ( {@link EAttribute#getDefaultValueLiteral()} ).
* @param genContext
* is used to add qualified java names to the stack of import statements (
* {@link ModelGenAnnotatorContext#getImportedName(GenEPackage, String)} )
* @return a String which can be used in a template as the initialization value of a java member.
*/
public static String toLiteral(final Class<?> clz, final String literalValue) {
if (clz.isArray()) {
final Class<?> componentType = clz.getComponentType();
final StringBuilder sb = new StringBuilder();
for (final String arrayPart : literalValue.split(",")) { //$NON-NLS-1$
if (sb.length() > 0) {
sb.append(", "); //$NON-NLS-1$
}
sb.append(toLiteral(componentType, arrayPart.trim()));
}
return "new " + componentType.getName() + //$NON-NLS-1$
"[]{" + sb.toString() + //$NON-NLS-1$
"}"; //$NON-NLS-1$
}
if (clz == Boolean.class) {
return "Boolean." + literalValue.toUpperCase(Locale.ENGLISH); //$NON-NLS-1$
} else if (clz == Boolean.TYPE) {
return literalValue.toLowerCase(Locale.ENGLISH);
} else if (clz == Byte.class) {
return "new Byte((byte)" + literalValue + //$NON-NLS-1$
")"; //$NON-NLS-1$
} else if (clz == Byte.TYPE) {
return literalValue;
} else if (clz == Short.class) {
return "new Short((short)" + literalValue + //$NON-NLS-1$
")"; //$NON-NLS-1$
} else if (clz == Short.TYPE) {
return literalValue;
} else if (clz == Integer.class) {
return "new Integer(" + literalValue + //$NON-NLS-1$
")"; //$NON-NLS-1$
} else if (clz == Integer.TYPE) {
return literalValue;
} else if (clz == Long.class) {
return "new Long(" + literalValue + //$NON-NLS-1$
")"; //$NON-NLS-1$
} else if (clz == Long.TYPE) {
return literalValue;
} else if (clz == Float.class) {
return "new Float(" + literalValue + //$NON-NLS-1$
"f)"; //$NON-NLS-1$
} else if (clz == Float.TYPE) {
return literalValue + "f"; //$NON-NLS-1$
} else if (clz == Double.class) {
return "new Double(" + literalValue + //$NON-NLS-1$
")"; //$NON-NLS-1$
} else if (clz == Double.TYPE) {
return literalValue;
} else if (clz == Character.class) {
return "new Character(" + toCharLiteral(literalValue) + //$NON-NLS-1$
")"; //$NON-NLS-1$
} else if (clz == Character.TYPE) {
return toCharLiteral(literalValue);
} else if (clz == String.class) {
return toStringLiteral(literalValue);
} else if (clz == BigDecimal.class) {
return "new " + BigDecimal.class.getName() + //$NON-NLS-1$
"(\"" + literalValue //$NON-NLS-1$
+ "\")"; //$NON-NLS-1$
} else if (clz == BigInteger.class) {
return "new " + BigInteger.class.getName() + //$NON-NLS-1$
"(\"" + literalValue //$NON-NLS-1$
+ "\")"; //$NON-NLS-1$
} else if (clz == Date.class) {
try {
final Date dt = xmlDateFormat.parse(literalValue);
return "new " + Date.class.getName() + //$NON-NLS-1$
"(" + dt.getTime() + //$NON-NLS-1$
")"; //$NON-NLS-1$
} catch (final ParseException e) {
return "new Date(" + toStringLiteral(literalValue) + //$NON-NLS-1$
")"; //$NON-NLS-1$
}
} else if (clz == java.sql.Date.class) {
try {
final Date dt = xmlDateFormat.parse(literalValue);
return "new " + java.sql.Date.class.getName() + //$NON-NLS-1$
"(" //$NON-NLS-1$
+ dt.getTime() + ")"; //$NON-NLS-1$
} catch (final ParseException e) {
return "new Date(" + toStringLiteral(literalValue) + //$NON-NLS-1$
")"; //$NON-NLS-1$
}
} else if (clz == java.sql.Timestamp.class) {
try {
final Date dt = xmlDateFormat.parse(literalValue);
return "new " + java.sql.Timestamp.class.getName() + //$NON-NLS-1$
"(" //$NON-NLS-1$
+ dt.getTime() + ")"; //$NON-NLS-1$
} catch (final ParseException e) {
return "new Date(" + toStringLiteral(literalValue) + //$NON-NLS-1$
")"; //$NON-NLS-1$
}
}
return null;
}
private static String toCharLiteral(final String literalValue) {
final StringBuilder result = new StringBuilder(8);
result.append('\'');
result.append(escapeChar(literalValue.toCharArray()[0]));
result.append('\'');
return result.toString();
}
/**
* Returns a literal expression for the given <code>String</code>. Each of its characters will appear in the same form
* as if it was the argument to {@link #toCharLiteral}.
*/
public static String toStringLiteral(final String s) {
if (s == null) {
return GenConstants.NULL;
}
final int len = s.length();
final StringBuilder result = new StringBuilder(len + 16);
result.append('\"');
for (int i = 0; i < len; i++) {
result.append(escapeChar(s.charAt(i)));
}
result.append('\"');
return result.toString();
}
private static String escapeChar(final char c) {
if (c == '\b') {
return "\\b"; //$NON-NLS-1$
}
if (c == '\t') {
return "\\t"; //$NON-NLS-1$
}
if (c == '\n') {
return "\\n"; //$NON-NLS-1$
}
if (c == '\f') {
return "\\f"; //$NON-NLS-1$
}
if (c == '\r') {
return "\\r"; //$NON-NLS-1$
}
if (c == '\"') {
return "\\\""; //$NON-NLS-1$
}
if (c == '\'') {
return "\\\'"; //$NON-NLS-1$
}
if (c == '\\') {
return "\\\\"; //$NON-NLS-1$
}
if (c >= 32 && c < 127) {
return String.valueOf(c);
}
// escaped unicode form
final String num = Integer.toHexString(c);
switch (num.length()) {
case 1:
return "\\u000" + num; //$NON-NLS-1$
case 2:
return "\\u00" + num; //$NON-NLS-1$
case 3:
return "\\u0" + num; //$NON-NLS-1$
}
return "\\u" + num; //$NON-NLS-1$
}
}