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
jaroslav@9
     1
/**
jaroslav@358
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jaroslav@9
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jaroslav@9
     5
 *
jaroslav@358
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@358
     7
 * Other names may be trademarks of their respective owners.
jaroslav@9
     8
 *
jaroslav@358
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@358
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@358
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@358
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@358
    13
 * License. You can obtain a copy of the License at
jaroslav@358
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@358
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@358
    16
 * specific language governing permissions and limitations under the
jaroslav@358
    17
 * License.  When distributing the software, include this License Header
jaroslav@358
    18
 * Notice in each file and include the License file at
jaroslav@358
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@358
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@358
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@358
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@358
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@358
    24
 * your own identifying information:
jaroslav@358
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@358
    26
 *
jaroslav@358
    27
 * Contributor(s):
jaroslav@358
    28
 *
jaroslav@358
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@551
    30
 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
jaroslav@358
    31
 *
jaroslav@358
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@358
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@358
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@358
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@358
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@358
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@358
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@358
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@358
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@358
    41
 * made subject to such option by the copyright holder.
jaroslav@9
    42
 */
jtulach@838
    43
package org.netbeans.html.json.spi;
jaroslav@9
    44
jtulach@870
    45
import java.lang.ref.Reference;
jtulach@870
    46
import java.lang.ref.WeakReference;
jaroslav@262
    47
import net.java.html.BrwsrCtx;
jtulach@1055
    48
import net.java.html.json.ComputedProperty;
jaroslav@404
    49
import org.netbeans.html.json.impl.Bindings;
jaroslav@414
    50
import org.netbeans.html.json.impl.JSON;
jaroslav@362
    51
import org.netbeans.html.json.impl.PropertyBindingAccessor;
jaroslav@362
    52
import org.netbeans.html.json.impl.RcvrJSON;
jaroslav@9
    53
jtulach@940
    54
/** Describes a property when one is asked to
jtulach@940
    55
 * bind it
jaroslav@9
    56
 *
jtulach@790
    57
 * @author Jaroslav Tulach
jaroslav@9
    58
 */
jaroslav@415
    59
