/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.visage.tools.tree.xml;
import org.visage.api.tree.UnitTree;
import com.sun.source.tree.LineMap;
import com.sun.tools.mjavac.code.Symbol;
import com.sun.tools.mjavac.code.Type;
import com.sun.tools.mjavac.model.JavacElements;
import com.sun.tools.mjavac.util.Context;
import com.sun.tools.mjavac.util.Convert;
import com.sun.tools.mjavac.util.Options;
import com.sun.tools.mjavac.util.Position;
import org.visage.tools.code.VisageTypes;
import java.util.HashMap;
import java.util.Map;
/**
* API for XSL stylesheets. This class provides access to symbols, types, command
* line options and line/colum number information to XSL stylesheets. While XSL
* can access types and symbols in the input AST document, more specific queries
* like subtype etc. will need API calls.
*
* XSL stylesheets can invoke methods of this class using the namespace URI
* http://xml.apache.org/xalan/java/org.visage.tools.tree.xml.Compiler.
*
* @author A. Sundararajan
*/
public final class Compiler {
// This method escapes special characters in String so that it can be used
// as string literal in source code.
public static String quoteString(String str) {
return Convert.quote(str);
}
// This method escapes special characters so that it can be used
// as character literal in source code.
public static String quoteChar(String str) {
return Convert.quote(str.charAt(0));
}
// type mirror from a given String name of type
public static Type typeMirror(String name) {
return typeSymbol(name).asType();
}
// type element from string name
public static Symbol typeElement(String name) {
return typeSymbol(name);
}
// synonym for typeElement
public static Symbol typeSymbol(String name) {
return elements().getTypeElement(name);
}
// package name from string name
public static Symbol packageElement(String name) {
return packageSymbol(name);
}
// synonym for packageSymbol
public static Symbol packageSymbol(String name) {
return elements().getTypeElement(name);
}
// symbol from symbol referen id
public static Symbol symbol(String id) {
return getState().converter.idToSymbol(id);
}
// synonym for symbol
public static Symbol element(String id) {
return symbol(id);
}
// type from type reference id
public static Type type(String id) {
return getState().converter.idToType(id);
}
public static VisageTypes types() {
return VisageTypes.instance(getState().context);
}
public static JavacElements symbols() {
return JavacElements.instance(getState().context);
}
// synonym to symbols
public static JavacElements elements() {
return symbols();
}
// access to command line options
public static String option(String name) {
return Options.instance(getState().context).get(name);
}
// line, column and position information
public static long line(long position) {
LineMap lm = getState().compilationUnit.getLineMap();
return (lm != null) ? lm.getLineNumber(position) : 0;
}
public static long column(long position) {
LineMap lm = getState().compilationUnit.getLineMap();
return (lm != null) ? lm.getColumnNumber(position) : 0;
}
public static long position(long line, long column) {
LineMap lm = getState().compilationUnit.getLineMap();
return (lm != null) ? lm.getPosition(line, column) : Position.NOPOS;
}
public static long startPosition(long line) {
LineMap lm = getState().compilationUnit.getLineMap();
return (lm != null) ? lm.getStartPosition(line) : Position.NOPOS;
}
// get/put globals in compiler context
public static Object getGlobal(String name) {
return getGlobalsMap().get(name);
}
public static Object putGlobal(String name, Object value) {
Object res = getGlobalsMap().put(name, value);
return (res != null)? res : "";
}
// scripting extension
// evaluate given script code
public static Object evalScriptFile(String file) throws Exception {
if (scriptingSupported) {
return ScriptEvaluator.evalScriptFile(getState().context, file);
} else {
throw new UnsupportedOperationException();
}
}
public static Object evalScript(String code) throws Exception {
if (scriptingSupported) {
return ScriptEvaluator.evalScript(getState().context, code);
} else {
throw new UnsupportedOperationException();
}
}
// package privates below this point
// enter compiler into specific context
static void enter(Context context, UnitTree cu, TreeXMLSerializer converter) {
context.getClass(); // null check
cu.getClass(); // null check
converter.getClass(); // null check
State s = new State();
s.context = context;
s.compilationUnit = cu;
s.converter = converter;
state.set(s);
}
// remove compiler state
static void leave() {
state.remove();
}
// -- Internals only below this point
private static boolean scriptingSupported;
static {
try {
Class.forName("javax.script.ScriptEngine");
scriptingSupported = true;
} catch (ClassNotFoundException cnfe) {
scriptingSupported = false;
}
}
private static class State {
Context context;
UnitTree compilationUnit;
TreeXMLSerializer converter;
}
private static ThreadLocal<State> state = new ThreadLocal<State>();
private static State getState() {
State s = state.get();
if (s == null) {
throw new IllegalStateException("compiler state is null!");
}
return s;
}
private static class Globals extends HashMap<String, Object> {
}
private static Map<String, Object> getGlobalsMap() {
Context context = getState().context;
Globals globals = context.get(Globals.class);
if (globals == null) {
globals = new Globals();
context.put(Globals.class, globals);
}
return globals;
}
// Don't create me!
private Compiler() {
}
}