package org.reldb.rel.v0.types;
import org.reldb.rel.exceptions.*;
import org.reldb.rel.v0.generator.Generator;
import org.reldb.rel.v0.values.Value;
import org.reldb.rel.v0.values.ValueTuple;
/** Defines a join mapping between a two source TypeTupleS into a destination TypeTuple. */
public class JoinMap {
private int degree;
private int[] leftCommonToRight;
private boolean[] rightExclude;
private int commonDegree;
/** Create a JoinMap to join tuples of the source types, which may contain common attributes,
* to the destination type. */
public JoinMap(Heading destinationType, Heading leftType, Heading rightType) {
degree = destinationType.getDegree();
Heading intersection = leftType.intersect(rightType);
if (intersection.getDegree() == 0)
throw new ExceptionFatal("RS0382: " + leftType + " and " + rightType + " have no common attributes, and therefore need not be mapped.");
leftCommonToRight = new int[leftType.getDegree()];
rightExclude = new boolean[rightType.getDegree()];
int leftAttributeIndex = 0;
for (Attribute attribute: leftType.getAttributes()) {
int rightAttributeIndex = rightType.getIndexOf(attribute.getName());
leftCommonToRight[leftAttributeIndex++] = rightAttributeIndex;
if (rightAttributeIndex >= 0)
rightExclude[rightAttributeIndex] = true;
}
commonDegree = 0;
for (int i=0; i<leftCommonToRight.length; i++)
commonDegree += (leftCommonToRight[i] >= 0) ? 1 : 0;
}
/** Return true if the left and right tuples have matching common attributes. */
public boolean isJoinable(ValueTuple left, ValueTuple right) {
Value[] leftValues = left.getValues();
Value[] rightValues = right.getValues();
for (int i=0; i<leftCommonToRight.length; i++)
if (leftCommonToRight[i] >= 0 && !(leftValues[i].compareTo(rightValues[leftCommonToRight[i]])==0))
return false;
return true;
}
/** Return a new tuple consisting of a left tuple's common attributes. */
public ValueTuple getLeftTupleCommon(Generator generator, ValueTuple left) {
Value[] leftValues = left.getValues();
Value[] leftCommonValues = new Value[commonDegree];
int leftIndex = 0;
for (int i=0; i<leftCommonToRight.length; i++)
if (leftCommonToRight[i] >= 0)
leftCommonValues[leftIndex++] = leftValues[i];
return new ValueTuple(generator, leftCommonValues);
}
/** Return a new tuple consisting of a right tuple's common attributes. */
public ValueTuple getRightTupleCommon(Generator generator, ValueTuple right) {
Value[] rightValues = right.getValues();
Value[] rightCommonValues = new Value[commonDegree];
int rightIndex = 0;
for (int i=0; i<leftCommonToRight.length; i++)
if (leftCommonToRight[i] >= 0)
rightCommonValues[rightIndex++] = rightValues[leftCommonToRight[i]];
return new ValueTuple(generator, rightCommonValues);
}
/** Create a new tuple by a join of the left and right ValueTupleS.
* Assume that common attributes have matching values, as (perhaps)
* determined by isJoinable(). */
public ValueTuple join(Generator generator, ValueTuple left, ValueTuple right) {
Value[] leftValues = left.getValues();
Value[] rightValues = right.getValues();
Value[] target = new Value[degree];
System.arraycopy(leftValues, 0, target, 0, leftValues.length);
int destinationIndex = leftValues.length;
for (int i=0; i<rightValues.length; i++)
if (!rightExclude[i])
target[destinationIndex++] = rightValues[i];
return new ValueTuple(generator, target);
}
/** Create a new tuple by a join of the left and right ValueTupleS.
* Throw an exception if common attributes do not have matching values. */
public ValueTuple joinChecked(Generator generator, ValueTuple left, ValueTuple right) {
Value[] leftValues = left.getValues();
Value[] rightValues = right.getValues();
Value[] target = new Value[degree];
int destinationIndex = 0;
for (int i=0; i<leftCommonToRight.length; i++) {
if (leftCommonToRight[i] >= 0 && !(leftValues[i].compareTo(rightValues[leftCommonToRight[i]])==0))
throw new ExceptionSemantic("RS0254: Common attributes differ in value.");
target[destinationIndex++] = leftValues[i];
}
for (int i=0; i<rightValues.length; i++)
if (!rightExclude[i])
target[destinationIndex++] = rightValues[i];
return new ValueTuple(generator, target);
}
public String toString() {
String outLR = null;
for (int i=0; i<leftCommonToRight.length; i++)
if (leftCommonToRight[i] >= 0)
outLR = ((outLR==null) ? "" : outLR + ", ") + i + "=" + leftCommonToRight[i];
String outR = "";
for (int i=0; i<rightExclude.length; i++)
outR += ((rightExclude[i]) ? "x" : "_");
return "JoinMap commonLR=[" + ((outLR == null) ? "" : outLR) + "] excludeR=[" + outR + "]";
}
}