diff --git a/cosmo-api/src/main/java/org/unitedinternet/cosmo/model/filter/FilterEval.java b/cosmo-api/src/main/java/org/unitedinternet/cosmo/model/filter/FilterEval.java new file mode 100644 index 00000000..1b177c80 --- /dev/null +++ b/cosmo-api/src/main/java/org/unitedinternet/cosmo/model/filter/FilterEval.java @@ -0,0 +1,13 @@ +package org.unitedinternet.cosmo.model.filter; + +public enum FilterEval { + FILTER_PARENT_NOTNULL, + + INSTANCE_OF_NOTE_ITEM_FILTER, + + INSTANCE_OF_CONTENT_ITEM_FILTER, + + FILTER_DISPLAY_NAME_NOT_NULL, + + FILTER_UID_NOT_NULL +} diff --git a/cosmo-api/src/main/java/org/unitedinternet/cosmo/model/filter/ItemFilter.java b/cosmo-api/src/main/java/org/unitedinternet/cosmo/model/filter/ItemFilter.java index ba9d9970..6902df2f 100644 --- a/cosmo-api/src/main/java/org/unitedinternet/cosmo/model/filter/ItemFilter.java +++ b/cosmo-api/src/main/java/org/unitedinternet/cosmo/model/filter/ItemFilter.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.List; +import org.springframework.context.annotation.FilterType; import org.unitedinternet.cosmo.model.CollectionItem; import org.unitedinternet.cosmo.model.QName; @@ -46,7 +47,27 @@ public class ItemFilter { public ItemFilter() { } - + + public FilterEval judgeItemFilter(ItemFilter filter){ + + if(filter.getParent()!=null) + return FilterEval.FILTER_PARENT_NOTNULL; + + if(filter instanceof NoteItemFilter) + return FilterEval.INSTANCE_OF_NOTE_ITEM_FILTER; + + if(filter instanceof ContentItemFilter) + return FilterEval.INSTANCE_OF_CONTENT_ITEM_FILTER; + + if(filter.getDisplayName()!=null) + return FilterEval.FILTER_DISPLAY_NAME_NOT_NULL; + + if(filter.getUid()!=null) + return FilterEval.FILTER_UID_NOT_NULL; + + return null; + } + /** * List of AttributeFilters. If there are multiple attribute filters, * each filter must match for an item to match the ItemFilter. diff --git a/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/hcalendar/HCalendarParser.java b/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/hcalendar/HCalendarParser.java index d0f9daa9..fa71c9a5 100644 --- a/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/hcalendar/HCalendarParser.java +++ b/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/hcalendar/HCalendarParser.java @@ -649,9 +649,7 @@ private Date icalDate(String original) normalized = original.replace("Z", "GMT-00:00"); } // 2002-10-10T00:00:00+05:00 - else if (original.indexOf("GMT") == -1 && - (original.charAt(original.length()-6) == '+' || - original.charAt(original.length()-6) == '-')) { + else if (needsGmtConversion(original)) { String tzId = "GMT" + original.substring(original.length()-6); normalized = original.substring(0, original.length()-6) + tzId; } @@ -675,4 +673,16 @@ else if (original.indexOf("GMT") == -1 && return dt; } + + private boolean isPlusOrMinusAtPosition(String original, int position) { + return original.charAt(position) == '+' || original.charAt(position) == '-'; + } + + private boolean needsGmtConversion(String original) { + return !original.contains("GMT") && isPlusOrMinusAtPosition(original, original.length() - 6); + } } + + + + diff --git a/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/query/CalendarFilterEvaluater.java b/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/query/CalendarFilterEvaluater.java index 2eaccd44..96cddefd 100644 --- a/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/query/CalendarFilterEvaluater.java +++ b/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/query/CalendarFilterEvaluater.java @@ -72,7 +72,7 @@ public CalendarFilterEvaluater() {} * @throws UnsupportedQueryException if filter represents a query * that the server does not support */ - public boolean evaluate(Calendar calendar, CalendarFilter filter) { + public boolean evaluateCalendarFilter(Calendar calendar, CalendarFilter filter) { ComponentFilter rootFilter = filter.getFilter(); // root filter must be "VCALENDAR" @@ -100,7 +100,7 @@ public boolean evaluate(Calendar calendar, CalendarFilter filter) { * @param filter The component filter. * @return The result. */ - private boolean evaluate(ComponentList comps, ComponentFilter filter) { + private boolean evaluateComponentFilter(ComponentList comps, ComponentFilter filter) { // Evaluate component filter against a set of components. // If any component matches, then evaluation succeeds. // This is basically a big OR @@ -121,7 +121,7 @@ private boolean evaluate(ComponentList comps, ComponentFilt * @param filter The property filter. * @return The result. */ - private boolean evaluate(ComponentList comps, PropertyFilter filter) { + private boolean evaluatePropertyFilter(ComponentList comps, PropertyFilter filter) { // Evaluate property filter against a set of components. // If any component matches, then evaluation succeeds. @@ -180,13 +180,13 @@ private boolean evaluateComps(ComponentList components, Com } for(Iterator it = filter.getComponentFilters().iterator(); it.hasNext();) { - if(evaluate(comps, it.next())==false) { + if(evaluateComponentFilter(comps, it.next())==false) { return false; } } for(Iterator it = filter.getPropFilters().iterator(); it.hasNext();) { - if(evaluate(comps, it.next())==false) { + if(evaluatePropertyFilter(comps, it.next())==false) { return false; } } diff --git a/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/query/impl/StandardCalendarQueryProcessor.java b/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/query/impl/StandardCalendarQueryProcessor.java index da9d547c..eb0af5ba 100644 --- a/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/query/impl/StandardCalendarQueryProcessor.java +++ b/cosmo-core/src/main/java/org/unitedinternet/cosmo/calendar/query/impl/StandardCalendarQueryProcessor.java @@ -123,7 +123,7 @@ public boolean filterQuery(ICalendarItem item, CalendarFilter filter) { Calendar calendar = entityConverter.convertContent(item); if(calendar!=null) { - return new CalendarFilterEvaluater().evaluate(calendar, filter); + return new CalendarFilterEvaluater().evaluateCalendarFilter(calendar, filter); } else { return false; @@ -249,79 +249,50 @@ protected void doFreeBusyQuery(PeriodList busyPeriods, busyTentativePeriods, busyUnavailablePeriods); } } - - /** - * Adds relevant periods. - * @param calendar The calendar. - * @param timezone The timezone. - * @param freeBusyRange - * @param busyPeriods - * @param busyTentativePeriods - * @param busyUnavailablePeriods - */ - protected void addBusyPeriods(Calendar calendar, TimeZone timezone, - Period freeBusyRange, PeriodList busyPeriods, - PeriodList busyTentativePeriods, PeriodList busyUnavailablePeriods) { - - // Create list of instances within the specified time-range - InstanceList instances = new InstanceList(); - instances.setUTC(true); - instances.setTimezone(timezone); - // Look at each VEVENT/VFREEBUSY component only - ComponentList overrides = new ComponentList<>(); - for (Object comp: calendar.getComponents()) { - if (comp instanceof VEvent) { - VEvent vcomp = (VEvent) comp; - // See if this is the master instance - if (vcomp.getRecurrenceId() == null) { - instances.addComponent(vcomp, freeBusyRange.getStart(), - freeBusyRange.getEnd()); - } else { - overrides.add(vcomp); - } - } else if (comp instanceof VFreeBusy) { - // Add all FREEBUSY BUSY/BUSY-TENTATIVE/BUSY-UNAVAILABLE to the periods - List fbs = ((Component)comp).getProperties().getProperties(Property.FREEBUSY); - for (FreeBusy fb : fbs) { - FbType fbt = (FbType) fb.getParameters().getParameter( - Parameter.FBTYPE); - if (fbt == null || FbType.BUSY.equals(fbt)) { - addRelevantPeriods(busyPeriods, fb.getPeriods(), - freeBusyRange); - } else if (FbType.BUSY_TENTATIVE.equals(fbt)) { - addRelevantPeriods(busyTentativePeriods, fb - .getPeriods(), freeBusyRange); - } else if (FbType.BUSY_UNAVAILABLE.equals(fbt)) { - addRelevantPeriods(busyUnavailablePeriods, fb - .getPeriods(), freeBusyRange); - } - } - } - } + private VEvent addComponentsToInstances(Calendar calendar, Period freeBusyRange, InstanceList instances, Object comp) { - for (Iterator i = overrides.iterator(); i.hasNext();) { - Component comp = i.next(); - instances.addComponent(comp, freeBusyRange.getStart(), + VEvent vcomp = (VEvent) comp; + // See if this is the master instance + if (vcomp.getRecurrenceId() == null) { + instances.addComponent(vcomp, freeBusyRange.getStart(), freeBusyRange.getEnd()); + } else { + return vcomp; } + return vcomp; + } - // See if there is nothing to do (should not really happen) - if (instances.size() == 0) { - return; + private void addFreeBusyPeriods(Object comp, Period freeBusyRange, PeriodList busyPeriods, PeriodList busyTentativePeriods, PeriodList busyUnavailablePeriods) { + List fbs = ((Component)comp).getProperties().getProperties(Property.FREEBUSY); + for (FreeBusy fb : fbs) { + FbType fbt = (FbType) fb.getParameters().getParameter( + Parameter.FBTYPE); + if (fbt == null || FbType.BUSY.equals(fbt)) { + addRelevantPeriods(busyPeriods, fb.getPeriods(), + freeBusyRange); + } else if (FbType.BUSY_TENTATIVE.equals(fbt)) { + addRelevantPeriods(busyTentativePeriods, fb + .getPeriods(), freeBusyRange); + } else if (FbType.BUSY_UNAVAILABLE.equals(fbt)) { + addRelevantPeriods(busyUnavailablePeriods, fb + .getPeriods(), freeBusyRange); + } } + } + + private void addPeriodsToBusyLists(InstanceList instances, Period freeBusyRange, PeriodList busyPeriods, PeriodList busyTentativePeriods) { - // Add start/end period for each instance for (Iterator> i = instances.entrySet().iterator(); i.hasNext();) { Map.Entry entry = i.next(); - + Object instanceObj = entry.getValue(); - + if(!(instanceObj instanceof Instance)){ continue; } Instance instance = (Instance) instanceObj; - + // Check that the VEVENT has the proper busy status if (Transp.TRANSPARENT.equals(instance.getComp().getProperties() .getProperty(Property.TRANSP))) { @@ -335,10 +306,10 @@ protected void addBusyPeriods(Calendar calendar, TimeZone timezone, // Can only have DATE-TIME values in PERIODs Date start = null; Date end = null; - + start = instance.getStart(); end = instance.getEnd(); - + if (start.compareTo(freeBusyRange.getStart()) < 0) { start = (DateTime) org.unitedinternet.cosmo.calendar.util.Dates.getInstance(freeBusyRange .getStart(), start); @@ -355,8 +326,52 @@ protected void addBusyPeriods(Calendar calendar, TimeZone timezone, } else { busyPeriods.add(new Period(dtStart, dtEnd)); } - + + } + + } + + /** + * Adds relevant periods. + * @param calendar The calendar. + * @param timezone The timezone. + * @param freeBusyRange + * @param busyPeriods + * @param busyTentativePeriods + * @param busyUnavailablePeriods + */ + protected void addBusyPeriods(Calendar calendar, TimeZone timezone, + Period freeBusyRange, PeriodList busyPeriods, + PeriodList busyTentativePeriods, PeriodList busyUnavailablePeriods) { + + // Create list of instances within the specified time-range + InstanceList instances = new InstanceList(); + instances.setUTC(true); + instances.setTimezone(timezone); + + // Look at each VEVENT/VFREEBUSY component only + ComponentList overrides = new ComponentList<>(); + for (Object comp: calendar.getComponents()) { + if (comp instanceof VEvent) { + overrides.add(addComponentsToInstances(calendar,freeBusyRange, instances,comp)); + } else if (comp instanceof VFreeBusy) { + // Add all FREEBUSY BUSY/BUSY-TENTATIVE/BUSY-UNAVAILABLE to the periods + addFreeBusyPeriods(comp, freeBusyRange, busyPeriods, busyTentativePeriods, busyUnavailablePeriods); + } + } + + for (Iterator i = overrides.iterator(); i.hasNext();) { + Component comp = i.next(); + instances.addComponent(comp, freeBusyRange.getStart(), + freeBusyRange.getEnd()); } + + // See if there is nothing to do (should not really happen) + if (instances.size() == 0) { + return; + } + + addPeriodsToBusyLists(instances,freeBusyRange, busyPeriods, busyTentativePeriods); } /** diff --git a/cosmo-core/src/main/java/org/unitedinternet/cosmo/dao/hibernate/CalendarDaoImpl.java b/cosmo-core/src/main/java/org/unitedinternet/cosmo/dao/hibernate/CalendarDaoImpl.java index 951aae76..4ce8cd72 100644 --- a/cosmo-core/src/main/java/org/unitedinternet/cosmo/dao/hibernate/CalendarDaoImpl.java +++ b/cosmo-core/src/main/java/org/unitedinternet/cosmo/dao/hibernate/CalendarDaoImpl.java @@ -138,7 +138,7 @@ public Set findCalendarItems(CollectionItem collection, CalendarF ICalendarItem content = (ICalendarItem) child; Calendar calendar = entityConverter.convertContent(content); - if (calendar != null && evaluater.evaluate(calendar, filter)) { + if (calendar != null && evaluater.evaluateCalendarFilter(calendar, filter)) { results.add(content); } } diff --git a/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/CaldavMultiStatusReport.java b/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/CaldavMultiStatusReport.java index a6c80477..921f8488 100644 --- a/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/CaldavMultiStatusReport.java +++ b/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/CaldavMultiStatusReport.java @@ -44,14 +44,14 @@ */ public abstract class CaldavMultiStatusReport extends MultiStatusReport implements CaldavConstants { - - private OutputFilter outputFilter; // ReportBase methods // MultiStatusReport methods + protected OutputFilter outputFilter; + /** * Removes CALDAV:calendar-data from the property spec * since it doesn't represent a real property. @@ -88,9 +88,6 @@ public OutputFilter getOutputFilter() { return outputFilter; } - public void setOutputFilter(OutputFilter outputFilter) { - this.outputFilter = outputFilter; - } /** * Parses an output filter out of the given report info. @@ -128,4 +125,20 @@ private String readCalendarData(DavCalendarResource resource) } return builder.toString(); } + + public void setReportSpecifics(ReportInfo info) throws CosmoDavException { + setPropFindProps(info.getPropertyNameSet()); + if (info.containsContentElement(XML_ALLPROP, NAMESPACE)) { + setPropFindType(PROPFIND_ALL_PROP); + } else if (info.containsContentElement(XML_PROPNAME, NAMESPACE)) { + setPropFindType(PROPFIND_PROPERTY_NAMES); + } else { + setPropFindType(PROPFIND_BY_PROPERTY); + setOutputFilter(findOutputFilter(info)); + } + } + + public void setOutputFilter(OutputFilter outputFilter) { + this.outputFilter = outputFilter; + } } diff --git a/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/MultigetReport.java b/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/MultigetReport.java index 7d81af8e..1e347812 100644 --- a/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/MultigetReport.java +++ b/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/MultigetReport.java @@ -86,15 +86,7 @@ protected void parseReport(ReportInfo info) throws CosmoDavException { throw new CosmoDavException("Report not of type " + getType().getReportName()); } - setPropFindProps(info.getPropertyNameSet()); - if (info.containsContentElement(XML_ALLPROP, NAMESPACE)) { - setPropFindType(PROPFIND_ALL_PROP); - } else if (info.containsContentElement(XML_PROPNAME, NAMESPACE)) { - setPropFindType(PROPFIND_PROPERTY_NAMES); - } else { - setPropFindType(PROPFIND_BY_PROPERTY); - setOutputFilter(findOutputFilter(info)); - } + setReportSpecifics(info); List hrefElements = info.getContentElements(XML_HREF, NAMESPACE); diff --git a/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/QueryReport.java b/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/QueryReport.java index dab0a21b..6c2748c1 100644 --- a/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/QueryReport.java +++ b/cosmo-core/src/main/java/org/unitedinternet/cosmo/dav/caldav/report/QueryReport.java @@ -69,15 +69,7 @@ protected void parseReport(ReportInfo info) throw new CosmoDavException("Report not of type " + getType()); } - setPropFindProps(info.getPropertyNameSet()); - if (info.containsContentElement(XML_ALLPROP, NAMESPACE)) { - setPropFindType(PROPFIND_ALL_PROP); - } else if (info.containsContentElement(XML_PROPNAME, NAMESPACE)) { - setPropFindType(PROPFIND_PROPERTY_NAMES); - } else { - setPropFindType(PROPFIND_BY_PROPERTY); - setOutputFilter(findOutputFilter(info)); - } + setReportSpecifics(info); tz = findTimeZone(info); if ( tz == null && getResource() instanceof DavCalendarCollection) { diff --git a/cosmo-core/src/main/java/org/unitedinternet/cosmo/service/impl/NoteTriageStatusHelper.java b/cosmo-core/src/main/java/org/unitedinternet/cosmo/service/impl/NoteTriageStatusHelper.java new file mode 100644 index 00000000..e7f0b7e9 --- /dev/null +++ b/cosmo-core/src/main/java/org/unitedinternet/cosmo/service/impl/NoteTriageStatusHelper.java @@ -0,0 +1,465 @@ +package org.unitedinternet.cosmo.service.impl; + +import java.time.Duration; +import java.time.temporal.TemporalAmount; +import java.util.*; + +import net.fortuna.ical4j.model.DateTime; +import net.fortuna.ical4j.model.Recur; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.unitedinternet.cosmo.calendar.Instance; +import org.unitedinternet.cosmo.calendar.InstanceList; +import org.unitedinternet.cosmo.calendar.RecurrenceExpander; +import org.unitedinternet.cosmo.dao.ContentDao; +import org.unitedinternet.cosmo.model.*; +import org.unitedinternet.cosmo.model.hibernate.ModificationUidImpl; +import org.unitedinternet.cosmo.service.triage.TriageStatusQueryContext; +import net.fortuna.ical4j.model.TemporalAmountAdapter; +import org.unitedinternet.cosmo.util.NoteOccurrenceUtil; + +@Component +public class NoteTriageStatusHelper { + + public static final Comparator COMPARE_ASC = new NoteItemTriageStatusComparator(false); + public static final Comparator COMPARE_DESC = new NoteItemTriageStatusComparator(true); + + @Autowired + private ContentDao contentDao; + + // 366 days (1 year) + private TemporalAmount yearLaterDur = Duration.ofDays(366); + private TemporalAmount yearDoneDur = Duration.ofDays(-366); + + // 31 days (1 month) + private TemporalAmount monthLaterDur = Duration.ofDays(31); + private TemporalAmount monthDoneDur = Duration.ofDays(-31); + private static final Logger LOG = LoggerFactory.getLogger(StandardTriageStatusQueryProcessor.class); + + public static class QueryResult { + private ArrayList results = new ArrayList(); + private HashSet masters = new HashSet(); + private Comparator comparator; + private int limit; + + /** + * + */ + public QueryResult() { + this(true, -1); + } + + /** + * @param ascending boolean + * @param limit int + */ + public QueryResult(boolean ascending, int limit) { + results = new ArrayList(); + masters = new HashSet(); + comparator = ascending ? COMPARE_ASC : COMPARE_DESC; + this.limit = limit; + } + + public ArrayList getResults() { + return results; + } + + /** + * + */ + public void processResults() { + + // sort + Collections.sort(results, comparator); + + // trim based on limit + if (limit != -1 && results.size() > limit) { + while (results.size() > limit) { + results.remove(results.size() - 1); + } + + // rebuild masters list as it may have changed + masters.clear(); + for (NoteItem note : results) { + if (note instanceof NoteOccurrence) { + masters.add(((NoteOccurrence) note).getMasterNote()); + } else if (note.getModifies() != null) { + masters.add(note.getModifies()); + } + } + } + } + + public HashSet getMasters() { + return masters; + } + + /** + * @param qr QueryResult + */ + public void add(QueryResult qr) { + qr.processResults(); + results.addAll(qr.getResults()); + masters.addAll(qr.getMasters()); + } + + /** + * @return SortedSet + */ + public SortedSet merge() { + + TreeSet merged = new TreeSet(comparator); + merged.addAll(results); + merged.addAll(masters); + + return merged; + } + } + + /** + * @param note NoteItem + * @param context TriageStatusQueryContext + * @return QueryResult + */ + public QueryResult getAll(NoteItem note, + TriageStatusQueryContext context) { + QueryResult qr = new QueryResult(); + + qr.add(getNow(note, context)); + qr.add(getDone(note, context)); + qr.add(getLater(note, context)); + + return qr; + } + + + /** + * NOW Query for a specific master NoteItem:
+ * - Modifications with triage status NOW
+ * - Occurrences whose period overlaps the current point in time + * - Modifications with triage status null and whose period + * overlaps the current point in time. + * + * @param master NoteItem + * @param context TriageStatusQueryContext + * @return QueryResult + */ + public QueryResult getNow(NoteItem master, + TriageStatusQueryContext context) { + QueryResult qr = new QueryResult(); + Set mods = null; + + mods = getModificationsByTriageStatus(master, TriageStatus.CODE_NOW); + qr.getResults().addAll(mods); + + // add all occurrences that occur NOW + mods = getNowFromRecurringNote(master, context); + qr.getResults().addAll(mods); + + // add master if necessary + if (!qr.getResults().isEmpty()) { + qr.getMasters().add(master); + } + + return qr; + } + + + /** + * LATER Query for a specific master NoteItem:
+ * - the next occurring modification + * with triage status LATER or the next occurrence, whichever occurs sooner + * + * @param master NoteItem + * @param context TriageStatusQueryContext + * @return QueryResult + */ + public QueryResult getLater(NoteItem master, + TriageStatusQueryContext context) { + QueryResult qr = new QueryResult(false, -1); + + // get the next occurring modification or occurrence + NoteItem result = getLaterFromRecurringNote(master, context); + + // add result and master if present + if (result != null) { + qr.getMasters().add(master); + qr.getResults().add(result); + } + + // add all modifications with trigaeStatus LATER + Set mods = + getModificationsByTriageStatus(master, TriageStatus.CODE_LATER); + if (qr.getResults().addAll(mods)) { + qr.getMasters().add(master); + } + + return qr; + } + + + /** + * DONE Query for a specific master NoteItem:
+ * - the last occurring modification + * with triage status DONE or the last occurrence, whichever occurred + * most recently + * + * @param master NoteItem + * @param context TriageStatusQueryContext + * @return QueryResult + */ + public QueryResult getDone(NoteItem master, + TriageStatusQueryContext context) { + QueryResult qr = new QueryResult(); + + // get the most recently occurred modification or occurrence + NoteItem result = getDoneFromRecurringNote(master, context); + + // add result and master if present + if (result != null) { + qr.getMasters().add(master); + qr.getResults().add(result); + } + + // add all modifications with trigaeStatus DONE + Set mods = + getModificationsByTriageStatus(master, TriageStatus.CODE_DONE); + if (qr.getResults().addAll(mods)) { + qr.getMasters().add(master); + } + + return qr; + } + + /** + * @param master NoteItem + * @param triageStatus Integer + * @return Set + */ + public Set getModificationsByTriageStatus(NoteItem master, Integer triageStatus) { + + HashSet mods = new HashSet(); + + for (NoteItem mod : master.getModifications()) { + if (mod.getTriageStatus() == null + || mod.getTriageStatus().getCode() == null + || mod.getTriageStatus().getCode().equals(triageStatus)) { + continue; + } + + mods.add(mod); + } + + return mods; + } + + + /** + * Get the last occurring modification or occurrence, whichever occurred + * last. + * + * @param note NoteItem + * @param context TriageStatusQueryContext + * @return NoteItem + */ + public NoteItem + getDoneFromRecurringNote(NoteItem note, + TriageStatusQueryContext context) { + EventStamp eventStamp = StampUtils.getEventStamp(note); + Date currentDate = context.getPointInTime(); + Date pastDate = new TemporalAmountAdapter(getDurToUseForExpanding(eventStamp, false)).getTime(currentDate); + + // calculate the previous occurrence or modification + NoteItem latest = getLatestInstanceOrModification(eventStamp, pastDate, + currentDate, context.getTimeZone()); + + return latest; + } + + + /** + * @param es EventStamp + * @param later boolean + * @return Dur + */ + public TemporalAmount getDurToUseForExpanding(EventStamp es, boolean later) { + List rules = es.getRecurrenceRules(); + + // No rules, assume RDATEs so expand a year + if (rules.size() == 0) { + return later ? yearLaterDur : yearDoneDur; + } + + // Look at first rule only + Recur recur = rules.get(0); + + // If rule is yearly or monthly then expand a year, + // otherwise only expand a month + if (Recur.Frequency.YEARLY.equals(recur.getFrequency()) || + Recur.Frequency.MONTHLY.equals(recur.getFrequency())) { + return later ? yearLaterDur : yearDoneDur; + } else { + return later ? monthLaterDur : monthDoneDur; + } + } + + + /** + * Calculate and return the latest ocurring instance or modification for the + * specified master event and date range. + * The instance must end before the end of the range. + * If the latest instance is a modification, then the modification must + * have a triageStatus of DONE + * + * @param event Eventstamp + * @param rangeStart Date + * @param rangeEnd Date + * @param timezone Timezone + * @return NoteItem + */ + public NoteItem getLatestInstanceOrModification(EventStamp event, Date rangeStart, Date rangeEnd, + net.fortuna.ical4j.model.TimeZone timezone) { + NoteItem note = (NoteItem) event.getItem(); + RecurrenceExpander expander = new RecurrenceExpander(); + + InstanceList instances = expander.getOcurrences(event.getEvent(), event.getExceptions(), + new DateTime(rangeStart), new DateTime(rangeEnd), timezone); + + // Find the latest occurrence that ends before the end of the range + while (instances.size() > 0) { + String lastKey = (String) instances.lastKey(); + Instance instance = (Instance) instances.remove(lastKey); + if (instance.getEnd().before(rangeEnd)) { + if (instance.isOverridden()) { + ModificationUid modUid = new ModificationUidImpl(note, instance.getRid()); + NoteItem mod = (NoteItem) contentDao.findItemByUid(modUid.toString()); + // shouldn't happen, but log and continue if it does + if (mod == null) { + LOG.error("no modification found for uid: {}", modUid.toString()); + continue; + } + TriageStatus status = mod.getTriageStatus(); + if (status == null || status.getCode().equals(TriageStatus.CODE_DONE)) { + return mod; + } + } else { + return NoteOccurrenceUtil.createNoteOccurrence(instance.getRid(), note); + } + } + + } + + return null; + } + + + /** + * Get all instances that are occuring during a given point in time + * + * @param note NoteItem + * @param context TriageStatusQueryContext + * @return Set + */ + public Set + getNowFromRecurringNote(NoteItem note, + TriageStatusQueryContext context) { + EventStamp eventStamp = StampUtils.getEventStamp(note); + DateTime currentDate = new DateTime(context.getPointInTime()); + RecurrenceExpander expander = new RecurrenceExpander(); + HashSet results = new HashSet(); + + // Get all occurrences that overlap current instance in time + InstanceList occurrences = expander.getOcurrences( + eventStamp.getEvent(), eventStamp.getExceptions(), currentDate, + currentDate, context.getTimeZone()); + + for (Instance instance : (Collection) occurrences.values()) { + // Not interested in modifications + if (!instance.isOverridden()) { + // add occurrence + results.add(NoteOccurrenceUtil.createNoteOccurrence(instance.getRid(), note)); + } else { + // return modification if it has no triage-status + ModificationUid modUid = new ModificationUidImpl(note, instance.getRid()); + NoteItem mod = (NoteItem) contentDao.findItemByUid(modUid.toString()); + if (mod.getTriageStatus() == null || mod.getTriageStatus().getCode() == null) { + results.add(mod); + } + } + } + + return results; + } + + /** + * Get the next occurrence or modification for a recurring event, whichever + * occurrs sooner relative to a point in time. + * + * @param note NoteItem + * @param context TriageStatusQueryContext + * @return Set + */ + public NoteItem + getLaterFromRecurringNote(NoteItem note, + TriageStatusQueryContext context) { + EventStamp eventStamp = StampUtils.getEventStamp(note); + Date currentDate = context.getPointInTime(); + Date futureDate = new TemporalAmountAdapter(getDurToUseForExpanding(eventStamp, true)).getTime(currentDate); + + // calculate the next occurrence or LATER modification + NoteItem first = getFirstInstanceOrModification(eventStamp, + currentDate, futureDate, context.getTimeZone()); + + return first; + } + + + /** + * Calculate and return the first ocurring instance or modification + * for the specified master event and date range. + * The instance must begin after the start of the range and if it + * is a modification it must have a triageStatus of LATER. + * + * @param event Eventstamp + * @param rangeStart Date + * @param rangeEnd Date + * @param timezone Timezone + * @return NoteItem + */ + public NoteItem getFirstInstanceOrModification(EventStamp event, Date rangeStart, Date rangeEnd, net.fortuna.ical4j.model.TimeZone timezone) { + NoteItem note = (NoteItem) event.getItem(); + RecurrenceExpander expander = new RecurrenceExpander(); + + InstanceList instances = expander.getOcurrences(event.getEvent(), + event.getExceptions(), new DateTime(rangeStart), new DateTime(rangeEnd), + timezone); + + // Find the first occurrence that begins after the start range + while (instances.size() > 0) { + String firstKey = (String) instances.firstKey(); + Instance instance = (Instance) instances.remove(firstKey); + if (instance.getStart().after(rangeStart)) { + if (instance.isOverridden()) { + ModificationUid modUid = new ModificationUidImpl(note, instance.getRid()); + NoteItem mod = (NoteItem) contentDao.findItemByUid(modUid.toString()); + // shouldn't happen, but log and continue if it does + if (mod == null) { + LOG.error("no modification found for uid: {}", modUid.toString()); + continue; + } + TriageStatus status = mod.getTriageStatus(); + if (status == null || status.getCode().equals(TriageStatus.CODE_LATER)) { + return mod; + } + } else { + return NoteOccurrenceUtil.createNoteOccurrence(instance.getRid(), note); + } + } + } + + return null; + } + +} diff --git a/cosmo-core/src/main/java/org/unitedinternet/cosmo/service/impl/StandardTriageStatusQueryProcessor.java b/cosmo-core/src/main/java/org/unitedinternet/cosmo/service/impl/StandardTriageStatusQueryProcessor.java index 71c1566a..74189cb7 100644 --- a/cosmo-core/src/main/java/org/unitedinternet/cosmo/service/impl/StandardTriageStatusQueryProcessor.java +++ b/cosmo-core/src/main/java/org/unitedinternet/cosmo/service/impl/StandardTriageStatusQueryProcessor.java @@ -15,96 +15,68 @@ */ package org.unitedinternet.cosmo.service.impl; -import java.time.Duration; -import java.time.temporal.TemporalAmount; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; - +import net.fortuna.ical4j.model.DateTime; +import net.fortuna.ical4j.model.TemporalAmountAdapter; +import net.fortuna.ical4j.model.TimeZone; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.unitedinternet.cosmo.calendar.Instance; -import org.unitedinternet.cosmo.calendar.InstanceList; -import org.unitedinternet.cosmo.calendar.RecurrenceExpander; import org.unitedinternet.cosmo.dao.ContentDao; -import org.unitedinternet.cosmo.model.CollectionItem; -import org.unitedinternet.cosmo.model.EventStamp; -import org.unitedinternet.cosmo.model.Item; -import org.unitedinternet.cosmo.model.ModificationUid; -import org.unitedinternet.cosmo.model.NoteItem; -import org.unitedinternet.cosmo.model.NoteItemTriageStatusComparator; -import org.unitedinternet.cosmo.model.NoteOccurrence; -import org.unitedinternet.cosmo.model.StampUtils; -import org.unitedinternet.cosmo.model.TriageStatus; -import org.unitedinternet.cosmo.model.filter.ContentItemFilter; -import org.unitedinternet.cosmo.model.filter.EventStampFilter; -import org.unitedinternet.cosmo.model.filter.ItemFilter; -import org.unitedinternet.cosmo.model.filter.NoteItemFilter; -import org.unitedinternet.cosmo.model.filter.Restrictions; -import org.unitedinternet.cosmo.model.hibernate.ModificationUidImpl; +import org.unitedinternet.cosmo.model.*; +import org.unitedinternet.cosmo.model.filter.*; import org.unitedinternet.cosmo.service.triage.TriageStatusQueryContext; import org.unitedinternet.cosmo.service.triage.TriageStatusQueryProcessor; -import org.unitedinternet.cosmo.util.NoteOccurrenceUtil; -import net.fortuna.ical4j.model.DateTime; -import net.fortuna.ical4j.model.Recur; -import net.fortuna.ical4j.model.Recur.Frequency; -import net.fortuna.ical4j.model.TemporalAmountAdapter; -import net.fortuna.ical4j.model.TimeZone; +import java.time.Duration; +import java.time.temporal.TemporalAmount; +import java.util.*; /** * Standard implementation of TriageStatusQueryProcessor that - * uses NoteItemFilters and custom logic to process a + * uses NoteItemFilters and custom logic to process a * TriageStatus query. */ @Component public class StandardTriageStatusQueryProcessor implements TriageStatusQueryProcessor { - + private static final Logger LOG = LoggerFactory.getLogger(StandardTriageStatusQueryProcessor.class); - - private static final Comparator COMPARE_ASC = new NoteItemTriageStatusComparator(false); - private static final Comparator COMPARE_DESC = new NoteItemTriageStatusComparator(true); - + @Autowired private ContentDao contentDao; - - + + public static final Comparator COMPARE_ASC = new NoteItemTriageStatusComparator(false); + public static final Comparator COMPARE_DESC = new NoteItemTriageStatusComparator(true); + + NoteTriageStatusHelper noteTriageStatusHelper = new NoteTriageStatusHelper(); + // Durations used to search forward/backward for recurring events // and used to determine time periods that events will be expanded // to determine the previous/next occurrence - + // 31 days (1 month) private TemporalAmount monthLaterDur = Duration.ofDays(31); private TemporalAmount monthDoneDur = Duration.ofDays(-31); - + // 366 days (1 year) private TemporalAmount yearLaterDur = Duration.ofDays(366); private TemporalAmount yearDoneDur = Duration.ofDays(-366); - + // number of DONE items to return private int maxDone = 25; - + /* (non-Javadoc) * @see org.unitedinternet.cosmo.service.triage.TriageStatusQueryProcessor#processTriageStatusQuery * (org.unitedinternet.cosmo.model.CollectionItem, java.lang.String, java.util.Date, * net.fortuna.ical4j.model.TimeZone) */ /** - * + * * {@inheritDoc} */ public SortedSet - processTriageStatusQuery(CollectionItem collection, - TriageStatusQueryContext context) { + processTriageStatusQuery(CollectionItem collection, + TriageStatusQueryContext context) { if (context.isAll()) { return getAll(collection, context).merge(); } @@ -121,33 +93,33 @@ else if (context.isLater()) { throw new IllegalArgumentException("invalid status: " + context.getTriageStatus()); } } - + /** - * + * * {@inheritDoc} */ public SortedSet - processTriageStatusQuery(NoteItem note, - TriageStatusQueryContext context) { + processTriageStatusQuery(NoteItem note, + TriageStatusQueryContext context) { if (context.isAll()) { - return getAll(note, context).merge(); + return noteTriageStatusHelper.getAll(note, context).merge(); } if (context.isDone()) { - return getDone(note, context).merge(); + return noteTriageStatusHelper.getDone(note, context).merge(); } else if (context.isNow()) { - return getNow(note, context).merge(); + return noteTriageStatusHelper.getNow(note, context).merge(); } else if (context.isLater()) { - return getLater(note, context).merge(); + return noteTriageStatusHelper.getLater(note, context).merge(); } else { throw new IllegalArgumentException("invalid status: " + context.getTriageStatus()); } } - + /** - * + * * @param collection CollectionItem * @param context TriageStatusQueryContext * @return QueryResult @@ -163,29 +135,12 @@ private QueryResult getAll(CollectionItem collection, return qr; } - /** - * - * @param note NoteItem - * @param context TriageStatusQueryContext - * @return QueryResult - */ - private QueryResult getAll(NoteItem note, - TriageStatusQueryContext context) { - QueryResult qr = new QueryResult(); - - qr.add(getNow(note, context)); - qr.add(getDone(note, context)); - qr.add(getLater(note, context)); - - return qr; - } - /** * NOW Query:
* - Non-recurring with no or null triage status
* - Non-recurring with triage status NOW
* - Modifications with triage status NOW
- * - Occurrences whose period overlaps the current point in time + * - Occurrences whose period overlaps the current point in time * - Modifications with triage status null and whose period * overlaps the current point in time. * @param collection CollectionItem @@ -198,28 +153,28 @@ private QueryResult getNow(CollectionItem collection, // filter for NOW triage notes NoteItemFilter nowFilter = - getTriageStatusFilter(collection, TriageStatus.CODE_NOW); - + getTriageStatusFilter(collection, TriageStatus.CODE_NOW); + // filter for no (null) triage status NoteItemFilter noTriageStatusFilter = - getTriageStatusFilter(collection, -1); + getTriageStatusFilter(collection, -1); noTriageStatusFilter.setIsModification(false); - + // recurring event filter NoteItemFilter eventFilter = - getRecurringEventFilter(collection, context.getPointInTime(), - context.getPointInTime(), - context.getTimeZone()); - + getRecurringEventFilter(collection, context.getPointInTime(), + context.getPointInTime(), + context.getTimeZone()); + // Add all non-recurring items that are have an explicit NOW triage, // modifications with NOW triage, or no triage (null triage) ItemFilter[] filters = new ItemFilter[] { - nowFilter, noTriageStatusFilter + nowFilter, noTriageStatusFilter }; for(Item item : contentDao.findItems(filters)) { NoteItem note = (NoteItem) item; EventStamp eventStamp = StampUtils.getEventStamp(note); - + // Don't add recurring events if(eventStamp==null || !eventStamp.isRecurring()) { qr.getResults().add(note); @@ -229,7 +184,7 @@ private QueryResult getNow(CollectionItem collection, } } } - + // Now process recurring events, returning only occurrences that overlap // current instant in time for(Item item: contentDao.findItems(eventFilter)) { @@ -238,7 +193,7 @@ private QueryResult getNow(CollectionItem collection, continue; } Set occurrences = - getNowFromRecurringNote(note, context); + noteTriageStatusHelper.getNowFromRecurringNote(note, context); if(occurrences.size()>0) { qr.getResults().addAll(occurrences); qr.getMasters().add(note); @@ -247,79 +202,12 @@ private QueryResult getNow(CollectionItem collection, return qr; } - - /** - * NOW Query for a specific master NoteItem:
- * - Modifications with triage status NOW
- * - Occurrences whose period overlaps the current point in time - * - Modifications with triage status null and whose period - * overlaps the current point in time. - * @param master NoteItem - * @param context TriageStatusQueryContext - * @return QueryResult - */ - private QueryResult getNow(NoteItem master, - TriageStatusQueryContext context) { - QueryResult qr = new QueryResult(); - Set mods = null; - - mods = getModificationsByTriageStatus(master, TriageStatus.CODE_NOW); - qr.getResults().addAll(mods); - - // add all occurrences that occur NOW - mods = getNowFromRecurringNote(master, context); - qr.getResults().addAll(mods); - - // add master if necessary - if (! qr.getResults().isEmpty()) { - qr.getMasters().add(master); - } - return qr; - } - - /** - * Get all instances that are occuring during a given point in time - * @param note NoteItem - * @param context TriageStatusQueryContext - * @return Set - */ - private Set - getNowFromRecurringNote(NoteItem note, - TriageStatusQueryContext context) { - EventStamp eventStamp = StampUtils.getEventStamp(note); - DateTime currentDate = new DateTime(context.getPointInTime()); - RecurrenceExpander expander = new RecurrenceExpander(); - HashSet results = new HashSet(); - - // Get all occurrences that overlap current instance in time - InstanceList occurrences = expander.getOcurrences( - eventStamp.getEvent(), eventStamp.getExceptions(), currentDate, - currentDate, context.getTimeZone()); - - for(Instance instance: (Collection) occurrences.values()) { - // Not interested in modifications - if(!instance.isOverridden()) { - // add occurrence - results.add(NoteOccurrenceUtil.createNoteOccurrence(instance.getRid(), note)); - } else { - // return modification if it has no triage-status - ModificationUid modUid = new ModificationUidImpl(note, instance.getRid()); - NoteItem mod = (NoteItem) contentDao.findItemByUid(modUid.toString()); - if(mod.getTriageStatus()==null || mod.getTriageStatus().getCode()==null) { - results.add(mod); - } - } - } - - return results; - } - /** * LATER Query:
* - Non-recurring with triage status LATER
- * - For each recurring item, either the next occurring modification - * with triage status LATER or the next occurrence, whichever occurs sooner + * - For each recurring item, either the next occurring modification + * with triage status LATER or the next occurrence, whichever occurs sooner * @param collection CollectionItem * @param context TriageStatusQueryContext * @return QueryResult @@ -328,17 +216,17 @@ private QueryResult getLater(CollectionItem collection, TriageStatusQueryContext context) { QueryResult qr = new QueryResult(false, -1); - // filter for LATER triage status + // filter for LATER triage status NoteItemFilter laterFilter = - getTriageStatusFilter(collection, TriageStatus.CODE_LATER); - - // Recurring event filter + getTriageStatusFilter(collection, TriageStatus.CODE_LATER); + + // Recurring event filter // Search for recurring events that have occurrences up to a // year from point in time NoteItemFilter eventFilter = - getRecurringEventFilter(collection, context.getPointInTime(), - new TemporalAmountAdapter(yearLaterDur).getTime(context.getPointInTime()), - context.getTimeZone()); + getRecurringEventFilter(collection, context.getPointInTime(), + new TemporalAmountAdapter(yearLaterDur).getTime(context.getPointInTime()), + context.getTimeZone()); // Add all items that are have an explicit LATER triage for(Item item : contentDao.findItems(laterFilter)) { @@ -358,7 +246,7 @@ private QueryResult getLater(CollectionItem collection, // Now process recurring events for(Item item: contentDao.findItems(eventFilter)) { NoteItem note = (NoteItem) item; - + // per bug 10623: // return all modifications for later if(note.getModifies()!=null) { @@ -366,10 +254,10 @@ private QueryResult getLater(CollectionItem collection, qr.getMasters().add(note.getModifies()); continue; } - + NoteItem laterItem = - getLaterFromRecurringNote(note, context); - + noteTriageStatusHelper.getLaterFromRecurringNote(note, context); + // add laterItem and master if present if(laterItem!=null) { qr.getResults().add(laterItem); @@ -379,65 +267,13 @@ private QueryResult getLater(CollectionItem collection, return qr; } - - /** - * LATER Query for a specific master NoteItem:
- * - the next occurring modification - * with triage status LATER or the next occurrence, whichever occurs sooner - * @param master NoteItem - * @param context TriageStatusQueryContext - * @return QueryResult - */ - private QueryResult getLater(NoteItem master, - TriageStatusQueryContext context) { - QueryResult qr = new QueryResult(false, -1); - // get the next occurring modification or occurrence - NoteItem result = getLaterFromRecurringNote(master, context); - - // add result and master if present - if(result!=null) { - qr.getMasters().add(master); - qr.getResults().add(result); - } - - // add all modifications with trigaeStatus LATER - Set mods = - getModificationsByTriageStatus(master, TriageStatus.CODE_LATER); - if(qr.getResults().addAll(mods)) { - qr.getMasters().add(master); - } - - return qr; - } - - /** - * Get the next occurrence or modification for a recurring event, whichever - * occurrs sooner relative to a point in time. - * @param note NoteItem - * @param context TriageStatusQueryContext - * @return Set - */ - private NoteItem - getLaterFromRecurringNote(NoteItem note, - TriageStatusQueryContext context) { - EventStamp eventStamp = StampUtils.getEventStamp(note); - Date currentDate = context.getPointInTime(); - Date futureDate = new TemporalAmountAdapter(getDurToUseForExpanding(eventStamp, true)).getTime(currentDate); - - // calculate the next occurrence or LATER modification - NoteItem first = getFirstInstanceOrModification(eventStamp, - currentDate, futureDate, context.getTimeZone()); - - return first; - } - /** * DONE Query:
* - Non-recurring with triage status DONE
- * - For each recurring item, either the most recently occurring + * - For each recurring item, either the most recently occurring * modification with triage status DONE or the most recent occurrence, - * whichever occurred most recently + * whichever occurred most recently * - Limit to maxDone results * @param collection CollectionItem * @param context TriageStatusQueryContext @@ -449,7 +285,7 @@ private QueryResult getDone(CollectionItem collection, // filter for DONE triage status NoteItemFilter doneFilter = - getTriageStatusFilter(collection, TriageStatus.CODE_DONE); + getTriageStatusFilter(collection, TriageStatus.CODE_DONE); // Limit the number of items with DONE status so we don't load // tons of items on the server before merging with the recurring @@ -458,21 +294,21 @@ private QueryResult getDone(CollectionItem collection, // more than maxDone items as long as they are sorted by rank. doneFilter.setMaxResults(maxDone); doneFilter.addOrderBy(ContentItemFilter.ORDER_BY_TRIAGE_STATUS_RANK_ASC); - - // Recurring event filter + + // Recurring event filter // Search for recurring events that had occurrences up to a // year from point in time NoteItemFilter eventFilter = - getRecurringEventFilter(collection, - new TemporalAmountAdapter(yearDoneDur).getTime(context.getPointInTime()), - context.getPointInTime(), - context.getTimeZone()); + getRecurringEventFilter(collection, + new TemporalAmountAdapter(yearDoneDur).getTime(context.getPointInTime()), + context.getPointInTime(), + context.getTimeZone()); // Add all items that are have an explicit DONE triage for(Item item : contentDao.findItems(doneFilter)) { NoteItem note = (NoteItem) item; EventStamp eventStamp = StampUtils.getEventStamp(note); - + // Don't add recurring events if(eventStamp==null || !eventStamp.isRecurring()) { qr.getResults().add(note); @@ -485,14 +321,14 @@ private QueryResult getDone(CollectionItem collection, if(note.getModifies()!=null) { continue; } - - NoteItem doneItem = getDoneFromRecurringNote(note, context); + + NoteItem doneItem = noteTriageStatusHelper.getDoneFromRecurringNote(note, context); // add doneItem and master if present if(doneItem!=null) { qr.getResults().add(doneItem); } } - + // add masters for all ocurrences and modifications for(NoteItem note: qr.getResults()) { if(note instanceof NoteOccurrence) { @@ -502,189 +338,17 @@ else if(note.getModifies()!=null) { qr.getMasters().add(note.getModifies()); } } - - return qr; - } - - /** - * DONE Query for a specific master NoteItem:
- * - the last occurring modification - * with triage status DONE or the last occurrence, whichever occurred - * most recently - * @param master NoteItem - * @param context TriageStatusQueryContext - * @return QueryResult - */ - private QueryResult getDone(NoteItem master, - TriageStatusQueryContext context) { - QueryResult qr = new QueryResult(); - - // get the most recently occurred modification or occurrence - NoteItem result = getDoneFromRecurringNote(master, context); - - // add result and master if present - if(result!=null) { - qr.getMasters().add(master); - qr.getResults().add(result); - } - - // add all modifications with trigaeStatus DONE - Set mods = - getModificationsByTriageStatus(master, TriageStatus.CODE_DONE); - if(qr.getResults().addAll(mods)) { - qr.getMasters().add(master); - } - + return qr; } - - /** - * Get the last occurring modification or occurrence, whichever occurred - * last. - * @param note NoteItem - * @param context TriageStatusQueryContext - * @return NoteItem - */ - private NoteItem - getDoneFromRecurringNote(NoteItem note, - TriageStatusQueryContext context) { - EventStamp eventStamp = StampUtils.getEventStamp(note); - Date currentDate = context.getPointInTime(); - Date pastDate = new TemporalAmountAdapter(getDurToUseForExpanding(eventStamp, false)).getTime(currentDate); - - // calculate the previous occurrence or modification - NoteItem latest = getLatestInstanceOrModification(eventStamp, pastDate, - currentDate, context.getTimeZone()); - - return latest; - } - - - /** - * Calculate and return the latest ocurring instance or modification for the - * specified master event and date range. - * The instance must end before the end of the range. - * If the latest instance is a modification, then the modification must - * have a triageStatus of DONE - * - * @param event Eventstamp - * @param rangeStart Date - * @param rangeEnd Date - * @param timezone Timezone - * @return NoteItem - */ - private NoteItem getLatestInstanceOrModification(EventStamp event, Date rangeStart, Date rangeEnd, - TimeZone timezone) { - NoteItem note = (NoteItem) event.getItem(); - RecurrenceExpander expander = new RecurrenceExpander(); - - InstanceList instances = expander.getOcurrences(event.getEvent(), event.getExceptions(), - new DateTime(rangeStart), new DateTime(rangeEnd), timezone); - - // Find the latest occurrence that ends before the end of the range - while (instances.size() > 0) { - String lastKey = (String) instances.lastKey(); - Instance instance = (Instance) instances.remove(lastKey); - if (instance.getEnd().before(rangeEnd)) { - if(instance.isOverridden()) { - ModificationUid modUid = new ModificationUidImpl(note, instance.getRid()); - NoteItem mod = (NoteItem) contentDao.findItemByUid(modUid.toString()); - // shouldn't happen, but log and continue if it does - if(mod==null) { - LOG.error("no modification found for uid: {}", modUid.toString()); - continue; - } - TriageStatus status = mod.getTriageStatus(); - if(status==null || status.getCode().equals(TriageStatus.CODE_DONE)) { - return mod; - } - } else { - return NoteOccurrenceUtil.createNoteOccurrence(instance.getRid(), note); - } - } - - } - return null; - } - - - /** - * Calculate and return the first ocurring instance or modification - * for the specified master event and date range. - * The instance must begin after the start of the range and if it - * is a modification it must have a triageStatus of LATER. - * - * @param event Eventstamp - * @param rangeStart Date - * @param rangeEnd Date - * @param timezone Timezone - * @return NoteItem - */ - private NoteItem getFirstInstanceOrModification(EventStamp event, Date rangeStart, Date rangeEnd, TimeZone timezone) { - NoteItem note = (NoteItem) event.getItem(); - RecurrenceExpander expander = new RecurrenceExpander(); - - InstanceList instances = expander.getOcurrences(event.getEvent(), - event.getExceptions(), new DateTime(rangeStart), new DateTime(rangeEnd), - timezone ); - - // Find the first occurrence that begins after the start range - while(instances.size()>0) { - String firstKey = (String) instances.firstKey(); - Instance instance = (Instance) instances.remove(firstKey); - if(instance.getStart().after(rangeStart)) { - if(instance.isOverridden()) { - ModificationUid modUid = new ModificationUidImpl(note, instance.getRid()); - NoteItem mod = (NoteItem) contentDao.findItemByUid(modUid.toString()); - // shouldn't happen, but log and continue if it does - if(mod==null) { - LOG.error("no modification found for uid: {}", modUid.toString()); - continue; - } - TriageStatus status = mod.getTriageStatus(); - if(status==null || status.getCode().equals(TriageStatus.CODE_LATER)) { - return mod; - } - } else { - return NoteOccurrenceUtil.createNoteOccurrence(instance.getRid(), note); - } - } - } - - return null; - } - - /** - * - * @param master NoteItem - * @param triageStatus Integer - * @return Set - */ - private Set getModificationsByTriageStatus(NoteItem master, Integer triageStatus) { - - HashSet mods = new HashSet(); - - for(NoteItem mod: master.getModifications()) { - if (mod.getTriageStatus() == null - || mod.getTriageStatus().getCode() == null - || mod.getTriageStatus().getCode().equals(triageStatus)) { - continue; - } - - mods.add(mod); - } - - return mods; - } - /** * Create NoteItemFilter that matches a parent collection and a specific * TriageStatus code. The filter matches only master events (no modifications). - * + * * @param collection CollectionItem * @param code int - * @return NoteItemFilter + * @return NoteItemFilter */ private NoteItemFilter getTriageStatusFilter(CollectionItem collection, int code) { NoteItemFilter triageStatusFilter = new NoteItemFilter(); @@ -697,17 +361,17 @@ private NoteItemFilter getTriageStatusFilter(CollectionItem collection, int code } return triageStatusFilter; } - - + + /** * Create NoteItemFilter that matches all recurring event NoteItems that belong * to a specified parent collection. - * + * * @param collection CollectionItem * @param start Date * @param end Date * @param timezone Timezone - * @return NoteItemFiler + * @return NoteItemFiler */ private NoteItemFilter getRecurringEventFilter(CollectionItem collection, Date start, Date end, TimeZone timezone) { NoteItemFilter eventNoteFilter = new NoteItemFilter(); @@ -720,33 +384,6 @@ private NoteItemFilter getRecurringEventFilter(CollectionItem collection, Date s eventNoteFilter.getStampFilters().add(eventFilter); return eventNoteFilter; } - /** - * - * @param es EventStamp - * @param later boolean - * @return Dur - */ - private TemporalAmount getDurToUseForExpanding(EventStamp es, boolean later) { - List rules = es.getRecurrenceRules(); - - // No rules, assume RDATEs so expand a year - if(rules.size()==0) { - return later ? yearLaterDur : yearDoneDur; - } - - // Look at first rule only - Recur recur = rules.get(0); - - // If rule is yearly or monthly then expand a year, - // otherwise only expand a month - if(Frequency.YEARLY.equals(recur.getFrequency()) || - Frequency.MONTHLY.equals(recur.getFrequency())) { - return later ? yearLaterDur : yearDoneDur; - } - else { - return later ? monthLaterDur : monthDoneDur; - } - } public void setContentDao(ContentDao contentDao) { this.contentDao = contentDao; @@ -756,23 +393,23 @@ public void setMaxDone(int maxDone) { this.maxDone = maxDone; } - private static class QueryResult { + + public static class QueryResult { private ArrayList results = new ArrayList(); private HashSet masters = new HashSet(); private Comparator comparator; private int limit; - + /** - * + * */ public QueryResult() { this(true, -1); } /** - * - * @param ascending boolean - * @param limit int + * @param ascending boolean + * @param limit int */ public QueryResult(boolean ascending, int limit) { results = new ArrayList(); @@ -784,39 +421,38 @@ public QueryResult(boolean ascending, int limit) { public ArrayList getResults() { return results; } - + /** - * + * */ public void processResults() { - + // sort Collections.sort(results, comparator); // trim based on limit - if(limit!=-1 && results.size() > limit) { - while(results.size() > limit) { - results.remove(results.size()-1); + if (limit != -1 && results.size() > limit) { + while (results.size() > limit) { + results.remove(results.size() - 1); } - + // rebuild masters list as it may have changed masters.clear(); - for(NoteItem note: results) { - if(note instanceof NoteOccurrence) { + for (NoteItem note : results) { + if (note instanceof NoteOccurrence) { masters.add(((NoteOccurrence) note).getMasterNote()); - } - else if(note.getModifies()!=null) { + } else if (note.getModifies() != null) { masters.add(note.getModifies()); } } } } - + public HashSet getMasters() { return masters; } + /** - * * @param qr QueryResult */ public void add(QueryResult qr) { @@ -826,11 +462,10 @@ public void add(QueryResult qr) { } /** - * * @return SortedSet */ public SortedSet merge() { - + TreeSet merged = new TreeSet(comparator); merged.addAll(results); merged.addAll(masters); @@ -838,4 +473,5 @@ public SortedSet merge() { return merged; } } + } diff --git a/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/calendar/query/CalendarFilterEvaluaterTest.java b/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/calendar/query/CalendarFilterEvaluaterTest.java index 775c6617..c3708d17 100644 --- a/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/calendar/query/CalendarFilterEvaluaterTest.java +++ b/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/calendar/query/CalendarFilterEvaluaterTest.java @@ -75,27 +75,27 @@ public void testEvaluateFilterPropFilter() throws Exception { propFilter.setTextMatchFilter(textFilter); eventFilter.getPropFilters().add(propFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); textFilter.setValue("ViSiBle"); textFilter.setCollation(TextMatchFilter.COLLATION_OCTET); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); textFilter.setCollation(null); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); textFilter.setValue("XXX"); textFilter.setNegateCondition(true); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); propFilter.setTextMatchFilter(null); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); propFilter.setName("RRULE"); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); propFilter.setIsNotDefinedFilter(new IsNotDefinedFilter()); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -120,22 +120,22 @@ public void testEvaluateFilterParamFilter() throws Exception { propFilter.getParamFilters().add(paramFilter); eventFilter.getPropFilters().add(propFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); textFilter.setValue("XXX"); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); textFilter.setNegateCondition(true); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); paramFilter.setTextMatchFilter(null); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); paramFilter.setName("BOGUS"); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); paramFilter.setIsNotDefinedFilter(new IsNotDefinedFilter()); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -162,12 +162,12 @@ public void testEvaluateFilterEventTimeRangeFilter() throws Exception { eventFilter.setTimeRangeFilter(timeRangeFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); start = new DateTime("20050818T115000Z"); period = new Period(start, end); timeRangeFilter.setPeriod(period); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -194,12 +194,12 @@ public void testEvaluateFilterRecurringEventTimeRangeFilter() throws Exception { eventFilter.setTimeRangeFilter(timeRangeFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); start = new DateTime("20070515T205000Z"); period = new Period(start, end); timeRangeFilter.setPeriod(period); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -228,12 +228,12 @@ public void testEvaluateFilterPropertyTimeRangeFilter() throws Exception { propFilter.setTimeRangeFilter(timeRangeFilter); eventFilter.getPropFilters().add(propFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); start = new DateTime("20060717T115000Z"); period = new Period(start, end); timeRangeFilter.setPeriod(period); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -277,11 +277,11 @@ public void testEvaluateComplicated() throws Exception { eventFilter.getPropFilters().add(propFilter2); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); // change one thing paramFilter2.setName("XXX"); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -309,13 +309,13 @@ public void testEvaluateVAlarmFilter() throws Exception { eventFilter.getComponentFilters().add(alarmFilter); alarmFilter.getPropFilters().add(propFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); textMatch.setValue("EMAIL"); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); alarmFilter.getPropFilters().clear(); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); // time-range filter on VALARM @@ -326,32 +326,32 @@ public void testEvaluateVAlarmFilter() throws Exception { Period period = new Period(start, end); TimeRangeFilter timeRangeFilter = new TimeRangeFilter(period); alarmFilter.setTimeRangeFilter(timeRangeFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); // find alarm relative to end start = new DateTime("20060101T050000Z"); end = new DateTime("20060101T190000Z"); period = new Period(start, end); timeRangeFilter.setPeriod(period); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); // find absolute repeating alarm start = new DateTime("20051230T050000Z"); end = new DateTime("20051230T080000Z"); period = new Period(start, end); timeRangeFilter.setPeriod(period); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); // find no alarms start = new DateTime("20060101T020000Z"); end = new DateTime("20060101T030000Z"); period = new Period(start, end); timeRangeFilter.setPeriod(period); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); alarmFilter.setTimeRangeFilter(null); alarmFilter.setIsNotDefinedFilter(new IsNotDefinedFilter()); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -372,7 +372,7 @@ public void testEvaluateFilterPropFilterAgainstException() throws Exception { PropertyFilter propFilter = new PropertyFilter("DESCRIPTION"); eventFilter.getPropFilters().add(propFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -392,17 +392,17 @@ public void testEvaluateVJournalFilterPropFilter() throws Exception { filter.setFilter(compFilter); compFilter.getComponentFilters().add(eventFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); PropertyFilter propFilter = new PropertyFilter("SUMMARY"); TextMatchFilter textFilter = new TextMatchFilter("Staff"); propFilter.setTextMatchFilter(textFilter); eventFilter.getPropFilters().add(propFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); textFilter.setValue("bogus"); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -422,17 +422,17 @@ public void testEvaluateVToDoFilterPropFilter() throws Exception { filter.setFilter(compFilter); compFilter.getComponentFilters().add(eventFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); PropertyFilter propFilter = new PropertyFilter("SUMMARY"); TextMatchFilter textFilter = new TextMatchFilter("Income"); propFilter.setTextMatchFilter(textFilter); eventFilter.getPropFilters().add(propFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); textFilter.setValue("bogus"); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -460,24 +460,24 @@ public void testEvaluateVToDoTimeRangeFilter() throws Exception { TimeRangeFilter timeRangeFilter = new TimeRangeFilter(period); vtodoFilter.setTimeRangeFilter(timeRangeFilter); - assertTrue(evaluater.evaluate(calendar1, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar1, filter)); // Verify VTODO that has DTSTART doesn't match start = new DateTime("19970420T133000Z"); end = new DateTime("19970421T133000Z"); period = new Period(start, end); timeRangeFilter.setPeriod(period); - assertFalse(evaluater.evaluate(calendar1, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar1, filter)); // Verify VTODO that has DUE doesn't match - assertFalse(evaluater.evaluate(calendar2, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar2, filter)); // Verify VTODO that has DUE matches start = new DateTime("20080401T133000Z"); end = new DateTime("20080421T133000Z"); period = new Period(start, end); timeRangeFilter.setPeriod(period); - assertTrue(evaluater.evaluate(calendar2, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar2, filter)); } /** @@ -496,17 +496,17 @@ public void testEvaluateVFreeBusyFilterFilter() throws Exception { filter.setFilter(compFilter); compFilter.getComponentFilters().add(vfbFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); PropertyFilter propFilter = new PropertyFilter("ORGANIZER"); TextMatchFilter textFilter = new TextMatchFilter("Joe"); propFilter.setTextMatchFilter(textFilter); vfbFilter.getPropFilters().add(propFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); textFilter.setValue("bogus"); - assertFalse(evaluater.evaluate(calendar, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar, filter)); } /** @@ -533,8 +533,8 @@ public void testEvaluateVFreeBusyFilterFilterTimeRange() throws Exception { TimeRangeFilter timeRangeFilter = new TimeRangeFilter(period); vfbFilter.setTimeRangeFilter(timeRangeFilter); - assertTrue(evaluater.evaluate(calendar1, filter)); - assertTrue(evaluater.evaluate(calendar2, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar1, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar2, filter)); start = new DateTime("20070102T115000Z"); end = new DateTime("20070109T115000Z"); @@ -542,8 +542,8 @@ public void testEvaluateVFreeBusyFilterFilterTimeRange() throws Exception { period = new Period(start, end); timeRangeFilter.setPeriod(period); - assertFalse(evaluater.evaluate(calendar1, filter)); - assertFalse(evaluater.evaluate(calendar2, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar1, filter)); + assertFalse(evaluater.evaluateCalendarFilter(calendar2, filter)); } @@ -563,7 +563,7 @@ public void testEvaluateVAvailabilityFilter() throws Exception { filter.setFilter(compFilter); compFilter.getComponentFilters().add(vfbFilter); - assertTrue(evaluater.evaluate(calendar, filter)); + assertTrue(evaluater.evaluateCalendarFilter(calendar, filter)); } /** diff --git a/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/dao/mock/MockCalendarDao.java b/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/dao/mock/MockCalendarDao.java index 85ca46aa..ea016add 100755 --- a/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/dao/mock/MockCalendarDao.java +++ b/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/dao/mock/MockCalendarDao.java @@ -90,7 +90,7 @@ public Set findCalendarItems(CollectionItem collection, Calendar calendar = new EntityConverter(null).convertContent(content); if(calendar!=null) { - if (evaluater.evaluate(calendar, filter) == true) { + if (evaluater.evaluateCalendarFilter(calendar, filter) == true) { results.add(content); } } diff --git a/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/model/filter/ItemFilterEvaluater.java b/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/model/filter/ItemFilterEvaluater.java index a6266851..4dc2b4dc 100644 --- a/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/model/filter/ItemFilterEvaluater.java +++ b/cosmo-core/src/test/unit/java/org/unitedinternet/cosmo/model/filter/ItemFilterEvaluater.java @@ -37,7 +37,7 @@ * Provides api for determining if item matches given filter. */ public class ItemFilterEvaluater { - + /** * Evaluate. * @param item The item. @@ -45,39 +45,47 @@ public class ItemFilterEvaluater { * @return boolean. */ public boolean evaulate(Item item, ItemFilter filter) { - + + + FilterEval filterEval = filter.judgeItemFilter(filter); + if(item==null || filter==null) { return false; } - - if(filter.getParent()!=null) { - if(!item.getParents().contains(filter.getParent())) { - return false; - } - } - - if(filter instanceof NoteItemFilter) { - if(!handleNoteItemFilter((NoteItemFilter) filter, item)) { - return false; - } - } - - if(filter instanceof ContentItemFilter) { - if(!handleContentItemFilter((ContentItemFilter) filter, item)) { - return false; - } - } - - if(filter.getDisplayName()!=null) { - if(!handleFilterCriteria(item.getDisplayName(), filter.getDisplayName())) { - return false; - } - } - - if(filter.getUid()!=null) { - if(!handleFilterCriteria(item.getUid(), filter.getUid())) { - return false; - } + + + switch (filterEval){ + case FILTER_PARENT_NOTNULL: + if(!item.getParents().contains(filter.getParent())) { + return false; + } + break; + + case INSTANCE_OF_NOTE_ITEM_FILTER: + if(!handleNoteItemFilter((NoteItemFilter) filter, item)) { + return false; + } + break; + + case INSTANCE_OF_CONTENT_ITEM_FILTER: + if(!handleContentItemFilter((ContentItemFilter) filter, item)) { + return false; + } + break; + + case FILTER_DISPLAY_NAME_NOT_NULL: + if(!handleFilterCriteria(item.getDisplayName(), filter.getDisplayName())) { + return false; + } + break; + + case FILTER_UID_NOT_NULL: + if(!handleFilterCriteria(item.getUid(), filter.getUid())) { + return false; + } + break; + + } for(AttributeFilter af: filter.getAttributeFilters()) { @@ -360,7 +368,7 @@ else if(!esf.getIsRecurring().booleanValue() && es.isRecurring()) { CalendarFilter cf = getCalendarFilter(esf); CalendarFilterEvaluater cfe = new CalendarFilterEvaluater(); - if(cfe.evaluate(cal, cf)==false) { + if(cfe.evaluateCalendarFilter(cal, cf)==false) { return false; }