jfxtras.icalendarfx.components.VTodo Maven / Gradle / Ivy
package jfxtras.icalendarfx.components;
import java.time.DateTimeException;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAmount;
import java.util.Collections;
import java.util.List;
import jfxtras.icalendarfx.VCalendar;
import jfxtras.icalendarfx.components.VDescribable2;
import jfxtras.icalendarfx.components.VLocatable;
import jfxtras.icalendarfx.components.VTodo;
import jfxtras.icalendarfx.properties.component.descriptive.PercentComplete;
import jfxtras.icalendarfx.properties.component.time.DateTimeCompleted;
import jfxtras.icalendarfx.properties.component.time.DateTimeDue;
import jfxtras.icalendarfx.properties.component.time.DurationProp;
import jfxtras.icalendarfx.utilities.DateTimeUtilities;
import jfxtras.icalendarfx.utilities.DateTimeUtilities.DateTimeType;
/**
* VTODO
* To-Do Component
* RFC 5545, 3.6.2, page 55
*
* A "VTODO" calendar component is a grouping of component
properties and possibly "VALARM" calendar components that
represent an action-item or assignment. For example, it can be
used to represent an item of work assigned to an individual; such
as "turn in travel expense today".
The "VTODO" calendar component cannot be nested within another
calendar component. However, "VTODO" calendar components can be
related to each other or to a "VEVENT" or to a "VJOURNAL" calendar
component with the "RELATED-TO" property.
A "VTODO" calendar component without the "DTSTART" and "DUE" (or
"DURATION") properties specifies a to-do that will be associated
with each successive calendar date, until it is completed.
Examples: The following is an example of a "VTODO" calendar
component that needs to be completed before May 1st, 2007. On
midnight May 1st, 2007 this to-do would be considered overdue.
BEGIN:VTODO
UID:[email protected]
DTSTAMP:20070313T123432Z
DUE;VALUE=DATE:20070501
SUMMARY:Submit Quebec Income Tax Return for 2006
CLASS:CONFIDENTIAL
CATEGORIES:FAMILY,FINANCE
STATUS:NEEDS-ACTION
END:VTODO
*
* @author David Bal
*
*/
public class VTodo extends VLocatable implements VDescribable2
{
/**
* COMPLETED: Date-Time Completed
* RFC 5545 iCalendar 3.8.2.1 page 94
* This property defines the date and time that a to-do was
* actually completed.
* The value MUST be specified in the UTC time format.
*
* Example:
* COMPLETED:19960401T150000Z
*/
private DateTimeCompleted dateTimeCompleted;
public DateTimeCompleted getDateTimeCompleted() { return dateTimeCompleted; }
public void setDateTimeCompleted(String dateTimeCompleted) { setDateTimeCompleted(DateTimeCompleted.parse(dateTimeCompleted)); }
public void setDateTimeCompleted(DateTimeCompleted dateTimeCompleted)
{
orderChild(this.dateTimeCompleted, dateTimeCompleted);
this.dateTimeCompleted = dateTimeCompleted;
}
public void setDateTimeCompleted(ZonedDateTime dateTimeCompleted) { setDateTimeCompleted(new DateTimeCompleted(dateTimeCompleted)); }
public VTodo withDateTimeCompleted(ZonedDateTime dateTimeCompleted)
{
setDateTimeCompleted(dateTimeCompleted);
return this;
}
public VTodo withDateTimeCompleted(String dateTimeCompleted)
{
setDateTimeCompleted(dateTimeCompleted);
return this;
}
public VTodo withDateTimeCompleted(DateTimeCompleted dateTimeCompleted)
{
setDateTimeCompleted(dateTimeCompleted);
return this;
}
/**
* DUE: Date-Time Due
* RFC 5545 iCalendar 3.8.2.3 page 96
* This property defines the date and time that a to-do is
* expected to be completed.
* the value type of this property MUST be the same as the "DTSTART" property
*
* Example:
* DUE:TZID=America/Los_Angeles:19970512T090000
*/
private DateTimeDue dateTimeDue;
public DateTimeDue getDateTimeDue() { return dateTimeDue; }
public void setDateTimeDue(String dateTimeDue) { setDateTimeDue(DateTimeDue.parse(dateTimeDue)); }
public void setDateTimeDue(DateTimeDue dateTimeDue)
{
orderChild(this.dateTimeDue, dateTimeDue);
this.dateTimeDue = dateTimeDue;
}
public void setDateTimeDue(Temporal dateTimeDue)
{
if ((dateTimeDue instanceof LocalDate) || (dateTimeDue instanceof LocalDateTime) || (dateTimeDue instanceof ZonedDateTime))
{
setDateTimeDue(new DateTimeDue(dateTimeDue));
} else
{
throw new DateTimeException("Only LocalDate, LocalDateTime and ZonedDateTime supported. "
+ dateTimeDue.getClass().getSimpleName() + " is not supported");
}
}
public VTodo withDateTimeDue(Temporal dateTimeDue)
{
setDateTimeDue(dateTimeDue);
return this;
}
public VTodo withDateTimeDue(String dateTimeDue)
{
setDateTimeDue(dateTimeDue);
return this;
}
public VTodo withDateTimeDue(DateTimeDue dateTimeDue)
{
setDateTimeDue(dateTimeDue);
return this;
}
@Override
public void setDuration(DurationProp duration)
{
if ((getDateTimeDue() != null) && (getDuration() != null))
{
throw new DateTimeException("DURATION and DUE can't both be set");
}
super.setDuration(duration);
}
/**
* PERCENT-COMPLETE
* RFC 5545 iCalendar 3.8.1.8. page 88
*
* This property is used by an assignee or delegatee of a
* to-do to convey the percent completion of a to-do to the "Organizer".
* The property value is a positive integer between 0 and
* 100. A value of "0" indicates the to-do has not yet been started.
* A value of "100" indicates that the to-do has been completed.
*
* Example: The following is an example of this property to show 39% completion:
* PERCENT-COMPLETE:39
*/
private PercentComplete percentComplete;
public PercentComplete getPercentComplete() { return percentComplete; }
public void setPercentComplete(String percentComplete) { setPercentComplete(PercentComplete.parse(percentComplete)); }
public void setPercentComplete(Integer percentComplete) { setPercentComplete(new PercentComplete(percentComplete)); }
public void setPercentComplete(PercentComplete percentComplete)
{
orderChild(this.percentComplete, percentComplete);
this.percentComplete = percentComplete;
}
public VTodo withPercentComplete(PercentComplete percentComplete)
{
setPercentComplete(percentComplete);
return this;
}
public VTodo withPercentComplete(Integer percentComplete)
{
setPercentComplete(percentComplete);
return this;
}
public VTodo withPercentComplete(String percentComplete)
{
setPercentComplete(PercentComplete.parse(percentComplete));
return this;
}
@Override
public List calendarList()
{
if (getParent() != null)
{
VCalendar cal = (VCalendar) getParent();
return cal.getVTodos();
}
return null;
}
/*
* CONSTRUCTORS
*/
public VTodo() { super(); }
public VTodo(VTodo source)
{
super(source);
}
@Override
public TemporalAmount getActualDuration()
{
final TemporalAmount duration;
if (getDuration() != null)
{
duration = getDuration().getValue();
} else if (getDateTimeDue() != null)
{
Temporal dtstart = getDateTimeStart().getValue();
Temporal dtdue = getDateTimeDue().getValue();
duration = DateTimeUtilities.temporalAmountBetween(dtstart, dtdue);
} else
{
return Duration.ZERO;
}
return duration;
}
@Override
public void setEndOrDuration(Temporal startRecurrence, Temporal endRecurrence)
{
TemporalAmount duration = DateTimeUtilities.temporalAmountBetween(startRecurrence, endRecurrence);
if (getDuration() != null)
{
setDuration(duration);
} else if (getDateTimeDue() != null)
{
Temporal due = getDateTimeStart().getValue().plus(duration);
setDateTimeDue(due);
} else
{
throw new RuntimeException("Either DTEND or DURATION must be set");
}
}
@Override
public List errors()
{
List errors = super.errors();
if (getDateTimeStart() == null)
{
errors.add("DTSTART is REQUIRED and MUST NOT occur more than once");
}
boolean isDateTimeDuePresent = getDateTimeDue() != null;
boolean isDurationPresent = getDuration() != null;
if (getDateTimeDue() != null)
{
if (getDateTimeStart() != null)
{
DateTimeType startType = DateTimeUtilities.DateTimeType.of(getDateTimeStart().getValue());
DateTimeType dueType = DateTimeUtilities.DateTimeType.of(getDateTimeDue().getValue());
boolean isDateTimeDueMatch = startType == dueType;
if (! isDateTimeDueMatch)
{
errors.add("The value type of DUE MUST be the same as the DTSTART property (" + dueType + ", " + startType);
}
}
}
if ((! isDateTimeDuePresent) && (! isDurationPresent))
{
// errors.add("Neither DUE or DURATION is present. DUE or DURATION is REQUIRED and MUST NOT occur more than once");
} else if (isDateTimeDuePresent && isDurationPresent)
{
errors.add("Both DUE and DURATION are present. DUE or DURATION MAY appear, but both MUST NOT occur in the same " + name());
} else if (isDateTimeDuePresent)
{
if (! DateTimeUtilities.isAfter(getDateTimeDue().getValue(), getDateTimeStart().getValue()))
{
errors.add("DUE is not after DTSTART. DUE MUST be after DTSTART");
}
}
return Collections.unmodifiableList(errors);
}
@Override
public void eraseDateTimeProperties()
{
super.eraseDateTimeProperties();
setDateTimeDue((DateTimeDue) null);
}
/**
* Creates a new VTodo calendar component by parsing a String of iCalendar content lines
*
* @param content the text to parse, not null
* @return the parsed VTodo
*/
public static VTodo parse(String content)
{
return VTodo.parse(new VTodo(), content);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy