
org.datanucleus.metadata.MetaDataUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datanucleus-core Show documentation
Show all versions of datanucleus-core Show documentation
DataNucleus Core provides the primary components of a heterogenous Java persistence solution.
It supports persistence API's being layered on top of the core functionality.
Also includes the JDO API.
/**********************************************************************
Copyright (c) 2004 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Contributors:
...
**********************************************************************/
package org.datanucleus.metadata;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.ClassNameConstants;
import org.datanucleus.ExecutionContext;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.metadata.xml.MetaDataParser;
import org.datanucleus.plugin.PluginManager;
import org.datanucleus.util.ClassUtils;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.NucleusLogger;
import org.datanucleus.util.StringUtils;
/**
* Utilities needed for the processing of MetaData.
*/
public class MetaDataUtils
{
private static MetaDataUtils instance;
/**
* Gets an instance of MetaDataUtils
* @return a singleton instance of MetaDataUtils
*/
public static synchronized MetaDataUtils getInstance()
{
if (instance == null)
{
instance = new MetaDataUtils();
}
return instance;
}
/**
* Protected constructor to prevent outside instantiation
*/
protected MetaDataUtils()
{
}
/**
* Convenience method to determine if an array is storable in a single column as a byte
* array.
* @param fmd The field
* @return Whether this is an array that can be stored in a single column as non-serialised
*/
public boolean arrayStorableAsByteArrayInSingleColumn(AbstractMemberMetaData fmd)
{
if (fmd == null || !fmd.hasArray())
{
return false;
}
String arrayComponentType = fmd.getType().getComponentType().getName();
if (arrayComponentType.equals(ClassNameConstants.BOOLEAN) ||
arrayComponentType.equals(ClassNameConstants.BYTE) ||
arrayComponentType.equals(ClassNameConstants.CHAR) ||
arrayComponentType.equals(ClassNameConstants.DOUBLE) ||
arrayComponentType.equals(ClassNameConstants.FLOAT) ||
arrayComponentType.equals(ClassNameConstants.INT) ||
arrayComponentType.equals(ClassNameConstants.LONG) ||
arrayComponentType.equals(ClassNameConstants.SHORT) ||
arrayComponentType.equals(ClassNameConstants.JAVA_LANG_BOOLEAN) ||
arrayComponentType.equals(ClassNameConstants.JAVA_LANG_BYTE) ||
arrayComponentType.equals(ClassNameConstants.JAVA_LANG_CHARACTER) ||
arrayComponentType.equals(ClassNameConstants.JAVA_LANG_DOUBLE) ||
arrayComponentType.equals(ClassNameConstants.JAVA_LANG_FLOAT) ||
arrayComponentType.equals(ClassNameConstants.JAVA_LANG_INTEGER) ||
arrayComponentType.equals(ClassNameConstants.JAVA_LANG_LONG) ||
arrayComponentType.equals(ClassNameConstants.JAVA_LANG_SHORT) ||
arrayComponentType.equals(ClassNameConstants.JAVA_MATH_BIGDECIMAL) ||
arrayComponentType.equals(ClassNameConstants.JAVA_MATH_BIGINTEGER))
{
// These types can be stored as a single-column but setting the bytes only
return true;
}
// All other arrays must be serialised into a single column
return false;
}
/**
* Convenience method that returns if a field stores a persistable object.
* Doesn't care if the persistable object is serialised or embedded, just that it is persistable.
* @param fmd MetaData for the field
* @param ec ExecutionContext
* @return Whether it stores a persistable object
*/
public boolean storesPersistable(AbstractMemberMetaData fmd, ExecutionContext ec)
{
if (fmd == null)
{
return false;
}
ClassLoaderResolver clr = ec.getClassLoaderResolver();
MetaDataManager mmgr = ec.getMetaDataManager();
if (fmd.hasCollection())
{
if (fmd.getCollection().elementIsPersistent())
{
// Collection of PC elements
return true;
}
String elementType = fmd.getCollection().getElementType();
Class elementCls = clr.classForName(elementType);
if (mmgr.getMetaDataForImplementationOfReference(elementCls, null, clr) != null)
{
// Collection of reference type for FCOs
return true;
}
if (elementCls != null && ClassUtils.isReferenceType(elementCls))
{
try
{
String[] impls = getImplementationNamesForReferenceField(fmd, FieldRole.ROLE_COLLECTION_ELEMENT, clr, mmgr);
if (impls != null)
{
elementCls = clr.classForName(impls[0]);
if (ec.getApiAdapter().isPersistable(elementCls))
{
// Collection of reference type for FCOs
return true;
}
}
}
catch (NucleusUserException nue)
{
// No implementations found so not persistable
}
}
}
else if (fmd.hasMap())
{
if (fmd.getMap().keyIsPersistent())
{
// Map of PC keys
return true;
}
String keyType = fmd.getMap().getKeyType();
Class keyCls = clr.classForName(keyType);
if (mmgr.getMetaDataForImplementationOfReference(keyCls, null, clr) != null)
{
// Map with keys of reference type for FCOs
return true;
}
if (keyCls != null && ClassUtils.isReferenceType(keyCls))
{
try
{
String[] impls = getImplementationNamesForReferenceField(fmd, FieldRole.ROLE_MAP_KEY, clr, mmgr);
if (impls != null)
{
keyCls = clr.classForName(impls[0]);
if (ec.getApiAdapter().isPersistable(keyCls))
{
// Map with keys of reference type for FCOs
return true;
}
}
}
catch (NucleusUserException nue)
{
// No implementations found so not persistable
}
}
if (fmd.getMap().valueIsPersistent())
{
// Map of PC values
return true;
}
String valueType = fmd.getMap().getValueType();
Class valueCls = clr.classForName(valueType);
if (mmgr.getMetaDataForImplementationOfReference(valueCls, null, clr) != null)
{
// Map with values of reference type for FCOs
return true;
}
if (valueCls != null && ClassUtils.isReferenceType(valueCls))
{
try
{
String[] impls = getImplementationNamesForReferenceField(fmd, FieldRole.ROLE_MAP_VALUE, clr, mmgr);
if (impls != null)
{
valueCls = clr.classForName(impls[0]);
if (ec.getApiAdapter().isPersistable(valueCls))
{
// Map with values of reference type for FCOs
return true;
}
}
}
catch (NucleusUserException nue)
{
// No implementations found so not persistable
}
}
}
else if (fmd.hasArray())
{
if (mmgr.getApiAdapter().isPersistable(fmd.getType().getComponentType()))
{
// persistable[]
return true;
}
String elementType = fmd.getArray().getElementType();
Class elementCls = clr.classForName(elementType);
if (mmgr.getApiAdapter().isPersistable(elementCls))
{
// Array of reference type for FCOs
return true;
}
else if (mmgr.getMetaDataForImplementationOfReference(elementCls, null, clr) != null)
{
// Array of reference type for FCOs
return true;
}
else if (elementCls != null && ClassUtils.isReferenceType(elementCls))
{
try
{
String[] impls = getImplementationNamesForReferenceField(fmd, FieldRole.ROLE_ARRAY_ELEMENT, clr, mmgr);
if (impls != null)
{
elementCls = clr.classForName(impls[0]);
if (ec.getApiAdapter().isPersistable(elementCls))
{
// Array of reference type for FCOs
return true;
}
}
}
catch (NucleusUserException nue)
{
// No implementations found so not persistable
}
}
}
else
{
// 1-1 relation with PC
if (ClassUtils.isReferenceType(fmd.getType()) &&
mmgr.getMetaDataForImplementationOfReference(fmd.getType(), null, clr) != null)
{
// Reference type for an FCO
return true;
}
if (mmgr.getMetaDataForClass(fmd.getType(), clr) != null)
{
return true;
}
}
return false;
}
/**
* Convenience method that returns if a field stores a First-Class object (FCO).
* If a field object is serialised/embedded then doesn't count the object as FCO - use
* storesPersistable() if you want that not checking.
* @param fmd MetaData for the field
* @param ec ExecutionContext
* @return Whether it stores a FCO
*/
public boolean storesFCO(AbstractMemberMetaData fmd, ExecutionContext ec)
{
if (fmd == null)
{
return false;
}
ClassLoaderResolver clr = ec.getClassLoaderResolver();
MetaDataManager mgr = ec.getMetaDataManager();
if (fmd.isSerialized() || fmd.isEmbedded())
{
// Serialised or embedded fields have no FCO
return false;
}
else if (fmd.hasCollection() && !fmd.getCollection().isSerializedElement() && !fmd.getCollection().isEmbeddedElement())
{
if (fmd.getCollection().elementIsPersistent())
{
// Collection of PC elements
return true;
}
String elementType = fmd.getCollection().getElementType();
Class elementCls = clr.classForName(elementType);
if (elementCls != null && ClassUtils.isReferenceType(elementCls) &&
mgr.getMetaDataForImplementationOfReference(elementCls, null, clr) != null)
{
// Collection of reference type for FCOs
return true;
}
}
else if (fmd.hasMap())
{
if (fmd.getMap().keyIsPersistent() && !fmd.getMap().isEmbeddedKey() && !fmd.getMap().isSerializedKey())
{
// Map of PC keys
return true;
}
String keyType = fmd.getMap().getKeyType();
Class keyCls = clr.classForName(keyType);
if (keyCls != null && ClassUtils.isReferenceType(keyCls) &&
mgr.getMetaDataForImplementationOfReference(keyCls, null, clr) != null)
{
// Map with keys of reference type for FCOs
return true;
}
if (fmd.getMap().valueIsPersistent() && !fmd.getMap().isEmbeddedValue() && !fmd.getMap().isSerializedValue())
{
// Map of PC values
return true;
}
String valueType = fmd.getMap().getValueType();
Class valueCls = clr.classForName(valueType);
if (valueCls != null && ClassUtils.isReferenceType(valueCls) &&
mgr.getMetaDataForImplementationOfReference(valueCls, null, clr) != null)
{
// Map with values of reference type for FCOs
return true;
}
}
else if (fmd.hasArray() && !fmd.getArray().isSerializedElement() && !fmd.getArray().isEmbeddedElement())
{
if (mgr.getApiAdapter().isPersistable(fmd.getType().getComponentType()))
{
// persistable[]
return true;
}
}
else
{
// 1-1 relation with PC
if (ClassUtils.isReferenceType(fmd.getType()) &&
mgr.getMetaDataForImplementationOfReference(fmd.getType(), null, clr) != null)
{
// Reference type for an FCO
return true;
}
if (mgr.getMetaDataForClass(fmd.getType(), clr) != null)
{
return true;
}
}
return false;
}
/**
* Convenience method that splits a comma-separated list of values into a String array (removing whitespace).
* @param attr The attribute value
* @return The string components
*/
public String[] getValuesForCommaSeparatedAttribute(String attr)
{
if (attr == null || attr.length() == 0)
{
return null;
}
String[] values=StringUtils.split(attr, ",");
// Remove any whitespace around the values
if (values != null)
{
for (int i=0;i definition to get some types
String type = null;
if (fmd.hasCollection() && fieldRole == FieldRole.ROLE_COLLECTION_ELEMENT)
{
type = fmd.getCollection().getElementType();
}
else if (fmd.hasMap() && fieldRole == FieldRole.ROLE_MAP_KEY)
{
type = fmd.getMap().getKeyType();
}
else if (fmd.hasMap() && fieldRole == FieldRole.ROLE_MAP_VALUE)
{
type = fmd.getMap().getValueType();
}
else if (fmd.hasArray() && fieldRole == FieldRole.ROLE_ARRAY_ELEMENT)
{
type = fmd.getArray().getElementType();
if (type == null)
{
type = fmd.getType().getComponentType().getName();
}
}
else
{
type = fmd.getTypeName();
}
if (!type.equals(ClassNameConstants.Object))
{
implTypes = mmgr.getClassesImplementingInterface(type,clr);
}
if (implTypes == null)
{
// Generate error since no implementations available
throw new InvalidMemberMetaDataException("044161", fmd.getClassName(), fmd.getName(), type);
}
}
// Remove all duplicates from the list but retain the original ordering
int noOfDups = 0;
for (int i=0;i getMetaDataForCandidates(Class cls, boolean subclasses,
ExecutionContext ec)
{
ClassLoaderResolver clr = ec.getClassLoaderResolver();
List cmds = new ArrayList();
if (cls.isInterface())
{
// Query of interface(+subclasses)
AbstractClassMetaData icmd = ec.getMetaDataManager().getMetaDataForInterface(cls, clr);
if (icmd == null)
{
throw new NucleusUserException("Attempting to query an interface yet it is not declared 'persistent'." +
" Define the interface in metadata as being persistent to perform this operation, and make sure" +
" any implementations use the same identity and identity member(s)");
}
String[] impls = ec.getMetaDataManager().getClassesImplementingInterface(cls.getName(), clr);
for (int i=0;i 0)
{
for (int j=0;j 0)
{
for (int j=0;j metadataFiles = new HashSet();
Set classNames = new HashSet();
for (int i=0;i definition?
embedded = true;
}
else if (RelationType.isRelationMultiValued(relationType))
{
// Is this an embedded element/key/value?
if (mmd.hasCollection() && mmd.getElementMetaData() != null && mmd.getElementMetaData().getEmbeddedMetaData() != null)
{
// Embedded collection element
embedded = true;
}
else if (mmd.hasArray() && mmd.getElementMetaData() != null && mmd.getElementMetaData().getEmbeddedMetaData() != null)
{
// Embedded array element
embedded = true;
}
else if (mmd.hasMap() &&
((mmd.getKeyMetaData() != null && mmd.getKeyMetaData().getEmbeddedMetaData() != null) ||
(mmd.getValueMetaData() != null && mmd.getValueMetaData().getEmbeddedMetaData() != null)))
{
// Embedded map key/value
embedded = true;
}
}
else
{
// Observe "embeddedOnly" of the persisted type
if (RelationType.isRelationSingleValued(relationType))
{
AbstractClassMetaData mmdCmd = mmgr.getMetaDataForClass(mmd.getType(), clr);
if (mmdCmd != null && mmdCmd.isEmbeddedOnly())
{
embedded = true;
}
}
else if (RelationType.isRelationMultiValued(relationType))
{
// TODO Check this too
}
}
return embedded;
}
/**
* Convenience method to return if the specified member is embedded.
* Only applies to relation fields, since all other fields are always "embedded".
* TODO Likely ought to change last arg to List<AbstractMemberMetaData> for multilevel of embedded
* @param mmgr Metadata manager
* @param clr ClassLoader resolver
* @param mmd Metadata for the member we are interested in
* @param relationType Relation type of the member we are interested in
* @param ownerMmd Optional metadata for the owner member (for nested embeddeds only. Set to null if not relevant to the member in question).
* @return Whether the member is embedded
*/
public boolean isMemberEmbedded(MetaDataManager mmgr, ClassLoaderResolver clr, AbstractMemberMetaData mmd, RelationType relationType, AbstractMemberMetaData ownerMmd)
{
boolean embedded = false;
if (relationType != RelationType.NONE)
{
// Determine if this relation field is embedded
if (RelationType.isRelationSingleValued(relationType))
{
AbstractClassMetaData mmdCmd = mmgr.getMetaDataForClass(mmd.getType(), clr);
if (mmdCmd != null && mmdCmd.isEmbeddedOnly())
{
// Member type is embedded-only, so has to be embedded
return true;
}
}
if (mmd.isEmbedded() || mmd.getEmbeddedMetaData() != null)
{
// Does this field have @Embedded definition?
return true;
}
else if (RelationType.isRelationMultiValued(relationType))
{
// Is this an embedded element/key/value?
if (mmd.hasCollection() && mmd.getElementMetaData() != null && mmd.getElementMetaData().getEmbeddedMetaData() != null)
{
// Embedded collection element
return true;
}
else if (mmd.hasArray() && mmd.getElementMetaData() != null && mmd.getElementMetaData().getEmbeddedMetaData() != null)
{
// Embedded array element
return true;
}
else if (mmd.hasMap() &&
((mmd.getKeyMetaData() != null && mmd.getKeyMetaData().getEmbeddedMetaData() != null) ||
(mmd.getValueMetaData() != null && mmd.getValueMetaData().getEmbeddedMetaData() != null)))
{
// Embedded map key/value
return true;
}
}
if (RelationType.isRelationSingleValued(relationType) && ownerMmd != null)
{
// Maybe part of a nested embedded?
if (ownerMmd.hasCollection())
{
// This is a field of the element of the collection, so check for any metadata spec for it
EmbeddedMetaData embmd = ownerMmd.getElementMetaData().getEmbeddedMetaData();
if (embmd != null)
{
AbstractMemberMetaData[] embMmds = embmd.getMemberMetaData();
if (embMmds != null)
{
for (AbstractMemberMetaData embMmd : embMmds)
{
if (embMmd.getName().equals(mmd.getName()))
{
if (embMmd.isEmbedded() || embMmd.getEmbeddedMetaData() != null)
{
// Embedded Field is marked in nested embedded definition as embedded
return true;
}
}
}
}
}
}
else if (ownerMmd.getEmbeddedMetaData() != null)
{
// Is this a nested embedded (from JDO definition) with specification for this field?
AbstractMemberMetaData[] embMmds = ownerMmd.getEmbeddedMetaData().getMemberMetaData();
if (embMmds != null)
{
for (int i=0;i block?
return embMmds[i].getEmbeddedMetaData() != null;
}
}
}
}
}
}
return embedded;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy