* @see org.jpox.store.StoreManager#getStrategyValue(org.jpox.ObjectManager, org.jpox.metadata.AbstractClassMetaData, int)
*/
public Object getStrategyValue(ObjectManager om, AbstractClassMetaData cmd, int absoluteFieldNumber)
{
// Extract the control information for this field that needs its value
AbstractMemberMetaData mmd = null;
String fieldName = null;
IdentityStrategy strategy = null;
String sequence = null;
String valueGeneratorName = null;
TableGeneratorMetaData tableGeneratorMetaData = null;
SequenceMetaData sequenceMetaData = null;
if (absoluteFieldNumber >= 0)
{
// real field
mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(absoluteFieldNumber);
fieldName = mmd.getFullFieldName();
strategy = mmd.getValueStrategy();
sequence = mmd.getSequence();
valueGeneratorName = mmd.getValueGeneratorName();
}
else
{
// datastore-identity surrogate field
fieldName = cmd.getFullClassName() + " (datastore id)";
strategy = cmd.getIdentityMetaData().getValueStrategy();
sequence = cmd.getIdentityMetaData().getSequence();
valueGeneratorName = cmd.getIdentityMetaData().getValueGeneratorName();
}
// Extract any metadata-based generation information
if (valueGeneratorName != null)
{
if (strategy == IdentityStrategy.INCREMENT)
{
tableGeneratorMetaData = getMetaDataManager().getMetaDataForTableGenerator(om.getClassLoaderResolver(),
valueGeneratorName);
if (tableGeneratorMetaData == null)
{
throw new JPOXUserException(LOCALISER.msg("038005", fieldName, valueGeneratorName));
}
}
else if (strategy == IdentityStrategy.SEQUENCE)
{
sequenceMetaData = getMetaDataManager().getMetaDataForSequence(om.getClassLoaderResolver(),
valueGeneratorName);
if (sequenceMetaData == null)
{
throw new JPOXUserException(LOCALISER.msg("038006", fieldName, valueGeneratorName));
}
}
}
else if (strategy == IdentityStrategy.SEQUENCE && sequence != null)
{
// TODO Allow for package name of this class prefix for the sequence name
sequenceMetaData = getMetaDataManager().getMetaDataForSequence(om.getClassLoaderResolver(), sequence);
if (sequenceMetaData == null)
{
// JPOX 1.1 behaviour is just to use the sequence name in the datastore so log it and fallback to that
JPOXLogger.DATASTORE.warn("Field " + fieldName + " has been specified to use sequence " + sequence +
" but there is no <sequence> specified in the MetaData. " +
"Falling back to use a sequence in the datastore with this name directly.");
}
}
String strategyName = strategy.toString();
if (strategy.equals(IdentityStrategy.CUSTOM))
{
// Using a "custom" generator
strategyName = strategy.getCustomName();
}
else if (strategy.equals(IdentityStrategy.NATIVE))
{
strategyName = getStrategyForNative(sequence);
}
// POID Generators are cached against a name. Some POID Generators are unique per datastore.
// Others are per class/field. Others have a user-defined name.
// The name that they are cached under relates to what they use.
// Generate the name for PoidManager to use the strategy for this field/class.
String poidGeneratorName = null;
String generatorNameKeyInManager = null;
ConfigurationElement elem =
omfContext.getPluginManager().getConfigurationElementForExtension("org.jpox.store_valuegenerator",
new String[]{"name", "unique"}, new String[] {strategyName, "true"});
if (elem != null)
{
// Unique value generator so set the key in PoidManager to the value generator name itself
poidGeneratorName = elem.getAttribute("name");
generatorNameKeyInManager = poidGeneratorName;
}
else
{
// Not a unique (datastore-independent) generator so try just for this datastore
elem = omfContext.getPluginManager().getConfigurationElementForExtension("org.jpox.store_valuegenerator",
new String[]{"name", "datastore"}, new String[] {strategyName, storeManagerKey});
if (elem != null)
{
// Set the generator name (for use by the PoidManager)
poidGeneratorName = elem.getAttribute("name");
}
}
if (generatorNameKeyInManager == null)
{
// Value generator is not unique so set based on class/field
if (absoluteFieldNumber >= 0)
{
// Require generation for a field so use field name for the generator symbolic name
generatorNameKeyInManager = mmd.getFullFieldName();
}
else
{
// Require generation for a datastore id field so use the class name for the generator symbolic name
generatorNameKeyInManager = cmd.getFullClassName();
}
}
// Try to find the generator from the PoidManager if we already have it managed
PoidGenerator generator = poidManager.getPoidGenerator(generatorNameKeyInManager);
if (generator == null)
{
if (poidGeneratorName == null)
{
// No available value-generator for the specified strategy for this datastore
throw new JPOXUserException(LOCALISER.msg("038004", strategy));
}
// Set up the default properties available for all value generators
Properties props = getPropertiesForGenerator(cmd, absoluteFieldNumber, om, sequenceMetaData,
tableGeneratorMetaData);
Class cls = null;
if (elem != null)
{
cls = omfContext.getPluginManager().loadClass(elem.getExtension().getPlugin().getSymbolicName(),
elem.getAttribute("class-name"));
}
if (cls == null)
{
throw new JPOXException("Cannot create Poid Generator for strategy " + poidGeneratorName);
}
// Create the new PoidGenerator since the first time required (registers it with the PoidManager too)
generator = poidManager.createPoidGenerator(generatorNameKeyInManager, cls, props, this, null);
}
// Get the next value from the generator
Object oid = getStrategyValueForGenerator(generator, om);
if (mmd != null)
{
// replace the value of the id, but before convert the value to the field type if needed
Object convertedValue = TypeConversionHelper.convertTo(oid, mmd.getType());
if (convertedValue == null)
{
throw new JPOXException(LOCALISER.msg("038003", mmd.getFullFieldName(), oid)).setFatal();
}
oid = convertedValue;
}
if (JPOXLogger.POID.isDebugEnabled())