/** {@inheritDoc} */
 @Override
 protected void computeChildren(final ChildObserver<P> observer, final TaskListener listener)
     throws IOException, InterruptedException {
   final BranchProjectFactory<P, R> _factory = getProjectFactory();
   for (final SCMSource source : getSCMSources()) {
     source.fetch(
         new SCMHeadObserver() {
           @Override
           public void observe(@NonNull SCMHead head, @NonNull SCMRevision revision) {
             Branch branch = newBranch(source, head);
             String rawName = branch.getName();
             String encodedName = branch.getEncodedName();
             P project = observer.shouldUpdate(encodedName);
             if (project != null) {
               if (!_factory.isProject(project)) {
                 listener
                     .getLogger()
                     .println("Detected unsupported subitem " + project + ", skipping");
                 return;
               }
               boolean needSave = !branch.equals(_factory.getBranch(project));
               _factory.decorate(_factory.setBranch(project, branch));
               if (revision.isDeterministic()) {
                 SCMRevision lastBuild = _factory.getRevision(project);
                 if (!revision.equals(lastBuild)) {
                   listener
                       .getLogger()
                       .println(
                           "Changes detected in "
                               + rawName
                               + " ("
                               + lastBuild
                               + " → "
                               + revision
                               + ")");
                   needSave = true;
                   scheduleBuild(_factory, project, revision, listener, rawName);
                 } else {
                   listener
                       .getLogger()
                       .println(
                           "No changes detected in " + rawName + " (still at " + revision + ")");
                 }
               } else {
                 // fall back to polling when we have a non-deterministic revision/hash.
                 SCMTriggerItem scmProject =
                     SCMTriggerItem.SCMTriggerItems.asSCMTriggerItem(project);
                 if (scmProject != null) {
                   PollingResult pollingResult = scmProject.poll(listener);
                   if (pollingResult.hasChanges()) {
                     listener.getLogger().println("Changes detected in " + rawName);
                     needSave = true;
                     scheduleBuild(_factory, project, revision, listener, rawName);
                   } else {
                     listener.getLogger().println("No changes detected in " + rawName);
                   }
                 }
               }
               if (needSave) {
                 try {
                   project.save();
                 } catch (IOException e) {
                   e.printStackTrace(listener.error("Could not save changes to " + rawName));
                 }
               }
               return;
             }
             if (!observer.mayCreate(encodedName)) {
               listener.getLogger().println("Ignoring duplicate branch project " + rawName);
               return;
             }
             project = _factory.newInstance(branch);
             if (!project.getName().equals(encodedName)) {
               throw new IllegalStateException(
                   "Name of created project "
                       + project
                       + " did not match expected "
                       + encodedName);
             }
             if (!rawName.equals(encodedName) && project.getDisplayName().equals(encodedName)) {
               try {
                 project.setDisplayName(rawName);
               } catch (IOException e) {
                 e.printStackTrace(listener.error("Could not save changes to " + rawName));
               }
             }
             _factory.decorate(project);
             observer.created(project);
             scheduleBuild(_factory, project, revision, listener, rawName);
           }
         },
         listener);
   }
 }