Package org.apache.ojb.broker.util

Source Code of org.apache.ojb.broker.util.BrokerHelper

package org.apache.ojb.broker.util;

/* Copyright 2002-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.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.WeakHashMap;

import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.ManageableCollection;
import org.apache.ojb.broker.OJBRuntimeException;
import org.apache.ojb.broker.PBKey;
import org.apache.ojb.broker.PersistenceBrokerException;
import org.apache.ojb.broker.PersistenceBrokerSQLException;
import org.apache.ojb.broker.accesslayer.StatementManagerIF;
import org.apache.ojb.broker.accesslayer.sql.SqlExistStatement;
import org.apache.ojb.broker.core.PersistenceBrokerImpl;
import org.apache.ojb.broker.core.ValueContainer;
import org.apache.ojb.broker.core.proxy.IndirectionHandler;
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.FieldDescriptor;
import org.apache.ojb.broker.metadata.FieldHelper;
import org.apache.ojb.broker.metadata.MetadataException;
import org.apache.ojb.broker.metadata.MetadataManager;
import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
import org.apache.ojb.broker.platforms.Platform;
import org.apache.ojb.broker.query.Criteria;
import org.apache.ojb.broker.query.MtoNQuery;
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.query.QueryByCriteria;
import org.apache.ojb.broker.query.QueryBySQL;
import org.apache.ojb.broker.query.ReportQueryByCriteria;
import org.apache.ojb.broker.query.ReportQueryByMtoNCriteria;
import org.apache.ojb.broker.util.logging.LoggerFactory;
import org.apache.ojb.broker.util.sequence.SequenceManagerException;

/**
* This class contains helper methods primarily used by the {@link org.apache.ojb.broker.PersistenceBroker}
* implementation (e.g. contains methods to assign the the values of 'autoincrement' fields).
* <br/>
* Furthermore it was used to introduce new features related to {@link org.apache.ojb.broker.PersistenceBroker} - these
* new features and services (if they stand the test of time) will be moved to separate services in future.
*
* @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
* @version $Id: BrokerHelper.java,v 1.57 2004/06/25 16:08:45 arminw Exp $
*/
public class BrokerHelper
{
    public static final String REPOSITORY_NAME_SEPARATOR = "#";
    private PersistenceBrokerImpl m_broker;

    public BrokerHelper(PersistenceBrokerImpl broker)
    {
        this.m_broker = broker;
    }

    /**
     * splits up the name string and extract db url,
     * user name and password and build a new PBKey
     * instance - the token '#' is used to separate
     * the substrings.
     * @throws PersistenceBrokerException if given name was <code>null</code>
     */
    public static PBKey extractAllTokens(String name)
    {
        if(name == null)
        {
            throw new PersistenceBrokerException("Could not extract PBKey, given argument is 'null'");
        }
        String user = null;
        String passwd = null;
        StringTokenizer tok = new StringTokenizer(name, REPOSITORY_NAME_SEPARATOR);
        String dbName = tok.nextToken();
        if(tok.hasMoreTokens())
        {
            user = tok.nextToken();
            if(user != null && user.trim().equals(""))
            {
                user = null;
            }
        }
        if(tok.hasMoreTokens())
        {
            if(user != null)
                passwd = tok.nextToken();
        }
        if(user != null && passwd == null)
        {
            passwd = "";
        }
        PBKey key = new PBKey(dbName, user, passwd);
        return key;
    }

    /**
     * Check if the user of the given PBKey was <code>null</code>, if so we try to
     * get user/password from the jdbc-connection-descriptor matching the given
     * PBKey.getAlias().
     */
    public static PBKey crossCheckPBKey(PBKey key)
    {
        if(key.getUser() == null)
        {
            PBKey defKey = MetadataManager.getInstance().connectionRepository().getStandardPBKeyForJcdAlias(key.getAlias());
            if(defKey != null)
            {
                return defKey;
            }
        }
        return key;
    }

    /**
     * Answer the real ClassDescriptor for anObj
     * ie. aCld may be an Interface of anObj, so the cld for anObj is returned
     */
    private ClassDescriptor getRealClassDescriptor(ClassDescriptor aCld, Object anObj)
    {
        ClassDescriptor result;

        if(aCld.getClassOfObject() == anObj.getClass())
        {
            result = aCld;
        }
        else
        {
            result = aCld.getRepository().getDescriptorFor(anObj.getClass());
        }

        return result;
    }

