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

jfxtras.icalendarfx.components.VTodo Maven / Gradle / Ivy

There is a newer version: 17-r1
Show newest version
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