class LaunchingRepositoryBuildVisitor extends AbstractRepositoryBuildVisitor {

  @Override
  protected void visitLaunching(RepositoryBuild build) throws Exception {
    LOG.info("Going to enqueue module builds for repository build {}", build.getId().get());

    final Set<Module> activeModules = filterActive(moduleService.getByBranch(build.getBranchId()));

    // 1. Check for malformed files
    if (!malformedFileService.getMalformedFiles(build.getBranchId()).isEmpty()) {
      failBranchAndModuleBuilds(build, activeModules);
      return;
    }

    // 2. Check for buildable modules
    if (activeModules.isEmpty()) {
      LOG.info("No active modules to build in branch {} - failing build", build.getId().get());
      repositoryBuildService.fail(build);
      return;
    }

    final Optional<Long> interProjectBuildId;
    final Set<Module> toBuild;

    // 3. The modules we choose to build depends on if this is an InterProject build or not
    //    If this is an InterProject build we enqueue one of those as well.
    if (build.getBuildOptions().getBuildDownstreams() == BuildDownstreams.INTER_PROJECT) {
      toBuild = determineModulesToBuildUsingInterProjectBuildGraph(build, activeModules);
      InterProjectBuild ipb = InterProjectBuild.getQueuedBuild(ImmutableSet.copyOf(getIds(toBuild)), build.getBuildTrigger());
      interProjectBuildId = Optional.of(interProjectBuildService.enqueue(ipb));
    } else {
      interProjectBuildId = Optional.absent();
      toBuild = findModulesToBuild(build, activeModules);
    }

    // 4. Launch the modules we want to build
    for (Module module : build.getDependencyGraph().get().orderByTopologicalSort(toBuild)) {

      enqueueModuleBuild(build, module);
      if (build.getBuildOptions().getBuildDownstreams() == BuildDownstreams.INTER_PROJECT) {
        interProjectBuildMappingService.insert(InterProjectBuildMapping.makeNewMapping(interProjectBuildId.get(), build.getBranchId(), build.getId(), module.getId().get()));
      }
    }

    // 5. Only calculate skipped modules after we know what modules will build
    Set<Module> skipped = Sets.difference(activeModules, toBuild);
    for (Module module : skipped) {
      moduleBuildService.skip(build, module);
    }

    // 6. Update the state of this branch build.
    repositoryBuildService.update(build.toBuilder().setState(State.IN_PROGRESS).build());
  }

  @Inject public  LaunchingRepositoryBuildVisitor(RepositoryBuildService repositoryBuildService,
                                         ModuleBuildService moduleBuildService,
                                         MalformedFileService malformedFileService,
                                         InterProjectBuildService interProjectBuildService,
                                         InterProjectBuildMappingService interProjectBuildMappingService,
                                         ModuleService moduleService,
                                         DependenciesService dependenciesService,
                                         GitHubHelper gitHubHelper);

}