diff --git a/src/main/java/biweekly/component/VEvent.java b/src/main/java/biweekly/component/VEvent.java index b6c3dcfb..46e4bf46 100644 --- a/src/main/java/biweekly/component/VEvent.java +++ b/src/main/java/biweekly/component/VEvent.java @@ -1655,15 +1655,7 @@ protected void validate(List components, ICalVersion version, Lis checkOptionalCardinality(warnings, Color.class); - Status[] validStatuses; - switch (version) { - case V1_0: - validStatuses = new Status[] { Status.tentative(), Status.confirmed(), Status.declined(), Status.needsAction(), Status.sent(), Status.delegated() }; - break; - default: - validStatuses = new Status[] { Status.tentative(), Status.confirmed(), Status.cancelled() }; - break; - } + Status[] validStatuses = getValidStatuses(version); checkStatus(warnings, validStatuses); ICalDate dateStart = getValue(getDateStart()); @@ -1719,6 +1711,14 @@ protected void validate(List components, ICalVersion version, Lis } } + private Status[] getValidStatuses(ICalVersion version) { + //@formatter:off + return (version == ICalVersion.V1_0) ? + new Status[] { Status.tentative(), Status.confirmed(), Status.declined(), Status.needsAction(), Status.sent(), Status.delegated() } : + new Status[] { Status.tentative(), Status.confirmed(), Status.cancelled() }; + //@formatter:on + } + @Override public VEvent copy() { return new VEvent(this); diff --git a/src/main/java/biweekly/component/VTodo.java b/src/main/java/biweekly/component/VTodo.java index 87ee2662..6b456821 100644 --- a/src/main/java/biweekly/component/VTodo.java +++ b/src/main/java/biweekly/component/VTodo.java @@ -1689,15 +1689,7 @@ protected void validate(List components, ICalVersion version, Lis checkOptionalCardinality(warnings, Color.class); - Status[] validStatuses; - switch (version) { - case V1_0: - validStatuses = new Status[] { Status.needsAction(), Status.completed(), Status.accepted(), Status.declined(), Status.delegated(), Status.sent() }; - break; - default: - validStatuses = new Status[] { Status.needsAction(), Status.completed(), Status.inProgress(), Status.cancelled() }; - break; - } + Status[] validStatuses = getValidStatuses(version); checkStatus(warnings, validStatuses); ICalDate dateStart = getValue(getDateStart()); @@ -1747,6 +1739,14 @@ protected void validate(List components, ICalVersion version, Lis } } + private Status[] getValidStatuses(ICalVersion version) { + //@formatter:off + return (version == ICalVersion.V1_0) ? + new Status[] { Status.needsAction(), Status.completed(), Status.accepted(), Status.declined(), Status.delegated(), Status.sent() } : + new Status[] { Status.needsAction(), Status.completed(), Status.inProgress(), Status.cancelled() }; + //@formatter:on + } + @Override public VTodo copy() { return new VTodo(this); diff --git a/src/main/java/biweekly/io/scribe/component/VAlarmScribe.java b/src/main/java/biweekly/io/scribe/component/VAlarmScribe.java index 1b5bb31b..65dac38c 100644 --- a/src/main/java/biweekly/io/scribe/component/VAlarmScribe.java +++ b/src/main/java/biweekly/io/scribe/component/VAlarmScribe.java @@ -128,59 +128,75 @@ private static VCalAlarmProperty create(VAlarm valarm) { } if (action.isAudio()) { - AudioAlarm aalarm = new AudioAlarm(); + return createAudioAlarm(valarm); + } - List attaches = valarm.getAttachments(); - if (!attaches.isEmpty()) { - Attachment attach = attaches.get(0); + if (action.isDisplay()) { + createDisplayAlarm(valarm); + } - String formatType = attach.getFormatType(); - aalarm.setParameter("TYPE", formatType); + if (action.isEmail()) { + return createEmailAlarm(valarm); + } - byte[] data = attach.getData(); - if (data != null) { - aalarm.setData(data); - } + if (action.isProcedure()) { + return createProcedureAlarm(valarm); + } - String uri = attach.getUri(); - if (uri != null) { - String contentId = StringUtils.afterPrefixIgnoreCase(uri, "cid:"); - if (contentId == null) { - aalarm.setUri(uri); - } else { - aalarm.setContentId(contentId); - } - } + return null; + } + + private static AudioAlarm createAudioAlarm(VAlarm valarm) { + AudioAlarm aalarm = new AudioAlarm(); + + List attachments = valarm.getAttachments(); + if (!attachments.isEmpty()) { + Attachment firstAttachment = attachments.get(0); + + String formatType = firstAttachment.getFormatType(); + aalarm.setParameter("TYPE", formatType); + + byte[] data = firstAttachment.getData(); + if (data != null) { + aalarm.setData(data); } - return aalarm; + String uri = firstAttachment.getUri(); + if (uri != null) { + String contentId = StringUtils.afterPrefixIgnoreCase(uri, "cid:"); + if (contentId == null) { + aalarm.setUri(uri); + } else { + aalarm.setContentId(contentId); + } + } } - if (action.isDisplay()) { - Description description = valarm.getDescription(); - String text = ValuedProperty.getValue(description); - return new DisplayAlarm(text); - } + return aalarm; + } - if (action.isEmail()) { - List attendees = valarm.getAttendees(); - String email = attendees.isEmpty() ? null : attendees.get(0).getEmail(); - EmailAlarm malarm = new EmailAlarm(email); + private static DisplayAlarm createDisplayAlarm(VAlarm valarm) { + Description description = valarm.getDescription(); + String text = ValuedProperty.getValue(description); + return new DisplayAlarm(text); + } - Description description = valarm.getDescription(); - String note = ValuedProperty.getValue(description); - malarm.setNote(note); + private static EmailAlarm createEmailAlarm(VAlarm valarm) { + List attendees = valarm.getAttendees(); + String email = attendees.isEmpty() ? null : attendees.get(0).getEmail(); + EmailAlarm malarm = new EmailAlarm(email); - return malarm; - } + Description description = valarm.getDescription(); + String note = ValuedProperty.getValue(description); + malarm.setNote(note); - if (action.isProcedure()) { - Description description = valarm.getDescription(); - String path = ValuedProperty.getValue(description); - return new ProcedureAlarm(path); - } + return malarm; + } - return null; + private static ProcedureAlarm createProcedureAlarm(VAlarm valarm) { + Description description = valarm.getDescription(); + String path = ValuedProperty.getValue(description); + return new ProcedureAlarm(path); } /** diff --git a/src/main/java/biweekly/io/scribe/component/VFreeBusyScribe.java b/src/main/java/biweekly/io/scribe/component/VFreeBusyScribe.java index a974a4e8..0f1c63a3 100644 --- a/src/main/java/biweekly/io/scribe/component/VFreeBusyScribe.java +++ b/src/main/java/biweekly/io/scribe/component/VFreeBusyScribe.java @@ -12,6 +12,7 @@ import biweekly.component.VFreeBusy; import biweekly.property.FreeBusy; import biweekly.property.ICalProperty; +import biweekly.util.ICalDate; import biweekly.util.Period; /* @@ -57,35 +58,7 @@ public List getProperties(VFreeBusy component) { } //sort FREEBUSY properties by start date (p.100) - Collections.sort(fb, new Comparator() { - public int compare(FreeBusy one, FreeBusy two) { - Date oneStart = getEarliestStartDate(one); - Date twoStart = getEarliestStartDate(two); - if (oneStart == null && twoStart == null) { - return 0; - } - if (oneStart == null) { - return 1; - } - if (twoStart == null) { - return -1; - } - return oneStart.compareTo(twoStart); - } - - private Date getEarliestStartDate(FreeBusy fb) { - Date date = null; - for (Period tp : fb.getValues()) { - if (tp.getStartDate() == null) { - continue; - } - if (date == null || date.compareTo(tp.getStartDate()) > 0) { - date = tp.getStartDate(); - } - } - return date; - } - }); + Collections.sort(fb, new FreeBusyStartDateComparator()); //find index of first FREEBUSY instance int index = 0; @@ -106,6 +79,40 @@ private Date getEarliestStartDate(FreeBusy fb) { return properties; } + private class FreeBusyStartDateComparator implements Comparator { + @Override + public int compare(FreeBusy one, FreeBusy two) { + Date oneStart = getEarliestStartDate(one); + Date twoStart = getEarliestStartDate(two); + + if (oneStart == null && twoStart == null) { + return 0; + } + if (oneStart == null) { + return 1; + } + if (twoStart == null) { + return -1; + } + return oneStart.compareTo(twoStart); + } + + private Date getEarliestStartDate(FreeBusy fb) { + Date earliestDate = null; + for (Period period : fb.getValues()) { + ICalDate startDate = period.getStartDate(); + if (startDate == null) { + continue; + } + + if (earliestDate == null || earliestDate.compareTo(startDate) > 0) { + earliestDate = startDate; + } + } + return earliestDate; + } + } + @Override protected VFreeBusy _newInstance() { return new VFreeBusy(); diff --git a/src/main/java/biweekly/io/scribe/property/ICalPropertyScribe.java b/src/main/java/biweekly/io/scribe/property/ICalPropertyScribe.java index c22d5b40..41bae102 100644 --- a/src/main/java/biweekly/io/scribe/property/ICalPropertyScribe.java +++ b/src/main/java/biweekly/io/scribe/property/ICalPropertyScribe.java @@ -730,35 +730,46 @@ public String write() { } if (observance) { - DateTimeComponents components = date.getRawComponents(); - if (components == null) { - ICalDateFormat format = extended ? ICalDateFormat.DATE_TIME_EXTENDED_WITHOUT_TZ : ICalDateFormat.DATE_TIME_BASIC_WITHOUT_TZ; - return format.format(date); - } - - return components.toString(true, extended); + return writeObservance(); } if (utc) { - ICalDateFormat format = extended ? ICalDateFormat.UTC_TIME_EXTENDED : ICalDateFormat.UTC_TIME_BASIC; + return writeUtc(); + } + + return date.hasTime() ? writeDateTime() : writeDate(); + } + + private String writeObservance() { + DateTimeComponents components = date.getRawComponents(); + if (components == null) { + ICalDateFormat format = extended ? ICalDateFormat.DATE_TIME_EXTENDED_WITHOUT_TZ : ICalDateFormat.DATE_TIME_BASIC_WITHOUT_TZ; return format.format(date); } + return components.toString(true, extended); + } + + private String writeUtc() { + ICalDateFormat format = extended ? ICalDateFormat.UTC_TIME_EXTENDED : ICalDateFormat.UTC_TIME_BASIC; + return format.format(date); + } + + private String writeDateTime() { ICalDateFormat format; - TimeZone timezone = this.timezone; - if (date.hasTime()) { - if (timezone == null) { - format = extended ? ICalDateFormat.UTC_TIME_EXTENDED : ICalDateFormat.UTC_TIME_BASIC; - } else { - format = extended ? ICalDateFormat.DATE_TIME_EXTENDED_WITHOUT_TZ : ICalDateFormat.DATE_TIME_BASIC_WITHOUT_TZ; - } + if (timezone == null) { + format = extended ? ICalDateFormat.UTC_TIME_EXTENDED : ICalDateFormat.UTC_TIME_BASIC; } else { - format = extended ? ICalDateFormat.DATE_EXTENDED : ICalDateFormat.DATE_BASIC; - timezone = null; + format = extended ? ICalDateFormat.DATE_TIME_EXTENDED_WITHOUT_TZ : ICalDateFormat.DATE_TIME_BASIC_WITHOUT_TZ; } return format.format(date, timezone); } + + private String writeDate() { + ICalDateFormat format = extended ? ICalDateFormat.DATE_EXTENDED : ICalDateFormat.DATE_BASIC; + return format.format(date); + } } /** diff --git a/src/main/java/biweekly/util/Google2445Utils.java b/src/main/java/biweekly/util/Google2445Utils.java index 9aefa613..fe16e956 100644 --- a/src/main/java/biweekly/util/Google2445Utils.java +++ b/src/main/java/biweekly/util/Google2445Utils.java @@ -234,8 +234,8 @@ public static RecurrenceIterable createRecurrenceIterable(Recurrence recurrence, * @return the iterator */ public static DateIterator getDateIterator(ICalComponent component, TimeZone timezone) { - DateStart dtstart = component.getProperty(DateStart.class); - ICalDate start = ValuedProperty.getValue(dtstart); + DateStart startProperty = component.getProperty(DateStart.class); + ICalDate start = ValuedProperty.getValue(startProperty); /* * If the start date is just a date and does not have a time component, @@ -246,8 +246,24 @@ public static DateIterator getDateIterator(ICalComponent component, TimeZone tim timezone = TimeZone.getDefault(); } - /////////////INCLUDE///////////// + List include = buildIncludeIterators(component, start, timezone); + if (include.isEmpty()) { + return new EmptyDateIterator(); + } + + List exclude = buildExcludeIterators(component, start, timezone); + + RecurrenceIterator includeJoined = join(include); + if (exclude.isEmpty()) { + return DateIteratorFactory.createDateIterator(includeJoined); + } + + RecurrenceIterator excludeJoined = join(exclude); + RecurrenceIterator iterator = RecurrenceIteratorFactory.except(includeJoined, excludeJoined); + return DateIteratorFactory.createDateIterator(iterator); + } + private static List buildIncludeIterators(ICalComponent component, ICalDate start, TimeZone timezone) { List include = new ArrayList(); if (start != null) { @@ -267,15 +283,14 @@ public static DateIterator getDateIterator(ICalComponent component, TimeZone tim include.add(new ICalDateRecurrenceIterator(allDates)); } - if (include.isEmpty()) { - if (start == null) { - return new EmptyDateIterator(); - } + if (include.isEmpty() && start != null) { include.add(new ICalDateRecurrenceIterator(Collections.singletonList(start))); } - /////////////EXCLUDE///////////// + return include; + } + private static List buildExcludeIterators(ICalComponent component, ICalDate start, TimeZone timezone) { List exclude = new ArrayList(); if (start != null) { @@ -287,7 +302,7 @@ public static DateIterator getDateIterator(ICalComponent component, TimeZone tim } } - allDates = new ArrayList(); + List allDates = new ArrayList(); for (ExceptionDates exdate : component.getProperties(ExceptionDates.class)) { allDates.addAll(exdate.getValues()); } @@ -295,16 +310,7 @@ public static DateIterator getDateIterator(ICalComponent component, TimeZone tim exclude.add(new ICalDateRecurrenceIterator(allDates)); } - /////////////JOIN///////////// - - RecurrenceIterator includeJoined = join(include); - if (exclude.isEmpty()) { - return DateIteratorFactory.createDateIterator(includeJoined); - } - - RecurrenceIterator excludeJoined = join(exclude); - RecurrenceIterator iterator = RecurrenceIteratorFactory.except(includeJoined, excludeJoined); - return DateIteratorFactory.createDateIterator(iterator); + return exclude; } /**