package org.reldb.rel.v0.types;
import java.io.Serializable;
import org.reldb.rel.exceptions.*;
import org.reldb.rel.v0.generator.Generator;
import org.reldb.rel.v0.values.*;
/** Defines a mapping between matching attributes in differing HeadingS, and methods for
* copying common attributes from one tuple to another. */
public class AttributeMap implements Serializable {
private static final long serialVersionUID = 1L;
private int[] map;
private AttributeMap[] nestmap;
/** Create an AttributeMap to map attributes of the 'from' type to tuples of the 'to' type.
*
* The set of 'to' attributes must be a subset of 'from' or an exception will be thrown.
*/
public AttributeMap(Heading to, Heading from) {
map = new int[to.getDegree()];
nestmap = new AttributeMap[to.getDegree()];
int toAttributeIndex = 0;
for (Attribute attribute: to.getAttributes()) {
int attributeIndex = from.getIndexOf(attribute.getName());
if (attributeIndex < 0)
throw new ExceptionSemantic("RS0240: Attribute " + attribute.getName() + " not found in " + from);
Attribute fromAttribute = from.getAttributes().get(attributeIndex);
if (!attribute.getType().canAccept(fromAttribute.getType()))
throw new ExceptionSemantic("RS0241: Attribute " + attribute.getName() + " mismatch between " + attribute.getType() + " and " + fromAttribute.getType());
if (attribute.getType().requiresReformatOf(fromAttribute.getType()))
nestmap[toAttributeIndex] = new AttributeMap(((TypeHeading)attribute.getType()).getHeading(), ((TypeHeading)fromAttribute.getType()).getHeading());
map[toAttributeIndex++] = attributeIndex;
}
}
/** Use this map to assign values from the 'from' tuple to the given tuple's array of ValueS. */
public void assign(Value[] values, ValueTuple from) {
Value[] source = from.getValues();
for (int i=0; i<map.length; i++) {
if (nestmap[i] != null)
values[map[i]] = ((Projectable)source[i]).project(nestmap[i]);
else
values[map[i]] = source[i];
}
}
/** Use this map to project the 'from' tuple to a new tuple.
* 'From' is a superset of the target. */
public ValueTuple project(Generator generator, ValueTuple from) {
Value[] source = from.getValues();
Value[] target = new Value[map.length];
for (int i=0; i<target.length; i++) {
if (nestmap[i] != null)
target[i] = ((Projectable)source[map[i]]).project(nestmap[i]);
else
target[i] = source[map[i]];
}
return new ValueTuple(generator, target);
}
public String toString() {
String out = null;
for (int i=0; i<map.length; i++)
if (nestmap[i] == null)
out = ((out==null) ? "" : out + ", ") + (i + "=" + map[i]);
else
out = ((out==null) ? "" : out + ", ") + (i + "=" + map[i] + " (" + nestmap[i] + ")");
return "AttributeMap [" + ((out == null) ? "" : out) + "]";
}
}