1 #region MIT license
2 //
3 // MIT license
4 //
5 // Copyright (c) 2007-2008 Jiri Moudry, Pascal Craponne
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 // THE SOFTWARE.
24 //
25 #endregion
26 using System;
27 using System.Collections.Generic;
28 using System.Diagnostics;
29 using System.Linq;
30 using System.Text;
31 using System.IO;
32 using System.Reflection;
33 using DbLinq.Util;
34 
35 using Mono.Options;
36 
37 namespace DbMetal
38 {
39     [DebuggerDisplay("Parameters from {Provider}, server={Server}")]
40     public class Parameters
41     {
42         /// <summary>
43         /// user name for database access
44         /// </summary>
45         public string User { get; set; }
46 
47         /// <summary>
48         /// user password for database access
49         /// </summary>
50         public string Password { get; set; }
51 
52         /// <summary>
53         /// server host name
54         /// </summary>
55         public string Server { get; set; }
56 
57         /// <summary>
58         /// database name
59         /// </summary>
60         public string Database { get; set; }
61 
62         /// <summary>
63         /// This connection string if present overrides User, Password, Server.
64         /// Database is always used to generate the specific DataContext name
65         /// </summary>
66         public string Conn { get; set; }
67 
68         /// <summary>
69         /// the namespace to put our classes into
70         /// </summary>
71         public string Namespace { get; set; }
72 
73         /// <summary>
74         /// the language to generate classes for
75         /// </summary>
76         public string Language { get; set; }
77 
78         /// <summary>
79         /// If present, write out C# code
80         /// </summary>
81         public string Code { get; set; }
82 
83         /// <summary>
84         /// if present, write out DBML XML representing the DB
85         /// </summary>
86         public string Dbml { get; set; }
87 
88         /// <summary>
89         /// when true, we will call Singularize()/Pluralize() functions.
90         /// </summary>
91         public bool Pluralize { get; set; }
92 
93         /// <summary>
94         /// the culture used for word recognition and pluralization
95         /// </summary>
96         public string Culture { get; set; }
97 
98         /// <summary>
99         /// load object renamings from an xml file
100         /// </summary>
101         public string Aliases { get; set; }
102 
103         /// <summary>
104         /// this is the "input file" parameter
105         /// </summary>
106         public string SchemaXmlFile
107         {
108             get
109             {
110                 return Extra.Count > 0 ? Extra[0] : null;
111             }
112         }
113 
114         public bool Schema { get; set; }
115 
116         /// <summary>
117         /// base class from which all generated entities will inherit
118         /// </summary>
119         public string EntityBase { get; set; }
120 
121         /// <summary>
122         /// interfaces to be implemented
123         /// </summary>
124         public string[] EntityInterfaces { get; set; }
125 
126         /// <summary>
127         /// extra attributes to be implemented by class members
128         /// </summary>
129         public IList<string> MemberAttributes { get; set; }
130 
131         /// <summary>
132         /// generate Equals() and GetHashCode()
133         /// </summary>
134         public bool GenerateEqualsHash { get; set; }
135 
136         /// <summary>
137         /// export stored procedures
138         /// </summary>
139         public bool Sprocs { get; set; }
140 
141         /// <summary>
142         /// preserve case of database names
143         /// </summary>
144         public string Case { get; set; }
145 
146         /// <summary>
147         /// force a Console.ReadKey at end of program.
148         /// Useful when running from Studio, so the output window does not disappear
149         /// picrap comment: you may use the tool to write output to Visual Studio output window instead of a console window
150         /// </summary>
151         public bool Readline { get; set; }
152 
153         /// <summary>
154         /// specifies a provider (which here is a pair or ISchemaLoader and IDbConnection implementors)
155         /// </summary>
156         public string Provider { get; set; }
157 
158         /// <summary>
159         /// for fine tuning, we allow to specifiy an ISchemaLoader
160         /// </summary>
161         public string DbLinqSchemaLoaderProvider { get; set; }
162 
163         /// <summary>
164         /// for fine tuning, we allow to specifiy an IDbConnection
165         /// </summary>
166         public string DatabaseConnectionProvider { get; set; }
167 
168         /// <summary>
169         /// the SQL dialect used by the database
170         /// </summary>
171         public string SqlDialectType { get; set; }
172 
173         /// <summary>
174         /// the types to be generated
175         /// </summary>
176         public IList<string> GenerateTypes { get; set; }
177 
178         /// <summary>
179         /// if true, put a timestamp comment before the generated code
180         /// </summary>
181         public bool GenerateTimestamps { get; set; }
182 
183         /// <summary>
184         /// show help
185         /// </summary>
186         public bool Help { get; set; }
187 
188         /// <summary>
189         /// Show stack traces in error messages, etc., instead of just the message.
190         /// </summary>
191         public bool Debug { get; set; }
192 
193         /// <summary>
194         /// non-option parameters
195         /// </summary>
196         public IList<string> Extra = new List<string>();
197 
198         TextWriter log;
199         public TextWriter Log
200         {
201             get { return log ?? Console.Out; }
202             set { log = value; }
203         }
204 
205 
206         protected OptionSet Options;
207 
Parameters()208         public Parameters()
209         {
210             Schema = true;
211             Culture = "en";
212             GenerateTypes = new List<string>();
213             MemberAttributes = new List<string>();
214             GenerateTimestamps = true;
215             EntityInterfaces = new []{ "INotifyPropertyChanging", "INotifyPropertyChanged" };
216         }
217 
Parse(IList<string> args)218         public void Parse(IList<string> args)
219         {
220             Options = new OptionSet() {
221                  // SQLMetal compatible
222                 { "c|conn=",
223                   "Database {CONNECTION STRING}. Cannot be used with /server, "
224                   +"/user or /password options.",
225                   conn => Conn = conn },
226                  // SQLMetal compatible
227                 { "u|user=",
228                   "Login user {NAME}.",
229                   name => User = name },
230                  // SQLMetal compatible
231                 { "p|password=",
232                   "Login {PASSWORD}.",
233                   password => Password = password },
234                  // SQLMetal compatible
235                 { "s|server=",
236                   "Database server {NAME}.",
237                   name => Server = name },
238                  // SQLMetal compatible
239                 { "d|database=",
240                   "Database catalog {NAME} on server.",
241                   name => Database = name },
242                 { "provider=",
243                   "Specify {PROVIDER}. May be Ingres, MySql, Oracle, OracleODP, PostgreSql or Sqlite.",
244                   provider => Provider = provider },
245                 { "with-schema-loader=",
246                   "ISchemaLoader implementation {TYPE}.",
247                   type => DbLinqSchemaLoaderProvider = type },
248                 { "with-dbconnection=",
249                   "IDbConnection implementation {TYPE}.",
250                   type => DatabaseConnectionProvider = type },
251                 { "with-sql-dialect=",
252                   "IVendor implementation {TYPE}.",
253                   type => SqlDialectType = type },
254                  // SQLMetal compatible
255                 { "code=",
256                   "Output as source code to {FILE}. Cannot be used with /dbml option.",
257                   file => Code = file },
258                  // SQLMetal compatible
259                 { "dbml=",
260                   "Output as dbml to {FILE}. Cannot be used with /map option.",
261                   file => Dbml = file },
262                  // SQLMetal compatible
263                 { "language=",
264                   "Language {NAME} for source code: C#, C#2 or VB "
265                   +"(default: derived from extension on code file name).",
266                   name => Language = name },
267                 { "aliases=",
268                   "Use mapping {FILE}.",
269                   file => Aliases = file },
270                 { "schema",
271                   "Generate schema in code files (default: enabled).",
272                   v => Schema = v != null },
273                  // SQLMetal compatible
274                 { "namespace=",
275                   "Namespace {NAME} of generated code (default: no namespace).",
276                   name => Namespace = name },
277                  // SQLMetal compatible
278                 { "entitybase=",
279                   "Base {TYPE} of entity classes in the generated code "
280                   +"(default: entities have no base class).",
281                   type => EntityBase = type },
282                 { "member-attribute=",
283                   "{ATTRIBUTE} for entity members in the generated code, "
284                   +"can be specified multiple times.",
285                   attribute => MemberAttributes.Add(attribute) },
286                 { "generate-type=",
287                   "Generate only the {TYPE} selected, can be specified multiple times "
288                   +"and does not prevent references from being generated (default: "
289                   +"generate a DataContex subclass and all the entities in the schema).",
290                   type => GenerateTypes.Add(type) },
291                 { "generate-equals-hash",
292                   "Generates overrides for Equals() and GetHashCode() methods.",
293                   v => GenerateEqualsHash = v != null },
294                  // SQLMetal compatible
295                 { "sprocs",
296                   "Extract stored procedures.",
297                   v => Sprocs = v != null},
298                  // SQLMetal compatible
299                 { "pluralize",
300                   "Automatically pluralize or singularize class and member names "
301                   +"using specified culture rules.",
302                   v => Pluralize = v != null},
303                 { "culture=",
304                   "Specify {CULTURE} for word recognition and pluralization (default: \"en\").",
305                   culture => Culture = culture },
306                 { "case=",
307                   "Transform names with the indicated {STYLE} "
308                   +"(default: net; may be: leave, pascal, camel, net).",
309                   style => Case = style },
310                 { "generate-timestamps",
311                   "Generate timestampes in the generated code (default: enabled).",
312                   v => GenerateTimestamps = v != null },
313                 { "readline",
314                   "Wait for a key to be pressed after processing.",
315                   v => Readline = v != null },
316                 { "debug",
317                   "Enables additional information to help with debugging, " +
318                   "such as full stack traces in error messages.",
319                   v => Debug = v != null },
320                 { "h|?|help",
321                   "Show this help",
322                   v => Help = v != null }
323             };
324 
325             Extra = Options.Parse(args);
326         }
327 
328         #region Help
329 
WriteHelp()330         public void WriteHelp()
331         {
332             WriteHeader(); // includes a WriteLine()
333             WriteSyntax();
334             WriteLine();
335             WriteSummary();
336             WriteLine();
337             Options.WriteOptionDescriptions(Log);
338             WriteLine();
339             WriteExamples();
340         }
341 
342         bool headerWritten;
343 
344         /// <summary>
345         /// Writes the application header
346         /// </summary>
WriteHeader()347         public void WriteHeader()
348         {
349             if (!headerWritten)
350             {
351                 WriteHeaderContents();
352                 WriteLine();
353                 headerWritten = true;
354             }
355         }
356 
WriteHeaderContents()357         protected void WriteHeaderContents()
358         {
359             var version = ApplicationVersion;
360             Write("DbLinq Database mapping generator 2008 version {0}.{1}", version.Major, version.Minor);
361             Write("for Microsoft (R) .NET Framework version 3.5");
362             Write("Distributed under the MIT licence (http://linq.to/db/license)");
363         }
364 
365         /// <summary>
366         /// Writes a small summary
367         /// </summary>
WriteSummary()368         public void WriteSummary()
369         {
370             Write("  Generates code and mapping for DbLinq. SqlMetal can:");
371             Write("  - Generate source code and mapping attributes or a mapping file from a database.");
372             Write("  - Generate an intermediate dbml file for customization from the database.");
373             Write("  - Generate code and mapping attributes or mapping file from a dbml file.");
374         }
375 
WriteSyntax()376         public void WriteSyntax()
377         {
378             var syntax = new StringBuilder();
379             syntax.AppendFormat("{0} [OPTIONS] [<DBML INPUT FILE>]", ApplicationName);
380             Write(syntax.ToString());
381         }
382 
383         /// <summary>
384         /// Writes examples
385         /// </summary>
WriteExamples()386         public void WriteExamples()
387         {
388         }
389 
390         /// <summary>
391         /// Outputs a formatted string to the console.
392         /// We're not using the ILogger here, since we want console output.
393         /// </summary>
394         /// <param name="format"></param>
395         /// <param name="args"></param>
Write(string format, params object[] args)396         public void Write(string format, params object[] args)
397         {
398             Output.WriteLine(Log, OutputLevel.Information, format, args);
399         }
400 
401         /// <summary>
402         /// Outputs an empty line
403         /// </summary>
WriteLine()404         public void WriteLine()
405         {
406             Output.WriteLine(Log, OutputLevel.Information, string.Empty);
407         }
408 
409         /// <summary>
410         /// Returns the application (assembly) name (without extension)
411         /// </summary>
412         protected static string ApplicationName
413         {
414             get
415             {
416                 return Assembly.GetEntryAssembly().GetName().Name;
417             }
418         }
419 
420         /// <summary>
421         /// Returns the application (assembly) version
422         /// </summary>
423         protected static Version ApplicationVersion
424         {
425             get
426             {
427                 // Assembly.GetEntryAssembly() is null when loading from the
428                 // non-default AppDomain.
429                 var a = Assembly.GetEntryAssembly();
430                 return a != null ? a.GetName().Version : new Version();
431             }
432         }
433 
434         #endregion
435     }
436 }
437