0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one
0003: * or more contributor license agreements. See the NOTICE file
0004: * distributed with this work for additional information
0005: * regarding copyright ownership. The ASF licenses this file
0006: * to you under the Apache License, Version 2.0 (the
0007: * "License"); you may not use this file except in compliance
0008: * with the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing,
0013: * software distributed under the License is distributed on an
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015: * KIND, either express or implied. See the License for the
0016: * specific language governing permissions and limitations
0017: * under the License.
0018: */
0019: package org.apache.openjpa.jdbc.meta;
0020:
0021: import java.lang.reflect.Modifier;
0022: import java.security.AccessController;
0023: import java.security.PrivilegedActionException;
0024: import java.sql.Types;
0025: import java.util.Collection;
0026: import java.util.HashMap;
0027: import java.util.List;
0028: import java.util.Map;
0029:
0030: import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
0031: import org.apache.openjpa.jdbc.meta.strats.BlobValueHandler;
0032: import org.apache.openjpa.jdbc.meta.strats.ByteArrayValueHandler;
0033: import org.apache.openjpa.jdbc.meta.strats.CharArrayStreamValueHandler;
0034: import org.apache.openjpa.jdbc.meta.strats.CharArrayValueHandler;
0035: import org.apache.openjpa.jdbc.meta.strats.ClassNameDiscriminatorStrategy;
0036: import org.apache.openjpa.jdbc.meta.strats.ClobValueHandler;
0037: import org.apache.openjpa.jdbc.meta.strats.ElementEmbedValueHandler;
0038: import org.apache.openjpa.jdbc.meta.strats.EmbedFieldStrategy;
0039: import org.apache.openjpa.jdbc.meta.strats.EmbeddedClassStrategy;
0040: import org.apache.openjpa.jdbc.meta.strats.FlatClassStrategy;
0041: import org.apache.openjpa.jdbc.meta.strats.FullClassStrategy;
0042: import org.apache.openjpa.jdbc.meta.strats.HandlerCollectionTableFieldStrategy;
0043: import org.apache.openjpa.jdbc.meta.strats.HandlerFieldStrategy;
0044: import org.apache.openjpa.jdbc.meta.strats.HandlerHandlerMapTableFieldStrategy;
0045: import org.apache.openjpa.jdbc.meta.strats.HandlerRelationMapTableFieldStrategy;
0046: import org.apache.openjpa.jdbc.meta.strats.ImmutableValueHandler;
0047: import org.apache.openjpa.jdbc.meta.strats.LobFieldStrategy;
0048: import org.apache.openjpa.jdbc.meta.strats.MaxEmbeddedBlobFieldStrategy;
0049: import org.apache.openjpa.jdbc.meta.strats.MaxEmbeddedByteArrayFieldStrategy;
0050: import org.apache.openjpa.jdbc.meta.strats.MaxEmbeddedCharArrayFieldStrategy;
0051: import org.apache.openjpa.jdbc.meta.strats.MaxEmbeddedClobFieldStrategy;
0052: import org.apache.openjpa.jdbc.meta.strats.NanoPrecisionTimestampVersionStrategy;
0053: import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
0054: import org.apache.openjpa.jdbc.meta.strats.NoneDiscriminatorStrategy;
0055: import org.apache.openjpa.jdbc.meta.strats.NoneFieldStrategy;
0056: import org.apache.openjpa.jdbc.meta.strats.NoneVersionStrategy;
0057: import org.apache.openjpa.jdbc.meta.strats.NumberVersionStrategy;
0058: import org.apache.openjpa.jdbc.meta.strats.ObjectIdClassStrategy;
0059: import org.apache.openjpa.jdbc.meta.strats.ObjectIdValueHandler;
0060: import org.apache.openjpa.jdbc.meta.strats.PrimitiveFieldStrategy;
0061: import org.apache.openjpa.jdbc.meta.strats.RelationCollectionInverseKeyFieldStrategy;
0062: import org.apache.openjpa.jdbc.meta.strats.RelationCollectionTableFieldStrategy;
0063: import org.apache.openjpa.jdbc.meta.strats.RelationFieldStrategy;
0064: import org.apache.openjpa.jdbc.meta.strats.RelationHandlerMapTableFieldStrategy;
0065: import org.apache.openjpa.jdbc.meta.strats.RelationMapInverseKeyFieldStrategy;
0066: import org.apache.openjpa.jdbc.meta.strats.RelationMapTableFieldStrategy;
0067: import org.apache.openjpa.jdbc.meta.strats.RelationRelationMapTableFieldStrategy;
0068: import org.apache.openjpa.jdbc.meta.strats.StateComparisonVersionStrategy;
0069: import org.apache.openjpa.jdbc.meta.strats.StringFieldStrategy;
0070: import org.apache.openjpa.jdbc.meta.strats.SubclassJoinDiscriminatorStrategy;
0071: import org.apache.openjpa.jdbc.meta.strats.SuperclassDiscriminatorStrategy;
0072: import org.apache.openjpa.jdbc.meta.strats.SuperclassVersionStrategy;
0073: import org.apache.openjpa.jdbc.meta.strats.TimestampVersionStrategy;
0074: import org.apache.openjpa.jdbc.meta.strats.UntypedPCValueHandler;
0075: import org.apache.openjpa.jdbc.meta.strats.ValueMapDiscriminatorStrategy;
0076: import org.apache.openjpa.jdbc.meta.strats.VerticalClassStrategy;
0077: import org.apache.openjpa.jdbc.schema.Column;
0078: import org.apache.openjpa.jdbc.schema.SchemaGroup;
0079: import org.apache.openjpa.jdbc.sql.DBDictionary;
0080: import org.apache.openjpa.jdbc.sql.JoinSyntaxes;
0081: import org.apache.openjpa.lib.conf.Configurable;
0082: import org.apache.openjpa.lib.conf.Configurations;
0083: import org.apache.openjpa.lib.util.J2DoPrivHelper;
0084: import org.apache.openjpa.lib.util.JavaVersions;
0085: import org.apache.openjpa.lib.util.Localizer;
0086: import org.apache.openjpa.meta.ClassMetaData;
0087: import org.apache.openjpa.meta.FieldMetaData;
0088: import org.apache.openjpa.meta.JavaTypes;
0089: import org.apache.openjpa.meta.MetaDataRepository;
0090: import org.apache.openjpa.meta.Order;
0091: import org.apache.openjpa.meta.SequenceMetaData;
0092: import org.apache.openjpa.meta.ValueMetaData;
0093: import org.apache.openjpa.util.MetaDataException;
0094:
0095: /**
0096: * Repository of object/relational mapping information.
0097: *
0098: * @author Abe White
0099: */
0100: public class MappingRepository extends MetaDataRepository {
0101:
0102: private static final Localizer _loc = Localizer
0103: .forPackage(MappingRepository.class);
0104: private static final Map _handlers = new HashMap();
0105:
0106: static {
0107: // register default value handlers
0108: _handlers.put("java.lang.Enum",
0109: "org.apache.openjpa.jdbc.meta.strats.EnumValueHandler");
0110: }
0111:
0112: private transient DBDictionary _dict = null;
0113: private transient MappingDefaults _defaults = null;
0114:
0115: private Map _results = new HashMap(); // object->queryresultmapping
0116: private SchemaGroup _schema = null;
0117: private StrategyInstaller _installer = null;
0118:
0119: /**
0120: * Default constructor. Configure via
0121: * {@link org.apache.openjpa.lib.conf.Configurable}.
0122: */
0123: public MappingRepository() {
0124: setValidate(VALIDATE_MAPPING, true);
0125: }
0126:
0127: /**
0128: * Convenient access to dictionary for mappings.
0129: */
0130: public DBDictionary getDBDictionary() {
0131: return _dict;
0132: }
0133:
0134: /**
0135: * Mapping defaults.
0136: */
0137: public MappingDefaults getMappingDefaults() {
0138: return _defaults;
0139: }
0140:
0141: /**
0142: * Mapping default.
0143: */
0144: public void setMappingDefaults(MappingDefaults defaults) {
0145: _defaults = defaults;
0146: }
0147:
0148: /**
0149: * Representation of the database schema.
0150: */
0151: public synchronized SchemaGroup getSchemaGroup() {
0152: if (_schema == null)
0153: _schema = ((JDBCConfiguration) getConfiguration())
0154: .getSchemaFactoryInstance().readSchema();
0155: return _schema;
0156: }
0157:
0158: /**
0159: * Representation of the database schema.
0160: */
0161: public synchronized void setSchemaGroup(SchemaGroup schema) {
0162: _schema = schema;
0163: }
0164:
0165: /**
0166: * Installs mapping strategies on components.
0167: */
0168: public synchronized StrategyInstaller getStrategyInstaller() {
0169: if (_installer == null)
0170: _installer = new RuntimeStrategyInstaller(this );
0171: return _installer;
0172: }
0173:
0174: /**
0175: * Installs mapping strategies on components.
0176: */
0177: public synchronized void setStrategyInstaller(
0178: StrategyInstaller installer) {
0179: _installer = installer;
0180: }
0181:
0182: /**
0183: * Return the query result mapping for the given name.
0184: */
0185: public synchronized QueryResultMapping getQueryResultMapping(
0186: Class cls, String name, ClassLoader envLoader,
0187: boolean mustExist) {
0188: QueryResultMapping res = getQueryResultMappingInternal(cls,
0189: name, envLoader);
0190: if (res == null && mustExist)
0191: throw new MetaDataException(_loc.get("no-query-res", cls,
0192: name));
0193: return res;
0194: }
0195:
0196: /**
0197: * Returned the query result mapping with the given name.
0198: */
0199: private QueryResultMapping getQueryResultMappingInternal(Class cls,
0200: String name, ClassLoader envLoader) {
0201: if (name == null)
0202: return null;
0203:
0204: // check cache
0205: Object key = getQueryResultKey(cls, name);
0206: QueryResultMapping res = (QueryResultMapping) _results.get(key);
0207: if (res != null)
0208: return res;
0209:
0210: // get metadata for class, which will find results in metadata file
0211: if (cls != null && getMetaData(cls, envLoader, false) != null) {
0212: res = (QueryResultMapping) _results.get(key);
0213: if (res != null)
0214: return res;
0215: }
0216: if ((getSourceMode() & MODE_QUERY) == 0)
0217: return null;
0218:
0219: if (cls == null)
0220: cls = getMetaDataFactory().getResultSetMappingScope(name,
0221: envLoader);
0222: // not in cache; load
0223: getMetaDataFactory().load(cls, MODE_META | MODE_MAPPING,
0224: envLoader);
0225: return (QueryResultMapping) _results.get(key);
0226: }
0227:
0228: /**
0229: * Return all cached query result mappings.
0230: */
0231: public synchronized QueryResultMapping[] getQueryResultMappings() {
0232: Collection values = _results.values();
0233: return (QueryResultMapping[]) values
0234: .toArray(new QueryResultMapping[values.size()]);
0235: }
0236:
0237: /**
0238: * Return the cached query result mapping with the given name, or null if
0239: * none.
0240: */
0241: public synchronized QueryResultMapping getCachedQueryResultMapping(
0242: Class cls, String name) {
0243: return (QueryResultMapping) _results.get(getQueryResultKey(cls,
0244: name));
0245: }
0246:
0247: /**
0248: * Add a query result mapping.
0249: */
0250: public synchronized QueryResultMapping addQueryResultMapping(
0251: Class cls, String name) {
0252: QueryResultMapping res = new QueryResultMapping(name, this );
0253: res.setDefiningType(cls);
0254: _results.put(getQueryResultKey(res), res);
0255: return res;
0256: }
0257:
0258: /**
0259: * Remove a query result mapping.
0260: */
0261: public synchronized boolean removeQueryResultMapping(
0262: QueryResultMapping res) {
0263: return _results.remove(getQueryResultKey(res)) != null;
0264: }
0265:
0266: /**
0267: * Remove a query result mapping.
0268: */
0269: public synchronized boolean removeQueryResultMapping(Class cls,
0270: String name) {
0271: if (name == null)
0272: return false;
0273: return _results.remove(getQueryResultKey(cls, name)) != null;
0274: }
0275:
0276: /**
0277: * Return a unique key for the given mapping.
0278: */
0279: private static Object getQueryResultKey(QueryResultMapping res) {
0280: if (res == null)
0281: return null;
0282: return getQueryResultKey(res.getDefiningType(), res.getName());
0283: }
0284:
0285: /**
0286: * Return a unique key for the given class / name. The class argument
0287: * can be null.
0288: */
0289: private static Object getQueryResultKey(Class cls, String name) {
0290: return getQueryKey(cls, name);
0291: }
0292:
0293: public ClassMapping getMapping(Class cls, ClassLoader envLoader,
0294: boolean mustExist) {
0295: return (ClassMapping) super .getMetaData(cls, envLoader,
0296: mustExist);
0297: }
0298:
0299: public ClassMapping[] getMappings() {
0300: return (ClassMapping[]) super .getMetaDatas();
0301: }
0302:
0303: public ClassMapping getMapping(Object oid, ClassLoader envLoader,
0304: boolean mustExist) {
0305: return (ClassMapping) super .getMetaData(oid, envLoader,
0306: mustExist);
0307: }
0308:
0309: public ClassMapping[] getImplementorMappings(Class cls,
0310: ClassLoader envLoader, boolean mustExist) {
0311: return (ClassMapping[]) super .getImplementorMetaDatas(cls,
0312: envLoader, mustExist);
0313: }
0314:
0315: public synchronized void clear() {
0316: super .clear();
0317: _schema = null;
0318: _results.clear();
0319: }
0320:
0321: protected void prepareMapping(ClassMetaData meta) {
0322: // make sure superclass resolved first; resolving superclass may have
0323: // resolved this mapping
0324: ClassMapping mapping = (ClassMapping) meta;
0325: ClassMapping sup = mapping.getPCSuperclassMapping();
0326: if (sup != null && (mapping.getResolve() & MODE_MAPPING) != 0)
0327: return;
0328:
0329: // define superclass fields after mapping class, so we can tell whether
0330: // the class is mapped and needs to redefine abstract superclass fields
0331: getStrategyInstaller().installStrategy(mapping);
0332: mapping.defineSuperclassFields(mapping
0333: .getJoinablePCSuperclassMapping() == null);
0334:
0335: // resolve everything that doesn't involve relations to allow relation
0336: // mappings to use the others as joinables
0337: mapping.resolveNonRelationMappings();
0338: }
0339:
0340: protected ClassMetaData newClassMetaData(Class type) {
0341: return new ClassMapping(type, this );
0342: }
0343:
0344: protected ClassMetaData[] newClassMetaDataArray(int length) {
0345: return new ClassMapping[length];
0346: }
0347:
0348: protected FieldMetaData newFieldMetaData(String name, Class type,
0349: ClassMetaData owner) {
0350: return new FieldMapping(name, type, (ClassMapping) owner);
0351: }
0352:
0353: protected FieldMetaData[] newFieldMetaDataArray(int length) {
0354: return new FieldMapping[length];
0355: }
0356:
0357: protected ClassMetaData newEmbeddedClassMetaData(ValueMetaData owner) {
0358: return new ClassMapping(owner);
0359: }
0360:
0361: protected ValueMetaData newValueMetaData(FieldMetaData owner) {
0362: return new ValueMappingImpl((FieldMapping) owner);
0363: }
0364:
0365: protected SequenceMetaData newSequenceMetaData(String name) {
0366: return new SequenceMapping(name, this );
0367: }
0368:
0369: protected Order newValueOrder(FieldMetaData owner, boolean asc) {
0370: return new JDBCValueOrder((FieldMapping) owner, asc);
0371: }
0372:
0373: protected Order newRelatedFieldOrder(FieldMetaData owner,
0374: FieldMetaData rel, boolean asc) {
0375: return new JDBCRelatedFieldOrder((FieldMapping) owner,
0376: (FieldMapping) rel, asc);
0377: }
0378:
0379: protected Order[] newOrderArray(int size) {
0380: return new JDBCOrder[size];
0381: }
0382:
0383: /**
0384: * Create version metadata for the given class.
0385: */
0386: protected Version newVersion(ClassMapping cls) {
0387: return new Version(cls);
0388: }
0389:
0390: /**
0391: * Create discriminator metadata for the given class.
0392: */
0393: protected Discriminator newDiscriminator(ClassMapping cls) {
0394: return new Discriminator(cls);
0395: }
0396:
0397: /**
0398: * Create raw mapping info for the given instance.
0399: */
0400: protected ClassMappingInfo newMappingInfo(ClassMapping cls) {
0401: ClassMappingInfo info = new ClassMappingInfo();
0402: info.setClassName(cls.getDescribedType().getName());
0403: return info;
0404: }
0405:
0406: /**
0407: * Create raw mapping info for the given instance.
0408: */
0409: protected FieldMappingInfo newMappingInfo(FieldMapping fm) {
0410: return new FieldMappingInfo();
0411: }
0412:
0413: /**
0414: * Create raw mapping info for the given instance.
0415: */
0416: protected ValueMappingInfo newMappingInfo(ValueMapping vm) {
0417: return new ValueMappingInfo();
0418: }
0419:
0420: /**
0421: * Create raw mapping info for the given instance.
0422: */
0423: protected VersionMappingInfo newMappingInfo(Version version) {
0424: return new VersionMappingInfo();
0425: }
0426:
0427: /**
0428: * Create raw mapping info for the given instance.
0429: */
0430: protected DiscriminatorMappingInfo newMappingInfo(Discriminator disc) {
0431: return new DiscriminatorMappingInfo();
0432: }
0433:
0434: /**
0435: * Instantiate the given class' named strategy, or return null if no
0436: * named strategy.
0437: */
0438: protected ClassStrategy namedStrategy(ClassMapping cls) {
0439: String name = cls.getMappingInfo().getStrategy();
0440: return instantiateClassStrategy(name, cls);
0441: }
0442:
0443: /**
0444: * Return the strategy for the given name.
0445: */
0446: protected ClassStrategy instantiateClassStrategy(String name,
0447: ClassMapping cls) {
0448: if (name == null)
0449: return null;
0450: if (NoneClassStrategy.ALIAS.equals(name))
0451: return NoneClassStrategy.getInstance();
0452:
0453: String props = Configurations.getProperties(name);
0454: name = Configurations.getClassName(name);
0455: Class strat = null;
0456:
0457: // base and vertical strategies use same alias; differentiate on join
0458: if (FullClassStrategy.ALIAS.equals(name))
0459: strat = FullClassStrategy.class;
0460: else if (FlatClassStrategy.ALIAS.equals(name))
0461: strat = FlatClassStrategy.class;
0462: else if (VerticalClassStrategy.ALIAS.equals(name))
0463: strat = VerticalClassStrategy.class;
0464: try {
0465: if (strat == null)
0466: strat = JavaTypes
0467: .classForName(
0468: name,
0469: cls,
0470: (ClassLoader) AccessController
0471: .doPrivileged(J2DoPrivHelper
0472: .getClassLoaderAction(ClassStrategy.class)));
0473: ClassStrategy strategy = (ClassStrategy) AccessController
0474: .doPrivileged(J2DoPrivHelper
0475: .newInstanceAction(strat));
0476: Configurations.configureInstance(strategy,
0477: getConfiguration(), props);
0478: return strategy;
0479: } catch (Exception e) {
0480: if (e instanceof PrivilegedActionException)
0481: e = ((PrivilegedActionException) e).getException();
0482: throw new MetaDataException(_loc.get("bad-cls-strategy",
0483: cls, name), e);
0484: }
0485: }
0486:
0487: /**
0488: * Instantiate the given field's named strategy, or return null if no
0489: * named strategy.
0490: */
0491: protected FieldStrategy namedStrategy(FieldMapping field,
0492: boolean installHandlers) {
0493: String name = field.getMappingInfo().getStrategy();
0494: if (name == null)
0495: return null;
0496:
0497: if (NoneFieldStrategy.ALIAS.equals(name))
0498: return NoneFieldStrategy.getInstance();
0499:
0500: String props = Configurations.getProperties(name);
0501: name = Configurations.getClassName(name);
0502: try {
0503: Class c = JavaTypes
0504: .classForName(
0505: name,
0506: field,
0507: (ClassLoader) AccessController
0508: .doPrivileged(J2DoPrivHelper
0509: .getClassLoaderAction(FieldStrategy.class)));
0510: if (FieldStrategy.class.isAssignableFrom(c)) {
0511: FieldStrategy strat = (FieldStrategy) AccessController
0512: .doPrivileged(J2DoPrivHelper
0513: .newInstanceAction(c));
0514: Configurations.configureInstance(strat,
0515: getConfiguration(), props);
0516: return strat;
0517: }
0518:
0519: // must be named handler
0520: if (installHandlers) {
0521: ValueHandler vh = (ValueHandler) AccessController
0522: .doPrivileged(J2DoPrivHelper
0523: .newInstanceAction(c));
0524: Configurations.configureInstance(vh,
0525: getConfiguration(), props);
0526: field.setHandler(vh);
0527: }
0528: return new HandlerFieldStrategy();
0529: } catch (Exception e) {
0530: if (e instanceof PrivilegedActionException)
0531: e = ((PrivilegedActionException) e).getException();
0532: throw new MetaDataException(_loc.get("bad-field-strategy",
0533: field, name), e);
0534: }
0535: }
0536:
0537: /**
0538: * Instantiate the given discriminator's named strategy, or return null
0539: * if no named strategy.
0540: */
0541: protected DiscriminatorStrategy namedStrategy(Discriminator discrim) {
0542: String name = discrim.getMappingInfo().getStrategy();
0543: if (name == null)
0544: return null;
0545:
0546: // if there is a named strategy present, discard it if it matches
0547: // the base strategy, so that we won't create an independent instance
0548: ClassMapping cls = discrim.getClassMapping();
0549: while (cls.getJoinablePCSuperclassMapping() != null)
0550: cls = cls.getJoinablePCSuperclassMapping();
0551: Discriminator base = cls.getDiscriminator();
0552: if (base != discrim && base.getStrategy() != null
0553: && name.equals(base.getStrategy().getAlias()))
0554: return null;
0555:
0556: return instantiateDiscriminatorStrategy(name, discrim);
0557: }
0558:
0559: /**
0560: * Instantiate the given discriminator strategy.
0561: */
0562: protected DiscriminatorStrategy instantiateDiscriminatorStrategy(
0563: String name, Discriminator discrim) {
0564: if (NoneDiscriminatorStrategy.ALIAS.equals(name))
0565: return NoneDiscriminatorStrategy.getInstance();
0566:
0567: String props = Configurations.getProperties(name);
0568: name = Configurations.getClassName(name);
0569: Class strat = null;
0570:
0571: if (ClassNameDiscriminatorStrategy.ALIAS.equals(name))
0572: strat = ClassNameDiscriminatorStrategy.class;
0573: else if (ValueMapDiscriminatorStrategy.ALIAS.equals(name))
0574: strat = ValueMapDiscriminatorStrategy.class;
0575: else if (SubclassJoinDiscriminatorStrategy.ALIAS.equals(name))
0576: strat = SubclassJoinDiscriminatorStrategy.class;
0577:
0578: try {
0579: if (strat == null)
0580: strat = JavaTypes
0581: .classForName(
0582: name,
0583: discrim.getClassMapping(),
0584: (ClassLoader) AccessController
0585: .doPrivileged(J2DoPrivHelper
0586: .getClassLoaderAction(DiscriminatorStrategy.class)));
0587: DiscriminatorStrategy strategy = (DiscriminatorStrategy) AccessController
0588: .doPrivileged(J2DoPrivHelper
0589: .newInstanceAction(strat));
0590: Configurations.configureInstance(strategy,
0591: getConfiguration(), props);
0592: return strategy;
0593: } catch (Exception e) {
0594: if (e instanceof PrivilegedActionException)
0595: e = ((PrivilegedActionException) e).getException();
0596: throw new MetaDataException(_loc.get(
0597: "bad-discrim-strategy", discrim.getClassMapping(),
0598: name), e);
0599: }
0600: }
0601:
0602: /**
0603: * Instantiate the given version's named strategy, or return null
0604: * if no named strategy.
0605: */
0606: protected VersionStrategy namedStrategy(Version version) {
0607: String name = version.getMappingInfo().getStrategy();
0608: if (name == null)
0609: return null;
0610:
0611: // if there is a named strategy present, discard it if it matches
0612: // the base strategy, so that we won't create an independent instance
0613: ClassMapping cls = version.getClassMapping();
0614: while (cls.getJoinablePCSuperclassMapping() != null)
0615: cls = cls.getJoinablePCSuperclassMapping();
0616: Version base = cls.getVersion();
0617: if (base != version && base.getStrategy() != null
0618: && name.equals(base.getStrategy().getAlias()))
0619: return null;
0620:
0621: return instantiateVersionStrategy(name, version);
0622: }
0623:
0624: /**
0625: * Instantiate the given version strategy.
0626: */
0627: protected VersionStrategy instantiateVersionStrategy(String name,
0628: Version version) {
0629: if (NoneVersionStrategy.ALIAS.equals(name))
0630: return NoneVersionStrategy.getInstance();
0631:
0632: String props = Configurations.getProperties(name);
0633: name = Configurations.getClassName(name);
0634: Class strat = null;
0635:
0636: if (NumberVersionStrategy.ALIAS.equals(name))
0637: strat = NumberVersionStrategy.class;
0638: else if (TimestampVersionStrategy.ALIAS.equals(name))
0639: strat = TimestampVersionStrategy.class;
0640: else if (NanoPrecisionTimestampVersionStrategy.ALIAS
0641: .equals(name))
0642: strat = NanoPrecisionTimestampVersionStrategy.class;
0643: else if (StateComparisonVersionStrategy.ALIAS.equals(name))
0644: strat = StateComparisonVersionStrategy.class;
0645:
0646: try {
0647: if (strat == null)
0648: strat = JavaTypes
0649: .classForName(
0650: name,
0651: version.getClassMapping(),
0652: (ClassLoader) AccessController
0653: .doPrivileged(J2DoPrivHelper
0654: .getClassLoaderAction(VersionStrategy.class)));
0655: } catch (Exception e) {
0656: throw new MetaDataException(_loc.get(
0657: "bad-version-strategy", version.getClassMapping(),
0658: name), e);
0659: }
0660:
0661: return instantiateVersionStrategy(strat, version, props);
0662: }
0663:
0664: /**
0665: * Instantiate the given version strategy.
0666: */
0667: protected VersionStrategy instantiateVersionStrategy(Class strat,
0668: Version version, String props) {
0669: try {
0670: VersionStrategy strategy = (VersionStrategy) AccessController
0671: .doPrivileged(J2DoPrivHelper
0672: .newInstanceAction(strat));
0673: Configurations.configureInstance(strategy,
0674: getConfiguration(), props);
0675: return strategy;
0676: } catch (Exception e) {
0677: if (e instanceof PrivilegedActionException)
0678: e = ((PrivilegedActionException) e).getException();
0679: throw new MetaDataException(_loc.get(
0680: "bad-version-strategy", version.getClassMapping(),
0681: strat + ""), e);
0682: }
0683: }
0684:
0685: /**
0686: * Determine the default strategy to use for the given class. Does
0687: * not take into account the current strategy, if any.
0688: */
0689: protected ClassStrategy defaultStrategy(ClassMapping cls) {
0690: return defaultStrategy(cls, getStrategyInstaller().isAdapting());
0691: }
0692:
0693: /**
0694: * Determine the default strategy to use for the given class. Does
0695: * not take into account the current strategy, if any.
0696: */
0697: protected ClassStrategy defaultStrategy(ClassMapping cls,
0698: boolean adapting) {
0699: ValueMapping embed = cls.getEmbeddingMapping();
0700: if (embed != null) {
0701: // superclass of embedded class isn't mapped
0702: if (embed.getType() != cls.getDescribedType()
0703: || embed.getFieldMapping().getStrategy() == NoneFieldStrategy
0704: .getInstance())
0705: return NoneClassStrategy.getInstance();
0706: if (embed.getTypeCode() == JavaTypes.OID)
0707: return new ObjectIdClassStrategy();
0708: return new EmbeddedClassStrategy();
0709: }
0710: if (cls.isEmbeddedOnly())
0711: return NoneClassStrategy.getInstance();
0712:
0713: Object strat = _defaults.getStrategy(cls, adapting);
0714: if (strat instanceof String)
0715: return instantiateClassStrategy((String) strat, cls);
0716: if (strat != null)
0717: return (ClassStrategy) strat;
0718:
0719: // see if there is a declared hierarchy strategy
0720: ClassStrategy hstrat = null;
0721: for (ClassMapping base = cls; base != null && hstrat == null;) {
0722: hstrat = instantiateClassStrategy(base.getMappingInfo()
0723: .getHierarchyStrategy(), cls);
0724: base = base.getMappedPCSuperclassMapping();
0725: }
0726:
0727: // the full strategy as applied to a hierarchy is a
0728: // table-per-concrete-class strategy, so don't map abstract types
0729: if (hstrat instanceof FullClassStrategy
0730: && !cls.isManagedInterface()
0731: && Modifier.isAbstract(cls.getDescribedType()
0732: .getModifiers()))
0733: return NoneClassStrategy.getInstance();
0734:
0735: ClassMapping sup = cls.getMappedPCSuperclassMapping();
0736: if (sup == null)
0737: return new FullClassStrategy();
0738: if (hstrat != null)
0739: return hstrat;
0740: return new FlatClassStrategy();
0741: }
0742:
0743: /**
0744: * Determine the default strategy to use for the given field. Does
0745: * not take into account the named or current strategy, if any. If a
0746: * non-null strategy is returned, this method may as a side effect install
0747: * value handlers on the field's value mappings.
0748: */
0749: protected FieldStrategy defaultStrategy(FieldMapping field,
0750: boolean installHandlers) {
0751: return defaultStrategy(field, installHandlers,
0752: getStrategyInstaller().isAdapting());
0753: }
0754:
0755: /**
0756: * Determine the default strategy to use for the given field. Does
0757: * not take into account the named or current strategy, if any. If a
0758: * non-null strategy is returned, this method may as a side effect install
0759: * value handlers on the field's value mappings.
0760: */
0761: protected FieldStrategy defaultStrategy(FieldMapping field,
0762: boolean installHandlers, boolean adapting) {
0763: // not persistent?
0764: if (field.getManagement() != field.MANAGE_PERSISTENT
0765: || field.isVersion())
0766: return NoneFieldStrategy.getInstance();
0767: if (field.getDefiningMapping().getStrategy() == NoneClassStrategy
0768: .getInstance())
0769: return NoneFieldStrategy.getInstance();
0770:
0771: // check for named handler first
0772: ValueHandler handler = namedHandler(field);
0773: if (handler != null) {
0774: if (installHandlers)
0775: field.setHandler(handler);
0776: return new HandlerFieldStrategy();
0777: }
0778:
0779: if (field.isSerialized()) {
0780: if (_dict.maxEmbeddedBlobSize != -1)
0781: return new MaxEmbeddedBlobFieldStrategy();
0782: } else {
0783: // check for mapped strategy
0784: Object strat = mappedStrategy(field, field.getType(),
0785: adapting);
0786: if (strat instanceof FieldStrategy)
0787: return (FieldStrategy) strat;
0788: if (strat != null) {
0789: if (installHandlers)
0790: field.setHandler((ValueHandler) strat);
0791: return new HandlerFieldStrategy();
0792: }
0793: }
0794:
0795: // check for known field strategies
0796: if (!field.isSerialized()
0797: && (field.getType() == byte[].class || field.getType() == Byte[].class)) {
0798: if (_dict.maxEmbeddedBlobSize != -1)
0799: return new MaxEmbeddedByteArrayFieldStrategy();
0800: } else if (!field.isSerialized()
0801: && (field.getType() == char[].class || field.getType() == Character[].class)) {
0802: if (_dict.maxEmbeddedClobSize != -1 && isClob(field, false))
0803: return new MaxEmbeddedCharArrayFieldStrategy();
0804: } else if (!field.isSerialized()) {
0805: FieldStrategy strat = defaultTypeStrategy(field,
0806: installHandlers, adapting);
0807: if (strat != null)
0808: return strat;
0809: }
0810:
0811: // check for default handler
0812: handler = defaultHandler(field, adapting);
0813: if (handler != null) {
0814: if (installHandlers)
0815: field.setHandler(handler);
0816: return new HandlerFieldStrategy();
0817: }
0818:
0819: // default to blob
0820: if (installHandlers) {
0821: if (getLog().isWarnEnabled())
0822: getLog().warn(_loc.get("no-field-strategy", field));
0823: field.setSerialized(true);
0824: }
0825: if (_dict.maxEmbeddedBlobSize == -1) {
0826: if (installHandlers)
0827: field.setHandler(BlobValueHandler.getInstance());
0828: return new HandlerFieldStrategy();
0829: }
0830: return new MaxEmbeddedBlobFieldStrategy();
0831: }
0832:
0833: /**
0834: * Return the built-in strategy for the field's type, or null if none.
0835: */
0836: protected FieldStrategy defaultTypeStrategy(FieldMapping field,
0837: boolean installHandlers, boolean adapting) {
0838: switch (field.getTypeCode()) {
0839: case JavaTypes.BOOLEAN:
0840: case JavaTypes.BYTE:
0841: case JavaTypes.CHAR:
0842: case JavaTypes.DOUBLE:
0843: case JavaTypes.FLOAT:
0844: case JavaTypes.INT:
0845: case JavaTypes.LONG:
0846: case JavaTypes.SHORT:
0847: return new PrimitiveFieldStrategy();
0848: case JavaTypes.STRING:
0849: if (!isClob(field, false))
0850: return new StringFieldStrategy();
0851: if (_dict.maxEmbeddedClobSize != -1)
0852: return new MaxEmbeddedClobFieldStrategy();
0853: break;
0854: case JavaTypes.PC:
0855: if (field.isEmbeddedPC())
0856: return new EmbedFieldStrategy();
0857: if (field.getTypeMapping().isMapped()
0858: || !useUntypedPCHandler(field))
0859: return new RelationFieldStrategy();
0860: break;
0861: case JavaTypes.ARRAY:
0862: case JavaTypes.COLLECTION:
0863: ValueMapping elem = field.getElementMapping();
0864: ValueHandler ehandler = namedHandler(elem);
0865: if (ehandler == null)
0866: ehandler = defaultHandler(elem);
0867: if (ehandler != null)
0868: return handlerCollectionStrategy(field, ehandler,
0869: installHandlers);
0870: if (elem.getTypeCode() == JavaTypes.PC
0871: && !elem.isSerialized() && !elem.isEmbeddedPC()) {
0872: if (useInverseKeyMapping(field))
0873: return new RelationCollectionInverseKeyFieldStrategy();
0874: return new RelationCollectionTableFieldStrategy();
0875: }
0876: break;
0877: case JavaTypes.MAP:
0878: ValueMapping key = field.getKeyMapping();
0879: ValueHandler khandler = namedHandler(key);
0880: if (khandler == null)
0881: khandler = defaultHandler(key);
0882: ValueMapping val = field.getElementMapping();
0883: ValueHandler vhandler = namedHandler(val);
0884: if (vhandler == null)
0885: vhandler = defaultHandler(val);
0886: boolean krel = khandler == null
0887: && key.getTypeCode() == JavaTypes.PC
0888: && !key.isSerialized() && !key.isEmbeddedPC();
0889: boolean vrel = vhandler == null
0890: && val.getTypeCode() == JavaTypes.PC
0891: && !val.isSerialized() && !val.isEmbeddedPC();
0892: if (!krel && vrel && key.getValueMappedBy() != null) {
0893: if (useInverseKeyMapping(field))
0894: return new RelationMapInverseKeyFieldStrategy();
0895: return new RelationMapTableFieldStrategy();
0896: }
0897: if (!krel && khandler == null)
0898: break;
0899: if (!vrel && vhandler == null)
0900: break;
0901: return handlerMapStrategy(field, khandler, vhandler, krel,
0902: vrel, installHandlers);
0903: case JavaTypes.INPUT_STREAM:
0904: case JavaTypes.INPUT_READER:
0905: return new LobFieldStrategy();
0906: }
0907: return null;
0908: }
0909:
0910: /**
0911: * Return the collection strategy for the given element handler, or null
0912: * if none.
0913: */
0914: protected FieldStrategy handlerCollectionStrategy(
0915: FieldMapping field, ValueHandler ehandler,
0916: boolean installHandlers) {
0917: if (installHandlers)
0918: field.getElementMapping().setHandler(ehandler);
0919: return new HandlerCollectionTableFieldStrategy();
0920: }
0921:
0922: /**
0923: * Return the map strategy for the given key and value handlers / relations,
0924: * or null if none.
0925: */
0926: protected FieldStrategy handlerMapStrategy(FieldMapping field,
0927: ValueHandler khandler, ValueHandler vhandler, boolean krel,
0928: boolean vrel, boolean installHandlers) {
0929: if (installHandlers) {
0930: field.getKeyMapping().setHandler(khandler);
0931: field.getElementMapping().setHandler(vhandler);
0932: }
0933: if (!krel && !vrel)
0934: return new HandlerHandlerMapTableFieldStrategy();
0935: if (!krel && vrel)
0936: return new HandlerRelationMapTableFieldStrategy();
0937: if (krel && !vrel)
0938: return new RelationHandlerMapTableFieldStrategy();
0939: return new RelationRelationMapTableFieldStrategy();
0940: }
0941:
0942: /**
0943: * Use hints in mapping data to figure out whether the given relation
0944: * field should use an inverse foreign key or an association table mapping.
0945: */
0946: private boolean useInverseKeyMapping(FieldMapping field) {
0947: FieldMapping mapped = field.getMappedByMapping();
0948: if (mapped != null) {
0949: if (mapped.getTypeCode() == JavaTypes.PC)
0950: return true;
0951: if (mapped.getElement().getTypeCode() == JavaTypes.PC)
0952: return false;
0953: throw new MetaDataException(_loc.get("bad-mapped-by",
0954: field, mapped));
0955: }
0956:
0957: // without a mapped-by, we have to look for clues as to the mapping.
0958: // we assume that anything with element foreign key columns but no join
0959: // columns or table uses an inverse foreign key, and anything else uses
0960: // an association table
0961: FieldMappingInfo info = field.getMappingInfo();
0962: ValueMapping elem = field.getElementMapping();
0963: return info.getTableName() == null
0964: && info.getColumns().isEmpty()
0965: && !elem.getValueInfo().getColumns().isEmpty();
0966: }
0967:
0968: /**
0969: * Check the given value against mapped strategies.
0970: */
0971: private Object mappedStrategy(ValueMapping val, Class type,
0972: boolean adapting) {
0973: if (type == null || type == Object.class)
0974: return null;
0975:
0976: Object strat = _defaults.getStrategy(val, type, adapting);
0977: if (strat == null)
0978: strat = _handlers.get(type.getName());
0979:
0980: // recurse on superclass so that, for example, a registered handler
0981: // for java.lang.Enum will work on all enums
0982: if (strat == null)
0983: return mappedStrategy(val, type.getSuperclass(), adapting);
0984: if (!(strat instanceof String))
0985: return strat;
0986:
0987: String name = (String) strat;
0988: if (NoneFieldStrategy.ALIAS.equals(name))
0989: return NoneFieldStrategy.getInstance();
0990:
0991: String props = Configurations.getProperties(name);
0992: name = Configurations.getClassName(name);
0993: try {
0994: Class c = JavaTypes
0995: .classForName(
0996: name,
0997: val,
0998: (ClassLoader) AccessController
0999: .doPrivileged(J2DoPrivHelper
1000: .getClassLoaderAction(FieldStrategy.class)));
1001: Object o = AccessController.doPrivileged(J2DoPrivHelper
1002: .newInstanceAction(c));
1003: Configurations.configureInstance(o, getConfiguration(),
1004: props);
1005: return o;
1006: } catch (Exception e) {
1007: if (e instanceof PrivilegedActionException)
1008: e = ((PrivilegedActionException) e).getException();
1009: throw new MetaDataException(_loc.get("bad-mapped-strategy",
1010: val, name), e);
1011: }
1012: }
1013:
1014: /**
1015: * Instantiate the given value's named handler, or return null if no
1016: * named handler.
1017: */
1018: protected ValueHandler namedHandler(ValueMapping val) {
1019: String name = val.getValueInfo().getStrategy();
1020: if (name == null)
1021: return null;
1022:
1023: String props = Configurations.getProperties(name);
1024: name = Configurations.getClassName(name);
1025: try {
1026: Class c = JavaTypes
1027: .classForName(
1028: name,
1029: val,
1030: (ClassLoader) AccessController
1031: .doPrivileged(J2DoPrivHelper
1032: .getClassLoaderAction(ValueHandler.class)));
1033: if (ValueHandler.class.isAssignableFrom(c)) {
1034: ValueHandler vh = (ValueHandler) AccessController
1035: .doPrivileged(J2DoPrivHelper
1036: .newInstanceAction(c));
1037: Configurations.configureInstance(vh,
1038: getConfiguration(), props);
1039: return vh;
1040: }
1041: return null; // named field strategy
1042: } catch (Exception e) {
1043: if (e instanceof PrivilegedActionException)
1044: e = ((PrivilegedActionException) e).getException();
1045: throw new MetaDataException(_loc.get("bad-value-handler",
1046: val, name), e);
1047: }
1048: }
1049:
1050: /**
1051: * Determine the default handler to use for the given value. Does
1052: * not take into account the named handler, if any.
1053: */
1054: protected ValueHandler defaultHandler(ValueMapping val) {
1055: return defaultHandler(val, getStrategyInstaller().isAdapting());
1056: }
1057:
1058: /**
1059: * Determine the default handler to use for the given value. Does
1060: * not take into account the named handler, if any.
1061: */
1062: protected ValueHandler defaultHandler(ValueMapping val,
1063: boolean adapting) {
1064: if (val.isSerialized()) {
1065: if (_dict.maxEmbeddedBlobSize != -1)
1066: warnMaxEmbedded(val, _dict.maxEmbeddedBlobSize);
1067: return BlobValueHandler.getInstance();
1068: }
1069:
1070: Object handler = mappedStrategy(val, val.getType(), adapting);
1071: if (handler instanceof ValueHandler)
1072: return (ValueHandler) handler;
1073:
1074: if (val.getType() == byte[].class
1075: || val.getType() == Byte[].class) {
1076: if (_dict.maxEmbeddedBlobSize != -1)
1077: warnMaxEmbedded(val, _dict.maxEmbeddedBlobSize);
1078: return ByteArrayValueHandler.getInstance();
1079: }
1080: if (val.getType() == char[].class
1081: || val.getType() == Character[].class) {
1082: if (isClob(val, true))
1083: return CharArrayStreamValueHandler.getInstance();
1084: return CharArrayValueHandler.getInstance();
1085: }
1086:
1087: switch (val.getTypeCode()) {
1088: case JavaTypes.BOOLEAN:
1089: case JavaTypes.BYTE:
1090: case JavaTypes.CHAR:
1091: case JavaTypes.DOUBLE:
1092: case JavaTypes.FLOAT:
1093: case JavaTypes.INT:
1094: case JavaTypes.LONG:
1095: case JavaTypes.SHORT:
1096: case JavaTypes.BOOLEAN_OBJ:
1097: case JavaTypes.BYTE_OBJ:
1098: case JavaTypes.CHAR_OBJ:
1099: case JavaTypes.DOUBLE_OBJ:
1100: case JavaTypes.FLOAT_OBJ:
1101: case JavaTypes.INT_OBJ:
1102: case JavaTypes.LONG_OBJ:
1103: case JavaTypes.SHORT_OBJ:
1104: case JavaTypes.BIGINTEGER:
1105: case JavaTypes.BIGDECIMAL:
1106: case JavaTypes.NUMBER:
1107: case JavaTypes.DATE:
1108: case JavaTypes.CALENDAR:
1109: case JavaTypes.LOCALE:
1110: return ImmutableValueHandler.getInstance();
1111: case JavaTypes.STRING:
1112: if (isClob(val, true))
1113: return ClobValueHandler.getInstance();
1114: return ImmutableValueHandler.getInstance();
1115: case JavaTypes.PC:
1116: if (!val.getTypeMapping().isMapped()
1117: && useUntypedPCHandler(val))
1118: return UntypedPCValueHandler.getInstance();
1119: break;
1120: case JavaTypes.PC_UNTYPED:
1121: return UntypedPCValueHandler.getInstance();
1122: case JavaTypes.OID:
1123: return new ObjectIdValueHandler();
1124: }
1125: if (val.isEmbeddedPC())
1126: return new ElementEmbedValueHandler();
1127: return null;
1128: }
1129:
1130: /**
1131: * Return true if we should use the generic untyped PC handler for the
1132: * given unmapped relation.
1133: */
1134: private boolean useUntypedPCHandler(ValueMapping val) {
1135: ClassMapping rel = val.getTypeMapping();
1136: return rel.getIdentityType() == ClassMapping.ID_UNKNOWN
1137: || (rel.getIdentityType() == ClassMapping.ID_APPLICATION && (rel
1138: .getPrimaryKeyFields().length == 0 || (!rel
1139: .isOpenJPAIdentity() && Modifier.isAbstract(rel
1140: .getObjectIdType().getModifiers()))));
1141: }
1142:
1143: /**
1144: * Checks for hints as to whether the given column is a CLOB.
1145: */
1146: private boolean isClob(ValueMapping val, boolean warn) {
1147: List cols = val.getValueInfo().getColumns();
1148: if (cols.size() != 1)
1149: return false;
1150:
1151: Column col = (Column) cols.get(0);
1152: if (col.getSize() != -1 && col.getType() != Types.CLOB)
1153: return false;
1154:
1155: if (_dict.getPreferredType(Types.CLOB) != Types.CLOB)
1156: return false;
1157:
1158: if (warn && _dict.maxEmbeddedClobSize != -1)
1159: warnMaxEmbedded(val, _dict.maxEmbeddedClobSize);
1160: return true;
1161: }
1162:
1163: /**
1164: * Warn that the given value is being mapped to a handler that will not
1165: * be able to store large lobs.
1166: */
1167: private void warnMaxEmbedded(ValueMapping val, int size) {
1168: if (getLog().isWarnEnabled())
1169: getLog().warn(
1170: _loc
1171: .get("max-embed-lob", val, String
1172: .valueOf(size)));
1173: }
1174:
1175: /**
1176: * Determine the default strategy to use for the given discriminator.
1177: * Does not take into account the current strategy, if any.
1178: */
1179: protected DiscriminatorStrategy defaultStrategy(
1180: Discriminator discrim) {
1181: return defaultStrategy(discrim, getStrategyInstaller()
1182: .isAdapting());
1183: }
1184:
1185: /**
1186: * Determine the default strategy to use for the given discriminator.
1187: * Does not take into account the current strategy, if any.
1188: */
1189: protected DiscriminatorStrategy defaultStrategy(
1190: Discriminator discrim, boolean adapting) {
1191: ClassMapping cls = discrim.getClassMapping();
1192: if (cls.getEmbeddingMetaData() != null)
1193: return NoneDiscriminatorStrategy.getInstance();
1194: if (cls.getJoinablePCSuperclassMapping() == null
1195: && (cls.getStrategy() == NoneClassStrategy
1196: .getInstance() || Modifier.isFinal(discrim
1197: .getClassMapping().getDescribedType()
1198: .getModifiers())))
1199: return NoneDiscriminatorStrategy.getInstance();
1200:
1201: Object strat = _defaults.getStrategy(discrim, adapting);
1202: if (strat instanceof String)
1203: return instantiateDiscriminatorStrategy((String) strat,
1204: discrim);
1205: if (strat != null)
1206: return (DiscriminatorStrategy) strat;
1207:
1208: if (cls.getJoinablePCSuperclassMapping() != null)
1209: return new SuperclassDiscriminatorStrategy();
1210: if (discrim.getMappingInfo().getValue() != null)
1211: return new ValueMapDiscriminatorStrategy();
1212: if (cls.getMappedPCSuperclassMapping() != null)
1213: return NoneDiscriminatorStrategy.getInstance();
1214: if (adapting || _defaults.defaultMissingInfo())
1215: return new ClassNameDiscriminatorStrategy();
1216: DBDictionary dict = ((JDBCConfiguration) getConfiguration())
1217: .getDBDictionaryInstance();
1218: if (dict.joinSyntax == JoinSyntaxes.SYNTAX_TRADITIONAL)
1219: return NoneDiscriminatorStrategy.getInstance();
1220: return new SubclassJoinDiscriminatorStrategy();
1221: }
1222:
1223: /**
1224: * Determine the default strategy to use for the given version.
1225: * Does not take into account the current strategy, if any.
1226: */
1227: protected VersionStrategy defaultStrategy(Version version) {
1228: return defaultStrategy(version, getStrategyInstaller()
1229: .isAdapting());
1230: }
1231:
1232: /**
1233: * Determine the default strategy to use for the given version.
1234: * Does not take into account the current strategy, if any.
1235: */
1236: protected VersionStrategy defaultStrategy(Version version,
1237: boolean adapting) {
1238: ClassMapping cls = version.getClassMapping();
1239: if (cls.getEmbeddingMetaData() != null)
1240: return NoneVersionStrategy.getInstance();
1241: if (cls.getJoinablePCSuperclassMapping() == null
1242: && cls.getStrategy() == NoneClassStrategy.getInstance())
1243: return NoneVersionStrategy.getInstance();
1244:
1245: Object strat = _defaults.getStrategy(version, adapting);
1246: if (strat instanceof String)
1247: return instantiateVersionStrategy((String) strat, version);
1248: if (strat != null)
1249: return (VersionStrategy) strat;
1250:
1251: if (cls.getJoinablePCSuperclassMapping() != null)
1252: return new SuperclassVersionStrategy();
1253:
1254: FieldMapping vfield = version.getClassMapping()
1255: .getVersionFieldMapping();
1256: if (vfield != null)
1257: return defaultStrategy(version, vfield);
1258: if (adapting || _defaults.defaultMissingInfo())
1259: return new NumberVersionStrategy();
1260: return NoneVersionStrategy.getInstance();
1261: }
1262:
1263: /**
1264: * Return the default version strategy, given a version field.
1265: */
1266: protected VersionStrategy defaultStrategy(Version vers,
1267: FieldMapping vfield) {
1268: switch (vfield.getTypeCode()) {
1269: case JavaTypes.DATE:
1270: case JavaTypes.CALENDAR:
1271: return (JavaVersions.VERSION >= 5) ? new NanoPrecisionTimestampVersionStrategy()
1272: : new TimestampVersionStrategy();
1273: case JavaTypes.BYTE:
1274: case JavaTypes.INT:
1275: case JavaTypes.LONG:
1276: case JavaTypes.SHORT:
1277: case JavaTypes.BYTE_OBJ:
1278: case JavaTypes.INT_OBJ:
1279: case JavaTypes.LONG_OBJ:
1280: case JavaTypes.SHORT_OBJ:
1281: case JavaTypes.NUMBER:
1282: return new NumberVersionStrategy();
1283: default:
1284: return NoneVersionStrategy.getInstance();
1285: }
1286: }
1287:
1288: public void endConfiguration() {
1289: super .endConfiguration();
1290:
1291: JDBCConfiguration conf = (JDBCConfiguration) getConfiguration();
1292: _dict = conf.getDBDictionaryInstance();
1293: if (_defaults == null)
1294: _defaults = conf.getMappingDefaultsInstance();
1295: if (_schema != null && _schema instanceof Configurable) {
1296: ((Configurable) _schema).setConfiguration(conf);
1297: ((Configurable) _schema).startConfiguration();
1298: ((Configurable) _schema).endConfiguration();
1299: }
1300: }
1301: }
|