package org.aikodi.chameleon.analysis;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.aikodi.chameleon.core.document.Document;
import org.aikodi.chameleon.core.element.Element;
import org.aikodi.chameleon.util.action.GuardedTreeWalker;
import org.aikodi.chameleon.util.action.TopDown;
import org.aikodi.chameleon.workspace.DocumentLoader;
import org.aikodi.chameleon.workspace.InputException;
import org.aikodi.chameleon.workspace.Project;
import org.aikodi.chameleon.workspace.View;
import org.aikodi.rejuse.exception.Handler;

import be.kuleuven.cs.distrinet.rejuse.action.Action;

public abstract class Analyzer {

  /**
   * Create a new analyser for the given project.
   * @param project
   */
  /*@
   @ public behavior
   @
   @ pre project != null;
   @ post project() == project;
   @*/
  public Analyzer(Project project) {
    _project = project;
  }

  private Project _project;

  /**
   * Perform the given analysis on the project of this analyzer.
   * 
   * @param analysis The analysis to be executed.
   * @return The result of performing the given analysis top down on every
   * source document in the project. 
   * @throws InputException
   */
  protected <R extends Result<R>, E extends Exception, A extends Exception, I extends Exception> R analysisResult(
      Analysis<? extends Element,R,E> analysis,
      Handler<? super E,A> analysisHandler,
      Handler<InputException,I> handler) throws A, I {
    GuardedTreeWalker<Element, E, A> todo = new GuardedTreeWalker<>(analysis, analysisHandler) ;
    TopDown<Element, A> topDown = new TopDown<>(todo);
    Stream<View> stream = project().views().stream();
    List<DocumentLoader> flatMap = stream.flatMap(v -> v.sourceScanners().stream()).flatMap(s -> s.documentLoaders().stream()).collect(Collectors.toList());
    for(DocumentLoader loader: flatMap) {
      try {
        Document document = loader.load();
        topDown.traverse(document.lexical());
      } catch(InputException exc) {
        handler.handle(exc);
      }
    }
    return analysis.result();
  }

  public Project project() {
    return _project;
  }

  public Collection<Document> sourceDocuments() throws InputException {
    return project().sourceDocuments();
  }

}

@@ -252,24 +252,143 @@
 nt.Element;%0A
+import org.aikodi.chameleon.core.lookup.LookupException;%0Aimport org.aikodi.chameleon.core.namespacedeclaration.Import;%0A
 import org.a
@@ -731,63 +731,8 @@
 r;%0A%0A
-import be.kuleuven.cs.distrinet.rejuse.action.Action;%0A%0A
 publ
@@ -2027,24 +2027,55 @@
 der.load();%0A
+      %09cleanImports(document);%0A
         topD
@@ -2216,24 +2216,260 @@
 esult();%0A  %7D
+%0A  %0A  private void cleanImports(Document document) %7B%0A  %09document.descendants(Import.class).forEach(i -%3E %7B%0A  %09%09try %7B%0A  %09%09%09i.demandImports();%0A  %09%09%09i.directImports();%0A  %09%09%7Dcatch (LookupException exc) %7B%0A  %09%09%09i.disconnect();%0A  %09%09%7D%0A  %09%7D);%0A  %7D
 %0A%0A  public P

Clean up bad imports before analysis. Best solution would be to process only relevant imports.