json/src/main/java/org/netbeans/html/json/impl/JSONList.java
author Jaroslav Tulach <jtulach@netbeans.org>
Mon, 22 Feb 2016 06:09:33 +0100
branchNonMutable258088
changeset 1054 4c40ceb185e5
parent 1028 453e44c757ff
permissions -rw-r--r--
#258088: Introducing @Property(mutable=false) and making sure the generated Java code yields exceptions when such properties are modified after their use by the technology
jtulach@2
     1
/**
jaroslav@358
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jtulach@2
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jtulach@2
     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.
jtulach@2
     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.
jtulach@2
    42
 */
jaroslav@362
    43
package org.netbeans.html.json.impl;
jtulach@2
    44
jaroslav@312
    45
import java.lang.reflect.Array;
jtulach@2
    46
import java.util.ArrayList;
jaroslav@4
    47
import java.util.Collection;
jaroslav@4
    48
import java.util.Iterator;
jtulach@838
    49
import org.netbeans.html.json.spi.Proto;
jtulach@2
    50
jtulach@2
    51
/**
jtulach@2
    52
 *
jtulach@790
    53
 * @author Jaroslav Tulach
jtulach@2
    54
 */
jtulach@2
    55
public final class JSONList<T> extends ArrayList<T> {
jaroslav@383
    56
    private final Proto proto;
jaroslav@4
    57
    private final String name;
jaroslav@4
    58
    private final String[] deps;
jaroslav@383
    59
    private final int index;
jtulach@2
    60
jaroslav@383
    61
    public JSONList(Proto proto, String name, int changeIndex, String... deps) {
jaroslav@374
    62
        this.proto = proto;
jaroslav@4
    63
        this.name = name;
jaroslav@4
    64
        this.deps = deps;
jaroslav@383
    65
        this.index = changeIndex;
jaroslav@254
    66
    }
jaroslav@312
    67
    
jaroslav@312
    68
    public void init(Object values) {
jaroslav@312
    69
        int len;
jaroslav@312
    70
        if (values == null || (len = Array.getLength(values)) == 0) {
jaroslav@312
    71
            return;
jaroslav@312
    72
        }
jaroslav@312
    73
        for (int i = 0; i < len; i++) {
jaroslav@312
    74
            Object data = Array.get(values, i);
jaroslav@312
    75
            super.add((T)data);
jaroslav@312
    76
        }
jaroslav@312
    77
    }
jaroslav@383
    78
    public static <T> void init(Collection<T> to, Object values) {
jaroslav@383
    79
        int len;
jaroslav@383
    80
        if (values == null || (len = Array.getLength(values)) == 0) {
jaroslav@383
    81
            return;
jaroslav@383
    82
        }
jaroslav@383
    83
        for (int i = 0; i < len; i++) {
jaroslav@383
    84
            Object data = Array.get(values, i);
jaroslav@383
    85
            to.add((T)data);
jaroslav@383
    86
        }
jaroslav@383
    87
    }
jaroslav@312
    88
    
jaroslav@4
    89
    @Override
jaroslav@4
    90
    public boolean add(T e) {
jtulach@1054
    91
        prepareChange();
jaroslav@4
    92
        boolean ret = super.add(e);
jaroslav@4
    93
        notifyChange();
jaroslav@4
    94
        return ret;
jtulach@2
    95
    }
jaroslav@4
    96
jtulach@2
    97
    @Override
jaroslav@4
    98
    public boolean addAll(Collection<? extends T> c) {
jtulach@1054
    99
        prepareChange();
jaroslav@4
   100
        boolean ret = super.addAll(c);
jaroslav@4
   101
        notifyChange();
jaroslav@4
   102
        return ret;
jaroslav@4
   103
    }
jaroslav@4
   104
jaroslav@4
   105
    @Override
jaroslav@4
   106
    public boolean addAll(int index, Collection<? extends T> c) {
jtulach@1054
   107
        prepareChange();
jaroslav@4
   108
        boolean ret = super.addAll(index, c);
jaroslav@4
   109
        notifyChange();
jaroslav@4
   110
        return ret;
jaroslav@4
   111
    }
jaroslav@4
   112
jtulach@970
   113
    public void fastReplace(Collection<? extends T> c) {
jtulach@1054
   114
        prepareChange();
jtulach@970
   115
        super.clear();
jtulach@970
   116
        super.addAll(c);
jtulach@970
   117
        notifyChange();
jtulach@970
   118
    }
jtulach@970
   119
jaroslav@4
   120
    @Override
jaroslav@4
   121
    public boolean remove(Object o) {
jtulach@1054
   122
        prepareChange();
jaroslav@4
   123
        boolean ret = super.remove(o);
jaroslav@4
   124
        notifyChange();
jaroslav@4
   125
        return ret;
jaroslav@4
   126
    }
jaroslav@4
   127
jaroslav@4
   128
    @Override
jaroslav@4
   129
    public void clear() {
jtulach@1054
   130
        prepareChange();
jaroslav@4
   131
        super.clear();
jaroslav@4
   132
        notifyChange();
jaroslav@4
   133
    }
jaroslav@4
   134
jaroslav@4
   135
    @Override
jaroslav@4
   136
    public boolean removeAll(Collection<?> c) {
jtulach@1054
   137
        prepareChange();
jaroslav@4
   138
        boolean ret = super.removeAll(c);
jaroslav@4
   139
        notifyChange();
jaroslav@4
   140
        return ret;
jaroslav@4
   141
    }
jaroslav@4
   142
jaroslav@4
   143
    @Override
jaroslav@4
   144
    public boolean retainAll(Collection<?> c) {
jtulach@1054
   145
        prepareChange();
jaroslav@4
   146
        boolean ret = super.retainAll(c);
jaroslav@4
   147
        notifyChange();
jaroslav@4
   148
        return ret;
jaroslav@4
   149
    }
jaroslav@4
   150
jaroslav@4
   151
    @Override
jaroslav@4
   152
    public T set(int index, T element) {
jtulach@1054
   153
        prepareChange();
jaroslav@4
   154
        T ret = super.set(index, element);
jaroslav@4
   155
        notifyChange();
jaroslav@4
   156
        return ret;
jaroslav@4
   157
    }
jaroslav@4
   158
jaroslav@4
   159
    @Override
jaroslav@4
   160
    public void add(int index, T element) {
jtulach@1054
   161
        prepareChange();
jaroslav@4
   162
        super.add(index, element);
jaroslav@4
   163
        notifyChange();
jaroslav@4
   164
    }
jaroslav@4
   165
jaroslav@4
   166
    @Override
jaroslav@4
   167
    public T remove(int index) {
jtulach@1054
   168
        prepareChange();
jaroslav@4
   169
        T ret = super.remove(index);
jaroslav@4
   170
        notifyChange();
jaroslav@4
   171
        return ret;
jaroslav@4
   172
    }
jaroslav@4
   173
jaroslav@4
   174
    @Override
jaroslav@4
   175
    public String toString() {
jaroslav@4
   176
        Iterator<T> it = iterator();
jaroslav@4
   177
        if (!it.hasNext()) {
jaroslav@4
   178
            return "[]";
jaroslav@4
   179
        }
jaroslav@4
   180
        String sep = "";
jaroslav@4
   181
        StringBuilder sb = new StringBuilder();
jaroslav@4
   182
        sb.append('[');
jaroslav@4
   183
        while (it.hasNext()) {
jaroslav@4
   184
            T t = it.next();
jaroslav@4
   185
            sb.append(sep);
jaroslav@4
   186
            sb.append(JSON.toJSON(t));
jaroslav@4
   187
            sep = ",";
jaroslav@4
   188
        }
jaroslav@4
   189
        sb.append(']');
jaroslav@4
   190
        return sb.toString();
jaroslav@4
   191
    }
jaroslav@4
   192
jtulach@1054
   193
    private void prepareChange() {
jtulach@1054
   194
        if (index == Integer.MIN_VALUE) {
jtulach@1054
   195
            try {
jtulach@1054
   196
                proto.initTo(null, null);
jtulach@1054
   197
            } catch (IllegalStateException ex) {
jtulach@1054
   198
                throw new UnsupportedOperationException();
jtulach@1054
   199
            }
jtulach@1054
   200
        }
jtulach@1054
   201
    }
jtulach@1054
   202
jaroslav@4
   203
    private void notifyChange() {
jaroslav@719
   204
        proto.getContext().execute(new Runnable() {
jaroslav@719
   205
            @Override
jaroslav@719
   206
            public void run() {
jtulach@1028
   207
                Bindings m = PropertyBindingAccessor.getBindings(proto, false, null);
jaroslav@719
   208
                if (m != null) {
jtulach@908
   209
                    m.valueHasMutated(name, null, JSONList.this);
jaroslav@719
   210
                    for (String dependant : deps) {
jaroslav@719
   211
                        m.valueHasMutated(dependant, null, null);
jaroslav@719
   212
                    }
jaroslav@719
   213
                    if (index >= 0) {
jaroslav@719
   214
                        PropertyBindingAccessor.notifyProtoChange(proto, index);
jaroslav@719
   215
                    }
jaroslav@719
   216
                }
jaroslav@4
   217
            }
jaroslav@719
   218
        });
jaroslav@282
   219
    }
jaroslav@4
   220
jaroslav@4
   221
    @Override
jaroslav@4
   222
    public JSONList clone() {
jaroslav@282
   223
        throw new UnsupportedOperationException();
jtulach@2
   224
    }
jaroslav@16
   225
jaroslav@235
   226
    static final Object koData(Collection<?> c, Bindings m) {
jtulach@328
   227
        Object[] arr = c.toArray(new Object[c.size()]);
jaroslav@16
   228
        for (int i = 0; i < arr.length; i++) {
jaroslav@414
   229
            Object r = JSON.find(arr[i], m);
jaroslav@19
   230
            if (r != null) {
jaroslav@19
   231
                arr[i] = r;
jaroslav@19
   232
            }
jaroslav@16
   233
        }
jaroslav@235
   234
        return m.wrapArray(arr);
jaroslav@16
   235
    }
jaroslav@235
   236
jaroslav@235
   237
    final Object koData() {
jtulach@1028
   238
        return koData(this, PropertyBindingAccessor.getBindings(proto, true, null));
jaroslav@235
   239
    }
jtulach@2
   240
}