/* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is the Kowari Metadata Store. * * The Initial Developer of the Original Code is Plugged In Software Pty * Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002 * Plugged In Software Pty Ltd. All Rights Reserved. * * Contributor(s): N/A. * * [NOTE: The text of this Exhibit A may differ slightly from the text * of the notices in the Source Code files of the Original Code. You * should use the text of this Exhibit A rather than the text found in the * Original Code Source Code for Your Modifications.] * */ package org.mulgara.store.tuples; // Java 2 standard packages import java.util.*; // Log4J import org.apache.log4j.Logger; // Locally written packages import org.mulgara.query.Cursor; import org.mulgara.query.TuplesException; import org.mulgara.query.Variable; import org.mulgara.util.StackTrace; /** * Rearrange columns, discarding any existing sort order. If columns need to be * discarded but not rearranged, {@link OrderedProjection} should be used * instead. * * @created 2003-02-04 * * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a> * * @version $Revision: 1.9 $ * * @modified $Date: 2005/01/05 04:59:10 $ * * @maintenanceAuthor $Author: newmana $ * * @company <A href="mailto:info@PIsoftware.com">Plugged In Software</A> * * @copyright © 2003 <A href="http://www.PIsoftware.com/">Plugged In * Software Pty Ltd</A> * * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a> */ class UnorderedProjection extends AbstractTuples { /** * Logger. */ private final static Logger logger = Logger.getLogger(UnorderedProjection.class); /** * The proposition to project. */ private final Tuples operand; /** * Array indexed on operand columns, whose values are projected columns. */ private final int[] columnMapping; /** * Value within the {@link #columnMapping} array to indicate that the operand * lacks a given column. */ private final int ABSENT_COLUMN = -1; /** * Eliminate columns from a {@link Tuples}. This does not eliminate * duplicates; {@link DistinctTuples} should be used to produce a formal * relational projection. * * @param operand the tuples to project * @param columnList the rearranged columns * @throws IllegalArgumentException if <var>operand</var> is <code>null</code> * @throws TuplesException EXCEPTION TO DO */ UnorderedProjection(Tuples operand, List<Variable> columnList) throws TuplesException { // Validate "operand" parameter if (operand == null) { throw new IllegalArgumentException("Null \"operand\" parameter"); } // Validate "variables" parameter if (columnList == null) { throw new IllegalArgumentException("Null \"columnList\" parameter"); } if (logger.isDebugEnabled()) { logger.debug("Projecting columns " + columnList + " on " + operand); } // Initialize fields this.operand = (Tuples)operand.clone(); setVariables(columnList); // Create column mapping columnMapping = new int[getNumberOfVariables()]; Variable[] vars = getVariables(); Arrays.fill(columnMapping, ABSENT_COLUMN); Variable[] operandVariables = operand.getVariables(); for (int i = 0; i < getNumberOfVariables(); i++) { for (int j = 0; j < operandVariables.length; j++) { if (vars[i].equals(operandVariables[j])) { columnMapping[i] = j; break; } } } } /** * Cloning constructor. * * @param parent PARAMETER TO DO */ private UnorderedProjection(UnorderedProjection parent) { operand = (Tuples) parent.operand.clone(); setVariables(parent.getVariables()); columnMapping = parent.columnMapping; } /** * Gets the ColumnValue attribute of the UnorderedProjection object * * @param column The 0-indexed column number to get the value from * @return The value for the column binding, or {@link Tuples#UNBOUND} if the value is not bound. * @throws TuplesException If there is an error accessing one of the original Tuples. */ public long getColumnValue(int column) throws TuplesException { assert((column >= 0) && (column < getNumberOfVariables())) || (column == ABSENT_COLUMN):"Invalid column " + column; if (columnMapping[column] == ABSENT_COLUMN) { if (logger.isDebugEnabled()) { logger.debug(getVariables()[column] + " is never bound\n " + new StackTrace()); } return Tuples.UNBOUND; } else { return operand.getColumnValue(columnMapping[column]); } } /** * Gets the Comparator attribute of the UnorderedProjection object * * @return The Comparator value */ public RowComparator getComparator() { return null; } /** * Gets the RowCount attribute of the UnorderedProjection object * * @return The RowCount value * @throws TuplesException Error accessing underlying data */ public long getRowCount() throws TuplesException { return operand.getRowCount(); } public long getRowUpperBound() throws TuplesException { return operand.getRowUpperBound(); } public long getRowExpectedCount() throws TuplesException { return operand.getRowExpectedCount(); } public boolean isEmpty() throws TuplesException { return operand.isEmpty(); } /** * A column is unbound if it is unbound in the source of the projection. */ public boolean isColumnEverUnbound(int column) throws TuplesException { assert((column >= 0) && (column < getNumberOfVariables())) || (column == ABSENT_COLUMN):"Invalid column " + column; if (columnMapping[column] == ABSENT_COLUMN) { if (logger.isInfoEnabled()) { logger.info(getVariables()[column] + " is never bound", new Throwable()); } return true; } else { return operand.isColumnEverUnbound(columnMapping[column]); } } /** * Gets the Materialized attribute of the UnorderedProjection object * * @return The Materialized value */ public boolean isMaterialized() { return operand.isMaterialized(); } /** * @return whether every operand is unconstrained * @throws TuplesException EXCEPTION TO DO */ public boolean isUnconstrained() throws TuplesException { return (((getVariables().length == 0 && operand.getRowCardinality() != Cursor.ZERO)) || (getVariables().length > 0 && operand.isUnconstrained())); } public List<Tuples> getOperands() { return Collections.singletonList(operand); } // // Methods implementing Tuples // /** * METHOD TO DO * * @param prefix PARAMETER TO DO * @param suffixTruncation PARAMETER TO DO * @throws TuplesException EXCEPTION TO DO */ public void beforeFirst(long[] prefix, int suffixTruncation) throws TuplesException { if (suffixTruncation != 0) { throw new TuplesException("Suffix truncation not supported"); } if (prefix.length > 0) { throw new TuplesException("Prefix not supported in UnorderedProjection" + "- use TuplesOperations.sort() to provide prefix support"); } operand.beforeFirst(prefix, 0); } /** * METHOD TO DO * * @throws TuplesException EXCEPTION TO DO */ public void close() throws TuplesException { operand.close(); } /** * METHOD TO DO * * @return RETURNED VALUE TO DO * @throws TuplesException EXCEPTION TO DO */ public boolean hasNoDuplicates() throws TuplesException { return (operand.getVariables().length <= getNumberOfVariables()) ? operand.hasNoDuplicates() : false; } /** * METHOD TO DO * * @return RETURNED VALUE TO DO * @throws TuplesException EXCEPTION TO DO */ public boolean next() throws TuplesException { return operand.next(); } // // Methods overriding Object // /** * METHOD TO DO * * @return RETURNED VALUE TO DO */ public Object clone() { return new UnorderedProjection(this); } }