SchedulerServiceImpl extends AbstractIndexProducer implements SchedulerService, ManagedService { @Override public Map<String, Period> addMultipleEvents(RRule rRule, Date start, Date end, Long duration, TimeZone tz, String captureAgentId, Set<String> userIds, MediaPackage templateMp, Map<String, String> wfProperties, Map<String, String> caMetadata, Opt<String> schedulingSource) throws UnauthorizedException, SchedulerConflictException, SchedulerException { Util.adjustRrule(rRule, start, tz); List<Period> periods = Util.calculatePeriods(start, end, duration, rRule, tz); if (periods.isEmpty()) { return Collections.emptyMap(); } return addMultipleEventInternal(periods, captureAgentId, userIds, templateMp, wfProperties, caMetadata, schedulingSource); }  void setMessageSender(MessageSender messageSender); void setMessageReceiver(MessageReceiver messageReceiver); void setPersistence(SchedulerServiceDatabase persistence); void setSeriesService(SeriesService seriesService); void setSecurityService(SecurityService securityService); void setAssetManager(AssetManager assetManager); void setWorkspace(Workspace workspace); void setAuthorizationService(AuthorizationService authorizationService); void setOrgDirectoryService(OrganizationDirectoryService orgDirectoryService); void addCatalogUIAdapter(EventCatalogUIAdapter catalogUIAdapter); void removeCatalogUIAdapter(EventCatalogUIAdapter catalogUIAdapter); void activate(ComponentContext cc); @Override void deactivate(); @Override void updated(Dictionary<String, ?> properties); @Override void addEvent(Date startDateTime, Date endDateTime, String captureAgentId, Set<String> userIds,
          MediaPackage mediaPackage, Map<String, String> wfProperties, Map<String, String> caMetadata,
          Opt<String> schedulingSource); @Override Map<String, Period> addMultipleEvents(RRule rRule, Date start, Date end, Long duration, TimeZone tz,
          String captureAgentId, Set<String> userIds, MediaPackage templateMp, Map<String, String> wfProperties,
          Map<String, String> caMetadata, Opt<String> schedulingSource); @Override void updateEvent(final String mpId, Opt<Date> startDateTime, Opt<Date> endDateTime, Opt<String> captureAgentId,
          Opt<Set<String>> userIds, Opt<MediaPackage> mediaPackage, Opt<Map<String, String>> wfProperties,
          Opt<Map<String, String>> caMetadata); @Override void updateEvent(final String mpId, Opt<Date> startDateTime, Opt<Date> endDateTime, Opt<String> captureAgentId,
          Opt<Set<String>> userIds, Opt<MediaPackage> mediaPackage, Opt<Map<String, String>> wfProperties,
          Opt<Map<String, String>> caMetadata, boolean allowConflict); @Override synchronized void removeEvent(String mediaPackageId); @Override MediaPackage getMediaPackage(String mediaPackageId); @Override DublinCoreCatalog getDublinCore(String mediaPackageId); @Override TechnicalMetadata getTechnicalMetadata(String mediaPackageId); @Override Map<String, String> getWorkflowConfig(String mediaPackageId); @Override Map<String, String> getCaptureAgentConfiguration(String mediaPackageId); @Override int getEventCount(); @Override List<MediaPackage> search(Opt<String> captureAgentId, Opt<Date> startsFrom, Opt<Date> startsTo,
          Opt<Date> endFrom, Opt<Date> endTo); @Override Opt<MediaPackage> getCurrentRecording(String captureAgentId); @Override Opt<MediaPackage> getUpcomingRecording(String captureAgentId); @Override List<MediaPackage> findConflictingEvents(String captureDeviceID, Date startDate, Date endDate); @Override List<MediaPackage> findConflictingEvents(String captureAgentId, RRule rrule, Date start, Date end,
          long duration, TimeZone tz); @Override String getCalendar(Opt<String> captureAgentId, Opt<String> seriesId, Opt<Date> cutoff); @Override String getScheduleLastModified(String captureAgentId); @Override void removeScheduledRecordingsBeforeBuffer(long buffer); @Override boolean updateRecordingState(String id, String state); @Override Recording getRecordingState(String id); @Override void removeRecording(String id); @Override Map<String, Recording> getKnownRecordings(); @Override void repopulate(final String indexName); @Override MessageReceiver getMessageReceiver(); @Override Service getService(); @Override String getClassName(); @Override MessageSender getMessageSender(); @Override SecurityService getSecurityService(); @Override String getSystemUserName(); static final String WORKFLOW_CONFIG_PREFIX; }
