FileDocCategorySizeDatePackage
EventListImpl.javaAPI DocphoneME MR2 API (J2ME)8617Wed May 02 18:00:28 BST 2007com.sun.kvem.midp.pim

EventListImpl.java

/*
 *   
 *
 * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 only, as published by the Free Software Foundation.
 * 
 * This program 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 version 2 for more details (a copy is
 * included at /legal/license.txt).
 * 
 * You should have received a copy of the GNU General Public License
 * version 2 along with this work; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 or visit www.sun.com if you need additional
 * information or have any questions.
 */

package com.sun.kvem.midp.pim;

import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
import javax.microedition.pim.Event;
import javax.microedition.pim.EventList;
import javax.microedition.pim.PIM;
import javax.microedition.pim.PIMException;
import javax.microedition.pim.RepeatRule;

/**
 * Class EventListImpl implements methods of PIM interface EventList.
 *
 */
class EventListImpl extends AbstractPIMList implements EventList {
    /**
     * Constructs an Event list.
     * @param name label for the Event List
     * @param mode read or write access
     * @param handle handle of the list
     */
    EventListImpl(String name, int mode, Object handle) {
        super(PIM.EVENT_LIST, name, mode, handle);
    }

    /**
     * Creates a new event instance.
     * @return Event handler
     */
    public Event createEvent() {
        return new EventImpl(this);
    }

    /**
     * Gets supported repeat rule fields.
     * @param frequency repeat rule frequency
     * @return array of repeat rule fields
     */
    public int[] getSupportedRepeatRuleFields(int frequency) {
        switch (frequency) {
            case RepeatRule.DAILY:
                return new int[] {
                    RepeatRule.COUNT,
                    RepeatRule.INTERVAL,
                    RepeatRule.END
                };
            case RepeatRule.WEEKLY:
                return new int[] {
                    RepeatRule.COUNT,
                    RepeatRule.INTERVAL,
                    RepeatRule.END,
                    RepeatRule.DAY_IN_WEEK
                };
            case RepeatRule.MONTHLY:
                return new int[] {
                    RepeatRule.COUNT,
                    RepeatRule.INTERVAL,
                    RepeatRule.END,
                    RepeatRule.DAY_IN_WEEK,
                    RepeatRule.WEEK_IN_MONTH,
                    RepeatRule.DAY_IN_MONTH
                };
            case RepeatRule.YEARLY:
                return new int[] {
                    RepeatRule.COUNT,
                    RepeatRule.INTERVAL,
                    RepeatRule.END,
                    RepeatRule.DAY_IN_WEEK,
                    RepeatRule.WEEK_IN_MONTH,
                    RepeatRule.DAY_IN_MONTH,
                    RepeatRule.MONTH_IN_YEAR,
                    RepeatRule.DAY_IN_YEAR
                };
            default:
                throw new IllegalArgumentException("Unsupported frequency: "
                    + frequency);
        }
    }

    /**
     * Creates new event from item template.
     * @param item template with initial data
     * @return Event implementation handler
     */
    public Event importEvent(Event item) {
        return new EventImpl(this, item);
    }

    /**
     * Gets enumeration of Event items.
     * @param searchType search rule
     * @param startDate beginning of range
     * @param endDate end of range
     * @param initialEventOnly first event only
     * @return Enumeration of matching events
     */
    public Enumeration items(int searchType,
        long startDate,
        long endDate,
        boolean initialEventOnly) throws PIMException {

        switch (searchType) {
            case ENDING:
            case OCCURRING:
            case STARTING:
                break;
            default:
                throw new IllegalArgumentException(
                    "Invalid search type: " + searchType);
        }
        if (startDate > endDate) {
            throw new IllegalArgumentException(
                "Start date must be earlier than end date");
        }
        Vector selectedItems = new Vector();
        Vector itemKeys = new Vector();
        for (Enumeration e = items(); e.hasMoreElements(); ) {
            Event event = (Event) e.nextElement();
            long eventStart = 0l;
            long eventEnd = 0l;
            // a START or END field may have at most one value
            if (event.countValues(Event.START) != 0) {
                eventStart = event.getDate(Event.START, 0);
                if (event.countValues(Event.END) != 0) {
                    eventEnd = event.getDate(Event.END, 0);
                } else {
                    // see specification of Event.END field: if
                    // END is not specified but START is, the event only
                    // occurs at the START time.
                    eventEnd = eventStart;
                }
            } else if (event.countValues(Event.END) != 0) {
                // see specification of Event.START field: if
                // START is not specified but END is, the event only
                // occurs at the END time.
                eventEnd = event.getDate(Event.END, 0);
                eventStart = eventEnd;
            } else {
                // no start or end date
                continue;
            }
            long duration = Math.max(0, eventEnd - eventStart);
            RepeatRule repeatRule = event.getRepeat();
            boolean includeItem = false;
            if (repeatRule != null) {
                // check all occurrences of the event
                long timeSlot = eventEnd - eventStart;
                Enumeration dates =
                    repeatRule.dates(eventStart,
                        Math.max(startDate - duration, 0), endDate);
                while (dates.hasMoreElements()) {
                    Date date = (Date) dates.nextElement();
                    eventStart = date.getTime();
                    eventEnd = eventStart + timeSlot;
                    if (eventStart > endDate) {
                        // no point continuing
                        break;
                    }
                    includeItem =
                        checkRange(searchType,
                            startDate, endDate,
                            eventStart, eventEnd);
                    if (includeItem) {
                        break;
                    }
                    if (initialEventOnly) {
                        break;
                    }
                }
            } else {
                // check the base occurrence
                includeItem =
                    checkRange(searchType,
                        startDate, endDate,
                        eventStart, eventEnd);
            }
            if (includeItem) {
                KeySortUtility.store(itemKeys, selectedItems,
				     eventStart, event);
            }
        }
        return selectedItems.elements();
    }

    /**
     * Verifies search range.
     * @param searchType search mode
     * @param startDate beginning of range
     * @param endDate end of range
     * @param eventStart event start date
     * @param eventEnd event end date
     * @return <code>true</code> if event is within range
     */
    private boolean checkRange(int searchType,
        long startDate, long endDate,
        long eventStart, long eventEnd) {
        switch (searchType) {
            case EventList.STARTING:
                return (eventStart >= startDate && eventStart <= endDate);
            case EventList.ENDING:
                return (eventEnd >= startDate && eventEnd <= endDate);
            case EventList.OCCURRING:
                return (eventStart <= endDate && eventEnd >= startDate);
            default:
                return false;
        }
    }

    /**
     * Removes event.
     * @param item to remove
     * @throws PIMException if item not found
     */
    public void removeEvent(Event item) throws PIMException {
        removeItem(item);
    }

}