PageRenderTime 42ms CodeModel.GetById 20ms app.highlight 7ms RepoModel.GetById 13ms app.codeStats 0ms

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