package mclint;

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import ast.CompilationUnits;

import com.google.common.base.Preconditions;

public class Project {
  private Path projectRoot;
  private Map<Path, MatlabProgram> programs = new HashMap<>();

  public static Project at(final Path projectRoot) throws IOException {
    Preconditions.checkArgument(Files.isDirectory(projectRoot),
        "project root %s is not a directory", projectRoot);
    final Project project = new Project(projectRoot);

    Files.walkFileTree(projectRoot, new SimpleFileVisitor<Path>() {
      @Override
      public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
        if (file.toString().endsWith(".m")) {
          Path normalizedRelativeFile = projectRoot.relativize(file).normalize();
          project.addMatlabProgram(normalizedRelativeFile);
        }
        return FileVisitResult.CONTINUE;
      }
    });

    return project;
  }

  private Project(Path projectRoot) {
    this.projectRoot = projectRoot;
  }

  public Path getProjectRoot() {
    return projectRoot;
  }

  public MatlabProgram addMatlabProgram(Path program) {
    MatlabProgram matlabProgram = MatlabProgram.at(program, this);
    programs.put(matlabProgram.getPath(), matlabProgram);
    return matlabProgram;
  }
  
  public MatlabProgram getMatlabProgram(Path rootRelativePath) {
    return programs.get(rootRelativePath);
  }
  
  public MatlabProgram getMatlabProgram(String rootRelativePath) {
    return getMatlabProgram(getProjectRoot().resolve(rootRelativePath));
  }

  public Collection<MatlabProgram> getMatlabPrograms() {
    return Collections.unmodifiableCollection(programs.values());
  }

  public CompilationUnits asCompilationUnits() {
    CompilationUnits units = new CompilationUnits();
    units.setProject(this);
    for (MatlabProgram program : getMatlabPrograms()) {
      units.addProgram(program.parse());
    }
    return units;
  }

  public void write() throws IOException {
    write(projectRoot);
  }

  public void write(Path root) throws IOException {
    for (MatlabProgram program : getMatlabPrograms()) {
      program.write(root);
    }
  }
}
@@ -67,166 +67,36 @@
 File
-VisitResult;%0Aimport java.nio.file.Files;%0Aimport java.nio.file.Path;%0Aimport java.nio.file.SimpleFileVisitor;%0Aimport java.nio.file.attribute.BasicFileAttributes
+s;%0Aimport java.nio.file.Path
 ;%0Aim
@@ -230,17 +230,16 @@
 nUnits;%0A
-%0A
 import c
@@ -660,16 +660,8 @@
 walk
-FileTree
 (pro
@@ -672,152 +672,76 @@
 Root
-, new SimpleFileVisitor%3CPath%3E() %7B%0A      @Override%0A      public FileVisitResult visitFile(Path file, BasicFileAttributes attr) %7B%0A        if (file
+)%0A        .filter(Files::isRegularFile)%0A        .filter(path -%3E path
 .toS
@@ -763,18 +763,16 @@
 h(%22.m%22))
- %7B
 %0A       
@@ -776,39 +776,20 @@
     
-  Path normalizedRelativeFile =
+.map(path -%3E
  pro
@@ -808,20 +808,20 @@
 ativize(
-file
+path
 ).normal
@@ -825,17 +825,17 @@
 malize()
-;
+)
 %0A       
@@ -839,18 +839,26 @@
     
-  
+.forEach(
 project
-.
+::
 addM
@@ -873,98 +873,8 @@
 gram
-(normalizedRelativeFile);%0A        %7D%0A        return FileVisitResult.CONTINUE;%0A      %7D%0A    %7D
 );%0A%0A

Simplify Project initialization.