Skip to content

Instantly share code, notes, and snippets.

@emiaj
Created April 13, 2011 23:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emiaj/918658 to your computer and use it in GitHub Desktop.
Save emiaj/918658 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Bottles;
using FubuCore;
using FubuCore.Util;
namespace FubuMVC.Spark.Scanning
{
public interface IFileFinder
{
void Scan(FindFileRequest request);
}
public class FindFileRequest
{
private readonly List<string> _roots;
private readonly List<string> _filter;
private CompositeAction<FileFound> _onFound;
public FindFileRequest()
{
_roots = new List<string>();
_filter = new List<string>();
_onFound = new CompositeAction<FileFound>();
}
public IEnumerable<string> Roots { get { return _roots; } }
public string Filters { get { return _filter.Join(";"); } }
public void AddRoot(string root)
{
_roots.Add(root);
}
public void AddFileFilter(string filter)
{
_filter.Add(filter);
}
public void AddHandler(Action<FileFound> handler)
{
_onFound += handler;
}
public void OnFound(FileFound file)
{
_onFound.Do(file);
}
}
public class FileFound
{
public string Root { get; set; }
public string Directory { get; set; }
public string Path { get; set; }
}
public class FileFinder : IFileFinder
{
private readonly IFileSystem _fileSystem;
private IList<string> _scannedDirectories;
public FileFinder(IFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
public void Scan(FindFileRequest request)
{
var sources = sortPaths(request.Roots);
var fileSet = new FileSet { Include = request.Filters, DeepSearch = false };
_scannedDirectories = new List<string>();
sources.Each(root => scan(root, root, fileSet, request.OnFound));
}
private void scan(string root, string directory, FileSet fileSet, Action<FileFound> onFound)
{
if (alreadyScannedOrNonexistent(directory)) { return; }
_scannedDirectories.Add(directory);
_fileSystem.ChildDirectoriesFor(directory)
.Each(dir => scan(root, dir, fileSet, onFound));
_fileSystem.FindFiles(directory, fileSet)
.Each(file => onFound(new FileFound { Path = file, Root = root, Directory = directory }));
}
private static IEnumerable<string> sortPaths(IEnumerable<string> paths)
{
return paths
.Select(p => new { Path = p, Depth = p.Split(Path.DirectorySeparatorChar).Count() })
.OrderByDescending(o => o.Depth)
.Select(p => p.Path).ToList();
}
private bool alreadyScannedOrNonexistent(string path)
{
return _scannedDirectories.Contains(path) || !_fileSystem.DirectoryExists(path);
}
}
public interface ISparkFileComposer
{
IEnumerable<SparkFile> Compose();
}
public interface ISparkFileAlteration
{
void Alter(SparkFile file);
}
public class SparkFileComposer : ISparkFileComposer
{
private readonly IFileFinder _fileFinder;
private readonly IEnumerable<ISparkFileAlteration> _alterations;
private readonly IEnumerable<IPackageInfo> _packages;
public SparkFileComposer(IFileFinder fileFinder, IEnumerable<ISparkFileAlteration> alterations,IEnumerable<IPackageInfo> packages)
{
_fileFinder = fileFinder;
_alterations = alterations;
_packages = packages;
}
public IEnumerable<SparkFile> Compose()
{
var files = new List<SparkFile>();
var request = new FindFileRequest();
var roots = getRootSources().ToList();
request.AddFileFilter("*.spark");
roots.Select(x => x.Path).Each(request.AddRoot);
request.AddHandler(file =>
{
var origin = roots.First(x => x.Path == file.Root).Origin;
files.Add(new SparkFile(file.Path, file.Root, origin));
});
_fileFinder.Scan(request);
files.Each(x => _alterations.Each(a => a.Alter(x)));
return files;
}
private IEnumerable<RootSource> getRootSources()
{
var roots = new List<RootSource>();
foreach (var package in _packages)
{
var local = package;
package.ForFolder(BottleFiles.WebContentFolder, file => roots.Add(new RootSource { Origin = local.Name, Path = file }));
}
roots.Add(new RootSource { Origin = "Host", Path = "~/".ToPhysicalPath() });
return roots;
}
private class RootSource
{
public string Path { get; set; }
public string Origin { get; set; }
}
}
public class ViewModelAlteration : ISparkFileAlteration
{
private readonly IViewModelTypeResolver _resolver;
public ViewModelAlteration(IViewModelTypeResolver resolver)
{
_resolver = resolver;
}
public void Alter(SparkFile file)
{
file.ViewModel = _resolver.Resolve(file);
}
}
public class NamespaceAlteration : ISparkFileAlteration
{
public void Alter(SparkFile file)
{
//TODO: FIX THIS, INTRODUCE PROPER ALGORITHM
if (file.ViewModel == null)
{
return;
}
var assemblyName = file.ViewModel.Assembly.GetName().Name;
var relativePath = file.Path.Replace(file.Root, "").TrimStart(Path.DirectorySeparatorChar);
var parts = relativePath
.Split(Path.DirectorySeparatorChar)
.Reverse().Skip(1) // exclude file name [something.spark]
.Reverse();// swap back to the original order
var relativeNamespace = string.Empty;
if(parts.Any())
{
// joining each part with '.'
relativeNamespace = parts
.Aggregate((a, b) => a + "." + b);
relativeNamespace = "." + relativeNamespace;
}
var ns = assemblyName + relativeNamespace;
file.Namespace = ns;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment