Coverage Report - com.sun.javafx.runtime.location.SequenceVariable
 
Classes in this File Line Coverage Branch Coverage Complexity
SequenceVariable
87%
139/159
75%
45/60
0
SequenceVariable$1
100%
3/3
N/A
0
SequenceVariable$2
0%
0/2
N/A
0
SequenceVariable$3
0%
0/3
N/A
0
SequenceVariable$4
100%
3/3
N/A
0
SequenceVariable$5
100%
4/4
N/A
0
SequenceVariable$6
100%
3/3
N/A
0
SequenceVariable$7
75%
3/4
25%
1/4
0
 
 1  
 package com.sun.javafx.runtime.location;
 2  
 
 3  
 import java.util.Iterator;
 4  
 import java.util.List;
 5  
 import java.util.ArrayList;
 6  
 
 7  
 import com.sun.javafx.runtime.AssignToBoundException;
 8  
 import com.sun.javafx.runtime.ErrorHandler;
 9  
 import com.sun.javafx.runtime.sequence.Sequence;
 10  
 import com.sun.javafx.runtime.sequence.SequenceMutator;
 11  
 import com.sun.javafx.runtime.sequence.SequencePredicate;
 12  
 import com.sun.javafx.runtime.sequence.Sequences;
 13  
 
 14  
 /**
 15  
  * SequenceVariable
 16  
  *
 17  
  * @author Brian Goetz
 18  
  */
 19  8155
 public class SequenceVariable<T>
 20  
         extends AbstractVariable<Sequence<T>, SequenceLocation<T>, SequenceBindingExpression<T>>
 21  
         implements SequenceLocation<T> {
 22  
 
 23  
     private final Class<T> clazz;
 24  
     private final SequenceMutator.Listener<T> mutationListener;
 25  
     private List<SequenceChangeListener<T>> changeListeners;
 26  
     private Sequence<T> value;
 27  
     private SequenceLocation<T> boundLocation;
 28  
 
 29  
 
 30  
     public static <T> SequenceVariable<T> make(Class clazz) {
 31  602
         return new SequenceVariable<T>(clazz);
 32  
     }
 33  
 
 34  
     public static <T> SequenceVariable<T> make(Sequence<T> value) {
 35  31
         return new SequenceVariable<T>(value);
 36  
     }
 37  
 
 38  
     public static <T> SequenceVariable<T> make(Class clazz, Sequence<? extends T> value) {
 39  648
         return new SequenceVariable<T>(clazz, value);
 40  
     }
 41  
 
 42  
     public static<T> SequenceVariable<T> make(Class clazz, boolean lazy, SequenceBindingExpression<T> binding, Location... dependencies) {
 43  8
         return new SequenceVariable<T>(clazz, lazy, binding, dependencies);
 44  
     }
 45  
 
 46  
     public static<T> SequenceVariable<T> make(Class clazz, SequenceBindingExpression<T> binding, Location... dependencies) {
 47  40
         return new SequenceVariable<T>(clazz, false, binding, dependencies);
 48  
     }
 49  
 
 50  
     public static<T> SequenceVariable<T> make(Class clazz, SequenceLocation<T> otherLocation) {
 51  0
         SequenceVariable<T> me = make(clazz);
 52  0
         me.bind(otherLocation);
 53  0
         return me;
 54  
     }
 55  
 
 56  
     /** Create a bijectively bound variable */
 57  
     public static<T> SequenceVariable<T> makeBijective(Class clazz, SequenceVariable<T> other) {
 58  0
         SequenceVariable<T> me = SequenceVariable.<T>make(clazz);
 59  0
         me.bijectiveBind(other);
 60  0
         return me;
 61  
     }
 62  
 
 63  1733
     protected SequenceVariable(Class clazz) {
 64  1733
         this.clazz = clazz;
 65  1733
         this.value = Sequences.emptySequence(clazz);
 66  1733
         this.mutationListener = new SequenceMutator.Listener<T>() {
 67  
             public void onReplaceSlice(int startPos, int endPos, Sequence<? extends T> newElements, Sequence<T> oldValue, Sequence<T> newValue) {
 68  7262
                 replaceSlice(startPos, endPos, newElements, newValue);
 69  7262
             }
 70  
         };
 71  1733
     }
 72  
 
 73  
     protected SequenceVariable(Sequence<T> value) {
 74  31
         this(value.getElementType());
 75  31
         replaceValue(value);
 76  31
     }
 77  
 
 78  
     protected SequenceVariable(Class clazz, Sequence<? extends T> value) {
 79  648
         this(clazz);
 80  648
         if (value == null)
 81  0
             value = Sequences.emptySequence(clazz);
 82  648
         replaceValue(Sequences.upcast(clazz, value));
 83  648
     }
 84  
 
 85  
     protected SequenceVariable(Class clazz, boolean lazy, SequenceBindingExpression<T> binding, Location... dependencies) {
 86  48
         this(clazz);
 87  48
         bind(lazy, binding);
 88  48
         addDependencies(dependencies);
 89  48
     }
 90  
 
 91  
     private void ensureValid() {
 92  17996
         if (isBound() && !isValid())
 93  332
             update();
 94  17996
     }
 95  
 
 96  
     /** Update the held value, notifying change listeners */
 97  
     private void replaceValue(Sequence<T> newValue) {
 98  1695
         assert(boundLocation == null);
 99  1695
         if (newValue == null)
 100  0
             newValue = Sequences.emptySequence(clazz);
 101  1695
         replaceSlice(0, Sequences.size(value)-1, newValue, newValue);
 102  1695
     }
 103  
 
 104  
     /** Update the held value, notifying change listeners */
 105  
     private void replaceSlice(int startPos, int endPos, Sequence<? extends T> newElements, Sequence<T> newValue) {
 106  8957
         assert(boundLocation == null);
 107  8957
         Sequence<T> oldValue = value;
 108  8957
         if (!Sequences.isEqual(oldValue, newValue) || !isInitialized() || !isEverValid()) {
 109  8598
             boolean notifyDependencies = isValid() || !isInitialized() || !isEverValid();
 110  8598
             value = newValue;
 111  8598
             setValid();
 112  8598
             notifyListeners(startPos, endPos, newElements, oldValue, newValue, notifyDependencies);
 113  8598
         }
 114  
         else
 115  359
             setValid();
 116  8957
     }
 117  
 
 118  
 
 119  
     private Sequence<T> getRawValue() {
 120  8737
         return value;
 121  
     }
 122  
 
 123  
     public Sequence<T> get() {
 124  27
         return getAsSequence();
 125  
     }
 126  
 
 127  
     public T get(int position) {
 128  10420
         return getAsSequence().get(position);
 129  
     }
 130  
 
 131  
     public Sequence<T> getAsSequence() {
 132  17996
         ensureValid();
 133  17996
         return value;
 134  
     }
 135  
 
 136  
     public Sequence<T> getSlice(int startPos, int endPos) {
 137  40
         return getAsSequence().getSlice(startPos, endPos);
 138  
     }
 139  
 
 140  
     public boolean isNull() {
 141  0
         return Sequences.size(getAsSequence()) == 0;
 142  
     }
 143  
 
 144  
     protected SequenceBindingExpression<T> makeBindingExpression(final SequenceLocation<T> otherLocation) {
 145  0
         return new SequenceBindingExpression<T>() {
 146  
             public Sequence<T> computeValue() {
 147  0
                 return otherLocation.getAsSequence();
 148  
             }
 149  
         };
 150  
     }
 151  
 
 152  
     public void addChangeListener(final ObjectChangeListener<Sequence<T>> listener) {
 153  0
         addChangeListener(new SequenceChangeListener<T>() {
 154  
             public void onChange(int startPos, int endPos, Sequence<? extends T> newElements, Sequence<T> oldValue, Sequence<T> newValue) {
 155  0
                 listener.onChange(oldValue, newValue);
 156  0
             }
 157  
         });
 158  0
     }
 159  
 
 160  
     public void addChangeListener(SequenceChangeListener<T> listener) {
 161  589
         if (changeListeners == null)
 162  566
             changeListeners = new ArrayList<SequenceChangeListener<T>>();
 163  589
         changeListeners.add(listener);
 164  589
     }
 165  
 
 166  
     public void removeChangeListener(SequenceChangeListener<T> listener) {
 167  159
         if (changeListeners != null)
 168  159
             changeListeners.remove(listener);
 169  159
     }
 170  
 
 171  
     private void notifyListeners(int startPos, int endPos,
 172  
                                  Sequence<? extends T> newElements,
 173  
                                  Sequence<T> oldValue, Sequence<T> newValue,
 174  
                                  boolean notifyDependencies) {
 175  9047
         if (notifyDependencies)
 176  8351
             invalidateDependencies();
 177  9047
         if (changeListeners != null) {
 178  568
             for (SequenceChangeListener<T> listener : changeListeners)
 179  662
                 listener.onChange(startPos, endPos, newElements, oldValue, newValue);
 180  
         }
 181  9047
     }
 182  
 
 183  
     public void bind(SequenceLocation<T> otherLocation) {
 184  65
         ensureBindable();
 185  65
         boundLocation = otherLocation;
 186  65
         Sequence<T> oldValue = value;
 187  65
         value = otherLocation.get();
 188  65
         otherLocation.addChangeListener(new ChangeListener() {
 189  
             public boolean onChange() {
 190  384
                 invalidateDependencies();
 191  384
                 return true;
 192  
             }
 193  
         });
 194  65
         otherLocation.addChangeListener(new SequenceChangeListener<T>() {
 195  
             public void onChange(int startPos, int endPos, Sequence<? extends T> newElements, Sequence<T> oldValue, Sequence<T> newValue) {
 196  384
                 value = newValue;
 197  
                 // @@@ Right value of notifyDependencies?
 198  384
                 notifyListeners(startPos, endPos, newElements, oldValue, newValue, false);
 199  384
             }
 200  
         });
 201  65
         notifyListeners(0, Sequences.size(oldValue)-1, value, oldValue, value, true);
 202  65
     }
 203  
 
 204  
     public boolean isBound() {
 205  30735
         return super.isBound() || (boundLocation != null);
 206  
     }
 207  
 
 208  
     @Override
 209  
     public String toString() {
 210  0
         return getAsSequence().toString();
 211  
     }
 212  
 
 213  
     public Iterator<T> iterator() {
 214  0
         return getAsSequence().iterator();
 215  
     }
 216  
 
 217  
     @Override
 218  
     public void update() {
 219  
         try {
 220  1369
             if (isBound() && !isValid() && boundLocation == null) {
 221  1016
                 replaceValue(Sequences.upcast(clazz, binding.computeValue()));
 222  
             }
 223  
         }
 224  0
         catch (RuntimeException e) {
 225  0
             ErrorHandler.bindException(e);
 226  0
             if (isInitialized())
 227  0
                 replaceValue(Sequences.emptySequence(clazz));
 228  1369
         }
 229  1369
     }
 230  
 
 231  
     private void ensureNotBound() {
 232  9477
         if (isBound())
 233  149
             throw new AssignToBoundException("Cannot mutate bound sequence");
 234  9328
     }
 235  
 
 236  
     public Sequence<T> set(Sequence<T> value) {
 237  1
         return setAsSequence(value);
 238  
     }
 239  
 
 240  
     public void setDefault() {
 241  0
         setAsSequence(Sequences.emptySequence(clazz));
 242  0
     }
 243  
 
 244  
     public Sequence<T> setAsSequence(Sequence<? extends T> newValue) {
 245  
         Sequence<T> result;
 246  2646
         ensureNotBound();
 247  2645
         Sequence<T> oldValue = getRawValue();
 248  
         // Workaround for JFXC-885 -- reverted AGAIN
 249  
 //        if (!isInitialized() && !isEverValid() && Sequences.size(newValue) == 0 && Sequences.size(value) == 0) {
 250  
 //            result = Sequences.emptySequence(clazz);
 251  
 //            replaceValue(result);
 252  
 //        }
 253  
 //        else
 254  2645
         if (!Sequences.isEqual(oldValue, newValue) || !isInitialized() || !isEverValid()) {
 255  2447
             result = SequenceMutator.replaceSlice(oldValue, mutationListener, 0, Sequences.size(oldValue) - 1, newValue);
 256  
         }
 257  
         else
 258  198
             result = oldValue;
 259  2645
         return result;
 260  
     }
 261  
 
 262  
     public Sequence<T> setAsSequenceFromLiteral(final Sequence<? extends T> value) {
 263  77
         deferredLiteral = new DeferredInitializer() {
 264  
             public void apply() {
 265  76
                 setAsSequence(value);
 266  76
             }
 267  
         };
 268  77
         return Sequences.upcast(clazz, value);
 269  
     }
 270  
 
 271  
     @Override
 272  
     public T set(int position, T newValue) {
 273  2166
         ensureNotBound();
 274  2122
         SequenceMutator.set(getRawValue(), mutationListener, position, newValue);
 275  2122
         return newValue;
 276  
     }
 277  
 
 278  
     @Override
 279  
     public Sequence<? extends T> replaceSlice(int startPos, int endPos, Sequence<? extends T> newValues) {
 280  585
         ensureNotBound();
 281  576
         SequenceMutator.replaceSlice(getRawValue(), mutationListener, startPos, endPos, newValues);
 282  576
         return newValues;
 283  
     }
 284  
 
 285  
     @Override
 286  
     public void delete(int position) {
 287  475
         ensureNotBound();
 288  465
         SequenceMutator.delete(getRawValue(), mutationListener, position);
 289  465
     }
 290  
 
 291  
     @Override
 292  
     public void deleteSlice(int startPos, int endPos) {
 293  373
         replaceSlice(startPos, endPos, null);
 294  364
     }
 295  
 
 296  
     @Override
 297  
     public void delete(SequencePredicate<T> sequencePredicate) {
 298  532
         ensureNotBound();
 299  532
         SequenceMutator.delete(getRawValue(), mutationListener, sequencePredicate);
 300  532
     }
 301  
 
 302  
     @Override
 303  
     public void deleteAll() {
 304  70
         ensureNotBound();
 305  60
         setAsSequence(Sequences.emptySequence(clazz));
 306  60
     }
 307  
 
 308  
     @Override
 309  
     public void deleteValue(final T targetValue) {
 310  541
         ensureNotBound();
 311  531
         delete(new SequencePredicate<T>() {
 312  
             public boolean matches(Sequence<? extends T> sequence, int index, T value) {
 313  4305
                 if (value == null)
 314  0
                     return targetValue == null;
 315  4305
                 return value.equals(targetValue);
 316  
             }
 317  
         });
 318  531
     }
 319  
 
 320  
     @Override
 321  
     public void insert(T value) {
 322  1954
         ensureNotBound();
 323  1944
         SequenceMutator.insert(getRawValue(), mutationListener, value);
 324  1944
     }
 325  
 
 326  
     @Override
 327  
     public void insert(Sequence<? extends T> values) {
 328  6
         ensureNotBound();
 329  5
         SequenceMutator.insert(getRawValue(), mutationListener, values);
 330  5
     }
 331  
 
 332  
     public void insertFirst(T value) {
 333  21
         ensureNotBound();
 334  20
         SequenceMutator.insertFirst(getRawValue(), mutationListener, value);
 335  20
     }
 336  
 
 337  
     @Override
 338  
     public void insertFirst(Sequence<? extends T> values) {
 339  2
         ensureNotBound();
 340  1
         SequenceMutator.insertFirst(getRawValue(), mutationListener, values);
 341  1
     }
 342  
 
 343  
     @Override
 344  
     public void insertBefore(T value, int position) {
 345  33
         ensureNotBound();
 346  7
         SequenceMutator.insertBefore(getRawValue(), mutationListener, value, position);
 347  7
     }
 348  
 
 349  
     @Override
 350  
     public void insertBefore(T value, SequencePredicate<T> sequencePredicate) {
 351  1
         ensureNotBound();
 352  1
         SequenceMutator.insertBefore(getRawValue(), mutationListener, value, sequencePredicate);
 353  1
     }
 354  
 
 355  
     @Override
 356  
     public void insertBefore(Sequence<? extends T> values, int position) {
 357  204
         ensureNotBound();
 358  204
         SequenceMutator.insertBefore(getRawValue(), mutationListener, values, position);
 359  204
     }
 360  
 
 361  
     @Override
 362  
     public void insertBefore(Sequence<? extends T> values, SequencePredicate<T> sequencePredicate) {
 363  1
         ensureNotBound();
 364  1
         SequenceMutator.insertBefore(getRawValue(), mutationListener, values, sequencePredicate);
 365  1
     }
 366  
 
 367  
     @Override
 368  
     public void insertAfter(T value, int position) {
 369  34
         ensureNotBound();
 370  8
         SequenceMutator.insertAfter(this.getRawValue(), mutationListener, value, position);
 371  8
     }
 372  
 
 373  
     @Override
 374  
     public void insertAfter(T value, SequencePredicate<T> sequencePredicate) {
 375  1
         ensureNotBound();
 376  1
         SequenceMutator.insertAfter(getRawValue(), mutationListener, value, sequencePredicate);
 377  1
     }
 378  
 
 379  
     @Override
 380  
     public void insertAfter(Sequence<? extends T> values, int position) {
 381  204
         ensureNotBound();
 382  204
         SequenceMutator.insertAfter(getRawValue(), mutationListener, values, position);
 383  204
     }
 384  
 
 385  
     @Override
 386  
     public void insertAfter(Sequence<? extends T> values, SequencePredicate<T> sequencePredicate) {
 387  1
         ensureNotBound();
 388  1
         SequenceMutator.insertAfter(getRawValue(), mutationListener, values, sequencePredicate);
 389  1
     }
 390  
 }