/* * 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; import java.util.Collections; import java.util.List; // Third party packages import org.apache.log4j.*; // Locally written packages import org.mulgara.query.TuplesException; import org.mulgara.query.Variable; /** * A {@link Tuples} representing a single variable assignment. * * A variable assignment has one column (the variable) and one row, binding that * one column to the value. * * @created 2004-03-19 * * @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 ©2004 <a href="http://www.PIsoftware.com/">Plugged In Software Pty Ltd</a> * * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a> */ class Assignment extends AbstractTuples { /** Logger. */ @SuppressWarnings("unused") private static final Logger logger = Logger.getLogger(Assignment.class.getName()); /** * The value the variable is assigned. */ private long value; /** * The cursor position. * * The only values this field takes are {@link #BEFORE_ROW}, {@link #ON_ROW} * and {@link #AFTER_ROW}. */ private int row = BEFORE_ROW; /** * Value of {@link #row} indicating that the cursor is before the single row. */ private static final int BEFORE_ROW = -1; /** * Value of {@link #row} indicating that the cursor is on the single row. */ private static final int ON_ROW = 0; /** * Value of {@link #row} indicating that the cursor is after the single row. */ private static final int AFTER_ROW = 1; // // Constructor // /** * Construct an assignment. * * @param variable the variable to bind * @param value the value to bind the <var>variable</var> * @throws IllegalArgumentException if <var>variable</var> is * <code>null</code> or <var>value</var> is {@link #UNBOUND} */ Assignment(Variable variable, long value) { // Validate "variable" parameter if (variable == null) { throw new IllegalArgumentException("Null \"variable\" parameter"); } // Validate "value" parameter if (value == UNBOUND) { throw new IllegalArgumentException("Unbound \"value\" parameter"); } // Initialize fields setVariables(new Variable[] {variable}); this.value = value; } // // Methods implementing AbstractTuples // /** * Gets the ColumnValue attribute of the AbstractTuples object * * @param column PARAMETER TO DO * @return The ColumnValue value * @throws TuplesException EXCEPTION TO DO */ public long getColumnValue(int column) throws TuplesException { // Make sure we're asking for column zero (the only column, in this case) if (column != 0) { throw new TuplesException("No column " + column); } return value; } /** * Move the cursor to before the first row, optionally with a specifies list * of leading column values. * * @param prefix only iterate through product terms with the specified leading * column values ({@link #NO_PREFIX} should be passed if all prefix * values are desired * @param suffixTruncation the number of trailing rows to ignore when * determining whether a row is distinct * @throws IllegalArgumentException if <var>prefix</var> is <code>null</code> * @throws TuplesException EXCEPTION TO DO */ public void beforeFirst(long[] prefix, int suffixTruncation) throws TuplesException { // Validate "prefix" parameter if (prefix == null) { throw new IllegalArgumentException("Null \"prefix\" parameter"); } switch (prefix.length) { case 0: row = BEFORE_ROW; break; case 1: // We want a subsequent call to next() to move the cursor to be on the // single row if the prefix value matches the assignment value, or to // move the cursor to after the single row if the prefix value doesn't // match the assignment value. row = (value == prefix[0]) ? BEFORE_ROW : ON_ROW; break; default: // Any prefix longer than the number of columns (1) makes no sense throw new IllegalArgumentException( "Value " + toString(prefix) + " for parameter \"prefix\" is too long" ); } } /** * Convenience method for the usual case of wanting to reset a tuples to * iterate through every single element. * * Equivalent to * {@link #beforeFirst(long[], int)}<code>({@link #NO_PREFIX}, 0)</code>. * * @throws TuplesException {@inheritDoc} */ public void beforeFirst() throws TuplesException { row = BEFORE_ROW; // before the first row } /** * Move to the next row satisfying the current prefix and suffix truncation. * * If no such row exists, return <code>false<code> and the current row * becomes unspecified. The current row is unspecified when a tuples instance * is created. To specify the current row, the {@link #beforeFirst()} or * {@link #beforeFirst(long[], int)} methods must be invoked * * @return whether a subsequent row with the specified prefix exists * @throws IllegalStateException if the current row is unspecified. * @throws TuplesException EXCEPTION TO DO */ public boolean next() throws TuplesException { switch (row) { case BEFORE_ROW: row = ON_ROW; return true; case ON_ROW: row = AFTER_ROW; return false; case AFTER_ROW: throw new TuplesException("Already after last row"); default: // any other row value should never occur throw new Error("Impossible row value: " + row); } } /** * METHOD TO DO * * @throws TuplesException EXCEPTION TO DO */ public void close() throws TuplesException { // null implementation } /** * An assignment always has a single row. * * @return 1 */ public long getRowCount() { return 1; } public long getRowUpperBound() { return getRowCount(); } public long getRowExpectedCount() { return getRowCount(); } /* (non-Javadoc) * @see org.mulgara.store.tuples.AbstractTuples#isEmpty() */ @Override public boolean isEmpty() throws TuplesException { return false; } /** * METHOD TO DO * * @return RETURNED VALUE TO DO * @throws TuplesException EXCEPTION TO DO */ public boolean hasNoDuplicates() throws TuplesException { return true; } /** * An unbound assignment would be a contradiction. * * @return <code>false</code> */ public boolean isColumnEverUnbound(int column) { return false; } /** * An assignment is stored in RAM. * * @return <code>true</code> */ public boolean isMaterialized() { return true; } public List<Tuples> getOperands() { return Collections.emptyList(); } public RowComparator getRowComparator() { return DefaultRowComparator.getInstance(); } /** * METHOD TO DO * * @return RETURNED VALUE TO DO */ public Object clone() { Assignment cloned = (Assignment)super.clone(); // Copy immutable fields by reference cloned.value = value; // Copy mutable fields by value cloned.row = row; return cloned; } }