json/src/main/java/org/apidesign/html/json/impl/JSON.java
branchnetbeans
changeset 362 92fb71afdc0e
parent 361 700087d2a5d3
child 364 2739565c7a45
     1.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSON.java	Mon Dec 16 15:48:09 2013 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,474 +0,0 @@
     1.4 -/**
     1.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.6 - *
     1.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
     1.8 - *
     1.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    1.10 - * Other names may be trademarks of their respective owners.
    1.11 - *
    1.12 - * The contents of this file are subject to the terms of either the GNU
    1.13 - * General Public License Version 2 only ("GPL") or the Common
    1.14 - * Development and Distribution License("CDDL") (collectively, the
    1.15 - * "License"). You may not use this file except in compliance with the
    1.16 - * License. You can obtain a copy of the License at
    1.17 - * http://www.netbeans.org/cddl-gplv2.html
    1.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    1.19 - * specific language governing permissions and limitations under the
    1.20 - * License.  When distributing the software, include this License Header
    1.21 - * Notice in each file and include the License file at
    1.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    1.23 - * particular file as subject to the "Classpath" exception as provided
    1.24 - * by Oracle in the GPL Version 2 section of the License file that
    1.25 - * accompanied this code. If applicable, add the following below the
    1.26 - * License Header, with the fields enclosed by brackets [] replaced by
    1.27 - * your own identifying information:
    1.28 - * "Portions Copyrighted [year] [name of copyright owner]"
    1.29 - *
    1.30 - * Contributor(s):
    1.31 - *
    1.32 - * The Original Software is NetBeans. The Initial Developer of the Original
    1.33 - * Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
    1.34 - *
    1.35 - * If you wish your version of this file to be governed by only the CDDL
    1.36 - * or only the GPL Version 2, indicate your decision by adding
    1.37 - * "[Contributor] elects to include this software in this distribution
    1.38 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
    1.39 - * single choice of license, a recipient has the option to distribute
    1.40 - * your version of this file under either the CDDL, the GPL Version 2 or
    1.41 - * to extend the choice of license to its licensees as provided above.
    1.42 - * However, if you add GPL Version 2 code and therefore, elected the GPL
    1.43 - * Version 2 license, then the option applies only if the new code is
    1.44 - * made subject to such option by the copyright holder.
    1.45 - */
    1.46 -package org.apidesign.html.json.impl;
    1.47 -
    1.48 -import java.io.IOException;
    1.49 -import java.io.InputStream;
    1.50 -import java.util.HashMap;
    1.51 -import java.util.Map;
    1.52 -import net.java.html.BrwsrCtx;
    1.53 -import org.apidesign.html.context.spi.Contexts;
    1.54 -import org.apidesign.html.json.spi.FunctionBinding;
    1.55 -import org.apidesign.html.json.spi.JSONCall;
    1.56 -import org.apidesign.html.json.spi.PropertyBinding;
    1.57 -import org.apidesign.html.json.spi.Technology;
    1.58 -import org.apidesign.html.json.spi.Transfer;
    1.59 -import org.apidesign.html.json.spi.WSTransfer;
    1.60 -
    1.61 -/**
    1.62 - *
    1.63 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    1.64 - */
    1.65 -public final class JSON {
    1.66 -    private JSON() {
    1.67 -    }
    1.68 -
    1.69 -    static Technology<?> findTechnology(BrwsrCtx c) {
    1.70 -        Technology<?> t = Contexts.find(c, Technology.class);
    1.71 -        return t == null ? EmptyTech.EMPTY : t;
    1.72 -    }
    1.73 -
    1.74 -    static Transfer findTransfer(BrwsrCtx c) {
    1.75 -        Transfer t = Contexts.find(c, Transfer.class);
    1.76 -        return t == null ? EmptyTech.EMPTY : t;
    1.77 -    }
    1.78 -
    1.79 -    static WSTransfer<?> findWSTransfer(BrwsrCtx c) {
    1.80 -        WSTransfer<?> t = Contexts.find(c, WSTransfer.class);
    1.81 -        return t == null ? EmptyTech.EMPTY : t;
    1.82 -    }
    1.83 -    
    1.84 -    public static void runInBrowser(BrwsrCtx c, Runnable runnable) {
    1.85 -        findTechnology(c).runSafe(runnable);
    1.86 -    }
    1.87 -    
    1.88 -    public static void extract(BrwsrCtx c, Object value, String[] props, Object[] values) {
    1.89 -        Transfer t = findTransfer(c);
    1.90 -        t.extract(value, props, values);
    1.91 -    }
    1.92 -    
    1.93 -    private static Object getProperty(BrwsrCtx c, Object obj, String prop) {
    1.94 -        if (prop == null) return obj;
    1.95 -        
    1.96 -        String[] arr = { prop };
    1.97 -        Object[] val = { null };
    1.98 -        extract(c, obj, arr, val);
    1.99 -        return val[0];
   1.100 -    }
   1.101 -
   1.102 -    public static Object toJSON(Object value) {
   1.103 -        if (value == null) {
   1.104 -            return "null";
   1.105 -        }
   1.106 -        if (value instanceof Enum) {
   1.107 -            value = value.toString();
   1.108 -        }
   1.109 -        if (value instanceof String) {
   1.110 -            String s = (String)value;
   1.111 -            int len = s.length();
   1.112 -            StringBuilder sb = new StringBuilder(len + 10);
   1.113 -            sb.append('"');
   1.114 -            for (int i = 0; i < len; i++) {
   1.115 -                char ch = s.charAt(i);
   1.116 -                switch (ch) {
   1.117 -                    case '\"': sb.append("\\\""); break;
   1.118 -                    case '\n': sb.append("\\n"); break;
   1.119 -                    case '\r': sb.append("\\r"); break;
   1.120 -                    case '\t': sb.append("\\t"); break;
   1.121 -                    case '\\': sb.append("\\\\"); break;
   1.122 -                    default: sb.append(ch);
   1.123 -                }
   1.124 -            }
   1.125 -            sb.append('"');
   1.126 -            return sb.toString();
   1.127 -        }
   1.128 -        return value.toString();
   1.129 -    }
   1.130 -
   1.131 -    public static String toString(BrwsrCtx c, Object obj, String prop) {
   1.132 -        obj = getProperty(c, obj, prop);
   1.133 -        return obj instanceof String ? (String)obj : null;
   1.134 -    }
   1.135 -    public static Number toNumber(BrwsrCtx c, Object obj, String prop) {
   1.136 -        obj = getProperty(c, obj, prop);
   1.137 -        if (!(obj instanceof Number)) {
   1.138 -            obj = Double.NaN;
   1.139 -        }
   1.140 -        return (Number)obj;
   1.141 -    }
   1.142 -    public static <M> M toModel(BrwsrCtx c, Class<M> aClass, Object data, Object object) {
   1.143 -        Technology<?> t = findTechnology(c);
   1.144 -        Object o = t.toModel(aClass, data);
   1.145 -        return aClass.cast(o);
   1.146 -    }
   1.147 -    
   1.148 -    public static boolean isSame(int a, int b) {
   1.149 -        return a == b;
   1.150 -    }
   1.151 -    
   1.152 -    public static boolean isSame(double a, double b) {
   1.153 -        return a == b;
   1.154 -    }
   1.155 -    
   1.156 -    public static boolean isSame(Object a, Object b) {
   1.157 -        if (a == b) {
   1.158 -            return true;
   1.159 -        }
   1.160 -        if (a == null || b == null) {
   1.161 -            return false;
   1.162 -        }
   1.163 -        return a.equals(b);
   1.164 -    }
   1.165 -    
   1.166 -    public static int hashPlus(Object o, int h) {
   1.167 -        return o == null ? h : h ^ o.hashCode();
   1.168 -    }
   1.169 -
   1.170 -    public static <T> T extractValue(Class<T> type, Object val) {
   1.171 -        if (Number.class.isAssignableFrom(type)) {
   1.172 -            val = numberValue(val);
   1.173 -        }
   1.174 -        if (Boolean.class == type) {
   1.175 -            val = boolValue(val);
   1.176 -        }
   1.177 -        if (String.class == type) {
   1.178 -            val = stringValue(val);
   1.179 -        }
   1.180 -        if (Character.class == type) {
   1.181 -            val = charValue(val);
   1.182 -        }
   1.183 -        if (Integer.class == type) {
   1.184 -            val = val instanceof Number ? ((Number)val).intValue() : 0;
   1.185 -        }
   1.186 -        if (Long.class == type) {
   1.187 -            val = val instanceof Number  ? ((Number)val).longValue() : 0;
   1.188 -        }
   1.189 -        if (Short.class == type) {
   1.190 -            val = val instanceof Number ? ((Number)val).shortValue() : 0;
   1.191 -        }
   1.192 -        if (Byte.class == type) {
   1.193 -            val = val instanceof Number ? ((Number)val).byteValue() : 0;
   1.194 -        }        
   1.195 -        if (Double.class == type) {
   1.196 -            val = val instanceof Number ? ((Number)val).doubleValue() : Double.NaN;
   1.197 -        }
   1.198 -        if (Float.class == type) {
   1.199 -            val = val instanceof Number ? ((Number)val).floatValue() : Float.NaN;
   1.200 -        }
   1.201 -        return type.cast(val);
   1.202 -    }
   1.203 -    
   1.204 -    protected static boolean isNumeric(Object val) {
   1.205 -        return ((val instanceof Integer) || (val instanceof Long) || (val instanceof Short) || (val instanceof Byte));
   1.206 -    }
   1.207 -    
   1.208 -    public static String stringValue(Object val) {
   1.209 -        if (val instanceof Boolean) {
   1.210 -            return ((Boolean)val ? "true" : "false");
   1.211 -        }
   1.212 -        if (isNumeric(val)) {
   1.213 -            return Long.toString(((Number)val).longValue());
   1.214 -        }
   1.215 -        if (val instanceof Float) {
   1.216 -            return Float.toString((Float)val);
   1.217 -        }
   1.218 -        if (val instanceof Double) {
   1.219 -            return Double.toString((Double)val);
   1.220 -        }
   1.221 -        return (String)val;
   1.222 -    }
   1.223 -
   1.224 -    public static Number numberValue(Object val) {
   1.225 -        if (val instanceof String) {
   1.226 -            try {
   1.227 -                return Double.valueOf((String)val);
   1.228 -            } catch (NumberFormatException ex) {
   1.229 -                return Double.NaN;
   1.230 -            }
   1.231 -        }
   1.232 -        if (val instanceof Boolean) {
   1.233 -            return (Boolean)val ? 1 : 0;
   1.234 -        }
   1.235 -        return (Number)val;
   1.236 -    }
   1.237 -
   1.238 -    public static Character charValue(Object val) {
   1.239 -        if (val instanceof Number) {
   1.240 -            return Character.toChars(numberValue(val).intValue())[0];
   1.241 -        }
   1.242 -        if (val instanceof Boolean) {
   1.243 -            return (Boolean)val ? (char)1 : (char)0;
   1.244 -        }
   1.245 -        if (val instanceof String) {
   1.246 -            String s = (String)val;
   1.247 -            return s.isEmpty() ? (char)0 : s.charAt(0);
   1.248 -        }
   1.249 -        return (Character)val;
   1.250 -    }
   1.251 -    
   1.252 -    public static Boolean boolValue(Object val) {
   1.253 -        if (val instanceof String) {
   1.254 -            return Boolean.parseBoolean((String)val);
   1.255 -        }
   1.256 -        if (val instanceof Number) {
   1.257 -            return numberValue(val).doubleValue() != 0.0;
   1.258 -        }
   1.259 -    
   1.260 -        return Boolean.TRUE.equals(val);
   1.261 -    }
   1.262 -    
   1.263 -    public static void loadJSON(
   1.264 -        BrwsrCtx c, RcvrJSON callback,
   1.265 -        String urlBefore, String urlAfter, String method,
   1.266 -        Object data
   1.267 -    ) {
   1.268 -        JSONCall call = PropertyBindingAccessor.createCall(c, callback, urlBefore, urlAfter, method, data);
   1.269 -        Transfer t = findTransfer(c);
   1.270 -        t.loadJSON(call);
   1.271 -    }
   1.272 -    public static WS openWS(
   1.273 -        BrwsrCtx c, RcvrJSON r, String url, Object data
   1.274 -    ) {
   1.275 -        WS ws = WSImpl.create(findWSTransfer(c), r);
   1.276 -        ws.send(c, url, data);
   1.277 -        return ws;
   1.278 -    }
   1.279 -    
   1.280 -    public static abstract class WS {
   1.281 -        private WS() {
   1.282 -        }
   1.283 -        
   1.284 -        public abstract void send(BrwsrCtx ctx, String url, Object model);
   1.285 -    }
   1.286 -    
   1.287 -    private static final class WSImpl<Socket> extends WS {
   1.288 -
   1.289 -        private final WSTransfer<Socket> trans;
   1.290 -        private final RcvrJSON rcvr;
   1.291 -        private Socket socket;
   1.292 -        private String prevURL;
   1.293 -
   1.294 -        private WSImpl(WSTransfer<Socket> trans, RcvrJSON rcvr) {
   1.295 -            this.trans = trans;
   1.296 -            this.rcvr = rcvr;
   1.297 -        }
   1.298 -        
   1.299 -        static <Socket> WS create(WSTransfer<Socket> t, RcvrJSON r) {
   1.300 -            return new WSImpl<Socket>(t, r);
   1.301 -        }
   1.302 -
   1.303 -        @Override
   1.304 -        public void send(BrwsrCtx ctx, String url, Object data) {
   1.305 -            Socket s = socket;
   1.306 -            if (s == null) {
   1.307 -                if (data != null) {
   1.308 -                    throw new IllegalStateException("WebSocket is not opened yet. Call with null data, was: " + data);
   1.309 -                }
   1.310 -                JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, url, null, "WebSocket", null);
   1.311 -                socket = trans.open(url, call);
   1.312 -                prevURL = url;
   1.313 -                return;
   1.314 -            }
   1.315 -            if (data == null) {
   1.316 -                trans.close(s);
   1.317 -                socket = null;
   1.318 -                return;
   1.319 -            }
   1.320 -            if (!prevURL.equals(url)) {
   1.321 -                throw new IllegalStateException(
   1.322 -                    "Can't call to different URL " + url + " was: " + prevURL + "!"
   1.323 -                    + " Close the socket by calling it will null data first!"
   1.324 -                );
   1.325 -            }
   1.326 -            JSONCall call = PropertyBindingAccessor.createCall(ctx, rcvr, prevURL, null, "WebSocket", data);
   1.327 -            trans.send(s, call);
   1.328 -        }
   1.329 -        
   1.330 -    }
   1.331 -    
   1.332 -    private static final Map<Class,FromJSON<?>> froms;
   1.333 -    static {
   1.334 -        Map<Class,FromJSON<?>> m = new HashMap<Class,FromJSON<?>>();
   1.335 -        froms = m;
   1.336 -    }
   1.337 -    public static void register(FromJSON<?> from) {
   1.338 -        froms.put(from.factoryFor(), from);
   1.339 -    }
   1.340 -    
   1.341 -    public static boolean isModel(Class<?> clazz) {
   1.342 -        return findFrom(clazz) != null; 
   1.343 -    }
   1.344 -    
   1.345 -    private static FromJSON<?> findFrom(Class<?> clazz) {
   1.346 -        for (int i = 0; i < 2; i++) {
   1.347 -            FromJSON<?> from = froms.get(clazz);
   1.348 -            if (from == null) {
   1.349 -                initClass(clazz);
   1.350 -            } else {
   1.351 -                return from;
   1.352 -            }
   1.353 -        }
   1.354 -        return null;
   1.355 -    }
   1.356 -    
   1.357 -    public static <Model> Model bindTo(Model model, BrwsrCtx c) {
   1.358 -        FromJSON<?> from = findFrom(model.getClass());
   1.359 -        if (from == null) {
   1.360 -            throw new IllegalArgumentException();
   1.361 -        }
   1.362 -        return (Model) from.cloneTo(model, c);
   1.363 -    }
   1.364 -    
   1.365 -    public static <T> T readStream(BrwsrCtx c, Class<T> modelClazz, InputStream data) 
   1.366 -    throws IOException {
   1.367 -        Transfer tr = findTransfer(c);
   1.368 -        return read(c, modelClazz, tr.toJSON((InputStream)data));
   1.369 -    }
   1.370 -    public static <T> T read(BrwsrCtx c, Class<T> modelClazz, Object data) {
   1.371 -        if (data == null) {
   1.372 -            return null;
   1.373 -        }
   1.374 -        if (modelClazz == String.class) {
   1.375 -            return modelClazz.cast(data.toString());
   1.376 -        }
   1.377 -        for (int i = 0; i < 2; i++) {
   1.378 -            FromJSON<?> from = froms.get(modelClazz);
   1.379 -            if (from == null) {
   1.380 -                initClass(modelClazz);
   1.381 -            } else {
   1.382 -                return modelClazz.cast(from.read(c, data));
   1.383 -            }
   1.384 -        }
   1.385 -        throw new NullPointerException();
   1.386 -    }
   1.387 -    static void initClass(Class<?> modelClazz) {
   1.388 -        try {
   1.389 -            // try to resolve the class
   1.390 -            ClassLoader l;
   1.391 -            try {
   1.392 -                l = modelClazz.getClassLoader();
   1.393 -            } catch (SecurityException ex) {
   1.394 -                l = null;
   1.395 -            }
   1.396 -            if (l != null) {
   1.397 -                Class.forName(modelClazz.getName(), true, l);
   1.398 -            }
   1.399 -            modelClazz.newInstance();
   1.400 -        } catch (Exception ex) {
   1.401 -            // ignore and try again
   1.402 -        }
   1.403 -    }
   1.404 -    
   1.405 -    private static final class EmptyTech
   1.406 -    implements Technology<Object>, Transfer, WSTransfer<Void> {
   1.407 -        private static final EmptyTech EMPTY = new EmptyTech();
   1.408 -
   1.409 -        @Override
   1.410 -        public Object wrapModel(Object model) {
   1.411 -            return model;
   1.412 -        }
   1.413 -
   1.414 -        @Override
   1.415 -        public void valueHasMutated(Object data, String propertyName) {
   1.416 -        }
   1.417 -
   1.418 -        @Override
   1.419 -        public void bind(PropertyBinding b, Object model, Object data) {
   1.420 -        }
   1.421 -
   1.422 -        @Override
   1.423 -        public void expose(FunctionBinding fb, Object model, Object d) {
   1.424 -        }
   1.425 -
   1.426 -        @Override
   1.427 -        public void applyBindings(Object data) {
   1.428 -        }
   1.429 -
   1.430 -        @Override
   1.431 -        public Object wrapArray(Object[] arr) {
   1.432 -            return arr;
   1.433 -        }
   1.434 -
   1.435 -        @Override
   1.436 -        public void extract(Object obj, String[] props, Object[] values) {
   1.437 -            for (int i = 0; i < values.length; i++) {
   1.438 -                values[i] = null;
   1.439 -            }
   1.440 -        }
   1.441 -
   1.442 -        @Override
   1.443 -        public void loadJSON(JSONCall call) {
   1.444 -            call.notifyError(new UnsupportedOperationException());
   1.445 -        }
   1.446 -
   1.447 -        @Override
   1.448 -        public <M> M toModel(Class<M> modelClass, Object data) {
   1.449 -            return modelClass.cast(data);
   1.450 -        }
   1.451 -
   1.452 -        @Override
   1.453 -        public Object toJSON(InputStream is) throws IOException {
   1.454 -            throw new IOException("Not supported");
   1.455 -        }
   1.456 -
   1.457 -        @Override
   1.458 -        public synchronized void runSafe(Runnable r) {
   1.459 -            r.run();
   1.460 -        }
   1.461 -
   1.462 -        @Override
   1.463 -        public Void open(String url, JSONCall onReply) {
   1.464 -            onReply.notifyError(new UnsupportedOperationException("WebSockets not supported!"));
   1.465 -            return null;
   1.466 -        }
   1.467 -
   1.468 -        @Override
   1.469 -        public void send(Void socket, JSONCall data) {
   1.470 -        }
   1.471 -
   1.472 -        @Override
   1.473 -        public void close(Void socket) {
   1.474 -        }
   1.475 -    }
   1.476 -    
   1.477 -}