jan@866: /** jan@866: * Back 2 Browser Bytecode Translator jan@866: * Copyright (C) 2012 Jaroslav Tulach jan@866: * jan@866: * This program is free software: you can redistribute it and/or modify jan@866: * it under the terms of the GNU General Public License as published by jan@866: * the Free Software Foundation, version 2 of the License. jan@866: * jan@866: * This program is distributed in the hope that it will be useful, jan@866: * but WITHOUT ANY WARRANTY; without even the implied warranty of jan@866: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jan@866: * GNU General Public License for more details. jan@866: * jan@866: * You should have received a copy of the GNU General Public License jan@866: * along with this program. Look for COPYING file in the top folder. jan@866: * If not, see http://opensource.org/licenses/GPL-2.0. jan@866: */ jan@866: package org.apidesign.bck2brwsr.htmlpage; jan@866: jan@866: import java.io.IOException; jan@866: import java.io.OutputStreamWriter; jan@866: import java.io.Writer; jan@866: import java.util.Arrays; jan@866: import java.util.Collections; jan@866: import java.util.HashMap; jan@866: import java.util.Map; jan@866: import java.util.Map.Entry; jan@866: import java.util.ServiceLoader; jan@866: import javax.annotation.processing.ProcessingEnvironment; jan@866: import javax.lang.model.element.Element; jan@866: import javax.tools.Diagnostic; jan@866: import javax.tools.FileObject; jan@866: import org.netbeans.modules.html.editor.lib.api.HtmlVersion; jan@866: import org.netbeans.modules.html.editor.lib.api.model.HtmlModel; jan@866: import org.netbeans.modules.html.editor.lib.api.model.HtmlModelProvider; jan@866: import org.netbeans.modules.html.editor.lib.api.model.HtmlTag; jan@866: import org.netbeans.modules.html.editor.lib.api.model.HtmlTagAttribute; jan@866: jan@866: /** jan@866: * jan@866: * @author Jan Horvath jan@866: */ jan@866: public class ElementGenerator { jan@866: jan@866: static final Map NAMING_EXCEPTIONS = new HashMap() { jan@866: { jan@866: put("img", "Image"); jan@866: put("class", "Clazz"); jan@866: } jan@866: }; jan@866: jan@866: static final String javaKeywords[] = { jan@866: "abstract", "assert", "boolean", "break", "byte", "case", jan@866: "catch", "char", "class", "const", "continue", "default", jan@866: "do", "double", "else", "extends", "false", "final", "finally", jan@866: "float", "for", "goto", "if", "implements", "import", jan@866: "instanceof", "int", "interface", "long", "native", "new", jan@866: "null", "package", "private", "protected", "public", jan@866: "return", "short", "static", "strictfp", "super", jan@866: "switch", "synchronized", "this", "throw", "throws", jan@866: "transient", "true", "try", "void", "volatile", "while" jan@866: }; jan@866: jan@866: private static Map elements = new HashMap(); jan@866: private final ProcessingEnvironment processingEnv; jan@866: private HtmlModel model = null; jan@866: jan@866: ElementGenerator(ProcessingEnvironment processingEnv) { jan@866: this.processingEnv = processingEnv; jan@866: } jan@866: jan@866: String getType(String pkg, String tag, Element e) { jan@866: String className = elements.get(tag); jan@866: if (className == null) { jan@866: className = createClass(pkg, tag, e); jan@866: elements.put(tag, className); jan@866: } jan@866: return className; jan@866: } jan@866: jan@866: private String createClass(String pkg, String tag, Element e) { jan@866: String className = className(tag); jan@866: Writer w; jan@866: try { jan@866: FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e); jan@866: w = new OutputStreamWriter(java.openOutputStream()); jan@866: try { jan@866: w.append("package " + pkg + ";\n\n"); jan@866: w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n"); jan@866: PredefinedFields.appendImports(w, tag); jan@866: w.append("\n"); jan@866: jan@866: w.append("class ").append(className).append(" extends Element {\n\n"); jan@866: w.append(" public ").append(className).append("(String id) {\n"); jan@866: w.append(" super(id);\n"); jan@866: w.append(" }\n\n"); jan@866: for (Entry entry : getAttributes(tag).entrySet()) { jan@866: String attrName = entry.getKey(); jan@866: String attrType = entry.getValue(); jan@866: // getter jan@866: w.append(" public ").append(attrType).append(" ") jan@866: .append("get").append(className(attrName)).append("() {\n"); jan@866: w.append(" return (").append(attrType).append(")getAttribute(\"") jan@866: .append(attrName).append("\");\n"); jan@866: w.append(" }\n\n"); jan@866: // setter jan@866: w.append(" public void ") jan@866: .append("set").append(className(attrName)).append("(") jan@866: .append(attrType).append(" ").append(attributeName(attrName)).append(") {\n"); jan@866: w.append(" setAttribute(\"").append(attrName).append("\", ").append(attributeName(attrName)).append(");\n"); jan@866: w.append(" }\n\n"); jan@866: } jan@866: PredefinedFields.appendFields(w, tag); jan@866: w.append("}\n"); jan@866: } finally { jan@866: w.close(); jan@866: } jan@866: } catch (IOException ex) { jan@866: processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + className + ".java", e); jan@866: return null; jan@866: } jan@866: return className; jan@866: } jan@866: jan@866: Map getAttributes(String tagName) { jan@866: Map result = new HashMap(); jan@866: jan@866: if (model == null) { jan@866: // HtmlModelProvider modelProvider = Lookup.getDefault().lookup(HtmlModelProvider.class); jan@866: ServiceLoader hmpLoader = jan@866: ServiceLoader.load(HtmlModelProvider.class, this.getClass().getClassLoader()); jan@866: for (HtmlModelProvider htmlModelProvider : hmpLoader) { jan@866: model = htmlModelProvider.getModel(HtmlVersion.HTML5); jan@866: if (model != null) { jan@866: break; jan@866: } jan@866: } jan@866: } jan@866: jan@866: if (model == null) { jan@866: processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, jan@866: "HTML 5 model provider was not found on classpath"); jan@866: return Collections.emptyMap(); jan@866: } jan@866: HtmlTag tag = model.getTag(tagName); jan@866: for (HtmlTagAttribute attr : tag.getAttributes()) { jan@866: String name = attr.getName(); jan@866: String type = Attributes.TYPES.get(name); jan@866: if (type != null) { jan@866: result.put(name, type); jan@866: } jan@866: } jan@866: jan@866: return result; jan@866: } jan@866: jan@866: private String className(String s) { jan@866: if (s.length() == 0) { jan@866: return s; jan@866: } jan@866: String name = NAMING_EXCEPTIONS.get(s.toLowerCase()); jan@866: if (name == null) { jan@866: name = s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase(); jan@866: } jan@866: return name; jan@866: } jan@866: jan@866: private String attributeName(String s) { jan@866: if (Arrays.binarySearch(javaKeywords, s) >= 0) { jan@866: return String.format("%sAttr", s); jan@866: } jan@866: return s; jan@866: } jan@866: jan@866: }