You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/07/19 23:35:07 UTC
svn commit: r423615 [14/44] - in /incubator/openjpa/trunk: ./
openjpa-jdbc-5/ openjpa-jdbc-5/src/ openjpa-jdbc-5/src/main/
openjpa-jdbc-5/src/main/java/ openjpa-jdbc-5/src/main/java/org/
openjpa-jdbc-5/src/main/java/org/apache/ openjpa-jdbc-5/src/main/...
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,1135 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * 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.
+ */
+package org.apache.openjpa.jdbc.meta;
+
+import java.lang.reflect.Modifier;
+import java.sql.Types;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.meta.strats.BlobValueHandler;
+import org.apache.openjpa.jdbc.meta.strats.ByteArrayValueHandler;
+import org.apache.openjpa.jdbc.meta.strats.CharArrayStreamValueHandler;
+import org.apache.openjpa.jdbc.meta.strats.CharArrayValueHandler;
+import org.apache.openjpa.jdbc.meta.strats.ClassNameDiscriminatorStrategy;
+import org.apache.openjpa.jdbc.meta.strats.ClobValueHandler;
+import org.apache.openjpa.jdbc.meta.strats.EmbedFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.EmbeddedClassStrategy;
+import org.apache.openjpa.jdbc.meta.strats.FlatClassStrategy;
+import org.apache.openjpa.jdbc.meta.strats.FullClassStrategy;
+import org.apache.openjpa.jdbc.meta.strats.HandlerFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.ImmutableValueHandler;
+import org.apache.openjpa.jdbc.meta.strats.MaxEmbeddedBlobFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.MaxEmbeddedByteArrayFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.MaxEmbeddedCharArrayFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.MaxEmbeddedClobFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
+import org.apache.openjpa.jdbc.meta.strats.NoneDiscriminatorStrategy;
+import org.apache.openjpa.jdbc.meta.strats.NoneFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.NoneVersionStrategy;
+import org.apache.openjpa.jdbc.meta.strats.NumberVersionStrategy;
+import org.apache.openjpa.jdbc.meta.strats.ObjectIdClassStrategy;
+import org.apache.openjpa.jdbc.meta.strats.ObjectIdValueHandler;
+import org.apache.openjpa.jdbc.meta.strats.PrimitiveFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.RelationCollectionInverseKeyFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.RelationCollectionTableFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.RelationFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.RelationMapInverseKeyFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.RelationMapTableFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.StateComparisonVersionStrategy;
+import org.apache.openjpa.jdbc.meta.strats.StringFieldStrategy;
+import org.apache.openjpa.jdbc.meta.strats.SubclassJoinDiscriminatorStrategy;
+import org.apache.openjpa.jdbc.meta.strats.SuperclassDiscriminatorStrategy;
+import org.apache.openjpa.jdbc.meta.strats.SuperclassVersionStrategy;
+import org.apache.openjpa.jdbc.meta.strats.TimestampVersionStrategy;
+import org.apache.openjpa.jdbc.meta.strats.UntypedPCValueHandler;
+import org.apache.openjpa.jdbc.meta.strats.ValueMapDiscriminatorStrategy;
+import org.apache.openjpa.jdbc.meta.strats.VerticalClassStrategy;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.SchemaGroup;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.JoinSyntaxes;
+import org.apache.openjpa.lib.conf.Configurations;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.FieldMetaData;
+import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.meta.MetaDataFactory;
+import org.apache.openjpa.meta.MetaDataRepository;
+import org.apache.openjpa.meta.Order;
+import org.apache.openjpa.meta.SequenceMetaData;
+import org.apache.openjpa.meta.ValueMetaData;
+import org.apache.openjpa.util.MetaDataException;
+
+/**
+ * Repository of object/relational mapping information.
+ *
+ * @author Abe White
+ */
+public class MappingRepository
+ extends MetaDataRepository {
+
+ private static final Localizer _loc = Localizer.forPackage
+ (MappingRepository.class);
+ private static final Map _handlers = new HashMap();
+
+ static {
+ // register default value handlers
+ _handlers.put("java.lang.Enum",
+ "org.apache.openjpa.jdbc.meta.strats.EnumValueHandler");
+ }
+
+ private final MappingDefaults _defaults;
+ private final DBDictionary _dict;
+ private final Map _results = new HashMap(); // object->queryresultmapping
+ private SchemaGroup _schema = null;
+ private StrategyInstaller _installer = null;
+
+ /**
+ * Constructor; supply configuration.
+ */
+ public MappingRepository(JDBCConfiguration conf) {
+ this(conf, conf.newMetaDataFactoryInstance(),
+ conf.getMappingDefaultsInstance());
+ }
+
+ /**
+ * Constructor; supply configuration and mapping factory.
+ */
+ public MappingRepository(JDBCConfiguration conf, MetaDataFactory mdf,
+ MappingDefaults mapDefaults) {
+ super(conf, mdf);
+ setValidate(VALIDATE_MAPPING, true);
+ _defaults = mapDefaults;
+ _dict = conf.getDBDictionaryInstance();
+ }
+
+ /**
+ * Convenient access to dictionary for mappings.
+ */
+ public DBDictionary getDBDictionary() {
+ return _dict;
+ }
+
+ /**
+ * Mapping defaults.
+ */
+ public MappingDefaults getMappingDefaults() {
+ return _defaults;
+ }
+
+ /**
+ * Representation of the database schema.
+ */
+ public synchronized SchemaGroup getSchemaGroup() {
+ if (_schema == null)
+ _schema = ((JDBCConfiguration) getConfiguration()).
+ getSchemaFactoryInstance().readSchema();
+ return _schema;
+ }
+
+ /**
+ * Representation of the database schema.
+ */
+ public synchronized void setSchemaGroup(SchemaGroup schema) {
+ _schema = schema;
+ }
+
+ /**
+ * Installs mapping strategies on components.
+ */
+ public synchronized StrategyInstaller getStrategyInstaller() {
+ if (_installer == null)
+ _installer = new RuntimeStrategyInstaller(this);
+ return _installer;
+ }
+
+ /**
+ * Installs mapping strategies on components.
+ */
+ public synchronized void setStrategyInstaller(StrategyInstaller installer) {
+ _installer = installer;
+ }
+
+ /**
+ * Return the query result mapping for the given name.
+ */
+ public synchronized QueryResultMapping getQueryResultMapping(Class cls,
+ String name, ClassLoader envLoader, boolean mustExist) {
+ QueryResultMapping res = getQueryResultMappingInternal(cls, name,
+ envLoader);
+ if (res == null && mustExist)
+ throw new MetaDataException(_loc.get("no-query-res", cls, name));
+ return res;
+ }
+
+ /**
+ * Returned the query result mapping with the given name.
+ */
+ private QueryResultMapping getQueryResultMappingInternal(Class cls,
+ String name, ClassLoader envLoader) {
+ if (name == null)
+ return null;
+
+ // check cache
+ Object key = getQueryResultKey(cls, name);
+ QueryResultMapping res = (QueryResultMapping) _results.get(key);
+ if (res != null)
+ return res;
+
+ // get metadata for class, which will find results in metadata file
+ if (cls != null && getMetaData(cls, envLoader, false) != null) {
+ res = (QueryResultMapping) _results.get(key);
+ if (res != null)
+ return res;
+ }
+ if ((getSourceMode() & MODE_QUERY) == 0)
+ return null;
+
+ // not in cache; load
+ getMetaDataFactory().load(cls, MODE_QUERY, envLoader);
+ return (QueryResultMapping) _results.get(key);
+ }
+
+ /**
+ * Return all cached query result mappings.
+ */
+ public synchronized QueryResultMapping[] getQueryResultMappings() {
+ Collection values = _results.values();
+ return (QueryResultMapping[]) values.toArray
+ (new QueryResultMapping[values.size()]);
+ }
+
+ /**
+ * Return the cached query result mapping with the given name, or null if
+ * none.
+ */
+ public synchronized QueryResultMapping getCachedQueryResultMapping
+ (Class cls, String name) {
+ return (QueryResultMapping) _results.get(getQueryResultKey(cls, name));
+ }
+
+ /**
+ * Add a query result mapping.
+ */
+ public synchronized QueryResultMapping addQueryResultMapping(Class cls,
+ String name) {
+ QueryResultMapping res = new QueryResultMapping(name, this);
+ res.setDefiningType(cls);
+ _results.put(getQueryResultKey(res), res);
+ return res;
+ }
+
+ /**
+ * Remove a query result mapping.
+ */
+ public synchronized boolean removeQueryResultMapping
+ (QueryResultMapping res) {
+ return _results.remove(getQueryResultKey(res)) != null;
+ }
+
+ /**
+ * Remove a query result mapping.
+ */
+ public synchronized boolean removeQueryResultMapping(Class cls,
+ String name) {
+ if (name == null)
+ return false;
+ return _results.remove(getQueryResultKey(cls, name)) != null;
+ }
+
+ /**
+ * Return a unique key for the given mapping.
+ */
+ private static Object getQueryResultKey(QueryResultMapping res) {
+ if (res == null)
+ return null;
+ return getQueryResultKey(res.getDefiningType(), res.getName());
+ }
+
+ /**
+ * Return a unique key for the given class / name. The class argument
+ * can be null.
+ */
+ private static Object getQueryResultKey(Class cls, String name) {
+ return getQueryKey(cls, name);
+ }
+
+ public MetaDataRepository newInstance() {
+ return new MappingRepository((JDBCConfiguration) getConfiguration());
+ }
+
+ public MetaDataRepository newInstance(MetaDataFactory mdf,
+ MappingDefaults mapDefaults) {
+ return new MappingRepository
+ ((JDBCConfiguration) getConfiguration(), mdf, mapDefaults);
+ }
+
+ public ClassMapping getMapping(Class cls, ClassLoader envLoader,
+ boolean mustExist) {
+ return (ClassMapping) super.getMetaData(cls, envLoader, mustExist);
+ }
+
+ public ClassMapping[] getMappings() {
+ return (ClassMapping[]) super.getMetaDatas();
+ }
+
+ public ClassMapping getMapping(Object oid, ClassLoader envLoader,
+ boolean mustExist) {
+ return (ClassMapping) super.getMetaData(oid, envLoader, mustExist);
+ }
+
+ public ClassMapping[] getImplementorMappings(Class cls,
+ ClassLoader envLoader, boolean mustExist) {
+ return (ClassMapping[]) super.getImplementorMetaDatas(cls, envLoader,
+ mustExist);
+ }
+
+ public synchronized void clear() {
+ super.clear();
+ _schema = null;
+ _results.clear();
+ }
+
+ protected void prepareMapping(ClassMetaData meta) {
+ // make sure superclass resolved first; resolving superclass may have
+ // resolved this mapping
+ ClassMapping mapping = (ClassMapping) meta;
+ ClassMapping sup = mapping.getPCSuperclassMapping();
+ if (sup != null && (mapping.getResolve() & MODE_MAPPING) != 0)
+ return;
+
+ // define superclass fields after mapping class, so we can tell whether
+ // the class is mapped and needs to redefine abstract superclass fields
+ getStrategyInstaller().installStrategy(mapping);
+ mapping.defineSuperclassFields(mapping.
+ getJoinablePCSuperclassMapping() == null);
+
+ // resolve everything that doesn't involve relations to allow relation
+ // mappings to use the others as joinables
+ mapping.resolveNonRelationMappings();
+ }
+
+ protected ClassMetaData newClassMetaData(Class type) {
+ return new ClassMapping(type, this);
+ }
+
+ protected ClassMetaData[] newClassMetaDataArray(int length) {
+ return new ClassMapping[length];
+ }
+
+ protected FieldMetaData newFieldMetaData(String name, Class type,
+ ClassMetaData owner) {
+ return new FieldMapping(name, type, (ClassMapping) owner);
+ }
+
+ protected FieldMetaData[] newFieldMetaDataArray(int length) {
+ return new FieldMapping[length];
+ }
+
+ protected ClassMetaData newEmbeddedClassMetaData(ValueMetaData owner) {
+ return new ClassMapping(owner);
+ }
+
+ protected ValueMetaData newValueMetaData(FieldMetaData owner) {
+ return new ValueMappingImpl((FieldMapping) owner);
+ }
+
+ protected SequenceMetaData newSequenceMetaData(String name) {
+ return new SequenceMapping(name, this);
+ }
+
+ protected Order newValueOrder(FieldMetaData owner, boolean asc) {
+ return new JDBCValueOrder((FieldMapping) owner, asc);
+ }
+
+ protected Order newRelatedFieldOrder(FieldMetaData owner,
+ FieldMetaData rel, boolean asc) {
+ return new JDBCRelatedFieldOrder((FieldMapping) owner,
+ (FieldMapping) rel, asc);
+ }
+
+ protected Order[] newOrderArray(int size) {
+ return new JDBCOrder[size];
+ }
+
+ /**
+ * Create version metadata for the given class.
+ */
+ protected Version newVersion(ClassMapping cls) {
+ return new Version(cls);
+ }
+
+ /**
+ * Create discriminator metadata for the given class.
+ */
+ protected Discriminator newDiscriminator(ClassMapping cls) {
+ return new Discriminator(cls);
+ }
+
+ /**
+ * Create raw mapping info for the given instance.
+ */
+ protected ClassMappingInfo newMappingInfo(ClassMapping cls) {
+ ClassMappingInfo info = new ClassMappingInfo();
+ info.setClassName(cls.getDescribedType().getName());
+ return info;
+ }
+
+ /**
+ * Create raw mapping info for the given instance.
+ */
+ protected FieldMappingInfo newMappingInfo(FieldMapping fm) {
+ return new FieldMappingInfo();
+ }
+
+ /**
+ * Create raw mapping info for the given instance.
+ */
+ protected ValueMappingInfo newMappingInfo(ValueMapping vm) {
+ return new ValueMappingInfo();
+ }
+
+ /**
+ * Create raw mapping info for the given instance.
+ */
+ protected VersionMappingInfo newMappingInfo(Version version) {
+ return new VersionMappingInfo();
+ }
+
+ /**
+ * Create raw mapping info for the given instance.
+ */
+ protected DiscriminatorMappingInfo newMappingInfo(Discriminator disc) {
+ return new DiscriminatorMappingInfo();
+ }
+
+ /**
+ * Instantiate the given class' named strategy, or return null if no
+ * named strategy.
+ */
+ protected ClassStrategy namedStrategy(ClassMapping cls) {
+ String name = cls.getMappingInfo().getStrategy();
+ if (name == null)
+ return null;
+ return instantiateClassStrategy(name, cls);
+ }
+
+ /**
+ * Return the strategy for the given name.
+ */
+ protected ClassStrategy instantiateClassStrategy(String name,
+ ClassMapping cls) {
+ if (NoneClassStrategy.ALIAS.equals(name))
+ return NoneClassStrategy.getInstance();
+
+ String props = Configurations.getProperties(name);
+ name = Configurations.getClassName(name);
+ Class strat = null;
+
+ // base and vertical strategies use same alias; differentiate on join
+ if (FullClassStrategy.ALIAS.equals(name))
+ strat = FullClassStrategy.class;
+ else if (FlatClassStrategy.ALIAS.equals(name))
+ strat = FlatClassStrategy.class;
+ else if (VerticalClassStrategy.ALIAS.equals(name))
+ strat = VerticalClassStrategy.class;
+ try {
+ if (strat == null)
+ strat = JavaTypes.classForName(name, cls,
+ ClassStrategy.class.getClassLoader());
+ ClassStrategy strategy = (ClassStrategy) strat.newInstance();
+ Configurations.configureInstance(strategy, getConfiguration(),
+ props);
+ return strategy;
+ } catch (Exception e) {
+ throw new MetaDataException(_loc.get("bad-cls-strategy",
+ cls, name), e);
+ }
+ }
+
+ /**
+ * Instantiate the given field's named strategy, or return null if no
+ * named strategy.
+ */
+ protected FieldStrategy namedStrategy(FieldMapping field,
+ boolean installHandlers) {
+ String name = field.getMappingInfo().getStrategy();
+ if (name == null)
+ return null;
+
+ if (NoneFieldStrategy.ALIAS.equals(name))
+ return NoneFieldStrategy.getInstance();
+
+ String props = Configurations.getProperties(name);
+ name = Configurations.getClassName(name);
+ try {
+ Class c = JavaTypes.classForName(name, field,
+ FieldStrategy.class.getClassLoader());
+ if (FieldStrategy.class.isAssignableFrom(c)) {
+ FieldStrategy strat = (FieldStrategy) c.newInstance();
+ Configurations.configureInstance(strat, getConfiguration(),
+ props);
+ return strat;
+ }
+
+ // must be named handler
+ if (installHandlers) {
+ ValueHandler vh = (ValueHandler) c.newInstance();
+ Configurations.configureInstance(vh, getConfiguration(),
+ props);
+ field.setHandler(vh);
+ }
+ return new HandlerFieldStrategy();
+ } catch (Exception e) {
+ throw new MetaDataException(_loc.get("bad-field-strategy",
+ field, name), e);
+ }
+ }
+
+ /**
+ * Instantiate the given discriminator's named strategy, or return null
+ * if no named strategy.
+ */
+ protected DiscriminatorStrategy namedStrategy(Discriminator discrim) {
+ String name = discrim.getMappingInfo().getStrategy();
+ if (name == null)
+ return null;
+
+ // if there is a named strategy present, discard it if it matches
+ // the base strategy, so that we won't create an independent instance
+ ClassMapping cls = discrim.getClassMapping();
+ while (cls.getJoinablePCSuperclassMapping() != null)
+ cls = cls.getJoinablePCSuperclassMapping();
+ Discriminator base = cls.getDiscriminator();
+ if (base != discrim && base.getStrategy() != null
+ && name.equals(base.getStrategy().getAlias()))
+ return null;
+
+ return instantiateDiscriminatorStrategy(name, discrim);
+ }
+
+ /**
+ * Instantiate the given discriminator strategy.
+ */
+ protected DiscriminatorStrategy instantiateDiscriminatorStrategy
+ (String name, Discriminator discrim) {
+ if (NoneDiscriminatorStrategy.ALIAS.equals(name))
+ return NoneDiscriminatorStrategy.getInstance();
+
+ String props = Configurations.getProperties(name);
+ name = Configurations.getClassName(name);
+ Class strat = null;
+
+ if (ClassNameDiscriminatorStrategy.ALIAS.equals(name))
+ strat = ClassNameDiscriminatorStrategy.class;
+ else if (ValueMapDiscriminatorStrategy.ALIAS.equals(name))
+ strat = ValueMapDiscriminatorStrategy.class;
+ else if (SubclassJoinDiscriminatorStrategy.ALIAS.equals(name))
+ strat = SubclassJoinDiscriminatorStrategy.class;
+
+ try {
+ if (strat == null)
+ strat = JavaTypes.classForName(name,
+ discrim.getClassMapping(),
+ DiscriminatorStrategy.class.getClassLoader());
+ DiscriminatorStrategy strategy = (DiscriminatorStrategy)
+ strat.newInstance();
+ Configurations.configureInstance(strategy, getConfiguration(),
+ props);
+ return strategy;
+ } catch (Exception e) {
+ throw new MetaDataException(_loc.get("bad-discrim-strategy",
+ discrim.getClassMapping(), name), e);
+ }
+ }
+
+ /**
+ * Instantiate the given version's named strategy, or return null
+ * if no named strategy.
+ */
+ protected VersionStrategy namedStrategy(Version version) {
+ String name = version.getMappingInfo().getStrategy();
+ if (name == null)
+ return null;
+
+ // if there is a named strategy present, discard it if it matches
+ // the base strategy, so that we won't create an independent instance
+ ClassMapping cls = version.getClassMapping();
+ while (cls.getJoinablePCSuperclassMapping() != null)
+ cls = cls.getJoinablePCSuperclassMapping();
+ Version base = cls.getVersion();
+ if (base != version && base.getStrategy() != null
+ && name.equals(base.getStrategy().getAlias()))
+ return null;
+
+ return instantiateVersionStrategy(name, version);
+ }
+
+ /**
+ * Instantiate the given version strategy.
+ */
+ protected VersionStrategy instantiateVersionStrategy(String name,
+ Version version) {
+ if (NoneVersionStrategy.ALIAS.equals(name))
+ return NoneVersionStrategy.getInstance();
+
+ String props = Configurations.getProperties(name);
+ name = Configurations.getClassName(name);
+ Class strat = null;
+
+ if (NumberVersionStrategy.ALIAS.equals(name))
+ strat = NumberVersionStrategy.class;
+ else if (TimestampVersionStrategy.ALIAS.equals(name))
+ strat = TimestampVersionStrategy.class;
+ else if (StateComparisonVersionStrategy.ALIAS.equals(name))
+ strat = StateComparisonVersionStrategy.class;
+
+ try {
+ if (strat == null)
+ strat = JavaTypes.classForName(name,
+ version.getClassMapping(),
+ VersionStrategy.class.getClassLoader());
+ } catch (Exception e) {
+ throw new MetaDataException(_loc.get("bad-version-strategy",
+ version.getClassMapping(), name), e);
+ }
+
+ return instantiateVersionStrategy(strat, version, props);
+ }
+
+ protected VersionStrategy instantiateVersionStrategy(Class strat,
+ Version version, String props) {
+ try {
+ VersionStrategy strategy = (VersionStrategy) strat.newInstance();
+ Configurations.configureInstance(strategy, getConfiguration(),
+ props);
+ return strategy;
+ } catch (Exception e) {
+ throw new MetaDataException(_loc.get("bad-version-strategy",
+ version.getClassMapping(), strat + ""), e);
+ }
+ }
+
+ /**
+ * Determine the default strategy to use for the given class. Does
+ * not take into account the current strategy, if any.
+ */
+ protected ClassStrategy defaultStrategy(ClassMapping cls) {
+ return defaultStrategy(cls, getStrategyInstaller().isAdapting());
+ }
+
+ /**
+ * Determine the default strategy to use for the given class. Does
+ * not take into account the current strategy, if any.
+ */
+ protected ClassStrategy defaultStrategy(ClassMapping cls,
+ boolean adapting) {
+ ValueMapping embed = cls.getEmbeddingMapping();
+ if (embed != null) {
+ // superclass of embedded class isn't mapped
+ if (embed.getType() != cls.getDescribedType()
+ || embed.getFieldMapping().getStrategy()
+ == NoneFieldStrategy.getInstance())
+ return NoneClassStrategy.getInstance();
+ if (embed.getTypeCode() == JavaTypes.OID)
+ return new ObjectIdClassStrategy();
+ return new EmbeddedClassStrategy();
+ }
+ if (cls.isEmbeddedOnly())
+ return NoneClassStrategy.getInstance();
+
+ Object strat = _defaults.getStrategy(cls, adapting);
+ if (strat instanceof String)
+ return instantiateClassStrategy((String) strat, cls);
+ if (strat != null)
+ return (ClassStrategy) strat;
+
+ ClassMapping sup = cls.getMappedPCSuperclassMapping();
+ if (sup == null)
+ return new FullClassStrategy();
+
+ while (sup.getMappedPCSuperclassMapping() != null)
+ sup = sup.getMappedPCSuperclassMapping();
+ String subStrat = sup.getMappingInfo().getHierarchyStrategy();
+ if (subStrat != null)
+ return instantiateClassStrategy(subStrat, cls);
+
+ return new FlatClassStrategy();
+ }
+
+ /**
+ * Determine the default strategy to use for the given field. Does
+ * not take into account the named or current strategy, if any. If a
+ * non-null strategy is returned, this method may as a side effect install
+ * value handlers on the field's value mappings.
+ */
+ protected FieldStrategy defaultStrategy(FieldMapping field,
+ boolean installHandlers) {
+ return defaultStrategy(field, installHandlers,
+ getStrategyInstaller().isAdapting());
+ }
+
+ /**
+ * Determine the default strategy to use for the given field. Does
+ * not take into account the named or current strategy, if any. If a
+ * non-null strategy is returned, this method may as a side effect install
+ * value handlers on the field's value mappings.
+ */
+ protected FieldStrategy defaultStrategy(FieldMapping field,
+ boolean installHandlers, boolean adapting) {
+ // not persistent?
+ if (field.getManagement() != field.MANAGE_PERSISTENT
+ || field.isVersion())
+ return NoneFieldStrategy.getInstance();
+ if (field.getDefiningMapping().getStrategy() ==
+ NoneClassStrategy.getInstance())
+ return NoneFieldStrategy.getInstance();
+
+ // check for named handler first
+ ValueHandler handler = namedHandler(field);
+ if (handler != null) {
+ if (installHandlers)
+ field.setHandler(handler);
+ return new HandlerFieldStrategy();
+ }
+
+ if (field.isSerialized()) {
+ if (_dict.maxEmbeddedBlobSize != -1)
+ return new MaxEmbeddedBlobFieldStrategy();
+ } else {
+ // check for mapped strategy
+ Object strat = mappedStrategy(field, field.getType(), adapting);
+ if (strat instanceof FieldStrategy)
+ return (FieldStrategy) strat;
+ if (strat != null) {
+ if (installHandlers)
+ field.setHandler((ValueHandler) strat);
+ return new HandlerFieldStrategy();
+ }
+ }
+
+ // check for known field strategies
+ if (!field.isSerialized() && (field.getType() == byte[].class
+ || field.getType() == Byte[].class)) {
+ if (_dict.maxEmbeddedBlobSize != -1)
+ return new MaxEmbeddedByteArrayFieldStrategy();
+ } else if (!field.isSerialized()
+ && (field.getType() == char[].class
+ || field.getType() == Character[].class)) {
+ if (_dict.maxEmbeddedClobSize != -1 && isClob(field, false))
+ return new MaxEmbeddedCharArrayFieldStrategy();
+ } else if (!field.isSerialized()) {
+ FieldStrategy strat = defaultTypeStrategy(field, installHandlers,
+ adapting);
+ if (strat != null)
+ return strat;
+ }
+
+ // check for default handler
+ handler = defaultHandler(field, adapting);
+ if (handler != null) {
+ if (installHandlers)
+ field.setHandler(handler);
+ return new HandlerFieldStrategy();
+ }
+
+ // default to blob
+ if (installHandlers) {
+ if (getLog().isWarnEnabled())
+ getLog().warn(_loc.get("no-field-strategy", field));
+ field.setSerialized(true);
+ }
+ if (_dict.maxEmbeddedBlobSize == -1) {
+ if (installHandlers)
+ field.setHandler(BlobValueHandler.getInstance());
+ return new HandlerFieldStrategy();
+ }
+ return new MaxEmbeddedBlobFieldStrategy();
+ }
+
+ /**
+ * Return the built-in strategy for the field's type, or null if none.
+ */
+ protected FieldStrategy defaultTypeStrategy(FieldMapping field,
+ boolean installHandlers, boolean adapting) {
+ switch (field.getTypeCode()) {
+ case JavaTypes.BOOLEAN:
+ case JavaTypes.BYTE:
+ case JavaTypes.CHAR:
+ case JavaTypes.DOUBLE:
+ case JavaTypes.FLOAT:
+ case JavaTypes.INT:
+ case JavaTypes.LONG:
+ case JavaTypes.SHORT:
+ return new PrimitiveFieldStrategy();
+ case JavaTypes.STRING:
+ if (!isClob(field, false))
+ return new StringFieldStrategy();
+ if (_dict.maxEmbeddedClobSize != -1)
+ return new MaxEmbeddedClobFieldStrategy();
+ break;
+ case JavaTypes.PC:
+ if (field.isEmbeddedPC())
+ return new EmbedFieldStrategy();
+ if (field.getTypeMapping().isMapped()
+ || !useUntypedPCHandler(field))
+ return new RelationFieldStrategy();
+ break;
+ case JavaTypes.ARRAY:
+ case JavaTypes.COLLECTION:
+ ValueMapping elem = field.getElementMapping();
+ if (elem.getTypeCode() == JavaTypes.PC
+ && !elem.isSerialized() && !elem.isEmbeddedPC()) {
+ if (useInverseKeyMapping(field))
+ return new RelationCollectionInverseKeyFieldStrategy();
+ return new RelationCollectionTableFieldStrategy();
+ }
+ break;
+ case JavaTypes.MAP:
+ ValueMapping key = field.getKeyMapping();
+ ValueMapping val = field.getElementMapping();
+ boolean krel = key.getTypeCode() == JavaTypes.PC
+ && !key.isSerialized() && !key.isEmbeddedPC();
+ boolean vrel = val.getTypeCode() == JavaTypes.PC
+ && !val.isSerialized() && !val.isEmbeddedPC();
+ if (!krel && vrel && key.getValueMappedBy() != null) {
+ if (useInverseKeyMapping(field))
+ return new RelationMapInverseKeyFieldStrategy();
+ return new RelationMapTableFieldStrategy();
+ }
+ break;
+ }
+ return null;
+ }
+
+ /**
+ * Use hints in mapping data to figure out whether the given relation
+ * field should use an inverse foreign key or an association table mapping.
+ */
+ private boolean useInverseKeyMapping(FieldMapping field) {
+ FieldMapping mapped = field.getMappedByMapping();
+ if (mapped != null) {
+ if (mapped.getTypeCode() == JavaTypes.PC)
+ return true;
+ if (mapped.getElement().getTypeCode() == JavaTypes.PC)
+ return false;
+ throw new MetaDataException(_loc.get("bad-mapped-by", field,
+ mapped));
+ }
+
+ // without a mapped-by, we have to look for clues as to the mapping.
+ // we assume that anything with element foreign key columns but no join
+ // columns or table uses an inverse foreign key, and anything else uses
+ // an association table
+ FieldMappingInfo info = field.getMappingInfo();
+ ValueMapping elem = field.getElementMapping();
+ return info.getTableName() == null && info.getColumns().isEmpty()
+ && !elem.getValueInfo().getColumns().isEmpty();
+ }
+
+ /**
+ * Check the given value against mapped strategies.
+ */
+ private Object mappedStrategy(ValueMapping val, Class type,
+ boolean adapting) {
+ if (type == null || type == Object.class)
+ return null;
+
+ Object strat = _defaults.getStrategy(val, type, adapting);
+ if (strat == null)
+ strat = _handlers.get(type.getName());
+
+ // recurse on superclass so that, for example, a registered handler
+ // for java.lang.Enum will work on all enums
+ if (strat == null)
+ return mappedStrategy(val, type.getSuperclass(), adapting);
+ if (!(strat instanceof String))
+ return strat;
+
+ String name = (String) strat;
+ if (NoneFieldStrategy.ALIAS.equals(name))
+ return NoneFieldStrategy.getInstance();
+
+ String props = Configurations.getProperties(name);
+ name = Configurations.getClassName(name);
+ try {
+ Object o = JavaTypes.classForName(name, val,
+ FieldStrategy.class.getClassLoader()).newInstance();
+ Configurations.configureInstance(o, getConfiguration(), props);
+ return o;
+ } catch (Exception e) {
+ throw new MetaDataException(_loc.get("bad-mapped-strategy",
+ val, name), e);
+ }
+ }
+
+ /**
+ * Instantiate the given value's named handler, or return null if no
+ * named handler.
+ */
+ protected ValueHandler namedHandler(ValueMapping val) {
+ String name = val.getValueInfo().getStrategy();
+ if (name == null)
+ return null;
+
+ String props = Configurations.getProperties(name);
+ name = Configurations.getClassName(name);
+ try {
+ Class c = JavaTypes.classForName(name, val,
+ ValueHandler.class.getClassLoader());
+ if (ValueHandler.class.isAssignableFrom(c)) {
+ ValueHandler vh = (ValueHandler) c.newInstance();
+ Configurations.configureInstance(vh, getConfiguration(),
+ props);
+ return vh;
+ }
+ return null; // named field strategy
+ } catch (Exception e) {
+ throw new MetaDataException(_loc.get("bad-value-handler",
+ val, name), e);
+ }
+ }
+
+ /**
+ * Determine the default handler to use for the given value. Does
+ * not take into account the named handler, if any.
+ */
+ protected ValueHandler defaultHandler(ValueMapping val) {
+ return defaultHandler(val, getStrategyInstaller().isAdapting());
+ }
+
+ /**
+ * Determine the default handler to use for the given value. Does
+ * not take into account the named handler, if any.
+ */
+ protected ValueHandler defaultHandler(ValueMapping val, boolean adapting) {
+ if (val.isSerialized()) {
+ if (_dict.maxEmbeddedBlobSize != -1)
+ warnMaxEmbedded(val, _dict.maxEmbeddedBlobSize);
+ return BlobValueHandler.getInstance();
+ }
+
+ Object handler = mappedStrategy(val, val.getType(), adapting);
+ if (handler instanceof ValueHandler)
+ return (ValueHandler) handler;
+
+ if (val.getType() == byte[].class) {
+ if (_dict.maxEmbeddedBlobSize != -1)
+ warnMaxEmbedded(val, _dict.maxEmbeddedBlobSize);
+ return ByteArrayValueHandler.getInstance();
+ }
+ if (val.getType() == char[].class
+ || val.getType() == Character[].class) {
+ if (isClob(val, true))
+ return CharArrayStreamValueHandler.getInstance();
+ return CharArrayValueHandler.getInstance();
+ }
+
+ switch (val.getTypeCode()) {
+ case JavaTypes.BOOLEAN:
+ case JavaTypes.BYTE:
+ case JavaTypes.CHAR:
+ case JavaTypes.DOUBLE:
+ case JavaTypes.FLOAT:
+ case JavaTypes.INT:
+ case JavaTypes.LONG:
+ case JavaTypes.SHORT:
+ case JavaTypes.BOOLEAN_OBJ:
+ case JavaTypes.BYTE_OBJ:
+ case JavaTypes.CHAR_OBJ:
+ case JavaTypes.DOUBLE_OBJ:
+ case JavaTypes.FLOAT_OBJ:
+ case JavaTypes.INT_OBJ:
+ case JavaTypes.LONG_OBJ:
+ case JavaTypes.SHORT_OBJ:
+ case JavaTypes.BIGINTEGER:
+ case JavaTypes.BIGDECIMAL:
+ case JavaTypes.NUMBER:
+ case JavaTypes.DATE:
+ case JavaTypes.CALENDAR:
+ case JavaTypes.LOCALE:
+ return ImmutableValueHandler.getInstance();
+ case JavaTypes.STRING:
+ if (isClob(val, true))
+ return ClobValueHandler.getInstance();
+ return ImmutableValueHandler.getInstance();
+ case JavaTypes.PC:
+ if (!val.getTypeMapping().isMapped()
+ && useUntypedPCHandler(val))
+ return UntypedPCValueHandler.getInstance();
+ break;
+ case JavaTypes.PC_UNTYPED:
+ return UntypedPCValueHandler.getInstance();
+ case JavaTypes.OID:
+ return new ObjectIdValueHandler();
+ }
+ return null;
+ }
+
+ /**
+ * Return true if we should use the generic untyped PC handler for the
+ * given unmapped relation.
+ */
+ private boolean useUntypedPCHandler(ValueMapping val) {
+ ClassMapping rel = val.getTypeMapping();
+ return rel.getIdentityType() == ClassMapping.ID_UNKNOWN
+ || (rel.getIdentityType() == ClassMapping.ID_APPLICATION
+ && (rel.getPrimaryKeyFields().length == 0
+ || (!rel.isOpenJPAIdentity() && Modifier.isAbstract
+ (rel.getObjectIdType().getModifiers()))));
+ }
+
+ /**
+ * Checks for hints as to whether the given column is a CLOB.
+ */
+ private boolean isClob(ValueMapping val, boolean warn) {
+ List cols = val.getValueInfo().getColumns();
+ if (cols.size() != 1)
+ return false;
+
+ Column col = (Column) cols.get(0);
+ if (col.getSize() != -1 && col.getType() != Types.CLOB)
+ return false;
+
+ if (_dict.getPreferredType(Types.CLOB) != Types.CLOB)
+ return false;
+
+ if (warn && _dict.maxEmbeddedClobSize != -1)
+ warnMaxEmbedded(val, _dict.maxEmbeddedClobSize);
+ return true;
+ }
+
+ /**
+ * Warn that the given value is being mapped to a handler that will not
+ * be able to store large lobs.
+ */
+ private void warnMaxEmbedded(ValueMapping val, int size) {
+ if (getLog().isWarnEnabled())
+ getLog().warn(_loc.get("max-embed-lob", val,
+ String.valueOf(size)));
+ }
+
+ /**
+ * Determine the default strategy to use for the given discriminator.
+ * Does not take into account the current strategy, if any.
+ */
+ protected DiscriminatorStrategy defaultStrategy(Discriminator discrim) {
+ return defaultStrategy(discrim, getStrategyInstaller().isAdapting());
+ }
+
+ /**
+ * Determine the default strategy to use for the given discriminator.
+ * Does not take into account the current strategy, if any.
+ */
+ protected DiscriminatorStrategy defaultStrategy(Discriminator discrim,
+ boolean adapting) {
+ ClassMapping cls = discrim.getClassMapping();
+ if (cls.getEmbeddingMetaData() != null)
+ return NoneDiscriminatorStrategy.getInstance();
+ if (cls.getJoinablePCSuperclassMapping() == null
+ && (cls.getStrategy() == NoneClassStrategy.getInstance()
+ || Modifier.isFinal(discrim.getClassMapping().getDescribedType().
+ getModifiers())))
+ return NoneDiscriminatorStrategy.getInstance();
+
+ Object strat = _defaults.getStrategy(discrim, adapting);
+ if (strat instanceof String)
+ return instantiateDiscriminatorStrategy((String) strat, discrim);
+ if (strat != null)
+ return (DiscriminatorStrategy) strat;
+
+ if (cls.getJoinablePCSuperclassMapping() != null)
+ return new SuperclassDiscriminatorStrategy();
+ if (discrim.getMappingInfo().getValue() != null)
+ return new ValueMapDiscriminatorStrategy();
+ if (cls.getMappedPCSuperclassMapping() != null)
+ return NoneDiscriminatorStrategy.getInstance();
+ if (adapting || _defaults.defaultMissingInfo())
+ return new ClassNameDiscriminatorStrategy();
+ DBDictionary dict = ((JDBCConfiguration) getConfiguration()).
+ getDBDictionaryInstance();
+ if (dict.joinSyntax == JoinSyntaxes.SYNTAX_TRADITIONAL)
+ return NoneDiscriminatorStrategy.getInstance();
+ return new SubclassJoinDiscriminatorStrategy();
+ }
+
+ /**
+ * Determine the default strategy to use for the given version.
+ * Does not take into account the current strategy, if any.
+ */
+ protected VersionStrategy defaultStrategy(Version version) {
+ return defaultStrategy(version, getStrategyInstaller().isAdapting());
+ }
+
+ /**
+ * Determine the default strategy to use for the given version.
+ * Does not take into account the current strategy, if any.
+ */
+ protected VersionStrategy defaultStrategy(Version version,
+ boolean adapting) {
+ ClassMapping cls = version.getClassMapping();
+ if (cls.getEmbeddingMetaData() != null)
+ return NoneVersionStrategy.getInstance();
+ if (cls.getJoinablePCSuperclassMapping() == null
+ && cls.getStrategy() == NoneClassStrategy.getInstance())
+ return NoneVersionStrategy.getInstance();
+
+ Object strat = _defaults.getStrategy(version, adapting);
+ if (strat instanceof String)
+ return instantiateVersionStrategy((String) strat, version);
+ if (strat != null)
+ return (VersionStrategy) strat;
+
+ if (cls.getJoinablePCSuperclassMapping() != null)
+ return new SuperclassVersionStrategy();
+
+ FieldMapping vfield = version.getClassMapping().
+ getVersionFieldMapping();
+ if (vfield != null)
+ return defaultStrategy(version, vfield);
+ if (adapting || _defaults.defaultMissingInfo())
+ return new NumberVersionStrategy();
+ return NoneVersionStrategy.getInstance();
+ }
+
+ /**
+ * Return the default version strategy, given a version field.
+ */
+ protected VersionStrategy defaultStrategy(Version vers,
+ FieldMapping vfield) {
+ switch (vfield.getTypeCode()) {
+ case JavaTypes.DATE:
+ case JavaTypes.CALENDAR:
+ return new TimestampVersionStrategy();
+ case JavaTypes.BYTE:
+ case JavaTypes.INT:
+ case JavaTypes.LONG:
+ case JavaTypes.SHORT:
+ case JavaTypes.BYTE_OBJ:
+ case JavaTypes.INT_OBJ:
+ case JavaTypes.LONG_OBJ:
+ case JavaTypes.SHORT_OBJ:
+ case JavaTypes.NUMBER:
+ return new NumberVersionStrategy();
+ default:
+ return NoneVersionStrategy.getInstance();
+ }
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingStrategyInstaller.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingStrategyInstaller.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingStrategyInstaller.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingStrategyInstaller.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * 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.
+ */
+package org.apache.openjpa.jdbc.meta;
+
+/**
+ * Installer used during mapping that attempts to use the given mapping
+ * information (if any), and fails if it does not work.
+ *
+ * @author Abe White
+ * @nojavadoc
+ * @since 4.0
+ */
+public class MappingStrategyInstaller
+ extends StrategyInstaller {
+
+ /**
+ * Constructor; supply configuration.
+ */
+ public MappingStrategyInstaller(MappingRepository repos) {
+ super(repos);
+ }
+
+ public boolean isAdapting() {
+ return true;
+ }
+
+ public void installStrategy(ClassMapping cls) {
+ ClassStrategy strat = repos.namedStrategy(cls);
+ if (strat == null)
+ strat = repos.defaultStrategy(cls, true);
+ cls.setStrategy(strat, Boolean.TRUE);
+ cls.setSourceMode(cls.MODE_MAPPING, true);
+ }
+
+ public void installStrategy(FieldMapping field) {
+ FieldStrategy strategy = repos.namedStrategy(field, true);
+ if (strategy == null)
+ strategy = repos.defaultStrategy(field, true, true);
+ field.setStrategy(strategy, Boolean.TRUE);
+ }
+
+ public void installStrategy(Version version) {
+ VersionStrategy strat = repos.namedStrategy(version);
+ if (strat == null)
+ strat = repos.defaultStrategy(version, true);
+ version.setStrategy(strat, Boolean.TRUE);
+ }
+
+ public void installStrategy(Discriminator discrim) {
+ DiscriminatorStrategy strat = repos.namedStrategy(discrim);
+ if (strat == null)
+ strat = repos.defaultStrategy(discrim, true);
+ discrim.setStrategy(strat, Boolean.TRUE);
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingStrategyInstaller.java
------------------------------------------------------------------------------
svn:executable = *