ko4j/src/main/java/org/netbeans/html/ko4j/FXContext.java
author Jaroslav Tulach <jtulach@netbeans.org>
Sat, 02 Aug 2014 12:59:31 +0200
changeset 790 30f20d9c0986
parent 590 17e3ded623a0
child 838 bdc3d696dd4a
permissions -rw-r--r--
Fixing Javadoc to succeed on JDK8
     1 /**
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     5  *
     6  * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
     7  * Other names may be trademarks of their respective owners.
     8  *
     9  * The contents of this file are subject to the terms of either the GNU
    10  * General Public License Version 2 only ("GPL") or the Common
    11  * Development and Distribution License("CDDL") (collectively, the
    12  * "License"). You may not use this file except in compliance with the
    13  * License. You can obtain a copy of the License at
    14  * http://www.netbeans.org/cddl-gplv2.html
    15  * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    16  * specific language governing permissions and limitations under the
    17  * License.  When distributing the software, include this License Header
    18  * Notice in each file and include the License file at
    19  * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    20  * particular file as subject to the "Classpath" exception as provided
    21  * by Oracle in the GPL Version 2 section of the License file that
    22  * accompanied this code. If applicable, add the following below the
    23  * License Header, with the fields enclosed by brackets [] replaced by
    24  * your own identifying information:
    25  * "Portions Copyrighted [year] [name of copyright owner]"
    26  *
    27  * Contributor(s):
    28  *
    29  * The Original Software is NetBeans. The Initial Developer of the Original
    30  * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    31  *
    32  * If you wish your version of this file to be governed by only the CDDL
    33  * or only the GPL Version 2, indicate your decision by adding
    34  * "[Contributor] elects to include this software in this distribution
    35  * under the [CDDL or GPL Version 2] license." If you do not indicate a
    36  * single choice of license, a recipient has the option to distribute
    37  * your version of this file under either the CDDL, the GPL Version 2 or
    38  * to extend the choice of license to its licensees as provided above.
    39  * However, if you add GPL Version 2 code and therefore, elected the GPL
    40  * Version 2 license, then the option applies only if the new code is
    41  * made subject to such option by the copyright holder.
    42  */
    43 package org.netbeans.html.ko4j;
    44 
    45 import java.io.ByteArrayOutputStream;
    46 import java.io.Closeable;
    47 import java.io.IOException;
    48 import java.io.InputStream;
    49 import java.io.InputStreamReader;
    50 import java.io.Reader;
    51 import java.net.URL;
    52 import java.util.logging.Logger;
    53 import org.apidesign.html.boot.spi.Fn;
    54 import org.apidesign.html.json.spi.FunctionBinding;
    55 import org.apidesign.html.json.spi.JSONCall;
    56 import org.apidesign.html.json.spi.PropertyBinding;
    57 import org.apidesign.html.json.spi.Technology;
    58 import org.apidesign.html.json.spi.Transfer;
    59 import org.apidesign.html.json.spi.WSTransfer;
    60 
    61 /** This is an implementation package - just
    62  * include its JAR on classpath and use official {@link Context} API
    63  * to access the functionality.
    64  * <p>
    65  *
    66  * @author Jaroslav Tulach
    67  */
    68 final class FXContext
    69 implements Technology.BatchInit<Object>, Technology.ValueMutated<Object>,
    70 Transfer, WSTransfer<LoadWS> {
    71     static final Logger LOG = Logger.getLogger(FXContext.class.getName());
    72     private Object[] jsObjects;
    73     private int jsIndex;
    74 
    75     public FXContext(Fn.Presenter browserContext) {
    76     }
    77     
    78     @Override
    79     public Object wrapModel(Object model, PropertyBinding[] propArr, FunctionBinding[] funcArr) {
    80         String[] propNames = new String[propArr.length];
    81         boolean[] propReadOnly = new boolean[propArr.length];
    82         Object[] propValues = new Object[propArr.length];
    83         for (int i = 0; i < propNames.length; i++) {
    84             propNames[i] = propArr[i].getPropertyName();
    85             propReadOnly[i] = propArr[i].isReadOnly();
    86             propValues[i] = propArr[i].getValue();
    87         }
    88         String[] funcNames = new String[funcArr.length];
    89         for (int i = 0; i < funcNames.length; i++) {
    90             funcNames[i] = funcArr[i].getFunctionName();
    91         }
    92         Object ret = getJSObject();
    93         Knockout.wrapModel(ret, model, 
    94             propNames, propReadOnly, propValues, propArr,
    95             funcNames, funcArr
    96         );
    97         return ret;
    98     }
    99     
   100     private Object getJSObject() {
   101         int len = 64;
   102         if (jsObjects != null && jsIndex < (len = jsObjects.length)) {
   103             return jsObjects[jsIndex++];
   104         }
   105         jsObjects = Knockout.allocJS(len * 2);
   106         jsIndex = 1;
   107         return jsObjects[0];
   108     }
   109     
   110     @Override
   111     public Object wrapModel(Object model) {
   112         throw new UnsupportedOperationException();
   113     }
   114 
   115     @Override
   116     public void bind(PropertyBinding b, Object model, Object data) {
   117         throw new UnsupportedOperationException();
   118     }
   119 
   120     @Override
   121     public void valueHasMutated(Object data, String propertyName) {
   122         Knockout.valueHasMutated(data, propertyName, null, null);
   123     }
   124     
   125     @Override
   126     public void valueHasMutated(Object data, String propertyName, Object oldValue, Object newValue) {
   127         Knockout.valueHasMutated(data, propertyName, oldValue, newValue);
   128     }
   129 
   130     @Override
   131     public void expose(FunctionBinding fb, Object model, Object d) {
   132         throw new UnsupportedOperationException();
   133     }
   134 
   135     @Override
   136     public void applyBindings(Object data) {
   137         Knockout.applyBindings(data);
   138     }
   139 
   140     @Override
   141     public Object wrapArray(Object[] arr) {
   142         return arr;
   143     }
   144 
   145     @Override
   146     public void extract(Object obj, String[] props, Object[] values) {
   147         LoadJSON.extractJSON(obj, props, values);
   148     }
   149 
   150     @Override
   151     public void loadJSON(final JSONCall call) {
   152         if (call.isJSONP()) {
   153             String me = LoadJSON.createJSONP(call);
   154             LoadJSON.loadJSONP(call.composeURL(me), me);
   155         } else {
   156             String data = null;
   157             if (call.isDoOutput()) {
   158                 try {
   159                     ByteArrayOutputStream bos = new ByteArrayOutputStream();
   160                     call.writeData(bos);
   161                     data = new String(bos.toByteArray(), "UTF-8");
   162                 } catch (IOException ex) {
   163                     call.notifyError(ex);
   164                 }
   165             }
   166             LoadJSON.loadJSON(call.composeURL(null), call, call.getMethod(), data);
   167         }
   168     }
   169 
   170     @Override
   171     public <M> M toModel(Class<M> modelClass, Object data) {
   172         return modelClass.cast(Knockout.toModel(data));
   173     }
   174 
   175     @Override
   176     public Object toJSON(InputStream is) throws IOException {
   177         StringBuilder sb = new StringBuilder();
   178         InputStreamReader r = new InputStreamReader(is);
   179         for (;;) {
   180             int ch = r.read();
   181             if (ch == -1) {
   182                 break;
   183             }
   184             sb.append((char)ch);
   185         }
   186         return LoadJSON.parse(sb.toString());
   187     }
   188 
   189     @Override
   190     public void runSafe(final Runnable r) {
   191         LOG.warning("Technology.runSafe has been deprecated. Use BrwsrCtx.execute!");
   192         r.run();
   193     }
   194 
   195     @Override
   196     public LoadWS open(String url, JSONCall onReply) {
   197         return new LoadWS(onReply, url);
   198     }
   199 
   200     @Override
   201     public void send(LoadWS socket, JSONCall data) {
   202         socket.send(data);
   203     }
   204 
   205     @Override
   206     public void close(LoadWS socket) {
   207         socket.close();
   208     }
   209 
   210     boolean areWebSocketsSupported() {
   211         return Knockout.areWebSocketsSupported();
   212     }
   213 
   214     private static final class TrueFn extends Fn implements Fn.Presenter {
   215         @Override
   216         public Object invoke(Object thiz, Object... args) throws Exception {
   217             return true;
   218         }
   219 
   220         @Override
   221         public Fn defineFn(String code, String... names) {
   222             return this;
   223         }
   224 
   225         @Override
   226         public void displayPage(URL page, Runnable onPageLoad) {
   227         }
   228 
   229         @Override
   230         public void loadScript(Reader code) throws Exception {
   231         }
   232     } // end of TrueFn
   233 }