package net.sourceforge.squirrel_sql.client.session.mainpanel.overview.datascale; import net.sourceforge.squirrel_sql.fw.datasetviewer.ColumnDisplayDefinition; import java.util.Arrays; import java.util.HashSet; import java.util.List; public class ScaleFactory { /** * 2^(DEFAULT_CALL_DEPTH-1) is the maximum number of intervals that will be generated. */ public static final int DEFAULT_CALL_DEPTH = 4; private IndexedColumn _indexedColumn; private int _callDepth; public ScaleFactory(List<Object[]> rows, int colIx, ColumnDisplayDefinition colDef, int callDepth) { _indexedColumn = IndexedColumnFactory.create(rows, colIx, colDef); _callDepth = callDepth; } public DataScale createScale(DataScaleListener dataScaleListener) { Object min = _indexedColumn.getMin(); Object max = _indexedColumn.getMax(); DataScale ret = new DataScale(_indexedColumn.getColumnName(), dataScaleListener, _indexedColumn.getColumnIndex(), _indexedColumn.getColumnDisplayDefinition()); if(0 == _indexedColumn.compareObjects(min, max)) { ret.addInterval(new Interval(_indexedColumn, 0, _indexedColumn.size() - 1, min, max)); return ret; } Object[] borders = createBorders(min, max).toArray(new Object[0]); sortBorders(borders); Integer lastIx = null; Object lastBorder = min; for (Object border : borders) { int bsRet = _indexedColumn.binarySearch(border); int ip; if( 0 > bsRet) { ip = (- bsRet - 1); } else { //ip = _indexedColumn.getFirstIndexOfVal(bsRet); ip = _indexedColumn.getLastIndexOfVal(bsRet)+1; } if(null == lastIx) { //ret.addInterval(new Interval(_indexedColumn, 0, Math.max(0, ip-1), lastBorder, border)); // int firstIx = 0; // int endIx = Math.max(0, ip - 1); // if (1 == endIx - firstIx) // { // ret.addInterval(new Interval(_indexedColumn, firstIx, firstIx, _indexedColumn.get(firstIx), _indexedColumn.get(firstIx))); // ret.addInterval(new Interval(_indexedColumn, endIx, endIx, _indexedColumn.get(endIx), _indexedColumn.get(endIx))); // } // else // { // ret.addInterval(new Interval(_indexedColumn, 0, Math.max(0, ip-1), lastBorder, border)); // } int firstIx = 0; int endIx = Math.max(0, ip - 1); if (1 == createBorders(_indexedColumn.get(firstIx), _indexedColumn.get(endIx)).size()) { // This makes sure that the first interval can always drilled down to one single value. // Without this it might happen that the first interval contains two different values and cannot be further drilled down. int lastIndexOfVal = _indexedColumn.getLastIndexOfVal(firstIx); ret.addInterval(new Interval(_indexedColumn, firstIx, lastIndexOfVal, _indexedColumn.get(firstIx), _indexedColumn.get(firstIx))); if (lastIndexOfVal+1 <= endIx) { ret.addInterval(new Interval(_indexedColumn, lastIndexOfVal+1, endIx, _indexedColumn.get(endIx), _indexedColumn.get(endIx))); } } else { ret.addInterval(new Interval(_indexedColumn, 0, Math.max(0, ip-1), lastBorder, border)); } lastIx = ip; } else if(ip > lastIx) { ret.addInterval(new Interval(_indexedColumn, lastIx, Math.max(0, ip-1), lastBorder, border)); lastIx = ip; } lastBorder = border; } if (_indexedColumn.size() > lastIx) { ret.addInterval(new Interval(_indexedColumn, lastIx, _indexedColumn.size() - 1, lastBorder, max)); } // System.out.println("sumWeights = " + ret.getSumWeights()); // System.out.println("sumLens = " + ret.getSumLens()); return ret; } private void sortBorders(Object[] borders) { NoIx[] noIxes = new NoIx[borders.length]; for (int i = 0; i < noIxes.length; i++) { noIxes[i] = new NoIx(borders[i]); } Arrays.sort(noIxes, _indexedColumn.getComparator()); for (int i = 0; i < noIxes.length; i++) { borders[i] = noIxes[i].get(); } } private HashSet<Object> createBorders(Object min, Object max) { HashSet<Object> ret = new HashSet<Object>(); int callDepth[] = new int[]{0}; divide(min, max, ret, callDepth); // if(0 == ret.size()) // { // // There was no value that fits between min and max. // // Now calling methods expect us to return min as a border. // ret.add(min); // } //ret.add(min); ret.add(max); return ret; } private void divide(Object min, Object max, HashSet<Object> ret, int[] callDepth) { ++callDepth[0]; if(_callDepth == callDepth[0]) { return; } Object mid = _indexedColumn.getCalculator().getMid(min, max); if (0 != _indexedColumn.compareObjects(min, mid)) { ret.add(mid); } divide(min, mid, ret, new int[]{callDepth[0]}); divide(mid, max, ret, new int[]{callDepth[0]}); --callDepth[0]; } }