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 [21/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/strats/HandlerHandlerMapTableFieldStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,255 @@
+/*
+ * 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 java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.ValueHandler;
+import org.apache.openjpa.jdbc.meta.ValueMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ColumnIO;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.Row;
+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.util.Localizer;
+import org.apache.openjpa.util.ChangeTracker;
+import org.apache.openjpa.util.MetaDataException;
+import org.apache.openjpa.util.Proxies;
+import org.apache.openjpa.util.Proxy;
+
+/**
+ * Mapping for a map of keys and values both controlled by
+ * {@link ValueHandler}s.
+ *
+ * @author Abe White
+ * @since 4.0
+ */
+public class HandlerHandlerMapTableFieldStrategy
+    extends MapTableFieldStrategy {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (HandlerHandlerMapTableFieldStrategy.class);
+
+    private Column[] _kcols = null;
+    private ColumnIO _kio = null;
+    private boolean _kload = false;
+    private Column[] _vcols = null;
+    private ColumnIO _vio = null;
+    private boolean _vload = false;
+
+    public Column[] getKeyColumns(ClassMapping cls) {
+        return _kcols;
+    }
+
+    public Column[] getValueColumns(ClassMapping cls) {
+        return _vcols;
+    }
+
+    public void selectKey(Select sel, ClassMapping cls, OpenJPAStateManager sm,
+        JDBCStore store, JDBCFetchState fetchState, Joins joins) {
+        sel.select(_kcols, joins);
+    }
+
+    public void selectValue(Select sel, ClassMapping cls,
+        OpenJPAStateManager sm,
+        JDBCStore store, JDBCFetchState fetchState, Joins joins) {
+        sel.select(_vcols, joins);
+    }
+
+    public Result[] getResults(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, int eagerMode, Joins[] joins, boolean lrs)
+        throws SQLException {
+        Select sel = store.getSQLFactory().newSelect();
+        sel.setLRS(lrs);
+        sel.select(_kcols);
+        sel.select(_vcols);
+        sel.whereForeignKey(field.getJoinForeignKey(), sm.getObjectId(),
+            field.getDefiningMapping(), store);
+        Result res = sel.execute(store,
+            fetchState.getJDBCFetchConfiguration());
+        return new Result[]{ res, res };
+    }
+
+    public Object loadKey(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, Result res, Joins joins)
+        throws SQLException {
+        return HandlerStrategies.loadObject(field.getKeyMapping(),
+            sm, store, fetchState, res, joins, _kcols, _kload);
+    }
+
+    public Object loadValue(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, Result res, Joins joins)
+        throws SQLException {
+        return HandlerStrategies.loadObject(field.getElementMapping(),
+            sm, store, fetchState, res, joins, _vcols, _vload);
+    }
+
+    public void map(boolean adapt) {
+        super.map(adapt);
+
+        ValueMapping key = field.getKeyMapping();
+        if (key.getHandler() == null)
+            throw new MetaDataException(_loc.get("no-handler", key));
+        ValueMapping val = field.getElementMapping();
+        if (val.getHandler() == null)
+            throw new MetaDataException(_loc.get("no-handler", val));
+        assertNotMappedBy();
+
+        field.mapJoin(adapt, true);
+        _kio = new ColumnIO();
+        _kcols = HandlerStrategies.map(key, "key", _kio, adapt);
+        _vio = new ColumnIO();
+        _vcols = HandlerStrategies.map(val, "value", _vio, adapt);
+        field.mapPrimaryKey(adapt);
+    }
+
+    public void initialize() {
+        _kload = field.getKeyMapping().getHandler().
+            objectValueRequiresLoad(field.getKeyMapping());
+        _vload = field.getElementMapping().getHandler().
+            objectValueRequiresLoad(field.getElementMapping());
+    }
+
+    public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException {
+        insert(sm, store, rm, (Map) sm.fetchObject(field.getIndex()));
+    }
+
+    private void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm,
+        Map map)
+        throws SQLException {
+        if (map == null || map.isEmpty())
+            return;
+
+        Row row = rm.getSecondaryRow(field.getTable(), Row.ACTION_INSERT);
+        row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(),
+            sm);
+
+        ValueMapping key = field.getKeyMapping();
+        ValueMapping val = field.getElementMapping();
+        Map.Entry entry;
+        for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) {
+            entry = (Map.Entry) itr.next();
+            HandlerStrategies.set(key, entry.getKey(), store, row, _kcols,
+                _kio, true);
+            HandlerStrategies.set(val, entry.getValue(), store, row, _vcols,
+                _vio, true);
+            rm.flushSecondaryRow(row);
+        }
+    }
+
+    public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException {
+        Map map = (Map) sm.fetchObject(field.getIndex());
+        ChangeTracker ct = null;
+        if (map instanceof Proxy) {
+            Proxy proxy = (Proxy) map;
+            if (Proxies.isOwner(proxy, sm, field.getIndex()))
+                ct = proxy.getChangeTracker();
+        }
+
+        // if no fine-grained change tracking then just delete and reinsert
+        if (ct == null || !ct.isTracking()) {
+            delete(sm, store, rm);
+            insert(sm, store, rm, map);
+            return;
+        }
+
+        // delete the removes
+        ValueMapping key = field.getKeyMapping();
+        Collection rem = ct.getRemoved();
+        if (!rem.isEmpty()) {
+            Row delRow = rm.getSecondaryRow(field.getTable(),
+                Row.ACTION_DELETE);
+            delRow.setForeignKey(field.getJoinForeignKey(),
+                field.getJoinColumnIO(), sm);
+            for (Iterator itr = rem.iterator(); itr.hasNext();) {
+                HandlerStrategies.where(key, itr.next(), store, delRow,
+                    _kcols);
+                rm.flushSecondaryRow(delRow);
+            }
+        }
+
+        // insert the adds
+        ValueMapping val = field.getElementMapping();
+        Collection add = ct.getAdded();
+        Object mkey;
+        if (!add.isEmpty()) {
+            Row addRow = rm.getSecondaryRow(field.getTable(),
+                Row.ACTION_INSERT);
+            addRow.setForeignKey(field.getJoinForeignKey(),
+                field.getJoinColumnIO(), sm);
+
+            for (Iterator itr = add.iterator(); itr.hasNext();) {
+                mkey = itr.next();
+                HandlerStrategies.set(key, mkey, store, addRow, _kcols,
+                    _kio, true);
+                HandlerStrategies.set(val, map.get(mkey), store, addRow,
+                    _vcols, _vio, true);
+                rm.flushSecondaryRow(addRow);
+            }
+        }
+
+        // update the changes
+        Collection change = ct.getChanged();
+        if (!change.isEmpty()) {
+            Row changeRow = rm.getSecondaryRow(field.getTable(),
+                Row.ACTION_UPDATE);
+            changeRow.whereForeignKey(field.getJoinForeignKey(), sm);
+
+            for (Iterator itr = change.iterator(); itr.hasNext();) {
+                mkey = itr.next();
+                HandlerStrategies.where(key, mkey, store, changeRow, _kcols);
+                HandlerStrategies.set(val, map.get(mkey), store, changeRow,
+                    _vcols, _vio, true);
+                rm.flushSecondaryRow(changeRow);
+            }
+        }
+    }
+
+    public Object toDataStoreValue(Object val, JDBCStore store) {
+        return HandlerStrategies.toDataStoreValue(field.getElementMapping(),
+            val, _vcols, store);
+    }
+
+    public Object toKeyDataStoreValue(Object val, JDBCStore store) {
+        return HandlerStrategies.toDataStoreValue(field.getKeyMapping(), val,
+            _kcols, store);
+    }
+
+    public Joins joinRelation(Joins joins, boolean forceOuter,
+        boolean traverse) {
+        if (traverse)
+            HandlerStrategies.assertJoinable(field.getElementMapping());
+        return joins;
+    }
+
+    public Joins joinKeyRelation(Joins joins, boolean forceOuter,
+        boolean traverse) {
+        if (traverse)
+            HandlerStrategies.assertJoinable(field.getKeyMapping());
+        return joins;
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerStrategies.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerStrategies.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerStrategies.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerStrategies.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,258 @@
+/*
+ * 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.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.RelationId;
+import org.apache.openjpa.jdbc.meta.ValueHandler;
+import org.apache.openjpa.jdbc.meta.ValueMapping;
+import org.apache.openjpa.jdbc.meta.ValueMappingInfo;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ColumnIO;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.Row;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.InvalidStateException;
+
+/**
+ * Utility methods for strategies using value handlers.
+ *
+ * @author Abe White
+ * @since 4.0
+ */
+public class HandlerStrategies {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (HandlerStrategies.class);
+
+    /**
+     * Map the given value.
+     */
+    public static Column[] map(ValueMapping vm, String name, ColumnIO io,
+        boolean adapt) {
+        ValueMappingInfo vinfo = vm.getValueInfo();
+        vinfo.assertNoJoin(vm, true);
+        vinfo.assertNoForeignKey(vm, !adapt);
+
+        Column[] cols = vm.getHandler().map(vm, name, io, adapt);
+        if (cols.length > 0 && cols[0].getTable() == null) {
+            cols = vinfo.getColumns(vm, name, cols,
+                vm.getFieldMapping().getTable(), adapt);
+            ColumnIO mappedIO = vinfo.getColumnIO();
+            vm.setColumns(cols);
+            vm.setColumnIO(mappedIO);
+            if (mappedIO != null) {
+                for (int i = 0; i < cols.length; i++) {
+                    io.setInsertable(i, mappedIO.isInsertable(i, false));
+                    io.setNullInsertable(i, mappedIO.isInsertable(i, true));
+                    io.setUpdatable(i, mappedIO.isUpdatable(i, false));
+                    io.setNullUpdatable(i, mappedIO.isUpdatable(i, true));
+                }
+            }
+        }
+        vm.mapConstraints(name, adapt);
+        return cols;
+    }
+
+    /**
+     * Set the given value into the given row.
+     */
+    public static void set(ValueMapping vm, Object val, JDBCStore store,
+        Row row, Column[] cols, ColumnIO io, boolean nullNone)
+        throws SQLException {
+        if (!canSetAny(row, io, cols))
+            return;
+
+        ValueHandler handler = vm.getHandler();
+        val = handler.toDataStoreValue(vm, val, store);
+        if (val == null) {
+            for (int i = 0; i < cols.length; i++)
+                if (canSet(row, io, i, true))
+                    set(row, cols[i], null, handler, nullNone);
+        } else if (cols.length == 1) {
+            if (canSet(row, io, 0, val == null))
+                set(row, cols[0], val, handler, nullNone);
+        } else {
+            Object[] vals = (Object[]) val;
+            for (int i = 0; i < vals.length; i++)
+                if (canSet(row, io, i, vals[i] == null))
+                    set(row, cols[i], vals[i], handler, nullNone);
+        }
+    }
+
+    /**
+     * Return true if the given column index is settable.
+     */
+    private static boolean canSet(Row row, ColumnIO io, int i,
+        boolean nullValue) {
+        if (row.getAction() == Row.ACTION_INSERT)
+            return io.isInsertable(i, nullValue);
+        if (row.getAction() == Row.ACTION_UPDATE)
+            return io.isUpdatable(i, nullValue);
+        return true;
+    }
+
+    /**
+     * Return true if the any column up to the given index is settable.
+     */
+    private static boolean canSetAny(Row row, ColumnIO io, Column[] cols) {
+        if (row.getAction() == Row.ACTION_INSERT)
+            return io.isAnyInsertable(cols, false);
+        if (row.getAction() == Row.ACTION_UPDATE)
+            return io.isAnyUpdatable(cols, false);
+        return true;
+    }
+
+    /**
+     * Set a value into a row, taking care not to override column defualts
+     * with nulls unless the user wants us to.
+     */
+    private static void set(Row row, Column col, Object val,
+        ValueHandler handler, boolean nullNone)
+        throws SQLException {
+        if (val == null)
+            row.setNull(col, nullNone);
+        else if (col.isRelationId() && handler instanceof RelationId)
+            row.setRelationId(col, (OpenJPAStateManager) val,
+                (RelationId) handler);
+        else
+            row.setObject(col, val);
+    }
+
+    /**
+     * Add where conditions to the given row.
+     */
+    public static void where(ValueMapping vm, Object val, JDBCStore store,
+        Row row, Column[] cols)
+        throws SQLException {
+        if (cols.length == 0)
+            return;
+
+        val = toDataStoreValue(vm, val, cols, store);
+        if (val == null)
+            for (int i = 0; i < cols.length; i++)
+                row.whereNull(cols[i]);
+        else if (cols.length == 1)
+            where(row, cols[0], val);
+        else {
+            Object[] vals = (Object[]) val;
+            for (int i = 0; i < vals.length; i++)
+                where(row, cols[i], vals[i]);
+        }
+    }
+
+    /**
+     * Set a where condition on the given row.
+     */
+    private static void where(Row row, Column col, Object val)
+        throws SQLException {
+        if (val == null)
+            row.whereNull(col);
+        else
+            row.whereObject(col, val);
+    }
+
+    /**
+     * Load the Object value from the given result.
+     */
+    public static Object loadObject(ValueMapping vm, OpenJPAStateManager sm,
+        JDBCStore store, JDBCFetchState fetchState, Result res,
+        Joins joins, Column[] cols, boolean objectValueRequiresLoad)
+        throws SQLException {
+        if (cols.length == 0)
+            throw new InvalidStateException(_loc.get("cant-project-owned",
+                vm));
+
+        Object val = loadDataStore(vm, res, joins, cols);
+        if (objectValueRequiresLoad)
+            return vm.getHandler().toObjectValue(vm, val, sm, store,
+                fetchState);
+        return vm.getHandler().toObjectValue(vm, val);
+    }
+
+    /**
+     * Load the datastore value from the given result. This method does
+     * <b>not</b> process the loaded value through
+     * {@link ValueHandler#toObjectValue}.
+     */
+    public static Object loadDataStore(ValueMapping vm, Result res,
+        Joins joins, Column[] cols)
+        throws SQLException {
+        if (cols.length == 0)
+            return null;
+        if (cols.length == 1)
+            return res.getObject(cols[0], vm.getHandler().
+                getResultArgument(vm), joins);
+
+        Object[] vals = new Object[cols.length];
+        Object[] args = (Object[]) vm.getHandler().getResultArgument(vm);
+        for (int i = 0; i < cols.length; i++)
+            vals[i] = res.getObject(cols[i], (args == null) ? null : args[i],
+                joins);
+        return vals;
+    }
+
+    /**
+     * Convert the given object to its datastore value(s). Relation ids are
+     * converted to their final values immediately.
+     */
+    public static Object toDataStoreValue(ValueMapping vm, Object val,
+        Column[] cols, JDBCStore store) {
+        ValueHandler handler = vm.getHandler();
+        val = handler.toDataStoreValue(vm, val, store);
+        if (val == null) {
+            if (cols.length > 1)
+                return new Object[cols.length];
+            return null;
+        }
+
+        // relation ids are returned as state managers; resolve the final
+        // datastore value immediately
+        Object[] vals;
+        for (int i = 0; i < cols.length; i++) {
+            if (!cols[i].isRelationId())
+                continue;
+            if (!(handler instanceof RelationId))
+                break;
+            if (cols.length == 1) {
+                val = ((RelationId) handler).toRelationDataStoreValue
+                    ((OpenJPAStateManager) val, cols[i]);
+            } else {
+                vals = (Object[]) val;
+                vals[i] = ((RelationId) handler).toRelationDataStoreValue
+                    ((OpenJPAStateManager) vals[i], cols[i]);
+            }
+        }
+        return val;
+    }
+
+    /**
+     * Throw the proper exception if the given handler-controlled value
+     * represents an unjoinable relation.
+     */
+    public static void assertJoinable(ValueMapping vm) {
+        ClassMapping rel = vm.getTypeMapping();
+        if (rel != null && (rel.getTable() == null
+            || !rel.getTable().equals(vm.getFieldMapping().getTable())))
+            throw RelationStrategies.unjoinable(vm);
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/IdentityJoinable.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/IdentityJoinable.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/IdentityJoinable.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/IdentityJoinable.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,83 @@
+/*
+ * 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.ClassMapping;
+import org.apache.openjpa.jdbc.meta.Joinable;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.util.Id;
+import serp.util.Numbers;
+
+/**
+ * {@link Joinable} for the datastore identity column.
+ *
+ * @author Abe White
+ */
+class IdentityJoinable
+    implements Joinable {
+
+    private final ClassMapping mapping;
+
+    /**
+     * Constructor; supply datastore identity mapping.
+     */
+    public IdentityJoinable(ClassMapping mapping) {
+        this.mapping = mapping;
+    }
+
+    public int getFieldIndex() {
+        return -1;
+    }
+
+    public Object getPrimaryKeyValue(Result res, Column[] cols, ForeignKey fk,
+        Joins joins)
+        throws SQLException {
+        Column col = cols[0];
+        if (fk != null)
+            col = fk.getColumn(col);
+        long id = res.getLong(col);
+        if (id == 0 && res.wasNull())
+            return null;
+        return Numbers.valueOf(id);
+    }
+
+    public Column[] getColumns() {
+        return mapping.getPrimaryKeyColumns();
+    }
+
+    public Object getJoinValue(Object val, Column col, JDBCStore store) {
+        return val;
+    }
+
+    public Object getJoinValue(OpenJPAStateManager sm, Column col,
+        JDBCStore store) {
+        return Numbers.valueOf(((Id) sm.getObjectId()).getId());
+    }
+
+    public void setAutoAssignedValue(OpenJPAStateManager sm, JDBCStore store,
+        Column col, Object autogen) {
+        long id = ((Number) autogen).longValue();
+        sm.setObjectId(store.newDataStoreId(id, (ClassMapping)
+            sm.getMetaData(), true));
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ImmutableValueHandler.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ImmutableValueHandler.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ImmutableValueHandler.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ImmutableValueHandler.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,95 @@
+/*
+ * 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 org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
+import org.apache.openjpa.jdbc.meta.ValueMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ColumnIO;
+import org.apache.openjpa.meta.JavaTypes;
+
+/**
+ * Handler for simple type and string values.
+ *
+ * @nojavadoc
+ */
+public class ImmutableValueHandler
+    extends AbstractValueHandler {
+
+    private static final ImmutableValueHandler _instance =
+        new ImmutableValueHandler();
+
+    /**
+     * Singleton instance.
+     */
+    public static ImmutableValueHandler getInstance() {
+        return _instance;
+    }
+
+    public Column[] map(ValueMapping vm, String name, ColumnIO io,
+        boolean adapt) {
+        Column col = new Column();
+        col.setName(name);
+        if (vm.getTypeCode() == JavaTypes.DATE)
+            col.setJavaType(JavaSQLTypes.getDateTypeCode(vm.getType()));
+        else
+            col.setJavaType(vm.getTypeCode());
+        return new Column[]{ col };
+    }
+
+    public boolean isVersionable(ValueMapping vm) {
+        switch (vm.getTypeCode()) {
+            case JavaTypes.BOOLEAN:
+            case JavaTypes.BYTE:
+            case JavaTypes.CHAR:
+            case JavaTypes.INT:
+            case JavaTypes.LONG:
+            case JavaTypes.SHORT:
+            case JavaTypes.BOOLEAN_OBJ:
+            case JavaTypes.BYTE_OBJ:
+            case JavaTypes.CHAR_OBJ:
+            case JavaTypes.INT_OBJ:
+            case JavaTypes.LONG_OBJ:
+            case JavaTypes.SHORT_OBJ:
+            case JavaTypes.STRING:
+            case JavaTypes.DATE:
+            case JavaTypes.BIGINTEGER:
+            case JavaTypes.LOCALE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public Object toDataStoreValue(ValueMapping vm, Object val,
+        JDBCStore store) {
+        if (val != null)
+            return val;
+
+        FieldMapping field = vm.getFieldMapping();
+        if (field.getNullValue() != FieldMapping.NULL_DEFAULT)
+            return null;
+
+        Column[] cols = vm.getColumns();
+        if (cols[0].getDefaultString() != null)
+            return null;
+
+        // honor the user's null-value=default
+        return JavaSQLTypes.getEmptyValue(vm.getTypeCode());
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/InValueDiscriminatorStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/InValueDiscriminatorStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/InValueDiscriminatorStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/InValueDiscriminatorStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,144 @@
+/*
+ * 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.ClassMapping;
+import org.apache.openjpa.jdbc.meta.DiscriminatorMappingInfo;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Index;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.Row;
+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.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.util.MetaDataException;
+
+/**
+ * Base discriminator strategy that determines the class of database
+ * records using a column holding a value mapped to a class, and limits
+ * SELECTs using an IN (...) statement.
+ *
+ * @author Abe White
+ */
+public abstract class InValueDiscriminatorStrategy
+    extends AbstractDiscriminatorStrategy {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (InValueDiscriminatorStrategy.class);
+
+    /**
+     * Return the Java type code from {@link JavaTypes} for the discriminator
+     * values. This method is only used during mapping installation.
+     */
+    protected abstract int getJavaType();
+
+    /**
+     * Return the discriminator value for the given type.
+     */
+    protected abstract Object getDiscriminatorValue(ClassMapping cls);
+
+    /**
+     * Convert the given discriminator value to the corresponding class.
+     */
+    protected abstract Class getClass(Object val, JDBCStore store)
+        throws ClassNotFoundException;
+
+    public void map(boolean adapt) {
+        ClassMapping cls = disc.getClassMapping();
+        if (cls.getJoinablePCSuperclassMapping() != null
+            || cls.getEmbeddingMetaData() != null)
+            throw new MetaDataException(_loc.get("not-base-disc", cls));
+
+        DiscriminatorMappingInfo info = disc.getMappingInfo();
+        info.assertNoJoin(disc, true);
+        info.assertNoForeignKey(disc, !adapt);
+        info.assertNoUnique(disc, false);
+
+        Column tmplate = new Column();
+        tmplate.setJavaType(getJavaType());
+        tmplate.setName("typ");
+
+        Column[] cols = info.getColumns(disc, new Column[]{ tmplate }, adapt);
+        disc.setColumns(cols);
+        disc.setColumnIO(info.getColumnIO());
+
+        Index idx = info.getIndex(disc, cols, adapt);
+        disc.setIndex(idx);
+    }
+
+    public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException {
+        Row row = rm.getRow(disc.getClassMapping().getTable(),
+            Row.ACTION_INSERT, sm, true);
+        Object cls = getDiscriminatorValue((ClassMapping) sm.getMetaData());
+        if (disc.getColumnIO().isInsertable(0, cls == null))
+            row.setObject(disc.getColumns()[0], cls);
+    }
+
+    public boolean select(Select sel, ClassMapping mapping) {
+        if (isFinal)
+            return false;
+        sel.select(disc.getColumns());
+        return true;
+    }
+
+    public Class getClass(JDBCStore store, ClassMapping base, Result res)
+        throws SQLException, ClassNotFoundException {
+        if (isFinal || !res.contains(disc.getColumns()[0])
+            || (base.getPCSuperclass() == null
+            && base.getJoinablePCSubclassMappings().length == 0))
+            return base.getDescribedType();
+
+        Object cls = res.getObject(disc.getColumns()[0], -1, null);
+        return getClass(cls, store);
+    }
+
+    public SQLBuffer getClassConditions(JDBCStore store, Select sel,
+        Joins joins, ClassMapping base, boolean subclasses) {
+        // if selecting the first mapped class and all subclasses, no need
+        // to limit the query
+        if (isFinal || (base.getJoinablePCSuperclassMapping() == null
+            && subclasses))
+            return null;
+
+        // if no subclasses or superclass, no need for conditions
+        ClassMapping[] subs = base.getJoinablePCSubclassMappings();
+        if (subs.length == 0 && base.getJoinablePCSuperclassMapping() == null)
+            return null;
+
+        // if not selecting subclasses, limit to just the given class
+        Column col = disc.getColumns()[0];
+        SQLBuffer sql = new SQLBuffer(store.getDBDictionary());
+        sql.append(sel.getColumnAlias(col, joins));
+        if (!subclasses || subs.length == 0)
+            return sql.append(" = ").appendValue(getDiscriminatorValue(base),
+                col);
+
+        sql.append(" IN (");
+        sql.appendValue(getDiscriminatorValue(base), col);
+        for (int i = 0; i < subs.length; i++)
+            sql.append(", ").appendValue(getDiscriminatorValue(subs[i]), col);
+        sql.append(")");
+        return sql;
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSCollectionFieldStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSCollectionFieldStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSCollectionFieldStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSCollectionFieldStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,96 @@
+/*
+ * 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.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.meta.FieldStrategy;
+import org.apache.openjpa.jdbc.meta.ValueMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+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;
+
+/**
+ * Interface implemented by collection strategies so that they can
+ * support large result set collections.
+ *
+ * @author Abe White
+ */
+public interface LRSCollectionFieldStrategy
+    extends FieldStrategy {
+
+    /**
+     * The owning field mapping.
+     */
+    public FieldMapping getFieldMapping();
+
+    /**
+     * Return all independent mappings to which this strategy must join in
+     * order to access collection elements, or empty array if none.
+     *
+     * @param traverse whether we're traversing through to the related type
+     * @see ValueMapping#getIndependentTypeMappings
+     * @see ClassMapping#EMPTY_MAPPINGS
+     */
+    public ClassMapping[] getIndependentElementMappings(boolean traverse);
+
+    /**
+     * Return the foreign key used to join to the owning field for the given
+     * element mapping from {@link #getIndependentElementMappings} (or null).
+     */
+    public ForeignKey getJoinForeignKey(ClassMapping elem);
+
+    /**
+     * Return the columns holding the data for a collection element for the
+     * given element mapping from {@link #getIndependentElementMappings}
+     * (or null).
+     */
+    public Column[] getElementColumns(ClassMapping elem);
+
+    /**
+     * Implement this method to select the elements of this field for the
+     * given element mapping from {@link #getIndependentElementMappings}
+     * (or null). Elements of the result will be loaded with
+     * {@link #loadElement}.
+     */
+    public void selectElement(Select sel, ClassMapping elem,
+        JDBCStore store, JDBCFetchState fetchState, int eagerMode,
+        Joins joins);
+
+    /**
+     * Load an element of the collection. The given state manager might be
+     * null if the load is for a projection or for processing eager parallel
+     * results.
+     */
+    public Object loadElement(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, Result res, Joins joins)
+        throws SQLException;
+
+    /**
+     * Join this value's table to the table for the given element mapping
+     * from {@link #getIndependentElementMappings} (or null).
+     *
+     * @see FieldMapping#joinRelation
+     */
+    public Joins joinElementRelation(Joins joins, ClassMapping elem);
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSMapFieldStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSMapFieldStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSMapFieldStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSMapFieldStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,149 @@
+/*
+ * 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.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.ClassMapping;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.meta.FieldStrategy;
+import org.apache.openjpa.jdbc.meta.ValueMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+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;
+
+/**
+ * Interface implemented by map strategies so that they can
+ * support large result set maps.
+ *
+ * @author Abe White
+ */
+public interface LRSMapFieldStrategy
+    extends FieldStrategy {
+
+    /**
+     * The owning field mapping.
+     */
+    public FieldMapping getFieldMapping();
+
+    /**
+     * Return all independent mappings to which this strategy must join in
+     * order to access map keys, or empty array if none.
+     *
+     * @see ValueMapping#getIndependentTypeMappings
+     * @see ClassMapping#EMPTY_MAPPINGS
+     */
+    public ClassMapping[] getIndependentKeyMappings(boolean traverse);
+
+    /**
+     * Return all independent mappings to which this strategy must join in
+     * order to access map values, or empty array if none.
+     *
+     * @see ValueMapping#getIndependentTypeMappings
+     * @see ClassMapping#EMPTY_MAPPINGS
+     */
+    public ClassMapping[] getIndependentValueMappings(boolean traverse);
+
+    /**
+     * Return the foreign key used to join to the owning field for the given
+     * mapping from either {@link #getIndependentKeyMappings} or
+     * {@link #getIndependentValueMappings} (or null).
+     */
+    public ForeignKey getJoinForeignKey(ClassMapping cls);
+
+    /**
+     * Return the columns holding data for a map key for the given key mapping
+     * from {@link #getIndependentKeyMappings} or
+     * {@link #getIndependentValueMappings} (or null).
+     */
+    public Column[] getKeyColumns(ClassMapping cls);
+
+    /**
+     * Return the columns holding data for a map value for the given value
+     * mapping from {@link #getIndependentKeyMappings} or
+     * {@link #getIndependentValueMappings} (or null).
+     */
+    public Column[] getValueColumns(ClassMapping cls);
+
+    /**
+     * Implement this method to select the keys of this field.
+     * Elements of the result will be loaded with {@link #loadKey}.
+     * This method is only used if the key is not derived from the value.
+     */
+    public void selectKey(Select sel, ClassMapping key, OpenJPAStateManager sm,
+        JDBCStore store, JDBCFetchState fetchState, Joins joins);
+
+    /**
+     * Load a key from the given result.
+     * This method is only used if the key is not derived from the value.
+     */
+    public Object loadKey(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, Result res, Joins joins)
+        throws SQLException;
+
+    /**
+     * Some mapping derive keys from map values. Other mappings may return null.
+     */
+    public Object deriveKey(JDBCStore store, Object value);
+
+    /**
+     * Some mapping derive values from map keys. Other mappings may return null.
+     */
+    public Object deriveValue(JDBCStore store, Object key);
+
+    /**
+     * Implement this method to select the values of this field.
+     * Elements of the result will be loaded with {@link #loadValue}.
+     */
+    public void selectValue(Select sel, ClassMapping val,
+        OpenJPAStateManager sm,
+        JDBCStore store, JDBCFetchState fetchState, Joins joins);
+
+    /**
+     * Load a value from the given result.
+     */
+    public Object loadValue(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, Result res, Joins joins)
+        throws SQLException;
+
+    /**
+     * Return results containing all keys and values for this map. If only
+     * one result is needed, set both array indexes to the same result
+     * instance. Also fill in the key and value joins in the given array.
+     * The results will be loaded with the {@link #loadKey} or
+     * {@link #deriveKey} and {@link #loadValue} methods.
+     */
+    public Result[] getResults(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState, int eagerMode, Joins[] joins, boolean lrs)
+        throws SQLException;
+
+    /**
+     * Join this value's table to the table for the given key mapping
+     * from {@link #getIndependentKeyMappings} (or null).
+     */
+    public Joins joinKeyRelation(Joins joins, ClassMapping key);
+
+    /**
+     * Join this value's table to the table for the given value mapping
+     * from {@link #getIndependentValueMappings} (or null).
+     */
+    public Joins joinValueRelation(Joins joins, ClassMapping val);
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyCollection.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyCollection.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyCollection.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyCollection.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,234 @@
+/*
+ * 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 java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.openjpa.conf.OpenJPAConfiguration;
+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.ClassMapping;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+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.SQLExceptions;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.jdbc.sql.Union;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.util.Closeable;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.AbstractLRSProxyCollection;
+import org.apache.openjpa.util.InvalidStateException;
+
+/**
+ * Large result set collection.
+ *
+ * @author Abe White
+ */
+public class LRSProxyCollection
+    extends AbstractLRSProxyCollection {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (LRSProxyCollection.class);
+
+    private final LRSCollectionFieldStrategy _strat;
+
+    public LRSProxyCollection(LRSCollectionFieldStrategy strat,
+        OpenJPAConfiguration conf) {
+        super(strat.getFieldMapping().getElement().getDeclaredType(),
+            strat.getFieldMapping().getOrderColumn() != null, conf);
+        _strat = strat;
+    }
+
+    protected int count() {
+        final ClassMapping[] elems = _strat.getIndependentElementMappings
+            (false);
+        final OpenJPAStateManager sm = assertOwner();
+        final JDBCStore store = getStore();
+        Union union = store.getSQLFactory().newUnion
+            (Math.max(1, elems.length));
+        union.select(new Union.Selector() {
+            public void select(Select sel, int idx) {
+                ClassMapping elem = (elems.length == 0) ? null : elems[idx];
+                sel.whereForeignKey(_strat.getJoinForeignKey(elem),
+                    sm.getObjectId(), _strat.getFieldMapping().
+                    getDefiningMapping(), store);
+            }
+        });
+
+        try {
+            return union.getCount(store);
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        }
+    }
+
+    protected boolean has(final Object obj) {
+        final ClassMapping[] elems = _strat.getIndependentElementMappings
+            (false);
+        final OpenJPAStateManager sm = assertOwner();
+        final JDBCStore store = getStore();
+        Union union = store.getSQLFactory().newUnion
+            (Math.max(1, elems.length));
+        union.select(new Union.Selector() {
+            public void select(Select sel, int idx) {
+                ClassMapping elem = (elems.length == 0) ? null : elems[idx];
+                sel.whereForeignKey(_strat.getJoinForeignKey(elem),
+                    sm.getObjectId(), _strat.getFieldMapping().
+                    getDefiningMapping(), store);
+
+                Object val = _strat.toDataStoreValue(obj, store);
+                Column[] cols = _strat.getElementColumns(elem);
+                Object[] vals = (cols.length == 1) ? null : (Object[]) val;
+                SQLBuffer sql = new SQLBuffer(store.getDBDictionary());
+                for (int i = 0; i < cols.length; i++) {
+                    if (i > 0)
+                        sql.append(" AND ");
+
+                    sql.append(sel.getColumnAlias(cols[i]));
+                    if (vals == null)
+                        sql.append((val == null) ? " IS " : " = ").
+                            appendValue(val, cols[i]);
+                    else
+                        sql.append((vals[i] == null) ? " IS " : " = ").
+                            appendValue(vals[i], cols[i]);
+                }
+                sel.where(sql);
+            }
+        });
+
+        try {
+            return union.getCount(store) > 0;
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        }
+    }
+
+    protected Iterator itr() {
+        final ClassMapping[] elems = _strat.getIndependentElementMappings(true);
+        final OpenJPAStateManager sm = assertOwner();
+        final JDBCStore store = getStore();
+        final JDBCFetchConfiguration fetch = store.getFetchConfiguration();
+        final JDBCFetchState fetchState =
+            (JDBCFetchState) fetch.newFetchState();
+        final Joins[] resJoins = new Joins[Math.max(1, elems.length)];
+        final FieldMapping fm = _strat.getFieldMapping();
+
+        Union union = store.getSQLFactory().newUnion
+            (Math.max(1, elems.length));
+        if (fetch.getSubclassFetchMode(fm.getElementMapping().
+            getTypeMapping()) != fetch.EAGER_JOIN)
+            union.abortUnion();
+        union.setLRS(true);
+        union.select(new Union.Selector() {
+            public void select(Select sel, int idx) {
+                ClassMapping elem = (elems.length == 0) ? null : elems[idx];
+                sel.whereForeignKey(_strat.getJoinForeignKey(elem),
+                    sm.getObjectId(), fm.getDefiningMapping(), store);
+
+                // order before select in case we're faking union with
+                // multiple selects; order vals used to merge results
+                fm.orderLocal(sel, elem, null);
+                resJoins[idx] = _strat.joinElementRelation(sel.newJoins(),
+                    elem);
+                fm.orderRelation(sel, elem, resJoins[idx]);
+                _strat.selectElement(sel, elem, store, fetchState,
+                    fetch.EAGER_JOIN, resJoins[idx]);
+            }
+        });
+
+        try {
+            Result res = union.execute(store, fetch);
+            return new ResultIterator(sm, store, fetchState, res, resJoins);
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        }
+    }
+
+    private OpenJPAStateManager assertOwner() {
+        OpenJPAStateManager sm = getOwner();
+        if (sm == null)
+            throw new InvalidStateException(_loc.get("lrs-no-owner",
+                _strat.getFieldMapping()));
+        return sm;
+    }
+
+    private JDBCStore getStore() {
+        return (JDBCStore) getOwner().getContext().getStoreManager().
+            getInnermostDelegate();
+    }
+
+    /**
+     * Closeable iterator built around a JDBC result.
+     */
+    private class ResultIterator
+        implements Iterator, Closeable {
+
+        private final OpenJPAStateManager _sm;
+        private final JDBCStore _store;
+        private final JDBCFetchState _fetchState;
+        private final Result _res;
+        private final Joins[] _joins;
+        private Boolean _next = null;
+
+        public ResultIterator(OpenJPAStateManager sm, JDBCStore store,
+            JDBCFetchState fetchState, Result res, Joins[] joins) {
+            _sm = sm;
+            _store = store;
+            _fetchState = fetchState;
+            _res = res;
+            _joins = joins;
+        }
+
+        public boolean hasNext() {
+            if (_next == null) {
+                try {
+                    _next = (_res.next()) ? Boolean.TRUE : Boolean.FALSE;
+                } catch (SQLException se) {
+                    throw SQLExceptions.getStore(se, _store.getDBDictionary());
+                }
+            }
+            return _next.booleanValue();
+        }
+
+        public Object next() {
+            if (!hasNext())
+                throw new NoSuchElementException();
+            try {
+                _next = null;
+                return _strat.loadElement(_sm, _store, _fetchState, _res,
+                    _joins[_res.indexOf()]);
+            } catch (SQLException se) {
+                throw SQLExceptions.getStore(se, _store.getDBDictionary());
+            }
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        public void close() {
+            _next = Boolean.FALSE;
+            _res.close();
+        }
+    }
+}
+

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyMap.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyMap.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyMap.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/LRSProxyMap.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,430 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.apache.openjpa.conf.OpenJPAConfiguration;
+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.ClassMapping;
+import org.apache.openjpa.jdbc.schema.Column;
+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.SQLExceptions;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.jdbc.sql.Union;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.util.Closeable;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.AbstractLRSProxyMap;
+import org.apache.openjpa.util.InvalidStateException;
+
+/**
+ * Large result set map.
+ *
+ * @author Abe White
+ */
+class LRSProxyMap
+    extends AbstractLRSProxyMap {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (LRSProxyMap.class);
+
+    private final LRSMapFieldStrategy _strat;
+
+    public LRSProxyMap(LRSMapFieldStrategy strat, OpenJPAConfiguration conf) {
+        super(strat.getFieldMapping().getKey().getDeclaredType(),
+            strat.getFieldMapping().getElement().getDeclaredType(), conf);
+        _strat = strat;
+    }
+
+    protected synchronized int count() {
+        boolean derivedVal = _strat.getFieldMapping().getElement().
+            getValueMappedBy() != null;
+        final ClassMapping[] clss = (derivedVal)
+            ? _strat.getIndependentKeyMappings(false)
+            : _strat.getIndependentValueMappings(false);
+        final OpenJPAStateManager sm = assertOwner();
+        final JDBCStore store = getStore();
+        Union union = store.getSQLFactory().newUnion
+            (Math.max(1, clss.length));
+        union.select(new Union.Selector() {
+            public void select(Select sel, int idx) {
+                ClassMapping cls = (clss.length == 0) ? null : clss[idx];
+                sel.whereForeignKey(_strat.getJoinForeignKey(cls),
+                    sm.getObjectId(), _strat.getFieldMapping().
+                    getDefiningMapping(), store);
+            }
+        });
+
+        try {
+            return union.getCount(store);
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        }
+    }
+
+    protected boolean hasKey(Object key) {
+        return has(key, true);
+    }
+
+    protected boolean hasValue(Object value) {
+        return has(value, false);
+    }
+
+    private boolean has(final Object obj, final boolean key) {
+        final boolean derivedKey = key && _strat.getFieldMapping().
+            getKey().getValueMappedBy() != null;
+        final boolean derivedVal = !key && _strat.getFieldMapping().
+            getElement().getValueMappedBy() != null;
+
+        final ClassMapping[] clss = ((key && !derivedKey) || derivedVal)
+            ? _strat.getIndependentKeyMappings(derivedVal)
+            : _strat.getIndependentValueMappings(derivedKey);
+        final OpenJPAStateManager sm = assertOwner();
+        final JDBCStore store = getStore();
+
+        Union union = store.getSQLFactory().newUnion
+            (Math.max(1, clss.length));
+        union.select(new Union.Selector() {
+            public void select(Select sel, int idx) {
+                ClassMapping cls = (clss.length == 0) ? null : clss[idx];
+                sel.whereForeignKey(_strat.getJoinForeignKey(cls),
+                    sm.getObjectId(), _strat.getFieldMapping().
+                    getDefiningMapping(), store);
+
+                Joins joins = null;
+                Column[] cols;
+                Object val;
+                if (key) {
+                    if (derivedKey)
+                        joins = _strat.joinValueRelation(sel.newJoins(), cls);
+                    val = _strat.toKeyDataStoreValue(obj, store);
+                    cols = _strat.getKeyColumns(cls);
+                } else {
+                    if (derivedVal)
+                        joins = _strat.joinKeyRelation(sel.newJoins(), cls);
+                    val = _strat.toDataStoreValue(obj, store);
+                    cols = _strat.getValueColumns(cls);
+                }
+                Object[] vals = (cols.length == 1) ? null : (Object[]) val;
+                SQLBuffer sql = new SQLBuffer(store.getDBDictionary());
+                for (int i = 0; i < cols.length; i++) {
+                    if (i > 0)
+                        sql.append(" AND ");
+
+                    sql.append(sel.getColumnAlias(cols[i], joins));
+                    if (vals == null)
+                        sql.append((val == null) ? " IS " : " = ").
+                            appendValue(val, cols[i]);
+                    else
+                        sql.append((vals[i] == null) ? " IS " : " = ").
+                            appendValue(vals[i], cols[i]);
+                }
+                sel.where(sql, joins);
+            }
+        });
+
+        try {
+            return union.getCount(store) > 0;
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        }
+    }
+
+    protected Collection keys(final Object obj) {
+        final OpenJPAStateManager sm = assertOwner();
+        final JDBCStore store = getStore();
+        if (_strat.getFieldMapping().getKey().getValueMappedBy() != null) {
+            Object key = _strat.deriveKey(store, obj);
+            if (hasKey(key))
+                return Collections.singleton(key);
+            return Collections.EMPTY_LIST;
+        }
+
+        final ClassMapping[] clss = _strat.getIndependentKeyMappings(true);
+        final JDBCFetchConfiguration fetch = store.getFetchConfiguration();
+        final JDBCFetchState jfetchState = (JDBCFetchState) fetch
+            .newFetchState();
+        final Joins[] resJoins = new Joins[Math.max(1, clss.length)];
+
+        Union union = store.getSQLFactory().newUnion
+            (Math.max(1, clss.length));
+        if (fetch.getSubclassFetchMode(_strat.getFieldMapping().
+            getKeyMapping().getTypeMapping()) != fetch.EAGER_JOIN)
+            union.abortUnion();
+        union.select(new Union.Selector() {
+            public void select(Select sel, int idx) {
+                ClassMapping cls = (clss.length == 0) ? null : clss[idx];
+                sel.whereForeignKey(_strat.getJoinForeignKey(cls),
+                    sm.getObjectId(), _strat.getFieldMapping().
+                    getDefiningMapping(), store);
+                if (_strat.getFieldMapping().getElement().getValueMappedBy()
+                    != null)
+                    resJoins[idx] = _strat.joinKeyRelation(sel.newJoins(),
+                        cls);
+
+                Object val = _strat.toDataStoreValue(obj, store);
+                Column[] cols = _strat.getValueColumns(cls);
+                Object[] vals = (cols.length == 1) ? null : (Object[]) val;
+                SQLBuffer sql = new SQLBuffer(store.getDBDictionary());
+                for (int i = 0; i < cols.length; i++) {
+                    if (i > 0)
+                        sql.append(" AND ");
+
+                    sql.append(sel.getColumnAlias(cols[i]));
+                    if (vals == null)
+                        sql.append((val == null) ? " IS " : " = ").
+                            appendValue(val, cols[i]);
+                    else
+                        sql.append((vals[i] == null) ? " IS " : " = ").
+                            appendValue(vals[i], cols[i]);
+                }
+                sel.where(sql);
+
+                if (resJoins[idx] == null)
+                    resJoins[idx] = _strat.joinKeyRelation(sel.newJoins(),
+                        cls);
+                _strat.selectKey(sel, cls, sm, store, jfetchState,
+                    resJoins[idx]);
+            }
+        });
+
+        Result res = null;
+        Collection keys = new ArrayList(3);
+        try {
+            res = union.execute(store, fetch);
+            while (res.next())
+                keys.add(_strat.loadKey(sm, store, jfetchState, res,
+                    resJoins[res.indexOf()]));
+            return keys;
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        } finally {
+            if (res != null)
+                res.close();
+        }
+    }
+
+    protected Object value(final Object obj) {
+        final OpenJPAStateManager sm = assertOwner();
+        final JDBCStore store = getStore();
+        if (_strat.getFieldMapping().getElement().getValueMappedBy() != null) {
+            Object val = _strat.deriveValue(store, obj);
+            if (hasValue(val))
+                return val;
+            return null;
+        }
+
+        final JDBCFetchConfiguration fetch = store.getFetchConfiguration();
+        final JDBCFetchState fetchState =
+            (JDBCFetchState) fetch.newFetchState();
+        final ClassMapping[] clss = _strat.getIndependentValueMappings(true);
+        final Joins[] resJoins = new Joins[Math.max(1, clss.length)];
+        Union union = store.getSQLFactory().newUnion
+            (Math.max(1, clss.length));
+        union.setSingleResult(true);
+        if (fetch.getSubclassFetchMode(_strat.getFieldMapping().
+            getElementMapping().getTypeMapping())
+            != JDBCFetchConfiguration.EAGER_JOIN)
+            union.abortUnion();
+        union.select(new Union.Selector() {
+            public void select(Select sel, int idx) {
+                ClassMapping cls = (clss.length == 0) ? null : clss[idx];
+                sel.whereForeignKey(_strat.getJoinForeignKey(cls),
+                    sm.getObjectId(), _strat.getFieldMapping().
+                    getDefiningMapping(), store);
+                if (_strat.getFieldMapping().getKey().getValueMappedBy()
+                    != null)
+                    resJoins[idx] = _strat.joinValueRelation(sel.newJoins(),
+                        cls);
+
+                Object key = _strat.toKeyDataStoreValue(obj, store);
+                Column[] cols = _strat.getKeyColumns(cls);
+                Object[] vals = (cols.length == 1) ? null : (Object[]) key;
+                SQLBuffer sql = new SQLBuffer(store.getDBDictionary());
+                for (int i = 0; i < cols.length; i++) {
+                    if (i > 0)
+                        sql.append(" AND ");
+
+                    sql.append(sel.getColumnAlias(cols[i], resJoins[idx]));
+                    if (vals == null)
+                        sql.append((key == null) ? " IS " : " = ").
+                            appendValue(key, cols[i]);
+                    else
+                        sql.append((vals[i] == null) ? " IS " : " = ").
+                            appendValue(vals[i], cols[i]);
+                }
+                sel.where(sql, resJoins[idx]);
+
+                if (resJoins[idx] == null)
+                    resJoins[idx] = _strat.joinValueRelation(sel.newJoins(),
+                        cls);
+                _strat.selectValue(sel, cls, sm, store, fetchState,
+                    resJoins[idx]);
+            }
+        });
+
+        Result res = null;
+        try {
+            res = union.execute(store, fetch);
+            if (res.next())
+                return _strat.loadValue(sm, store, fetchState, res,
+                    resJoins[res.indexOf()]);
+            return null;
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        } finally {
+            if (res != null)
+                res.close();
+        }
+    }
+
+    protected Iterator itr() {
+        OpenJPAStateManager sm = assertOwner();
+        JDBCStore store = getStore();
+        JDBCFetchConfiguration fetch = store.getFetchConfiguration();
+        JDBCFetchState jfetchState = (JDBCFetchState) fetch.newFetchState();
+        try {
+            Joins[] joins = new Joins[2];
+            Result[] res = _strat.getResults(sm, store, jfetchState,
+                fetch.EAGER_JOIN, joins, true);
+            return new ResultIterator(sm, store, jfetchState, res, joins);
+        } catch (SQLException se) {
+            throw SQLExceptions.getStore(se, store.getDBDictionary());
+        }
+    }
+
+    private OpenJPAStateManager assertOwner() {
+        OpenJPAStateManager sm = getOwner();
+        if (sm == null)
+            throw new InvalidStateException(_loc.get("lrs-no-owner",
+                _strat.getFieldMapping()));
+        return sm;
+    }
+
+    private JDBCStore getStore() {
+        return (JDBCStore) getOwner().getContext().getStoreManager().
+            getInnermostDelegate();
+    }
+
+    /**
+     * Closeable iterator built around key and value JDBC results.
+     */
+    private class ResultIterator
+        implements Iterator, Closeable {
+
+        private final OpenJPAStateManager _sm;
+        private final JDBCStore _store;
+        private final JDBCFetchState _fetchState;
+        private final Result[] _res;
+        private final Joins[] _joins;
+        private Boolean _next = null;
+
+        public ResultIterator(OpenJPAStateManager sm, JDBCStore store,
+            JDBCFetchState fetchState, Result[] res, Joins[] joins) {
+            _sm = sm;
+            _store = store;
+            _fetchState = fetchState;
+            _res = res;
+            _joins = joins;
+        }
+
+        public boolean hasNext() {
+            if (_next == null) {
+                try {
+                    _next = (_res[0].next()) ? Boolean.TRUE : Boolean.FALSE;
+                    if (_next.booleanValue() && _res[1] != _res[0])
+                        _res[1].next();
+                } catch (SQLException se) {
+                    throw SQLExceptions.getStore(se, _store.getDBDictionary());
+                }
+            }
+            return _next.booleanValue();
+        }
+
+        public Object next() {
+            if (!hasNext())
+                throw new NoSuchElementException();
+            _next = null;
+
+            boolean keyDerived = _strat.getFieldMapping().getKey().
+                getValueMappedBy() != null;
+            boolean valDerived = _strat.getFieldMapping().getElement().
+                getValueMappedBy() != null;
+            Entry entry = new Entry();
+            try {
+
+                if (!keyDerived)
+                    entry.key = _strat.loadKey(_sm, _store, _fetchState,
+                        _res[0], _joins[0]);
+                if (!valDerived)
+                    entry.val = _strat.loadValue(_sm, _store, _fetchState,
+                        _res[1], _joins[1]);
+                if (keyDerived)
+                    entry.key = _strat.deriveKey(_store, entry.val);
+                if (valDerived)
+                    entry.val = _strat.deriveValue(_store, entry.key);
+                return entry;
+            } catch (SQLException se) {
+                throw SQLExceptions.getStore(se, _store.getDBDictionary());
+            }
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        public void close() {
+            _next = Boolean.FALSE;
+            _res[0].close();
+            if (_res[1] != _res[0])
+                _res[1].close();
+        }
+    }
+
+    /**
+     * Map.Entry struct.
+     */
+    private static class Entry
+        implements Map.Entry {
+
+        public Object key;
+        public Object val;
+
+        public Object getKey() {
+            return key;
+        }
+
+        public Object getValue() {
+            return val;
+        }
+
+        public Object setValue(Object val) {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
+

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,175 @@
+/*
+ * 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 java.util.Map;
+
+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.ClassMapping;
+import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.meta.FieldStrategy;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.Row;
+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.util.Localizer;
+import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.util.MetaDataException;
+
+/**
+ * Base class for map mappings. Handles managing the secondary table
+ * used to hold map keys and values and loading. Subclasses must implement
+ * abstract methods and insert/update behavior as well as overriding
+ * {@link FieldStrategy#toDataStoreValue},
+ * {@link FieldStrategy#toKeyDataStoreValue},
+ * {@link FieldStrategy#joinRelation}, and
+ * {@link FieldStrategy#joinKeyRelation} if necessary.
+ *
+ * @author Abe White
+ */
+public abstract class MapTableFieldStrategy
+    extends ContainerFieldStrategy
+    implements LRSMapFieldStrategy {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (MapTableFieldStrategy.class);
+
+    public FieldMapping getFieldMapping() {
+        return field;
+    }
+
+    public ClassMapping[] getIndependentKeyMappings(boolean traverse) {
+        return (traverse) ? field.getKeyMapping().getIndependentTypeMappings()
+            : ClassMapping.EMPTY_MAPPINGS;
+    }
+
+    public ClassMapping[] getIndependentValueMappings(boolean traverse) {
+        return (traverse) ? field.getElementMapping().
+            getIndependentTypeMappings() : ClassMapping.EMPTY_MAPPINGS;
+    }
+
+    public ForeignKey getJoinForeignKey(ClassMapping cls) {
+        return field.getJoinForeignKey();
+    }
+
+    public Object deriveKey(JDBCStore store, Object value) {
+        return null;
+    }
+
+    public Object deriveValue(JDBCStore store, Object key) {
+        return null;
+    }
+
+    /**
+     * Invokes {@link FieldStrategy#joinKeyRelation} by default.
+     */
+    public Joins joinKeyRelation(Joins joins, ClassMapping key) {
+        return joinKeyRelation(joins, false, false);
+    }
+
+    /**
+     * Invokes {@link FieldStrategy#joinRelation} by default.
+     */
+    public Joins joinValueRelation(Joins joins, ClassMapping val) {
+        return joinRelation(joins, false, false);
+    }
+
+    public void map(boolean adapt) {
+        if (field.getTypeCode() != JavaTypes.MAP)
+            throw new MetaDataException(_loc.get("not-map", field));
+        if (field.getKey().getValueMappedBy() != null)
+            throw new MetaDataException(_loc.get("mapped-by-key", field));
+        field.getValueInfo().assertNoSchemaComponents(field, !adapt);
+    }
+
+    public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+        throws SQLException {
+        Row row = rm.getAllRows(field.getTable(), Row.ACTION_DELETE);
+        row.whereForeignKey(field.getJoinForeignKey(), sm);
+        rm.flushAllRows(row);
+    }
+
+    public int supportsSelect(Select sel, int type, OpenJPAStateManager sm,
+        JDBCStore store, JDBCFetchConfiguration fetch) {
+        return 0;
+    }
+
+    public void load(OpenJPAStateManager sm, JDBCStore store,
+        JDBCFetchState fetchState)
+        throws SQLException {
+        if (field.isLRS()) {
+            sm.storeObjectField(field.getIndex(), new LRSProxyMap(this,
+                store.getConfiguration()));
+            return;
+        }
+
+        // select all and load into a normal proxy
+        Joins[] joins = new Joins[2];
+        Result[] res = getResults(sm, store, fetchState,
+            JDBCFetchConfiguration.EAGER_PARALLEL, joins, false);
+        try {
+            Map map = (Map) sm.newProxy(field.getIndex());
+            Object key, val;
+            while (res[0].next()) {
+                if (res[1] != res[0] && !res[1].next())
+                    break;
+
+                key = loadKey(sm, store, fetchState, res[0], joins[0]);
+                val = loadValue(sm, store, fetchState, res[1], joins[1]);
+                map.put(key, val);
+            }
+            sm.storeObject(field.getIndex(), map);
+        } finally {
+            res[0].close();
+            if (res[1] != res[0])
+                res[1].close();
+        }
+    }
+
+    public Object loadKeyProjection(JDBCStore store,
+        JDBCFetchState fetchState, Result res, Joins joins)
+        throws SQLException {
+        return loadKey(null, store, fetchState, res, joins);
+    }
+
+    public Object loadProjection(JDBCStore store, JDBCFetchState fetchState,
+        Result res, Joins joins)
+        throws SQLException {
+        return loadValue(null, store, fetchState, res, joins);
+    }
+
+    public Joins join(Joins joins, boolean forceOuter) {
+        return field.join(joins, forceOuter, true);
+    }
+
+    public Joins joinKey(Joins joins, boolean forceOuter) {
+        return field.join(joins, forceOuter, true);
+    }
+
+    protected ForeignKey getJoinForeignKey() {
+        return field.getJoinForeignKey();
+    }
+
+    protected ClassMapping[] getIndependentElementMappings(boolean traverse) {
+        return ClassMapping.EMPTY_MAPPINGS;
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MaxEmbeddedBlobFieldStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MaxEmbeddedBlobFieldStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MaxEmbeddedBlobFieldStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MaxEmbeddedBlobFieldStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,104 @@
+/*
+ * 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.ResultSet;
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.Row;
+import org.apache.openjpa.jdbc.sql.SQLExceptions;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.util.MetaDataException;
+
+/**
+ * Mapping for serialized fields on a dictionary that has a maximum embedded
+ * BLOB size.
+ *
+ * @author Abe White
+ * @nojavadoc
+ * @since 4.0
+ */
+public class MaxEmbeddedBlobFieldStrategy
+    extends MaxEmbeddedLobFieldStrategy {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (MaxEmbeddedBlobFieldStrategy.class);
+
+    private int _maxSize = 0;
+
+    protected int getExpectedJavaType() {
+        return JavaTypes.OBJECT;
+    }
+
+    protected void update(OpenJPAStateManager sm, Row row)
+        throws SQLException {
+        byte[] b = (byte[]) sm.getImplData(field.getIndex());
+        if (b == null || b.length > _maxSize)
+            row.setNull(field.getColumns()[0], true);
+        else {
+            sm.setImplData(field.getIndex(), null);
+            DBDictionary.SerializedData dat =
+                new DBDictionary.SerializedData(b);
+            row.setObject(field.getColumns()[0], dat);
+        }
+    }
+
+    protected Boolean isCustom(OpenJPAStateManager sm, JDBCStore store) {
+        // have we already stored our serialized data?
+        byte[] b = (byte[]) sm.getImplData(field.getIndex());
+        if (b == null) {
+            Object o = sm.fetch(field.getIndex());
+            if (o == null)
+                return Boolean.FALSE;
+
+            // serialize field value
+            DBDictionary dict = field.getMappingRepository().getDBDictionary();
+            try {
+                b = dict.serialize(o, store);
+            } catch (SQLException se) {
+                throw SQLExceptions.getStore(se, dict);
+            }
+
+            // set in impl data so that we don't have to re-serialize on store
+            sm.setImplData(field.getIndex(), b);
+        }
+        return (b.length > _maxSize) ? null : Boolean.FALSE;
+    }
+
+    protected void putData(OpenJPAStateManager sm, ResultSet rs,
+        DBDictionary dict)
+        throws SQLException {
+        byte[] b = (byte[]) sm.setImplData(field.getIndex(), null);
+        Object blob = rs.getBlob(1);
+        dict.putBytes(blob, b);
+    }
+
+    public void map(boolean adapt) {
+        if (!field.isSerialized())
+            throw new MetaDataException(_loc.get("not-serialized", field));
+        super.map(adapt);
+    }
+
+    public void initialize() {
+        DBDictionary dict = field.getMappingRepository().getDBDictionary();
+        _maxSize = dict.maxEmbeddedBlobSize;
+        field.setUsesImplData(Boolean.TRUE);
+    }
+}

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

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MaxEmbeddedByteArrayFieldStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MaxEmbeddedByteArrayFieldStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MaxEmbeddedByteArrayFieldStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MaxEmbeddedByteArrayFieldStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,93 @@
+/*
+ * 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.Array;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.Row;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.MetaDataException;
+
+/**
+ * Mapping for byte array fields on a dictionary that has a maximum embedded
+ * BLOB size.
+ *
+ * @author Abe White
+ * @nojavadoc
+ * @since 4.0
+ */
+public class MaxEmbeddedByteArrayFieldStrategy
+    extends MaxEmbeddedLobFieldStrategy {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (MaxEmbeddedByteArrayFieldStrategy.class);
+
+    private int _maxSize = 0;
+
+    protected int getExpectedJavaType() {
+        return JavaSQLTypes.BYTES;
+    }
+
+    protected void update(OpenJPAStateManager sm, Row row)
+        throws SQLException {
+        byte[] b = PrimitiveWrapperArrays.toByteArray(sm.fetchObject
+            (field.getIndex()));
+        if (b == null || b.length > _maxSize)
+            row.setBytes(field.getColumns()[0], null);
+        else
+            row.setBytes(field.getColumns()[0], b);
+    }
+
+    protected Boolean isCustom(OpenJPAStateManager sm, JDBCStore store) {
+        Object val = sm.fetchObject(field.getIndex());
+        return (val != null && Array.getLength(val) > _maxSize) ? null
+            : Boolean.FALSE;
+    }
+
+    protected void putData(OpenJPAStateManager sm, ResultSet rs,
+        DBDictionary dict)
+        throws SQLException {
+        Object blob = rs.getBlob(1);
+        dict.putBytes(blob, PrimitiveWrapperArrays.toByteArray(sm.fetchObject
+            (field.getIndex())));
+    }
+
+    protected Object load(Column col, Result res, Joins joins)
+        throws SQLException {
+        return PrimitiveWrapperArrays.toObjectValue(field,
+            (byte[]) res.getBytes(col, joins));
+    }
+
+    public void map(boolean adapt) {
+        if (field.getType() != byte[].class && field.getType() != Byte[].class)
+            throw new MetaDataException(_loc.get("not-bytes", field));
+        super.map(adapt);
+    }
+
+    public void initialize() {
+        DBDictionary dict = field.getMappingRepository().getDBDictionary();
+        _maxSize = dict.maxEmbeddedBlobSize;
+    }
+}

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