/* This file is part of the db4o object database http://www.db4o.com Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com db4o is free software; you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. db4o is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/. */ package com.db4o.internal.query.result; import com.db4o.ext.*; import com.db4o.foundation.*; import com.db4o.internal.*; import com.db4o.internal.btree.*; import com.db4o.internal.classindex.*; import com.db4o.internal.query.processor.*; import com.db4o.query.*; import com.db4o.reflect.*; /** * @exclude */ public class IdListQueryResult extends AbstractQueryResult implements Visitor4, IntVisitor{ private Tree _candidates; private boolean _checkDuplicates; public IntArrayList _ids; public IdListQueryResult(Transaction trans, int initialSize){ super(trans); _ids = new IntArrayList(initialSize); } public IdListQueryResult(Transaction trans) { this(trans, 0); } public IntIterator4 iterateIDs() { return _ids.intIterator(); } public Object get(int index) { synchronized (lock()) { return activatedObject(getId(index)); } } public int getId(int index) { if (index < 0 || index >= size()) { throw new Db4oRecoverableException(new IndexOutOfBoundsException()); } return _ids.get(index); } public final void checkDuplicates(){ _checkDuplicates = true; } public void visit(Object a_tree) { InternalCandidate candidate = (InternalCandidate) a_tree; if (candidate.include()) { addKeyCheckDuplicates(candidate.id()); } } public void visit(int id){ addKeyCheckDuplicates(id); } public void addKeyCheckDuplicates(int a_key){ if(_checkDuplicates){ TreeInt newNode = new TreeInt(a_key); _candidates = Tree.add(_candidates, newNode); if(newNode._size == 0){ return; } } add(a_key); } @Override public void sort(final QueryComparator cmp) { Algorithms4.sort(new Sortable4() { public void swap(int leftIndex, int rightIndex) { _ids.swap(leftIndex, rightIndex); } public int size() { return IdListQueryResult.this.size(); } public int compare(int leftIndex, int rightIndex) { return cmp.compare(get(leftIndex), get(rightIndex)); } }); } @Override public void sortIds(final IntComparator cmp) { Algorithms4.sort(new Sortable4() { public void swap(int leftIndex, int rightIndex) { _ids.swap(leftIndex, rightIndex); } public int size() { return IdListQueryResult.this.size(); } public int compare(int leftIndex, int rightIndex) { return cmp.compare(_ids.get(leftIndex), _ids.get(rightIndex)); } }); } public void loadFromClassIndex(final ClassMetadata clazz) { final ClassIndexStrategy index = clazz.index(); if(index instanceof BTreeClassIndexStrategy){ BTree btree = ((BTreeClassIndexStrategy)index).btree(); _ids = new IntArrayList(btree.size(transaction())); } index.traverseIds(_transaction, new Visitor4() { public void visit(Object a_object) { add(((Integer)a_object).intValue()); } }); } public void loadFromQuery(QQuery query) { query.executeLocal(this); } public void loadFromClassIndexes(ClassMetadataIterator iter){ // duplicates because of inheritance hierarchies final ByRef<Tree> duplicates = new ByRef<Tree>(); while (iter.moveNext()) { final ClassMetadata classMetadata = iter.currentClass(); if (classMetadata.getName() != null) { ReflectClass claxx = classMetadata.classReflector(); if (claxx == null || !(stream()._handlers.ICLASS_INTERNAL.isAssignableFrom(claxx))) { final ClassIndexStrategy index = classMetadata.index(); index.traverseIds(_transaction, new Visitor4() { public void visit(Object obj) { int id = ((Integer)obj).intValue(); TreeInt newNode = new TreeInt(id); duplicates.value = Tree.add(duplicates.value, newNode); if (newNode.size() != 0) { add(id); } } }); } } } } public void loadFromIdReader(Iterator4 ids) { while (ids.moveNext()) { add((Integer)ids.current()); } } public void add(int id){ _ids.add(id); } public int indexOf(int id) { return _ids.indexOf(id); } public int size() { return _ids.size(); } }