com.db4o.inside.ix.NIxPaths Maven / Gradle / Ivy
The newest version!
/* Copyright (C) 2004 - 2005 db4objects Inc. http://www.db4o.com
This file is part of the db4o open source object database.
db4o is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published
by the Free Software Foundation and as clarified by db4objects' GPL
interpretation policy, available at
http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
Suite 350, San Mateo, CA 94403, USA.
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, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
package com.db4o.inside.ix;
import com.db4o.*;
import com.db4o.foundation.*;
/**
*
* A note on the logic of #count() and #traverse():
*
* Within the visitor we are always looking at two NIxPath: last[0] and current.
* Each run of the visitor takes care of all nodes:
* - smaller than last[0] for the first run only
* - equal to last[0]
* - between last[0] and current
* - but *NOT* equal to current, which is handled in the next run.
*
*/
public class NIxPaths {
Tree _paths;
void add(NIxPath path){
path.i_size = 1;
path.i_preceding = null;
path.i_subsequent = null;
_paths = Tree.add(_paths, path);
}
void removeRedundancies(){
// FIXME: removeRedundancies not in function yet
// This is written very simple for ANDs only first
// and worst of all it doesn't work yet.
final Collection4 add = new Collection4();
final boolean[] stop = new boolean[]{false};
_paths.traverse(new Visitor4() {
public void visit(Object a_object) {
if(! stop[0]){
NIxPath path = (NIxPath)a_object;
if(! path._takePreceding){
add.clear();
}
add.add(path);
if(! path._takeSubsequent){
stop[0] = true;
}
}
}
});
_paths = null;
Iterator4 i = add.iterator();
while(i.hasNext()){
this.add((NIxPath)i.next());
}
}
int count(){
final NIxPath[] last = new NIxPath[] {null};
final int[] sum = new int[] { 0 };
_paths.traverse(new Visitor4() {
public void visit(Object a_object) {
NIxPath current = (NIxPath)a_object;
if(last[0] == null){
if(current._takePreceding){
sum[0] += countAllPreceding(current._head);
}
}else{
if( (last[0]._takeSubsequent || last[0]._takeMatches)
&& (current._takePreceding || current._takeMatches) ){
sum[0] += countSpan(current, last[0], current._head, last[0]._head, current._head._next, last[0]._head._next,0);
} else if(last[0]._takeMatches){
sum[0] += countAllMatching(last[0]._head);
}
}
last[0] = current;
}
});
if(last[0]._takeMatches){
sum[0] += countAllMatching(last[0]._head);
}
if(last[0]._takeSubsequent){
sum[0] += countAllSubsequent(last[0]._head);
}
return sum[0];
}
private int countAllPreceding(NIxPathNode head){
int count = 0;
while (head != null) {
count += head.countPreceding();
head = head._next;
}
return count;
}
private int countAllMatching(NIxPathNode head){
int count = 0;
while (head != null) {
count += head.countMatching();
head = head._next;
}
return count;
}
private int countAllSubsequent(NIxPathNode head){
int count = 0;
while (head != null) {
count += head.countSubsequent();
head = head._next;
}
return count;
}
/** see documentation to this class for behaviour **/
private int countSpan(NIxPath greatPath, NIxPath smallPath, NIxPathNode a_previousGreat, NIxPathNode a_previousSmall, NIxPathNode a_great, NIxPathNode a_small, int sum) {
sum += a_previousGreat.countSpan(greatPath, smallPath, a_previousSmall);
if(a_great != null && a_great.carriesTheSame(a_small)){
return countSpan(greatPath, smallPath, a_great, a_small, a_great._next, a_small._next, sum);
}
return sum + countGreater(a_small, 0) + countSmaller(a_great, 0);
}
private int countSmaller(NIxPathNode a_path, int a_sum) {
if(a_path == null){
return a_sum;
}
if (a_path._next == null) {
return a_sum + countPreceding(a_path);
}
if (a_path._next._tree == a_path._tree.i_subsequent) {
a_sum += countPreceding(a_path);
} else {
a_sum += a_path.countMatching();
}
return countSmaller(a_path._next, a_sum);
}
private int countGreater(NIxPathNode a_path, int a_sum) {
if(a_path == null){
return a_sum;
}
if (a_path._next == null) {
return a_sum + countSubsequent(a_path);
}
if (a_path._next._tree == a_path._tree.i_preceding) {
a_sum += countSubsequent(a_path);
} else {
a_sum += a_path.countMatching();
}
return countGreater(a_path._next, a_sum);
}
private int countPreceding(NIxPathNode a_path) {
return Tree.size(a_path._tree.i_preceding) + a_path.countMatching();
}
private int countSubsequent(NIxPathNode a_path) {
return Tree.size(a_path._tree.i_subsequent) + a_path.countMatching();
}
void traverse(Visitor4 visitor) {
final NIxPath[] last = new NIxPath[] {null};
final Visitor4Dispatch dispatcher = new Visitor4Dispatch(visitor);
_paths.traverse(new Visitor4() {
public void visit(Object a_object) {
NIxPath current = (NIxPath)a_object;
if(last[0] == null){
if(current._takePreceding){
traverseAllPreceding(current._head, dispatcher);
}
}else{
if( (last[0]._takeSubsequent || last[0]._takeMatches)
&& (current._takePreceding || current._takeMatches) ){
traverseSpan(current, last[0], current._head, last[0]._head, current._head._next, last[0]._head._next, dispatcher);
} else if(last[0]._takeMatches){
traverseAllMatching(last[0]._head, dispatcher);
}
}
last[0] = current;
}
});
if(last[0]._takeMatches){
traverseAllMatching(last[0]._head, dispatcher);
}
if(last[0]._takeSubsequent){
traverseAllSubsequent(last[0]._head, dispatcher);
}
}
private void traverseAllPreceding(NIxPathNode head, Visitor4Dispatch dispatcher){
while (head != null) {
head.traversePreceding(dispatcher);
head = head._next;
}
}
private void traverseAllMatching(NIxPathNode head, Visitor4Dispatch dispatcher){
while (head != null) {
head.traverseMatching(dispatcher);
head = head._next;
}
}
private void traverseAllSubsequent(NIxPathNode head, Visitor4Dispatch dispatcher){
while (head != null) {
head.traverseSubsequent(dispatcher);
head = head._next;
}
}
/** see documentation to this class for behaviour **/
private void traverseSpan(NIxPath greatPath, NIxPath smallPath, NIxPathNode a_previousGreat, NIxPathNode a_previousSmall, NIxPathNode a_great, NIxPathNode a_small, Visitor4Dispatch dispatcher) {
a_previousGreat.traverseSpan(greatPath, smallPath, a_previousSmall, dispatcher);
if(a_great != null && a_great.carriesTheSame(a_small)){
traverseSpan(greatPath, smallPath, a_great, a_small, a_great._next, a_small._next, dispatcher);
return;
}
traverseGreater(a_small, dispatcher);
traverseSmaller(a_great, dispatcher);
}
private void traverseSmaller(NIxPathNode a_path, Visitor4Dispatch dispatcher) {
if(a_path == null){
return;
}
if (a_path._next == null) {
traversePreceding(a_path, dispatcher);
return;
}
if (a_path._next._tree == a_path._tree.i_subsequent) {
traversePreceding(a_path, dispatcher);
} else {
a_path.traverseMatching(dispatcher);
}
traverseSmaller(a_path._next, dispatcher);
}
private void traverseGreater(NIxPathNode a_path, Visitor4Dispatch dispatcher) {
if(a_path == null){
return;
}
if (a_path._next == null) {
traverseSubsequent(a_path, dispatcher);
return;
}
if (a_path._next._tree == a_path._tree.i_preceding) {
traverseSubsequent(a_path, dispatcher);
} else {
a_path.traverseMatching(dispatcher);
}
traverseGreater(a_path._next, dispatcher);
}
private void traversePreceding(NIxPathNode a_path, Visitor4Dispatch dispatcher) {
a_path.traverseMatching(dispatcher);
Tree.traverse(a_path._tree.i_preceding, dispatcher);
}
private void traverseSubsequent(NIxPathNode a_path, Visitor4Dispatch dispatcher) {
a_path.traverseMatching(dispatcher);
Tree.traverse(a_path._tree.i_subsequent, dispatcher);
}
}