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:[EMAIL PROTECTED]">Thomas Mahler<a>
  - * @author <a href="mailto:[EMAIL PROTECTED]">Leandro Rodrigo Saad Cruz<a>
  - * @author <a href="mailto:[EMAIL PROTECTED]">Matthew Baird<a>
  - * @author <a href="mailto:[EMAIL PROTECTED]">Jakob Braeuchi</a>
  - * @author <a href="mailto:[EMAIL PROTECTED]">Armin Waibel</a>
  - * @version $Id$
  - */
  -public class MtoNBroker
  -{
  -    private Logger log = LoggerFactory.getLogger(MtoNBroker.class);
  -
  -    private PersistenceBroker pb;
  -    /**
  -     * Used to store [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 
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 [EMAIL PROTECTED] 
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:[EMAIL PROTECTED]">Thomas Mahler<a>

  + * @author <a href="mailto:[EMAIL PROTECTED]">Leandro Rodrigo Saad Cruz<a>

  + * @author <a href="mailto:[EMAIL PROTECTED]">Matthew Baird<a>

  + * @author <a href="mailto:[EMAIL PROTECTED]">Jakob Braeuchi</a>

  + * @author <a href="mailto:[EMAIL PROTECTED]">Armin Waibel</a>

  + * @version $Id$

  + */

  +public class MtoNBroker

  +{

  +    private Logger log = LoggerFactory.getLogger(MtoNBroker.class);

  +

  +    private PersistenceBroker pb;

  +    /**

  +     * Used to store [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 
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 [EMAIL PROTECTED] 
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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to