/* 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.processor;
import com.db4o.*;
import com.db4o.foundation.*;
import com.db4o.internal.*;
import com.db4o.internal.btree.*;
import com.db4o.internal.classindex.*;
import com.db4o.query.*;
import com.db4o.reflect.*;
/**
*
* Class constraint on queries
*
* @exclude
*/
public class QConClass extends QConObject{
private transient ReflectClass _claxx;
@decaf.Public
private String _className;
@decaf.Public
private boolean i_equal;
public QConClass(){
// C/S
}
QConClass(Transaction trans, QCon parent, QField field, ReflectClass claxx){
super(trans, parent, field, null);
if(claxx != null){
ObjectContainerBase container = trans.container();
_classMetadata = container.classMetadataForReflectClass(claxx);
if(_classMetadata == null){
// could be an aliased class, try to resolve.
String className = claxx.getName();
String aliasRunTimeName = container.config().resolveAliasStoredName(className);
if(! className.equals(aliasRunTimeName)){
_classMetadata = container.classMetadataForName(aliasRunTimeName);
}
}
if(claxx.equals(container._handlers.ICLASS_OBJECT)){
_classMetadata = (ClassMetadata)_classMetadata.typeHandler();
}
}
_claxx = claxx;
}
QConClass(Transaction trans, ReflectClass claxx){
this(trans ,null, null, claxx);
}
public String getClassName() {
return _claxx == null ? null : _claxx.getName();
}
public boolean canBeIndexLeaf(){
return false;
}
boolean evaluate(InternalCandidate candidate){
boolean result = true;
QCandidates qCandidates = candidate.candidates();
if(qCandidates.isTopLevel() && qCandidates.wasLoadedFromClassFieldIndex()) {
if(_classMetadata.getAncestor() != null){
BTreeClassIndexStrategy index = (BTreeClassIndexStrategy) _classMetadata.index();
if(index == null){
return i_evaluator.not(true);
}
BTree btree = index.btree();
Object searchResult = btree.search(candidate.transaction(), candidate.id());
result = searchResult != null;
}
} else {
ReflectClass claxx = candidate.classMetadata().classReflector();
if(claxx == null){
result = false;
}else{
result = i_equal ? _claxx.equals(claxx) : _claxx.isAssignableFrom(claxx);
}
}
return i_evaluator.not(result);
}
void evaluateSelf() {
if(i_candidates.wasLoadedFromClassIndex()){
if(i_evaluator.isDefault()){
if(! hasJoins()){
if(_classMetadata != null && i_candidates._classMetadata != null){
if(_classMetadata.getHigherHierarchy(i_candidates._classMetadata) == _classMetadata){
return;
}
}
}
}
}
if(i_candidates.wasLoadedFromClassFieldIndex()){
if(i_candidates.isTopLevel()) {
if(i_evaluator.isDefault()){
if(! hasJoins()){
if(canResolveByFieldIndex()){
return;
}
}
}
}
}
i_candidates.filter(this);
}
@Override
protected boolean canResolveByFieldIndex() {
return _classMetadata != null && _classMetadata.getAncestor() == null;
}
public Constraint equal (){
synchronized(streamLock()){
i_equal = true;
return this;
}
}
boolean isNullConstraint() {
return false;
}
String logObject() {
if (Debug4.queries) {
if(_claxx != null){
return _claxx.toString();
}
}
return "";
}
void marshall() {
super.marshall();
if(_claxx!=null) {
_className = container().config().resolveAliasRuntimeName(_claxx.getName());
}
}
public String toString(){
String str = "QConClass ";
if(_claxx != null){
str += _claxx.getName() + " ";
}
return str + super.toString();
}
void unmarshall(Transaction a_trans) {
if (i_trans == null) {
super.unmarshall(a_trans);
if(_className!=null) {
_className = container().config().resolveAliasStoredName(_className);
_claxx = a_trans.reflector().forName(_className);
}
}
}
void setEvaluationMode() {
Iterator4 children = iterateChildren();
while (children.moveNext()) {
Object child = children.current();
if (child instanceof QConObject) {
((QConObject) child).setEvaluationMode();
}
}
}
@Override
public void setProcessedByIndex(QCandidates candidates) {
// do nothing, QConClass needs to stay in the evaluation graph.
}
}