Skip to content

Commit

Permalink
Use standard collections when period normalisation,etc. is not required
Browse files Browse the repository at this point in the history
  • Loading branch information
benfortuna committed Apr 26, 2019
1 parent 35b293b commit de6610c
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 53 deletions.
11 changes: 6 additions & 5 deletions src/main/java/net/fortuna/ical4j/filter/PeriodRule.java
Expand Up @@ -33,8 +33,9 @@

import net.fortuna.ical4j.model.Component;
import net.fortuna.ical4j.model.Period;
import net.fortuna.ical4j.model.PeriodList;

import java.time.temporal.Temporal;
import java.util.List;
import java.util.function.Predicate;

/**
Expand All @@ -45,15 +46,15 @@
* A rule that matches any component that occurs in the specified time period.
* @author Ben Fortuna
*/
public class PeriodRule<T extends Component> implements Predicate<T> {
public class PeriodRule<C extends Component, T extends Temporal> implements Predicate<C> {

private Period period;
private Period<T> period;

/**
* Constructs a new instance using the specified period.
* @param period a period instance to match on
*/
public PeriodRule(final Period period) {
public PeriodRule(final Period<T> period) {
this.period = period;
}

Expand All @@ -80,7 +81,7 @@ public final boolean test(final Component component) {
*/

// try {
final PeriodList recurrenceSet = component.calculateRecurrenceSet(period);
final List<Period<T>> recurrenceSet = component.calculateRecurrenceSet(period);
return (!recurrenceSet.isEmpty());
// }
// catch (ValidationException ve) {
Expand Down
53 changes: 22 additions & 31 deletions src/main/java/net/fortuna/ical4j/model/Component.java
Expand Up @@ -44,7 +44,7 @@
import java.text.ParseException;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAmount;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -288,32 +288,22 @@ public Component copy() throws ParseException, IOException,
* @param period a range to calculate recurrences for
* @return a list of periods
*/
public final PeriodList calculateRecurrenceSet(final Period period) {
public final <T extends Temporal> List<Period<T>> calculateRecurrenceSet(final Period<T> period) {

// validate();

final PeriodList recurrenceSet = new PeriodList();
final Set<Period<T>> recurrenceSet = new TreeSet<>();

final DtStart start = getProperty(Property.DTSTART);
DateProperty end = getProperty(Property.DTEND);
final DtStart<T> start = getProperty(Property.DTSTART);
DateProperty<T> end = getProperty(Property.DTEND);
if (end == null) {
end = getProperty(Property.DUE);
}
Duration duration = getProperty(Property.DURATION);

// if no start date specified return empty list..
if (start == null) {
return recurrenceSet;
}

final Value startValue = start.getParameter(Parameter.VALUE);

// initialise timezone..
// if (startValue == null || Value.DATE_TIME.equals(startValue)) {
if (start.isUtc()) {
recurrenceSet.setUtc(true);
} else if (start.getDate() instanceof DateTime) {
recurrenceSet.setTimeZone(((DateTime) start.getDate()).getTimeZone());
return Collections.emptyList();
}

// if an explicit event duration is not specified, derive a value for recurring
Expand All @@ -329,34 +319,35 @@ public final PeriodList calculateRecurrenceSet(final Period period) {
}

// add recurrence dates..
List<RDate> rDates = getProperties(Property.RDATE);
List<RDate<T>> rDates = getProperties(Property.RDATE);
recurrenceSet.addAll(rDates.stream().filter(p -> p.getParameter(Parameter.VALUE) == Value.PERIOD)
.map(RDate::getPeriods).flatMap(List::stream).filter(rdatePeriod -> period.intersects(rdatePeriod))
.map(RDate::getPeriods).map(PeriodList<T>::getPeriods).flatMap(Set::stream).filter(period::intersects)
.collect(Collectors.toList()));

recurrenceSet.addAll(rDates.stream().filter(p -> p.getParameter(Parameter.VALUE) == Value.DATE_TIME)
.map(DateListProperty::getDates).flatMap(List::stream).filter(date -> period.includes(date))
.map(rdateTime -> new Period(rdateTime, rDuration)).collect(Collectors.toList()));
List<Period<T>> calculated = rDates.stream().filter(p -> p.getParameter(Parameter.VALUE) == Value.DATE_TIME)
.map(DateListProperty::getDates).map(DateList::getDates).flatMap(List<T>::stream).filter(period::includes)
.map(rdateTime -> new Period<T>(rdateTime, rDuration)).collect(Collectors.toList());
recurrenceSet.addAll(calculated);

recurrenceSet.addAll(rDates.stream().filter(p -> p.getParameter(Parameter.VALUE) == Value.DATE)
.map(DateListProperty::getDates).flatMap(List::stream).filter(date -> period.includes(date))
.map(rdateDate -> new Period(rdateDate, rDuration)).collect(Collectors.toList()));
.map(DateListProperty::getDates).map(DateList::getDates).flatMap(List<T>::stream).filter(period::includes)
.map(rdateDate -> new Period<T>(rdateDate, rDuration)).collect(Collectors.toList()));

// allow for recurrence rules that start prior to the specified period
// but still intersect with it..
final Temporal startMinusDuration = period.getStart().minus(rDuration);
final T startMinusDuration = (T) period.getStart().minus(rDuration);

// add recurrence rules..
List<RRule> rRules = getProperties(Property.RRULE);
if (!rRules.isEmpty()) {
recurrenceSet.addAll(rRules.stream().map(r -> r.getRecur().getDates(start.getDate(),
startMinusDuration, period.getEnd())).flatMap(List::stream)
.map(rruleDate -> new Period(rruleDate, rDuration)).collect(Collectors.toList()));
startMinusDuration, period.getEnd())).flatMap(List<T>::stream)
.map(rruleDate -> new Period<T>(rruleDate, rDuration)).collect(Collectors.toList()));
} else {
// add initial instance if intersection with the specified period..
Period startPeriod;
if (end != null) {
startPeriod = new Period(start.getDate(), end.getDate());
startPeriod = new Period<>(start.getDate(), end.getDate());
} else {
/*
* PeS: Anniversary type has no DTEND nor DUR, define DUR
Expand All @@ -366,7 +357,7 @@ public final PeriodList calculateRecurrenceSet(final Period period) {
duration = new Duration(rDuration);
}

startPeriod = new Period(start.getDate(), duration.getDuration());
startPeriod = new Period<>(start.getDate(), duration.getDuration());
}
if (period.intersects(startPeriod)) {
recurrenceSet.add(startPeriod);
Expand All @@ -375,7 +366,7 @@ public final PeriodList calculateRecurrenceSet(final Period period) {

// subtract exception dates..
List<ExDate> exDateProps = getProperties(Property.EXDATE);
List<Temporal> exDates = exDateProps.stream().map(DateListProperty::getDates).flatMap(List::stream)
List<Temporal> exDates = exDateProps.stream().map(DateListProperty::getDates).map(DateList::getDates).flatMap(List<Temporal>::stream)
.collect(Collectors.toList());

recurrenceSet.removeIf(recurrence -> {
Expand All @@ -386,14 +377,14 @@ public final PeriodList calculateRecurrenceSet(final Period period) {
// subtract exception rules..
List<ExRule> exRules = getProperties(Property.EXRULE);
List<Object> exRuleDates = exRules.stream().map(e -> e.getRecur().getDates(start.getDate(),
period)).flatMap(List::stream).collect(Collectors.toList());
period)).flatMap(List<T>::stream).collect(Collectors.toList());

recurrenceSet.removeIf(recurrence -> {
// for DATE-TIME instances check for DATE-based exclusions also..
return exRuleDates.contains(recurrence.getStart())
|| exRuleDates.contains(recurrence.getStart());
});

return recurrenceSet;
return new ArrayList<>(recurrenceSet);
}
}
35 changes: 18 additions & 17 deletions src/main/java/net/fortuna/ical4j/model/ComponentGroup.java
Expand Up @@ -5,7 +5,10 @@
import net.fortuna.ical4j.model.property.RecurrenceId;
import net.fortuna.ical4j.model.property.Uid;

import java.time.temporal.Temporal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

/**
Expand All @@ -28,24 +31,24 @@
*
* Created by fortuna on 20/07/2017.
*/
public class ComponentGroup<T extends Component> {
public class ComponentGroup<C extends Component> {

private final ComponentList<T> components;
private final ComponentList<C> components;

private final Filter<T> componentFilter;
private final Filter<C> componentFilter;

public ComponentGroup(ComponentList<T> components, Uid uid) {
public ComponentGroup(ComponentList<C> components, Uid uid) {
this(components, uid, null);
}

public ComponentGroup(ComponentList<T> components, Uid uid, RecurrenceId recurrenceId) {
public ComponentGroup(ComponentList<C> components, Uid uid, RecurrenceId recurrenceId) {
this.components = components;

Predicate<T> componentPredicate;
Predicate<C> componentPredicate;
if (recurrenceId != null) {
componentPredicate = new HasPropertyRule<T>(uid).and(new HasPropertyRule<T>(recurrenceId));
componentPredicate = new HasPropertyRule<C>(uid).and(new HasPropertyRule<C>(recurrenceId));
} else {
componentPredicate = new HasPropertyRule<T>(uid);
componentPredicate = new HasPropertyRule<C>(uid);
}
componentFilter = new Filter<>(componentPredicate);
}
Expand All @@ -56,17 +59,17 @@ public ComponentGroup(ComponentList<T> components, Uid uid, RecurrenceId recurre
*
* @return
*/
public ComponentList<T> getRevisions() {
return (ComponentList<T>) componentFilter.filter(components);
public ComponentList<C> getRevisions() {
return (ComponentList<C>) componentFilter.filter(components);
}

/**
* Returns the latest component revision based on ascending sequence number and modified date.
*
* @return
*/
public T getLatestRevision() {
ComponentList<T> revisions = getRevisions();
public C getLatestRevision() {
ComponentList<C> revisions = getRevisions();
revisions.sort(new ComponentSequenceComparator());
Collections.reverse(revisions);
return revisions.iterator().next();
Expand All @@ -81,13 +84,11 @@ public T getLatestRevision() {
*
* @see Component#calculateRecurrenceSet(Period)
*/
public PeriodList calculateRecurrenceSet(final Period period) {
PeriodList periods = new PeriodList();

public <T extends Temporal> List<Period<T>> calculateRecurrenceSet(final Period<T> period) {
List<Period<T>> periods = new ArrayList<>();
for (Component component : getRevisions()) {
periods = periods.add(component.calculateRecurrenceSet(period));
periods.addAll(component.calculateRecurrenceSet(period));
}

return periods;
}
}

0 comments on commit de6610c

Please sign in to comment.