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