| /******************************************************************************* |
| * Copyright (c) 2006 Oracle Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Oracle Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.bpel.validator.helpers; |
| |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| |
| /** |
| * @author Michal Chmielewski (michal.chmielewski@oracle.com) |
| * |
| * |
| */ |
| |
| @SuppressWarnings("nls") |
| public class JavaScriptSource { |
| |
| static final JavaScriptSource singleton = new JavaScriptSource(); |
| |
| static private Map<String,Boolean> R = new HashMap<String,Boolean>(); |
| |
| static { |
| addReserved ("abstract,as,boolean,break,byte,case,catch,char,class,continue"); |
| addReserved ("const,debugger,default,delete,do,double,else,enum,export,extends"); |
| addReserved ("false,final,finally,float,for,function,goto,if,implements"); |
| addReserved ("import,in,instanceof,int,interface,is,long,namespace,native"); |
| addReserved ("new,null,package,private,protected,public,return,short"); |
| addReserved( "static,super,switch,synchronized,this,throw,throws,transient"); |
| addReserved( "true,try,typeof,use,var,void,volatile,while,with"); |
| } |
| |
| static private void addReserved (String s) |
| { |
| StringTokenizer tokenizer = new StringTokenizer(s,",;"); |
| while (tokenizer.hasMoreElements()) { |
| String next = (String) tokenizer.nextElement(); |
| String nextTrim = next.trim(); |
| if (nextTrim.length() < 1) { |
| continue; |
| } |
| R.put(nextTrim, Boolean.TRUE); |
| } |
| } |
| |
| /** |
| * Answer if the word is reserved |
| * @param word |
| * @return true if so, false otherwise |
| */ |
| |
| static public boolean isReserved (String word) { |
| return R.containsKey(word); |
| } |
| |
| /** |
| * Answer if we are valid javascript identifier. |
| * |
| * @param word |
| * @return true of yes, false if no |
| */ |
| |
| static public boolean isValidJSIdentifier (String word) |
| { |
| for(int i=0, j=word.length(); i < j; i++) { |
| char ch = word.charAt(i); |
| if (i==0) { |
| if (Character.isJavaIdentifierStart(ch) == false) { |
| return false; |
| } |
| } else if (Character.isJavaIdentifierPart(ch) == false) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Return the singleton instance |
| * |
| * @return the singleton instance of this object |
| */ |
| |
| public static JavaScriptSource getInstance() { |
| return singleton; |
| } |
| |
| /** |
| * |
| * @author mchmiele |
| * |
| */ |
| static public class Expression |
| { |
| String mExpr; |
| /** |
| * @param str |
| */ |
| public Expression (String str) { |
| mExpr = str; |
| } |
| |
| /** |
| * @see java.lang.Object#toString() |
| */ |
| @Override |
| public String toString() |
| { |
| return mExpr; |
| } |
| } |
| |
| /** |
| * Convert a string into a JavaScript equivalent |
| * |
| * @param value |
| * @return a JavaScript string source representation |
| */ |
| |
| public String toSource(String value) { |
| if (value == null) { |
| return "null"; |
| } |
| |
| StringBuilder result = new StringBuilder(value.length()); |
| result.append('"'); |
| |
| for (int i = 0; i < value.length(); i++) { |
| char c = value.charAt(i); |
| |
| if (c == '"') { |
| result.append("\\\""); |
| } else if (c == '\\') { |
| result.append("\\\\"); |
| } else if (c == '\n') { |
| result.append("\\n"); |
| } else if (c == '\t') { |
| result.append("\\t"); |
| } else if (c == '\\') { |
| result.append("\\\\"); |
| } else if (c != '\r') { |
| result.append(c); |
| } |
| |
| // TODO: Need to deal with other unicode characters here ... |
| } |
| |
| result.append('"'); |
| return result.toString(); |
| } |
| |
| /** |
| * Dispatch method for conversion |
| * |
| * @param o any object |
| * @return the JavaScript equivalent |
| */ |
| public String toSource(Object o) { |
| if (o == null) { |
| return "null"; |
| } |
| if (o instanceof Map) { |
| return toSource( (Map<?,?>) o); |
| } |
| if (o instanceof Object[]) { |
| return toSource( (Object[]) o); |
| } |
| if (o instanceof List) { |
| return toSource( (List<?>) o); |
| } |
| if (o instanceof Number) { |
| return toSource( (Number) o); |
| } |
| if (o instanceof Boolean) { |
| return toSource( (Boolean) o); |
| } |
| if (o instanceof Date) { |
| return toSource( (Date) o); |
| } |
| if (o instanceof String) { |
| return toSource( (String) o); |
| } |
| if (o instanceof StringBuilder) { |
| return toSource ( ((StringBuilder)o).toString() ); |
| } |
| if (o instanceof Expression) { |
| return ((Expression)o).toString(); |
| } |
| return "null"; |
| } |
| |
| /** |
| * Maps of any kind (including HashMaps) |
| * |
| * <i>Note:</i> The only constraint here is that keys must make sense after being |
| * converted to JS object. That is, it must be a string |
| * |
| * @param aMap |
| * @return a JavaScript representation of that map |
| */ |
| |
| public String toSource(Map<?,?> aMap) { |
| |
| if (aMap == null) { |
| return "null"; |
| } |
| |
| // { name1:"value1", name2:"value2" } |
| |
| StringBuilder js = new StringBuilder("{"); |
| |
| for(Map.Entry<?, ?> entry : aMap.entrySet()) { |
| // Note: Although key is an object, it only makes sense if it can be converted |
| // into a JavaScript property, namely, a string |
| String key = entry.getKey().toString(); |
| if ( isReserved(key) || isValidJSIdentifier(key) == false) { |
| js.append( toSource( key ) ); |
| } else { |
| js.append( key ); |
| } |
| js.append(":"); |
| js.append(toSource(entry.getValue())); |
| js.append(","); |
| } |
| /** erase last , */ |
| if (js.length() > 1) { |
| js.setLength(js.length()-1); |
| } |
| js.append("}"); |
| return js.toString(); |
| } |
| |
| |
| /** |
| * Lists of any kind (including vectors) |
| * |
| * @param o the list object to convert |
| * @return a string to source rendition of this list |
| */ |
| |
| public String toSource(List<?> o) { |
| if (o == null) { |
| return "null"; |
| } |
| return toSource(o.toArray()); |
| } |
| |
| |
| /** |
| * Object arrays are JavaScript arrays |
| * @param o the object array to convert to JavaScript source |
| * @return a string to source rendition of this array |
| */ |
| public String toSource(Object[] o) { |
| if (o == null) { |
| return "null"; |
| } |
| |
| StringBuilder buf = new StringBuilder("["); |
| for (int i = 0; i < o.length; i++) { |
| if (i > 0) { |
| buf.append(','); |
| } |
| buf.append(toSource(o[i])); |
| } |
| buf.append("]"); |
| return buf.toString(); |
| } |
| |
| |
| /** |
| * |
| * @param d a date object |
| * @return a JS representation of a Date |
| */ |
| public String toSource(Date d) { |
| if (d == null) { |
| return "null"; |
| } |
| |
| return "new Date(" + d.getTime() + ")"; |
| } |
| |
| |
| /** |
| * |
| * @param n a number |
| * @return a JS script representation of a number |
| */ |
| |
| public String toSource(Number n) { |
| if (n == null) { |
| return "0"; |
| } |
| return n.toString(); |
| } |
| |
| /** |
| * |
| * @param b boolean |
| * @return a JS script representation of a boolean |
| */ |
| |
| public String toSource(Boolean b) { |
| if (b == null) { |
| return "false"; |
| } |
| return b.toString(); |
| } |
| |
| } |