javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ElementGenerator.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 02 May 2013 10:08:35 +0200
branchelements
changeset 1073 9321b4016d5c
child 1074 3ab2f70b300d
permissions -rw-r--r--
Hopefully resuscitating the original code from rev. 146ae7b52b64 by manual merge
jan@866
     1
/**
jan@866
     2
 * Back 2 Browser Bytecode Translator
jan@866
     3
 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jan@866
     4
 *
jan@866
     5
 * This program is free software: you can redistribute it and/or modify
jan@866
     6
 * it under the terms of the GNU General Public License as published by
jan@866
     7
 * the Free Software Foundation, version 2 of the License.
jan@866
     8
 *
jan@866
     9
 * This program is distributed in the hope that it will be useful,
jan@866
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jan@866
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jan@866
    12
 * GNU General Public License for more details.
jan@866
    13
 *
jan@866
    14
 * You should have received a copy of the GNU General Public License
jan@866
    15
 * along with this program. Look for COPYING file in the top folder.
jan@866
    16
 * If not, see http://opensource.org/licenses/GPL-2.0.
jan@866
    17
 */
jan@866
    18
package org.apidesign.bck2brwsr.htmlpage;
jan@866
    19
jan@866
    20
import java.io.IOException;
jan@866
    21
import java.io.OutputStreamWriter;
jan@866
    22
import java.io.Writer;
jan@866
    23
import java.util.Arrays;
jan@866
    24
import java.util.Collections;
jan@866
    25
import java.util.HashMap;
jan@866
    26
import java.util.Map;
jan@866
    27
import java.util.Map.Entry;
jan@866
    28
import java.util.ServiceLoader;
jan@866
    29
import javax.annotation.processing.ProcessingEnvironment;
jan@866
    30
import javax.lang.model.element.Element;
jan@866
    31
import javax.tools.Diagnostic;
jan@866
    32
import javax.tools.FileObject;
jan@866
    33
import org.netbeans.modules.html.editor.lib.api.HtmlVersion;
jan@866
    34
import org.netbeans.modules.html.editor.lib.api.model.HtmlModel;
jan@866
    35
import org.netbeans.modules.html.editor.lib.api.model.HtmlModelProvider;
jan@866
    36
import org.netbeans.modules.html.editor.lib.api.model.HtmlTag;
jan@866
    37
import org.netbeans.modules.html.editor.lib.api.model.HtmlTagAttribute;
jan@866
    38
jan@866
    39
/**
jan@866
    40
 *
jan@866
    41
 * @author Jan Horvath <jhorvath@netbeans.org>
jan@866
    42
 */
jan@866
    43
