json/src/main/java/org/netbeans/html/json/spi/PropertyBinding.java
author Jaroslav Tulach <jtulach@netbeans.org>
Mon, 22 Feb 2016 19:58:32 +0100
branchNonMutable258088
changeset 1055 c61d247f087a
parent 1028 453e44c757ff
permissions -rw-r--r--
#258088: Non-mutable values aren't wrapped into ko.observable, but rather stored as primitive values
     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.json.spi;
    44 
    45 import java.lang.ref.Reference;
    46 import java.lang.ref.WeakReference;
    47 import net.java.html.BrwsrCtx;
    48 import net.java.html.json.ComputedProperty;
    49 import org.netbeans.html.json.impl.Bindings;
    50 import org.netbeans.html.json.impl.JSON;
    51 import org.netbeans.html.json.impl.PropertyBindingAccessor;
    52 import org.netbeans.html.json.impl.RcvrJSON;
    53 
    54 /** Describes a property when one is asked to
    55  * bind it
    56  *
    57  * @author Jaroslav Tulach
    58  */
    59 public abstract class PropertyBinding {
    60     PropertyBinding() {
    61     }
    62 
    63     static {
    64         new PropertyBindingAccessor() {
    65             @Override
    66             protected JSONCall newCall(BrwsrCtx ctx, RcvrJSON callback, String headers, String urlBefore, String urlAfter, String method, Object data) {
    67                 return new JSONCall(ctx, callback, headers, urlBefore, urlAfter, method, data);
    68             }
    69 
    70             @Override
    71             protected Bindings bindings(Proto proto, boolean initialize, Object copyFrom) {
    72                 return initialize ? proto.initBindings(copyFrom) : proto.getBindings();
    73             }
    74 
    75             @Override
    76             protected void notifyChange(Proto proto, int propIndex) {
    77                 proto.onChange(propIndex);
    78             }
    79 
    80             @Override
    81             protected Proto findProto(Proto.Type<?> type, Object object) {
    82                 return type.protoFor(object);
    83             }
    84 
    85             @Override
    86             protected <Model> Model cloneTo(Proto.Type<Model> type, Model model, BrwsrCtx c) {
    87                 return type.cloneTo(model, c);
    88             }
    89 
    90             @Override
    91             protected Object read(Proto.Type<?> from, BrwsrCtx c, Object data) {
    92                 return from.read(c, data);
    93             }
    94 
    95             @Override
    96             protected <M> PropertyBinding newBinding(
    97                 Proto.Type<M> access, Bindings<?> bindings, String name, int index, M model, byte propertyType) {
    98                 return new Impl(model, bindings, name, index, access, propertyType);
    99             }
   100         };
   101     }
   102 
   103     /** Name of the property this binding represents.
   104      * @return name of the property
   105      */
   106     public abstract String getPropertyName();
   107 
   108     /** Changes value of the property. Can be called only on dedicated
   109      * thread. See {@link Technology#runSafe(java.lang.Runnable)}.
   110      *
   111      * @param v new value of the property
   112      */
   113     public abstract void setValue(Object v);
   114 
   115     /** Obtains current value of the property this binding represents.
   116      * Can be called only on dedicated
   117      * thread. See {@link Technology#runSafe(java.lang.Runnable)}.
   118      *
   119      * @return the value or <code>null</code>
   120      */
   121     public abstract Object getValue();
   122 
   123     /** Is this property read only?. Or can one call {@link #setValue(java.lang.Object)}?
   124      * The property can still change, but only as a result of other
   125      * properties being changed, just like {@link ComputedProperty} can.
   126      *
   127      * @return true, if this property is read only
   128      */
   129     public abstract boolean isReadOnly();
   130 
   131     /** Is this property constant?. If a property is constant, than its
   132      * value cannot changed after it is read.
   133      *
   134      * @return true, if this property is constant
   135      * @since 1.3
   136      */
   137     public abstract boolean isConstant();
   138 
   139     /** Returns identical version of the binding, but one that holds on the
   140      * original model object via weak reference.
   141      *
   142      * @return binding that uses weak reference
   143      * @since 1.1
   144      */
   145     public abstract PropertyBinding weak();
   146 
   147     private static abstract class AImpl<M> extends PropertyBinding {
   148         public final String name;
   149         public final byte propertyType;
   150         final Proto.Type<M> access;
   151         final Bindings<?> bindings;
   152         final int index;
   153 
   154         public AImpl(Bindings<?> bindings, String name, int index, Proto.Type<M> access, byte propertyType) {
   155             this.bindings = bindings;
   156             this.name = name;
   157             this.index = index;
   158             this.access = access;
   159             this.propertyType = propertyType;
   160         }
   161 
   162         protected abstract M model();
   163 
   164         @Override
   165         public void setValue(Object v) {
   166             M model = model();
   167             if (model == null) {
   168                 return;
   169             }
   170             access.setValue(model, index, v);
   171         }
   172 
   173         @Override
   174         public Object getValue() {
   175             M model = model();
   176             if (model == null) {
   177                 return null;
   178             }
   179             Object v = access.getValue(model, index);
   180             Object r = JSON.find(v, bindings);
   181             return r == null ? v : r;
   182         }
   183 
   184         @Override
   185         public boolean isReadOnly() {
   186             return (propertyType & 1) != 0;
   187         }
   188 
   189         @Override
   190         public boolean isConstant() {
   191             return (propertyType & 2) != 0;
   192         }
   193 
   194         @Override
   195         public String getPropertyName() {
   196             return name;
   197         }
   198     } // end of PBData
   199 
   200     private static final class Impl<M> extends AImpl<M> {
   201         private final M model;
   202 
   203         public Impl(M model, Bindings<?> bindings, String name, int index, Proto.Type<M> access, byte propertyType) {
   204             super(bindings, name, index, access, propertyType);
   205             this.model = model;
   206         }
   207 
   208         @Override
   209         protected M model() {
   210             return model;
   211         }
   212 
   213         @Override
   214         public PropertyBinding weak() {
   215             return new Weak(model, bindings, name, index, access, propertyType);
   216         }
   217     }
   218 
   219     private static final class Weak<M> extends AImpl<M> {
   220         private final Reference<M> ref;
   221         public Weak(M model, Bindings<?> bindings, String name, int index, Proto.Type<M> access, byte propertyType) {
   222             super(bindings, name, index, access, propertyType);
   223             this.ref = new WeakReference<M>(model);
   224         }
   225 
   226         @Override
   227         protected M model() {
   228             return ref.get();
   229         }
   230 
   231         @Override
   232         public PropertyBinding weak() {
   233             return this;
   234         }
   235     }
   236 }