/** * GeDBIT.index.Cursor 2006.05.09 * * Copyright Information: * * Change Log: * 2006.05.09: Copied from the original GeDBIT package, by Rui Mao */ package GeDBIT.index; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import GeDBIT.dist.Metric; import GeDBIT.type.DoubleIndexObjectPair; import GeDBIT.type.IndexObject; import GeDBIT.util.ObjectIOManager; /** * Implements an {@link Iterator}, iterating on the results set. * * @author Rui Mao, Willard * @version 2006.05.31 */ @SuppressWarnings("rawtypes") public abstract class Cursor implements Iterator { ObjectIOManager[] oioms; ObjectIOManager oiom; Metric metric; long rootAddress; LinkedList<DoubleIndexObjectPair> result; protected Cursor(ObjectIOManager oiom, Metric metric, long rootAddress) { this.oiom = oiom; this.oioms = null; this.metric = metric; this.rootAddress = rootAddress; result = new LinkedList<DoubleIndexObjectPair>(); } protected Cursor(ObjectIOManager[] oioms, Metric metric, long rootAddress) { this.oiom = null; this.oioms = oioms; this.metric = metric; this.rootAddress = rootAddress; result = new LinkedList<DoubleIndexObjectPair>(); } public boolean hasNext() { if (result.size() > 0) return true; else { continueSearch(); return (result.size() > 0); } } public DoubleIndexObjectPair next() { if (result.size() > 0) return expandNext(); else { continueSearch(); if (result.size() > 0) return expandNext(); else throw new java.util.NoSuchElementException( "The search is already done!"); } } public DoubleIndexObjectPair expandNext() { DoubleIndexObjectPair dioPair = result.remove(); IndexObject iObject = dioPair.getObject(); if (iObject instanceof IndexObject) { double _double = dioPair.getDouble(); IndexObject[] cioArray = ((IndexObject) dioPair.getObject()) .expand(); // System.out.println("length=" + cioArray.length); for (int i = 0; i < cioArray.length; i++) { result.addFirst(new DoubleIndexObjectPair(_double, cioArray[i])); } return result.remove(); } return dioPair; } public void remove() { throw new UnsupportedOperationException(); } abstract void continueSearch(); abstract void searchResults(); /** * Return a list of all the data points in the subtree rooted at the address * * @param oiom * @param address * @return each data point is an IndexObject, consist of a row ID and an * index key */ static List<IndexObject> getAllPoints(ObjectIOManager oiom, long address) { IndexNode node = null; try { node = (IndexNode) oiom.readObject(address); } catch (Exception e) { e.printStackTrace(); } LinkedList<IndexObject> result = new LinkedList<IndexObject>(); for (int pivot = 0; pivot < node.numPivots(); pivot++) { result.add(node.getPivot(pivot)); } if (node instanceof InternalNode) { InternalNode iNode = (InternalNode) node; for (int child = 0; child < iNode.numChildren(); child++) result.addAll(getAllPoints(oiom, iNode.getChildAddress(child))); } else if (node instanceof LeafNode) { LeafNode lNode = (LeafNode) node; for (int child = 0; child < lNode.numChildren(); child++) { result.add(lNode.getChild(child)); } } else { throw new UnsupportedOperationException("Node type: " + node.getClass() + " is not supported!"); } // decompress LinkedList<IndexObject> expandedList = new LinkedList<IndexObject>(); Iterator<IndexObject> p = result.iterator(); while (p.hasNext()) { IndexObject o = p.next(); if (o instanceof IndexObject) { IndexObject[] expanded = ((IndexObject) o).expand(); for (IndexObject temp : expanded) expandedList.addFirst(temp); } else expandedList.addFirst(o); } return expandedList; } /** * Return the number of stored distance values in the subtree rooted at the * address * * @param oiom * @param address * @return each data point is an IndexObject, consist of a row ID and an * index key */ static int getStoredDistanceNumber(ObjectIOManager oiom, long address) { IndexNode node = null; try { node = (IndexNode) oiom.readObject(address); } catch (Exception e) { e.printStackTrace(); } int result = 0; if (node instanceof InternalNode) { VPInternalNode iNode = (VPInternalNode) node; result = iNode.numChildren() * iNode.numPivots() * 2; for (int child = 0; child < iNode.numChildren(); child++) result += getStoredDistanceNumber(oiom, iNode.getChildAddress(child)); } else if (node instanceof VPLeafNode) { VPLeafNode lNode = (VPLeafNode) node; // System.out.println(lNode.size()); if (lNode.numChildren() > 0) result = lNode.numChildren() * (lNode.getDataPointPathDistance(0).length + lNode .getDataPointPivotDistance(0).length); else result = 0; } else { throw new UnsupportedOperationException("Node type: " + node.getClass() + " is not supported!"); } return result; } static int getStoredDistanceNumbers(ObjectIOManager[] oioms, long rootAddress, int subtree) { IndexNode node = null; try { node = (IndexNode) oioms[0].readObject(rootAddress); } catch (Exception e) { e.printStackTrace(); } int result = 0; if (node instanceof InternalNode) { VPInternalNode iNode = (VPInternalNode) node; result = iNode.numChildren() * iNode.numPivots() * 2; for (int child = 0; child < iNode.numChildren(); child++) result += getStoredDistanceNumber(oioms[child % subtree + 1], iNode.getChildAddress(child)); } else if (node instanceof VPLeafNode) { VPLeafNode lNode = (VPLeafNode) node; if (lNode.numChildren() > 0) result = lNode.numChildren() * (lNode.getDataPointPathDistance(0).length + lNode .getDataPointPivotDistance(0).length); else result = 0; } else { throw new UnsupportedOperationException("Node type: " + node.getClass() + " is not supported!"); } return result; } /** * Return the total number of nodes in the subtree rooted at the address * * @param oiom * @param address * @return */ static int getNodeNumber(ObjectIOManager oiom, long address) { int result = 1; IndexNode node = null; try { node = (IndexNode) oiom.readObject(address); } catch (Exception e) { e.printStackTrace(); } if (node instanceof InternalNode) { InternalNode iNode = (InternalNode) node; for (int child = 0; child < iNode.numChildren(); child++) result += getNodeNumber(oiom, iNode.getChildAddress(child)); } return result; } /** * Return the total number of internal index node in the subtree rooted at * the address * * @param oiom * @param address * @return */ static int getInternalNodeNumber(ObjectIOManager oiom, long address) { int result = 0; IndexNode node = null; try { node = (IndexNode) oiom.readObject(address); } catch (Exception e) { e.printStackTrace(); } if (node instanceof InternalNode) { result++; InternalNode iNode = (InternalNode) node; for (int child = 0; child < iNode.numChildren(); child++) result += getInternalNodeNumber(oiom, iNode.getChildAddress(child)); } return result; } /** * Return the total number of leaf index node in the subtree rooted at the * address * * @param oiom * @param address * @return */ static int getLeafNodeNumber(ObjectIOManager oiom, long address) { int result = 0; IndexNode node = null; try { node = (IndexNode) oiom.readObject(address); } catch (Exception e) { e.printStackTrace(); } if (node instanceof InternalNode) { InternalNode iNode = (InternalNode) node; for (int child = 0; child < iNode.numChildren(); child++) result += getLeafNodeNumber(oiom, iNode.getChildAddress(child)); } else if (node instanceof LeafNode) { return 1; } else { throw new UnsupportedOperationException("Node type: " + node.getClass() + " is not supported!"); } return result; } abstract protected void visit(QueryTask t); protected class QueryTask { } }