    /**
     * Returns an Array with an Objects PK VALUES if convertToSql is true, any
     * associated java-to-sql conversions are applied. If the Object is a Proxy
     * or a VirtualProxy NO conversion is necessary.
     *
     * @param objectOrProxy
     * @param convertToSql
     * @return Object[]
     * @throws PersistenceBrokerException
     */
    public ValueContainer[] getKeyValues(ClassDescriptor cld, Object objectOrProxy, boolean convertToSql) throws PersistenceBrokerException
    {
        IndirectionHandler handler = ProxyHelper.getIndirectionHandler(objectOrProxy);

        if(handler != null)
        {
            return getKeyValues(cld, handler.getIdentity(), convertToSql)//BRJ: convert Identity
        }
        else
        {
            ClassDescriptor realCld = getRealClassDescriptor(cld, objectOrProxy);
            return getValuesForObject(realCld.getPkFields(), objectOrProxy, convertToSql);
        }
    }

    /**
     * Return primary key values of given Identity object.
     *
     * @param cld
     * @param oid
     * @return Object[]
     * @throws PersistenceBrokerException
     */
    public ValueContainer[] getKeyValues(ClassDescriptor cld, Identity oid) throws PersistenceBrokerException
    {
        return getKeyValues(cld, oid, true);
    }

    /**
     * Return key Values of an Identity
     * @param cld
     * @param oid
     * @param convertToSql
     * @return Object[]
     * @throws PersistenceBrokerException
     */
    public ValueContainer[] getKeyValues(ClassDescriptor cld, Identity oid, boolean convertToSql) throws PersistenceBrokerException
    {
        FieldDescriptor[] pkFields = cld.getPkFields();
        ValueContainer[] result = new ValueContainer[pkFields.length];
        Object[] pkValues = oid.getPrimaryKeyValues();

        try
        {
            for(int i = 0; i < result.length; i++)
            {
                FieldDescriptor fd = pkFields[i];
                Object cv = pkValues[i];
                if(convertToSql)
                {
                    // BRJ : apply type and value mapping
                    cv = fd.getFieldConversion().javaToSql(cv);
                }
                result[i] = new ValueContainer(cv, fd.getJdbcType());
            }
        }
        catch(Exception e)
        {
            throw new PersistenceBrokerException("Can't generate primary key values for given Identity " + oid, e);
        }
        return result;
    }

    /**
     * returns an Array with an Objects PK VALUES, with any java-to-sql
     * FieldConversion applied. If the Object is a Proxy or a VirtualProxy NO
     * conversion is necessary.
     *
     * @param objectOrProxy
     * @return Object[]
     * @throws PersistenceBrokerException
     */
    public ValueContainer[] getKeyValues(ClassDescriptor cld, Object objectOrProxy) throws PersistenceBrokerException
    {
        return getKeyValues(cld, objectOrProxy, true);
    }

    /**
     * Decide if the given object value represents 'null'.<br/>
     *
     * - If given value is 'null' itself, true will be returned<br/>
     *
     * - If given value is instance of Number with value 0 and the field-descriptor
     * represents a primitive field, true will be returned<br/>
     *
     * - If given value is instance of String with length 0 and the field-descriptor
     * is a primary key, true will be returned<br/>
     */
    public boolean representsNull(FieldDescriptor fld, Object aValue)
    {
        if(aValue == null) return true;

        boolean result = false;
        if(((aValue instanceof Number) && (((Number) aValue).longValue() == 0)))
        {
            Class type = fld.getPersistentField().getType();
            /*
            AnonymousPersistentFields will *always* have a null type according to the
            javadoc comments in AnonymousPersistentField.getType() and never represents
            a primitve java field with value 0, thus we return always 'false' in this case.
            (If the value object is null, the first check above return true)
            */
            if(type != null)
            {
                result = type.isPrimitive();
            }
        }
        // TODO: Do we need this check?? String could be nullified, why should we assume
        // it's 'null' on empty string?
        else if((aValue instanceof String) && (((String) aValue).length() == 0))
        {
            result = fld.isPrimaryKey();
        }
        return result;
    }

