Separating the callback processing into own class
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 11 Jul 2013 13:12:51 +0200
changeset 18319ee92613f00
parent 182 99c8145d1e4f
child 184 6c0807571258
Separating the callback processing into own class
boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java
boot/src/main/java/org/apidesign/html/boot/impl/JsCallback.java
     1.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java	Thu Jul 11 11:23:54 2013 +0200
     1.2 +++ b/boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java	Thu Jul 11 13:12:51 2013 +0200
     1.3 @@ -79,97 +79,13 @@
     1.4  
     1.5      static String callback(String body, ClassLoader loader, String ownName, Map<String,String> ownMethods) {
     1.6          try {
     1.7 -            return callbackImpl(body, loader, ownName, ownMethods);
     1.8 +            return new JsCallback(loader, ownName, ownMethods).callbackImpl(body);
     1.9          } catch (ClassNotFoundException ex) {
    1.10              throw new IllegalStateException("Can't parse " + body, ex);
    1.11          } catch (NoSuchMethodException ex) {
    1.12              throw new IllegalStateException("Can't parse " + body, ex);
    1.13          }
    1.14      }
    1.15 -    
    1.16 -    private static String callbackImpl(
    1.17 -        String body, ClassLoader loader, String ownName, Map<String,String> ownMethods
    1.18 -    ) throws ClassNotFoundException, NoSuchMethodException {
    1.19 -        StringBuilder sb = new StringBuilder();
    1.20 -        int pos = 0;
    1.21 -        for (;;) {
    1.22 -            int next = body.indexOf(".@", pos);
    1.23 -            if (next == -1) {
    1.24 -                sb.append(body.substring(pos));
    1.25 -                return sb.toString();
    1.26 -            }
    1.27 -            sb.append(body.substring(pos, next));
    1.28 -            
    1.29 -            int sigBeg = body.indexOf('(', next);
    1.30 -            int sigEnd = body.indexOf(')', sigBeg);
    1.31 -            
    1.32 -            int colon4 = body.indexOf("::", next);
    1.33 -            
    1.34 -            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
    1.35 -                throw new IllegalStateException("Malformed body " + body);
    1.36 -            }
    1.37 -            
    1.38 -            String fqn = body.substring(next + 2, colon4);
    1.39 -            String method = body.substring(colon4 + 2, sigBeg);
    1.40 -            String params = body.substring(sigBeg, sigEnd + 1);
    1.41 -            
    1.42 -            if (fqn.equals(ownName.replace('/', '.'))) {
    1.43 -                if (!ownMethods.containsKey(method + params)) {
    1.44 -                    throw new IllegalStateException("Wrong refernece to " + method + params);
    1.45 -                }
    1.46 -                sb.append("['").append(method).append("(");
    1.47 -                final Type[] argTps = Type.getArgumentTypes(params);
    1.48 -                Class<?>[] argCls = new Class<?>[argTps.length];
    1.49 -                String sep = "";
    1.50 -                for (int i = 0; i < argCls.length; i++) {
    1.51 -                    sb.append(sep).append(toClass(argTps[i], loader).getName());
    1.52 -                    sep = ",";
    1.53 -                }
    1.54 -                sb.append(")']");
    1.55 -            } else {
    1.56 -                Class<?> clazz = Class.forName(fqn, false, loader);
    1.57 -                final Type[] argTps = Type.getArgumentTypes(params);
    1.58 -                Class<?>[] argCls = new Class<?>[argTps.length];
    1.59 -                for (int i = 0; i < argCls.length; i++) {
    1.60 -                    argCls[i] = toClass(argTps[i], loader);
    1.61 -                }
    1.62 -                Method m = clazz.getMethod(method, argCls);
    1.63 -
    1.64 -                sb.append("['").append(m.getName()).append("(");
    1.65 -                String sep = "";
    1.66 -                for (Class<?> pt : m.getParameterTypes()) {
    1.67 -                    sb.append(sep).append(pt.getName());
    1.68 -                    sep = ",";
    1.69 -                }
    1.70 -                sb.append(")']");
    1.71 -            }
    1.72 -            
    1.73 -            pos = sigEnd + 1;
    1.74 -        }
    1.75 -    }
    1.76 -
    1.77 -    private static Class<?> toClass(final Type t, ClassLoader loader) throws ClassNotFoundException {
    1.78 -        if (t == Type.INT_TYPE) {
    1.79 -            return Integer.TYPE;
    1.80 -        } else if (t == Type.VOID_TYPE) {
    1.81 -            return Void.TYPE;
    1.82 -        } else if (t == Type.BOOLEAN_TYPE) {
    1.83 -            return Boolean.TYPE;
    1.84 -        } else if (t == Type.BYTE_TYPE) {
    1.85 -            return Byte.TYPE;
    1.86 -        } else if (t == Type.CHAR_TYPE) {
    1.87 -            return Character.TYPE;
    1.88 -        } else if (t == Type.SHORT_TYPE) {
    1.89 -            return Short.TYPE;
    1.90 -        } else if (t == Type.DOUBLE_TYPE) {
    1.91 -            return Double.TYPE;
    1.92 -        } else if (t == Type.FLOAT_TYPE) {
    1.93 -            return Float.TYPE;
    1.94 -        } else if (t == Type.LONG_TYPE) {
    1.95 -            return Long.TYPE;
    1.96 -        }
    1.97 -        return Class.forName(t.getClassName(), false, loader);
    1.98 -    }
    1.99  
   1.100      static void loadScript(JsClassLoader jcl, String resource) {
   1.101          final InputStream script = jcl.getResourceAsStream(resource);
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/boot/src/main/java/org/apidesign/html/boot/impl/JsCallback.java	Thu Jul 11 13:12:51 2013 +0200
     2.3 @@ -0,0 +1,134 @@
     2.4 +/**
     2.5 + * HTML via Java(tm) Language Bindings
     2.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     2.7 + *
     2.8 + * This program is free software: you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License as published by
    2.10 + * the Free Software Foundation, version 2 of the License.
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU General Public License for more details. apidesign.org
    2.16 + * designates this particular file as subject to the
    2.17 + * "Classpath" exception as provided by apidesign.org
    2.18 + * in the License file that accompanied this code.
    2.19 + *
    2.20 + * You should have received a copy of the GNU General Public License
    2.21 + * along with this program. Look for COPYING file in the top folder.
    2.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    2.23 + */
    2.24 +package org.apidesign.html.boot.impl;
    2.25 +
    2.26 +import java.lang.reflect.Method;
    2.27 +import java.util.Map;
    2.28 +import org.objectweb.asm.Type;
    2.29 +
    2.30 +/**
    2.31 + *
    2.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    2.33 + */
    2.34 +final class JsCallback {
    2.35 +    private final ClassLoader loader;
    2.36 +    private final String ownName;
    2.37 +    private final Map<String,String> ownMethods;
    2.38 +
    2.39 +    JsCallback(ClassLoader l, String ownName, Map<String, String> ownMethods) {
    2.40 +        this.loader = l;
    2.41 +        this.ownName = ownName;
    2.42 +        this.ownMethods = ownMethods;
    2.43 +    }
    2.44 +
    2.45 +    String callbackImpl(String body) throws ClassNotFoundException, NoSuchMethodException {
    2.46 +        StringBuilder sb = new StringBuilder();
    2.47 +        int pos = 0;
    2.48 +        for (;;) {
    2.49 +            int next = body.indexOf(".@", pos);
    2.50 +            if (next == -1) {
    2.51 +                sb.append(body.substring(pos));
    2.52 +                return sb.toString();
    2.53 +            }
    2.54 +            int ident = next;
    2.55 +            while (ident > 0 && Character.isJavaIdentifierPart(body.charAt(--ident))) {
    2.56 +            }
    2.57 +            ident++;
    2.58 +            String refId = body.substring(ident, next);
    2.59 +            
    2.60 +            sb.append(body.substring(pos, ident));
    2.61 +            
    2.62 +            int sigBeg = body.indexOf('(', next);
    2.63 +            int sigEnd = body.indexOf(')', sigBeg);
    2.64 +            int colon4 = body.indexOf("::", next);
    2.65 +            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
    2.66 +                throw new IllegalStateException("Malformed body " + body);
    2.67 +            }
    2.68 +            String fqn = body.substring(next + 2, colon4);
    2.69 +            String method = body.substring(colon4 + 2, sigBeg);
    2.70 +            String params = body.substring(sigBeg, sigEnd + 1);
    2.71 +            
    2.72 +            sb.append(workWithParams(refId, fqn, method, params));
    2.73 +            pos = sigEnd + 1;
    2.74 +        }
    2.75 +    }
    2.76 +
    2.77 +    static Class<?> toClass(final Type t, ClassLoader loader) throws ClassNotFoundException {
    2.78 +        if (t == Type.INT_TYPE) {
    2.79 +            return Integer.TYPE;
    2.80 +        } else if (t == Type.VOID_TYPE) {
    2.81 +            return Void.TYPE;
    2.82 +        } else if (t == Type.BOOLEAN_TYPE) {
    2.83 +            return Boolean.TYPE;
    2.84 +        } else if (t == Type.BYTE_TYPE) {
    2.85 +            return Byte.TYPE;
    2.86 +        } else if (t == Type.CHAR_TYPE) {
    2.87 +            return Character.TYPE;
    2.88 +        } else if (t == Type.SHORT_TYPE) {
    2.89 +            return Short.TYPE;
    2.90 +        } else if (t == Type.DOUBLE_TYPE) {
    2.91 +            return Double.TYPE;
    2.92 +        } else if (t == Type.FLOAT_TYPE) {
    2.93 +            return Float.TYPE;
    2.94 +        } else if (t == Type.LONG_TYPE) {
    2.95 +            return Long.TYPE;
    2.96 +        }
    2.97 +        return Class.forName(t.getClassName(), false, loader);
    2.98 +    }
    2.99 +
   2.100 +    private CharSequence workWithParams(
   2.101 +        String ident, String fqn, String method, String params
   2.102 +    ) throws NoSuchMethodException, ClassNotFoundException {
   2.103 +        StringBuilder sb = new StringBuilder();
   2.104 +        sb.append(ident);
   2.105 +        if (fqn.equals(ownName.replace('/', '.'))) {
   2.106 +            if (!ownMethods.containsKey(method + params)) {
   2.107 +                throw new IllegalStateException("Wrong reference to " + method + params);
   2.108 +            }
   2.109 +            sb.append("['").append(method).append("(");
   2.110 +            final Type[] argTps = Type.getArgumentTypes(params);
   2.111 +            Class<?>[] argCls = new Class<?>[argTps.length];
   2.112 +            String sep = "";
   2.113 +            for (int i = 0; i < argCls.length; i++) {
   2.114 +                sb.append(sep).append(toClass(argTps[i], loader).getName());
   2.115 +                sep = ",";
   2.116 +            }
   2.117 +            sb.append(")']");
   2.118 +        } else {
   2.119 +            Class<?> clazz = Class.forName(fqn, false, loader);
   2.120 +            final Type[] argTps = Type.getArgumentTypes(params);
   2.121 +            Class<?>[] argCls = new Class<?>[argTps.length];
   2.122 +            for (int i = 0; i < argCls.length; i++) {
   2.123 +                argCls[i] = toClass(argTps[i], loader);
   2.124 +            }
   2.125 +            Method m = clazz.getMethod(method, argCls);
   2.126 +            sb.append("['").append(m.getName()).append("(");
   2.127 +            String sep = "";
   2.128 +            for (Class<?> pt : m.getParameterTypes()) {
   2.129 +                sb.append(sep).append(pt.getName());
   2.130 +                sep = ",";
   2.131 +            }
   2.132 +            sb.append(")']");
   2.133 +        }
   2.134 +        return sb;
   2.135 +    }
   2.136 +    
   2.137 +}