PersistKeyCreator.java [plain text]
package com.sleepycat.persist.impl;
import java.util.Collection;
import java.util.Set;
import com.sleepycat.bind.tuple.TupleBase;
import com.sleepycat.db.DatabaseEntry;
import com.sleepycat.db.DatabaseException;
import com.sleepycat.db.ForeignMultiKeyNullifier;
import com.sleepycat.db.SecondaryDatabase;
import com.sleepycat.db.SecondaryKeyCreator;
import com.sleepycat.db.SecondaryMultiKeyCreator;
import com.sleepycat.persist.model.EntityMetadata;
import com.sleepycat.persist.model.Relationship;
import com.sleepycat.persist.model.SecondaryKeyMetadata;
import com.sleepycat.persist.raw.RawObject;
public class PersistKeyCreator implements SecondaryKeyCreator,
SecondaryMultiKeyCreator,
ForeignMultiKeyNullifier {
static boolean isManyType(Class cls) {
return cls.isArray() || Collection.class.isAssignableFrom(cls);
}
private Catalog catalog;
private int priKeyFormatId;
private String keyName;
private Format keyFormat;
private boolean toMany;
public PersistKeyCreator(Catalog catalog,
EntityMetadata entityMeta,
String keyClassName,
SecondaryKeyMetadata secKeyMeta) {
this.catalog = catalog;
Format priKeyFormat =
catalog.getFormat(entityMeta.getPrimaryKey().getClassName());
priKeyFormatId = priKeyFormat.getId();
keyName = secKeyMeta.getKeyName();
keyFormat = catalog.getFormat(keyClassName);
if (keyFormat == null) {
throw new IllegalArgumentException
("Not a key class: " + keyClassName);
}
if (keyFormat.isPrimitive()) {
throw new IllegalArgumentException
("Use a primitive wrapper class instead of class: " +
keyFormat.getClassName());
}
Relationship rel = secKeyMeta.getRelationship();
toMany = (rel == Relationship.ONE_TO_MANY ||
rel == Relationship.MANY_TO_MANY);
}
public boolean createSecondaryKey(SecondaryDatabase secondary,
DatabaseEntry key,
DatabaseEntry data,
DatabaseEntry result)
throws DatabaseException {
if (toMany) {
throw new IllegalStateException();
}
KeyLocation loc = moveToKey(key, data);
if (loc != null) {
RecordOutput output = new RecordOutput
(catalog, true );
loc.format.copySecKey(loc.input, output);
TupleBase.outputToEntry(output, result);
return true;
} else {
return false;
}
}
public void createSecondaryKeys(SecondaryDatabase secondary,
DatabaseEntry key,
DatabaseEntry data,
Set results)
throws DatabaseException {
if (!toMany) {
throw new IllegalStateException();
}
KeyLocation loc = moveToKey(key, data);
if (loc != null) {
loc.format.copySecMultiKey(loc.input, keyFormat, results);
}
}
public boolean nullifyForeignKey(SecondaryDatabase secondary,
DatabaseEntry key,
DatabaseEntry data,
DatabaseEntry secKey)
throws DatabaseException {
RawObject entity = (RawObject) PersistEntityBinding.readEntity
(catalog, key, data, true );
Format entityFormat = (Format) entity.getType();
Object secKeyObject = null;
if (toMany) {
secKeyObject = PersistKeyBinding.readKey
(keyFormat, catalog, secKey.getData(), secKey.getOffset(),
secKey.getSize(), true );
}
if (entityFormat.nullifySecKey
(catalog, entity, keyName, secKeyObject)) {
PersistEntityBinding.writeEntity
(entityFormat, catalog, entity, data, true );
return true;
} else {
return false;
}
}
private KeyLocation moveToKey(DatabaseEntry priKey, DatabaseEntry data) {
RecordInput input = new RecordInput
(catalog, true , priKey, priKeyFormatId,
data.getData(), data.getOffset(), data.getSize());
int formatId = input.readPackedInt();
Format entityFormat = catalog.getFormat(formatId);
Format fieldFormat = entityFormat.skipToSecKey(input, keyName);
if (fieldFormat != null) {
return input.getKeyLocation(fieldFormat);
} else {
return null;
}
}
}