public abstract class PropertyBinding {
jaroslav@415
    60
    PropertyBinding() {
jaroslav@9
    61
    }
jaroslav@9
    62
jaroslav@9
    63
    static {
jaroslav@9
    64
        new PropertyBindingAccessor() {
jaroslav@9
    65
            @Override
jtulach@940
    66
            protected JSONCall newCall(BrwsrCtx ctx, RcvrJSON callback, String headers, String urlBefore, String urlAfter, String method, Object data) {
jtulach@940
    67
                return new JSONCall(ctx, callback, headers, urlBefore, urlAfter, method, data);
jaroslav@24
    68
            }
jaroslav@404
    69
jaroslav@404
    70
            @Override
jtulach@1028
    71
            protected Bindings bindings(Proto proto, boolean initialize, Object copyFrom) {
jtulach@1028
    72
                return initialize ? proto.initBindings(copyFrom) : proto.getBindings();
jaroslav@404
    73
            }
jaroslav@406
    74
jaroslav@406
    75
            @Override
jaroslav@406
    76
            protected void notifyChange(Proto proto, int propIndex) {
jaroslav@406
    77
                proto.onChange(propIndex);
jaroslav@406
    78
            }
jaroslav@412
    79
jaroslav@412
    80
            @Override
jaroslav@412
    81
            protected Proto findProto(Proto.Type<?> type, Object object) {
jaroslav@412
    82
                return type.protoFor(object);
jaroslav@412
    83
            }
jaroslav@412
    84
jaroslav@412
    85
            @Override
jaroslav@412
    86
            protected <Model> Model cloneTo(Proto.Type<Model> type, Model model, BrwsrCtx c) {
jaroslav@412
    87
                return type.cloneTo(model, c);
jaroslav@412
    88
            }
jaroslav@412
    89
jaroslav@412
    90
            @Override
jaroslav@412
    91
            protected Object read(Proto.Type<?> from, BrwsrCtx c, Object data) {
jaroslav@412
    92
                return from.read(c, data);
jaroslav@412
    93
            }
jaroslav@415
    94
jaroslav@415
    95
            @Override
jaroslav@415
    96
            protected <M> PropertyBinding newBinding(
jtulach@1055
    97
                Proto.Type<M> access, Bindings<?> bindings, String name, int index, M model, byte propertyType) {
jtulach@1055
    98
                return new Impl(model, bindings, name, index, access, propertyType);
jaroslav@415
    99
            }
jaroslav@9
   100
        };
jaroslav@9
   101
    }
jaroslav@9
   102
jaroslav@415
   103
    /** Name of the property this binding represents.
jaroslav@415
   104
     * @return name of the property
jaroslav@415
   105
     */
jaroslav@415
   106
    public abstract String getPropertyName();
jaroslav@17
   107
jaroslav@415
   108
    /** Changes value of the property. Can be called only on dedicated
jaroslav@415
   109
     * thread. See {@link Technology#runSafe(java.lang.Runnable)}.
jtulach@940
   110
     *
jaroslav@415
   111
     * @param v new value of the property
jaroslav@415
   112
     */
jaroslav@415
   113
    public abstract void setValue(Object v);
jtulach@940
   114
jaroslav@415
   115
    /** Obtains current value of the property this binding represents.
jaroslav@415
   116
     * Can be called only on dedicated
jaroslav@415
   117
     * thread. See {@link Technology#runSafe(java.lang.Runnable)}.
jtulach@940
   118
     *
jaroslav@415
   119
     * @return the value or <code>null</code>
jaroslav@415
   120
     */
jaroslav@415
   121
    public abstract Object getValue();
jtulach@940
   122
jtulach@1055
   123
    /** Is this property read only?. Or can one call {@link #setValue(java.lang.Object)}?
jtulach@1055
   124
     * The property can still change, but only as a result of other
jtulach@1055
   125
     * properties being changed, just like {@link ComputedProperty} can.
jtulach@940
   126
     *
jaroslav@415
   127
     * @return true, if this property is read only
jaroslav@415
   128
     */
jaroslav@415
   129
    public abstract boolean isReadOnly();
jtulach@870
   130
jtulach@1055
   131
    /** Is this property constant?. If a property is constant, than its
jtulach@1055
   132
     * value cannot changed after it is read.
jtulach@1055
   133
     *
jtulach@1055
   134
     * @return true, if this property is constant
jtulach@1055
   135
     * @since 1.3
jtulach@1055
   136
     */
jtulach@1055
   137
    public abstract boolean isConstant();
jtulach@1055
   138
jtulach@870
   139
    /** Returns identical version of the binding, but one that holds on the
jtulach@870
   140
     * original model object via weak reference.
jtulach@940
   141
     *
jtulach@870
   142
     * @return binding that uses weak reference
jtulach@870
   143
     * @since 1.1
jtulach@870
   144
     */
jtulach@870
   145
    public abstract PropertyBinding weak();
jtulach@940
   146
jtulach@870
   147
    private static abstract class AImpl<M> extends PropertyBinding {
jaroslav@415
   148
        public final String name;
jtulach@1055
   149
        public final byte propertyType;
jtulach@870
   150
        final Proto.Type<M> access;
jtulach@870
   151
        final Bindings<?> bindings;
jtulach@870
   152
        final int index;
jaroslav@415
   153
jtulach@1055
   154
        public AImpl(Bindings<?> bindings, String name, int index, Proto.Type<M> access, byte propertyType) {
jaroslav@415
   155
            this.bindings = bindings;
jaroslav@415
   156
            this.name = name;
jaroslav@415
   157
            this.index = index;
jaroslav@415
   158
            this.access = access;
jtulach@1055
   159
            this.propertyType = propertyType;
jaroslav@415
   160
        }
jtulach@940
   161
jtulach@870
   162
        protected abstract M model();
jaroslav@415
   163
jaroslav@415
   164
        @Override
jaroslav@415
   165
        public void setValue(Object v) {
jtulach@870
   166
            M model = model();
jtulach@870
   167
            if (model == null) {
jtulach@870
   168
                return;
jtulach@870
   169
            }
jaroslav@415
   170
            access.setValue(model, index, v);
jaroslav@415
   171
        }
jaroslav@415
   172
jaroslav@415
   173
        @Override
jaroslav@415
   174
        public Object getValue() {
jtulach@870
   175
            M model = model();
jtulach@870
   176
            if (model == null) {
jtulach@870
   177
                return null;
jtulach@870
   178
            }
jaroslav@415
   179
            Object v = access.getValue(model, index);
jaroslav@415
   180
            Object r = JSON.find(v, bindings);
jaroslav@415
   181
            return r == null ? v : r;
jaroslav@415
   182
        }
jaroslav@415
   183
jaroslav@415
   184
        @Override
jaroslav@415
   185
        public boolean isReadOnly() {
jtulach@1055
   186
            return (propertyType & 1) != 0;
jtulach@1055
   187
        }
jtulach@1055
   188
jtulach@1055
   189
        @Override
jtulach@1055
   190
        public boolean isConstant() {
jtulach@1055
   191
            return (propertyType & 2) != 0;
jaroslav@415
   192
        }
jaroslav@415
   193
jaroslav@415
   194
        @Override
jaroslav@415
   195
        public String getPropertyName() {
jaroslav@415
   196
            return name;
jaroslav@415
   197
        }
jaroslav@415
   198
    } // end of PBData
jtulach@940
   199
jtulach@870
   200
    private static final class Impl<M> extends AImpl<M> {
jtulach@870
   201
        private final M model;
jtulach@870
   202
jtulach@1055
   203
        public Impl(M model, Bindings<?> bindings, String name, int index, Proto.Type<M> access, byte propertyType) {
jtulach@1055
   204
            super(bindings, name, index, access, propertyType);
jtulach@870
   205
            this.model = model;
jtulach@870
   206
        }
jtulach@870
   207
jtulach@870
   208
        @Override
jtulach@870
   209
        protected M model() {
jtulach@870
   210
            return model;
jtulach@870
   211
        }
jtulach@870
   212
jtulach@870
   213
        @Override
jtulach@870
   214
        public PropertyBinding weak() {
jtulach@1055
   215
            return new Weak(model, bindings, name, index, access, propertyType);
jtulach@870
   216
        }
jtulach@870
   217
    }
jtulach@940
   218
jtulach@870
   219
    private static final class Weak<M> extends AImpl<M> {
jtulach@870
   220
        private final Reference<M> ref;
jtulach@1055
   221
        public Weak(M model, Bindings<?> bindings, String name, int index, Proto.Type<M> access, byte propertyType) {
jtulach@1055
   222
            super(bindings, name, index, access, propertyType);
jtulach@870
   223
            this.ref = new WeakReference<M>(model);
jtulach@870
   224
        }
jtulach@870
   225
jtulach@870
   226
        @Override
jtulach@870
   227
        protected M model() {
jtulach@870
   228
            return ref.get();
jtulach@870
   229
        }
jtulach@870
   230
jtulach@870
   231
        @Override
jtulach@870
   232
        public PropertyBinding weak() {
jtulach@870
   233
            return this;
jtulach@870
   234
        }
jtulach@870
   235
    }
jaroslav@9
   236
}