@Test public void testAddMultipleEventsEmptyRange() throws Exception { final RRule rrule = new RRule("FREQ=WEEKLY;BYDAY=WE;BYHOUR=7;BYMINUTE=0"); final Date start = new Date(1546844400000L); final Date end = start; final Long duration = 6900000L; final TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); final String captureAgentId = "Device A"; final Set<String> userIds = Collections.emptySet(); final String id = "Recording1"; final String seriesId = "TestSeries"; final MediaPackage mpTemplate = generateEvent(Opt.some(id)); mpTemplate.setSeries(seriesId); final DublinCoreCatalog dublinCoreCatalog = generateEvent(captureAgentId, Opt.some(mpTemplate.getIdentifier().toString()), Opt.some("Test Title"), start, end); addDublinCore(Opt.some(mpTemplate.getIdentifier().toString()), mpTemplate, dublinCoreCatalog); final Map<String, String> wfProperties = this.wfProperties; final Map<String, String> caProperties = Collections.singletonMap("foo", "bar"); final Opt<String> schedulingSource = Opt.none(); final Map<String, Period> scheduled = schedSvc.addMultipleEvents( rrule, start, end, duration, tz, captureAgentId, userIds, mpTemplate, wfProperties, caProperties, schedulingSource ); assertTrue(scheduled.isEmpty()); }
@Test public void testAddMultipleEvents() throws Exception { final RRule rrule = new RRule("FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYHOUR=7;BYMINUTE=0"); final Date start = new Date(1546844400000L); final Date end = new Date(1570953300000L); final Long duration = 6900000L; final TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); final String captureAgentId = "Device A"; final Set<String> userIds = Collections.emptySet(); final String id = "Recording1"; final String seriesId = "TestSeries"; final MediaPackage mpTemplate = generateEvent(Opt.some(id)); mpTemplate.setSeries(seriesId); final DublinCoreCatalog dublinCoreCatalog = generateEvent(captureAgentId, Opt.some(mpTemplate.getIdentifier().toString()), Opt.some("Test Title"), start, end); addDublinCore(Opt.some(mpTemplate.getIdentifier().toString()), mpTemplate, dublinCoreCatalog); final Map<String, String> wfProperties = this.wfProperties; final Map<String, String> caProperties = Collections.singletonMap("foo", "bar"); final Opt<String> schedulingSource = Opt.none(); assertEquals("mod0", schedSvc.getScheduleLastModified(captureAgentId)); final Map<String, Period> scheduled = schedSvc.addMultipleEvents( rrule, start, end, duration, tz, captureAgentId, userIds, mpTemplate, wfProperties, caProperties, schedulingSource ); final int expectedEventCount = rrule.getRecur().getDates( new net.fortuna.ical4j.model.Date(start), new net.fortuna.ical4j.model.Date(end), Value.DATE ).size(); assertEquals(expectedEventCount, scheduled.keySet().size()); final String randomMpId = scheduled.keySet().stream().findAny().orElseThrow(() -> new RuntimeException("This should never happen")); final Period period = scheduled.get(randomMpId); final MediaPackage mediaPackage = schedSvc.getMediaPackage(randomMpId); final DublinCoreCatalog eventLoaded = schedSvc.getDublinCore(randomMpId); final TechnicalMetadata technicalMetadata = schedSvc.getTechnicalMetadata(randomMpId); assertEquals(seriesId, mediaPackage.getSeries()); assertTrue(eventLoaded.getFirst(PROPERTY_TITLE).startsWith(dublinCoreCatalog.getFirst(PROPERTY_TITLE))); assertEquals(randomMpId, technicalMetadata.getEventId()); assertEquals(captureAgentId, technicalMetadata.getAgentId()); assertEquals(new Date(period.getStart().getTime()), technicalMetadata.getStartDate()); assertEquals(new Date(period.getEnd().getTime()), technicalMetadata.getEndDate()); assertEquals(userIds, technicalMetadata.getPresenters()); assertTrue(technicalMetadata.getRecording().isNone()); assertTrue(technicalMetadata.getCaptureAgentConfiguration().size() >= caProperties.size()); assertEquals(wfProperties, new HashMap<>(schedSvc.getWorkflowConfig(randomMpId))); String lastModified = schedSvc.getScheduleLastModified(captureAgentId); assertNotEquals("mod0", lastModified); assertTrue(schedSvc.getCaptureAgentConfiguration(randomMpId).size() >= caProperties.size()); }
@Test(expected = SchedulerConflictException.class) public void testAddMultipleEventsConflict() throws Exception { for (int i = 0; i < 2; i++) { final RRule rrule = new RRule("FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYHOUR=7;BYMINUTE=30"); final Date start = new Date(1546844400000L); final Date end = new Date(1570953300000L); final Long duration = 6900000L; final TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); final String captureAgentId = "Device A"; final Set<String> userIds = Collections.emptySet(); final String id = "Recording" + i; final MediaPackage mpTemplate = generateEvent(Opt.some(id)); final DublinCoreCatalog dublinCoreCatalog = generateEvent(captureAgentId, Opt.some(mpTemplate.getIdentifier().toString()), Opt.some("Test Title"), start, end); addDublinCore(Opt.some(mpTemplate.getIdentifier().toString()), mpTemplate, dublinCoreCatalog); final Map<String, String> wfProperties = this.wfProperties; final Map<String, String> caProperties = Collections.singletonMap("foo", "bar"); final Opt<String> schedulingSource = Opt.none(); final Map<String, Period> scheduled = schedSvc.addMultipleEvents( rrule, start, end, duration, tz, captureAgentId, userIds, mpTemplate, wfProperties, caProperties, schedulingSource ); } }