boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 12 Sep 2013 17:59:10 +0200
branchbatchnotify
changeset 294 7a3abb6bcfc9
parent 288 8c5b40231d26
child 298 06719f52f85a
permissions -rw-r--r--
Notifies property changes in one batch
     1 /**
     2  * HTML via Java(tm) Language Bindings
     3  * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4  *
     5  * This program is free software: you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation, version 2 of the License.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details. apidesign.org
    13  * designates this particular file as subject to the
    14  * "Classpath" exception as provided by apidesign.org
    15  * in the License file that accompanied this code.
    16  *
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program. Look for COPYING file in the top folder.
    19  * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    20  */
    21 package org.apidesign.html.boot.impl;
    22 
    23 import java.io.InputStream;
    24 import java.io.InputStreamReader;
    25 import java.io.Reader;
    26 import java.net.URL;
    27 import java.util.ArrayList;
    28 import java.util.Collections;
    29 import java.util.Enumeration;
    30 import java.util.List;
    31 import org.apidesign.html.boot.spi.Fn;
    32 
    33 /**
    34  *
    35  * @author Jaroslav Tulach <jtulach@netbeans.org>
    36  */
    37 public final class FnUtils {
    38     private static final ThreadLocal<Fn.Presenter> CURRENT = new ThreadLocal<Fn.Presenter>();
    39     private static final ThreadLocal<List<Runnable>> LATER = new ThreadLocal<List<Runnable>>();
    40     
    41     private FnUtils() {
    42     }
    43     
    44     public static Fn define(Class<?> caller, String code, String... names) {
    45         return currentPresenter().defineFn(code, names);
    46     }
    47     
    48     public static boolean isJavaScriptCapable(ClassLoader l) {
    49         return l instanceof JsClassLoader;
    50     }
    51     
    52     public static boolean isValid(Fn fn) {
    53         return fn != null && fn.isValid();
    54     }
    55 
    56     public static ClassLoader newLoader(final FindResources f, final Fn.Presenter d, ClassLoader parent) {
    57         return new JsClassLoader(parent) {
    58             @Override
    59             protected URL findResource(String name) {
    60                 List<URL> l = res(name, true);
    61                 return l.isEmpty() ? null : l.get(0);
    62             }
    63             
    64             @Override
    65             protected Enumeration<URL> findResources(String name) {
    66                 return Collections.enumeration(res(name, false));
    67             }
    68             
    69             private List<URL> res(String name, boolean oneIsEnough) {
    70                 List<URL> l = new ArrayList<URL>();
    71                 f.findResources(name, l, oneIsEnough);
    72                 return l;
    73             }
    74             
    75             @Override
    76             protected Fn defineFn(String code, String... names) {
    77                 return d.defineFn(code, names);
    78             }
    79 
    80             @Override
    81             protected void loadScript(Reader code) throws Exception {
    82                 d.loadScript(code);
    83             }
    84         };
    85     }
    86 
    87     static String callback(final String body) {
    88         return new JsCallback() {
    89             @Override
    90             protected CharSequence callMethod(
    91                 String ident, String fqn, String method, String params
    92             ) {
    93                 StringBuilder sb = new StringBuilder();
    94                 sb.append("vm.").append(mangle(fqn, method, params));
    95                 sb.append("(");
    96                 if (ident != null) {
    97                     sb.append(ident);
    98                 }
    99                 return sb;
   100             }
   101 
   102         }.parse(body);
   103     }
   104 
   105     static void loadScript(JsClassLoader jcl, String resource) {
   106         final InputStream script = jcl.getResourceAsStream(resource);
   107         if (script == null) {
   108             throw new NullPointerException("Can't find " + resource);
   109         }
   110         try {
   111             Reader isr = null;
   112             try {
   113                 isr = new InputStreamReader(script, "UTF-8");
   114                 jcl.loadScript(isr);
   115             } finally {
   116                 if (isr != null) {
   117                     isr.close();
   118                 }
   119             }
   120         } catch (Exception ex) {
   121             throw new IllegalStateException("Can't execute " + resource, ex);
   122         } 
   123     }
   124 
   125     public static Fn.Presenter currentPresenter() {
   126         Fn.Presenter p = CURRENT.get();
   127         if (p == null) {
   128             throw new IllegalStateException("No current WebView context around!");
   129         }
   130         return p;
   131     }
   132     
   133     public static Fn.Presenter currentPresenter(Fn.Presenter p) {
   134         List<Runnable> list = LATER.get();
   135         LATER.set(null);
   136         if (list != null) for (Runnable runnable : list) {
   137             try {
   138                 runnable.run();
   139             } catch (Throwable t) {
   140                 t.printStackTrace();
   141             }
   142         }
   143         
   144         Fn.Presenter prev = CURRENT.get();
   145         CURRENT.set(p);
   146         return prev;
   147     }
   148     
   149     public static void runLater(Runnable r) {
   150         currentPresenter();
   151         List<Runnable> list = LATER.get();
   152         if (list == null) {
   153             list = new ArrayList<Runnable>();
   154             LATER.set(list);
   155         }
   156         list.add(r);
   157     }
   158 }