public class ElementGenerator {
jan@866
    44
jan@866
    45
    static final Map<String, String> NAMING_EXCEPTIONS = new HashMap<String, String>() {
jan@866
    46
        {
jan@866
    47
            put("img", "Image");
jan@866
    48
            put("class", "Clazz");
jan@866
    49
        }
jan@866
    50
    };
jan@866
    51
    
jan@866
    52
    static final String javaKeywords[] = {
jan@866
    53
        "abstract", "assert", "boolean", "break", "byte", "case",
jan@866
    54
        "catch", "char", "class", "const", "continue", "default", 
jan@866
    55
        "do", "double", "else", "extends", "false", "final", "finally", 
jan@866
    56
        "float", "for", "goto", "if", "implements", "import", 
jan@866
    57
        "instanceof", "int", "interface", "long", "native", "new",
jan@866
    58
        "null", "package", "private", "protected", "public",
jan@866
    59
        "return", "short", "static", "strictfp", "super",
jan@866
    60
        "switch", "synchronized", "this", "throw", "throws",
jan@866
    61
        "transient", "true", "try", "void", "volatile", "while"
jan@866
    62
    };
jan@866
    63
    
jan@866
    64
    private static Map<String, String> elements = new HashMap<String, String>();
jan@866
    65
    private final ProcessingEnvironment processingEnv;
jan@866
    66
    private HtmlModel model = null;
jan@866
    67
jan@866
    68
    ElementGenerator(ProcessingEnvironment processingEnv) {
jan@866
    69
        this.processingEnv = processingEnv;
jan@866
    70
    }
jan@866
    71
jan@866
    72
    String getType(String pkg, String tag, Element e) {
jan@866
    73
        String className = elements.get(tag);
jan@866
    74
        if (className == null) {
jan@866
    75
            className = createClass(pkg, tag, e);
jan@866
    76
            elements.put(tag, className);
jan@866
    77
        }
jan@866
    78
        return className;
jan@866
    79
    }
jan@866
    80
jan@866
    81
    private String createClass(String pkg, String tag, Element e) {
jan@866
    82
        String className = className(tag);
jan@866
    83
        Writer w;
jan@866
    84
        try {
jan@866
    85
            FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
jan@866
    86
            w = new OutputStreamWriter(java.openOutputStream());
jan@866
    87
            try {
jan@866
    88
                w.append("package " + pkg + ";\n\n");
jan@866
    89
                w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
jan@866
    90
                PredefinedFields.appendImports(w, tag);
jan@866
    91
                w.append("\n");
jan@866
    92
                
jan@866
    93
                w.append("class ").append(className).append(" extends Element {\n\n");
jan@866
    94
                w.append("    public ").append(className).append("(String id) {\n");
jan@866
    95
                w.append("        super(id);\n");
jan@866
    96
                w.append("    }\n\n");
jan@866
    97
                for (Entry<String, String> entry : getAttributes(tag).entrySet()) {
jan@866
    98
                    String attrName = entry.getKey();
jan@866
    99
                    String attrType = entry.getValue();
jan@866
   100
                    // getter
jan@866
   101
                    w.append("    public ").append(attrType).append(" ")
jan@866
   102
                            .append("get").append(className(attrName)).append("() {\n");
jan@866
   103
                    w.append("        return (").append(attrType).append(")getAttribute(\"")
jan@866
   104
                            .append(attrName).append("\");\n");
jan@866
   105
                    w.append("    }\n\n");
jan@866
   106
                    // setter
jan@866
   107
                    w.append("    public void ")
jan@866
   108
                            .append("set").append(className(attrName)).append("(")
jan@866
   109
                            .append(attrType).append(" ").append(attributeName(attrName)).append(") {\n");
jan@866
   110
                    w.append("        setAttribute(\"").append(attrName).append("\", ").append(attributeName(attrName)).append(");\n");
jan@866
   111
                    w.append("    }\n\n");
jan@866
   112
                }
jan@866
   113
                PredefinedFields.appendFields(w, tag);
jan@866
   114
                w.append("}\n");
jan@866
   115
            } finally {
jan@866
   116
                w.close();
jan@866
   117
            }
jan@866
   118
        } catch (IOException ex) {
jan@866
   119
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + className + ".java", e);
jan@866
   120
            return null;
jan@866
   121
        }
jan@866
   122
        return className;
jan@866
   123
    }
jan@866
   124
jan@866
   125
    Map<String, String> getAttributes(String tagName) {
jan@866
   126
        Map<String, String> result = new HashMap<String, String>();
jan@866
   127
jan@866
   128
        if (model == null) {
jan@866
   129
            // HtmlModelProvider modelProvider = Lookup.getDefault().lookup(HtmlModelProvider.class);
jan@866
   130
            ServiceLoader<HtmlModelProvider> hmpLoader = 
jan@866
   131
                    ServiceLoader.load(HtmlModelProvider.class, this.getClass().getClassLoader());
jan@866
   132
            for (HtmlModelProvider htmlModelProvider : hmpLoader) {
jan@866
   133
                model = htmlModelProvider.getModel(HtmlVersion.HTML5);
jan@866
   134
                if (model != null) {
jan@866
   135
                    break;
jan@866
   136
                }
jan@866
   137
            }
jan@866
   138
        }
jan@866
   139
        
jan@866
   140
        if (model == null) {
jan@866
   141
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
jan@866
   142
                    "HTML 5 model provider was not found on classpath");
jan@866
   143
            return Collections.emptyMap();
jan@866
   144
        }
jan@866
   145
        HtmlTag tag = model.getTag(tagName);
jan@866
   146
        for (HtmlTagAttribute attr : tag.getAttributes()) {
jan@866
   147
            String name = attr.getName();
jan@866
   148
            String type = Attributes.TYPES.get(name);
jan@866
   149
            if (type != null) {
jan@866
   150
                result.put(name, type);
jan@866
   151
            }
jan@866
   152
        }
jan@866
   153
        
jan@866
   154
        return result;
jan@866
   155
    }
jan@866
   156
jan@866
   157
    private String className(String s) {
jan@866
   158
        if (s.length() == 0) {
jan@866
   159
            return s;
jan@866
   160
        }
jan@866
   161
        String name = NAMING_EXCEPTIONS.get(s.toLowerCase());
jan@866
   162
        if (name == null) {
jan@866
   163
            name = s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
jan@866
   164
        }
jan@866
   165
        return name;
jan@866
   166
    }
jan@866
   167
jan@866
   168
    private String attributeName(String s) {
jan@866
   169
        if (Arrays.binarySearch(javaKeywords, s) >= 0) {
jan@866
   170
            return String.format("%sAttr", s);
jan@866
   171
        }
jan@866
   172
        return s;
jan@866
   173
    }
jan@866
   174
    
jan@866
   175
}