org.apache.ojb.broker.metadata.CollectionDescriptor.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ojb.broker.metadata.CollectionDescriptor.java

Source

package org.apache.ojb.broker.metadata;

/* Copyright 2002-2005 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.Vector;

import org.apache.commons.lang.SystemUtils;
import org.apache.ojb.broker.PersistenceBrokerException;
import org.apache.ojb.broker.accesslayer.QueryCustomizer;

/**
 * mapping Description for member fields that are Collections
 * <br>
 * Note: Be careful when use references of this class or caching instances of this class,
 * because instances could become invalid (see {@link MetadataManager}).
 *
 * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
 * @version $Id: CollectionDescriptor.java,v 1.30.2.1 2005/12/21 22:26:10 tomdz Exp $
 */
public class CollectionDescriptor extends ObjectReferenceDescriptor {
    private static final long serialVersionUID = -8570280662286424937L;

    /**
     * Represents the type of the collection, if set to null,
     * a java.util.Vector will be used.
     * If set to a valid collection type it will be used to build typed collections.
     */
    private Class collectionClass = null;
    /**
     * the Collection of orderby Fields
     */
    private Collection m_orderby = new ArrayList();
    /**
     * For m:n related Classes this is the indirection table.
     */
    private String indirectionTable = null;
    private Vector fksToItemClass = null;
    private Vector fksToThisClass = null;
    private String[] fksToItemClassAry;
    private String[] fksToThisClassAry;
    private QueryCustomizer m_queryCustomizer;
    private Boolean m_hasProxyItems;

    public CollectionDescriptor(ClassDescriptor descriptor) {
        super(descriptor);
    }

    public String[] getFksToThisClass() {
        if (fksToThisClassAry == null) {
            fksToThisClassAry = (String[]) fksToThisClass.toArray(new String[fksToThisClass.size()]);
        }
        return fksToThisClassAry;
    }

    public void setFksToThisClass(Vector fksToThisClass) {
        this.fksToThisClass = fksToThisClass;
        fksToThisClassAry = null;
    }

    /**
     * add a FK column pointing to This Class
     */
    public void addFkToThisClass(String column) {
        if (fksToThisClass == null) {
            fksToThisClass = new Vector();
        }
        fksToThisClass.add(column);
        fksToThisClassAry = null;
    }

    /**
     * add a FK column pointing to the item Class
     */
    public void addFkToItemClass(String column) {
        if (fksToItemClass == null) {
            fksToItemClass = new Vector();
        }
        fksToItemClass.add(column);
        fksToItemClassAry = null;
    }

    /**
     * returns the type of the collection.
     * @return java.lang.Class
     */
    public Class getCollectionClass() {
        return collectionClass;
    }

    /**
     * set the type of the collection
     * @param c the collection type
     */
    public void setCollectionClass(Class c) {
        collectionClass = c;
    }

    /**
     * Retrieve the classname of the collection.
     */
    public String getCollectionClassName() {
        return collectionClass != null ? collectionClass.getName() : null;
    }

    public String getIndirectionTable() {
        return indirectionTable;
    }

    public void setIndirectionTable(String indirectionTable) {
        this.indirectionTable = indirectionTable;
    }

    public String[] getFksToItemClass() {
        if (fksToItemClassAry == null) {
            fksToItemClassAry = (String[]) fksToItemClass.toArray(new String[fksToItemClass.size()]);
        }
        return fksToItemClassAry;
    }

    public void setFksToItemClass(Vector fksToItemClass) {
        this.fksToItemClass = fksToItemClass;
        fksToItemClassAry = null;
    }

    public boolean isMtoNRelation() {
        return (indirectionTable != null);
    }

    /**
     * Adds a field for orderBy
     * @param  fieldName    The field name to be used
     * @param  sortAscending    true for ASCENDING, false for DESCENDING
     */
    public void addOrderBy(String fieldName, boolean sortAscending) {
        if (fieldName != null) {
            m_orderby.add(new FieldHelper(fieldName, sortAscending));
        }
    }

    /**
     * Returns the orderby Collection of Fields.
     * @return Collection
     */
    public Collection getOrderBy() {
        return m_orderby;
    }

    protected int getCascadeDeleteValue(String cascade) {
        if (cascade.equalsIgnoreCase("false") && isMtoNRelation()) {
            /*
            "old" implementation does always delete entries in indirection table for
            m:n relations. For 1:n relations referenced objects are not touched.
            */
            return CASCADE_LINK;
        }
        return super.getCascadeDeleteValue(cascade);
    }

