Coverage Report - com.sun.javafx.runtime.sequence.BoundNumberRangeSequence
 
Classes in this File Line Coverage Branch Coverage Complexity
BoundNumberRangeSequence
92%
33/36
82%
18/22
0
BoundNumberRangeSequence$1
100%
17/17
72%
13/18
0
BoundNumberRangeSequence$2
100%
13/13
67%
8/12
0
BoundNumberRangeSequence$3
100%
7/7
25%
1/4
0
 
 1  
 /*
 2  
  * Copyright 2008 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  
 
 26  
 package com.sun.javafx.runtime.sequence;
 27  
 
 28  
 import com.sun.javafx.runtime.location.*;
 29  
 
 30  
 /**
 31  
  * BoundNumberRangeSequence
 32  
  *
 33  
  * @author Zhiqun Chen
 34  
  */
 35  203
 public class BoundNumberRangeSequence extends AbstractBoundSequence<Double> implements SequenceLocation<Double> {
 36  
 
 37  
     private final DoubleLocation lowerLoc, upperLoc, stepLoc;
 38  
     private final boolean exclusive;
 39  
     private double lower, upper, step;
 40  
     private int size;
 41  
 
 42  
     public BoundNumberRangeSequence(DoubleLocation lowerLoc, DoubleLocation upperLoc) {
 43  1
         this(lowerLoc, upperLoc, DoubleConstant.make(1), false);
 44  1
     }
 45  
 
 46  
     public BoundNumberRangeSequence(DoubleLocation lowerLoc, DoubleLocation upperLoc, DoubleLocation stepLoc) {
 47  0
         this(lowerLoc, upperLoc, stepLoc, false);
 48  0
     }
 49  
 
 50  
     public BoundNumberRangeSequence(DoubleLocation lowerLoc, DoubleLocation upperLoc, boolean exclusive) {
 51  1
         this(lowerLoc, upperLoc, DoubleConstant.make(1), exclusive);
 52  1
     }
 53  
 
 54  
     public BoundNumberRangeSequence(DoubleLocation lowerLoc, DoubleLocation upperLoc, DoubleLocation stepLoc, boolean exclusive) {
 55  3
         super(Double.class);
 56  3
         this.lowerLoc = lowerLoc;
 57  3
         this.upperLoc = upperLoc;
 58  3
         this.stepLoc = stepLoc;
 59  3
         this.exclusive = exclusive;
 60  3
         setInitialValue(computeValue());
 61  3
         addTriggers();
 62  3
     }
 63  
 
 64  
     private Sequence<Double> computeValue() {
 65  3
         computeBounds(lowerLoc.get(), upperLoc.get(), stepLoc.get());
 66  3
         return computeFull(lower, upper, step);
 67  
     }
 68  
 
 69  
     private Sequence<Double> computeFull(double lower, double upper, double step) {
 70  
     
 71  17
         return exclusive ? Sequences.rangeExclusive(lower, upper, step) : Sequences.range(lower, upper, step);
 72  
     }
 73  
 
 74  
     private void computeBounds(double newLower, double newUpper, double newStep) {       
 75  25
         lower = newLower;
 76  25
         upper = newUpper;
 77  25
         step = newStep;
 78  
 
 79  
         // Not all floating point numbers can be exactly represented as a binary (base 2) decimal number (e.g lower = 0.1).
 80  
         // The size of the sequence from the following calculation could be off by 1. However, such cases are very rare.
 81  25
         if (lower == upper) {
 82  1
             size = exclusive ? 0 : 1;
 83  
         }
 84  
         else {
 85  24
             long size = Math.max(0, ((long)((upper - lower) / step)) + 1);
 86  
 
 87  24
             if (exclusive) {
 88  13
                 boolean tooBig = (step > 0)
 89  
                         ? (lower + (size - 1) * step >= upper)
 90  
                         : (lower + (size - 1) * step <= upper);
 91  13
                 if (tooBig && size > 0)
 92  6
                     --size;
 93  
             }
 94  
             
 95  24
             if (size > Integer.MAX_VALUE || size < 0)
 96  0
                 throw new IllegalArgumentException("Range sequence too big");
 97  
             else
 98  24
                 this.size = (int) size;
 99  
         }
 100  25
     }
 101  
 
 102  
     private void addTriggers() {
 103  3
         lowerLoc.addChangeListener(new DoubleChangeListener() {
 104  
             public void onChange(double oldValue, double newValue) {
 105  
                 
 106  11
                 assert oldValue != newValue;
 107  11
                 int oldSize = size;
 108  11
                 computeBounds(newValue, upper, step);
 109  
                 Sequence<Double> newElements;
 110  
 
 111  11
                 if (oldSize == 0) {
 112  2
                     updateSlice(0, -1, computeFull(lower, upper, step));
 113  
                 }
 114  9
                 else if (oldSize < size) {
 115  
 
 116  3
                     if (((newValue - oldValue) % step) == 0) {
 117  1
                         updateSlice(0, -1, Sequences.rangeExclusive(lower, oldValue, step));
 118  
                     }
 119  
                     else {
 120  2
                         newElements = computeFull(lower, upper, step);
 121  2
                         updateSlice(0, newElements.isEmpty() ? 0 : (size - 1), newElements, newElements);
 122  
                     }
 123  
                 }
 124  6
                 else if (oldSize >= size) {
 125  6
                     if (((newValue - oldValue) % step) == 0) {
 126  
                         
 127  2
                         updateSlice(0, oldSize - size - 1, Sequences.emptySequence(Double.class));
 128  
                     }
 129  
                     else {
 130  4
                         newElements = computeFull(lower, upper, step);
 131  4
                         updateSlice(0, newElements.isEmpty() ? 0 : (size - 1), newElements, newElements);
 132  
                     }
 133  
                 }
 134  11
             }
 135  
         });
 136  3
         upperLoc.addChangeListener(new DoubleChangeListener() {
 137  
             public void onChange(double oldValue, double newValue) {
 138  
                 
 139  9
                 assert oldValue != newValue;         
 140  9
                 int oldSize = size;
 141  9
                 computeBounds(lower, newValue, step);
 142  
 
 143  9
                 if (size == oldSize) {
 144  1
                     return;
 145  
                 }
 146  8
                 else if (oldSize == 0) {
 147  1
                     updateSlice(0, -1, computeFull(lower, upper, step));
 148  
                 }
 149  7
                 else if (oldSize < size) {
 150  3
                    updateSlice(oldSize, oldSize - 1, computeFull(lower+oldSize*step, upper, step));
 151  
                 }
 152  4
                 else if (oldSize > size) {
 153  4
                     updateSlice(size, oldSize - 1, Sequences.emptySequence(Double.class));
 154  
                 }
 155  8
             }
 156  
         });
 157  
 
 158  3
         stepLoc.addChangeListener(new DoubleChangeListener() {
 159  
             public void onChange(double oldValue, double newValue) {
 160  
                 
 161  2
                 assert oldValue != newValue;                                  
 162  2
                 int oldSize = size;
 163  2
                 computeBounds(lower, upper, newValue);
 164  
 
 165  2
                 Sequence<Double> newSeq = computeFull(lower, upper, step);
 166  2
                 updateSlice(0, oldSize - 1, newSeq, newSeq);
 167  2
             }
 168  
         });
 169  3
     }
 170  
 }