    /**
     * Detect if the given object has a PK field represents a 'null' value.
     */
    public boolean hasNullPKField(ClassDescriptor cld, Object obj)
    {
        FieldDescriptor[] fields = cld.getPkFields();
        boolean hasNull = false;
        FieldDescriptor fld;
        for(int i = 0; i < fields.length; i++)
        {
            fld = fields[i];
            hasNull = representsNull(fld, fld.getPersistentField().get(obj));
            if(hasNull) break;
        }
        return hasNull;
    }

    /**
     * Set an autoincremented value in given object field that has already
     * had a field conversion run on it, if an value for the given field is
     * already set, it will be overridden - no further checks are done.
     * <p>
     * The data type of the value that is returned by this method is
     * compatible with the java-world.  The return value has <b>NOT</b>
     * been run through a field conversion and converted to a corresponding
     * sql-type.
     *
     * @return the autoincremented value set on given object
     * @throws PersistenceBrokerException if there is an erros accessing obj field values
     */
    private Object setAutoIncrementValue(FieldDescriptor fd, Object obj, Object cv)
    {
        PersistentField f = fd.getPersistentField();
        try
        {
            // lookup SeqMan for a value matching db column an
            Object result = m_broker.serviceSequenceManager().getUniqueValue(fd);
            // reflect autoincrement value back into object
            f.set(obj, result);
            return result;
        }
        catch(MetadataException e)
        {
            throw new PersistenceBrokerException(
                    "Error while trying to autoincrement field " + f.getDeclaringClass() + "#" + f.getName(),
                    e);
        }
        catch(SequenceManagerException e)
        {
            throw new PersistenceBrokerException("Could not get key value", e);
        }
    }

    /**
     * Get the values of the fields for an obj
     * @param fields
     * @param obj
     * @throws PersistenceBrokerException
     */
    public ValueContainer[] getValuesForObject(FieldDescriptor[] fields, Object obj, boolean convertToSql) throws PersistenceBrokerException
    {
        ValueContainer[] result = new ValueContainer[fields.length];

        for(int i = 0; i < fields.length; i++)
        {
            FieldDescriptor fd = fields[i];
            Object cv = fd.getPersistentField().get(obj);

            /*
            handle autoincrement attributes if
            - is a autoincrement field
            - field represents a 'null' value, is nullified
            and generate a new value
            */
            if(fd.isAutoIncrement() && representsNull(fd, cv))
            {
                /*
                setAutoIncrementValue returns a value that is
                properly typed for the java-world.  This value
                needs to be converted to it's corresponding
                sql type so that the entire result array contains
                objects that are properly typed for sql.
                */
                cv = setAutoIncrementValue(fd, obj, cv);
            }
            if(convertToSql)
            {
                // apply type and value conversion
                cv = fd.getFieldConversion().javaToSql(cv);
            }
            // create ValueContainer
            result[i] = new ValueContainer(cv, fd.getJdbcType());
        }
        return result;
    }

    /**
     * returns an Array with an Objects NON-PK VALUES (READ/WRITE only)
     * @throws MetadataException if there is an erros accessing o field values
     */
    public ValueContainer[] getNonKeyRwValues(ClassDescriptor cld, Object obj) throws PersistenceBrokerException
    {
        ClassDescriptor realCld = getRealClassDescriptor(cld, obj);
        return getValuesForObject(realCld.getNonPkRwFields(), obj, true);
    }

    /**
     * returns an array containing values for all the Objects attribute (READ/WRITE only)
     * @throws MetadataException if there is an erros accessing obj field values
     */
    public ValueContainer[] getAllRwValues(ClassDescriptor cld, Object obj) throws PersistenceBrokerException
    {
        ClassDescriptor realCld = getRealClassDescriptor(cld, obj);
        return getValuesForObject(realCld.getAllRwFields(), obj, true);
    }

    /**
     * Extract an value array of the given {@link ValueContainer} array.
     * @param containers
     * @return
     */
    public Object[] extractValueArray(ValueContainer[] containers)
    {
        Object[] result = new Object[containers.length];
        for(int i = 0; i < containers.length; i++)
        {
            result[i] = containers[i].getValue();
        }
        return result;
    }

    /**
     * returns true if the primary key fields are valid, else false.
     * PK fields are valid if each of them is either an OJB managed
     * attribute (autoincrement or locking) or if it contains
     * a valid non-null value
     * @param fieldDescriptors the array of PK fielddescriptors
     * @param pkValues the array of PK values
     * @return boolean
     */
    public boolean assertValidPkFields(FieldDescriptor[] fieldDescriptors, Object[] pkValues)
    {
        int fieldDescriptorSize = fieldDescriptors.length;
        for(int i = 0; i < fieldDescriptorSize; i++)
        {
            /**
             * a pk field is valid if it is either managed by OJB
             * (autoincrement or locking) or if it does contain a
             * valid non-null value.
             */
            if(!(fieldDescriptors[i].isAutoIncrement()
                    || fieldDescriptors[i].isLocking()
                    || assertValidPkValue(pkValues[i])))
            {
                return false;
            }
        }
        return true;
    }

    /**
     * returns true if a value is non-null, STring instances are also checked,
     * if they are non-empty.
     * @param pkValue the value to check
     * @return boolean
     */
    private boolean assertValidPkValue(Object pkValue)
    {
        // null as value of a primary key is not acceptable
        if(pkValue == null)
        {
            return false;
        }
        if(pkValue instanceof String)
        {
            // the toString() method on a String-object is maybe faster
            // than the downcast to String. Also use length() to test
            // if a String empty or not, this is faster than the comparing
            // a String-object with an empty string using the equals()-method.
            if(pkValue.toString().trim().length() == 0)
            {
                return false;
            }
        }
        return true;
    }

    /**
     * Build a Count-Query based on aQuery
     * @param aQuery
     * @return
     */
    public Query getCountQuery(Query aQuery)
    {
        if(aQuery instanceof QueryBySQL)
        {
            return getQueryBySqlCount((QueryBySQL) aQuery);
        }
        else if(aQuery instanceof ReportQueryByCriteria)
        {
            return getReportQueryByCriteriaCount((ReportQueryByCriteria) aQuery);
        }
        else
        {
            return getQueryByCriteriaCount((QueryByCriteria) aQuery);
        }
    }

    /**
     * Create a Count-Query for QueryBySQL
     *
     * @param aQuery
     * @return
     */
    private Query getQueryBySqlCount(QueryBySQL aQuery)
    {
        String countSql = aQuery.getSql();

        int fromPos = countSql.toUpperCase().indexOf(" FROM ");
        if(fromPos >= 0)
        {
            countSql = "select count(*)" + countSql.substring(fromPos);
        }

        int orderPos = countSql.toUpperCase().indexOf(" ORDER BY ");
        if(orderPos >= 0)
        {
            countSql = countSql.substring(0, orderPos);
        }

        return new QueryBySQL(aQuery.getSearchClass(), countSql);
    }

    /**
     * Create a Count-Query for QueryByCriteria
     *
     * @param aQuery
     * @return
     */
    private Query getQueryByCriteriaCount(QueryByCriteria aQuery)
    {
        Class searchClass = aQuery.getSearchClass();
        ReportQueryByCriteria countQuery;
        Criteria countCrit = null;
        String[] columns = new String[1];

        // BRJ: copied Criteria without groupby, orderby, and prefetched relationships
        if (aQuery.getCriteria() != null)
        {
            countCrit = aQuery.getCriteria().copy(false,false,false);
        }

        if(aQuery.isDistinct())
        {
            //
            // BRJ: Count distinct is dbms dependent
            // hsql/sapdb: select count (distinct(person_id || project_id)) from person_project
            // mysql: select count (distinct person_id,project_id) from person_project
            //
            // concatenation of pk-columns is a simple way to obtain a single column
            // but concatenation is also dbms dependent:
            //
            // SELECT count(distinct concat(row1, row2, row3)) mysql
            // SELECT count(distinct (row1 || row2 || row3)) ansi
            // SELECT count(distinct (row1 + row2 + row3)) ms sql-server
            //
            FieldDescriptor[] pkFields = m_broker.getClassDescriptor(searchClass).getPkFields();
            String[] keyColumns = new String[pkFields.length];

            if(pkFields.length > 1)
            {
                // TODO: Use ColumnName. This is a temporary solution because
                // we cannot yet resolve multiple columns in the same attribute.
                for(int i = 0; i < pkFields.length; i++)
                {
                    keyColumns[i] = pkFields[i].getColumnName();
                }
            }
            else
            {
                for(int i = 0; i < pkFields.length; i++)
                {
                    keyColumns[i] = pkFields[i].getAttributeName();
                }
            }
            columns[0] = "count(distinct " + getPlatform().concatenate(keyColumns) + ")";
        }
        else
        {
            columns[0] = "count(*)";
        }

        // BRJ: we have to preserve indirection table !
        if(aQuery instanceof MtoNQuery)
        {
            MtoNQuery mnQuery = (MtoNQuery) aQuery;
            ReportQueryByMtoNCriteria mnReportQuery = new ReportQueryByMtoNCriteria(searchClass,
                    columns, countCrit);
            mnReportQuery.setIndirectionTable(mnQuery.getIndirectionTable());

            countQuery = mnReportQuery;
        }
        else
        {
            countQuery = new ReportQueryByCriteria(searchClass, columns, countCrit);
        }

        // BRJ: we have to preserve outer-join-settings (by Andr� Markwalder)
        Iterator outerJoinPath = aQuery.getOuterJoinPaths().iterator();
        while (outerJoinPath.hasNext())
        {
            String path = (String) outerJoinPath.next();
            if (aQuery.isPathOuterJoin(path))
            {
                countQuery.setPathOuterJoin(path);
            }
        }

        return countQuery;
    }

    /**
     * Create a Count-Query for ReportQueryByCriteria
     *
     * @param aQuery
     * @return
     */
    private Query getReportQueryByCriteriaCount(ReportQueryByCriteria aQuery)
    {
        ReportQueryByCriteria countQuery = (ReportQueryByCriteria) getQueryByCriteriaCount(aQuery);

        // BRJ: keep the original columns to build the Join
        countQuery.setJoinAttributes(aQuery.getAttributes());

        // BRJ: we have to preserve groupby information
        Iterator iter = aQuery.getGroupBy().iterator();
        while(iter.hasNext())
        {
            countQuery.addGroupBy((FieldHelper) iter.next());
        }

        return countQuery;
    }

    /**
     * answer the platform
     *
     * @return the platform
     */
    private Platform getPlatform()
    {
        return m_broker.serviceSqlGenerator().getPlatform();
    }


    /*
    NOTE: use WeakHashMap to allow reclaiming of no longer used ClassDescriptor
    instances
    */
    private Map sqlSelectMap = new WeakHashMap();

    /**
     * TODO: This method should be moved to {@link org.apache.ojb.broker.accesslayer.JdbcAccess}
     * before 1.1 release. This method only checks if the requested object can be
     * found in DB (without full object materialization).
     */
    public boolean doesExist(ClassDescriptor cld, Identity oid, Object obj)
    {
        boolean result = false;
        String sql = (String) sqlSelectMap.get(cld);
        if(sql == null)
        {
            sql = new SqlExistStatement(cld, LoggerFactory.getDefaultLogger()).getStatement();
            sqlSelectMap.put(cld, sql);
        }
        StatementManagerIF sm = m_broker.serviceStatementManager();
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try
        {
            stmt = sm.getPreparedStatement(cld, sql, false);
            sm.bindSelect(stmt, oid, cld);
            rs = stmt.executeQuery();
            result = rs.next();
        }
        catch(SQLException e)
        {
            throw new PersistenceBrokerSQLException("Exist check failed for identity " + oid
                    + ", sql was " + sql, e);
        }
        finally
        {
            sm.closeResources(stmt, rs);
        }

        return result;
    }


    /**
     * This method concatenate the main object with all reference
     * objects (1:1, 1:n and m:n) by hand. This method is needed when
     * in the reference metadata definitions the auto-xxx setting was disabled.
     * More info see OJB doc.
     */
    public void link(Object obj, boolean insert)
    {
        linkOrUnlink(true, obj, insert);
    }

    /**
     * Unlink all references from this object.
     * More info see OJB doc.
     * @param obj
     */
    public void unlink(Object obj)
    {
        linkOrUnlink(false, obj, false);
    }

