Skip to content

Commit

Permalink
add - doc - Added REPEAT vCalendar 2.0 alarm prope...
Browse files Browse the repository at this point in the history
...rty

---

We've added a vCalendar 2.0 property for alarms, REPEAT, that specifies the repetition rate.

---

Type: add
Breaking: False
Doc Required: True
Backport Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Oct 1, 2024
1 parent ddc796c commit 4714ef2
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 1 deletion.
2 changes: 2 additions & 0 deletions VisualCard.Calendar/Parsers/VCalendarConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,7 @@ internal static class VCalendarConstants
internal const string _percentCompletionSpecifier = "PERCENT-COMPLETION";
internal const string _freeBusySpecifier = "FREEBUSY";
internal const string _recurIdSpecifier = "RECURRENCE-ID";
internal const string _repeatSpecifier = "REPEAT";
internal const string _durationSpecifier = "DURATION";
}
}
11 changes: 10 additions & 1 deletion VisualCard.Calendar/Parsers/VCalendarParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,16 @@ private void ValidateAlarm(CalendarAlarm alarmInfo)
if (!ValidateComponent(ref expectedMailAlarmFields, out string[] actualMailAlarmFields, alarmInfo))
throw new InvalidDataException($"The following keys [{string.Join(", ", expectedMailAlarmFields)}] are required in the mail alarm representation. Got [{string.Join(", ", actualMailAlarmFields)}].");
break;
}
}

// Check to see if there is a repeat property
int repeat = (int)alarmInfo.GetInteger(CalendarIntegersEnum.Repeat);
string[] expectedRepeatedAlarmFields = [VCalendarConstants._durationSpecifier];
if (repeat >= 1)
{
if (!ValidateComponent(ref expectedRepeatedAlarmFields, out string[] actualRepeatedAlarmFields, alarmInfo))
throw new InvalidDataException($"The following keys [{string.Join(", ", expectedRepeatedAlarmFields)}] are required in the repeated alarm representation. Got [{string.Join(", ", actualRepeatedAlarmFields)}].");
}
}

