using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using Xsd2Code.Library.Helpers; namespace Xsd2Code.Library { /// <summary> /// Encapsulation of all generation process. /// </summary> /// <remarks> /// Revision history: /// /// Modified 2009-02-20 by Ruslan Urban /// Changed signature of the GeneratorFacade class constructor /// Updated result types to <see cref="Result"/> /// /// </remarks> public class GeneratorFacade { /// <summary> /// Instance of CodeDom provider /// </summary> private CodeDomProvider providerField; #region Class constructor /// <summary> /// Initializes a new instance of the <see cref="GeneratorFacade"/> class. /// </summary> /// <param name="inputFile">The input file.</param> /// <param name="nameSpace">The name space.</param> /// <param name="language">The language.</param> /// <param name="collectionType">Type of the collection.</param> /// <param name="enableDataBinding">if set to <c>true</c> [enable data binding].</param> /// <param name="hidePrivate">if set to <c>true</c> [hide private].</param> /// <param name="enableSummaryComment">if set to <c>true</c> [enable summary comment].</param> /// <param name="customUsings">The custom usings.</param> /// <param name="collectionBase">The collection base.</param> /// <param name="includeSerializeMethod">if set to <c>true</c> [include serialize method].</param> /// <param name="serializeMethodName">Name of the serialize method.</param> /// <param name="deserializeMethodName">Name of the deserialize method.</param> /// <param name="saveToFileMethodName">Name of the save to file method.</param> /// <param name="loadFromFileMethodName">Name of the load from file method.</param> /// <param name="disableDebug">if set to <c>true</c> [disable debug].</param> /// <param name="implementCloneMethod"></param> /// <param name="targetFramework"></param> [Obsolete("Do not use", true)] public GeneratorFacade(string inputFile, string nameSpace, GenerationLanguage language, CollectionType collectionType, bool enableDataBinding, bool hidePrivate, bool enableSummaryComment, List<NamespaceParam> customUsings, string collectionBase, bool includeSerializeMethod, string serializeMethodName, string deserializeMethodName, string saveToFileMethodName, string loadFromFileMethodName, bool disableDebug, bool implementCloneMethod, TargetFramework targetFramework) { var provider = CodeDomProviderFactory.GetProvider(language); this.Init(inputFile, nameSpace, provider, collectionType, enableDataBinding, hidePrivate, enableSummaryComment, customUsings, collectionBase, includeSerializeMethod, serializeMethodName, deserializeMethodName, saveToFileMethodName, loadFromFileMethodName, disableDebug, implementCloneMethod, targetFramework); } /// <summary> /// Initializes a new instance of the <see cref="GeneratorFacade"/> class. /// </summary> /// <param name="inputFile">The input file.</param> /// <param name="nameSpace">The name space.</param> /// <param name="provider">The provider.</param> /// <param name="collectionType">Type of the collection.</param> /// <param name="enableDataBinding">if set to <c>true</c> [enable data binding].</param> /// <param name="hidePrivate">if set to <c>true</c> [hide private].</param> /// <param name="enableSummaryComment">if set to <c>true</c> [enable summary comment].</param> /// <param name="customUsings">The custom usings.</param> /// <param name="collectionBase">The collection base.</param> /// <param name="includeSerializeMethod">if set to <c>true</c> [include serialize method].</param> /// <param name="serializeMethodName">Name of the serialize method.</param> /// <param name="deserializeMethodName">Name of the deserialize method.</param> /// <param name="saveToFileMethodName">Name of the save to file method.</param> /// <param name="loadFromFileMethodName">Name of the load from file method.</param> /// <param name="disableDebug">if set to <c>true</c> [disable debug].</param> /// <param name="implementCloneMethod"></param> /// <param name="targetFramework"></param> public GeneratorFacade(string inputFile, string nameSpace, CodeDomProvider provider, CollectionType collectionType, bool enableDataBinding, bool hidePrivate, bool enableSummaryComment, List<NamespaceParam> customUsings, string collectionBase, bool includeSerializeMethod, string serializeMethodName, string deserializeMethodName, string saveToFileMethodName, string loadFromFileMethodName, bool disableDebug, bool implementCloneMethod, TargetFramework targetFramework) { this.Init(inputFile, nameSpace, provider, collectionType, enableDataBinding, hidePrivate, enableSummaryComment, customUsings, collectionBase, includeSerializeMethod, serializeMethodName, deserializeMethodName, saveToFileMethodName, loadFromFileMethodName, disableDebug, implementCloneMethod, targetFramework); } public GeneratorFacade(GeneratorParams generatorParams) { var provider = CodeDomProviderFactory.GetProvider(generatorParams.Language); this.Init(provider, generatorParams); } /// <summary> /// Generator facade class constructor /// </summary> /// <param name="provider">Code DOM provider</param> /// <param name="generatorParams">Generator parameters</param> public GeneratorFacade(CodeDomProvider provider, GeneratorParams generatorParams) { this.Init(provider, generatorParams); } /// <summary> /// Generator parameters /// </summary> public GeneratorParams GeneratorParams { get { return GeneratorContext.GeneratorParams; } } /// <summary> /// Initialize generator /// </summary> /// <param name="provider"></param> /// <param name="generatorParams"></param> public void Init(CodeDomProvider provider, GeneratorParams generatorParams) { this.providerField = provider; GeneratorContext.GeneratorParams = generatorParams.Clone(); if (string.IsNullOrEmpty(GeneratorContext.GeneratorParams.OutputFilePath)) { string outputFilePath = Utility.GetOutputFilePath(generatorParams.InputFilePath, provider); GeneratorContext.GeneratorParams.OutputFilePath = outputFilePath; } } /// <summary> /// Initializes a new instance of the <see cref="GeneratorFacade"/> class. /// </summary> /// <param name="inputFile">The input file.</param> /// <param name="nameSpace">The name space.</param> /// <param name="provider">The provider.</param> /// <param name="collectionType">Type of the collection.</param> /// <param name="enableDataBinding">if set to <c>true</c> [enable data binding].</param> /// <param name="hidePrivate">if set to <c>true</c> [hide private].</param> /// <param name="enableSummaryComment">if set to <c>true</c> [enable summary comment].</param> /// <param name="customUsings">The custom usings.</param> /// <param name="collectionBase">The collection base.</param> /// <param name="includeSerializeMethod">if set to <c>true</c> [include serialize method].</param> /// <param name="serializeMethodName">Name of the serialize method.</param> /// <param name="deserializeMethodName">Name of the deserialize method.</param> /// <param name="saveToFileMethodName">Name of the save to file method.</param> /// <param name="loadFromFileMethodName">Name of the load from file method.</param> /// <param name="disableDebug">if set to <c>true</c> [disable debug].</param> /// <param name="implementCloneMethod"></param> /// <param name="targetFramework"></param> public void Init(string inputFile, string nameSpace, CodeDomProvider provider, CollectionType collectionType, bool enableDataBinding, bool hidePrivate, bool enableSummaryComment, List<NamespaceParam> customUsings, string collectionBase, bool includeSerializeMethod, string serializeMethodName, string deserializeMethodName, string saveToFileMethodName, string loadFromFileMethodName, bool disableDebug, bool implementCloneMethod, TargetFramework targetFramework) { GeneratorContext.GeneratorParams.InputFilePath = inputFile; GeneratorContext.GeneratorParams.NameSpace = nameSpace; GeneratorContext.GeneratorParams.CollectionObjectType = collectionType; GeneratorContext.GeneratorParams.EnableDataBinding = enableDataBinding; GeneratorContext.GeneratorParams.HidePrivateFieldInIde = hidePrivate; GeneratorContext.GeneratorParams.EnableSummaryComment = enableSummaryComment; GeneratorContext.GeneratorParams.CustomUsings = customUsings; GeneratorContext.GeneratorParams.CollectionBase = collectionBase; GeneratorContext.GeneratorParams.IncludeSerializeMethod = includeSerializeMethod; GeneratorContext.GeneratorParams.GenerateCloneMethod = implementCloneMethod; GeneratorContext.GeneratorParams.TargetFramework = targetFramework; GeneratorContext.GeneratorParams.SerializeMethodName = serializeMethodName; GeneratorContext.GeneratorParams.DeserializeMethodName = deserializeMethodName; GeneratorContext.GeneratorParams.SaveToFileMethodName = saveToFileMethodName; GeneratorContext.GeneratorParams.LoadFromFileMethodName = loadFromFileMethodName; GeneratorContext.GeneratorParams.DisableDebug = disableDebug; this.providerField = provider; string outputFilePath = Utility.GetOutputFilePath(inputFile, provider); GeneratorContext.GeneratorParams.OutputFilePath = outputFilePath; } #endregion #region Methods /// <summary> /// Generates the specified buffer size. /// </summary> /// <returns>return generated code into byte array</returns> public Result<byte[]> GenerateBytes() { string outputFilePath = Path.GetTempFileName(); var processResult = this.Process(outputFilePath); if (processResult.Success) { byte[] result = FileToByte(outputFilePath); try { File.Delete(outputFilePath); } catch (Exception ex) { processResult.Messages.Add(MessageType.Error, ex.Message); } return new Result<byte[]>(result, true, processResult.Messages); } return new Result<byte[]>(null, false, processResult.Messages); } /// <summary> /// Processes the code generation. /// </summary> /// <returns>true if sucess or false.</returns> public Result<string> Generate(GeneratorParams generatorParams) { GeneratorContext.GeneratorParams = generatorParams; var outputFileName = GeneratorContext.GeneratorParams.OutputFilePath; var processResult = this.Process(outputFileName); return new Result<string>(outputFileName, processResult.Success, processResult.Messages); } /// <summary> /// Processes the code generation. /// </summary> /// <returns>true if sucess or false.</returns> public Result<string> Generate() { var outputFileName = GeneratorContext.GeneratorParams.OutputFilePath; var processResult = this.Process(outputFileName); return new Result<string>(outputFileName, processResult.Success, processResult.Messages); } /// <summary> /// Convert file into byte[]. /// </summary> /// <param name="path">The full file path to convert info byte[].</param> /// <returns>return file content info byte[].</returns> private static byte[] FileToByte(string path) { var infoFile = new FileInfo(path); using (var fileSteram = infoFile.OpenRead()) { var arrayOfByte = new byte[fileSteram.Length]; fileSteram.Read(arrayOfByte, 0, (int)fileSteram.Length); fileSteram.Close(); return arrayOfByte; } } /// <summary> /// Processes the specified file name. /// </summary> /// <param name="outputFilePath">The output file path.</param> /// <returns>true if sucess else false</returns> private Result Process(string outputFilePath) { #region Change CurrentDir for include schema resolution. string savedCurrentDir = Directory.GetCurrentDirectory(); var inputFile = new FileInfo(GeneratorContext.GeneratorParams.InputFilePath); if (!inputFile.Exists) { var errorMessage = string.Format("XSD File not found at location {0}\n", GeneratorContext.GeneratorParams.InputFilePath); errorMessage += "Exception :\n"; errorMessage += string.Format("Input file {0} not exist", GeneratorContext.GeneratorParams.InputFilePath); return new Result(false, MessageType.Error, errorMessage); } if (inputFile.Directory != null) Directory.SetCurrentDirectory(inputFile.Directory.FullName); #endregion try { try { var result = Generator.Process(GeneratorContext.GeneratorParams); if (!result.Success) return result; var ns = result.Entity; using (var outputStream = new StreamWriter(outputFilePath + ".tmp", false)) this.providerField.GenerateCodeFromNamespace(ns, outputStream, new CodeGeneratorOptions()); } catch (Exception e) { var errorMessage = "Failed to generate code\n"; errorMessage += "Exception :\n"; errorMessage += e.Message; Debug.WriteLine(string.Empty); Debug.WriteLine("XSD2Code - ----------------------------------------------------------"); Debug.WriteLine("XSD2Code - " + e.Message); Debug.WriteLine("XSD2Code - ----------------------------------------------------------"); Debug.WriteLine(string.Empty); return new Result(false, MessageType.Error, errorMessage); } var outputFile = new FileInfo(outputFilePath); if (outputFile.Exists) { if ((outputFile.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { var errorMessage = "Failed to generate code\n"; errorMessage += outputFilePath + " is write protect"; return new Result(false, MessageType.Error, errorMessage); } } #region Insert tag for future generation using (var outputStream = new StreamWriter(outputFilePath, false)) { string commentStr = GeneratorContext.GeneratorParams.Language == GenerationLanguage.CSharp ? "// " : "'' "; Assembly currentAssembly = Assembly.GetExecutingAssembly(); AssemblyName currentAssemblyName = currentAssembly.GetName(); outputStream.WriteLine( "{0}------------------------------------------------------------------------------", commentStr); outputStream.WriteLine(string.Format("{0} <auto-generated>", commentStr)); outputStream.WriteLine(string.Format("{0} Generated by Xsd2Code. Version {1}", commentStr, currentAssemblyName.Version)); string optionsLine = string.Format("{0} {1}", commentStr, GeneratorContext.GeneratorParams.ToXmlTag()); outputStream.WriteLine(optionsLine); outputStream.WriteLine("{0} </auto-generated>", commentStr); outputStream.WriteLine( "{0}------------------------------------------------------------------------------", commentStr); #endregion using (TextReader streamReader = new StreamReader(outputFilePath + ".tmp")) { string line; //DCM TODO Will refactor this to Not perform this last loop after verification that it works. while ((line = streamReader.ReadLine()) != null) { /* DCM REMOVED Language Specific Attribute removal Moved to CodeDOM Style in CodeExtension.ProcessClass() if (line.Trim() == "[System.SerializableAttribute()]" || line.Trim() == "[System.ComponentModel.DesignerCategoryAttribute(\"code\")]") continue; if (GeneratorContext.GeneratorParams.DisableDebug) outputStream.WriteLine(line); else { if (line.Trim() != "[System.Diagnostics.DebuggerStepThroughAttribute()]") outputStream.WriteLine(line); } DCM REMOVED */ outputStream.WriteLine(line); } } outputStream.Close(); } try { var tempFile = new FileInfo(outputFilePath + ".tmp"); tempFile.Delete(); } catch (Exception ex) { return new Result(false, MessageType.Error, ex.Message); } } finally { Directory.SetCurrentDirectory(savedCurrentDir); } return new Result(true); } #endregion } }