Home » apache-openjpa-1.1.0-source » org.apache.openjpa.jdbc » meta » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied.  See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.    
   18    */
   19   package org.apache.openjpa.jdbc.meta;
   20   
   21   import java.sql.SQLException;
   22   import java.util.ArrayList;
   23   import java.util.Arrays;
   24   import java.util.Collection;
   25   import java.util.Collections;
   26   import java.util.HashMap;
   27   import java.util.Iterator;
   28   import java.util.LinkedHashSet;
   29   import java.util.List;
   30   import java.util.Map;
   31   import java.util.Set;
   32   
   33   import org.apache.commons.lang.StringUtils;
   34   import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
   35   import org.apache.openjpa.jdbc.kernel.JDBCStore;
   36   import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
   37   import org.apache.openjpa.jdbc.schema.Column;
   38   import org.apache.openjpa.jdbc.schema.ColumnIO;
   39   import org.apache.openjpa.jdbc.schema.ForeignKey;
   40   import org.apache.openjpa.jdbc.schema.Schemas;
   41   import org.apache.openjpa.jdbc.schema.Table;
   42   import org.apache.openjpa.jdbc.sql.Joins;
   43   import org.apache.openjpa.jdbc.sql.Result;
   44   import org.apache.openjpa.jdbc.sql.RowManager;
   45   import org.apache.openjpa.jdbc.sql.Select;
   46   import org.apache.openjpa.kernel.FetchConfiguration;
   47   import org.apache.openjpa.kernel.OpenJPAStateManager;
   48   import org.apache.openjpa.kernel.PCState;
   49   import org.apache.openjpa.lib.log.Log;
   50   import org.apache.openjpa.lib.rop.ResultObjectProvider;
   51   import org.apache.openjpa.lib.util.Localizer;
   52   import org.apache.openjpa.meta.ClassMetaData;
   53   import org.apache.openjpa.meta.ValueMetaData;
   54   import org.apache.openjpa.util.ApplicationIds;
   55   import org.apache.openjpa.util.InternalException;
   56   import org.apache.openjpa.util.MetaDataException;
   57   import org.apache.openjpa.util.OpenJPAId;
   58   import org.apache.openjpa.util.ImplHelper;
   59   
   60   /**
   61    * Specialization of metadata for relational databases.
   62    *
   63    * @author Abe White
   64    */
   65   public class ClassMapping
   66       extends ClassMetaData
   67       implements ClassStrategy {
   68   
   69       public static final ClassMapping[] EMPTY_MAPPINGS = new ClassMapping[0];
   70   
   71       private static final Localizer _loc = Localizer.forPackage
   72           (ClassMapping.class);
   73   
   74       private final ClassMappingInfo _info;
   75       private final Discriminator _discrim;
   76       private final Version _version;
   77       private ClassStrategy _strategy = null;
   78   
   79       private Table _table = null;
   80       private ColumnIO _io = null;
   81       private Column[] _cols = Schemas.EMPTY_COLUMNS;
   82       private ForeignKey _fk = null;
   83       private int _subclassMode = Integer.MAX_VALUE;
   84   
   85       private ClassMapping[] _joinSubMaps = null;
   86       private ClassMapping[] _assignMaps = null;
   87   
   88       // maps columns to joinables
   89       private final Map _joinables = Collections.synchronizedMap(new HashMap());
   90   
   91       /**
   92        * Constructor. Supply described type and owning repository.
   93        */
   94       protected ClassMapping(Class type, MappingRepository repos) {
   95           super(type, repos);
   96           _discrim = repos.newDiscriminator(this);
   97           _version = repos.newVersion(this);
   98           _info = repos.newMappingInfo(this);
   99       }
  100   
  101       /**
  102        * Embedded constructor. Supply embedding value and owning repository.
  103        */
  104       protected ClassMapping(ValueMetaData vmd) {
  105           super(vmd);
  106           _discrim = getMappingRepository().newDiscriminator(this);
  107           _version = getMappingRepository().newVersion(this);
  108           _info = getMappingRepository().newMappingInfo(this);
  109       }
  110   
  111       /**
  112        * The class discriminator.
  113        */
  114       public Discriminator getDiscriminator() {
  115           return _discrim;
  116       }
  117   
  118       /**
  119        * The version indicator.
  120        */
  121       public Version getVersion() {
  122           return _version;
  123       }
  124   
  125       ///////////
  126       // Runtime
  127       ///////////
  128   
  129       /**
  130        * Return the oid value stored in the result. This implementation will
  131        * recurse until it finds an ancestor class who uses oid values for its
  132        * primary key.
  133        *
  134        * @param fk if non-null, use the local columns of the given foreign
  135        * key in place of this class' primary key columns
  136        * @see #isPrimaryKeyObjectId
  137        */
  138       public Object getObjectId(JDBCStore store, Result res, ForeignKey fk,
  139           boolean subs, Joins joins)
  140           throws SQLException {
  141           ValueMapping embed = getEmbeddingMapping();
  142           if (embed != null)
  143               return embed.getFieldMapping().getDefiningMapping().
  144                   getObjectId(store, res, fk, subs, joins);
  145   
  146           return getObjectId(this, store, res, fk, subs, joins);
  147       }
  148   
  149       /**
  150        * Recursive helper for public <code>getObjectId</code> method.
  151        */
  152       private Object getObjectId(ClassMapping cls, JDBCStore store, Result res,
  153           ForeignKey fk, boolean subs, Joins joins)
  154           throws SQLException {
  155           if (!isPrimaryKeyObjectId(true))
  156               return getPCSuperclassMapping().getObjectId(cls, store, res, fk,
  157                   subs, joins);
  158           if (getIdentityType() == ID_UNKNOWN)
  159               throw new InternalException();
  160   
  161           Column[] pks = getPrimaryKeyColumns();
  162           if (getIdentityType() == ID_DATASTORE) {
  163               Column col = (fk == null) ? pks[0] : fk.getColumn(pks[0]);
  164               long id = res.getLong(col, joins);
  165               return (id == 0 && res.wasNull()) ? null
  166                   : store.newDataStoreId(id, cls, subs);
  167           }
  168   
  169           // application identity
  170           Object[] vals = new Object[getPrimaryKeyFields().length];
  171           FieldMapping fm;
  172           Joinable join;
  173           int pkIdx;
  174           for (int i = 0; i < pks.length; i++) {
  175               // we know that all pk column join mappings use primary key fields,
  176               // cause this mapping uses the oid as its primary key (we recursed
  177               // at the beginning of the method to ensure this)
  178               join = assertJoinable(pks[i]);
  179               fm = getFieldMapping(join.getFieldIndex());
  180               pkIdx = fm.getPrimaryKeyIndex();
  181   
  182               // could have already set value with previous multi-column joinable
  183               if (vals[pkIdx] == null) {
  184                   res.startDataRequest(fm);
  185                   vals[pkIdx] = join.getPrimaryKeyValue(res, join.getColumns(),
  186                       fk, store, joins);
  187                   res.endDataRequest();
  188                   if (vals[pkIdx] == null)
  189                       return null;
  190               }
  191           }
  192           Object oid = ApplicationIds.fromPKValues(vals, cls);
  193           
  194           /**
  195            * For polymorphic relations,
  196            * the type field in the oid is initially set to base type.
  197            * If the discriminator value is preset in the current result,
  198            * then the type field needs reset based on the discriminator value.
  199            * If the discriminator value is not present or invalid,
  200            * ignore any exceptions being thrown.
  201            */        
  202           if (oid instanceof OpenJPAId) {
  203               Class type = cls.getDescribedType();
  204               if (!subs)
  205                   // non-polymorphic relations
  206                   ((OpenJPAId) oid).setManagedInstanceType(type);
  207               else if (cls.getDiscriminator() != null
  208                   && !StringUtils.equals("none",
  209                       cls.getDiscriminator().getStrategy().getAlias())) {
  210                   // polymorphic relations
  211                   res.startDataRequest(cls.getDiscriminator());
  212                   try {
  213                       type = cls.getDiscriminator().getClass(store, cls, res);
  214                       ((OpenJPAId) oid).setManagedInstanceType(type, true);
  215                   } catch (Exception e) {
  216                       // intentionally ignored
  217                   }
  218                   res.endDataRequest();  
  219               } 
  220           }
  221           return oid;
  222       }
  223   
  224       /**
  225        * Return the given column value(s) for the given object. The given
  226        * columns will be primary key columns of this mapping, but may be in
  227        * any order. If there is only one column, return its value. If there
  228        * are multiple columns, return an object array of their values, in the
  229        * same order the columns are given.
  230        */
  231       public Object toDataStoreValue(Object obj, Column[] cols, JDBCStore store) {
  232           Object ret = (cols.length == 1) ? null : new Object[cols.length];
  233   
  234           // in the past we've been lenient about being able to translate objects
  235           // from other persistence contexts, so try to get sm directly from
  236           // instance before asking our context
  237           OpenJPAStateManager sm;
  238           if (ImplHelper.isManageable(obj))
  239               sm = (OpenJPAStateManager) (ImplHelper.toPersistenceCapable(obj,
  240                   getRepository().getConfiguration()))
  241                   .pcGetStateManager();
  242           else
  243               sm = store.getContext().getStateManager(obj);
  244           if (sm == null)
  245               return ret;
  246   
  247           Object val;
  248           for (int i = 0; i < cols.length; i++) {
  249               val = assertJoinable(cols[i]).getJoinValue(sm, cols[i], store);
  250               if (cols.length == 1)
  251                   ret = val;
  252               else
  253                   ((Object[]) ret)[i] = val;
  254           }
  255           return ret;
  256       }
  257   
  258       /**
  259        * Return the joinable for the given column, or throw an exception if
  260        * none is available.
  261        */
  262       public Joinable assertJoinable(Column col) {
  263           Joinable join = getJoinable(col);
  264           if (join == null)
  265               throw new MetaDataException(_loc.get("no-joinable",
  266                   col.getFullName()));
  267           return join;
  268       }
  269   
  270       /**
  271        * Return the {@link Joinable} for the given column. Any column that
  272        * another mapping joins to must be controlled by a joinable.
  273        */
  274       public Joinable getJoinable(Column col) {
  275           Joinable join;
  276           if (getEmbeddingMetaData() != null) {
  277               join = getEmbeddingMapping().getFieldMapping().
  278                   getDefiningMapping().getJoinable(col);
  279               if (join != null)
  280                   return join;
  281           }
  282           ClassMapping sup = getJoinablePCSuperclassMapping();
  283           if (sup != null) {
  284               join = sup.getJoinable(col);
  285               if (join != null)
  286                   return join;
  287           }
  288           return (Joinable) _joinables.get(col);
  289       }
  290   
  291       /**
  292        * Add the given column-to-joinable mapping.
  293        */
  294       public void setJoinable(Column col, Joinable joinable) {
  295           // don't let non-pk override pk
  296           Joinable join = (Joinable) _joinables.get(col);
  297           if (join == null || (join.getFieldIndex() != -1
  298               && getField(join.getFieldIndex()).getPrimaryKeyIndex() == -1))
  299               _joinables.put(col, joinable);
  300       }
  301   
  302       /**
  303        * Return whether the columns of the given foreign key to this mapping
  304        * can be used to construct an object id for this type. This is a
  305        * relatively expensive operation; its results should be cached.
  306        *
  307        * @return {@link Boolean#TRUE} if the foreign key contains all oid
  308        * columns, <code>null</code> if it contains only some columns,
  309        * or {@link Boolean#FALSE} if it contains non-oid columns
  310        */
  311       public Boolean isForeignKeyObjectId(ForeignKey fk) {
  312           // if this mapping's primary key can't construct an oid, then no way
  313           // foreign key can
  314           if (getIdentityType() == ID_UNKNOWN || !isPrimaryKeyObjectId(false))
  315               return Boolean.FALSE;
  316   
  317           // with datastore identity, it's all or nothing
  318           Column[] cols = fk.getPrimaryKeyColumns();
  319           if (getIdentityType() == ID_DATASTORE) {
  320               if (cols.length != 1 || cols[0] != getPrimaryKeyColumns()[0])
  321                   return Boolean.FALSE;
  322               return Boolean.TRUE;
  323           }
  324   
  325           // check the join mapping for each pk column to see if it links up to
  326           // a primary key field
  327           Joinable join;
  328           for (int i = 0; i < cols.length; i++) {
  329               join = assertJoinable(cols[i]);
  330               if (join.getFieldIndex() != -1
  331                   && getField(join.getFieldIndex()).getPrimaryKeyIndex() == -1)
  332                   return Boolean.FALSE;
  333           }
  334   
  335           // if all primary key links, see whether we join to all pks
  336           if (isPrimaryKeyObjectId(true)
  337               && cols.length == getPrimaryKeyColumns().length)
  338               return Boolean.TRUE;
  339           return null;
  340       }
  341   
  342       ///////
  343       // ORM
  344       ///////
  345   
  346       /**
  347        * Raw mapping data.
  348        */
  349       public ClassMappingInfo getMappingInfo() {
  350           return _info;
  351       }
  352   
  353       /**
  354        * The strategy used to map this mapping.
  355        */
  356       public ClassStrategy getStrategy() {
  357           return _strategy;
  358       }
  359   
  360       /**
  361        * The strategy used to map this mapping. The <code>adapt</code>
  362        * parameter determines whether to adapt when mapping the strategy;
  363        * use null if the strategy should not be mapped.
  364        */
  365       public void setStrategy(ClassStrategy strategy, Boolean adapt) {
  366           // set strategy first so we can access it during mapping
  367           ClassStrategy orig = _strategy;
  368           _strategy = strategy;
  369           if (strategy != null) {
  370               try {
  371                   strategy.setClassMapping(this);
  372                   if (adapt != null)
  373                       strategy.map(adapt.booleanValue());
  374               } catch (RuntimeException re) {
  375                   // reset strategy
  376                   _strategy = orig;
  377                   throw re;
  378               }
  379           }
  380       }
  381   
  382       /**
  383        * The mapping's primary table.
  384        */
  385       public Table getTable() {
  386           return _table;
  387       }
  388   
  389       /**
  390        * The mapping's primary table.
  391        */
  392       public void setTable(Table table) {
  393           _table = table;
  394       }
  395   
  396       /**
  397        * The columns this mapping uses to uniquely identify an object.
  398        * These will typically be the primary key columns or the columns this
  399        * class uses to link to its superclass table.
  400        */
  401       public Column[] getPrimaryKeyColumns() {
  402           if (_cols.length == 0 && getIdentityType() == ID_APPLICATION
  403               && isMapped()) {
  404               FieldMapping[] pks = getPrimaryKeyFieldMappings();
  405               Collection cols = new ArrayList(pks.length);
  406               Column[] fieldCols;
  407               for (int i = 0; i < pks.length; i++) {
  408                   fieldCols = pks[i].getColumns();
  409                   for (int j = 0; j < fieldCols.length; j++)
  410                       cols.add(fieldCols[j]);
  411               }
  412               _cols = (Column[]) cols.toArray(new Column[cols.size()]);
  413           }
  414           return _cols;
  415       }
  416   
  417       /**
  418        * The columns this mapping uses to uniquely identify an object.
  419        * These will typically be the primary key columns or the columns this
  420        * class uses to link to its superclass table.
  421        */
  422       public void setPrimaryKeyColumns(Column[] cols) {
  423           if (cols == null)
  424               cols = Schemas.EMPTY_COLUMNS;
  425           _cols = cols;
  426       }
  427   
  428       /**
  429        * I/O information on the key columns / join key.
  430        */
  431       public ColumnIO getColumnIO() {
  432           return (_io == null) ? ColumnIO.UNRESTRICTED : _io;
  433       }
  434   
  435       /**
  436        * I/O information on the key columns / join key.
  437        */
  438       public void setColumnIO(ColumnIO io) {
  439           _io = io;
  440       }
  441   
  442       /**
  443        * Foreign key linking the primary key columns to the superclass table,
  444        * or null if none.
  445        */
  446       public ForeignKey getJoinForeignKey() {
  447           return _fk;
  448       }
  449   
  450       /**
  451        * Foreign key linking the primary key columns to the superclass table,
  452        * or null if none.
  453        */
  454       public void setJoinForeignKey(ForeignKey fk) {
  455           _fk = fk;
  456       }
  457   
  458       public void refSchemaComponents() {
  459           if (getEmbeddingMetaData() == null) {
  460               if (_table != null && _table.getPrimaryKey() != null)
  461                   _table.getPrimaryKey().ref();
  462               if (_fk != null)
  463                   _fk.ref();
  464               Column[] pks = getPrimaryKeyColumns();
  465               for (int i = 0; i < pks.length; i++)
  466                   pks[i].ref();
  467           } else {
  468               FieldMapping[] fields = getFieldMappings();
  469               for (int i = 0; i < fields.length; i++)
  470                   fields[i].refSchemaComponents();
  471           }
  472       }
  473   
  474       /**
  475        * Clear mapping information, including strategy.
  476        */
  477       public void clearMapping() {
  478           _strategy = null;
  479           _cols = Schemas.EMPTY_COLUMNS;
  480           _fk = null;
  481           _table = null;
  482           _info.clear();
  483           setResolve(MODE_MAPPING | MODE_MAPPING_INIT, false);
  484       }
  485   
  486       /**
  487        * Update {@link MappingInfo} with our current mapping information.
  488        */
  489       public void syncMappingInfo() {
  490           if (getEmbeddingMetaData() == null)
  491               _info.syncWith(this);
  492           else {
  493               _info.clear();
  494               FieldMapping[] fields = getFieldMappings();
  495               for (int i = 0; i < fields.length; i++)
  496                   fields[i].syncMappingInfo();
  497           }
  498       }
  499   
  500       //////////////////////
  501       // MetaData interface
  502       //////////////////////
  503   
  504       protected void setDescribedType(Class type) {
  505           super.setDescribedType(type);
  506           // this method called from superclass constructor, so _info not yet
  507           // initialized
  508           if (_info != null)
  509               _info.setClassName(type.getName());
  510       }
  511   
  512       /**
  513        * The subclass fetch mode, as one of the eager constants in
  514        * {@link JDBCFetchConfiguration}.
  515        */
  516       public int getSubclassFetchMode() {
  517           if (_subclassMode == Integer.MAX_VALUE) {
  518               if (getPCSuperclass() != null)
  519                   _subclassMode = getPCSuperclassMapping().
  520                       getSubclassFetchMode();
  521               else
  522                   _subclassMode = FetchConfiguration.DEFAULT;
  523           }
  524           return _subclassMode;
  525       }
  526   
  527       /**
  528        * The subclass fetch mode, as one of the eager constants in
  529        * {@link JDBCFetchConfiguration}.
  530        */
  531       public void setSubclassFetchMode(int mode) {
  532           _subclassMode = mode;
  533       }
  534   
  535       /**
  536        * Convenience method to perform cast from
  537        * {@link ClassMetaData#getRepository}.
  538        */
  539       public MappingRepository getMappingRepository() {
  540           return (MappingRepository) getRepository();
  541       }
  542   
  543       /**
  544        * Convenience method to perform cast from
  545        * {@link ClassMetaData#getEmbeddingMetaData}
  546        */
  547       public ValueMapping getEmbeddingMapping() {
  548           return (ValueMapping) getEmbeddingMetaData();
  549       }
  550   
  551       /**
  552        * Returns true if this class does not use the "none" strategy (including
  553        * if it has a null strategy, and therefore is probably in the process of
  554        * being mapped).
  555        */
  556       public boolean isMapped() {
  557           if (!super.isMapped())
  558               return false;
  559           if (_strategy != null)
  560               return _strategy != NoneClassStrategy.getInstance();
  561           return !NoneClassStrategy.ALIAS.equals(_info.getStrategy());
  562       }
  563   
  564       /**
  565        * Convenience method to perform cast from
  566        * {@link ClassMetaData#getPCSuperclassMetaData}.
  567        */
  568       public ClassMapping getPCSuperclassMapping() {
  569           return (ClassMapping) getPCSuperclassMetaData();
  570       }
  571   
  572       /**
  573        * Convenience method to perform cast from
  574        * {@link ClassMetaData#getMappedPCSuperclassMetaData}.
  575        */
  576       public ClassMapping getMappedPCSuperclassMapping() {
  577           return (ClassMapping) getMappedPCSuperclassMetaData();
  578       }
  579   
  580       /**
  581        * Return the nearest mapped superclass that can join to this class.
  582        */
  583       public ClassMapping getJoinablePCSuperclassMapping() {
  584           ClassMapping sup = getMappedPCSuperclassMapping();
  585           if (sup == null)
  586               return null;
  587           if (_fk != null || _table == null || _table.equals(sup.getTable()))
  588               return sup;
  589           return null;
  590       }
  591   
  592       /**
  593        * Convenience method to perform cast from
  594        * {@link ClassMetaData#getPCSubclassMetaDatas}.
  595        */
  596       public ClassMapping[] getPCSubclassMappings() {
  597           return (ClassMapping[]) getPCSubclassMetaDatas();
  598       }
  599   
  600       /**
  601        * Convenience method to perform cast from
  602        * {@link ClassMetaData#getMappedPCSubclassMetaDatas}.
  603        */
  604       public ClassMapping[] getMappedPCSubclassMappings() {
  605           return (ClassMapping[]) getMappedPCSubclassMetaDatas();
  606       }
  607   
  608       /**
  609        * Return mapped subclasses that are reachable via joins.
  610        */
  611       public ClassMapping[] getJoinablePCSubclassMappings() {
  612           ClassMapping[] subs = getMappedPCSubclassMappings(); // checks for new
  613           if (_joinSubMaps == null) {
  614               if (subs.length == 0)
  615                   _joinSubMaps = subs;
  616               else {
  617                   List joinable = new ArrayList(subs.length);
  618                   for (int i = 0; i < subs.length; i++)
  619                       if (isSubJoinable(subs[i]))
  620                           joinable.add(subs[i]);
  621                   _joinSubMaps = (ClassMapping[]) joinable.toArray
  622                       (new ClassMapping[joinable.size()]);
  623               }
  624           }
  625           return _joinSubMaps;
  626       }
  627   
  628       /**
  629        * Return whether we can reach the given subclass via joins.
  630        */
  631       private boolean isSubJoinable(ClassMapping sub) {
  632           if (sub == null)
  633               return false;
  634           if (sub == this)
  635               return true;
  636           return isSubJoinable(sub.getJoinablePCSuperclassMapping());
  637       }
  638   
  639       /**
  640        * Returns the closest-derived list of non-inter-joinable mapped types
  641        * assignable to this type. May return this mapping.
  642        */
  643       public ClassMapping[] getIndependentAssignableMappings() {
  644           ClassMapping[] subs = getMappedPCSubclassMappings(); // checks for new
  645           if (_assignMaps == null) {
  646               // remove unmapped subs
  647               if (subs.length == 0) {
  648                   if (isMapped())
  649                       _assignMaps = new ClassMapping[]{ this };
  650                   else
  651                       _assignMaps = subs;
  652               } else {
  653                   int size = (int) (subs.length * 1.33 + 2);
  654                   Set independent = new LinkedHashSet(size);
  655                   if (isMapped())
  656                       independent.add(this);
  657                   independent.addAll(Arrays.asList(subs));
  658   
  659                   // remove all mappings that have a superclass mapping in the set
  660                   ClassMapping map, sup;
  661                   List clear = null;
  662                   for (Iterator itr = independent.iterator(); itr.hasNext();) {
  663                       map = (ClassMapping) itr.next();
  664                       sup = map.getJoinablePCSuperclassMapping();
  665                       if (sup != null && independent.contains(sup)) {
  666                           if (clear == null)
  667                               clear = new ArrayList(independent.size() - 1);
  668                           clear.add(map);
  669                       }
  670                   }
  671                   if (clear != null)
  672                       independent.removeAll(clear);
  673   
  674                   _assignMaps = (ClassMapping[]) independent.toArray
  675                       (new ClassMapping[independent.size()]);
  676               }
  677           }
  678           return _assignMaps;
  679       }
  680   
  681       /**
  682        * Convenience method to perform cast from {@link ClassMetaData#getFields}.
  683        */
  684       public FieldMapping[] getFieldMappings() {
  685           return (FieldMapping[]) getFields();
  686       }
  687   
  688       /**
  689        * Convenience method to perform cast from
  690        * {@link ClassMetaData#getDeclaredFields}.
  691        */
  692       public FieldMapping[] getDeclaredFieldMappings() {
  693           return (FieldMapping[]) getDeclaredFields();
  694       }
  695   
  696       /**
  697        * Convenience method to perform cast from
  698        * {@link ClassMetaData#getPrimaryKeyFields}.
  699        */
  700       public FieldMapping[] getPrimaryKeyFieldMappings() {
  701           return (FieldMapping[]) getPrimaryKeyFields();
  702       }
  703   
  704       /**
  705        * Convenience method to perform cast from
  706        * {@link ClassMetaData#getVersionField}.
  707        */
  708       public FieldMapping getVersionFieldMapping() {
  709           return (FieldMapping) getVersionField();
  710       }
  711   
  712       /**
  713        * Convenience method to perform cast from
  714        * {@link ClassMetaData#getDefaultFetchGroupFields}.
  715        */
  716       public FieldMapping[] getDefaultFetchGroupFieldMappings() {
  717           return (FieldMapping[]) getDefaultFetchGroupFields();
  718       }
  719   
  720       /**
  721        * Convenience method to perform cast from
  722        * {@link ClassMetaData#getDefinedFields}.
  723        */
  724       public FieldMapping[] getDefinedFieldMappings() {
  725           return (FieldMapping[]) getDefinedFields();
  726       }
  727   
  728       /**
  729        * Convenience method to perform cast from
  730        * {@link ClassMetaData#getFieldsInListingOrder}.
  731        */
  732       public FieldMapping[] getFieldMappingsInListingOrder() {
  733           return (FieldMapping[]) getFieldsInListingOrder();
  734       }
  735   
  736       /**
  737        * Convenience method to perform cast from
  738        * {@link ClassMetaData#getDefinedFieldsInListingOrder}.
  739        */
  740       public FieldMapping[] getDefinedFieldMappingsInListingOrder() {
  741           return (FieldMapping[]) getDefinedFieldsInListingOrder();
  742       }
  743   
  744       /**
  745        * Convenience method to perform cast from {@link ClassMetaData#getField}.
  746        */
  747       public FieldMapping getFieldMapping(int index) {
  748           return (FieldMapping) getField(index);
  749       }
  750   
  751       /**
  752        * Convenience method to perform cast from
  753        * {@link ClassMetaData#getDeclaredField}.
  754        */
  755       public FieldMapping getDeclaredFieldMapping(int index) {
  756           return (FieldMapping) getDeclaredField(index);
  757       }
  758   
  759       /**
  760        * Convenience method to perform cast from {@link ClassMetaData#getField}.
  761        */
  762       public FieldMapping getFieldMapping(String name) {
  763           return (FieldMapping) getField(name);
  764       }
  765   
  766       /**
  767        * Convenience method to perform cast from
  768        * {@link ClassMetaData#getDeclaredField}.
  769        */
  770       public FieldMapping getDeclaredFieldMapping(String name) {
  771           return (FieldMapping) getDeclaredField(name);
  772       }
  773   
  774       /**
  775        * Convenience method to perform cast from
  776        * {@link ClassMetaData#getDeclaredUnmanagedFields}.
  777        */
  778       public FieldMapping[] getDeclaredUnmanagedFieldMappings() {
  779           return (FieldMapping[]) getDeclaredUnmanagedFields();
  780       }
  781   
  782       /**
  783        * Convenience method to perform cast from
  784        * {@link ClassMetaData#addDeclaredField}.
  785        */
  786       public FieldMapping addDeclaredFieldMapping(String name, Class type) {
  787           return (FieldMapping) addDeclaredField(name, type);
  788       }
  789   
  790       protected void resolveMapping(boolean runtime) {
  791           super.resolveMapping(runtime);
  792   
  793           // map class strategy; it may already be mapped by the repository before
  794           // the resolve process begins
  795           MappingRepository repos = getMappingRepository();
  796           if (_strategy == null)
  797               repos.getStrategyInstaller().installStrategy(this);
  798           Log log = getRepository().getLog();
  799           if (log.isTraceEnabled())
  800               log.trace(_loc.get("strategy", this, _strategy.getAlias()));
  801   
  802           // make sure unmapped superclass fields are defined if we're mapped;
  803           // also may have been done by repository already
  804           defineSuperclassFields(getJoinablePCSuperclassMapping() == null);
  805   
  806           // resolve everything that doesn't rely on any relations to avoid
  807           // recursion, then resolve all fields
  808           resolveNonRelationMappings();
  809           FieldMapping[] fms = getFieldMappings();
  810           for (int i = 0; i < fms.length; i++)
  811               if (fms[i].getDefiningMetaData() == this)
  812                   fms[i].resolve(MODE_MAPPING);
  813           fms = getDeclaredUnmanagedFieldMappings();
  814           for (int i = 0; i < fms.length; i++)
  815               fms[i].resolve(MODE_MAPPING);
  816   
  817           // mark mapped columns
  818           if (_cols != null) {
  819               ColumnIO io = getColumnIO();
  820               for (int i = 0; i < _cols.length; i++) {
  821                   if (io.isInsertable(i, false))
  822                       _cols[i].setFlag(Column.FLAG_DIRECT_INSERT, true);
  823                   if (io.isUpdatable(i, false))
  824                       _cols[i].setFlag(Column.FLAG_DIRECT_UPDATE, true);
  825               }
  826           }
  827           // once columns are resolved, resolve unique constraints as they need
  828           // the columns be resolved 
  829           _info.getUniques(this, true);
  830       }
  831       
  832       /**
  833        * Resolve non-relation field mappings so that when we do relation
  834        * mappings they can rely on them for joins.
  835        */
  836       void resolveNonRelationMappings() {
  837           // make sure primary key fields are resolved first because other
  838           // fields might rely on them
  839           FieldMapping[] fms = getPrimaryKeyFieldMappings();
  840           for (int i = 0; i < fms.length; i++)
  841               fms[i].resolve(MODE_MAPPING);
  842   
  843           // resolve defined fields that are safe; that don't rely on other types
  844           // also being resolved.  don't use getDefinedFields b/c it relies on
  845           // whether fields are mapped, which isn't known yet
  846           fms = getFieldMappings();
  847           for (int i = 0; i < fms.length; i++)
  848               if (fms[i].getDefiningMetaData() == this
  849                   && !fms[i].isTypePC() && !fms[i].getKey().isTypePC()
  850                   && !fms[i].getElement().isTypePC())
  851                   fms[i].resolve(MODE_MAPPING);
  852   
  853           _discrim.resolve(MODE_MAPPING);
  854           _version.resolve(MODE_MAPPING);        
  855       }
  856   
  857       protected void initializeMapping() {
  858           super.initializeMapping();
  859   
  860           FieldMapping[] fields = getDefinedFieldMappings();
  861           for (int i = 0; i < fields.length; i++)
  862               fields[i].resolve(MODE_MAPPING_INIT);
  863           _discrim.resolve(MODE_MAPPING_INIT);
  864           _version.resolve(MODE_MAPPING_INIT);
  865           _strategy.initialize();
  866       }
  867   
  868       protected void clearDefinedFieldCache() {
  869           // just make this method available to other classes in this package
  870           super.clearDefinedFieldCache();
  871       }
  872   
  873       protected void clearSubclassCache() {
  874           super.clearSubclassCache();
  875           _joinSubMaps = null;
  876           _assignMaps = null;
  877       }
  878   
  879       public void copy(ClassMetaData cls) {
  880           super.copy(cls);
  881           if (_subclassMode == Integer.MAX_VALUE)
  882               _subclassMode = ((ClassMapping) cls).getSubclassFetchMode();
  883       }
  884   
  885       protected boolean validateDataStoreExtensionPrefix(String prefix) {
  886           return "jdbc-".equals(prefix);
  887       }
  888   
  889       ////////////////////////////////
  890       // ClassStrategy implementation
  891       ////////////////////////////////
  892   
  893       public String getAlias() {
  894           return assertStrategy().getAlias();
  895       }
  896   
  897       public void map(boolean adapt) {
  898           assertStrategy().map(adapt);
  899       }
  900   
  901       public void initialize() {
  902           assertStrategy().initialize();
  903       }
  904   
  905       public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
  906           throws SQLException {
  907           assertStrategy().insert(sm, store, rm);
  908       }
  909   
  910       public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
  911           throws SQLException {
  912           assertStrategy().update(sm, store, rm);
  913       }
  914   
  915       public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
  916           throws SQLException {
  917           assertStrategy().delete(sm, store, rm);
  918       }
  919   
  920       public Boolean isCustomInsert(OpenJPAStateManager sm, JDBCStore store) {
  921           return assertStrategy().isCustomInsert(sm, store);
  922       }
  923   
  924       public Boolean isCustomUpdate(OpenJPAStateManager sm, JDBCStore store) {
  925           return assertStrategy().isCustomUpdate(sm, store);
  926       }
  927   
  928       public Boolean isCustomDelete(OpenJPAStateManager sm, JDBCStore store) {
  929           return assertStrategy().isCustomDelete(sm, store);
  930       }
  931   
  932       public void customInsert(OpenJPAStateManager sm, JDBCStore store)
  933           throws SQLException {
  934           assertStrategy().customInsert(sm, store);
  935       }
  936   
  937       public void customUpdate(OpenJPAStateManager sm, JDBCStore store)
  938           throws SQLException {
  939           assertStrategy().customUpdate(sm, store);
  940       }
  941   
  942       public void customDelete(OpenJPAStateManager sm, JDBCStore store)
  943           throws SQLException {
  944           assertStrategy().customDelete(sm, store);
  945       }
  946   
  947       public void setClassMapping(ClassMapping owner) {
  948           assertStrategy().setClassMapping(owner);
  949       }
  950   
  951       public boolean isPrimaryKeyObjectId(boolean hasAll) {
  952           return assertStrategy().isPrimaryKeyObjectId(hasAll);
  953       }
  954   
  955       public Joins joinSuperclass(Joins joins, boolean toThis) {
  956           return assertStrategy().joinSuperclass(joins, toThis);
  957       }
  958   
  959       public boolean supportsEagerSelect(Select sel, OpenJPAStateManager sm,
  960           JDBCStore store, ClassMapping base, JDBCFetchConfiguration fetch) {
  961           return assertStrategy().supportsEagerSelect(sel, sm, store, base,
  962               fetch);
  963       }
  964   
  965       public ResultObjectProvider customLoad(JDBCStore store, boolean subclasses,
  966           JDBCFetchConfiguration fetch, long startIdx, long endIdx)
  967           throws SQLException {
  968           return assertStrategy().customLoad(store, subclasses, fetch,
  969               startIdx, endIdx);
  970       }
  971   
  972       public boolean customLoad(OpenJPAStateManager sm, JDBCStore store,
  973           PCState state, JDBCFetchConfiguration fetch)
  974           throws SQLException, ClassNotFoundException {
  975           return assertStrategy().customLoad(sm, store, state, fetch);
  976       }
  977   
  978       public boolean customLoad(OpenJPAStateManager sm, JDBCStore store,
  979           JDBCFetchConfiguration fetch, Result result)
  980           throws SQLException {
  981           return assertStrategy().customLoad(sm, store, fetch, result);
  982       }
  983       
  984       private ClassStrategy assertStrategy() {
  985           if (_strategy == null)
  986               throw new InternalException();
  987           return _strategy;
  988       }
  989   }

Save This Page
Home » apache-openjpa-1.1.0-source » org.apache.openjpa.jdbc » meta » [javadoc | source]