private Parts.Calendar GetCalendarInheritedInstance(string type)
Expand Down
8 changes: 8 additions & 0 deletions VisualCard.Calendar/Parsers/VCalendarParserTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ internal static bool IntegerSupported(CalendarIntegersEnum integersEnum, Type co
CalendarIntegersEnum.Priority => TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarTodo)),
CalendarIntegersEnum.Sequence => TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarTodo), typeof(CalendarJournal)),
CalendarIntegersEnum.PercentComplete => TypeMatch(componentType, typeof(CalendarTodo)),
CalendarIntegersEnum.Repeat => TypeMatch(componentType, typeof(CalendarAlarm)),
_ =>
throw new InvalidOperationException("Invalid integer enumeration type to get supported value"),
};
Expand All @@ -83,6 +84,7 @@ internal static bool EnumArrayTypeSupported(CalendarPartsArrayEnum partsArrayEnu
CalendarPartsArrayEnum.DateCreatedAlt => TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarTodo)),
CalendarPartsArrayEnum.DateStart => TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarTodo), typeof(CalendarFreeBusy), typeof(CalendarStandard), typeof(CalendarDaylight)),
CalendarPartsArrayEnum.DateEnd => TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarFreeBusy)),
CalendarPartsArrayEnum.Duration => calendarVersion.Major == 2 && TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarTodo), typeof(CalendarAlarm)),
CalendarPartsArrayEnum.DateCompleted => TypeMatch(componentType, typeof(CalendarTodo)),
CalendarPartsArrayEnum.DueDate => TypeMatch(componentType, typeof(CalendarTodo)),
CalendarPartsArrayEnum.DateStamp => calendarVersion.Major == 2 && TypeMatch(componentType, typeof(CalendarEvent), typeof(CalendarTodo), typeof(CalendarJournal), typeof(CalendarFreeBusy)),
Expand Down Expand Up @@ -134,6 +136,7 @@ internal static string GetPrefixFromIntegersEnum(CalendarIntegersEnum integersEn
CalendarIntegersEnum.Priority => VCalendarConstants._prioritySpecifier,
CalendarIntegersEnum.Sequence => VCalendarConstants._sequenceSpecifier,
CalendarIntegersEnum.PercentComplete => VCalendarConstants._percentCompletionSpecifier,
CalendarIntegersEnum.Repeat => VCalendarConstants._repeatSpecifier,
_ =>
throw new NotImplementedException($"Integer enumeration {integersEnum} is not implemented.")
};
Expand All @@ -152,6 +155,7 @@ internal static string GetPrefixFromPartsArrayEnum(CalendarPartsArrayEnum partsA
CalendarPartsArrayEnum.DateCreatedAlt => VCalendarConstants._created1Specifier,
CalendarPartsArrayEnum.DateStart => VCalendarConstants._dateStartSpecifier,
CalendarPartsArrayEnum.DateEnd => VCalendarConstants._dateEndSpecifier,
CalendarPartsArrayEnum.Duration => VCalendarConstants._durationSpecifier,
CalendarPartsArrayEnum.DateCompleted => VCalendarConstants._dateCompletedSpecifier,
CalendarPartsArrayEnum.DueDate => VCalendarConstants._dueDateSpecifier,
CalendarPartsArrayEnum.DateStamp => VCalendarConstants._dateStampSpecifier,
Expand Down Expand Up @@ -200,6 +204,8 @@ internal static (CalendarPartsArrayEnum, PartCardinality) GetPartsArrayEnumFromT
return (CalendarPartsArrayEnum.DateStart, PartCardinality.ShouldBeOne);
else if (partsArrayType == typeof(DateEndInfo))
return (CalendarPartsArrayEnum.DateEnd, PartCardinality.MayBeOne);
else if (partsArrayType == typeof(DurationInfo))
return (CalendarPartsArrayEnum.Duration, PartCardinality.MayBeOne);
else if (partsArrayType == typeof(DateCompletedInfo))
return (CalendarPartsArrayEnum.DateCompleted, PartCardinality.MayBeOne);
else if (partsArrayType == typeof(DueDateInfo))
Expand Down Expand Up @@ -245,6 +251,7 @@ internal static (PartType type, object enumeration, Type? enumType, Func<string,
VCalendarConstants._created1Specifier => (PartType.PartsArray, CalendarPartsArrayEnum.DateCreatedAlt, typeof(DateCreatedInfo), DateCreatedInfo.FromStringVcalendarStatic, "", "", "date-time", []),
VCalendarConstants._dateStartSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.DateStart, typeof(DateStartInfo), DateStartInfo.FromStringVcalendarStatic, "", "", "date-time", []),
VCalendarConstants._dateEndSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.DateEnd, typeof(DateEndInfo), DateEndInfo.FromStringVcalendarStatic, "", "", "date-time", []),
VCalendarConstants._durationSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.Duration, typeof(DurationInfo), DurationInfo.FromStringVcalendarStatic, "", "", "duration", []),
VCalendarConstants._dateCompletedSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.DateCompleted, typeof(DateCompletedInfo), DateCompletedInfo.FromStringVcalendarStatic, "", "", "date-time", []),
VCalendarConstants._dueDateSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.DueDate, typeof(DueDateInfo), DueDateInfo.FromStringVcalendarStatic, "", "", "date-time", []),
VCalendarConstants._dateStampSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.DateStamp, typeof(DateStampInfo), DateStampInfo.FromStringVcalendarStatic, "", "", "date-time", []),
Expand Down Expand Up @@ -281,6 +288,7 @@ internal static (PartType type, object enumeration, Type? enumType, Func<string,
VCalendarConstants._prioritySpecifier => (PartType.Integers, CalendarIntegersEnum.Priority, null, null, "", "", "integer", []),
VCalendarConstants._sequenceSpecifier => (PartType.Integers, CalendarIntegersEnum.Sequence, null, null, "", "", "integer", []),
VCalendarConstants._percentCompletionSpecifier => (PartType.Integers, CalendarIntegersEnum.PercentComplete, null, null, "", "", "integer", []),
VCalendarConstants._repeatSpecifier => (PartType.Integers, CalendarIntegersEnum.Repeat, null, null, "", "", "integer", []),

// Extensions are allowed
VCalendarConstants._xSpecifier => (PartType.PartsArray, CalendarPartsArrayEnum.NonstandardNames, typeof(XNameInfo), XNameInfo.FromStringVcalendarStatic, "", "", "", []),
Expand Down
4 changes: 4 additions & 0 deletions VisualCard.Calendar/Parts/Enums/CalendarIntegersEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,9 @@ public enum CalendarIntegersEnum
/// To-do percent completion
/// </summary>
PercentComplete,
/// <summary>
/// Alarm repetition rate
/// </summary>
Repeat,
}
}
4 changes: 4 additions & 0 deletions VisualCard.Calendar/Parts/Enums/CalendarPartsArrayEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ public enum CalendarPartsArrayEnum
/// </summary>
FreeBusy,
/// <summary>
/// Duration (event, todo, or alarm)
/// </summary>
Duration,
/// <summary>
/// The calendar's extended IANA options (usually starts with SOMETHING:Value1;Value2...) (event, todo, journal, free/busy, or alarm)
/// </summary>
IanaNames = int.MaxValue - 2,
Expand Down
125 changes: 125 additions & 0 deletions VisualCard.Calendar/Parts/Implementations/DurationInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//
// VisualCard Copyright (C) 2021-2024 Aptivi
//
// This file is part of VisualCard
//
// VisualCard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// VisualCard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY, without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;
using VisualCard.Parsers;

namespace VisualCard.Calendar.Parts.Implementations
{
/// <summary>
/// Duration info
/// </summary>
[DebuggerDisplay("Duration = {Duration}")]
public class DurationInfo : BaseCalendarPartInfo, IEquatable<DurationInfo>
{
/// <summary>
/// Duration in a string
/// </summary>
public string? Duration { get; }

/// <summary>
/// Duration in a time span
/// </summary>
public TimeSpan DurationSpan =>
VcardCommonTools.GetDurationSpan(Duration ?? "").span;

/// <summary>
/// Duration in a date/time representation
/// </summary>
public DateTimeOffset DurationResult =>
VcardCommonTools.GetDurationSpan(Duration ?? "").result;

internal static BaseCalendarPartInfo FromStringVcalendarStatic(string value, string[] finalArgs, string[] elementTypes, string valueType, Version cardVersion) =>
new DurationInfo().FromStringVcalendarInternal(value, finalArgs, elementTypes, valueType, cardVersion);

internal override string ToStringVcalendarInternal(Version cardVersion) =>
Duration ?? "";

internal override BaseCalendarPartInfo FromStringVcalendarInternal(string value, string[] finalArgs, string[] elementTypes, string valueType, Version cardVersion)
{
// Populate the fields
string duration = Regex.Unescape(value);

// Add the fetched information
DurationInfo _time = new(finalArgs, elementTypes, valueType, duration);
return _time;
}

/// <inheritdoc/>
public override bool Equals(object obj) =>
Equals((DurationInfo)obj);

/// <summary>
/// Checks to see if both the parts are equal
/// </summary>
/// <param name="other">The target <see cref="DurationInfo"/> instance to check to see if they equal</param>
/// <returns>True if all the part elements are equal. Otherwise, false.</returns>
public bool Equals(DurationInfo other) =>
Equals(this, other);

/// <summary>
/// Checks to see if both the parts are equal
/// </summary>
/// <param name="source">The source <see cref="DurationInfo"/> instance to check to see if they equal</param>
/// <param name="target">The target <see cref="DurationInfo"/> instance to check to see if they equal</param>
/// <returns>True if all the part elements are equal. Otherwise, false.</returns>
public bool Equals(DurationInfo source, DurationInfo target)
{
// We can't perform this operation on null.
if (source is null || target is null)
return false;

// Check all the properties
return
source.Duration == target.Duration
;
}

/// <inheritdoc/>
public override int GetHashCode()
{
int hashCode = -101114941;
hashCode = hashCode * -1521134295 + base.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer<string?>.Default.GetHashCode(Duration);
return hashCode;
}

/// <inheritdoc/>
public static bool operator ==(DurationInfo left, DurationInfo right) =>
left.Equals(right);

/// <inheritdoc/>
public static bool operator !=(DurationInfo left, DurationInfo right) =>
!(left == right);

internal override bool EqualsInternal(BaseCalendarPartInfo source, BaseCalendarPartInfo target) =>
(DurationInfo)source == (DurationInfo)target;

internal DurationInfo() { }

internal DurationInfo(string[] arguments, string[] elementTypes, string valueType, string duration) :
base(arguments, elementTypes, valueType)
{
Duration = duration;
}
}
}

0 comments on commit 4714ef2

Please sign in to comment.