Coverage Report - com.sun.javafx.runtime.sequence.SimpleBoundComprehension
 
Classes in this File Line Coverage Branch Coverage Complexity
SimpleBoundComprehension
88%
14/16
100%
2/2
0
SimpleBoundComprehension$1
100%
17/17
100%
16/16
0
 
 1  
 package com.sun.javafx.runtime.sequence;
 2  
 
 3  
 import com.sun.javafx.runtime.Util;
 4  
 import com.sun.javafx.runtime.location.SequenceLocation;
 5  
 import com.sun.javafx.runtime.location.SequenceChangeListener;
 6  
 
 7  
 /**
 8  
  * SimpleBoundComprehension -- special case of a bound list comprehension with one dimension, no where clause
 9  
  * and where each iteration produces exactly one result
 10  
  *
 11  
  * @author Brian Goetz
 12  
  */
 13  32
 public abstract class SimpleBoundComprehension<T, V> extends AbstractBoundSequence<V> implements SequenceLocation<V> {
 14  
     private final SequenceLocation<T> sequenceLocation;
 15  
     private final boolean dependsOnIndex;
 16  
 
 17  
     /**
 18  
      * Create a bound list comprehension that meets the following criteria: no where clause, one dimension, and each
 19  
      * iteration contributes exactly one value.  For each input element, the computeElement() method will be called to
 20  
      * calculate the corresponding output element.
 21  
      *
 22  
      * @param clazz The Class of the resulting sequence element type
 23  
      * @param sequenceLocation The input sequence
 24  
      * @param dependsOnIndex Whether or not the computeElement$ makes use of the indexof operator
 25  
      */
 26  
     public SimpleBoundComprehension(Class<V> clazz,
 27  
                                     SequenceLocation<T> sequenceLocation,
 28  
                                     boolean dependsOnIndex) {
 29  5
         super(clazz);
 30  5
         this.sequenceLocation = sequenceLocation;
 31  5
         this.dependsOnIndex = dependsOnIndex;
 32  5
         setInitialValue(computeValue());
 33  5
         addTriggers();
 34  5
     }
 35  
 
 36  
     public SimpleBoundComprehension(Class<V> clazz, SequenceLocation<T> sequenceLocation) {
 37  0
         this(clazz, sequenceLocation, false);
 38  0
     }
 39  
 
 40  
     protected abstract V computeElement$(T element, int index);
 41  
 
 42  
     private Sequence<V> computeValue() {
 43  5
         Sequence<T> sequence = sequenceLocation.getAsSequence();
 44  5
         V[] intermediateResults = Util.<V>newObjectArray(sequence.size());
 45  20
         for (int i = 0; i < intermediateResults.length; i++)
 46  15
             intermediateResults[i] = computeElement$(sequence.get(i), i);
 47  5
         return Sequences.make(getClazz(), intermediateResults);
 48  
     }
 49  
 
 50  
     private void addTriggers() {
 51  5
         sequenceLocation.addChangeListener(new SequenceChangeListener<T>() {
 52  
             public void onChange(int startPos, int endPos, Sequence<? extends T> newElements, Sequence<T> oldValue, Sequence<T> newValue) {
 53  
                 // IF the closure depends on index, then an insertion or deletion causes recomputation of the whole
 54  
                 // trailing segment of the comprehension, so not only do we recompute the affected segment, but also
 55  
                 // the whole rest of the sequence too.
 56  
 
 57  18
                 int directlyAffectedSize = Sequences.size(newElements);
 58  18
                 int elementsAdded = directlyAffectedSize - (endPos - startPos + 1);
 59  18
                 boolean updateTrailingElements = dependsOnIndex
 60  
                         && (elementsAdded != 0)
 61  
                         && (endPos + 1 < Sequences.size(oldValue));
 62  18
                 int indirectlyAffectedStart=0, indirectlyAffectedEnd=0, indirectlyAffectedSize=0;
 63  18
                 if (updateTrailingElements) {
 64  3
                     indirectlyAffectedStart = endPos + 1;
 65  3
                     indirectlyAffectedEnd = oldValue.size() - 1;
 66  3
                     indirectlyAffectedSize = indirectlyAffectedEnd - indirectlyAffectedStart + 1;
 67  
                 }
 68  18
                 V[] ourNewElements = Util.<V>newObjectArray(directlyAffectedSize + indirectlyAffectedSize);
 69  32
                 for (int i = 0; i < directlyAffectedSize; i++)
 70  14
                     ourNewElements[i] = computeElement$(newElements.get(i), dependsOnIndex ? startPos + i : -1);
 71  26
                 for (int i = 0; i < indirectlyAffectedSize; i++)
 72  8
                     ourNewElements[directlyAffectedSize + i]
 73  
                             = computeElement$(oldValue.get(indirectlyAffectedStart + i), indirectlyAffectedStart + i + elementsAdded);
 74  
 
 75  18
                 Sequence<V> vSequence = Sequences.make(getClazz(), ourNewElements);
 76  18
                 updateSlice(startPos, updateTrailingElements ? indirectlyAffectedEnd : endPos, vSequence);
 77  18
             }
 78  
         });
 79  5
     }
 80  
 }