X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Ftools%2Fmono-xsd%2FNewMonoXSD.cs;h=48caa8d225c1b696ae3002778c7f106be5500f71;hb=9bf8d670fb9e8c223df4f4c11f4c935610b33320;hp=513c2d46d65cf732ef7f7bf57949d3d738615193;hpb=06b420b571e7f977de79a0e3f34a46826b1e9b86;p=mono.git diff --git a/mcs/tools/mono-xsd/NewMonoXSD.cs b/mcs/tools/mono-xsd/NewMonoXSD.cs old mode 100755 new mode 100644 index 513c2d46d65..48caa8d225c --- a/mcs/tools/mono-xsd/NewMonoXSD.cs +++ b/mcs/tools/mono-xsd/NewMonoXSD.cs @@ -1,8 +1,9 @@ /// /// MonoXSD.cs -- A reflection-based tool for dealing with XML Schema. /// -/// Author: Duncan Mak (duncan@ximian.com) -/// Lluis Sanchez Gual (lluis@ximian.com) +/// Authors: Duncan Mak (duncan@ximian.com) +/// Lluis Sanchez Gual (lluis@ximian.com) +/// Atsushi Enomoto (atsushi@ximian.com) /// /// Copyright (C) 2003, Duncan Mak, /// Ximian, Inc. @@ -10,6 +11,7 @@ using System; using System.Collections; +using System.Data; using System.IO; using System.Reflection; using System.Xml; @@ -18,6 +20,7 @@ using System.Xml.Serialization; using System.CodeDom; using System.CodeDom.Compiler; using Microsoft.CSharp; +using Microsoft.VisualBasic; namespace Mono.Util { @@ -27,13 +30,22 @@ namespace Mono.Util { "xsd.exe - a utility for generating schema or class files\n\n" + "xsd.exe .xsd /classes [/element:NAME] [/language:NAME]\n" + " [/namespace:NAME] [/outputdir:PATH] [/uri:NAME]\n\n" + + "xsd.exe .xsd /dataset [/element:NAME] [/language:NAME]\n" + + " [/namespace:NAME] [/outputdir:PATH] [/uri:NAME]\n\n" + + "xsd.exe .dll|.exe [/outputdir:PATH] [/type:NAME]\n\n" + + "xsd.exe .xml [.xml ...] [/outputdir:PATH]\n\n" + " /c /classes Generate classes for the specified schema.\n" + + " /d /dataset Generate typed dataset classes for the specified schema.\n" + " /e /element:NAME Element from schema to generate code for.\n" + " Multiple elements can be specified.\n" + " /u /uri:NAME Namespace uri of the elements to generate code for.\n" + - " /l /language:NAME The language to use for the generated code.\n" + - " Currently, the only supported language is CS (C#).\n" + + " /l /language:NAME The language, or type name of custom CodeDomProvider\n" + + " to use for the generated code.\n" + + " Shorthand specifiers are: \"CS\" (C#) and \"VB\" (VB.NET).\n" + + " For type name, assembly qualified name is required.\n" + + " /g /generator:TYPE Code Generator type name, followed by ','\n" + + " and assembly file name.\n" + " /o /outputdir:PATH The directory where to generate the code or schemas.\n" + " /n /namespace:NAME Namespace for the generated code.\n" + " /t /type:NAME Type for which to generate an xml schema.\n" + @@ -49,7 +61,11 @@ namespace Mono.Util { static readonly string errLoadAssembly = "Could not load assembly: {0}"; static readonly string typeNotFound = "Type {0} not found in the specified assembly"; static readonly string languageNotSupported = "The language {0} is not supported"; - + static readonly string missingOutputForXsdInput = "Can only generate one of classes or datasets."; + static readonly string generatorAssemblyNotFound = "Could not load code provider assembly file: {0}"; + static readonly string generatorTypeNotFound = "Could not find specified code provider type: {0}"; + static readonly string generatorTypeIsNotCodeGenerator = "Specified code provider type was not CodeDomProvider: {0}"; + static readonly string generatorThrewException = "Specified CodeDomProvider raised an error while creating its instance: {0}"; static void Main (string [] args) { @@ -62,9 +78,12 @@ namespace Mono.Util { { new Driver().Run (args); } - catch (Exception ex) + catch (ApplicationException ex) { Console.WriteLine (ex.Message); + } + catch (Exception ex) + { Console.WriteLine (ex); } } @@ -76,10 +95,13 @@ namespace Mono.Util { ArrayList assemblies = new ArrayList(); ArrayList schemaNames = new ArrayList(); + ArrayList inferenceNames = new ArrayList(); ArrayList elements = new ArrayList(); string language = null; string namesp = null; string uri = null; + string providerOption = null; + CodeDomProvider provider; public void Run (string[] args) { @@ -88,28 +110,42 @@ namespace Mono.Util { bool readingFiles = true; bool schemasOptions = false; bool assemblyOptions = false; + bool generateDataset = false; + bool inference = false; foreach (string arg in args) { - if (arg.EndsWith (".dll") || arg.EndsWith (".exe")) + if (!arg.StartsWith ("--") && !arg.StartsWith ("/") || + (arg.StartsWith ("/") && arg.IndexOfAny (Path.InvalidPathChars) == -1) + ) { - if (!readingFiles) throw new Exception (incorrectOrder); - assemblies.Add (arg); - assemblyOptions = true; - continue; - } - else if (arg.EndsWith (".xsd")) - { - if (!readingFiles) Error (incorrectOrder); - schemaNames.Add (arg); - schemasOptions = true; - continue; - } - else if (!arg.StartsWith ("/") && !arg.StartsWith ("-")) - { - if (!readingFiles) Error (incorrectOrder); - unknownFiles.Add (arg); - continue; + if ((arg.EndsWith (".dll") || arg.EndsWith (".exe")) && !arg.Substring (1).StartsWith ("generator:") && !arg.Substring (1).StartsWith ("g:")) + { + if (!readingFiles) throw new ApplicationException (incorrectOrder); + assemblies.Add (arg); + assemblyOptions = true; + continue; + } + else if (arg.EndsWith (".xsd")) + { + if (!readingFiles) Error (incorrectOrder); + schemaNames.Add (arg); + schemasOptions = true; + continue; + } + else if (arg.EndsWith (".xml")) + { + if (generateClasses || generateDataset) Error (duplicatedParam); + inferenceNames.Add (arg); + inference = true; + continue; + } + else if (!arg.StartsWith ("/")) + { + if (!readingFiles) Error (incorrectOrder); + unknownFiles.Add (arg); + continue; + } } readingFiles = false; @@ -121,10 +157,16 @@ namespace Mono.Util { if (option == "classes" || option == "c") { - if (generateClasses) Error (duplicatedParam, option); + if (generateClasses || generateDataset || inference) Error (duplicatedParam, option); generateClasses = true; schemasOptions = true; } + else if (option == "dataset" || option == "d") + { + if (generateClasses || generateDataset || inference) Error (duplicatedParam, option); + generateDataset = true; + schemasOptions = true; + } else if (option == "element" || option == "e") { elements.Add (param); @@ -132,6 +174,7 @@ namespace Mono.Util { } else if (option == "language" || option == "l") { + if (provider != null) Error (duplicatedParam, option); if (language != null) Error (duplicatedParam, option); language = param; schemasOptions = true; @@ -158,16 +201,24 @@ namespace Mono.Util { lookupTypes.Add (param); assemblyOptions = true; } + else if (option == "generator" || option == "g") + { + providerOption = param; + } else if (option == "help" || option == "h") { Console.WriteLine (helpString); return; } + else if (option == "nologo") + { + // ignore, since we do not output a logo anyway + } else Error (unknownOption, option); } - if (!schemasOptions && !assemblyOptions) + if (!schemasOptions && !assemblyOptions && !inference) Error (invalidParams); if (schemasOptions && assemblyOptions) @@ -177,11 +228,77 @@ namespace Mono.Util { Error (tooManyAssem); if (outputDir == null) outputDir = "."; - + + string typename = null; + Type generatorType = null; + + if (language != null) { + switch (language) { + case "CS": + provider = new CSharpCodeProvider (); + break; + case "VB": + provider = new VBCodeProvider (); + break; + default: + typename = StripQuot (language); + + generatorType = Type.GetType (typename); + if (generatorType == null) + Error (generatorTypeNotFound, typename); + break; + } + } + + if (providerOption != null) { + string param = providerOption; + int comma = param.IndexOf (','); + if (comma < 0) { + typename = StripQuot (param); + generatorType = Type.GetType (param); + } else { + typename = param.Substring (0, comma); + string asmName = param.Substring (comma + 1); + Assembly asm = Assembly.LoadFile (asmName); + if (asm == null) + Error (generatorAssemblyNotFound, asmName); + generatorType = asm.GetType (typename); + } + if (generatorType == null) + Error (generatorTypeNotFound, typename); + } + if (generatorType != null) { + if (!generatorType.IsSubclassOf (typeof (CodeDomProvider))) + Error (generatorTypeIsNotCodeGenerator, typename); + try { + provider = (CodeDomProvider) Activator.CreateInstance (generatorType, null); + } catch (Exception ex) { + Error (generatorThrewException, generatorType.AssemblyQualifiedName.ToString () + " --> " + ex.Message); + } + Console.WriteLine ("Loaded custom generator type " + generatorType + " ."); + } + if (provider == null) + provider = new CSharpCodeProvider (); + if (schemasOptions) { + if (!generateClasses && !generateDataset) + Error (missingOutputForXsdInput); schemaNames.AddRange (unknownFiles); - GenerateClasses (); + if (generateClasses) + GenerateClasses (); + else if (generateDataset) + GenerateDataset (); + } + else if (inference) + { + foreach (string xmlfile in inferenceNames) { + string genFile = Path.Combine (outputDir, Path.GetFileNameWithoutExtension (xmlfile) + ".xsd"); + DataSet ds = new DataSet (); + ds.InferXmlSchema (xmlfile, null); + ds.WriteXmlSchema (genFile); + Console.WriteLine ("Written file " + genFile); + } } else { @@ -252,7 +369,6 @@ namespace Mono.Util { public void GenerateClasses () { - if (language != null && language != "CS") Error (languageNotSupported, language); if (namesp == null) namesp = "Schemas"; if (uri == null) uri = ""; string targetFile = ""; @@ -261,14 +377,14 @@ namespace Mono.Util { foreach (string fileName in schemaNames) { StreamReader sr = new StreamReader (fileName); - schemas.Add (XmlSchema.Read (sr, null)); + schemas.Add (XmlSchema.Read (sr, new ValidationEventHandler (HandleValidationError))); sr.Close (); if (targetFile == "") targetFile = Path.GetFileNameWithoutExtension (fileName); else targetFile += "_" + Path.GetFileNameWithoutExtension (fileName); } - targetFile += ".cs"; + targetFile += "." + provider.FileExtension; CodeCompileUnit cunit = new CodeCompileUnit (); CodeNamespace codeNamespace = new CodeNamespace (namesp); @@ -286,9 +402,10 @@ namespace Mono.Util { else { foreach (XmlSchema schema in schemas) { - if (!schema.IsCompiled) schema.Compile (null); - foreach (XmlSchemaElement elem in schema.Elements.Values) - qnames.Add (elem.QualifiedName); + if (!schema.IsCompiled) schema.Compile (new ValidationEventHandler (HandleValidationError)); + foreach (XmlSchemaElement el in schema.Elements.Values) + if (!qnames.Contains (el.QualifiedName)) + qnames.Add (el.QualifiedName); } } @@ -312,7 +429,6 @@ namespace Mono.Util { // Generate the code - CSharpCodeProvider provider = new CSharpCodeProvider(); ICodeGenerator gen = provider.CreateGenerator(); string genFile = Path.Combine (outputDir, targetFile); @@ -323,14 +439,69 @@ namespace Mono.Util { Console.WriteLine ("Written file " + genFile); } + public void GenerateDataset () + { + if (namesp == null) namesp = ""; + if (uri == null) uri = ""; + string targetFile = ""; + + DataSet dataset = new DataSet (); + foreach (string fileName in schemaNames) + { + dataset.ReadXmlSchema (fileName); + + if (targetFile == "") targetFile = Path.GetFileNameWithoutExtension (fileName); + else targetFile += "_" + Path.GetFileNameWithoutExtension (fileName); + } + + targetFile += "." + provider.FileExtension; + + CodeCompileUnit cunit = new CodeCompileUnit (); + CodeNamespace codeNamespace = new CodeNamespace (namesp); + cunit.Namespaces.Add (codeNamespace); + codeNamespace.Comments.Add (new CodeCommentStatement ("\nThis source code was auto-generated by MonoXSD\n")); + + // Generate the code + + ICodeGenerator gen = provider.CreateGenerator (); + + TypedDataSetGenerator.Generate (dataset, codeNamespace, gen); + + string genFile = Path.Combine (outputDir, targetFile); + StreamWriter sw = new StreamWriter(genFile, false); + gen.GenerateCodeFromCompileUnit (cunit, sw, new CodeGeneratorOptions()); + sw.Close(); + + Console.WriteLine ("Written file " + genFile); + } + + void HandleValidationError (object o, ValidationEventArgs e) + { + Console.WriteLine ("{0}: {1} {2}", + e.Severity == XmlSeverityType.Error ? "Error" : "Warning", + e.Message, + e.Exception != null ? e.Exception.Message : null); + } + public void Error (string msg) { - throw new Exception (msg); + throw new ApplicationException (msg); } public void Error (string msg, string param) { - throw new Exception (string.Format(msg,param)); + throw new ApplicationException (string.Format(msg,param)); + } + + private string StripQuot (string input) + { + if (input.Length < 2) + return input; + if (input [0] == '"' && input [input.Length -1] == '"' || + input [0] == '\'' && input [input.Length - 1] == '\'') + return input.Substring (1, input.Length - 2); + else + return language; } } }