/* * #! * Ontopia Engine * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ package net.ontopia.topicmaps.query.spi; import net.ontopia.topicmaps.query.core.InvalidQueryException; import net.ontopia.topicmaps.query.impl.basic.QueryMatches; import net.ontopia.topicmaps.query.impl.utils.PredicateSignature; /** * EXPERIMENTAL: Base predicate that provides a simple interface for * implementing predicates. The process method lets one filter out, * pass through and/or produce new rows.<p> * * @since 4.0 */ public abstract class ProcessPredicate extends JavaPredicate { public final QueryMatches satisfy(QueryMatches matches, Object[] arguments) throws InvalidQueryException { // validate arguments PredicateSignature sign = PredicateSignature.getSignature(this); sign.verifyBound(matches, arguments, this); // do actual work Result result = new Result(matches, arguments); result.process(this); return result.getResult(); } static class Result implements ResultIF { QueryMatches input; QueryMatches output; int[] argindexes; boolean[] boundparams; int rownum; Result(QueryMatches matches, Object[] arguments) { this.input = matches; this.output = new QueryMatches(this.input); this.argindexes = new int[arguments.length]; this.boundparams = new boolean[arguments.length]; for (int i=0; i < arguments.length; i++) { this.argindexes[i] = this.input.getIndex(arguments[i]); this.boundparams[i] = this.input.bound(argindexes[i]); } } public QueryMatches getResult() { return output; } public void process(ProcessPredicate pred) throws InvalidQueryException { Object[] row = new Object[argindexes.length]; for (rownum = 0; rownum <= input.last; rownum++) { for (int i=0; i < argindexes.length; i++) { row[i] = input.data[rownum][argindexes[i]]; } pred.process(row, boundparams, this); } } public void add(Object[] row) { if (output.last+1 == output.size) output.increaseCapacity(); output.last++; // clone existing row Object[] newRow = (Object[]) input.data[rownum].clone(); // update argument columns for (int i=0; i < row.length; i++) { if (!boundparams[i]) newRow[this.argindexes[i]] = row[i]; } output.data[output.last] = newRow; } } /** * EXPERIMENTAL: Processes the input row and pushes result rows to the result. */ public abstract void process(Object[] row, boolean[] boundparams, ResultIF result) throws InvalidQueryException; }