emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 03 Feb 2013 18:58:09 +0100
branchreflection
changeset 652 f095ea52f417
parent 555 cde0c2d7794e
child 654 26a86cc00224
permissions -rw-r--r--
Supporting annotations with arrays
jaroslav@378
     1
/**
jaroslav@378
     2
 * Back 2 Browser Bytecode Translator
jaroslav@378
     3
 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@378
     4
 *
jaroslav@378
     5
 * This program is free software: you can redistribute it and/or modify
jaroslav@378
     6
 * it under the terms of the GNU General Public License as published by
jaroslav@378
     7
 * the Free Software Foundation, version 2 of the License.
jaroslav@378
     8
 *
jaroslav@378
     9
 * This program is distributed in the hope that it will be useful,
jaroslav@378
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@378
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jaroslav@378
    12
 * GNU General Public License for more details.
jaroslav@378
    13
 *
jaroslav@378
    14
 * You should have received a copy of the GNU General Public License
jaroslav@378
    15
 * along with this program. Look for COPYING file in the top folder.
jaroslav@378
    16
 * If not, see http://opensource.org/licenses/GPL-2.0.
jaroslav@235
    17
 */
jaroslav@555
    18
package org.apidesign.bck2brwsr.emul.reflect;
jaroslav@235
    19
jaroslav@235
    20
import java.lang.annotation.Annotation;
jaroslav@652
    21
import java.lang.reflect.Method;
jaroslav@652
    22
import java.lang.reflect.Modifier;
jaroslav@235
    23
import org.apidesign.bck2brwsr.core.JavaScriptBody;
jaroslav@235
    24
jaroslav@235
    25
/**
jaroslav@235
    26
 *
jaroslav@235
    27
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@235
    28
 */
jaroslav@266
    29
public final class AnnotationImpl implements Annotation {
jaroslav@235
    30
    public Class<? extends Annotation> annotationType() {
jaroslav@235
    31
        return getClass();
jaroslav@235
    32
    }
jaroslav@235
    33
jaroslav@652
    34
    @JavaScriptBody(args = { "a", "n", "arr", "values" }, body = ""
jaroslav@253
    35
        + "function f(v, p) {\n"
jaroslav@253
    36
        + "  var val = v;\n"
jaroslav@253
    37
        + "  var prop = p;\n"
jaroslav@253
    38
        + "  return function() {\n"
jaroslav@253
    39
        + "    return val[prop];\n"
jaroslav@253
    40
        + "  };\n"
jaroslav@253
    41
        + "}\n"
jaroslav@652
    42
        + "for (var i = 0; i < arr.length; i += 2) {\n"
jaroslav@652
    43
        + "  var m = arr[i];\n"
jaroslav@652
    44
        + "  var p = arr[i + 1];\n"
jaroslav@652
    45
        + "  a[m] = new f(values, p);\n"
jaroslav@253
    46
        + "}\n"
jaroslav@253
    47
        + "a['$instOf_' + n] = true;\n"
jaroslav@235
    48
        + "return a;"
jaroslav@235
    49
    )
jaroslav@652
    50
    private static native <T extends Annotation> T create(
jaroslav@652
    51
        AnnotationImpl a, String n, String[] methodsAndProps, Object values
jaroslav@652
    52
    );
jaroslav@652
    53
    
jaroslav@266
    54
    public static <T extends Annotation> T create(Class<T> annoClass, Object values) {
jaroslav@652
    55
        return create(new AnnotationImpl(), 
jaroslav@652
    56
            annoClass.getName().replace('.', '_'), 
jaroslav@652
    57
            findProps(annoClass), values
jaroslav@652
    58
        );
jaroslav@235
    59
    }
jaroslav@238
    60
jaroslav@266
    61
    public static Annotation[] create(Object anno) {
jaroslav@238
    62
        String[] names = findNames(anno);
jaroslav@238
    63
        Annotation[] ret = new Annotation[names.length];
jaroslav@238
    64
        for (int i = 0; i < names.length; i++) {
jaroslav@652
    65
            String annoNameSlash = names[i].substring(1, names[i].length() - 1);
jaroslav@652
    66
            Class<?> annoClass;
jaroslav@652
    67
            try {
jaroslav@652
    68
                annoClass = Class.forName(annoNameSlash.replace('/', '.'));
jaroslav@652
    69
            } catch (ClassNotFoundException ex) {
jaroslav@652
    70
                throw new IllegalStateException("Can't find annotation class " + annoNameSlash);
jaroslav@652
    71
            }
jaroslav@652
    72
            ret[i] = create(
jaroslav@652
    73
                new AnnotationImpl(), 
jaroslav@652
    74
                annoNameSlash.replace('/', '_'),
jaroslav@652
    75
                findProps(annoClass),
jaroslav@652
    76
                findData(anno, names[i])
jaroslav@652
    77
            );
jaroslav@238
    78
        }
jaroslav@238
    79
        return ret;
jaroslav@238
    80
    }
jaroslav@238
    81
    @JavaScriptBody(args = "anno", body =
jaroslav@238
    82
          "var arr = new Array();"
jaroslav@254
    83
        + "var props = Object.getOwnPropertyNames(anno);\n"
jaroslav@254
    84
        + "for (var i = 0; i < props.length; i++) {\n"
jaroslav@254
    85
        + "  var p = props[i];\n"
jaroslav@238
    86
        + "  arr.push(p);"
jaroslav@238
    87
        + "}"
jaroslav@238
    88
        + "return arr;"
jaroslav@238
    89
    )
jaroslav@652
    90
    private static native String[] findNames(Object anno);
jaroslav@238
    91
jaroslav@238
    92
    @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];")
jaroslav@652
    93
    private static native Object findData(Object anno, String p);
jaroslav@652
    94
jaroslav@652
    95
    private static String[] findProps(Class<?> annoClass) {
jaroslav@652
    96
        final Method[] marr = MethodImpl.findMethods(annoClass, Modifier.PUBLIC);
jaroslav@652
    97
        String[] arr = new String[marr.length * 2];
jaroslav@652
    98
        int pos = 0;
jaroslav@652
    99
        for (Method m : marr) {
jaroslav@652
   100
            arr[pos++] = MethodImpl.toSignature(m);
jaroslav@652
   101
            arr[pos++] = m.getName();
jaroslav@652
   102
        }
jaroslav@652
   103
        return arr;
jaroslav@238
   104
    }
jaroslav@235
   105
}