com.alkacon.opencms.documentcenter.CmsDocumentList.java Source code

Java tutorial

Introduction

Here is the source code for com.alkacon.opencms.documentcenter.CmsDocumentList.java

Source

/*
 * File   : $Source: /alkacon/cvs/alkacon/com.alkacon.opencms.documentcenter/src/com/alkacon/opencms/documentcenter/CmsDocumentList.java,v $
 * Date   : $Date: 2010/03/19 15:31:13 $
 * Version: $Revision: 1.3 $
 *
 * This file is part of the Alkacon OpenCms Add-On Module Package
 *
 * Copyright (c) 2010 Alkacon Software GmbH (http://www.alkacon.com)
 *
 * The Alkacon OpenCms Add-On Module Package is free software: 
 * you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * The Alkacon OpenCms Add-On Module Package is distributed 
 * in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with the Alkacon OpenCms Add-On Module Package.  
 * If not, see http://www.gnu.org/licenses/.
 *
 * For further information about Alkacon Software GmbH, please see the
 * company website: http://www.alkacon.com.
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org.
 */

package com.alkacon.opencms.documentcenter;

import org.opencms.main.CmsLog;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;

/**
 * Provides methods to create a special list of CmsDocument objects regarding language and attachment functionality.<p>
 * 
 * After adding all documents to the list, the {@link #closeList()} method has to be called once
 * before working with the list contents, e.g. before sorting the list or iterating it.<p>
 * 
 * @author  Andreas Zahner 
 * 
 * @version $Revision: 1.3 $ 
 * 
 * @since 6.2.0 
 */
public class CmsDocumentList extends AbstractList {

    /** The log object for this class. */
    private static final Log LOG = CmsLog.getLog(CmsDocumentList.class);

    private List m_attachments;

    private CmsDocument[] m_documents;

    private boolean m_onlyVersions;

    private int m_size;

    private boolean m_useAttachments;

    private boolean m_useLanguages;

    private boolean m_useTypes;

    private String m_defaultType;

    /**
     * Creates an empty document list with an initial capacity of 16 items.<p>
     */
    public CmsDocumentList() {

        this(16);
    }

    /**
     * Creates an empty document list with the flags to use language versions and attachments, to show only versions and 
     * the given initial capacity.<p>
     * 
     * @param useTypes the flag if different types of a document should be considered
     * @param defaultType if list uses types, the default type is specified here
     * @param useAttachments the flag if attachments of a document should be conbsidered
     * @param useLanguages the flag if language versions of a document should be considered
     * @param onlyVersions the flag if only versions of a specific document should be added to the list
     * @param initialCapacity the initial capacity of the document list
     */
    public CmsDocumentList(boolean useTypes, String defaultType, boolean useAttachments, boolean useLanguages,
            boolean onlyVersions, int initialCapacity) {

        m_documents = new CmsDocument[initialCapacity];
        m_size = 0;
        m_attachments = new ArrayList();
        m_useLanguages = useLanguages;
        m_onlyVersions = onlyVersions;
        m_useAttachments = useAttachments;
        m_useTypes = useTypes;
        m_defaultType = defaultType;
    }

    /**
     * Creates an empty document list with the flags to use language versions and attachments, to show only versions and 
     * the given initial capacity.<p>
     * 
     * @param useAttachments the flag is attachments of a document should be conbsidered
     * @param useLanguages the flag if language versions of a document should be considered
     * @param onlyVersions the flag if only versions of a specific document should be added to the list
     * @param initialCapacity the initial capacity of the document list
     */
    public CmsDocumentList(boolean useAttachments, boolean useLanguages, boolean onlyVersions,
            int initialCapacity) {

        this(false, null, useAttachments, useLanguages, onlyVersions, initialCapacity);
    }

    /**
     * Creates an empty document list with the flags to use language versions, to show only versions and the given initial capacity.<p>
     * 
     * @param useLanguages the flag if language versions of a document should be considered
     * @param onlyVersions the flag if only versions of a specific document should be added to the list
     * @param initialCapacity the initial capacity of the document list
     */
    public CmsDocumentList(boolean useLanguages, boolean onlyVersions, int initialCapacity) {

        this(true, useLanguages, onlyVersions, initialCapacity);
    }

    /**
     * Creates an empty document list with the given initial capacity.<p>
     * 
     * @param initialCapacity the initial capacity of the document list
     */
    public CmsDocumentList(int initialCapacity) {

        this(false, false, initialCapacity);
    }

    /**
     * @see java.util.AbstractList#add(int, java.lang.Object)
     */
    public void add(int index, Object element) {

        rangeCheck(index);
        CmsDocument doc = convertDocument(element);
        if (doc.isNullDocument() || checkContainer(doc)) {
            return;
        }

        ensureCapacity(m_size + 1); // Increments modCount!!
        System.arraycopy(m_documents, index, m_documents, index + 1, m_size - index);
        m_documents[index] = doc;
        m_size++;
    }

    /**
     * @see java.util.AbstractList#add(java.lang.Object)
     */
    public boolean add(Object element) {

        CmsDocument doc = convertDocument(element);
        if (doc.isNullDocument() || checkContainer(doc)) {
            return true;
        }

        ensureCapacity(m_size + 1);
        m_documents[m_size++] = doc;
        return true;
    }

    /**
     * @see java.util.Collection#clear()
     */
    public void clear() {

        modCount++;
        for (int i = 0; i < m_size; i++) {
            m_documents[i] = null;
        }
        m_size = 0;
    }

    /**
     * Closes the list after adding all documents to it, this is needed to assign the found attachments to the documents.<p>
     */
    public void closeList() {

        for (int i = 0; i < m_attachments.size(); i++) {
            // loop through all attachments
            CmsDocument att = (CmsDocument) m_attachments.get(i);
            boolean added = false;
            for (int k = 0; k < m_size; k++) {
                // check if the attachment belongs to a document
                if (m_documents[k].isVersionOf(att)) {
                    // found a document for the attachment
                    if (m_documents[k].addAttachment(att)) {
                        added = true;
                        break;
                    }
                }
            }
            if (!added) {
                // found no document for the attachment, add it as separate attachment to the list
                ensureCapacity(m_size + 1);
                m_documents[m_size++] = att;
            }
        }
        // empty the attachment list
        m_attachments = new ArrayList();
    }

    /**
     * @see java.util.Collection#contains(java.lang.Object)
     */
    public boolean contains(Object elem) {

        return indexOf(elem) >= 0;
    }

    /**
     * Increases the capacity of this <tt>CmsDocumentList</tt> instance, if
     * necessary, to ensure  that it can hold at least the number of elements
     * specified by the minimum capacity argument. 
     *
     * @param   minCapacity   the desired minimum capacity.
     */
    public void ensureCapacity(int minCapacity) {

        modCount++;
        int oldCapacity = m_documents.length;
        if (minCapacity > oldCapacity) {
            CmsDocument[] oldData = m_documents;
            int newCapacity = (oldCapacity * 3) / 2 + 1;
            if (newCapacity < minCapacity) {
                newCapacity = minCapacity;
            }
            m_documents = new CmsDocument[newCapacity];
            System.arraycopy(oldData, 0, m_documents, 0, m_size);
        }
    }

    /**
     * @see java.util.AbstractList#get(int)
     */
    public Object get(int index) {

        rangeCheck(index);
        return m_documents[index];
    }

    /**
     * @see java.util.List#indexOf(java.lang.Object)
     */
    public int indexOf(Object elem) {

        if (elem == null) {
            for (int i = 0; i < m_size; i++) {
                if (m_documents[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = 0; i < m_size; i++) {
                if (elem.equals(m_documents[i])) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * @see java.util.AbstractList#remove(int)
     */
    public Object remove(int index) {

        rangeCheck(index);
        modCount++;
        CmsDocument oldValue = m_documents[index];
        int numMoved = m_size - index - 1;
        if (numMoved > 0) {
            System.arraycopy(m_documents, index + 1, m_documents, index, numMoved);
        }
        m_documents[--m_size] = null;
        return oldValue;
    }

    /**
     * @see java.util.AbstractList#set(int, java.lang.Object)
     */
    public Object set(int index, Object element) {

        rangeCheck(index);
        CmsDocument newValue = (CmsDocument) element;
        CmsDocument oldValue = m_documents[index];
        m_documents[index] = newValue;
        return oldValue;
    }

    /**
     * @see java.util.AbstractCollection#size()
     */
    public int size() {

        return m_size;
    }

    /**
     * Checks if the document is added as a subdocument or attachment.<p>
     * 
     * If the document was not merged, it is a new document that has to be added to the list depending on the only versions flag.<p>
     * 
     * @param doc the document to check
     * @return true if the document was added as subdocument, attachment or if the document should not be added, otherwise false
     */
    private boolean checkContainer(CmsDocument doc) {

        boolean docnameWithoutPostfixEquality;
        for (int i = 0; i < m_size; i++) {
            docnameWithoutPostfixEquality = doc.getDocumentNameFullWithoutPostfix()
                    .equals(m_documents[i].getDocumentNameFullWithoutPostfix());
            if (m_documents[i].isVersionOf(doc) || (m_useTypes && docnameWithoutPostfixEquality)) {
                if (m_useTypes) {

                    if ((m_defaultType != null) && (m_defaultType.equals(doc.getPostfix()))) {
                        if (m_documents[i].getTypes().size() > 0) {
                            doc.setTypes(m_documents[i].getTypes());
                        }
                        doc.addType(m_documents[i]);
                        m_documents[i] = doc;
                    } else {
                        m_documents[i].addType(doc);
                    }
                    return true;
                } else if ((m_useAttachments) && (doc.isAttachment()) && (!m_documents[i].isAttachment())) {
                    // store attachment in temporary list to assign later
                    m_attachments.add(doc);
                    return true;
                } else if ((m_useAttachments) && (m_documents[i].isAttachment()) && (!doc.isAttachment())) {
                    if (isOnlyVersions()) {
                        return true;
                    } else {
                        m_attachments.add(m_documents[i]);
                        m_documents[i] = doc;
                        return true;
                    }
                } else if (m_useLanguages) {
                    // merge the document if languages are used
                    m_documents[i] = m_documents[i].mergeDocuments(doc);
                    return true;
                }
            } else if (isOnlyVersions()) {
                // this is no version of a present document, do not add it at all
                return true;
            }
        }
        return false;
    }

    /**
     * Converts an object to a document.<p>
     * 
     * @param element the object to convert
     * @return the document object representation
     */
    private CmsDocument convertDocument(Object element) {

        try {
            return (CmsDocument) element;
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Tried adding wrong object to document list " + e);
            }
        }
        return CmsDocument.getNullDocument();
    }

    /**
     * Returns the flag if only versions of a specific document should be added to the list.<p>
     *
     * @return the flag if only versions of a specific document should be added to the list
     */
    private boolean isOnlyVersions() {

        return m_onlyVersions;
    }

    /**
     * Check if the given index is in range.  If not, throw an appropriate
     * runtime exception.  This method does *not* check if the index is
     * negative: It is always used immediately prior to an array access,
     * which throws an ArrayIndexOutOfBoundsException if index is negative.
     * 
     * @param index the index to check
     */
    private void rangeCheck(int index) {

        if ((index > m_size) || (index < 0)) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + m_size);
        }
    }
}