Supports for interface query alias metadata

as well as refactoring persistence-aware metadata into non-persistent metadata
to support non-managed interfaces


git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@442363 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stephen Kim 2006-09-11 21:56:55 +00:00
parent da1961910b
commit 1defd23037
7 changed files with 152 additions and 37 deletions

View File

@ -660,7 +660,8 @@ public class MappingTool
ClassMapping mapping = repos.getMapping(cls, null, false);
if (mapping != null)
return mapping;
if (!validate || repos.getPersistenceAware(cls) != null)
if (!validate || cls.isInterface() ||
repos.getPersistenceAware(cls) != null)
return null;
throw new MetaDataException(_loc.get("no-meta", cls));
}

View File

@ -120,10 +120,11 @@ public class ExtentImpl
_broker.getClassLoader(), false);
ClassMetaData[] metas;
if (meta != null && (meta.isMapped() || (_subs
if (meta != null && (!_subs || !meta.isManagedInterface())
&& (meta.isMapped() || (_subs
&& meta.getMappedPCSubclassMetaDatas().length > 0)))
metas = new ClassMetaData[]{ meta };
else if (meta == null && _subs)
else if (_subs && (meta == null || meta.isManagedInterface()))
metas = repos.getImplementorMetaDatas(_type,
_broker.getClassLoader(), false);
else

View File

@ -657,11 +657,11 @@ public class QueryImpl
ClassMetaData[] metas;
if (_class == null || _storeQuery.supportsAbstractExecutors())
metas = new ClassMetaData[]{ meta };
else if (meta != null && (_subclasses || meta.isMapped()))
metas = new ClassMetaData[]{ meta };
else if (_subclasses)
else if (_subclasses && (meta == null || meta.isManagedInterface()))
metas = repos.getImplementorMetaDatas(_class,
_broker.getClassLoader(), true);
else if (meta != null && (_subclasses || meta.isMapped()))
metas = new ClassMetaData[]{ meta };
else
metas = StoreQuery.EMPTY_METAS;

View File

@ -142,6 +142,7 @@ public class ClassMetaData
private Boolean _embedded = null;
private Boolean _interface = null;
private Class _impl = null;
private Map _ifaceMap = new HashMap();
private int _identity = ID_UNKNOWN;
private int _idStrategy = ValueStrategies.NONE;
private int _accessType = ACCESS_UNKNOWN;
@ -694,6 +695,37 @@ public class ClassMetaData
public void setInterfaceImpl(Class impl) {
_impl = impl;
}
/**
* Alias properties from the given interface during queries to
* the local field.
*/
public void setInterfacePropertyAlias(Class iface, String orig,
String local) {
synchronized (_ifaceMap) {
Map fields = (Map) _ifaceMap.get(iface);
if (fields == null) {
fields = new HashMap();
_ifaceMap.put(iface, fields);
}
if (fields.containsKey(orig))
throw new MetaDataException(_loc.get("duplicate-iface-alias",
this, orig, local));
fields.put(orig, local);
}
}
/**
* Get local field alias for the given interface property.
*/
public String getInterfacePropertyAlias(Class iface, String orig) {
synchronized (_ifaceMap) {
Map fields = (Map) _ifaceMap.get(iface);
if (fields == null)
return null;
return (String) fields.get(orig);
}
}
/**
* Return the number of fields that use impl or intermediate data, in
@ -2194,6 +2226,10 @@ public class ClassMetaData
fg = addDeclaredFetchGroup(fgs[i].getName());
fg.copy(fgs[i]);
}
// copy iface re-mapping
_ifaceMap.clear();
_ifaceMap.putAll(meta._ifaceMap);
}
/**

View File

@ -83,8 +83,8 @@ public class MetaDataRepository
public static final int VALIDATE_RUNTIME = 8;
protected static final Class[] EMPTY_CLASSES = new Class[0];
protected static final PersistenceAwareClass[] EMPTY_PAWARE_CLASSES =
new PersistenceAwareClass[0];
protected static final NonPersistentMetaData[] EMPTY_NON_PERSISTENT =
new NonPersistentMetaData[0];
protected final ClassMetaData[] EMPTY_METAS;
protected final FieldMetaData[] EMPTY_FIELDS;
protected final Order[] EMPTY_ORDERS;
@ -110,6 +110,7 @@ public class MetaDataRepository
private final Map _seqs = new HashMap();
private final Map _aliases = Collections.synchronizedMap(new HashMap());
private final Map _pawares = Collections.synchronizedMap(new HashMap());
private final Map _nonMapped = Collections.synchronizedMap(new HashMap());
// map of classes to lists of their subclasses
private final Map _subs = Collections.synchronizedMap(new HashMap());
@ -886,6 +887,7 @@ public class MetaDataRepository
meta, impl));
_ifaces.put(meta.getDescribedType(), impl);
_metas.put(impl, meta);
addDeclaredInterfaceImpl(meta, meta.getDescribedType());
}
synchronized InterfaceImplGenerator getImplGenerator() {
@ -1034,56 +1036,112 @@ public class MetaDataRepository
}
/**
* Gets the persistence-aware class corresponding to the given class. Can
* be null, if the given class is not registered as persistence-aware with
* this receiver.
* Gets the metadata corresponding to the given persistence-aware class.
* Returns null, if the given class is not registered as
* persistence-aware.
*/
public PersistenceAwareClass getPersistenceAware(Class cls) {
return (PersistenceAwareClass)_pawares.get(cls);
public NonPersistentMetaData getPersistenceAware(Class cls) {
return (NonPersistentMetaData)_pawares.get(cls);
}
/**
* Gets all the registered persistence-aware classes.
* Gets all the metadatas for persistence-aware classes
*
* @return empty array if no class has been registered
* @return empty array if no class has been registered as pers-aware
*/
public PersistenceAwareClass[] getPersistenceAwares() {
public NonPersistentMetaData[] getPersistenceAwares() {
synchronized (_pawares) {
if (_pawares.isEmpty())
return EMPTY_PAWARE_CLASSES;
return (PersistenceAwareClass[])_pawares.values().toArray
(new PersistenceAwareClass[_pawares.size()]);
return EMPTY_NON_PERSISTENT;
return (NonPersistentMetaData[])_pawares.values().toArray
(new NonPersistentMetaData[_pawares.size()]);
}
}
/**
* Add the given class as persitence-aware.
* Add the given class as persistence-aware.
*
* @param cls non-null and must not alreaddy be added as persitence-capable
*/
public PersistenceAwareClass addPersistenceAware(Class cls) {
public NonPersistentMetaData addPersistenceAware(Class cls) {
if (cls == null)
return null;
synchronized(this) {
if (_pawares.containsKey(cls))
return (PersistenceAwareClass)_pawares.get(cls);
return (NonPersistentMetaData)_pawares.get(cls);
if (getCachedMetaData(cls) != null)
throw new MetaDataException(_loc.get("pc-and-aware", cls));
PersistenceAwareClass result = new PersistenceAwareClass(cls, this);
_pawares.put(cls, result);
return result;
NonPersistentMetaData meta = new NonPersistentMetaData(cls, this,
NonPersistentMetaData.TYPE_PERSISTENCE_AWARE);
_pawares.put(cls, meta);
return meta;
}
}
/**
* Remove a persitence-aware class from this receiver.
* Remove a persitence-aware class from the repository
*
* @return true if removed, false if not contained in this receiver
* @return true if removed
*/
public boolean removePersistenceAware(Class cls) {
return _pawares.remove(cls) != null;
}
/**
* Gets the metadata corresponding to the given non-mapped interface.
* Returns null, if the given interface is not registered as
* persistence-aware.
*/
public NonPersistentMetaData getNonMappedInterface(Class iface) {
return (NonPersistentMetaData)_nonMapped.get(iface);
}
/**
* Gets the corresponding metadatas for all registered, non-mapped
* interfaces
*
* @return empty array if no non-mapped interface has been registered.
*/
public NonPersistentMetaData[] getNonMappedInterfaces() {
synchronized (_nonMapped) {
if (_nonMapped.isEmpty())
return EMPTY_NON_PERSISTENT;
return (NonPersistentMetaData[])_nonMapped.values().toArray
(new NonPersistentMetaData[_nonMapped.size()]);
}
}
/**
* Add the given non-mapped interface to the repository.
*
* @param iface the non-mapped interface
*/
public NonPersistentMetaData addNonMappedInterface(Class iface) {
if (iface == null)
return null;
synchronized(this) {
if (!iface.isInterface())
throw new MetaDataException(_loc.get("not-non-mapped", iface));
if (_nonMapped.containsKey(iface))
return (NonPersistentMetaData)_nonMapped.get(iface);
if (getCachedMetaData(iface) != null)
throw new MetaDataException(_loc.get("non-mapped-pc", iface));
NonPersistentMetaData meta = new NonPersistentMetaData(iface, this,
NonPersistentMetaData.TYPE_NON_MAPPED_INTERFACE);
_nonMapped.put(iface, meta);
return meta;
}
}
/**
* Remove a non-mapped interface from the repository
*
* @return true if removed
*/
public boolean removeNonMappedInterface(Class iface) {
return _nonMapped.remove(iface) != null;
}
/**
* Clear the cache of parsed metadata. This method also clears the
* internal {@link MetaDataFactory MetaDataFactory}'s cache.
@ -1102,6 +1160,7 @@ public class MetaDataRepository
_factory.clear();
_aliases.clear();
_pawares.clear();
_nonMapped.clear();
}
/**
@ -1317,7 +1376,7 @@ public class MetaDataRepository
* Update the list of implementations of base classes and interfaces.
*/
private void updateImpls(Class cls, Class leastDerived, Class check) {
if (_factory.getDefaults().isDeclaredInterfacePersistent())
if (!_factory.getDefaults().isDeclaredInterfacePersistent())
return;
// allow users to query on common non-pc superclasses
Class sup = check.getSuperclass();

View File

@ -10,20 +10,25 @@ import org.apache.openjpa.lib.xml.Commentable;
*
* @author Pinaki Poddar
*/
public class PersistenceAwareClass
public class NonPersistentMetaData
implements Comparable, SourceTracker, Commentable, MetaDataContext {
public static final int TYPE_PERSISTENCE_AWARE = 1;
public static final int TYPE_NON_MAPPED_INTERFACE = 2;
private final MetaDataRepository _repos;
private final Class _class;
private final int _type;
private File _srcFile = null;
private int _srcType = SRC_OTHER;
private String[] _comments = null;
private int _listIndex = -1;
protected PersistenceAwareClass(Class cls, MetaDataRepository repos) {
protected NonPersistentMetaData(Class cls, MetaDataRepository repos,
int type) {
_repos = repos;
_class = cls;
_type = type;
}
/**
@ -39,6 +44,13 @@ public class PersistenceAwareClass
public Class getDescribedType() {
return _class;
}
/**
* The type of metadata.
*/
public int getType() {
return _type;
}
/**
* The index in which this class was listed in the metadata. Defaults to
@ -85,13 +97,14 @@ public class PersistenceAwareClass
_comments = comments;
}
public int compareTo(Object other) {
if (other == this)
public int compareTo(Object o) {
if (o == this)
return 0;
if (!(other instanceof PersistenceAwareClass))
if (!(o instanceof NonPersistentMetaData))
return 1;
return _class.getName().compareTo(((PersistenceAwareClass) other).
getDescribedType().getName());
NonPersistentMetaData other = (NonPersistentMetaData) o;
if (_type != other.getType())
return _type - other.getType();
return _class.getName().compareTo(other.getDescribedType().getName());
}
}

View File

@ -259,8 +259,13 @@ bad-fg-inclue: Attempt to include non-existent fetch group "{1}" in fetch \
group "{0}".
unknown-fg: Attempt to add fetch group "{0}" to type field "{1}" failed. \
This fetch group has not been defined.
duplicate-iface-alias: Cannot alias interface "{0}" property "{1}" to local \
field "{2}" as the property has already been aliased.
pc-and-aware: Attempt to register "{0}" as a persistence-aware class failed. \
The same class has been registered as persistence-capable already.=======
The same class has been registered as persistence-capable already.
not-non-mapped: Type "{0}" cannot be a non-mapped interface as the class is \
not an interface
non-mapped-pc: A non-mapped interface cannot also be mapped.
no-metadatafactory: No configuration properties were found. If you are \
using Ant, please see the <properties> or <propertiesFile> attributes \
of the task''s nested <config> element.