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

jfxtras.icalendarfx.properties.component.alarm.Trigger Maven / Gradle / Ivy

There is a newer version: 17-r1
Show newest version
package jfxtras.icalendarfx.properties.component.alarm;

import java.time.DateTimeException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAmount;
import java.util.List;

import jfxtras.icalendarfx.components.VAlarm;
import jfxtras.icalendarfx.parameters.AlarmTriggerRelationship;
import jfxtras.icalendarfx.parameters.ValueParameter;
import jfxtras.icalendarfx.properties.PropAlarmTrigger;
import jfxtras.icalendarfx.properties.VPropertyBase;
import jfxtras.icalendarfx.properties.ValueType;

/**
 * TRIGGER
 * RFC 5545, 3.8.6.3, page 133
 * 
 * This property specifies when an alarm will trigger.
 * 
 * Value defaults to DURATION, but can also be DATE-TIME.  Only UTC-formatted
 * DATE-TIME is valid.
 * 
 * Example:  A trigger set 15 minutes prior to the start of the event or to-do.
 * TRIGGER:-PT15M
 * A trigger set five minutes after the end of an event or the due date of a to-do.
 * TRIGGER;RELATED=END:PT5M
 * 
 * @author David Bal
 * 
 * The property can be specified in following components:
 * @see VAlarm
 */
public class Trigger extends VPropertyBase> implements PropAlarmTrigger
{
    /**
    * RELATED: Alarm Trigger Relationship
    * RFC 5545, 3.2.14, page 24
    * To specify the relationship of the alarm trigger with
    * respect to the start or end of the calendar component.
    */
   @Override
   public AlarmTriggerRelationship getAlarmTrigger() { return relationship; }
   private AlarmTriggerRelationship relationship;
   @Override
   public void setAlarmTrigger(AlarmTriggerRelationship relationship)
   {
       if (relationship != null)
       {
           ValueType valueType = (getValueType() == null) ? defaultValueType : getValueType().getValue();
           if (valueType == ValueType.DURATION)
           {
        	   orderChild(relationship);
               this.relationship = relationship;
           } else
           {
               throw new IllegalArgumentException("Alarm Trigger Relationship can only be set if value type is DURATION");
           }
       }
   }
   public Trigger withAlarmTrigger(AlarmTriggerRelationship format) { setAlarmTrigger(format); return this; }
    
    public Trigger(Trigger source)
    {
        super(source);
    }
    
    public Trigger(T value)
    {
        super(value);
    }
    
    public Trigger()
    {
        super();
    }
    
    @Override
    public void setValue(T value)
    {
        if (value instanceof ZonedDateTime)
        {
            ZoneId zone = ((ZonedDateTime) value).getZone();
            if (! zone.equals(ZoneId.of("Z")))
            {
                throw new DateTimeException("Unsupported ZoneId:" + zone + " only Z supported");
            }
            setValueType(ValueType.DATE_TIME); // override default value type
        }
        super.setValue(value);
    }

    @Override
    public void setValueType(ValueParameter valueType)
    {
        if ((valueType.getValue() == ValueType.DATE_TIME) && (getAlarmTrigger() != null))
        {
            throw new IllegalArgumentException("Value type can only be set to DATE-TIME if Alarm Trigger Relationship is null");
        }
        super.setValueType(valueType);
    }
    
    @Override
    protected void setConverterByClass(Class clazz)
    {
        if (TemporalAmount.class.isAssignableFrom(clazz))
        {
            setConverter(ValueType.DURATION.getConverter());
        } else if (clazz.equals(ZonedDateTime.class))
        {
            setConverter(ValueType.DATE_TIME.getConverter());           
        } else
        {
            throw new IllegalArgumentException("Only parameterized types of Duration, Period and ZonedDateTime are supported.");           
        }
    }
    
    @Override
    public boolean isValid()
    {
        boolean isDateTimeValue = (getValueType() == null) ? false : getValueType().getValue() != ValueType.DATE_TIME;
        if (isDateTimeValue)
        {
            // The "RELATED" property parameter is not valid if the value type of the property is set to DATE-TIME
            if (getAlarmTrigger() != null)
            {
                return false;
            }
        }
        return true && super.isValid();
    }
    
    /** Parse string to Temporal.  Not type safe.  Implementation must
     * ensure parameterized type is the same as date-time represented by String parameter */
    public static  Trigger parse(String content)
    {
        return Trigger.parse(new Trigger(), content);
    }
    
    /** Parse string with Temporal class explicitly provided as parameter */
    public static  Trigger parse(Class clazz, String value)
    {
        Trigger property = new Trigger();
        property.setConverterByClass(clazz);
        List m = property.parseContent(value);
        if (! m.isEmpty()) throw new DateTimeException("Invalid value:" + value);
        return property;
    }
}