Coverage Report - com.sun.javafx.runtime.sequence.BoundCompositeSequence
 
Classes in this File Line Coverage Branch Coverage Complexity
BoundCompositeSequence
98%
50/51
94%
17/18
0
BoundCompositeSequence$1
N/A
N/A
0
BoundCompositeSequence$IndexListener
N/A
N/A
0
BoundCompositeSequence$Info
100%
10/10
N/A
0
BoundCompositeSequence$MyListener
100%
15/15
100%
4/4
0
 
 1  
 /*
 2  
  * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
 3  
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 4  
  *
 5  
  * This code is free software; you can redistribute it and/or modify it
 6  
  * under the terms of the GNU General Public License version 2 only, as
 7  
  * published by the Free Software Foundation.  Sun designates this
 8  
  * particular file as subject to the "Classpath" exception as provided
 9  
  * by Sun in the LICENSE file that accompanied this code.
 10  
  *
 11  
  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  
  * version 2 for more details (a copy is included in the LICENSE file that
 15  
  * accompanied this code).
 16  
  *
 17  
  * You should have received a copy of the GNU General Public License version
 18  
  * 2 along with this work; if not, write to the Free Software Foundation,
 19  
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  
  *
 21  
  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 22  
  * CA 95054 USA or visit www.sun.com if you need additional information or
 23  
  * have any questions.
 24  
  */
 25  
 package com.sun.javafx.runtime.sequence;
 26  
 
 27  
 import com.sun.javafx.runtime.Util;
 28  
 import com.sun.javafx.runtime.location.SequenceLocation;
 29  
 import com.sun.javafx.runtime.location.SequenceChangeListener;
 30  
 
 31  
 /**
 32  
  * BoundCompositeSequence
 33  
  *
 34  
  * @author Brian Goetz
 35  
  */
 36  27526
 public class BoundCompositeSequence<T> extends AbstractBoundSequence<T> implements SequenceLocation<T> {
 37  
     private Info<T>[] infos;
 38  
 
 39  16612
     static class Info<T> {
 40  
         private final SequenceLocation<? extends T> location;
 41  
         private int startPosition, size;
 42  
         private IndexListener listener;
 43  
 
 44  726
         public Info(SequenceLocation<? extends T> location) {
 45  726
             this.location = location;
 46  726
         }
 47  
 
 48  
         public void addListener(IndexListener listener) {
 49  726
             this.listener = listener;
 50  726
             location.addChangeListener(this.listener);
 51  726
         }
 52  
 
 53  
         public void removeListener() {
 54  229
             location.removeChangeListener(this.listener);
 55  229
             this.listener = null;
 56  229
         }
 57  
     }
 58  
 
 59  
     public BoundCompositeSequence(Class<T> clazz, SequenceLocation<? extends T>... locations) {
 60  46
         this(clazz, locations, locations.length);
 61  46
     }
 62  
 
 63  
     public BoundCompositeSequence(Class<T> clazz, SequenceLocation<? extends T>[] locations, int size) {
 64  84
         super(clazz);
 65  84
         this.infos = newInfoArray(size);
 66  737
         for (int i = 0; i < size; i++) {
 67  653
             infos[i] = new Info<T>(locations[i]);
 68  653
             Class eClass = locations[i].getAsSequence().getElementType();
 69  653
             if (!clazz.isAssignableFrom(eClass))
 70  0
                 throw new ClassCastException("cannot cast " + eClass.getName()
 71  
                         + " segment to " + clazz.getName() + " sequence");
 72  
         }
 73  
 
 74  84
         setInitialValue(computeValue());
 75  84
         addTriggers();
 76  84
     }
 77  
 
 78  
     @SuppressWarnings("unchecked")
 79  
     private Info<T>[] newInfoArray(int len) {
 80  139
         return (Info<T>[]) new Info[len];
 81  
     }
 82  
 
 83  
     private Sequence<T> computeValue() {
 84  84
         Sequence<? extends T>[] sequences = Util.newSequenceArray(infos.length);
 85  737
         for (int i = 0, offset = 0; i < infos.length; i++) {
 86  653
             sequences[i] = infos[i].location.getAsSequence();
 87  653
             infos[i].startPosition = offset;
 88  653
             infos[i].size = sequences[i].size();
 89  653
             offset += sequences[i].size();
 90  
         }
 91  84
         return Sequences.concatenate(getClazz(), sequences);
 92  
     }
 93  
 
 94  
     private void addTriggers() {
 95  737
         for (int i = 0; i < infos.length; i++)
 96  653
             infos[i].addListener(new MyListener(i));
 97  84
     }
 98  
 
 99  
     public void replaceSlice(int startPos, int endPos, SequenceLocation<? extends T>[] newValues) {
 100  55
         Info<T>[] newInfos = newInfoArray(newValues.length);
 101  55
         Sequence<? extends T>[] sequences = Util.newSequenceArray(newValues.length);
 102  
         int affectedStart, affectedEnd;
 103  55
         if (startPos < infos.length) {
 104  39
             affectedStart = infos[startPos].startPosition;
 105  39
             affectedEnd = (endPos >= 0) ? (infos[endPos].startPosition + infos[endPos].size - 1) : affectedStart - 1;
 106  
         }
 107  
         else {
 108  16
             affectedStart = getRawValue().size();
 109  16
             affectedEnd = affectedStart - 1;
 110  
         }
 111  55
         int offset = affectedStart;
 112  128
         for (int i = 0; i < newInfos.length; i++) {
 113  73
             newInfos[i] = new Info<T>(newValues[i]);
 114  73
             sequences[i] = newInfos[i].location.getAsSequence();
 115  73
             newInfos[i].startPosition = offset;
 116  73
             newInfos[i].size = sequences[i].size();
 117  73
             offset += sequences[i].size();
 118  73
             newInfos[i].addListener(new MyListener(i + startPos));
 119  
         }
 120  55
         Sequence<T> newSlice = Sequences.concatenate(getClazz(), sequences);
 121  55
         int deltaElements = newSlice.size() - (affectedEnd - affectedStart + 1);
 122  55
         int deltaLocations = newValues.length - (endPos - startPos + 1);
 123  119
         for (int i = endPos + 1; i < infos.length; i++) {
 124  64
             infos[i].startPosition += deltaElements;
 125  64
             infos[i].listener.setIndex(i + deltaLocations);
 126  
         }
 127  284
         for (int i = startPos; i <= endPos; i++)
 128  229
             infos[i].removeListener();
 129  55
         infos = Util.replaceSlice(infos, startPos, endPos, newInfos);
 130  55
         updateSlice(affectedStart, affectedEnd, newSlice);
 131  55
     }
 132  
 
 133  
     public void validate() {
 134  
         // Uncomment for debugging
 135  
 //        int offset = 0;
 136  
 //        for (int i=0; i<infos.length; i++) {
 137  
 //            Info info = infos[i];
 138  
 //            Assert.assertEquals(offset, info.startPosition);
 139  
 //            Assert.assertTrue(info.startPosition >= 0);
 140  
 //            Assert.assertTrue(info.size >= 0);
 141  
 //            Assert.assertEquals(info.size, info.location.getAsSequence().size());
 142  
 //            Assert.assertEquals(value().getSlice(info.startPosition, info.startPosition + info.size - 1), info.location.getAsSequence());
 143  
 //            Assert.assertEquals(((MyListener) info.listener).index, i);
 144  
 //            offset += info.size;
 145  
 //        }
 146  
 //        Assert.assertEquals(offset, value().size());
 147  16
     }
 148  
 
 149  
     private interface IndexListener<T> extends SequenceChangeListener<T> {
 150  
         public void setIndex(int index);
 151  
     }
 152  
 
 153  726
     private class MyListener<V extends T> implements IndexListener<V> {
 154  
         private int index;
 155  
 
 156  726
         private MyListener(int index) {
 157  726
             this.index = index;
 158  726
         }
 159  
 
 160  
         public void setIndex(int index) {
 161  64
             this.index = index;
 162  64
         }
 163  
 
 164  
         public void onChange(int startPos, int endPos, Sequence<? extends V> newElements,
 165  
                               Sequence<V> oldValue, Sequence<V> newValue) {
 166  391
             int actualStart = infos[index].startPosition + startPos;
 167  391
             int actualEnd = infos[index].startPosition + endPos;
 168  391
             infos[index].size = newValue.size();
 169  391
             int delta = Sequences.size(newElements) - (endPos - startPos + 1);
 170  391
             if (delta != 0)
 171  13329
                 for (int i = index + 1; i < infos.length; i++)
 172  13024
                     infos[i].startPosition += delta;
 173  391
             updateSlice(actualStart, actualEnd, newElements);
 174  391
         }
 175  
     }
 176  
 }