/Rhino.Etl.Dsl/EtlDslEngine.cs

http://github.com/ayende/rhino-etl · C# · 121 lines · 76 code · 13 blank · 32 comment · 5 complexity · bccd3f16d5dd673a6a2220e3e31ce4bb MD5 · raw file

  1. using Boo.Lang.Compiler;
  2. using Boo.Lang.Compiler.Steps;
  3. using Rhino.DSL;
  4. namespace Rhino.Etl.Dsl
  5. {
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Reflection;
  10. using CompilerSteps;
  11. using Core;
  12. /// <summary>
  13. /// The Etl DSL engine
  14. /// </summary>
  15. public class EtlDslEngine : DslEngine
  16. {
  17. private static readonly DslFactory factory = CreateFactory();
  18. private readonly IDictionary<string, IList<string>> moduleNameToContainedTypes = new Dictionary<string, IList<string>>();
  19. private readonly string[] _namespaces;
  20. /// <summary>
  21. /// Create the ETL DSL engine
  22. /// </summary>
  23. public EtlDslEngine() : this(new string[0])
  24. { }
  25. /// <summary>
  26. /// Create the ETL DSL engine, registering additional namespaces with the compiler pipeline
  27. /// </summary>
  28. /// <param name="additionalNamespaces">Additional namespaces to register</param>
  29. public EtlDslEngine(IEnumerable<string> additionalNamespaces)
  30. {
  31. var namespaces = new List<string> {"Rhino.Etl.Core", "Rhino.Etl.Dsl", "Rhino.Etl.Dsl.Macros"};
  32. namespaces.AddRange(additionalNamespaces);
  33. _namespaces = namespaces.ToArray();
  34. }
  35. /// <summary>
  36. /// Compile the DSL and return the resulting context
  37. /// </summary>
  38. /// <param name="urls">The files to compile</param>
  39. /// <returns>The resulting compiler context</returns>
  40. public override CompilerContext Compile(params string[] urls)
  41. {
  42. //disable caching, we always compile from scratch
  43. return ForceCompile(urls, GetFileName(urls));
  44. }
  45. /// <summary>
  46. /// Gets the name of the file.
  47. /// </summary>
  48. /// <param name="urls">The urls.</param>
  49. /// <returns></returns>
  50. private static string GetFileName(IEnumerable<string> urls)
  51. {
  52. string file = Path.GetTempFileName();
  53. foreach (string url in urls)
  54. {
  55. file = url;
  56. break;
  57. }
  58. return Path.GetFileNameWithoutExtension(file) + ".dll";
  59. }
  60. /// <summary>
  61. /// Get a type from the assembly according to the URL.
  62. /// Here we are making the assumption that we will have only a single class
  63. /// inheriting from EtlProcess in the assembly
  64. /// </summary>
  65. public override Type GetTypeForUrl(Assembly assembly, string url)
  66. {
  67. string moduleName = Path.GetFileNameWithoutExtension(url);
  68. IList<string> typesInCurrentModule;
  69. if (moduleNameToContainedTypes.TryGetValue(moduleName, out typesInCurrentModule) == false)
  70. throw new InvalidOperationException("DSL Error: Module " + moduleName + " was not processed correctly");
  71. var types = new List<Type>();
  72. foreach (Type type in assembly.GetTypes())
  73. {
  74. if (typeof(EtlProcess).IsAssignableFrom(type) && typesInCurrentModule.Contains(type.Name))
  75. types.Add(type);
  76. }
  77. Guard.Against(types.Count > 1, "Found more than a single EtlProcess type in this assembly");
  78. Guard.Against(types.Count == 0, "Could not find an EtlProcess in this assembly");
  79. return types[0];
  80. }
  81. /// <summary>
  82. /// Customise the compiler to fit the etl engine
  83. /// </summary>
  84. protected override void CustomizeCompiler(BooCompiler compiler, CompilerPipeline pipeline, string[] urls)
  85. {
  86. compiler.Parameters.References.Add(typeof(EtlDslEngine).Assembly);
  87. compiler.Parameters.References.Add(typeof(EtlProcess).Assembly);
  88. pipeline.Insert(1, new AutoReferenceFilesCompilerStep());
  89. pipeline.Insert(2, new UseModuleNameAsNamespaceIfMissing());
  90. pipeline.Insert(3, new AutoImportCompilerStep(_namespaces));
  91. pipeline.InsertAfter(typeof(MacroAndAttributeExpansion),
  92. new CorrelateTypesToModuleName(moduleNameToContainedTypes));
  93. }
  94. /// <summary>
  95. /// Creates the DSL facotry
  96. /// </summary>
  97. public static DslFactory Factory
  98. {
  99. get { return factory; }
  100. }
  101. private static DslFactory CreateFactory()
  102. {
  103. DslFactory dslFactory = new DslFactory();
  104. dslFactory.Register<EtlProcess>(new EtlDslEngine());
  105. return dslFactory;
  106. }
  107. }
  108. }