public void installIntents(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
        // If no any Intents to be uninstalled or installed, ignore it.
        if (!toUninstall.isPresent() && !toInstall.isPresent()) {
            return;
        }

        // Classify installable Intents to different installers.
        ArrayListMultimap<IntentInstaller, Intent> uninstallInstallers;
        ArrayListMultimap<IntentInstaller, Intent> installInstallers;
        Set<IntentInstaller> allInstallers = Sets.newHashSet();

        if (toUninstall.isPresent()) {
            uninstallInstallers = getInstallers(toUninstall.get());
            allInstallers.addAll(uninstallInstallers.keySet());
        } else {
            uninstallInstallers = ArrayListMultimap.create();
        }

        if (toInstall.isPresent()) {
            installInstallers = getInstallers(toInstall.get());
            allInstallers.addAll(installInstallers.keySet());
        } else {
            installInstallers = ArrayListMultimap.create();
        }

        // Generates an installation context for the high level Intent.
        IntentInstallationContext installationContext =
                new IntentInstallationContext(toUninstall.orElse(null), toInstall.orElse(null));

        //Generates different operation context for different installable Intents.
        Map<IntentInstaller, IntentOperationContext> contexts = Maps.newHashMap();
        allInstallers.forEach(installer -> {
            List<Intent> intentsToUninstall = uninstallInstallers.get(installer);
            List<Intent> intentsToInstall = installInstallers.get(installer);

            // Connect context to high level installation context
            IntentOperationContext context =
                    new IntentOperationContext(intentsToUninstall, intentsToInstall,
                                               installationContext);
            installationContext.addPendingContext(context);
            contexts.put(installer, context);
        });

        // Apply contexts to installers
        contexts.forEach((installer, context) -> {
            installer.apply(context);
        });
    }
@Test
    public void testUninstallAndInstallIntent() {
        IntentData toUninstall = new IntentData(createTestIntent(),
                                                IntentState.INSTALLED,
                                                new WallClockTimestamp());
        IntentData toInstall = new IntentData(createTestIntent(),
                                                IntentState.INSTALLING,
                                                new WallClockTimestamp());
        List<Intent> intentsToUninstall = Lists.newArrayList();
        List<Intent> intentsToInstall = Lists.newArrayList();

        IntStream.range(0, 10).forEach(val -> {
            intentsToUninstall.add(new TestInstallableIntent(val));
        });

        IntStream.range(10, 20).forEach(val -> {
            intentsToInstall.add(new TestInstallableIntent(val));
        });

        toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
        toInstall = IntentData.compiled(toInstall, intentsToInstall);

        installCoordinator.installIntents(Optional.of(toUninstall), Optional.of(toInstall));
        Intent toInstallIntent = toInstall.intent();

        TestTools.assertAfter(INSTALL_DELAY, INSTALL_DURATION, () -> {
            IntentData newData = intentStore.newData;
            assertEquals(toInstallIntent, newData.intent());
            assertEquals(IntentState.INSTALLED, newData.state());
            assertEquals(intentsToInstall, newData.installables());
        });
    }