package org.exolab.castor.mapping.loader;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import org.exolab.castor.mapping.ClassDescriptor;
import org.exolab.castor.mapping.MappingException;
import org.exolab.castor.mapping.MappingLoader;
public abstract class AbstractMappingLoader2 implements MappingLoader {
/** The class loader to use. */
private ClassLoader _loader;
/** A flag indicating whether or not mappings can be redefined. */
private boolean _allowRedefinitions = false;
/** Has loadMapping been called? */
private boolean _loaded = false;
/**
* All class descriptors in the original order.
*/
private List<ClassDescriptor> _descriptors = new Vector<ClassDescriptor>();
/**
* All class descriptors added so far, keyed by class name.
*/
private Map<String, ClassDescriptor> _descriptorsByClassname =
new Hashtable<String, ClassDescriptor>();
public AbstractMappingLoader2(final ClassLoader loader) {
setClassLoader(loader);
}
public final void clear() {
_allowRedefinitions = false;
_loaded = false;
_descriptors.clear();
_descriptorsByClassname.clear();
}
/**
* @see org.exolab.castor.mapping.MappingLoader#setClassLoader(java.lang.ClassLoader)
* {@inheritDoc}
*/
public final void setClassLoader(final ClassLoader loader) {
if (loader == null) {
_loader = getClass().getClassLoader();
} else {
_loader = loader;
}
}
/**
* @see org.exolab.castor.mapping.MappingLoader#getClassLoader()
* {@inheritDoc}
*/
public final ClassLoader getClassLoader() {
return _loader;
}
/**
* Enables or disables the ability to allow the redefinition of class mappings.
*
* @param allow A boolean that when true enables redefinitions.
*/
public final void setAllowRedefinitions(boolean allow) {
_allowRedefinitions = allow;
}
/**
* Is the ability to allow redefinitions enabled or disabled?
*
* @return A boolean that when true enables redefinitions.
*/
public final boolean isAllowRedefinition() {
return _allowRedefinitions;
}
/**
* Adds a class descriptor. Will throw a mapping exception if a descriptor for this class
* already exists.
*
* @param descriptor The descriptor to add.
* @throws MappingException A descriptor for this class already exists.
*/
protected final void addDescriptor(final ClassDescriptor descriptor)
throws MappingException {
String classname = descriptor.getJavaClass().getName();
if (_descriptorsByClassname.containsKey(classname)) {
if (!isAllowRedefinition()) {
throw new MappingException("mapping.duplicateDescriptors", classname);
}
for (Iterator<ClassDescriptor> iterator = _descriptors.iterator(); iterator.hasNext(); ) {
ClassDescriptor d = iterator.next();
if (classname.equals(d.getJavaClass().getName())) {
iterator.remove();
}
}
_descriptors.add(descriptor);
} else {
_descriptors.add(descriptor);
}
//-- if we make it here...add class
_descriptorsByClassname.put(classname, descriptor);
}
/**
* @see org.exolab.castor.mapping.MappingLoader#getDescriptor(java.lang.String)
* {@inheritDoc}
*/
public final ClassDescriptor getDescriptor(final String classname) {
if (classname == null) { return null; }
return _descriptorsByClassname.get(classname);
}
// /**
// * @see org.exolab.castor.mapping.MappingLoader#descriptorIterator()
// * {@inheritDoc}
// */
// public final Iterator<ClassDescriptor> descriptorIterator() {
// return _descriptors.iterator();
// }
public final List<ClassDescriptor> getDescriptors() {
return _descriptors;
}
/**
* Return if mapping should be loaded with this MappingLoader instance or if another
* mapping have been loaded previously. If no mapping have been loaded previously
* then prevent any other mapping to be loaded later on.
*
* @return <code>true</code> if mapping should be loaded, <code>false</code>
* otherwise.
*/
protected final boolean loadMapping() {
if (_loaded) { return false; }
_loaded = true;
return true;
}
}