AutomationEngine { @NonNull public PendingResult<Boolean> editSchedule(@NonNull final String scheduleId, @NonNull final ScheduleEdits<? extends ScheduleData> edits) { final PendingResult<Boolean> pendingResult = new PendingResult<>(); backgroundHandler.post(new Runnable() { @Override public void run() { FullSchedule entry = dao.getSchedule(scheduleId); if (entry == null) { Logger.error("AutomationEngine - Schedule no longer exists. Unable to edit: %s", scheduleId); pendingResult.setResult(false); return; } applyEdits(entry, edits); boolean subscribeForStateChanges = false; long stateChangeTimeStamp = -1; boolean isOverLimit = isOverLimit(entry); boolean isExpired = isExpired(entry); if (entry.schedule.executionState == ScheduleState.FINISHED && !isOverLimit && !isExpired) { subscribeForStateChanges = true; stateChangeTimeStamp = entry.schedule.executionStateChangeDate; updateExecutionState(entry, ScheduleState.IDLE); } else if (entry.schedule.executionState != ScheduleState.FINISHED && (isOverLimit || isExpired)) { updateExecutionState(entry, ScheduleState.FINISHED); if (isOverLimit) { notifyScheduleLimitReached(entry); } else { notifyExpiredSchedules(Collections.singleton(entry)); } } dao.update(entry); if (subscribeForStateChanges) { subscribeStateObservables(entry, stateChangeTimeStamp); } Logger.verbose("AutomationEngine - Updated schedule: %s", scheduleId); pendingResult.setResult(true); } }); return pendingResult; } AutomationEngine(@NonNull Context context,
                     @NonNull AirshipRuntimeConfig runtimeConfig,
                     @NonNull Analytics analytics,
                     @NonNull PreferenceDataStore dataStore); @VisibleForTesting  AutomationEngine(@NonNull Analytics analytics,
                     @NonNull ActivityMonitor activityMonitor,
                     @NonNull OperationScheduler scheduler,
                     @NonNull AutomationDao dao,
                     @NonNull LegacyDataMigrator legacyDataMigrator); void start(@NonNull AutomationDriver driver); void setPaused(boolean isPaused); void stop(); @NonNull PendingResult<Boolean> schedule(@NonNull final Schedule<? extends ScheduleData> schedule); @NonNull PendingResult<Boolean> schedule(@NonNull final List<Schedule<? extends ScheduleData>> schedules); @NonNull PendingResult<Boolean> cancel(@NonNull final Collection<String> ids); @NonNull PendingResult<Boolean> cancelByType(@NonNull @Schedule.Type final String type); @NonNull PendingResult<Boolean> cancelGroup(@NonNull final String group); @NonNull PendingResult<Void> cancelGroups(@NonNull final Collection<String> groups); @NonNull PendingResult<Void> cancelAll(); @NonNull PendingResult<Collection<Schedule<T>>> getSchedulesByType(@Schedule.Type final String type); @NonNull PendingResult<Schedule<T>> getSchedule(@NonNull final String scheduleId, @Schedule.Type final String type); @NonNull PendingResult<Collection<Schedule<? extends ScheduleData>>> getSchedules(@NonNull final Set<String> scheduleIds); @NonNull PendingResult<Collection<Schedule<T>>> getSchedules(@NonNull final String group, @NonNull @Schedule.Type final String type); @NonNull PendingResult<Boolean> editSchedule(@NonNull final String scheduleId, @NonNull final ScheduleEdits<? extends ScheduleData> edits); void checkPendingSchedules(); @NonNull PendingResult<Collection<Schedule<? extends ScheduleData>>> getSchedules(); void setScheduleListener(@Nullable ScheduleListener scheduleListener); void applyEdits(@NonNull FullSchedule entry, @NonNull ScheduleEdits edits);  }
@Test public void testEditSchedule() throws Exception { final Schedule<Actions> schedule = Schedule.newBuilder(this.schedule) .setEditGracePeriod(100, TimeUnit.SECONDS) .build(); schedule(schedule); CustomEvent.newBuilder("event") .build() .track(); runLooperTasks(); driver.prepareCallbackMap.get(schedule.getId()) .onFinish(AutomationDriver.PREPARE_RESULT_CONTINUE); runLooperTasks(); driver.executionCallbackMap.get(schedule.getId()).onFinish(); runLooperTasks(); verifyState(this.schedule, ScheduleState.FINISHED); long end = System.currentTimeMillis() + 1000 * 60 * 60 * 24; final ScheduleEdits<Actions> edits = ScheduleEdits.newBuilder(new Actions(JsonMap.newBuilder() .put("another_action", "COOL") .build())) .setLimit(2) .setStart(10) .setEnd(end) .setPriority(300) .build(); Future<Boolean> future = automationEngine.editSchedule(schedule.getId(), edits); runLooperTasks(); assertEquals(Boolean.TRUE, future.get()); Future<Schedule<Actions>> updatedFuture = automationEngine.getSchedule(schedule.getId(), Schedule.TYPE_ACTION); runLooperTasks(); Schedule<Actions> updated = updatedFuture.get(); verifyState(this.schedule, ScheduleState.IDLE); assertEquals(edits.getLimit().intValue(), updated.getLimit()); assertEquals(edits.getStart().longValue(), updated.getStart()); assertEquals(edits.getEnd().longValue(), updated.getEnd()); assertEquals(edits.getPriority().intValue(), updated.getPriority()); assertEquals("COOL", updated.getData().getActionsMap().get("another_action").getString()); }