All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apidesign.bck2brwsr.emul.reflect.AnnotationImpl Maven / Gradle / Ivy

There is a newer version: 0.54
Show newest version
/**
 * Back 2 Browser Bytecode Translator
 * Copyright (C) 2012 Jaroslav Tulach 
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 2 of the License.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. Look for COPYING file in the top folder.
 * If not, see http://opensource.org/licenses/GPL-2.0.
 */
package org.apidesign.bck2brwsr.emul.reflect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.apidesign.bck2brwsr.core.JavaScriptBody;

/**
 *
 * @author Jaroslav Tulach 
 */
public final class AnnotationImpl implements Annotation {
    private final Class type;

    public AnnotationImpl(Class type) {
        this.type = type;
    }
    
    public Class annotationType() {
        return type;
    }

    @JavaScriptBody(args = { "a", "n", "arr", "values" }, body = ""
        + "function r(anno, val, prop, m) {\n"
        + "  var v = val[prop];\n"
        + "  if (typeof v === 'undefined') {\n"
        + "    var cls = anno.fld_org_apidesign_bck2brwsr_emul_reflect_AnnotationImpl_type.cnstr;\n"
        + "    v = cls.prototype[m]();\n"
        + "  }\n"
        + "  return v;\n"
        + "}\n"
        + "function f(val, prop, clazz, m) {\n"
        + "  return function() {\n"
        + "    if (clazz == null) return r(this, val, prop, m);\n"
        + "    if (clazz.isArray__Z()) {\n"
        + "      var valarr = r(this, val, prop, m);\n"
        + "      var cmp = clazz.getComponentType__Ljava_lang_Class_2();\n"
        + "      var retarr = vm.java_lang_reflect_Array(false).newInstance__Ljava_lang_Object_2Ljava_lang_Class_2I(cmp, valarr.length);\n"
        + "      for (var i = 0; i < valarr.length; i++) {\n"
        + "        retarr[i] = CLS.prototype.c__Ljava_lang_Object_2Ljava_lang_Class_2Ljava_lang_Object_2(cmp, valarr[i]);\n"
        + "      }\n"
        + "      return retarr;\n"
        + "    }\n"
        + "    return CLS.prototype.c__Ljava_lang_Object_2Ljava_lang_Class_2Ljava_lang_Object_2(clazz, r(this, val, prop, m));\n"
        + "  };\n"
        + "}\n"
        + "for (var i = 0; i < arr.length; i += 3) {\n"
        + "  var m = arr[i];\n"
        + "  var p = arr[i + 1];\n"
        + "  var c = arr[i + 2];\n"
        + "  a[m] = f(values, p, c, m);\n"
        + "}\n"
        + "a['$instOf_' + n] = true;\n"
        + "return a;"
    )
    private static native  T create(
        AnnotationImpl a, String n, Object[] methodsAndProps, Object values
    );
    
    private static Object c(Class a, Object v) {
        return create(a, v);
    }
    
    public static  T create(Class annoClass, Object values) {
        return create(new AnnotationImpl(annoClass), 
            annoClass.getName().replace('.', '_'), 
            findProps(annoClass), values
        );
    }

    public static Annotation[] create(Object anno) {
        String[] names = findNames(anno);
        Annotation[] ret = new Annotation[names.length];
        for (int i = 0; i < names.length; i++) {
            String annoNameSlash = names[i].substring(1, names[i].length() - 1);
            Class annoClass;
            try {
                annoClass = (Class)Class.forName(annoNameSlash.replace('/', '.'));
            } catch (ClassNotFoundException ex) {
                throw new IllegalStateException("Can't find annotation class " + annoNameSlash);
            }
            ret[i] = create(
                new AnnotationImpl(annoClass), 
                annoNameSlash.replace('/', '_'),
                findProps(annoClass),
                findData(anno, names[i])
            );
        }
        return ret;
    }
    @JavaScriptBody(args = "anno", body =
          "var arr = new Array();"
        + "var props = Object.getOwnPropertyNames(anno);\n"
        + "for (var i = 0; i < props.length; i++) {\n"
        + "  var p = props[i];\n"
        + "  arr.push(p);"
        + "}"
        + "return arr;"
    )
    private static native String[] findNames(Object anno);

    @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];")
    private static native Object findData(Object anno, String p);

    private static Object[] findProps(Class annoClass) {
        final Method[] marr = MethodImpl.findMethods(annoClass, Modifier.PUBLIC);
        Object[] arr = new Object[marr.length * 3];
        int pos = 0;
        for (Method m : marr) {
            arr[pos++] = MethodImpl.toSignature(m);
            arr[pos++] = m.getName();
            final Class rt = m.getReturnType();
            if (rt.isArray()) {
                arr[pos++] = rt.getComponentType().isAnnotation() ? rt : null;
            } else {
                arr[pos++] = rt.isAnnotation() ? rt : null;
            }
        }
        return arr;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy