db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b..@apache.org
Subject cvs commit: db-ojb/src/java/org/apache/ojb/broker/accesslayer PkEnumeration.java
Date Sat, 22 Jan 2005 20:52:34 GMT
brj         2005/01/22 12:52:34

  Modified:    src/java/org/apache/ojb/broker/core MtoNBroker.java
               src/java/org/apache/ojb/broker/accesslayer
                        PkEnumeration.java
  Log:
  small refactorings based on findbugs
  
  Revision  Changes    Path
  1.16      +529 -530  db-ojb/src/java/org/apache/ojb/broker/core/MtoNBroker.java
  
  Index: MtoNBroker.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/core/MtoNBroker.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- MtoNBroker.java	10 Dec 2004 22:40:42 -0000	1.15
  +++ MtoNBroker.java	22 Jan 2005 20:52:34 -0000	1.16
  @@ -1,530 +1,529 @@
  -package org.apache.ojb.broker.core;
  -
  -/* Copyright 2003-2004 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.
  - */
  -
  -import java.util.ArrayList;
  -import java.util.Collection;
  -import java.util.Iterator;
  -import java.util.List;
  -import java.util.Vector;
  -import java.io.Serializable;
  -
  -import org.apache.commons.lang.builder.EqualsBuilder;
  -import org.apache.commons.lang.builder.HashCodeBuilder;
  -import org.apache.commons.lang.builder.ToStringBuilder;
  -import org.apache.ojb.broker.MtoNImplementor;
  -import org.apache.ojb.broker.PersistenceBroker;
  -import org.apache.ojb.broker.PersistenceBrokerException;
  -import org.apache.ojb.broker.OJBRuntimeException;
  -import org.apache.ojb.broker.core.proxy.ProxyHelper;
  -import org.apache.ojb.broker.accesslayer.ResultSetAndStatement;
  -import org.apache.ojb.broker.accesslayer.sql.SqlGenerator;
  -import org.apache.ojb.broker.metadata.ClassDescriptor;
  -import org.apache.ojb.broker.metadata.CollectionDescriptor;
  -import org.apache.ojb.broker.metadata.DescriptorRepository;
  -import org.apache.ojb.broker.metadata.FieldDescriptor;
  -import org.apache.ojb.broker.metadata.JdbcType;
  -import org.apache.ojb.broker.query.Query;
  -import org.apache.ojb.broker.util.logging.Logger;
  -import org.apache.ojb.broker.util.logging.LoggerFactory;
  -
  -/**
  - * Manage all stuff related to non-decomposed M:N association.
  - *
  - * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
  - * @author <a href="mailto:leandro@ibnetwork.com.br">Leandro Rodrigo Saad Cruz<a>
  - * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird<a>
  - * @author <a href="mailto:jbraeuchi@hotmail.com">Jakob Braeuchi</a>
  - * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
  - * @version $Id$
  - */
  -public class MtoNBroker
  -{
  -    private Logger log = LoggerFactory.getLogger(MtoNBroker.class);
  -
  -    private PersistenceBroker pb;
  -    /**
  -     * Used to store {@link GenericObject} while transaction running, used as
  -     * workaround for m:n insert problem.
  -     * TODO: find better solution for m:n handling
  -     */
  -    private List tempObjects = new ArrayList();
  -
  -    public MtoNBroker(final PersistenceBroker broker)
  -    {
  -        this.pb = broker;
  -    }
  -
  -    public void reset()
  -    {
  -        tempObjects.clear();
  -    }
  -
  -    /**
  -     * Stores new values of a M:N association in a indirection table.
  -     *
  -     * @param cod        The {@link org.apache.ojb.broker.metadata.CollectionDescriptor}
for the m:n relation
  -     * @param realObject The real object
  -     * @param otherObj   The referenced object
  -     * @param mnKeys     The all {@link org.apache.ojb.broker.core.MtoNBroker.Key} matching
the real object
  -     */
  -    public void storeMtoNImplementor(CollectionDescriptor cod, Object realObject, Object
otherObj, Collection mnKeys)
  -    {
  -        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(realObject.getClass());
  -        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, realObject);
  -        String[] pkColumns = cod.getFksToThisClass();
  -
  -        ClassDescriptor otherCld = pb.getDescriptorRepository().getDescriptorFor(ProxyHelper.getRealClass(otherObj));
  -        ValueContainer[] otherPkValues = pb.serviceBrokerHelper().getKeyValues(otherCld,
otherObj);
  -
  -        String[] otherPkColumns = cod.getFksToItemClass();
  -        String table = cod.getIndirectionTable();
  -        MtoNBroker.Key key = new MtoNBroker.Key(otherPkValues);
  -
  -        if(mnKeys.contains(key))
  -        {
  -            return;
  -        }
  -
  -        String[] cols = mergeColumns(pkColumns, otherPkColumns);
  -        String insertStmt = pb.serviceSqlGenerator()
  -                .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_INSERT, table, cols,
null);
  -        ValueContainer[] values = mergeContainer(pkValues, otherPkValues);
  -        GenericObject gObj = new GenericObject(table, cols, values);
  -        if(! tempObjects.contains(gObj))
  -        {
  -            pb.serviceJdbcAccess().executeUpdateSQL(insertStmt, cld, values);
  -            tempObjects.add(gObj);
  -        }
  -    }
  -
  -    /**
  -     * get a Collection of Keys of already existing m:n rows
  -     *
  -     * @param cod
  -     * @param obj
  -     * @return Collection of Key
  -     */
  -    public List getMtoNImplementor(CollectionDescriptor cod, Object obj)
  -    {
  -        ResultSetAndStatement rs = null;
  -        ArrayList result = new ArrayList();
  -        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(obj.getClass());
  -        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, obj);
  -        String[] pkColumns = cod.getFksToThisClass();
  -        String[] fkColumns = cod.getFksToItemClass();
  -        String table = cod.getIndirectionTable();
  -
  -        String selectStmt = pb.serviceSqlGenerator()
  -                .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_SELECT, table, fkColumns,
pkColumns);
  -
  -        ClassDescriptor itemCLD = cod.getItemClassDescriptor();
  -        Collection extents = pb.getDescriptorRepository().getAllConcreteSubclassDescriptors(itemCLD);
  -        if(extents.size() > 0)
  -        {
  -            itemCLD = (ClassDescriptor) extents.iterator().next();
  -        }
  -        FieldDescriptor[] itemClassPKFields = itemCLD.getPkFields();
  -        if(itemClassPKFields.length != fkColumns.length)
  -        {
  -            throw new PersistenceBrokerException("All pk fields of the element-class need
to" +
  -                    " be declared in the indirection table. Element class is "
  -                    + itemCLD.getClassNameOfObject() + " with " + itemClassPKFields.length
+ " pk-fields." +
  -                    " Declared 'fk-pointing-to-element-class' elements in collection-descriptor
are"
  -                    + fkColumns.length);
  -        }
  -        try
  -        {
  -            rs = pb.serviceJdbcAccess().executeSQL(selectStmt, pkValues, Query.NOT_SCROLLABLE);
  -            while(rs.m_rs.next())
  -            {
  -                ValueContainer[] row = new ValueContainer[fkColumns.length];
  -                for(int i = 0; i < row.length; i++)
  -                {
  -                    row[i] = new ValueContainer(rs.m_rs.getObject(i + 1), itemClassPKFields[i].getJdbcType());
  -                }
  -                result.add(new MtoNBroker.Key(row));
  -            }
  -        }
  -        catch(Exception e)
  -        {
  -            throw new PersistenceBrokerException(e);
  -        }
  -        finally
  -        {
  -            rs.close();
  -        }
  -        return result;
  -    }
  -
  -    /**
  -     * delete all rows from m:n table belonging to obj
  -     *
  -     * @param cod
  -     * @param obj
  -     */
  -    public void deleteMtoNImplementor(CollectionDescriptor cod, Object obj)
  -    {
  -        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(obj.getClass());
  -        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, obj);
  -        String[] pkColumns = cod.getFksToThisClass();
  -        String table = cod.getIndirectionTable();
  -        String deleteStmt = pb.serviceSqlGenerator()
  -                .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_DELETE, table, null,
pkColumns);
  -        pb.serviceJdbcAccess().executeUpdateSQL(deleteStmt, cld, pkValues);
  -    }
  -
  -    /**
  -     * deletes all rows from m:n table that are not used in relatedObjects
  -     *
  -     * @param cod
  -     * @param obj
  -     * @param collectionIterator
  -     * @param mnKeys
  -     */
  -    public void deleteMtoNImplementor(CollectionDescriptor cod, Object obj, Iterator collectionIterator,
Collection mnKeys)
  -    {
  -        if(mnKeys.isEmpty() || collectionIterator == null)
  -        {
  -            return;
  -        }
  -        List workList = new ArrayList(mnKeys);
  -        MtoNBroker.Key relatedObjKeys;
  -        ClassDescriptor relatedCld = cod.getItemClassDescriptor();
  -        Object relatedObj;
  -
  -        // remove keys of relatedObject from the existing m:n rows in workList
  -        while(collectionIterator.hasNext())
  -        {
  -            relatedObj = collectionIterator.next();
  -            relatedObjKeys = new MtoNBroker.Key(pb.serviceBrokerHelper().getKeyValues(relatedCld,
relatedObj, true));
  -            workList.remove(relatedObjKeys);
  -        }
  -
  -        // delete all remaining keys in workList
  -        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(obj.getClass());
  -        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, obj);
  -
  -        String[] pkColumns = cod.getFksToThisClass();
  -        String[] fkColumns = cod.getFksToItemClass();
  -        String table = cod.getIndirectionTable();
  -        String deleteStmt;
  -
  -        String[] columns = mergeColumns(pkColumns, fkColumns);
  -        ValueContainer[] fkValues;
  -        Iterator iter = workList.iterator();
  -        while(iter.hasNext())
  -        {
  -            fkValues = ((MtoNBroker.Key) iter.next()).m_containers;
  -            deleteStmt = pb.serviceSqlGenerator()
  -                    .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_DELETE, table,
null, columns);
  -            pb.serviceJdbcAccess().executeUpdateSQL(deleteStmt, cld, mergeContainer(pkValues,
fkValues));
  -        }
  -    }
  -
  -    /**
  -     * @param m2n
  -     */
  -    public void storeMtoNImplementor(MtoNImplementor m2n)
  -    {
  -        if(log.isDebugEnabled()) log.debug("Storing M2N implementor [" + m2n + "]");
  -        insertOrDeleteMtoNImplementor(m2n, true);
  -    }
  -
  -    /**
  -     * @param m2n
  -     */
  -    public void deleteMtoNImplementor(MtoNImplementor m2n)
  -    {
  -        if(log.isDebugEnabled()) log.debug("Deleting M2N implementor [" + m2n + "]");
  -        insertOrDeleteMtoNImplementor(m2n, false);
  -    }
  -
  -
  -    /**
  -     * @see org.apache.ojb.broker.PersistenceBroker#deleteMtoNImplementor
  -     */
  -    private void insertOrDeleteMtoNImplementor(MtoNImplementor m2nImpl, boolean insert)
  -            throws PersistenceBrokerException
  -    {
  -        //look for a collection descriptor on left  such as left.element-class-ref='right'
  -        DescriptorRepository dr = pb.getDescriptorRepository();
  -
  -        Object leftObject = m2nImpl.getLeftObject();
  -        Class leftClass = leftObject.getClass();
  -        Object rightObject = m2nImpl.getRightObject();
  -        Class rightClass = rightObject.getClass();
  -
  -        //are written per class, maybe referencing abstract classes or interfaces
  -        //so let's look for collection descriptors on the left class and try to
  -        // handle extents on teh right class
  -        ClassDescriptor leftCld = dr.getDescriptorFor(leftClass);
  -        ClassDescriptor rightCld = dr.getDescriptorFor(rightClass);
  -        Vector leftColds = leftCld.getCollectionDescriptors();
  -        CollectionDescriptor wanted = findCollectionDescriptor(leftClass, rightClass, leftColds);
  -
  -        if(leftObject == null || rightObject == null)
  -        {
  -            //TODO: to be implemented, must change MtoNImplementor
  -            //deleteMtoNImplementor(wanted,leftObject) || deleteMtoNImplementor(wanted,rightObject)
  -        }
  -        else
  -        {
  -            //delete only one row
  -            ValueContainer[] leftPkValues = pb.serviceBrokerHelper().getKeyValues(leftCld,
leftObject);
  -            ValueContainer[] rightPkValues = pb.serviceBrokerHelper().getKeyValues(rightCld,
rightObject);
  -            String[] pkLeftColumns = wanted.getFksToThisClass();
  -            String[] pkRightColumns = wanted.getFksToItemClass();
  -            String table = wanted.getIndirectionTable();
  -            if(table == null) throw new PersistenceBrokerException("Can't remove MtoN implementor
without an indirection table");
  -
  -            String stmt = null;
  -            String[] cols = mergeColumns(pkLeftColumns, pkRightColumns);
  -            ValueContainer[] values = mergeContainer(leftPkValues, rightPkValues);
  -            if(insert)
  -            {
  -                stmt = pb.serviceSqlGenerator()
  -                        .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_INSERT,
table, cols, null);
  -                GenericObject gObj = new GenericObject(table, cols, values);
  -                if(!tempObjects.contains(gObj))
  -                {
  -                    pb.serviceJdbcAccess().executeUpdateSQL(stmt, leftCld, values);
  -                    tempObjects.add(gObj);
  -                }
  -            }
  -            else
  -            {
  -                stmt = pb.serviceSqlGenerator()
  -                        .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_DELETE,
table, null, cols);
  -                pb.serviceJdbcAccess().executeUpdateSQL(stmt, leftCld, values);
  -            }
  -        }
  -    }
  -
  -    private CollectionDescriptor findCollectionDescriptor(Class leftClass, Class rightClass,
Vector leftColds)
  -    {
  -        for(Iterator iter = leftColds.iterator(); iter.hasNext();)
  -        {
  -            CollectionDescriptor element = (CollectionDescriptor) iter.next();
  -
  -            //try super classes and interfaces too
  -            if(element.getItemClass().isAssignableFrom(rightClass))
  -            {
  -                //we found it !
  -                return element;
  -            }
  -        }
  -        throw new PersistenceBrokerException("Can't find reasonable collection descriptor
for MtoN implementor left[" + leftClass
  -                + "] right[" + rightClass + "]");
  -    }
  -
  -    private String[] mergeColumns(String[] first, String[] second)
  -    {
  -        String[] cols = new String[first.length + second.length];
  -        System.arraycopy(first, 0, cols, 0, first.length);
  -        System.arraycopy(second, 0, cols, first.length, second.length);
  -        return cols;
  -    }
  -
  -    private ValueContainer[] mergeContainer(ValueContainer[] first, ValueContainer[] second)
  -    {
  -        ValueContainer[] values = new ValueContainer[first.length + second.length];
  -        System.arraycopy(first, 0, values, 0, first.length);
  -        System.arraycopy(second, 0, values, first.length, second.length);
  -        return values;
  -    }
  -
  -
  -
  -// ************************************************************************
  -// inner class
  -// ************************************************************************
  -
  -    /**
  -     * This is a helper class to model a Key of an Object
  -     */
  -    private static final class Key
  -    {
  -        final ValueContainer[] m_containers;
  -
  -        Key(final ValueContainer[] containers)
  -        {
  -            m_containers = new ValueContainer[containers.length];
  -
  -            for(int i = 0; i < containers.length; i++)
  -            {
  -                Object value = containers[i].getValue();
  -                JdbcType type = containers[i].getJdbcType();
  -
  -                // BRJ:
  -                // convert all Numbers to Long to simplify equals
  -                // Long(100) is not equal to Integer(100)
  -                //
  -                // could lead to problems when Floats are used as key
  -                // converting to String could be a better alternative
  -                if(value instanceof Number)
  -                {
  -                    value = new Long(((Number) value).longValue());
  -                }
  -
  -                m_containers[i] = new ValueContainer(value, type);
  -            }
  -        }
  -
  -        public boolean equals(Object other)
  -        {
  -            if(other == this)
  -            {
  -                return true;
  -            }
  -            if(!(other instanceof Key))
  -            {
  -                return false;
  -            }
  -
  -            Key otherKey = (Key) other;
  -            EqualsBuilder eb = new EqualsBuilder();
  -
  -            eb.append(m_containers, otherKey.m_containers);
  -            return eb.isEquals();
  -        }
  -
  -        public int hashCode()
  -        {
  -            HashCodeBuilder hb = new HashCodeBuilder();
  -            hb.append(m_containers);
  -
  -            return hb.toHashCode();
  -        }
  -    }
  -
  -
  -
  -    // ************************************************************************
  -    // inner class
  -    // ************************************************************************
  -    private static final class GenericObject
  -    {
  -        private String tablename;
  -        private String[] columnNames;
  -        private ValueContainer[] values;
  -
  -        public GenericObject(String tablename, String[] columnNames, ValueContainer[] values)
  -        {
  -            this.tablename = tablename;
  -            this.columnNames = columnNames;
  -            this.values = values;
  -            if(values != null && columnNames.length != values.length)
  -            {
  -                throw new OJBRuntimeException("Column name array and value array have NOT
same length");
  -            }
  -        }
  -
  -        public boolean equals(Object obj)
  -        {
  -            if(this == obj)
  -            {
  -                return true;
  -            }
  -            boolean result = false;
  -            if(obj instanceof GenericObject)
  -            {
  -                GenericObject other = (GenericObject) obj;
  -                result = (tablename.equalsIgnoreCase(other.tablename)
  -                        && (columnNames != null)
  -                        && (other.columnNames != null)
  -                        && (columnNames.length == other.columnNames.length));
  -                if(result)
  -                {
  -                    for (int i = 0; i < columnNames.length; i++)
  -                    {
  -                        // System.out.println("## test: " + this);
  -                        int otherIndex = other.indexForColumn(columnNames[i]);
  -                        if(otherIndex < 0)
  -                        {
  -                            result = false;
  -                            break;
  -                        }
  -                        result = result && values[i].equals(other.values[otherIndex]);
  -                        if(!result) break;
  -                    }
  -                }
  -            }
  -            return result;
  -        }
  -
  -        int indexForColumn(String name)
  -        {
  -            int result = -1;
  -            for (int i = 0; i < columnNames.length; i++)
  -            {
  -                if(columnNames[i].equals(name))
  -                {
  -                    result = i;
  -                    break;
  -                }
  -            }
  -            return result;
  -        }
  -
  -        public int hashCode()
  -        {
  -            return super.hashCode();
  -        }
  -
  -        public ValueContainer getValueFor(String columnName)
  -        {
  -            try
  -            {
  -                return values[indexForColumn(columnName)];
  -            }
  -            catch(Exception e)
  -            {
  -                throw new OJBRuntimeException("Can't find value for column " + columnName
  -                        + (indexForColumn(columnName) < 0 ? ". Column name was not found"
: ""), e);
  -            }
  -        }
  -
  -        public String getTablename()
  -        {
  -            return tablename;
  -        }
  -
  -        public String[] getColumnNames()
  -        {
  -            return columnNames;
  -        }
  -
  -        public ValueContainer[] getValues()
  -        {
  -            return values;
  -        }
  -
  -        public void setValues(ValueContainer[] values)
  -        {
  -            this.values = values;
  -        }
  -
  -        public String toString()
  -        {
  -            return new ToStringBuilder(this)
  -                    .append("tableName", tablename)
  -                    .append("columnNames", columnNames)
  -                    .append("values", values)
  -                    .toString();
  -        }
  -    }
  -}
  +package org.apache.ojb.broker.core;
  +
  +/* Copyright 2003-2004 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.
  + */
  +
  +import java.util.ArrayList;
  +import java.util.Collection;
  +import java.util.Iterator;
  +import java.util.List;
  +import java.util.Vector;
  +
  +import org.apache.commons.lang.builder.EqualsBuilder;
  +import org.apache.commons.lang.builder.HashCodeBuilder;
  +import org.apache.commons.lang.builder.ToStringBuilder;
  +import org.apache.ojb.broker.MtoNImplementor;
  +import org.apache.ojb.broker.OJBRuntimeException;
  +import org.apache.ojb.broker.PersistenceBroker;
  +import org.apache.ojb.broker.PersistenceBrokerException;
  +import org.apache.ojb.broker.accesslayer.ResultSetAndStatement;
  +import org.apache.ojb.broker.accesslayer.sql.SqlGenerator;
  +import org.apache.ojb.broker.core.proxy.ProxyHelper;
  +import org.apache.ojb.broker.metadata.ClassDescriptor;
  +import org.apache.ojb.broker.metadata.CollectionDescriptor;
  +import org.apache.ojb.broker.metadata.DescriptorRepository;
  +import org.apache.ojb.broker.metadata.FieldDescriptor;
  +import org.apache.ojb.broker.metadata.JdbcType;
  +import org.apache.ojb.broker.query.Query;
  +import org.apache.ojb.broker.util.logging.Logger;
  +import org.apache.ojb.broker.util.logging.LoggerFactory;
  +
  +/**
  + * Manage all stuff related to non-decomposed M:N association.
  + *
  + * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
  + * @author <a href="mailto:leandro@ibnetwork.com.br">Leandro Rodrigo Saad Cruz<a>
  + * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird<a>
  + * @author <a href="mailto:jbraeuchi@hotmail.com">Jakob Braeuchi</a>
  + * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
  + * @version $Id$
  + */
  +public class MtoNBroker
  +{
  +    private Logger log = LoggerFactory.getLogger(MtoNBroker.class);
  +
  +    private PersistenceBroker pb;
  +    /**
  +     * Used to store {@link GenericObject} while transaction running, used as
  +     * workaround for m:n insert problem.
  +     * TODO: find better solution for m:n handling
  +     */
  +    private List tempObjects = new ArrayList();
  +
  +    public MtoNBroker(final PersistenceBroker broker)
  +    {
  +        this.pb = broker;
  +    }
  +
  +    public void reset()
  +    {
  +        tempObjects.clear();
  +    }
  +
  +    /**
  +     * Stores new values of a M:N association in a indirection table.
  +     *
  +     * @param cod        The {@link org.apache.ojb.broker.metadata.CollectionDescriptor}
for the m:n relation
  +     * @param realObject The real object
  +     * @param otherObj   The referenced object
  +     * @param mnKeys     The all {@link org.apache.ojb.broker.core.MtoNBroker.Key} matching
the real object
  +     */
  +    public void storeMtoNImplementor(CollectionDescriptor cod, Object realObject, Object
otherObj, Collection mnKeys)
  +    {
  +        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(realObject.getClass());
  +        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, realObject);
  +        String[] pkColumns = cod.getFksToThisClass();
  +
  +        ClassDescriptor otherCld = pb.getDescriptorRepository().getDescriptorFor(ProxyHelper.getRealClass(otherObj));
  +        ValueContainer[] otherPkValues = pb.serviceBrokerHelper().getKeyValues(otherCld,
otherObj);
  +
  +        String[] otherPkColumns = cod.getFksToItemClass();
  +        String table = cod.getIndirectionTable();
  +        MtoNBroker.Key key = new MtoNBroker.Key(otherPkValues);
  +
  +        if(mnKeys.contains(key))
  +        {
  +            return;
  +        }
  +
  +        String[] cols = mergeColumns(pkColumns, otherPkColumns);
  +        String insertStmt = pb.serviceSqlGenerator()
  +                .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_INSERT, table, cols,
null);
  +        ValueContainer[] values = mergeContainer(pkValues, otherPkValues);
  +        GenericObject gObj = new GenericObject(table, cols, values);
  +        if(! tempObjects.contains(gObj))
  +        {
  +            pb.serviceJdbcAccess().executeUpdateSQL(insertStmt, cld, values);
  +            tempObjects.add(gObj);
  +        }
  +    }
  +
  +    /**
  +     * get a Collection of Keys of already existing m:n rows
  +     *
  +     * @param cod
  +     * @param obj
  +     * @return Collection of Key
  +     */
  +    public List getMtoNImplementor(CollectionDescriptor cod, Object obj)
  +    {
  +        ResultSetAndStatement rs = null;
  +        ArrayList result = new ArrayList();
  +        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(obj.getClass());
  +        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, obj);
  +        String[] pkColumns = cod.getFksToThisClass();
  +        String[] fkColumns = cod.getFksToItemClass();
  +        String table = cod.getIndirectionTable();
  +
  +        String selectStmt = pb.serviceSqlGenerator()
  +                .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_SELECT, table, fkColumns,
pkColumns);
  +
  +        ClassDescriptor itemCLD = cod.getItemClassDescriptor();
  +        Collection extents = pb.getDescriptorRepository().getAllConcreteSubclassDescriptors(itemCLD);
  +        if(extents.size() > 0)
  +        {
  +            itemCLD = (ClassDescriptor) extents.iterator().next();
  +        }
  +        FieldDescriptor[] itemClassPKFields = itemCLD.getPkFields();
  +        if(itemClassPKFields.length != fkColumns.length)
  +        {
  +            throw new PersistenceBrokerException("All pk fields of the element-class need
to" +
  +                    " be declared in the indirection table. Element class is "
  +                    + itemCLD.getClassNameOfObject() + " with " + itemClassPKFields.length
+ " pk-fields." +
  +                    " Declared 'fk-pointing-to-element-class' elements in collection-descriptor
are"
  +                    + fkColumns.length);
  +        }
  +        try
  +        {
  +            rs = pb.serviceJdbcAccess().executeSQL(selectStmt, pkValues, Query.NOT_SCROLLABLE);
  +            while(rs.m_rs.next())
  +            {
  +                ValueContainer[] row = new ValueContainer[fkColumns.length];
  +                for(int i = 0; i < row.length; i++)
  +                {
  +                    row[i] = new ValueContainer(rs.m_rs.getObject(i + 1), itemClassPKFields[i].getJdbcType());
  +                }
  +                result.add(new MtoNBroker.Key(row));
  +            }
  +        }
  +        catch(Exception e)
  +        {
  +            throw new PersistenceBrokerException(e);
  +        }
  +        finally
  +        {
  +            rs.close();
  +        }
  +        return result;
  +    }
  +
  +    /**
  +     * delete all rows from m:n table belonging to obj
  +     *
  +     * @param cod
  +     * @param obj
  +     */
  +    public void deleteMtoNImplementor(CollectionDescriptor cod, Object obj)
  +    {
  +        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(obj.getClass());
  +        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, obj);
  +        String[] pkColumns = cod.getFksToThisClass();
  +        String table = cod.getIndirectionTable();
  +        String deleteStmt = pb.serviceSqlGenerator()
  +                .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_DELETE, table, null,
