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 [18/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/Strategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/Strategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/Strategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/Strategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,131 @@
+/*
+ * 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.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.sql.RowManager;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.util.MetaDataException;
+
+/**
+ * Interface implemented by all mapping strategies.
+ *
+ * @author Abe White
+ * @since 4.0
+ */
+public interface Strategy {
+
+    /**
+     * Return the alias of this strategy. For custom strategies, return the
+     * full class name.
+     */
+    public String getAlias();
+
+    /**
+     * Map the owning mapping using this strategy.
+     *
+     * @param adapt if true, use the owning mapping's raw mapping info
+     * to set its ORM data; if false, ORM data will already be set
+     * @throws MetaDataException if unable to map
+     */
+    public void map(boolean adapt);
+
+    /**
+     * Perform caching and other initialization operations. This method is
+     * called after {@link #map}, and after all related components have been
+     * mapped as well.
+     */
+    public void initialize();
+
+    /**
+     * Set values for the mapping into the proper rows. For class mappings,
+     * this method	will be called only after the corresponding method has
+     * been called for all fields of this mapping.
+     */
+    public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException;
+
+    /**
+     * Set values for the mapping into the proper rows.
+     *
+     * @see #insert
+     */
+    public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException;
+
+    /**
+     * Set the where values appropriately to delete the proper instance,
+     * and set all relations on non-secondary tables as updates. This allows
+     * foreign key analysis.
+     *
+     * @see #insert
+     */
+    public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException;
+
+    /**
+     * Return {@link Boolean#FALSE} if this mapping does not customize the
+     * insert process, {@link Boolean#TRUE} if it does, or null if it does
+     * customize the insert, but also relies on the standard insert method
+     * being called. Implement the {@link #customInsert} method
+     * to implement the custom insertion behavior.
+     */
+    public Boolean isCustomInsert(OpenJPAStateManager sm, JDBCStore store);
+
+    /**
+     * Return {@link Boolean#FALSE} if this mapping does not customize the
+     * update process, {@link Boolean#TRUE} if it does, or null if it does
+     * customize the update, but also relies on the standard update method
+     * being called. Implement the {@link #customUpdate} method
+     * to override the default update behavior.
+     */
+    public Boolean isCustomUpdate(OpenJPAStateManager sm, JDBCStore store);
+
+    /**
+     * Return {@link Boolean#FALSE} if this mapping does not customize the
+     * delete process, {@link Boolean#TRUE} if it does, or null if it does
+     * customize the delete, but also relies on the standard delete method
+     * being called. Implement the {@link #customDelete} method
+     * to override the default deletion behavior.
+     */
+    public Boolean isCustomDelete(OpenJPAStateManager sm, JDBCStore store);
+
+    /**
+     * Override this method to customize flushing this mapping. For classes,
+     * this method must also flush all fields. For fields, this method
+     * is called after the owning object is inserted, so if this field is in
+     * a row with other fields, that row will already exist.
+     */
+    public void customInsert(OpenJPAStateManager sm, JDBCStore store)
+        throws SQLException;
+
+    /**
+     * Override this method to customize flushing this mapping. For classes,
+     * this method must also flush all fields.
+     */
+    public void customUpdate(OpenJPAStateManager sm, JDBCStore store)
+        throws SQLException;
+
+    /**
+     * Override this method to customize flushing this mapping. For classes,
+     * this method must also flush all fields. For fields, this method
+     * will be called after the owning object is deleted.
+     */
+    public void customDelete(OpenJPAStateManager sm, JDBCStore store)
+        throws SQLException;
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/Strategy.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/StrategyInstaller.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/StrategyInstaller.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/StrategyInstaller.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/StrategyInstaller.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,67 @@
+/*
+ * 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 org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+
+/**
+ * Installs mapping strategies.
+ *
+ * @author Abe White
+ * @nojavadoc
+ * @since 4.0
+ */
+public abstract class StrategyInstaller {
+
+    protected final JDBCConfiguration conf;
+    protected final MappingRepository repos;
+
+    /**
+     * Constructor; supply repository.
+     */
+    public StrategyInstaller(MappingRepository repos) {
+        this.repos = repos;
+        this.conf = (JDBCConfiguration) repos.getConfiguration();
+    }
+
+    /**
+     * Return whether this installer adapts the given mapping data and
+     * schema, vs requiring that all information be supplied correctly.
+     */
+    public boolean isAdapting() {
+        return false;
+    }
+
+    /**
+     * Install a strategy on the given mapping.
+     */
+    public abstract void installStrategy(ClassMapping cls);
+
+    /**
+     * Install a strategy on the given mapping.
+     */
+    public abstract void installStrategy(FieldMapping fm);
+
+    /**
+     * Install a strategy on the given mapping.
+     */
+    public abstract void installStrategy(Version version);
+
+    /**
+     * Install a strategy on the given mapping.
+     */
+    public abstract void installStrategy(Discriminator discrim);
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/StrategyInstaller.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueHandler.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueHandler.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueHandler.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueHandler.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,99 @@
+/*
+ * 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.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ColumnIO;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+
+/**
+ * Maps a value to a relational schema. Value handler are stateless.
+ *
+ * @author Abe White
+ * @since 4.0
+ */
+public interface ValueHandler {
+
+    /**
+     * Map the given value and return all mapped columns, or simply return an
+     * array of unmapped default columns. The columns should have at least
+     * their <code>Name</code> and <code>JavaType</code> properties set.
+     *
+     * @param name use as a base to form column name(s); the column names
+     * of unmapped columns will automatically be made to fit
+     * database limitations
+     * @param io I/O information about mapped columns; you do not
+     * have to set this information if returning templates
+     * @param adapt whether to adapt the mapping or schema
+     */
+    public Column[] map(ValueMapping vm, String name, ColumnIO io,
+        boolean adapt);
+
+    /**
+     * Return whether the values managed by this handler can be used in
+     * state image versioning.
+     */
+    public boolean isVersionable(ValueMapping vm);
+
+    /**
+     * Return whether this handler potentially must load extra data to extract
+     * the object value from its datastore representation.
+     */
+    public boolean objectValueRequiresLoad(ValueMapping vm);
+
+    /**
+     * Return the argument to pass to the result set when loading data
+     * via {@link Result#getObject}, or null if none. If this value
+     * occupies multiple columns, return an array with one element per
+     * column. You may return null if all array elements would be null.
+     */
+    public Object getResultArgument(ValueMapping vm);
+
+    /**
+     * Translate the given value to its datastore equivalent. If this value
+     * occupies multiple columns, return an object array with one element
+     * per column. For relation id columns, return the state manager
+     * the column depends on.
+     */
+    public Object toDataStoreValue(ValueMapping vm, Object val,
+        JDBCStore store);
+
+    /**
+     * Translate the given datastore value into its Java equivalent. If
+     * the value occupies multiple columns, the given object will be an object
+     * array with one entry per column. This method is only called if
+     * {@link #objectValueRequiresLoad} returns false.
+     */
+    public Object toObjectValue(ValueMapping vm, Object val);
+
+    /**
+     * Translate the given datastore value into its Java equivalent. If
+     * the value occupies multiple columns, the given object will be an object
+     * array with one entry per column. This method is only called if
+     * {@link #objectValueRequiresLoad} returns true.
+     *
+     * @param sm the state manager that owns the value; may be null if
+     * loading a projection
+     */
+    public Object toObjectValue(ValueMapping vm, Object val,
+        OpenJPAStateManager sm, JDBCStore store, JDBCFetchState fetchState)
+        throws SQLException;
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueHandler.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMapping.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMapping.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMapping.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMapping.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,265 @@
+/*
+ * 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.sql.SQLException;
+
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ColumnIO;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.schema.Index;
+import org.apache.openjpa.jdbc.schema.Unique;
+import org.apache.openjpa.jdbc.sql.Row;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.meta.MetaDataContext;
+import org.apache.openjpa.meta.ValueMetaData;
+
+/**
+ * Specialization of value metadata for relational databases.
+ *
+ * @author Abe White
+ * @since 4.0
+ */
+public interface ValueMapping
+    extends ValueMetaData, MetaDataContext {
+
+    /**
+     * Standard forward join.
+     */
+    public static final int JOIN_FORWARD = 0;
+
+    /**
+     * Inverse join.
+     */
+    public static final int JOIN_INVERSE = 1;
+
+    /**
+     * Inverse join that is marked up as a forward join because the
+     * backing mapping expects an inverse direction.
+     */
+    public static final int JOIN_EXPECTED_INVERSE = 2;
+
+    /**
+     * A fully polymorphic relation (the default).
+     */
+    public static final int POLY_TRUE = 0;
+
+    /**
+     * A non-polymorphic relation.
+     */
+    public static final int POLY_FALSE = 1;
+
+    /**
+     * A relation that can hold any joinable subclass type.
+     */
+    public static final int POLY_JOINABLE = 2;
+
+    /**
+     * Raw mapping data.
+     */
+    public ValueMappingInfo getValueInfo();
+
+    /**
+     * The handler used for this value, or null if none.
+     */
+    public ValueHandler getHandler();
+
+    /**
+     * The handler used for this value, or null if none.
+     */
+    public void setHandler(ValueHandler handler);
+
+    /**
+     * Convenience method to perform cast from
+     * {@link ValueMetaData#getRepository}.
+     */
+    public MappingRepository getMappingRepository();
+
+    /**
+     * Convenience method to perform cast from
+     * {@link ValueMetaData#getFieldMetaData}.
+     */
+    public FieldMapping getFieldMapping();
+
+    /**
+     * Convenience method to perform cast from
+     * {@link ValueMetaData#getTypeMetaData}.
+     */
+    public ClassMapping getTypeMapping();
+
+    /**
+     * Convenience method to perform cast from
+     * {@link ValueMetaData#getDeclaredTypeMetaData}.
+     */
+    public ClassMapping getDeclaredTypeMapping();
+
+    /**
+     * Convenience method to perform cast from
+     * {@link ValueMetaData#getEmbeddedMetaData}.
+     */
+    public ClassMapping getEmbeddedMapping();
+
+    /**
+     * Convenience method to perform cast from
+     * {@link ValueMetaData#getValueMappedByMetaData}.
+     */
+    public FieldMapping getValueMappedByMapping();
+
+    /**
+     * The columns that hold the data for this value.
+     */
+    public Column[] getColumns();
+
+    /**
+     * The columns that hold the data for this value.
+     */
+    public void setColumns(Column[] cols);
+
+    /**
+     * I/O information on the foreign key, or columns if this value doesn't
+     * have a key.
+     */
+    public ColumnIO getColumnIO();
+
+    /**
+     * I/O information on the foreign key, or columns if this value doesn't
+     * have a key.
+     */
+    public void setColumnIO(ColumnIO io);
+
+    /**
+     * If this value joins to another record, the foreign key.
+     */
+    public ForeignKey getForeignKey();
+
+    /**
+     * Return an equivalent of this value's foreign key, but joining to the
+     * given target, which may be an unjoined subclass of this value's
+     * related type.
+     */
+    public ForeignKey getForeignKey(ClassMapping target);
+
+    /**
+     * If this value joins to another record, the foreign key.
+     */
+    public void setForeignKey(ForeignKey fk);
+
+    /**
+     * The join direction.
+     */
+    public int getJoinDirection();
+
+    /**
+     * The join direction.
+     */
+    public void setJoinDirection(int direction);
+
+    /**
+     * Sets this value's foreign key to the given related object. The object
+     * may be null.
+     */
+    public void setForeignKey(Row row, OpenJPAStateManager rel)
+        throws SQLException;
+
+    /**
+     * Sets this value's foreign key to the given related object. The object
+     * may be null.
+     */
+    public void whereForeignKey(Row row, OpenJPAStateManager rel)
+        throws SQLException;
+
+    /**
+     * Return all independently-mapped joinable types for this value, depending
+     * on whether this value is polymorphic and how the related type is mapped.
+     * Return an empty array if value type is not PC.
+     */
+    public ClassMapping[] getIndependentTypeMappings();
+
+    /**
+     * Return the {@link org.apache.openjpa.sql.Select} subclasses constant for loading
+     * this relation, based on how the related type is mapped, whether this
+     * relation is polymorphic, and whether it is configured to use class
+     * criteria.
+     */
+    public int getSelectSubclasses();
+
+    /**
+     * Unique constraint on this value's columns, or null if none.
+     */
+    public Unique getValueUnique();
+
+    /**
+     * Unique constraint on this value's columns, or null if none.
+     */
+    public void setValueUnique(Unique unq);
+
+    /**
+     * Index on this value's columns, or null if none.
+     */
+    public Index getValueIndex();
+
+    /**
+     * Index on this value's columns, or null if none.
+     */
+    public void setValueIndex(Index idx);
+
+    /**
+     * Whether to use class criteria when joining to related type.
+     */
+    public boolean getUseClassCriteria();
+
+    /**
+     * Whether to use class criteria when joining to related type.
+     */
+    public void setUseClassCriteria(boolean criteria);
+
+    /**
+     * The degree to which this relation is polymorphic.
+     */
+    public int getPolymorphic();
+
+    /**
+     * The degree to which this relation is polymorphic.
+     */
+    public void setPolymorphic(int polymorphic);
+
+    /**
+     * Increase the reference count on used schema components.
+     */
+    public void refSchemaComponents();
+
+    /**
+     * Map indexes and constraints for this value, using the current
+     * {@link ValueMappingInfo}. The foreign key or columns of this value
+     * must be set before calling this method.
+     */
+    public void mapConstraints(String name, boolean adapt);
+
+    /**
+     * Clear mapping information, including strategy.
+     */
+    public void clearMapping();
+
+    /**
+     * Update {@link MappingInfo} with our current mapping information.
+     */
+    public void syncMappingInfo();
+
+    /**
+     * Copy mapping info from the given instance to this one.
+     */
+    public void copyMappingInfo(ValueMapping vm);
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMapping.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingImpl.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingImpl.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingImpl.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,536 @@
+/*
+ * 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.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ColumnIO;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.schema.Index;
+import org.apache.openjpa.jdbc.schema.Schemas;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.jdbc.schema.Unique;
+import org.apache.openjpa.jdbc.sql.Row;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.meta.ValueMetaDataImpl;
+import org.apache.openjpa.util.InternalException;
+import org.apache.openjpa.util.MetaDataException;
+
+/**
+ * Standalone {@link ValueMapping} implementation.
+ *
+ * @author Abe White
+ * @since 4.0
+ */
+public class ValueMappingImpl
+    extends ValueMetaDataImpl
+    implements ValueMapping {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (ValueMappingImpl.class);
+
+    private final ValueMappingInfo _info;
+    private ValueHandler _handler = null;
+    private ClassMapping[] _typeArr = null;
+
+    private Column[] _cols = Schemas.EMPTY_COLUMNS;
+    private ColumnIO _io = null;
+    private ForeignKey _fk = null;
+    private Map _targetFKs = null;
+    private Index _idx = null;
+    private Unique _unq = null;
+    private int _join = JOIN_FORWARD;
+    private boolean _criteria = false;
+    private int _poly = POLY_TRUE;
+
+    /**
+     * Constructor. Supply owning mapping.
+     */
+    public ValueMappingImpl(FieldMapping owner) {
+        super(owner);
+        _info = owner.getMappingRepository().newMappingInfo(this);
+        _info.setUseClassCriteria(owner.getMappingRepository().
+            getMappingDefaults().useClassCriteria());
+    }
+
+    public ValueMappingInfo getValueInfo() {
+        return _info;
+    }
+
+    public ValueHandler getHandler() {
+        return _handler;
+    }
+
+    public void setHandler(ValueHandler handler) {
+        _handler = handler;
+    }
+
+    public MappingRepository getMappingRepository() {
+        return (MappingRepository) getRepository();
+    }
+
+    public FieldMapping getFieldMapping() {
+        return (FieldMapping) getFieldMetaData();
+    }
+
+    public ClassMapping getTypeMapping() {
+        return (ClassMapping) getTypeMetaData();
+    }
+
+    public ClassMapping getDeclaredTypeMapping() {
+        return (ClassMapping) getDeclaredTypeMetaData();
+    }
+
+    public ClassMapping getEmbeddedMapping() {
+        return (ClassMapping) getEmbeddedMetaData();
+    }
+
+    public FieldMapping getValueMappedByMapping() {
+        return (FieldMapping) getValueMappedByMetaData();
+    }
+
+    public Column[] getColumns() {
+        if (_cols.length != 0)
+            return _cols;
+        if (_fk != null)
+            return _fk.getColumns();
+        if (getValueMappedBy() != null)
+            return getValueMappedByMapping().getColumns();
+        return _cols;
+    }
+
+    public void setColumns(Column[] cols) {
+        if (cols == null)
+            cols = Schemas.EMPTY_COLUMNS;
+        _cols = cols;
+    }
+
+    public ColumnIO getColumnIO() {
+        if (_cols.length == 0 && _fk == null && getValueMappedBy() != null)
+            return getValueMappedByMapping().getColumnIO();
+        return (_io == null) ? ColumnIO.UNRESTRICTED : _io;
+    }
+
+    public void setColumnIO(ColumnIO io) {
+        _io = io;
+    }
+
+    public ForeignKey getForeignKey() {
+        if (_fk == null && getValueMappedBy() != null)
+            return getValueMappedByMapping().getForeignKey();
+        return _fk;
+    }
+
+    public void setForeignKey(ForeignKey fk) {
+        _fk = fk;
+        if (fk == null)
+            _join = JOIN_FORWARD;
+    }
+
+    public ForeignKey getForeignKey(ClassMapping target) {
+        if (_fk == null && getValueMappedBy() != null)
+            return getValueMappedByMapping().getForeignKey(target);
+        if (target == null)
+            return _fk;
+        if (_fk == null && _cols.length == 0)
+            return null;
+
+        // always use least-derived joinable type
+        for (ClassMapping sup = target; sup != null;
+            sup = sup.getJoinablePCSuperclassMapping()) {
+            if (sup == getTypeMetaData())
+                return _fk;
+            target = sup;
+        }
+
+        synchronized (this) {
+            if (_targetFKs != null) {
+                Object cachedFK = _targetFKs.get(target);
+                if (cachedFK != null)
+                    return (ForeignKey) cachedFK;
+            } else
+                _targetFKs = new HashMap();
+
+            ForeignKey newfk = (_join == JOIN_FORWARD)
+                ? newForwardForeignKey(target) : newInverseForeignKey(target);
+            _targetFKs.put(target, newfk);
+            return newfk;
+        }
+    }
+
+    /**
+     * Create a forward foreign key to the given target.
+     */
+    private ForeignKey newForwardForeignKey(ClassMapping target) {
+        Table table;
+        Column[] cols;
+        if (_fk == null) {
+            table = _cols[0].getTable();
+            cols = _cols;
+        } else {
+            table = _fk.getTable();
+            cols = _fk.getColumns();
+        }
+
+        // gather target cols before adding foreign key to table in case
+        // there is an error while looking for a target col
+        Column[] tcols = new Column[cols.length];
+        for (int i = 0; i < cols.length; i++) {
+            if (cols[i].getTargetField() != null)
+                tcols[i] = getEquivalentColumn(cols[i], target,
+                    cols[i].getTargetField());
+            else if (_fk != null)
+                tcols[i] = getEquivalentColumn(_fk.getPrimaryKeyColumn
+                    (cols[i]).getName(), target, true);
+            else if (cols[i].getTarget() != null)
+                tcols[i] = getEquivalentColumn(cols[i].getTarget(), target,
+                    true);
+            else
+                tcols[i] = getEquivalentColumn(cols[i].getName(), target,
+                    false);
+        }
+
+        ForeignKey newfk = table.addForeignKey();
+        newfk.setJoins(cols, tcols);
+        if (_fk != null) {
+            cols = _fk.getConstantColumns();
+            for (int i = 0; i < cols.length; i++)
+                newfk.joinConstant(cols[i], _fk.getConstant(cols[i]));
+
+            cols = _fk.getConstantPrimaryKeyColumns();
+            for (int i = 0; i < cols.length; i++)
+                newfk.joinConstant(_fk.getPrimaryKeyConstant(cols[i]),
+                    getEquivalentColumn(cols[i].getName(), target, true));
+        }
+        return newfk;
+    }
+
+    /**
+     * Return the given mapping's equivalent to the given column, using the
+     * target field.
+     */
+    private Column getEquivalentColumn(Column col, ClassMapping target,
+        String fieldName) {
+        fieldName = fieldName.substring(fieldName.indexOf('.') + 1);
+        FieldMapping field = target.getFieldMapping(fieldName);
+        if (field == null)
+            throw new MetaDataException(_loc.get("no-equiv-field",
+                new Object[]{ this, target, fieldName, col }));
+
+        Column[] cols = field.getColumns();
+        if (cols.length != 1)
+            throw new MetaDataException(_loc.get("bad-equiv-field",
+                new Object[]{ this, target, fieldName, col }));
+
+        return cols[0];
+    }
+
+    /**
+     * Return the given mapping's equivalent of the given column.
+     */
+    private Column getEquivalentColumn(String colName, ClassMapping target,
+        boolean explicit) {
+        // if there was no explicit target, use single pk column
+        if (!explicit) {
+            for (ClassMapping cls = target; cls != null;
+                cls = cls.getJoinablePCSuperclassMapping()) {
+                if (cls.getTable() != null) {
+                    if (cls.getPrimaryKeyColumns().length == 1)
+                        return cls.getPrimaryKeyColumns()[0];
+                    break;
+                }
+            }
+        }
+
+        Column ret;
+        for (ClassMapping cls = target; cls != null;
+            cls = cls.getJoinablePCSuperclassMapping()) {
+            if (cls.getTable() != null) {
+                ret = cls.getTable().getColumn(colName);
+                if (ret != null)
+                    return ret;
+            }
+        }
+
+        throw new MetaDataException(_loc.get("no-equiv-col", this, target,
+            colName));
+    }
+
+    /**
+     * Return an inverse foreign key from the given related type to our table.
+     */
+    private ForeignKey newInverseForeignKey(ClassMapping target) {
+        FieldMapping field = getFieldMapping();
+        FieldMapping mapped = field.getMappedByMapping();
+        if (mapped == null)
+            throw new MetaDataException(_loc.get("cant-inverse", this));
+
+        mapped = target.getFieldMapping(mapped.getIndex());
+        if (mapped == null || mapped.getTypeCode() != JavaTypes.PC)
+            throw new MetaDataException(_loc.get("no-equiv-mapped-by",
+                this, target, field.getMappedBy()));
+        return mapped.getForeignKey();
+    }
+
+    public int getJoinDirection() {
+        if (_fk == null && getValueMappedBy() != null)
+            return getValueMappedByMapping().getJoinDirection();
+        return _join;
+    }
+
+    public void setJoinDirection(int direction) {
+        _join = direction;
+    }
+
+    public void setForeignKey(Row row, OpenJPAStateManager rel)
+        throws SQLException {
+        if (rel != null)
+            row.setForeignKey(getForeignKey((ClassMapping) rel.getMetaData()),
+                _io, rel);
+        else if (_fk != null)
+            row.setForeignKey(_fk, _io, null);
+        else {
+            for (int i = 0; i < _cols.length; i++) {
+                if (_io == null || (row.getAction() == Row.ACTION_INSERT
+                    && _io.isInsertable(i, true))
+                    || (row.getAction() != Row.ACTION_INSERT
+                    && _io.isUpdatable(i, true)))
+                    row.setNull(_cols[i]);
+            }
+        }
+    }
+
+    public void whereForeignKey(Row row, OpenJPAStateManager rel)
+        throws SQLException {
+        if (rel != null)
+            row.whereForeignKey(getForeignKey((ClassMapping)
+                rel.getMetaData()), rel);
+        else if (_fk != null)
+            row.whereForeignKey(_fk, null);
+        else
+            for (int i = 0; i < _cols.length; i++)
+                row.whereNull(_cols[i]);
+    }
+
+    public ClassMapping[] getIndependentTypeMappings() {
+        ClassMapping rel = getTypeMapping();
+        if (rel == null)
+            return ClassMapping.EMPTY_MAPPINGS;
+        if (_poly != POLY_TRUE) {
+            if (!rel.isMapped())
+                return ClassMapping.EMPTY_MAPPINGS;
+            if (_typeArr == null)
+                _typeArr = new ClassMapping[]{ rel };
+            return _typeArr;
+        }
+        return rel.getIndependentAssignableMappings();
+    }
+
+    public int getSelectSubclasses() {
+        ClassMapping rel = getTypeMapping();
+        if (rel == null || !rel.isMapped())
+            return -1;
+
+        switch (_poly) {
+            case POLY_FALSE:
+                return (_criteria) ? Select.SUBS_NONE : Select.SUBS_EXACT;
+            case POLY_TRUE:
+                ClassMapping[] assign = rel.getIndependentAssignableMappings();
+                if (assign.length != 1 || assign[0] != rel)
+                    return -1;
+                // no break
+            case POLY_JOINABLE:
+                return (_criteria) ? Select.SUBS_JOINABLE
+                    : Select.SUBS_ANY_JOINABLE;
+            default:
+                throw new InternalException();
+        }
+    }
+
+    public Unique getValueUnique() {
+        return _unq;
+    }
+
+    public void setValueUnique(Unique unq) {
+        _unq = unq;
+    }
+
+    public Index getValueIndex() {
+        return _idx;
+    }
+
+    public void setValueIndex(Index idx) {
+        _idx = idx;
+    }
+
+    public boolean getUseClassCriteria() {
+        if (_fk == null && getValueMappedBy() != null)
+            return getValueMappedByMapping().getUseClassCriteria();
+        return _criteria;
+    }
+
+    public void setUseClassCriteria(boolean criteria) {
+        _criteria = criteria;
+    }
+
+    public int getPolymorphic() {
+        return _poly;
+    }
+
+    public void setPolymorphic(int poly) {
+        _poly = poly;
+    }
+
+    public void refSchemaComponents() {
+        for (int i = 0; i < _cols.length; i++)
+            _cols[i].ref();
+        if (_fk != null) {
+            _fk.ref();
+            _fk.refColumns();
+        }
+
+        ClassMapping embed = getEmbeddedMapping();
+        if (embed != null)
+            embed.refSchemaComponents();
+    }
+
+    public void mapConstraints(String name, boolean adapt) {
+        _unq = _info.getUnique(this, name, adapt);
+        _idx = _info.getIndex(this, name, adapt);
+    }
+
+    public void clearMapping() {
+        _handler = null;
+        _cols = Schemas.EMPTY_COLUMNS;
+        _unq = null;
+        _idx = null;
+        _fk = null;
+        _join = JOIN_FORWARD;
+        _info.clear();
+        setResolve(MODE_MAPPING | MODE_MAPPING_INIT, false);
+    }
+
+    public void syncMappingInfo() {
+        if (getValueMappedBy() != null)
+            _info.clear();
+        else {
+            _info.syncWith(this);
+            ClassMapping embed = getEmbeddedMapping();
+            if (embed != null)
+                embed.syncMappingInfo();
+        }
+    }
+
+    public void copyMappingInfo(ValueMapping vm) {
+        setValueMappedBy(vm.getValueMappedBy());
+        setPolymorphic(vm.getPolymorphic());
+        _info.copy(vm.getValueInfo());
+
+        ClassMapping embed = vm.getEmbeddedMapping();
+        if (embed != null && getEmbeddedMapping() != null) {
+            FieldMapping[] tmplates = embed.getFieldMappings();
+            FieldMapping[] fms = getEmbeddedMapping().getFieldMappings();
+            if (tmplates.length == fms.length)
+                for (int i = 0; i < fms.length; i++)
+                    fms[i].copyMappingInfo(tmplates[i]);
+        }
+    }
+
+    public boolean resolve(int mode) {
+        int cur = getResolve();
+        if (super.resolve(mode))
+            return true;
+        ClassMapping embed = getEmbeddedMapping();
+        if (embed != null)
+            embed.resolve(mode);
+        if ((mode & MODE_MAPPING) != 0 && (cur & MODE_MAPPING) == 0)
+            resolveMapping();
+        if ((mode & MODE_MAPPING_INIT) != 0 && (cur & MODE_MAPPING_INIT) == 0)
+            initializeMapping();
+        return false;
+    }
+
+    /**
+     * Setup mapping. Our handler will already have been set by our owning
+     * field.
+     */
+    private void resolveMapping() {
+        // mark mapped columns
+        Column[] cols;
+        int insertFlag, updateFlag;
+        if (_fk != null) {
+            cols = _fk.getColumns();
+            insertFlag = Column.FLAG_FK_INSERT;
+            updateFlag = Column.FLAG_FK_UPDATE;
+        } else {
+            cols = getColumns();
+            insertFlag = Column.FLAG_DIRECT_INSERT;
+            updateFlag = Column.FLAG_DIRECT_UPDATE;
+        }
+        ColumnIO io = getColumnIO();
+        for (int i = 0; i < cols.length; i++) {
+            if (io.isInsertable(i, false))
+                cols[i].setFlag(insertFlag, true);
+            if (io.isUpdatable(i, false))
+                cols[i].setFlag(insertFlag, true);
+        }
+    }
+
+    /**
+     * Prepare mapping for runtime use.
+     */
+    private void initializeMapping() {
+        if (_fk == null)
+            return;
+
+        // if our fk cols are direct mapped by other values, make them
+        // non-nullable
+        Column[] cols = _fk.getColumns();
+        for (int i = 0; i < cols.length; i++) {
+            if (cols[i].getFlag(Column.FLAG_DIRECT_INSERT))
+                newIO().setNullInsertable(i, false);
+            if (cols[i].getFlag(Column.FLAG_DIRECT_UPDATE))
+                newIO().setNullUpdatable(i, false);
+        }
+
+        // if anything maps our constant fk cols, make them read only
+        int len = cols.length;
+        cols = _fk.getConstantColumns();
+        for (int i = 0; i < cols.length; i++) {
+            if (cols[i].getFlag(Column.FLAG_DIRECT_INSERT)
+                || cols[i].getFlag(Column.FLAG_FK_INSERT))
+                newIO().setInsertable(len + i, false);
+            if (cols[i].getFlag(Column.FLAG_DIRECT_UPDATE)
+                || cols[i].getFlag(Column.FLAG_FK_UPDATE))
+                newIO().setUpdatable(len + i, false);
+        }
+    }
+
+    /**
+     * Return the column I/O information, creating it if necessary.
+     */
+    private ColumnIO newIO() {
+        if (_io == null)
+            _io = new ColumnIO();
+        return _io;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingImpl.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingInfo.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingInfo.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingInfo.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingInfo.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,318 @@
+/*
+ * 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.util.List;
+
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ColumnIO;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.schema.Index;
+import org.apache.openjpa.jdbc.schema.SchemaGroup;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.jdbc.schema.Unique;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.util.MetaDataException;
+
+/**
+ * Information about the mapping from a field value to the schema, in
+ * raw form. The columns and tables used in mapping info will not be part of
+ * the {@link SchemaGroup} used at runtime. Rather, they will be structs
+ * with the relevant pieces of information filled in.
+ *
+ * @author Abe White
+ */
+public class ValueMappingInfo
+    extends MappingInfo {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (ValueMappingInfo.class);
+
+    private boolean _criteria = false;
+    private boolean _canNull = true;
+
+    /**
+     * Whether to use class criteria when joining to related type.
+     */
+    public boolean getUseClassCriteria() {
+        return _criteria;
+    }
+
+    /**
+     * Whether to use class criteria when joining to related type.
+     */
+    public void setUseClassCriteria(boolean criteria) {
+        _criteria = criteria;
+    }
+
+    /**
+     * Whether user has explicitly turned null indicator column off.
+     */
+    public boolean canIndicateNull() {
+        return _canNull;
+    }
+
+    /**
+     * Whether user has explicitly turned null indicator column off.
+     */
+    public void setCanIndicateNull(boolean ind) {
+        _canNull = ind;
+    }
+
+    /**
+     * Return the join from this value to its related type.
+     *
+     * @param name base name for value mapping
+     * @param inversable whether an inverse join is allowed
+     */
+    public ForeignKey getTypeJoin(final ValueMapping val, final String name,
+        boolean inversable, boolean adapt) {
+        ClassMapping rel = val.getTypeMapping();
+        if (rel == null)
+            return null;
+
+        ForeignKeyDefaults def = new ForeignKeyDefaults() {
+            public ForeignKey get(Table local, Table foreign, boolean inverse) {
+                return val.getMappingRepository().getMappingDefaults().
+                    getForeignKey(val, name, local, foreign, inverse);
+            }
+
+            public void populate(Table local, Table foreign, Column col,
+                Object target, boolean inverse, int pos, int cols) {
+                val.getMappingRepository().getMappingDefaults().
+                    populateForeignKeyColumn(val, name, local, foreign, col,
+                        target, inverse, pos, cols);
+            }
+        };
+        return createForeignKey(val, null, getColumns(), def,
+            val.getFieldMapping().getTable(), val.getFieldMapping().
+            getDefiningMapping(), rel, inversable, adapt);
+    }
+
+    /**
+     * Return the join from the related type to this value.
+     */
+    public ForeignKey getInverseTypeJoin(final ValueMapping val,
+        final String name, boolean adapt) {
+        ClassMapping rel = val.getTypeMapping();
+        if (rel == null || rel.getTable() == null)
+            return null;
+
+        ForeignKeyDefaults def = new ForeignKeyDefaults() {
+            public ForeignKey get(Table local, Table foreign, boolean inverse) {
+                return val.getMappingRepository().getMappingDefaults().
+                    getForeignKey(val, name, local, foreign, !inverse);
+            }
+
+            public void populate(Table local, Table foreign, Column col,
+                Object target, boolean inverse, int pos, int cols) {
+                val.getMappingRepository().getMappingDefaults().
+                    populateForeignKeyColumn(val, name, local, foreign, col,
+                        target, !inverse, pos, cols);
+            }
+        };
+        return createForeignKey(val, null, getColumns(), def, rel.getTable(),
+            rel, val.getFieldMapping().getDefiningMapping(), false, adapt);
+    }
+
+    /**
+     * Return the columns for this value, based on the given templates.
+     */
+    public Column[] getColumns(ValueMapping val, String name,
+        Column[] tmplates, Table table, boolean adapt) {
+        orderColumnsByTargetField(val, tmplates, adapt);
+        val.getMappingRepository().getMappingDefaults().populateColumns
+            (val, name, table, tmplates);
+        return createColumns(val, null, tmplates, table, adapt);
+    }
+
+    /**
+     * Make given columns match up with the target fields supplied on the
+     * templates.
+     */
+    private void orderColumnsByTargetField(ValueMapping val, Column[] tmplates,
+        boolean adapt) {
+        if (tmplates.length < 2 || tmplates[0].getTargetField() == null)
+            return;
+        List cols = getColumns();
+        if (cols.isEmpty() || cols.size() != tmplates.length)
+            return;
+
+        int pos = 0;
+        Column cur = (Column) cols.get(0);
+        Column next;
+        for (int i = 0; i < cols.size(); i++) {
+            if (cur.getTargetField() == null)
+                throw new MetaDataException(_loc.get("no-targetfield", val));
+
+            pos = findTargetField(tmplates, cur.getTargetField());
+            if (pos == -1)
+                throw new MetaDataException(_loc.get("bad-targetfield",
+                    val, cur.getTargetField()));
+
+            next = (Column) cols.get(pos);
+            cols.set(pos, cur);
+            cur = next;
+        }
+    }
+
+    /**
+     * Return the position of the template column with the given target field.
+     */
+    public int findTargetField(Column[] tmplates, String target) {
+        for (int i = 0; i < tmplates.length; i++)
+            if (target.equals(tmplates[i].getTargetField()))
+                return i;
+        return -1;
+    }
+
+    /**
+     * Return a unique constraint for the given columns, or null if none.
+     */
+    public Unique getUnique(ValueMapping val, String name, boolean adapt) {
+        Column[] cols = val.getColumns();
+        if (cols.length == 0)
+            return null;
+
+        Unique unq = val.getMappingRepository().getMappingDefaults().
+            getUnique(val, name, cols[0].getTable(), cols);
+        return createUnique(val, null, unq, cols, adapt);
+    }
+
+    /**
+     * Return an index for the given columns, or null if none.
+     */
+    public Index getIndex(ValueMapping val, String name, boolean adapt) {
+        Column[] cols = val.getColumns();
+        if (cols.length == 0)
+            return null;
+
+        Index idx = val.getMappingRepository().getMappingDefaults().
+            getIndex(val, name, cols[0].getTable(), cols);
+        return createIndex(val, null, idx, cols, adapt);
+    }
+
+    /**
+     * Return the null indicator column for this value, or null if none.
+     */
+    public Column getNullIndicatorColumn(ValueMapping val, String name,
+        Table table, boolean adapt) {
+        // reset IO
+        setColumnIO(null);
+
+        // has the user explicitly turned null indicator off?
+        if (!_canNull)
+            return null;
+
+        // extract given null-ind column
+        List cols = getColumns();
+        Column given = (cols.isEmpty()) ? null : (Column) cols.get(0);
+        MappingDefaults def = val.getMappingRepository().getMappingDefaults();
+        if (given == null && (!adapt && !def.defaultMissingInfo()))
+            return null;
+
+        Column tmplate = new Column();
+        tmplate.setName(name + "_null");
+        tmplate.setJavaType(JavaTypes.INT);
+        if (!def.populateNullIndicatorColumns(val, name, table, new Column[]
+            { tmplate }) && given == null)
+            return null;
+
+        if (given != null && (given.getFlag(Column.FLAG_UNINSERTABLE)
+            || given.getFlag(Column.FLAG_UNUPDATABLE))) {
+            ColumnIO io = new ColumnIO();
+            io.setInsertable(0, !given.getFlag(Column.FLAG_UNINSERTABLE));
+            io.setUpdatable(0, !given.getFlag(Column.FLAG_UNUPDATABLE));
+            setColumnIO(io);
+        }
+
+        if (given != null && given.getName() != null) {
+            // test if given column name is actually a field name, in which
+            // case we use its column as the null indicator column
+            ClassMapping embed = val.getEmbeddedMapping();
+            FieldMapping efm = (embed == null) ? null
+                : embed.getFieldMapping(given.getName());
+            if (efm != null && efm.getColumns().length > 0)
+                given.setName(efm.getColumns()[0].getName());
+        }
+        boolean compat = given == null || given.getName() == null
+            || table == null || !table.isNameTaken(given.getName());
+
+        return mergeColumn(val, "null-ind", tmplate, compat, given,
+            table, adapt, def.defaultMissingInfo());
+    }
+
+    /**
+     * Synchronize internal information with the mapping data for the given
+     * value.
+     */
+    public void syncWith(ValueMapping val) {
+        clear(false);
+
+        _criteria = val.getUseClassCriteria();
+        setColumnIO(val.getColumnIO());
+        if (val.getForeignKey() != null && val.getTypeMapping() != null
+            && val.getTypeMapping().getTable() != null) {
+            FieldMapping fm = val.getFieldMapping();
+            Table local = (fm.getJoinForeignKey() != null) ? fm.getTable()
+                : fm.getDefiningMapping().getTable();
+            Table foreign;
+            if (val.getJoinDirection() == ValueMapping.JOIN_EXPECTED_INVERSE) {
+                foreign = local;
+                local = val.getTypeMapping().getTable();
+                setJoinDirection(JOIN_FORWARD);
+            } else {
+                foreign = val.getTypeMapping().getTable();
+                setJoinDirection((val.getJoinDirection() == val.JOIN_FORWARD)
+                    ? JOIN_FORWARD : JOIN_INVERSE);
+            }
+            syncForeignKey(val, val.getForeignKey(), local, foreign);
+        } else
+            syncColumns(val, val.getColumns(), false);
+
+        syncIndex(val, val.getValueIndex());
+        syncUnique(val, val.getValueUnique());
+
+        // explicit handler strategy if the handler isn't the expected default
+        if (val.getHandler() != null) {
+            ValueHandler def = val.getFieldMapping().getMappingRepository().
+                defaultHandler(val);
+            if (def == null || val.getHandler().getClass() != def.getClass())
+                setStrategy(val.getHandler().getClass().getName());
+        }
+    }
+
+    protected void clear(boolean canFlags) {
+        super.clear(canFlags);
+        if (canFlags) {
+            _criteria = false;
+            _canNull = true;
+        }
+    }
+
+    public void copy(MappingInfo info) {
+        super.copy(info);
+        if (!(info instanceof ValueMappingInfo))
+            return;
+
+        ValueMappingInfo vinfo = (ValueMappingInfo) info;
+        if (!_criteria)
+            _criteria = vinfo.getUseClassCriteria();
+        if (_canNull)
+            _canNull = vinfo.canIndicateNull();
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingInfo.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/Version.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/Version.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/Version.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/Version.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,365 @@
+/*
+ * 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.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ColumnIO;
+import org.apache.openjpa.jdbc.schema.Index;
+import org.apache.openjpa.jdbc.schema.Schemas;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.RowManager;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.MetaDataContext;
+import org.apache.openjpa.meta.MetaDataModes;
+import org.apache.openjpa.meta.MetaDataRepository;
+import org.apache.openjpa.util.InternalException;
+
+/**
+ * Handles optimistic lock versioning for a class.
+ *
+ * @author Abe White
+ */
+public class Version
+    implements VersionStrategy, MetaDataContext, MetaDataModes {
+
+    private static final Localizer _loc = Localizer.forPackage(Version.class);
+
+    private final ClassMapping _mapping;
+    private final VersionMappingInfo _info;
+    private VersionStrategy _strategy = null;
+    private int _resMode = MODE_NONE;
+
+    private Column[] _cols = Schemas.EMPTY_COLUMNS;
+    private ColumnIO _io = null;
+    private Index _idx = null;
+
+    /**
+     * Constructor. Supply owning mapping.
+     */
+    public Version(ClassMapping mapping) {
+        _mapping = mapping;
+        _info = getMappingRepository().newMappingInfo(this);
+    }
+
+    public MetaDataRepository getRepository() {
+        return _mapping.getRepository();
+    }
+
+    public MappingRepository getMappingRepository() {
+        return _mapping.getMappingRepository();
+    }
+
+    /**
+     * Return the owning mapping.
+     */
+    public ClassMapping getClassMapping() {
+        return _mapping;
+    }
+
+    /**
+     * The strategy used for versioning.
+     */
+    public VersionStrategy getStrategy() {
+        return _strategy;
+    }
+
+    /**
+     * The strategy used for versioning. The <code>adapt</code>
+     * parameter determines whether to adapt when mapping the strategy;
+     * use null if the strategy should not be mapped.
+     */
+    public void setStrategy(VersionStrategy strategy, Boolean adapt) {
+        // set strategy first so we can access it during mapping
+        VersionStrategy orig = _strategy;
+        _strategy = strategy;
+        if (strategy != null) {
+            try {
+                strategy.setVersion(this);
+                if (adapt != null)
+                    strategy.map(adapt.booleanValue());
+            } catch (RuntimeException re) {
+                // reset strategy
+                _strategy = orig;
+                throw re;
+            }
+        }
+    }
+
+    /**
+     * Raw mapping data.
+     */
+    public VersionMappingInfo getMappingInfo() {
+        return _info;
+    }
+
+    /**
+     * Columns used for versioning.
+     */
+    public Column[] getColumns() {
+        return _cols;
+    }
+
+    /**
+     * Columns used for versioning.
+     */
+    public void setColumns(Column[] cols) {
+        if (cols == null)
+            cols = Schemas.EMPTY_COLUMNS;
+        _cols = cols;
+    }
+
+    /**
+     * I/O information on the version columns.
+     */
+    public ColumnIO getColumnIO() {
+        return (_io == null) ? ColumnIO.UNRESTRICTED : _io;
+    }
+
+    /**
+     * I/O information on the version columns.
+     */
+    public void setColumnIO(ColumnIO io) {
+        _io = io;
+    }
+
+    /**
+     * Index on the version columns, or null if none.
+     */
+    public Index getIndex() {
+        return _idx;
+    }
+
+    /**
+     * Index on the version columns, or null if none.
+     */
+    public void setIndex(Index idx) {
+        _idx = idx;
+    }
+
+    /**
+     * Increment the reference count of used schema components.
+     */
+    public void refSchemaComponents() {
+        for (int i = 0; i < _cols.length; i++)
+            _cols[i].ref();
+    }
+
+    /**
+     * Clear mapping information, including strategy.
+     */
+    public void clearMapping() {
+        _strategy = null;
+        _cols = Schemas.EMPTY_COLUMNS;
+        _idx = null;
+        _info.clear();
+        setResolve(MODE_MAPPING | MODE_MAPPING_INIT, false);
+    }
+
+    /**
+     * Update {@link MappingInfo} with our current mapping information.
+     */
+    public void syncMappingInfo() {
+        _info.syncWith(this);
+
+        // setup the version field with our mapping info
+        FieldMapping fm = _mapping.getVersionFieldMapping();
+        if (fm != null) {
+            // erase explicit strategy if it is standard version strategy for
+            // field type
+            if (_info.getStrategy() != null
+                && _info.getStrategy().equals(getMappingRepository().
+                defaultStrategy(this, fm).getAlias()))
+                _info.setStrategy(null);
+
+            fm.getMappingInfo().clear();
+            fm.getValueInfo().clear();
+            fm.getKeyMapping().getValueInfo().clear();
+            fm.getElementMapping().getValueInfo().clear();
+            fm.getValueInfo().copy(_info);
+            _info.clear();
+        }
+    }
+
+    /**
+     * Resolve mode.
+     */
+    public int getResolve() {
+        return _resMode;
+    }
+
+    /**
+     * Resolve mode.
+     */
+    public void setResolve(int mode) {
+        _resMode = mode;
+    }
+
+    /**
+     * Resolve mode.
+     */
+    public void setResolve(int mode, boolean on) {
+        if (mode == MODE_NONE)
+            _resMode = mode;
+        else if (on)
+            _resMode |= mode;
+        else
+            _resMode &= ~mode;
+    }
+
+    /**
+     * Resolve mapping information.
+     */
+    public boolean resolve(int mode) {
+        if ((_resMode & mode) == mode)
+            return true;
+        int cur = _resMode;
+        _resMode |= mode;
+        if ((mode & MODE_MAPPING) != 0 && (cur & MODE_MAPPING) == 0)
+            resolveMapping();
+        if ((mode & MODE_MAPPING_INIT) != 0 && (cur & MODE_MAPPING_INIT) == 0)
+            _strategy.initialize();
+        return false;
+    }
+
+    /**
+     * Setup mapping.
+     */
+    private void resolveMapping() {
+        // if there is a version field, copy mapping info from it
+        FieldMapping fm = _mapping.getVersionFieldMapping();
+        if (fm != null)
+            _info.copy(fm.getValueInfo());
+
+        // map strategy
+        MappingRepository repos = getMappingRepository();
+        if (_strategy == null)
+            repos.getStrategyInstaller().installStrategy(this);
+        Log log = repos.getLog();
+        if (log.isTraceEnabled())
+            log.trace(_loc.get("strategy", this, _strategy.getAlias()));
+
+        // mark columns as mapped
+        Column[] cols = getColumns();
+        ColumnIO io = getColumnIO();
+        for (int i = 0; i < cols.length; i++) {
+            if (io.isInsertable(i, false))
+                cols[i].setFlag(Column.FLAG_DIRECT_INSERT, true);
+            if (io.isUpdatable(i, false))
+                cols[i].setFlag(Column.FLAG_DIRECT_UPDATE, true);
+        }
+    }
+
+    //////////////////////////////////
+    // VersionStrategy implementation
+    //////////////////////////////////
+
+    public String getAlias() {
+        return assertStrategy().getAlias();
+    }
+
+    public void map(boolean adapt) {
+        assertStrategy().map(adapt);
+    }
+
+    public void initialize() {
+        assertStrategy().initialize();
+    }
+
+    public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException {
+        assertStrategy().insert(sm, store, rm);
+    }
+
+    public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException {
+        assertStrategy().update(sm, store, rm);
+    }
+
+    public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException {
+        assertStrategy().delete(sm, store, rm);
+    }
+
+    public Boolean isCustomInsert(OpenJPAStateManager sm, JDBCStore store) {
+        return assertStrategy().isCustomInsert(sm, store);
+    }
+
+    public Boolean isCustomUpdate(OpenJPAStateManager sm, JDBCStore store) {
+        return assertStrategy().isCustomUpdate(sm, store);
+    }
+
+    public Boolean isCustomDelete(OpenJPAStateManager sm, JDBCStore store) {
+        return assertStrategy().isCustomDelete(sm, store);
+    }
+
+    public void customInsert(OpenJPAStateManager sm, JDBCStore store)
+        throws SQLException {
+        assertStrategy().customInsert(sm, store);
+    }
+
+    public void customUpdate(OpenJPAStateManager sm, JDBCStore store)
+        throws SQLException {
+        assertStrategy().customUpdate(sm, store);
+    }
+
+    public void customDelete(OpenJPAStateManager sm, JDBCStore store)
+        throws SQLException {
+        assertStrategy().customDelete(sm, store);
+    }
+
+    public void setVersion(Version owner) {
+        assertStrategy().setVersion(owner);
+    }
+
+    public boolean select(Select sel, ClassMapping mapping) {
+        return assertStrategy().select(sel, mapping);
+    }
+
+    public void load(OpenJPAStateManager sm, JDBCStore store, Result res)
+        throws SQLException {
+        assertStrategy().load(sm, store, res);
+    }
+
+    public void afterLoad(OpenJPAStateManager sm, JDBCStore store) {
+        assertStrategy().afterLoad(sm, store);
+    }
+
+    public boolean checkVersion(OpenJPAStateManager sm, JDBCStore store,
+        boolean updateVersion)
+        throws SQLException {
+        return assertStrategy().checkVersion(sm, store, updateVersion);
+    }
+
+    public int compareVersion(Object v1, Object v2) {
+        return assertStrategy().compareVersion(v1, v2);
+    }
+
+    private VersionStrategy assertStrategy() {
+        if (_strategy == null)
+            throw new InternalException();
+        return _strategy;
+    }
+
+    public String toString() {
+        return _mapping + "<version>";
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/Version.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/VersionMappingInfo.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/VersionMappingInfo.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/VersionMappingInfo.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/VersionMappingInfo.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,90 @@
+/*
+ * 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 org.apache.openjpa.jdbc.meta.strats.NoneVersionStrategy;
+import org.apache.openjpa.jdbc.meta.strats.SuperclassVersionStrategy;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Index;
+import org.apache.openjpa.jdbc.schema.SchemaGroup;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.lib.util.Localizer;
+
+/**
+ * Information about the mapping from a version indicator to the schema, in
+ * raw form. The columns and tables used in mapping info will not be part of
+ * the {@link SchemaGroup} used at runtime. Rather, they will be structs
+ * with the relevant pieces of information filled in.
+ *
+ * @author Abe White
+ */
+public class VersionMappingInfo
+    extends MappingInfo {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (VersionMappingInfo.class);
+
+    /**
+     * Return the columns set for this version, based on the given templates.
+     */
+    public Column[] getColumns(Version version, Column[] tmplates,
+        boolean adapt) {
+        Table table = version.getClassMapping().getTable();
+        version.getMappingRepository().getMappingDefaults().populateColumns
+            (version, table, tmplates);
+        return createColumns(version, null, tmplates, table, adapt);
+    }
+
+    /**
+     * Return the index to set on the version columns, or null if none.
+     */
+    public Index getIndex(Version version, Column[] cols, boolean adapt) {
+        Index idx = null;
+        if (cols.length > 0)
+            idx = version.getMappingRepository().getMappingDefaults().
+                getIndex(version, cols[0].getTable(), cols);
+        return createIndex(version, null, idx, cols, adapt);
+    }
+
+    /**
+     * Synchronize internal information with the mapping data for the given
+     * version.
+     */
+    public void syncWith(Version version) {
+        clear(false);
+
+        ClassMapping cls = version.getClassMapping();
+        Column[] cols = version.getColumns();
+
+        setColumnIO(version.getColumnIO());
+        syncColumns(version, cols, false);
+        syncIndex(version, version.getIndex());
+
+        if (version.getStrategy() == null
+            || version.getStrategy()instanceof SuperclassVersionStrategy)
+            return;
+
+        // explicit version strategy if:
+        // - unmapped class and version mapped
+        // - mapped base class
+        // - mapped subclass that doesn't rely on superclass version
+        String strat = version.getStrategy().getAlias();
+        if ((!cls.isMapped() && !NoneVersionStrategy.ALIAS.equals(strat))
+            || (cls.isMapped()
+            && cls.getJoinablePCSuperclassMapping() == null))
+            setStrategy(strat);
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/VersionMappingInfo.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/VersionStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/VersionStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/VersionStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/VersionStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,74 @@
+/*
+ * 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.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.kernel.StoreManager;
+
+/**
+ * Handles optimistic lock versioning for a class.
+ *
+ * @author Abe White
+ */
+public interface VersionStrategy
+    extends Strategy {
+
+    /**
+     * Set the version that uses this strategy. This will be called before use.
+     */
+    public void setVersion(Version owner);
+
+    /**
+     * Select the data for this indicator.
+     *
+     * @param mapping the known base class being selected; this may
+     * not be the base class in the inheritance hierarchy
+     * @return true if anything was selected; false otherwise
+     */
+    public boolean select(Select sel, ClassMapping mapping);
+
+    /**
+     * Load data.
+     */
+    public void load(OpenJPAStateManager sm, JDBCStore store, Result res)
+        throws SQLException;
+
+    /**
+     * This method is called after data is loaded into the instance, in
+     * case the version indicator works off of a state image.
+     */
+    public void afterLoad(OpenJPAStateManager sm, JDBCStore store);
+
+    /**
+     * Checks the version of the given state manager with the version
+     * stored in memory.
+     *
+     * @return true if the in-memory version was up-to-date, false otherwise
+     */
+    public boolean checkVersion(OpenJPAStateManager sm, JDBCStore store,
+        boolean updateVersion)
+        throws SQLException;
+
+    /**
+     * @see StoreManager#compareVersion
+     */
+    public int compareVersion(Object v1, Object v2);
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/VersionStrategy.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/package.html
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/package.html?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/package.html (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/package.html Wed Jul 19 14:34:44 2006
@@ -0,0 +1,10 @@
+<html>
+<body>
+<p><strong>OpenJPA-JDBC ORM Metadata</strong></p>
+
+<p>
+    This package extends the standard persistence metadata with
+    object-relational mapping information.
+</p>
+</body>
+</html>

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/package.html
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractClassStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractClassStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractClassStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractClassStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,79 @@
+/*
+ * 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.strats;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.ClassStrategy;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.kernel.PCState;
+import org.apache.openjpa.lib.rop.ResultObjectProvider;
+
+/**
+ * No-op strategy for easy extension.
+ *
+ * @author Abe White
+ */
+public abstract class AbstractClassStrategy
+    extends AbstractStrategy
+    implements ClassStrategy {
+
+    /**
+     * The owning class mapping.
+     */
+    protected ClassMapping cls = null;
+
+    public void setClassMapping(ClassMapping owner) {
+        cls = owner;
+    }
+
+    public boolean isPrimaryKeyObjectId(boolean hasAll) {
+        return false;
+    }
+
+    public Joins joinSuperclass(Joins joins, boolean toThis) {
+        return joins;
+    }
+
+    public boolean supportsEagerSelect(Select sel, OpenJPAStateManager sm,
+        JDBCStore store, ClassMapping base, JDBCFetchConfiguration fetch) {
+        return true;
+    }
+
+    public ResultObjectProvider customLoad(JDBCStore store, boolean subclasses,
+        JDBCFetchConfiguration fetch, long startIdx, long endIdx)
+        throws SQLException {
+        return null;
+    }
+
+    public boolean customLoad(OpenJPAStateManager sm, JDBCStore store,
+        PCState state, JDBCFetchConfiguration fetch)
+        throws SQLException, ClassNotFoundException {
+        return false;
+    }
+
+    public boolean customLoad(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchConfiguration fetch, Result result)
+        throws SQLException {
+        return false;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractClassStrategy.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractDiscriminatorStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractDiscriminatorStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractDiscriminatorStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractDiscriminatorStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,89 @@
+/*
+ * 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.strats;
+
+import java.lang.reflect.Modifier;
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.Discriminator;
+import org.apache.openjpa.jdbc.meta.DiscriminatorStrategy;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.util.Localizer;
+
+/**
+ * No-op strategy for easy extension.
+ *
+ * @author Abe White
+ */
+public abstract class AbstractDiscriminatorStrategy
+    extends AbstractStrategy
+    implements DiscriminatorStrategy {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (AbstractDiscriminatorStrategy.class);
+
+    /**
+     * The owning discriminator.
+     */
+    protected Discriminator disc = null;
+
+    /**
+     * Whether the owning class is final.
+     */
+    protected boolean isFinal = false;
+
+    public void setDiscriminator(Discriminator owner) {
+        disc = owner;
+        ClassMapping cls = disc.getClassMapping();
+        isFinal = Modifier.isFinal(cls.getDescribedType().getModifiers());
+    }
+
+    public boolean select(Select sel, ClassMapping mapping) {
+        return false;
+    }
+
+    /**
+     * By default, logs a warning that this discriminator cannot calculate
+     * its list of subclasses on its own.
+     */
+    public void loadSubclasses(JDBCStore store)
+        throws SQLException, ClassNotFoundException {
+        if (!isFinal) {
+            Log log = disc.getMappingRepository().getLog();
+            if (log.isWarnEnabled())
+                log.warn(_loc.get("cant-init-subs", disc.getClassMapping()));
+        }
+
+        // don't need to call this method again
+        disc.setSubclassesLoaded(true);
+    }
+
+    public Class getClass(JDBCStore store, ClassMapping base, Result result)
+        throws SQLException, ClassNotFoundException {
+        return base.getDescribedType();
+    }
+
+    public SQLBuffer getClassConditions(JDBCStore store, Select sel,
+        Joins joins, ClassMapping base, boolean subs) {
+        return null;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractDiscriminatorStrategy.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractFieldStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractFieldStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractFieldStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractFieldStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,174 @@
+/*
+ * 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.strats;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.meta.FieldStrategy;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.RowManager;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.jdbc.sql.SelectExecutor;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.MetaDataException;
+
+/**
+ * No-op strategy for easy extension.
+ *
+ * @author Abe White
+ */
+public abstract class AbstractFieldStrategy
+    extends AbstractStrategy
+    implements FieldStrategy {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (AbstractFieldStrategy.class);
+
+    /**
+     * The owning field mapping.
+     */
+    protected FieldMapping field = null;
+
+    /**
+     * Throws an informative exception if the field declares a mapped-by value.
+     */
+    protected void assertNotMappedBy() {
+        if (field != null && field.getMappedBy() != null)
+            throw new MetaDataException(_loc.get("cant-mapped-by", field,
+                getAlias()));
+    }
+
+    public void setFieldMapping(FieldMapping owner) {
+        field = owner;
+    }
+
+    public int supportsSelect(Select sel, int type, OpenJPAStateManager sm,
+        JDBCStore store, JDBCFetchConfiguration fetch) {
+        return 0;
+    }
+
+    public void selectEagerJoin(Select sel, OpenJPAStateManager sm,
+        JDBCStore store, JDBCFetchState fetchState, int eagerMode) {
+    }
+
+    public void selectEagerParallel(SelectExecutor sel, OpenJPAStateManager sm,
+        JDBCStore store, JDBCFetchState fetchState, int eagerMode) {
+    }
+
+    public boolean isEagerSelectToMany() {
+        return false;
+    }
+
+    public int select(Select sel, OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, int eagerMode) {
+        return -1;
+    }
+
+    public Object loadEagerParallel(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, Object res)
+        throws SQLException {
+        return res;
+    }
+
+    public void loadEagerJoin(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, Result res)
+        throws SQLException {
+    }
+
+    public void load(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, Result res)
+        throws SQLException {
+    }
+
+    public void load(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState)
+        throws SQLException {
+    }
+
+    public Object toDataStoreValue(Object val, JDBCStore store) {
+        return val;
+    }
+
+    public Object toKeyDataStoreValue(Object val, JDBCStore store) {
+        return val;
+    }
+
+    public void appendIsEmpty(SQLBuffer sql, Select sel, Joins joins) {
+        sql.append("1 <> 1");
+    }
+
+    public void appendIsNotEmpty(SQLBuffer sql, Select sel, Joins joins) {
+        sql.append("1 = 1");
+    }
+
+    public void appendIsNull(SQLBuffer sql, Select sel, Joins joins) {
+        sql.append("1 <> 1");
+    }
+
+    public void appendIsNotNull(SQLBuffer sql, Select sel, Joins joins) {
+        sql.append("1 <> 1");
+    }
+
+    public void appendSize(SQLBuffer sql, Select sel, Joins joins) {
+        sql.append("1");
+    }
+
+    public Joins join(Joins joins, boolean forceOuter) {
+        return joins;
+    }
+
+    public Joins joinKey(Joins joins, boolean forceOuter) {
+        return joins;
+    }
+
+    public Joins joinRelation(Joins joins, boolean forceOuter,
+        boolean traverse) {
+        return joins;
+    }
+
+    public Joins joinKeyRelation(Joins joins, boolean forceOuter,
+        boolean traverse) {
+        return joins;
+    }
+
+    public Object loadProjection(JDBCStore store, JDBCFetchState fetchState,
+        Result res, Joins joins)
+        throws SQLException {
+        return null;
+    }
+
+    public Object loadKeyProjection(JDBCStore store,
+        JDBCFetchState fetchState, Result res, Joins joins)
+        throws SQLException {
+        return null;
+    }
+
+    public boolean isVersionable() {
+        return false;
+    }
+
+    public void where(OpenJPAStateManager sm, JDBCStore store, RowManager rm,
+        Object prevValue)
+        throws SQLException {
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractFieldStrategy.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,78 @@
+/*
+ * 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.strats;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.Strategy;
+import org.apache.openjpa.jdbc.sql.RowManager;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+
+/**
+ * No-op strategy for easy extension.
+ *
+ * @author Abe White
+ */
+public abstract class AbstractStrategy
+    implements Strategy {
+
+    public String getAlias() {
+        return getClass().getName();
+    }
+
+    public void map(boolean adapt) {
+    }
+
+    public void initialize() {
+    }
+
+    public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException {
+    }
+
+    public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException {
+    }
+
+    public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException {
+    }
+
+    public Boolean isCustomInsert(OpenJPAStateManager sm, JDBCStore store) {
+        return Boolean.FALSE;
+    }
+
+    public Boolean isCustomUpdate(OpenJPAStateManager sm, JDBCStore store) {
+        return Boolean.FALSE;
+    }
+
+    public Boolean isCustomDelete(OpenJPAStateManager sm, JDBCStore store) {
+        return Boolean.FALSE;
+    }
+
+    public void customInsert(OpenJPAStateManager sm, JDBCStore store)
+        throws SQLException {
+    }
+
+    public void customUpdate(OpenJPAStateManager sm, JDBCStore store)
+        throws SQLException {
+    }
+
+    public void customDelete(OpenJPAStateManager sm, JDBCStore store)
+        throws SQLException {
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/AbstractStrategy.java
------------------------------------------------------------------------------
    svn:executable = *