    /*
     * @see XmlCapable#toXML()
     */
    public String toXML() {
        RepositoryTags tags = RepositoryTags.getInstance();
        String eol = SystemUtils.LINE_SEPARATOR;

        // write opening tag
        String result = "      " + tags.getOpeningTagNonClosingById(COLLECTION_DESCRIPTOR) + eol;

        // write attributes
        // name
        result += "        " + tags.getAttribute(FIELD_NAME, this.getAttributeName()) + eol;

        // collection class is optional
        if (getCollectionClassName() != null) {
            result += "        " + tags.getAttribute(COLLECTION_CLASS, this.getCollectionClassName()) + eol;
        }

        // element-class-ref
        result += "        " + tags.getAttribute(ITEMS_CLASS, this.getItemClassName()) + eol;

        // indirection-table is optional
        if (isMtoNRelation()) {
            result += "        " + tags.getAttribute(INDIRECTION_TABLE, getIndirectionTable()) + eol;
        }

        // proxyReference is optional, disabled by default
        if (isLazy()) {
            result += "        " + tags.getAttribute(PROXY_REFERENCE, "true") + eol;
            result += "        " + tags.getAttribute(PROXY_PREFETCHING_LIMIT, "" + this.getProxyPrefetchingLimit())
                    + eol;
        }

        //reference refresh is optional, disabled by default
        if (isRefresh()) {
            result += "        " + tags.getAttribute(REFRESH, "true") + eol;
        }

        //auto retrieve
        result += "        " + tags.getAttribute(AUTO_RETRIEVE, "" + getCascadeRetrieve()) + eol;

        //auto update
        result += "        " + tags.getAttribute(AUTO_UPDATE, getCascadeAsString(getCascadingStore())) + eol;

        //auto delete
        result += "        " + tags.getAttribute(AUTO_DELETE, getCascadeAsString(getCascadingDelete())) + eol;

        //otm-dependent is optional, disabled by default
        if (getOtmDependent()) {
            result += "        " + tags.getAttribute(OTM_DEPENDENT, "true") + eol;
        }

        // close opening tag
        result += "      >" + eol;

        // write elements
        // inverse fk elements
        for (int i = 0; i < getForeignKeyFields().size(); i++) {
            Object obj = getForeignKeyFields().get(i);
            if (obj instanceof Integer) {
                String fkId = obj.toString();
                result += "        " + tags.getOpeningTagNonClosingById(INVERSE_FK) + " ";
                result += tags.getAttribute(FIELD_ID_REF, fkId) + "/>" + eol;
            } else {
                String fk = (String) obj;
                result += "        " + tags.getOpeningTagNonClosingById(INVERSE_FK) + " ";
                result += tags.getAttribute(FIELD_REF, fk) + "/>" + eol;
            }
        }

        // write optional M:N elements
        // m:n relationship settings, optional
        if (isMtoNRelation()) {
            // foreign keys to this class
            for (int i = 0; i < getFksToThisClass().length; i++) {
                String fkId = getFksToThisClass()[i];
                result += "        " + tags.getOpeningTagNonClosingById(FK_POINTING_TO_THIS_CLASS) + " ";
                result += tags.getAttribute(COLUMN_NAME, fkId) + "/>" + eol;
            }

            // foreign keys to item class
            for (int i = 0; i < getFksToItemClass().length; i++) {
                String fkId = getFksToItemClass()[i];
                result += "        " + tags.getOpeningTagNonClosingById(FK_POINTING_TO_ITEMS_CLASS) + " ";
                result += tags.getAttribute(COLUMN_NAME, fkId) + "/>" + eol;
            }
        }

        // closing tag
        result += "      " + tags.getClosingTagById(COLLECTION_DESCRIPTOR) + eol;
        return result;
    }

    /**
     * @return QueryCustomizer
     */
    public QueryCustomizer getQueryCustomizer() {
        return m_queryCustomizer;
    }

    /**
     * Sets the queryCustomizer.
     * @param queryCustomizer The queryCustomizer to set
     */
    public void setQueryCustomizer(QueryCustomizer queryCustomizer) {
        m_queryCustomizer = queryCustomizer;
    }

    public boolean hasProxyItems() throws PersistenceBrokerException {
        if (m_hasProxyItems == null) {
            DescriptorRepository repo = getClassDescriptor().getRepository();
            ClassDescriptor cld = repo.getDescriptorFor(getItemClass());
            if (cld.getProxyClass() != null) {
                m_hasProxyItems = Boolean.TRUE;
            } else {
                Collection extents = cld.getExtentClasses();
                m_hasProxyItems = Boolean.FALSE;
                for (Iterator it = extents.iterator(); it.hasNext();) {
                    Class ext = (Class) it.next();
                    ClassDescriptor cldExt = repo.getDescriptorFor(ext);
                    if (cldExt.getProxyClass() != null) {
                        m_hasProxyItems = Boolean.TRUE;
                        break;
                    }
                }
            }
        }

        return (m_hasProxyItems.booleanValue());
    }
}