package de.jpaw.bonaparte.core;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.jpaw.bonaparte.pojos.meta.ClassDefinition;
public class BonaPortableFactoryById {
private static final Logger LOG = LoggerFactory.getLogger(BonaPortableFactoryById.class);
// Skip the next field and PathResolverTest may fail. Required to load the meta data classes in the correct order, required due to cyclic dependencies
// of static fields and their initialization.
public static Object UNUSED = ClassDefinition.class$MetaData();
// it will definitely fail if for example FieldDefinition is loaded before ClassDefinition
/** Stub to call to force initialization, in case no other initialization is required. */
public static void init() {
}
// the big factory lookup map
static private ConcurrentHashMap<Long,BonaPortableClass<?>> lookup = new ConcurrentHashMap<Long,BonaPortableClass<?>>(2048);
/** Adds a new class to the registry. Returns true if the class has been accepted and was not known before. */
public static boolean registerClass(BonaPortableClass<?> bclass) {
if (bclass.getMetaData().getIsAbstract() || bclass.getFactoryId() == 0 || bclass.getId() == 0)
return false; // not relevant
Long id = keyByIds(bclass.getFactoryId(), bclass.getId());
BonaPortableClass<?> existing = lookup.putIfAbsent(id, bclass);
if (existing != null) {
// might at least issue a warning...
if (existing != bclass) {
String errorMsg = "Attempt to register 2 classes by the same ID: " + existing.getPqon() + " and " + bclass.getPqon();
LOG.error(errorMsg);
throw new RuntimeException(errorMsg);
}
return false; // no new class
}
return true;
}
/** Composes the factoryId and the classId into a single Long, which is used as a key. */
public static Long keyByIds(int factoryId, int classId) {
return Long.valueOf((((long)factoryId) << 32) | classId);
}
/** Returns the factory Id portion of a composed long value. */
public static int factoryIdByKey(long key) {
return (int)(key >> 32);
}
/** Returns the class Id portion of a composed long value. */
public static int classIdByKey(long key) {
return (int)key;
}
/** Returns the BClass for the baked key. */
public static BonaPortableClass<?> getByKey(Long key) {
return lookup.get(key);
}
/** Returns the BClass for the ids. */
public static BonaPortableClass<?> getByIds(int factoryId, int classId) {
return getByKey(keyByIds(factoryId, classId));
}
}