/******************************************************************************* * Copyright (c) 2004, 2008 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 Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.jsdt.web.core.javascript; import java.io.File; /** * * Provisional API: This class/interface is part of an interim API that is still under development and expected to * change significantly before reaching stability. It is being made available at this early stage to solicit feedback * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken * (repeatedly) as the API evolves. */ public class JsNameManglerUtil { /** * Determine if given string is a valid Hex representation of an ASCII * character (eg. 2F -> /) * * @param possible * @return */ private static boolean isValid(String possible) { boolean result = false; if (possible.length() == 2) { char c1 = possible.charAt(0); char c2 = possible.charAt(1); // 1st character must be a digit if (Character.isDigit(c1)) { // 2nd character must be digit or upper case letter A-F if (Character.isDigit(c2)) { result = true; } else if (Character.isUpperCase(c2) && (c2 == 'A' || c2 == 'B' || c2 == 'C' || c2 == 'D' || c2 == 'E' || c2 == 'F')) { result = true; } } } return result; } /** * Mangle string to WAS-like specifications * */ public final static String mangle(String name) { StringBuffer modifiedName = new StringBuffer(); // extension (.jsp, .jspf, .jspx, etc...) should already be encoded in // name int length = name.length(); // in case name is forbidden (a number, class, for, etc...) modifiedName.append('_'); // ensure rest of characters are valid for (int i = 0; i < length; i++) { char currentChar = name.charAt(i); if (Character.isJavaIdentifierPart(currentChar) == true) { modifiedName.append(currentChar); } else { modifiedName.append(JsNameManglerUtil.mangleChar(currentChar)); } } return modifiedName.toString(); } /** * take a character and return its hex equivalent */ private final static String mangleChar(char ch) { if (ch == File.separatorChar) { ch = '/'; } if (Character.isLetterOrDigit(ch) == true) { return "" + ch; //$NON-NLS-1$ } return "_" + Integer.toHexString(ch).toUpperCase() + "_"; //$NON-NLS-1$ //$NON-NLS-2$ } /** * WAS mangles Tom&Jerry as: _Tom_26_Jerry; this takes in the mangled name * and returns the original name. * * Unmangles the qualified type name. If an underscore is found it is * assumed to be a mangled representation of a non-alpha, non-digit * character of the form _NN_, where NN are hex digits representing the * encoded character. This routine converts it back to the original * character. */ public final static String unmangle(String qualifiedTypeName) { if (qualifiedTypeName.charAt(0) != '_') { return qualifiedTypeName; } StringBuffer buf = new StringBuffer(); String possible = ""; //$NON-NLS-1$ // remove the .java extension if there is one if (qualifiedTypeName.endsWith(".js")) { //$NON-NLS-1$ qualifiedTypeName = qualifiedTypeName.substring(0, qualifiedTypeName.length() - 3); } for (int i = 1; i < qualifiedTypeName.length(); i++) { // start at // index 1 b/c // 1st char is // always '_' char c = qualifiedTypeName.charAt(i); if (c == '_') { int endIndex = qualifiedTypeName.indexOf('_', i + 1); if (endIndex == -1) { buf.append(c); } else { char unmangled; try { possible = qualifiedTypeName.substring(i + 1, endIndex); if (JsNameManglerUtil.isValid(possible)) { unmangled = (char) Integer.decode("0x" + possible).intValue();//$NON-NLS-1$ i = endIndex; } else { unmangled = c; } } catch (NumberFormatException e) { unmangled = c; } buf.append(unmangled); } } else { buf.append(c); } } return buf.toString(); } }