pkColumns);
  +        pb.serviceJdbcAccess().executeUpdateSQL(deleteStmt, cld, pkValues);
  +    }
  +
  +    /**
  +     * deletes all rows from m:n table that are not used in relatedObjects
  +     *
  +     * @param cod
  +     * @param obj
  +     * @param collectionIterator
  +     * @param mnKeys
  +     */
  +    public void deleteMtoNImplementor(CollectionDescriptor cod, Object obj, Iterator collectionIterator,
Collection mnKeys)
  +    {
  +        if(mnKeys.isEmpty() || collectionIterator == null)
  +        {
  +            return;
  +        }
  +        List workList = new ArrayList(mnKeys);
  +        MtoNBroker.Key relatedObjKeys;
  +        ClassDescriptor relatedCld = cod.getItemClassDescriptor();
  +        Object relatedObj;
  +
  +        // remove keys of relatedObject from the existing m:n rows in workList
  +        while(collectionIterator.hasNext())
  +        {
  +            relatedObj = collectionIterator.next();
  +            relatedObjKeys = new MtoNBroker.Key(pb.serviceBrokerHelper().getKeyValues(relatedCld,
relatedObj, true));
  +            workList.remove(relatedObjKeys);
  +        }
  +
  +        // delete all remaining keys in workList
  +        ClassDescriptor cld = pb.getDescriptorRepository().getDescriptorFor(obj.getClass());
  +        ValueContainer[] pkValues = pb.serviceBrokerHelper().getKeyValues(cld, obj);
  +
  +        String[] pkColumns = cod.getFksToThisClass();
  +        String[] fkColumns = cod.getFksToItemClass();
  +        String table = cod.getIndirectionTable();
  +        String deleteStmt;
  +
  +        String[] columns = mergeColumns(pkColumns, fkColumns);
  +        ValueContainer[] fkValues;
  +        Iterator iter = workList.iterator();
  +        while(iter.hasNext())
  +        {
  +            fkValues = ((MtoNBroker.Key) iter.next()).m_containers;
  +            deleteStmt = pb.serviceSqlGenerator()
  +                    .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_DELETE, table,
null, columns);
  +            pb.serviceJdbcAccess().executeUpdateSQL(deleteStmt, cld, mergeContainer(pkValues,
fkValues));
  +        }
  +    }
  +
  +    /**
  +     * @param m2n
  +     */
  +    public void storeMtoNImplementor(MtoNImplementor m2n)
  +    {
  +        if(log.isDebugEnabled()) log.debug("Storing M2N implementor [" + m2n + "]");
  +        insertOrDeleteMtoNImplementor(m2n, true);
  +    }
  +
  +    /**
  +     * @param m2n
  +     */
  +    public void deleteMtoNImplementor(MtoNImplementor m2n)
  +    {
  +        if(log.isDebugEnabled()) log.debug("Deleting M2N implementor [" + m2n + "]");
  +        insertOrDeleteMtoNImplementor(m2n, false);
  +    }
  +
  +
  +    /**
  +     * @see org.apache.ojb.broker.PersistenceBroker#deleteMtoNImplementor
  +     */
  +    private void insertOrDeleteMtoNImplementor(MtoNImplementor m2nImpl, boolean insert)
  +            throws PersistenceBrokerException
  +    {
  +        //look for a collection descriptor on left  such as left.element-class-ref='right'
  +        DescriptorRepository dr = pb.getDescriptorRepository();
  +
  +        Object leftObject = m2nImpl.getLeftObject();
  +        Class leftClass = leftObject.getClass();
  +        Object rightObject = m2nImpl.getRightObject();
  +        Class rightClass = rightObject.getClass();
  +
  +        //are written per class, maybe referencing abstract classes or interfaces
  +        //so let's look for collection descriptors on the left class and try to
  +        // handle extents on teh right class
  +        ClassDescriptor leftCld = dr.getDescriptorFor(leftClass);
  +        ClassDescriptor rightCld = dr.getDescriptorFor(rightClass);
  +        Vector leftColds = leftCld.getCollectionDescriptors();
  +        CollectionDescriptor wanted = findCollectionDescriptor(leftClass, rightClass, leftColds);
  +
  +        if(leftObject == null || rightObject == null)
  +        {
  +            //TODO: to be implemented, must change MtoNImplementor
  +            //deleteMtoNImplementor(wanted,leftObject) || deleteMtoNImplementor(wanted,rightObject)
  +        }
  +        else
  +        {
  +            //delete only one row
  +            ValueContainer[] leftPkValues = pb.serviceBrokerHelper().getKeyValues(leftCld,
leftObject);
  +            ValueContainer[] rightPkValues = pb.serviceBrokerHelper().getKeyValues(rightCld,
rightObject);
  +            String[] pkLeftColumns = wanted.getFksToThisClass();
  +            String[] pkRightColumns = wanted.getFksToItemClass();
  +            String table = wanted.getIndirectionTable();
  +            if(table == null) throw new PersistenceBrokerException("Can't remove MtoN implementor
without an indirection table");
  +
  +            String stmt = null;
  +            String[] cols = mergeColumns(pkLeftColumns, pkRightColumns);
  +            ValueContainer[] values = mergeContainer(leftPkValues, rightPkValues);
  +            if(insert)
  +            {
  +                stmt = pb.serviceSqlGenerator()
  +                        .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_INSERT,
table, cols, null);
  +                GenericObject gObj = new GenericObject(table, cols, values);
  +                if(!tempObjects.contains(gObj))
  +                {
  +                    pb.serviceJdbcAccess().executeUpdateSQL(stmt, leftCld, values);
  +                    tempObjects.add(gObj);
  +                }
  +            }
  +            else
  +            {
  +                stmt = pb.serviceSqlGenerator()
  +                        .getGenericPreparedStatement(SqlGenerator.TYPE_GENERIC_DELETE,
table, null, cols);
  +                pb.serviceJdbcAccess().executeUpdateSQL(stmt, leftCld, values);
  +            }
  +        }
  +    }
  +
  +    private CollectionDescriptor findCollectionDescriptor(Class leftClass, Class rightClass,
Vector leftColds)
  +    {
  +        for(Iterator iter = leftColds.iterator(); iter.hasNext();)
  +        {
  +            CollectionDescriptor element = (CollectionDescriptor) iter.next();
  +
  +            //try super classes and interfaces too
  +            if(element.getItemClass().isAssignableFrom(rightClass))
  +            {
  +                //we found it !
  +                return element;
  +            }
  +        }
  +        throw new PersistenceBrokerException("Can't find reasonable collection descriptor
for MtoN implementor left[" + leftClass
  +                + "] right[" + rightClass + "]");
  +    }
  +
  +    private String[] mergeColumns(String[] first, String[] second)
  +    {
  +        String[] cols = new String[first.length + second.length];
  +        System.arraycopy(first, 0, cols, 0, first.length);
  +        System.arraycopy(second, 0, cols, first.length, second.length);
  +        return cols;
  +    }
  +
  +    private ValueContainer[] mergeContainer(ValueContainer[] first, ValueContainer[] second)
  +    {
  +        ValueContainer[] values = new ValueContainer[first.length + second.length];
  +        System.arraycopy(first, 0, values, 0, first.length);
  +        System.arraycopy(second, 0, values, first.length, second.length);
  +        return values;
  +    }
  +
  +
  +
  +// ************************************************************************
  +// inner class
  +// ************************************************************************
  +
  +    /**
  +     * This is a helper class to model a Key of an Object
  +     */
  +    private static final class Key
  +    {
  +        final ValueContainer[] m_containers;
  +
  +        Key(final ValueContainer[] containers)
  +        {
  +            m_containers = new ValueContainer[containers.length];
  +
  +            for(int i = 0; i < containers.length; i++)
  +            {
  +                Object value = containers[i].getValue();
  +                JdbcType type = containers[i].getJdbcType();
  +
  +                // BRJ:
  +                // convert all Numbers to Long to simplify equals
  +                // Long(100) is not equal to Integer(100)
  +                //
  +                // could lead to problems when Floats are used as key
  +                // converting to String could be a better alternative
  +                if(value instanceof Number)
  +                {
  +                    value = new Long(((Number) value).longValue());
  +                }
  +
  +                m_containers[i] = new ValueContainer(value, type);
  +            }
  +        }
  +
  +        public boolean equals(Object other)
  +        {
  +            if(other == this)
  +            {
  +                return true;
  +            }
  +            if(!(other instanceof Key))
  +            {
  +                return false;
  +            }
  +
  +            Key otherKey = (Key) other;
  +            EqualsBuilder eb = new EqualsBuilder();
  +
  +            eb.append(m_containers, otherKey.m_containers);
  +            return eb.isEquals();
  +        }
  +
  +        public int hashCode()
  +        {
  +            HashCodeBuilder hb = new HashCodeBuilder();
  +            hb.append(m_containers);
  +
  +            return hb.toHashCode();
  +        }
  +    }
  +
  +
  +
  +    // ************************************************************************
  +    // inner class
  +    // ************************************************************************
  +    private static final class GenericObject
  +    {
  +        private String tablename;
  +        private String[] columnNames;
  +        private ValueContainer[] values;
  +
  +        public GenericObject(String tablename, String[] columnNames, ValueContainer[] values)
  +        {
  +            this.tablename = tablename;
  +            this.columnNames = columnNames;
  +            this.values = values;
  +            if(values != null && columnNames.length != values.length)
  +            {
  +                throw new OJBRuntimeException("Column name array and value array have NOT
same length");
  +            }
  +        }
  +
  +        public boolean equals(Object obj)
  +        {
  +            if(this == obj)
  +            {
  +                return true;
  +            }
  +            boolean result = false;
  +            if(obj instanceof GenericObject)
  +            {
  +                GenericObject other = (GenericObject) obj;
  +                result = (tablename.equalsIgnoreCase(other.tablename)
  +                        && (columnNames != null)
  +                        && (other.columnNames != null)
  +                        && (columnNames.length == other.columnNames.length));
  +                if(result)
  +                {
  +                    for (int i = 0; i < columnNames.length; i++)
  +                    {
  +                        // System.out.println("## test: " + this);
  +                        int otherIndex = other.indexForColumn(columnNames[i]);
  +                        if(otherIndex < 0)
  +                        {
  +                            result = false;
  +                            break;
  +                        }
  +                        result = result && values[i].equals(other.values[otherIndex]);
  +                        if(!result) break;
  +                    }
  +                }
  +            }
  +            return result;
  +        }
  +
  +        int indexForColumn(String name)
  +        {
  +            int result = -1;
  +            for (int i = 0; i < columnNames.length; i++)
  +            {
  +                if(columnNames[i].equals(name))
  +                {
  +                    result = i;
  +                    break;
  +                }
  +            }
  +            return result;
  +        }
  +
  +        public int hashCode()
  +        {
  +            return super.hashCode();
  +        }
  +
  +        public ValueContainer getValueFor(String columnName)
  +        {
  +            try
  +            {
  +                return values[indexForColumn(columnName)];
  +            }
  +            catch(Exception e)
  +            {
  +                throw new OJBRuntimeException("Can't find value for column " + columnName
  +                        + (indexForColumn(columnName) < 0 ? ". Column name was not found"
: ""), e);
  +            }
  +        }
  +
  +        public String getTablename()
  +        {
  +            return tablename;
  +        }
  +
  +        public String[] getColumnNames()
  +        {
  +            return columnNames;
  +        }
  +
  +        public ValueContainer[] getValues()
  +        {
  +            return values;
  +        }
  +
  +        public void setValues(ValueContainer[] values)
  +        {
  +            this.values = values;
  +        }
  +
  +        public String toString()
  +        {
  +            return new ToStringBuilder(this)
  +                    .append("tableName", tablename)
  +                    .append("columnNames", columnNames)
  +                    .append("values", values)
  +                    .toString();
  +        }
  +    }
  +}
  
  
  
  1.18      +4 -3      db-ojb/src/java/org/apache/ojb/broker/accesslayer/PkEnumeration.java
  
  Index: PkEnumeration.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/PkEnumeration.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- PkEnumeration.java	4 Apr 2004 23:53:31 -0000	1.17
  +++ PkEnumeration.java	22 Jan 2005 20:52:34 -0000	1.18
  @@ -15,7 +15,6 @@
    * limitations under the License.
    */
   
  -import java.io.Serializable;
   import java.lang.reflect.Constructor;
   import java.sql.SQLException;
   import java.util.Enumeration;
  @@ -38,7 +37,7 @@
    * @author Thomas Mahler
    * @version $Id$
    */
  -public class PkEnumeration implements Enumeration, Serializable
  +public class PkEnumeration implements Enumeration
   {
   	static final long serialVersionUID = -834955711995869884L;
       protected boolean hasCalledCheck = false;
  @@ -177,7 +176,9 @@
           try
           {
               if (!hasCalledCheck)
  +            {
                   hasMoreElements();
  +            }    
               hasCalledCheck = false;
               if (hasNext)
               {
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message