rabbit.data.internal.xml.access.AbstractAccessor.java Source code

Java tutorial

Introduction

Here is the source code for rabbit.data.internal.xml.access.AbstractAccessor.java

Source

/*
 * Copyright 2010 The Rabbit Eclipse Plug-in Project
 * 
 * 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.
 */
package rabbit.data.internal.xml.access;

import static rabbit.data.internal.xml.DatatypeUtil.toLocalDate;
import static rabbit.data.internal.xml.DatatypeUtil.toXmlDate;

import rabbit.data.access.IAccessor;
import rabbit.data.access.model.WorkspaceStorage;
import rabbit.data.internal.xml.IDataStore;
import rabbit.data.internal.xml.XmlPlugin;
import rabbit.data.internal.xml.schema.events.EventGroupType;
import rabbit.data.internal.xml.schema.events.EventListType;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;

import org.eclipse.core.runtime.IPath;
import org.joda.time.LocalDate;

import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.xml.datatype.XMLGregorianCalendar;

/**
 * Abstract class provides default behaviors, this class is designed
 * specifically for the schema.
 * 
 * @param <T> The result type.
 * @param <E> The XML type.
 * @param <S> The XML category type.
 */
public abstract class AbstractAccessor<T, E, S extends EventGroupType> implements IAccessor<T> {

    private final IDataStore store;

    /**
     * Constructor.
     * 
     * @param store The data store to get the data from.
     * @throws NullPointerException If any arguments are null.
     */
    protected AbstractAccessor(IDataStore store) {
        this.store = checkNotNull(store);
    }

    @Override
    public final Collection<T> getData(LocalDate start, LocalDate end) {
        return filter(getXmlData(checkNotNull(start, "start date is null"), checkNotNull(end, "end date is null")));
    }

    /**
     * Creates a data node.
     * 
     * @param cal The date of the XML type.
     * @param type The XML type.
     * @return A data node, or null if one cannot be created.
     * @throws Exception If a data node cannot be created.
     */
    protected abstract T createDataNode(LocalDate cal, WorkspaceStorage ws, E type) throws Exception;

    /**
     * Gets the collection of categories from the given parameter.
     * 
     * @param doc The root of a document type.
     * @return A collection of categories.
     */
    protected abstract Collection<S> getCategories(EventListType doc);

    /**
     * Gets the data store.
     * 
     * @return The data store.
     */
    protected final IDataStore getDataStore() {
        return store;
    }

    /**
     * Gets a collection of types from the given category.
     * 
     * @param category The category.
     * @return A collection of objects.
     */
    protected abstract Collection<E> getElements(S category);

    /**
     * Filters the given data.
     * 
     * @param data The raw data between the two dates of
     *          {@link #getData(LocalDate, LocalDate)}.
     * @return The filtered data.
     */
    private Collection<T> filter(Multimap<WorkspaceStorage, S> data) {
        List<T> result = Lists.newLinkedList();
        for (Map.Entry<WorkspaceStorage, S> entry : data.entries()) {
            LocalDate date = toLocalDate(entry.getValue().getDate());
            for (E element : getElements(entry.getValue())) {
                T node = null;
                try {
                    node = createDataNode(date, entry.getKey(), element);
                } catch (Exception e) {
                    node = null;
                }
                if (node != null) {
                    result.add(node);
                }
            }
        }
        return result;
    }

    /**
     * Gets the data from the XML files.
     * 
     * @param start The start date of the data to get.
     * @param end The end date of the data to get.
     * @return The data between the dates, inclusive.
     */
    private Multimap<WorkspaceStorage, S> getXmlData(LocalDate start, LocalDate end) {

        XMLGregorianCalendar startDate = toXmlDate(start);
        XMLGregorianCalendar endDate = toXmlDate(end);
        XmlPlugin plugin = XmlPlugin.getDefault();

        IPath[] storagePaths = plugin.getStoragePaths();
        Multimap<WorkspaceStorage, S> data = LinkedListMultimap.create(storagePaths.length);
        Multimap<WorkspaceStorage, File> files = LinkedListMultimap.create(storagePaths.length);

        for (IPath storagePath : storagePaths) {
            List<File> fileList = getDataStore().getDataFiles(start, end, storagePath);
            IPath workspacePath = plugin.getWorkspacePath(storagePath);
            files.putAll(new WorkspaceStorage(storagePath, workspacePath), fileList);
        }

        for (Map.Entry<WorkspaceStorage, File> entry : files.entries()) {
            for (S list : getCategories(getDataStore().read(entry.getValue()))) {

                XMLGregorianCalendar date = list.getDate();
                if (date == null) {
                    continue; // Ignore invalid data.
                }
                if (startDate.compare(date) <= 0 && date.compare(endDate) <= 0) {
                    data.put(entry.getKey(), list);
                }
            }
        }
        return data;
    }

}