    private void linkOrUnlink(boolean doLink, Object obj, boolean insert)
    {
        ClassDescriptor cld = m_broker.getDescriptorRepository().getDescriptorFor(obj.getClass());
        // never returns null, thus we can direct call iterator
        Iterator descriptors = null;
        if(cld.getObjectReferenceDescriptors().size() > 0)
        {
            descriptors = cld.getObjectReferenceDescriptors().iterator();
            ObjectReferenceDescriptor ord;
            while(descriptors.hasNext())
            {
                ord = (ObjectReferenceDescriptor) descriptors.next();
                if(doLink)
                {
                    m_broker.linkOneToOne(obj, cld, ord, insert);
                }
                else
                {
                    m_broker.unlinkFK(obj, cld, ord);
                    // in 1:1 relation we have to set relation to null
                    ord.getPersistentField().set(obj, null);
                }
            }
        }
        if(cld.getCollectionDescriptors().size() > 0)
        {
            descriptors = cld.getCollectionDescriptors().iterator();
            CollectionDescriptor cod;
            while(descriptors.hasNext())
            {
                cod = (CollectionDescriptor) descriptors.next();
                if(doLink)
                {
                    if(cod.isMtoNRelation())
                    {
                        m_broker.linkMtoN(obj, cod, insert);
                    }
                    else
                    {
                        m_broker.linkOneToMany(obj, cod, insert);
                    }
                }
                else
                {
                    m_broker.unlinkXtoN(obj, cod);
                }
            }
        }
    }

    /**
     * This method concatenate the main object and the specified reference
     * object (1:1 reference a referenced object, 1:n and m:n reference a
     * collection of referenced objects) by hand. This method is needed when
     * in the reference metadata definitions the auto-xxx setting was disabled.
     * More info see OJB doc.
     *
     * @param obj Object with reference
     * @param attributeName field name of the reference
     * @param insert flag signals insert operation
     * @return true if the specified reference was found and linking was successful
     */
    public boolean link(Object obj, String attributeName, boolean insert)
    {
       return linkOrUnlink(true, obj, attributeName, insert);
    }

    /**
     * Unlink the specified reference from this object.
     * More info see OJB doc.
     * @param obj
     */
    public boolean unlink(Object obj, String attributeName)
    {
        return linkOrUnlink(false, obj, attributeName, false);
    }

    private boolean linkOrUnlink(boolean doLink, Object obj, String attributeName, boolean insert)
    {
        boolean match = false;
        ClassDescriptor cld = m_broker.getDescriptorRepository().getDescriptorFor(ProxyHelper.getRealClass(obj));
        ObjectReferenceDescriptor ord = cld.getObjectReferenceDescriptorByName(attributeName);
        if(ord != null)
        {
            if(doLink)
            {
                m_broker.linkOneToOne(obj, cld, ord, insert);
            }
            else
            {
                m_broker.unlinkFK(obj, cld, ord);
                // in 1:1 relation we have to set relation to null
                ord.getPersistentField().set(obj, null);
            }
            match = true;
        }
        else
        {
            CollectionDescriptor cod = cld.getCollectionDescriptorByName(attributeName);
            if(cod != null)
            {
                if(doLink)
                {
                    if(cod.isMtoNRelation())
                    {
                        m_broker.linkMtoN(obj, cod, insert);
                    }
                    else
                    {
                        m_broker.linkOneToMany(obj, cod, insert);
                    }
                }
                else
                {
                    m_broker.unlinkXtoN(obj, cod);
                }
                match = true;
            }
        }
        return match;
    }

    /**
     * Answer the Iterator for Collection or Array.
     * @param collectionOrArray a none null object of type {@link java.util.Collection},
     * Array or {@link org.apache.ojb.broker.ManageableCollection}.
     * @return Iterator able to handle given collection object
     */
    public static Iterator getCollectionIterator(Object collectionOrArray)
    {
        Iterator colIterator;
        if (collectionOrArray instanceof ManageableCollection)
        {
            colIterator = ((ManageableCollection) collectionOrArray).ojbIterator();
        }
        else if (collectionOrArray instanceof Collection)
        {
            colIterator = ((Collection) collectionOrArray).iterator();
        }
        else if (collectionOrArray.getClass().isArray())
        {
            colIterator = new ArrayIterator(collectionOrArray);
        }
        else
        {
            throw new OJBRuntimeException( "Given object collection of type " + collectionOrArray.getClass()
                + " can not be managed by OJB. Use Array, Collection or ManageableCollection instead!");
        }
        return colIterator;
    }
}
TOP

Related Classes of org.apache.ojb.broker.util.BrokerHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.