All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.primefaces.model.timeline.TimelineModel Maven / Gradle / Ivy

There is a newer version: 14.0.0-RC3
Show newest version
/*
 * Copyright 2009-2016 PrimeTek.
 *
 * 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 org.primefaces.model.timeline;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.TreeSet;
import org.primefaces.component.timeline.TimelineUpdater;
import org.primefaces.event.timeline.TimelineEventComparator;

public class TimelineModel implements Serializable {

    private static final long serialVersionUID = 20130316L;

    /**
     * list of events
     */
    private List events;

    /**
     * list of groups
     */
    private List groups;

    public TimelineModel() {
        events = new ArrayList();
    }

    public TimelineModel(List events) {
        this.events = new ArrayList();

        if (events != null && !events.isEmpty()) {
            for (TimelineEvent event : events) {
                add(event);
            }
        }
    }

    public TimelineModel(List events, List groups) {
        this(events);
        this.groups = groups;
    }

    /**
     * Adds a given event to the model without UI update.
     *
     * @param event event to be added
     */
    public void add(TimelineEvent event) {
        events.add(event);
    }

    /**
     * Adds a given group to the model.
     *
     * @param group group to be added
     */
    public void addGroup(TimelineGroup group) {
        if (groups == null) {
            groups = new ArrayList();
        }

        groups.add(group);
    }

    /**
     * Adds a given event to the model with UI update.
     *
     * @param event           event to be added
     * @param timelineUpdater TimelineUpdater instance to add the event in UI
     */
    public void add(TimelineEvent event, TimelineUpdater timelineUpdater) {
        events.add(event);

        if (timelineUpdater != null) {
            // update UI
            timelineUpdater.add(event);
        }
    }

    /**
     * Adds all given event to the model without UI update.
     *
     * @param events collection of events to be added
     */
    public void addAll(Collection events) {
        addAll(events, null);
    }

    /**
     * Adds all given groups to the model.
     *
     * @param groups collection of groups to be added
     */
    public void addAllGroups(Collection groups) {
        if (groups == null) {
            groups = new ArrayList();
        }

        groups.addAll(groups);
    }

    /**
     * Adds all given events to the model with UI update.
     *
     * @param events          collection of events to be added
     * @param timelineUpdater TimelineUpdater instance to add the events in UI
     */
    public void addAll(Collection events, TimelineUpdater timelineUpdater) {
        if (events != null && !events.isEmpty()) {
            for (TimelineEvent event : events) {
                add(event, timelineUpdater);
            }
        }
    }

    /**
     * Updates a given event in the model without UI update.
     *
     * @param event event to be updated
     */
    public void update(TimelineEvent event) {
        update(event, null);
    }

    /**
     * Updates a given event in the model with UI update.
     *
     * @param event           event to be added
     * @param timelineUpdater TimelineUpdater instance to update the event in UI
     */
    public void update(TimelineEvent event, TimelineUpdater timelineUpdater) {
        int index = getIndex(event);
        if (index >= 0) {
            events.set(index, event);

            if (timelineUpdater != null) {
                // update UI
                timelineUpdater.update(event, index);
            }
        }
    }

    /**
     * Updates all given events in the model without UI update.
     *
     * @param events collection of events to be updated
     */
    public void updateAll(Collection events) {
        updateAll(events, null);
    }

    /**
     * Updates all given events in the model with UI update.
     *
     * @param events          collection of events to be updated
     * @param timelineUpdater TimelineUpdater instance to update the events in UI
     */
    public void updateAll(Collection events, TimelineUpdater timelineUpdater) {
        if (events != null && !events.isEmpty()) {
            for (TimelineEvent event : events) {
                update(event, timelineUpdater);
            }
        }
    }

    /**
     * Deletes a given event in the model without UI update.
     *
     * @param event event to be deleted
     */
    public void delete(TimelineEvent event) {
        delete(event, null);
    }

    /**
     * Deletes a given event in the model with UI update.
     *
     * @param event           event to be deleted
     * @param timelineUpdater TimelineUpdater instance to delete the event in UI
     */
    public void delete(TimelineEvent event, TimelineUpdater timelineUpdater) {
        int index = getIndex(event);
        if (index >= 0) {
            events.remove(event);

            if (timelineUpdater != null) {
                // update UI
                timelineUpdater.delete(index);
            }
        }
    }

    /**
     * Deletes all given events in the model without UI update.
     *
     * @param events collection of events to be deleted
     */
    public void deleteAll(Collection events) {
        deleteAll(events, null);
    }

    /**
     * Deletes all given events in the model with UI update.
     *
     * @param events          collection of events to be deleted
     * @param timelineUpdater TimelineUpdater instance to delete the events in UI
     */
    public void deleteAll(Collection events, TimelineUpdater timelineUpdater) {
        if (events != null && !events.isEmpty()) {
            for (TimelineEvent event : events) {
                delete(event, timelineUpdater);
            }
        }
    }

    /**
     * Selects a given event in UI visually. To unselect all events, pass a null as event.
     *
     * @param event           event to be selected
     * @param timelineUpdater TimelineUpdater instance to select the event in UI
     */
    public void select(TimelineEvent event, TimelineUpdater timelineUpdater) {
        int index = getIndex(event);

        if (timelineUpdater != null) {
            // update UI
            timelineUpdater.select(index);
        }
    }

    /**
     * Clears the timeline model without UI update (no events are available after that)
     */
    public void clear() {
        events.clear();
    }

    /**
     * Clears the timeline model with UI update (no events are available after that)
     *
     * @param timelineUpdater TimelineUpdater instance to clear the timeline in UI
     */
    public void clear(TimelineUpdater timelineUpdater) {
        events.clear();

        if (timelineUpdater != null) {
            // update UI
            timelineUpdater.clear();
        }
    }

    /**
     * Gets all overlapped events to the given one. The given and overlapped events belong to the same group. Events are ordered
     * by their start dates - first events with more recent start dates and then events with older start dates. If start dates are
     * equal, events will be ordered by their end dates. In this case, if an event has a null end date, it is ordered before the
     * event with a not null end date.
     *
     * @param event given event
     * @return TreeSet ordered overlapped events or null if no overlapping exist
     */
    public TreeSet getOverlappedEvents(TimelineEvent event) {
        if (event == null) {
            return null;
        }

        List overlappedEvents = null;
        for (TimelineEvent e : events) {
            if (e.equals(event)) {
                // given event should not be included
                continue;
            }

            if (event.getGroup() == null && e.getGroup() != null
                    || (event.getGroup() != null && !event.getGroup().equals(e.getGroup()))) {
                // ignore different groups
                continue;
            }

            if (isOverlapping(event, e)) {
                if (overlappedEvents == null) {
                    overlappedEvents = new ArrayList();
                }

                overlappedEvents.add(e);
            }
        }

        if (overlappedEvents == null) {
            return null;
        }

        // order overlapped events according to their start / end dates
        TreeSet orderedOverlappedEvents = new TreeSet(new TimelineEventComparator());
        orderedOverlappedEvents.addAll(overlappedEvents);

        return orderedOverlappedEvents;
    }

    /**
     * Merge the given one event with the given collection of events without UI update. Only events within one group can be
     * merged. Note: after merging, the merged event will get the same properties as the given one event except start and end
     * dates.
     *
     * @param event  given event to be merged with collection of events
     * @param events collection of events
     * @return TimelineEvent result event after merging
     * @throws IllegalStateException thrown if not all events are within the same group
     */
    public TimelineEvent merge(TimelineEvent event, Collection events) {
        return merge(event, events, null);
    }

    /**
     * Merge the given one event with the given collection of events with UI update. Only events within one group can be merged.
     * Note: after merging, the merged event will get the same properties as the given one event except start and end dates.
     *
     * @param event           given event to be merged with collection of events
     * @param events          collection of events
     * @param timelineUpdater TimelineUpdater instance to update the merged events in UI
     * @return TimelineEvent result event after merging
     * @throws IllegalStateException thrown if not all events are within the same group
     */
    public TimelineEvent merge(TimelineEvent event, Collection events, TimelineUpdater timelineUpdater) {
        if (event == null) {
            // nothing to merge
            return null;
        }

        if (events == null || events.isEmpty()) {
            // nothing to merge
            return event;
        }

        // check whether all events within the same group
        String group = event.getGroup();
        for (TimelineEvent e : events) {
            if ((group == null && e.getGroup() != null) || (group != null && !group.equals(e.getGroup()))) {
                throw new IllegalStateException("Events to be merged may be only belong to one and the same group!");
            }
        }

        // order events according to their start / end dates
        TreeSet orderedEvents = new TreeSet(new TimelineEventComparator());
        orderedEvents.add(event);
        orderedEvents.addAll(events);

        // find the largest end date
        Date endDate = null;
        for (TimelineEvent e : orderedEvents) {
            if (endDate == null && e.getEndDate() != null) {
                endDate = e.getEndDate();
            } else if (endDate != null && e.getEndDate() != null && endDate.before(e.getEndDate())) {
                endDate = e.getEndDate();
            }
        }

        TimelineEvent mergedEvent =
                new TimelineEvent(event.getData(), orderedEvents.first().getStartDate(), endDate, event.isEditable(),
                        event.getGroup(), event.getStyleClass());

        // merge...
        deleteAll(events, timelineUpdater);
        update(mergedEvent, timelineUpdater);

        return mergedEvent;
    }

    /**
     * Gets all events in this model
     *
     * @return List list of events
     */
    public List getEvents() {
        return events;
    }

    /**
     * Sets events into this model
     *
     * @param events List list of events
     */
    public void setEvents(List events) {
        this.events = events;
    }

    /**
     * Gets all groups in this model
     *
     * @return List list of groups
     */
    public List getGroups() {
        return groups;
    }

    /**
     * Sets groups into this model
     *
     * @param groups List list of groups
     */
    public void setGroups(List groups) {
        this.groups = groups;
    }

    /**
     * Gets event by its index as String
     *
     * @param index index
     * @return TimelineEvent found event or null
     */
    public TimelineEvent getEvent(String index) {
        return getEvent(index != null ? Integer.valueOf(index) : -1);
    }

    /**
     * Gets event by its index as int
     *
     * @param index index
     * @return TimelineEvent found event or null
     */
    public TimelineEvent getEvent(int index) {
        if (index < 0) {
            return null;
        }

        return events.get(index);
    }

    /**
     * Gets index of the given timeline event
     *
     * @param event given event
     * @return int positive index or -1 if the given event is not available in the timeline
     */
    public int getIndex(TimelineEvent event) {
        int index = -1;

        if (event != null) {
            for (int i = 0; i < events.size(); i++) {
                if (events.get(i).equals(event)) {
                    index = i;

                    break;
                }
            }
        }

        return index;
    }

    private boolean isOverlapping(TimelineEvent event1, TimelineEvent event2) {
        if (event1.getEndDate() == null && event2.getEndDate() == null) {
            return event1.getStartDate().equals(event2.getStartDate());
        } else if (event1.getEndDate() == null && event2.getEndDate() != null) {
            return (event1.getStartDate().equals(event2.getStartDate()) || event1.getStartDate().equals(event2.getEndDate())
                    || (event1.getStartDate().after(event2.getStartDate()) && event1.getStartDate().before(event2.getEndDate())));
        } else if (event1.getEndDate() != null && event2.getEndDate() == null) {
            return (event2.getStartDate().equals(event1.getStartDate()) || event2.getStartDate().equals(event1.getEndDate())
                    || (event2.getStartDate().after(event1.getStartDate()) && event2.getStartDate().before(event1.getEndDate())));
        } else {
            // check with ODER if
            // 1. start date of the event 1 is within the event 2
            // 2. end date of the event 1 is within the event 2
            // 3. event 2 is completely strong within the event 1
            return (event1.getStartDate().equals(event2.getStartDate()) || event1.getStartDate().equals(event2.getEndDate())
                    || (event1.getStartDate().after(event2.getStartDate()) && event1.getStartDate().before(event2.getEndDate())))
                    ||
                    (event1.getEndDate().equals(event2.getStartDate()) || event1.getEndDate().equals(event2.getEndDate())
                            || (event1.getEndDate().after(event2.getStartDate()) && event1.getEndDate().before(event2.getEndDate())))
                    || (event1.getStartDate().before(event2.getStartDate()) && event1.getEndDate().after(event2.getEndDate()));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy