Mercurial > pub > bltoolkit
comparison Source/Templates/PluralSingular.ttinclude @ 0:f990fcb411a9
Копия текущей версии из github
| author | cin |
|---|---|
| date | Thu, 27 Mar 2014 21:46:09 +0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:f990fcb411a9 |
|---|---|
| 1 <#@ import namespace="System" #> | |
| 2 <#@ import namespace="System.Collections.Generic" #> | |
| 3 <#@ import namespace="System.Text" #> | |
| 4 <#@ import namespace="System.Text.RegularExpressions" #> | |
| 5 <# | |
| 6 { | |
| 7 var psPrevAfterLoadMetadata = AfterLoadMetadata; | |
| 8 | |
| 9 AfterLoadMetadata = _ => | |
| 10 { | |
| 11 psPrevAfterLoadMetadata(_); | |
| 12 | |
| 13 if (PluralizeDataContextPropertyNames || SingularizeDataContextPropertyNames) | |
| 14 { | |
| 15 foreach (var t in Tables.Values) | |
| 16 { | |
| 17 var propName = t.DataContextPropertyName ?? t.ClassName ?? t.TableName; | |
| 18 var newName = PluralizeDataContextPropertyNames ? ToPlural(propName) : ToSingular(propName); | |
| 19 | |
| 20 t.DataContextPropertyName = newName; | |
| 21 } | |
| 22 } | |
| 23 | |
| 24 if (PluralizeClassNames || SingularizeClassNames) | |
| 25 { | |
| 26 foreach (var t in Tables.Values) | |
| 27 { | |
| 28 var className = t.ClassName ?? t.TableName; | |
| 29 var newName = PluralizeClassNames ? ToPlural(className) : ToSingular(className); | |
| 30 | |
| 31 t.ClassName = newName; | |
| 32 } | |
| 33 } | |
| 34 }; | |
| 35 | |
| 36 PluralizeAssociationName = ToPlural; | |
| 37 SingularizeAssociationName = ToSingular; | |
| 38 } | |
| 39 | |
| 40 #><#+ | |
| 41 | |
| 42 bool PluralizeClassNames = false; | |
| 43 bool SingularizeClassNames = true; | |
| 44 bool PluralizeDataContextPropertyNames = true; | |
| 45 bool SingularizeDataContextPropertyNames = false; | |
| 46 | |
| 47 string ToPlural(string str) | |
| 48 { | |
| 49 var word = GetLastWord(str); | |
| 50 var newWord = Plurals.ToPlural(word); | |
| 51 | |
| 52 if (word != newWord) | |
| 53 { | |
| 54 if (char.IsUpper(word[0])) | |
| 55 newWord = char.ToUpper(newWord[0]) + newWord.Substring(1, newWord.Length - 1); | |
| 56 | |
| 57 return word == str ? newWord : str.Substring(0, str.Length - word.Length) + newWord; | |
| 58 } | |
| 59 | |
| 60 return str; | |
| 61 } | |
| 62 | |
| 63 string ToSingular(string str) | |
| 64 { | |
| 65 var word = GetLastWord(str); | |
| 66 var newWord = Plurals.ToSingular(word); | |
| 67 | |
| 68 if (word != newWord) | |
| 69 { | |
| 70 if (char.IsUpper(word[0])) | |
| 71 newWord = char.ToUpper(newWord[0]) + newWord.Substring(1, newWord.Length - 1); | |
| 72 | |
| 73 return word == str ? newWord : str.Substring(0, str.Length - word.Length) + newWord; | |
| 74 } | |
| 75 | |
| 76 return str; | |
| 77 } | |
| 78 | |
| 79 string GetLastWord(string word) | |
| 80 { | |
| 81 if (string.IsNullOrEmpty(word)) | |
| 82 return word; | |
| 83 | |
| 84 var len = word.Length; | |
| 85 var n = len - 1; | |
| 86 | |
| 87 if (char.IsLower(word[n])) | |
| 88 { | |
| 89 for (; n > 0 && char.IsLower(word[n]); n--); | |
| 90 } | |
| 91 else | |
| 92 { | |
| 93 for (; n > 0 && char.IsUpper(word[n]); n--); | |
| 94 if (char.IsLower(word[n])) | |
| 95 n++; | |
| 96 } | |
| 97 | |
| 98 return n > 0 ? word.Substring(n) : word; | |
| 99 } | |
| 100 | |
| 101 // Shamelessly jacked from http://www.bennysutton.com/C-sharp/Plural-Singular-Words.aspx with little modifications. | |
| 102 // | |
| 103 | |
| 104 //using System; | |
| 105 //using System.Collections.Generic; | |
| 106 //using System.Text; | |
| 107 //using System.Text.RegularExpressions; | |
| 108 | |
| 109 /// <summary> | |
| 110 /// Convert words to and from singulars/plurals | |
| 111 /// Copyright www.BennySutton.com 2008 | |
| 112 /// You may reuse this code BUT not for sale AND ONLY with credit to www.BennySutton.com | |
| 113 /// </summary> | |
| 114 public sealed class Plurals | |
| 115 { | |
| 116 /// <summary> | |
| 117 /// Store irregular plurals in a dictionary | |
| 118 /// </summary> | |
| 119 private static Dictionary<string, string> _dictionary = new Dictionary<string, string>(); | |
| 120 | |
| 121 #region Constructors | |
| 122 | |
| 123 /// <summary> | |
| 124 /// The singleton instance (thanks to dotnetpearls.com for help here) | |
| 125 /// </summary> | |
| 126 static readonly Plurals _instance = new Plurals(); | |
| 127 /// <summary> | |
| 128 /// Get an instance of the structure singleton. This effectively caches the dictionary | |
| 129 /// </summary> | |
| 130 public static Plurals Instance | |
| 131 { | |
| 132 get | |
| 133 { | |
| 134 // Fastest solution that avoids null check and is thread-safe | |
| 135 // because of readonly keyword. | |
| 136 return _instance; | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 /// <summary> | |
| 141 /// Run initialization on this singleton class | |
| 142 /// </summary> | |
| 143 private Plurals() | |
| 144 { | |
| 145 Initialize(); | |
| 146 } | |
| 147 | |
| 148 private void Initialize() | |
| 149 { | |
| 150 //to test that this class only initializes once uncomment next line | |
| 151 //System.Web.HttpContext.Current.Response.Write("initializing singleton <br>"); | |
| 152 // irregular plurals | |
| 153 _dictionary.Add("access", "accesses"); | |
| 154 _dictionary.Add("afterlife", "afterlives"); | |
| 155 _dictionary.Add("alga", "algae"); | |
| 156 _dictionary.Add("alumna", "alumnae"); | |
| 157 _dictionary.Add("alumnus", "alumni"); | |
| 158 _dictionary.Add("analysis", "analyses"); | |
| 159 _dictionary.Add("antenna", "antennae"); | |
| 160 _dictionary.Add("appendix", "appendices"); | |
| 161 _dictionary.Add("axis", "axes"); | |
| 162 _dictionary.Add("bacillus", "bacilli"); | |
| 163 _dictionary.Add("basis", "bases"); | |
| 164 _dictionary.Add("Bedouin", "Bedouin"); | |
| 165 _dictionary.Add("cactus", "cacti"); | |
| 166 _dictionary.Add("calf", "calves"); | |
| 167 _dictionary.Add("cherub", "cherubim"); | |
| 168 _dictionary.Add("child", "children"); | |
| 169 _dictionary.Add("cod", "cod"); | |
| 170 _dictionary.Add("cookie", "cookies"); | |
| 171 _dictionary.Add("criterion", "criteria"); | |
| 172 _dictionary.Add("curriculum", "curricula"); | |
| 173 _dictionary.Add("data", "data"); | |
| 174 _dictionary.Add("deer", "deer"); | |
| 175 _dictionary.Add("diagnosis", "diagnoses"); | |
| 176 _dictionary.Add("die", "dice"); | |
| 177 _dictionary.Add("dormouse", "dormice"); | |
| 178 _dictionary.Add("elf", "elves"); | |
| 179 _dictionary.Add("elk", "elk"); | |
| 180 _dictionary.Add("erratum", "errata"); | |
| 181 _dictionary.Add("esophagus", "esophagi"); | |
| 182 _dictionary.Add("fauna", "faunae"); | |
| 183 _dictionary.Add("fish", "fish"); | |
| 184 _dictionary.Add("flora", "florae"); | |
| 185 _dictionary.Add("focus", "foci"); | |
| 186 _dictionary.Add("foot", "feet"); | |
| 187 _dictionary.Add("formula", "formulae"); | |
| 188 _dictionary.Add("fundus", "fundi"); | |
| 189 _dictionary.Add("fungus", "fungi"); | |
| 190 _dictionary.Add("genie", "genii"); | |
| 191 _dictionary.Add("genus", "genera"); | |
| 192 _dictionary.Add("goose", "geese"); | |
| 193 _dictionary.Add("grouse", "grouse"); | |
| 194 _dictionary.Add("hake", "hake"); | |
| 195 _dictionary.Add("half", "halves"); | |
| 196 _dictionary.Add("headquarters", "headquarters"); | |
| 197 _dictionary.Add("hippo", "hippos"); | |
| 198 _dictionary.Add("hippopotamus", "hippopotami"); | |
| 199 _dictionary.Add("hoof", "hooves"); | |
| 200 _dictionary.Add("housewife", "housewives"); | |
| 201 _dictionary.Add("hypothesis", "hypotheses"); | |
| 202 _dictionary.Add("index", "indices"); | |
| 203 _dictionary.Add("jackknife", "jackknives"); | |
| 204 _dictionary.Add("knife", "knives"); | |
| 205 _dictionary.Add("labium", "labia"); | |
| 206 _dictionary.Add("larva", "larvae"); | |
| 207 _dictionary.Add("leaf", "leaves"); | |
| 208 _dictionary.Add("life", "lives"); | |
| 209 _dictionary.Add("loaf", "loaves"); | |
| 210 _dictionary.Add("louse", "lice"); | |
| 211 _dictionary.Add("magus", "magi"); | |
| 212 _dictionary.Add("man", "men"); | |
| 213 _dictionary.Add("memorandum", "memoranda"); | |
| 214 _dictionary.Add("midwife", "midwives"); | |
| 215 _dictionary.Add("millennium", "millennia"); | |
| 216 _dictionary.Add("moose", "moose"); | |
| 217 _dictionary.Add("mouse", "mice"); | |
| 218 _dictionary.Add("nebula", "nebulae"); | |
| 219 _dictionary.Add("neurosis", "neuroses"); | |
| 220 _dictionary.Add("nova", "novas"); | |
| 221 _dictionary.Add("nucleus", "nuclei"); | |
| 222 _dictionary.Add("oesophagus", "oesophagi"); | |
| 223 _dictionary.Add("offspring", "offspring"); | |
| 224 _dictionary.Add("ovum", "ova"); | |
| 225 _dictionary.Add("ox", "oxen"); | |
| 226 _dictionary.Add("papyrus", "papyri"); | |
| 227 _dictionary.Add("passerby", "passersby"); | |
| 228 _dictionary.Add("penknife", "penknives"); | |
| 229 _dictionary.Add("person", "people"); | |
| 230 _dictionary.Add("phenomenon", "phenomena"); | |
| 231 _dictionary.Add("placenta", "placentae"); | |
| 232 _dictionary.Add("pocketknife", "pocketknives"); | |
| 233 _dictionary.Add("process", "processes"); | |
| 234 _dictionary.Add("pupa", "pupae"); | |
| 235 _dictionary.Add("radius", "radii"); | |
| 236 _dictionary.Add("reindeer", "reindeer"); | |
| 237 _dictionary.Add("retina", "retinae"); | |
| 238 _dictionary.Add("rhinoceros", "rhinoceros"); | |
| 239 _dictionary.Add("roe", "roe"); | |
| 240 _dictionary.Add("salmon", "salmon"); | |
| 241 _dictionary.Add("scarf", "scarves"); | |
| 242 _dictionary.Add("self", "selves"); | |
| 243 _dictionary.Add("seraph", "seraphim"); | |
| 244 _dictionary.Add("series", "series"); | |
| 245 _dictionary.Add("sheaf", "sheaves"); | |
| 246 _dictionary.Add("sheep", "sheep"); | |
| 247 _dictionary.Add("shelf", "shelves"); | |
| 248 _dictionary.Add("species", "species"); | |
| 249 _dictionary.Add("spectrum", "spectra"); | |
| 250 _dictionary.Add("status", "status"); | |
| 251 _dictionary.Add("stimulus", "stimuli"); | |
| 252 _dictionary.Add("stratum", "strata"); | |
| 253 _dictionary.Add("supernova", "supernovas"); | |
| 254 _dictionary.Add("swine", "swine"); | |
| 255 _dictionary.Add("terminus", "termini"); | |
| 256 _dictionary.Add("thesaurus", "thesauri"); | |
| 257 _dictionary.Add("thesis", "theses"); | |
| 258 _dictionary.Add("thief", "thieves"); | |
| 259 _dictionary.Add("trout", "trout"); | |
| 260 _dictionary.Add("vulva", "vulvae"); | |
| 261 _dictionary.Add("wife", "wives"); | |
| 262 _dictionary.Add("wildebeest", "wildebeest"); | |
| 263 _dictionary.Add("wolf", "wolves"); | |
| 264 _dictionary.Add("woman", "women"); | |
| 265 _dictionary.Add("yen", "yen"); | |
| 266 } | |
| 267 | |
| 268 #endregion //Constructors | |
| 269 | |
| 270 #region Methods | |
| 271 | |
| 272 /// <summary> | |
| 273 /// Call this method to get the properly pluralized | |
| 274 /// English version of the word. | |
| 275 /// </summary> | |
| 276 /// <param name="word">The word needing conditional pluralization.</param> | |
| 277 /// <param name="count">The number of items the word refers to.</param> | |
| 278 /// <returns>The pluralized word</returns> | |
| 279 static public string ToPlural(string word) | |
| 280 { | |
| 281 word = word.ToLower(); | |
| 282 | |
| 283 if (_dictionary.ContainsKey(word)) | |
| 284 //it's an irregular plural, use the word from the dictionary | |
| 285 { | |
| 286 return _dictionary[word]; | |
| 287 } | |
| 288 | |
| 289 if (TestIsPlural(word) == true) | |
| 290 { | |
| 291 return word; //it's already a plural | |
| 292 } | |
| 293 | |
| 294 if (word.Length <= 2) | |
| 295 { | |
| 296 return word; //not a word that can be pluralised! | |
| 297 } | |
| 298 | |
| 299 ////1. If the word ends in a consonant plus -y, change the -y into | |
| 300 ///-ie and add an -s to form the plural | |
| 301 ///e.g. enemy--enemies baby--babies | |
| 302 switch (word.Substring(word.Length - 2)) | |
| 303 { | |
| 304 case "by": | |
| 305 case "cy": | |
| 306 case "dy": | |
| 307 case "fy": | |
| 308 case "gy": | |
| 309 case "hy": | |
| 310 case "jy": | |
| 311 case "ky": | |
| 312 case "ly": | |
| 313 case "my": | |
| 314 case "ny": | |
| 315 case "py": | |
| 316 case "ry": | |
| 317 case "sy": | |
| 318 case "ty": | |
| 319 case "vy": | |
| 320 case "wy": | |
| 321 case "xy": | |
| 322 case "zy": | |
| 323 { | |
| 324 return word.Substring(0, word.Length - 1) + "ies"; | |
| 325 } | |
| 326 | |
| 327 //2. For words that end in -is, change the -is to -es to make the plural form. | |
| 328 //synopsis--synopses | |
| 329 //thesis--theses | |
| 330 case "is": | |
| 331 { | |
| 332 return word.Substring(0, word.Length - 1) + "es"; | |
| 333 } | |
| 334 | |
| 335 //3. For words that end in a "hissing" sound (s,z,x,ch,sh), add an -es to form the plural. | |
| 336 //box--boxes | |
| 337 //church--churches | |
| 338 case "ch": | |
| 339 case "sh": | |
| 340 { | |
| 341 return word + "es"; | |
| 342 } | |
| 343 default: | |
| 344 { | |
| 345 switch (word.Substring(word.Length - 1)) | |
| 346 { | |
| 347 case "s": | |
| 348 case "z": | |
| 349 case "x": | |
| 350 { | |
| 351 return word + "es"; | |
| 352 } | |
| 353 default: | |
| 354 { | |
| 355 //4. Assume add an -s to form the plural of most words. | |
| 356 return word + "s"; | |
| 357 } | |
| 358 } | |
| 359 } | |
| 360 } | |
| 361 } | |
| 362 | |
| 363 /// <summary> | |
| 364 /// Call this method to get the singular | |
| 365 /// version of a plural English word. | |
| 366 /// </summary> | |
| 367 /// <param name="word">The word to turn into a singular</param> | |
| 368 /// <returns>The singular word</returns> | |
| 369 static public string ToSingular(string word) | |
| 370 { | |
| 371 word = word.ToLower(); | |
| 372 | |
| 373 if (_dictionary.ContainsKey(word)) | |
| 374 return word; | |
| 375 | |
| 376 if (_dictionary.ContainsValue(word)) | |
| 377 { | |
| 378 foreach (KeyValuePair<string, string> kvp in _dictionary) | |
| 379 { | |
| 380 if (kvp.Value == word) return kvp.Key; | |
| 381 } | |
| 382 } | |
| 383 | |
| 384 if (word.Substring(word.Length - 1) != "s") | |
| 385 { | |
| 386 return word; // not a plural word if it doesn't end in S | |
| 387 } | |
| 388 | |
| 389 if (word.Length <= 2) | |
| 390 { | |
| 391 return word; // not a word that can be made singular if only two letters! | |
| 392 } | |
| 393 | |
| 394 if (word.Length >= 4) | |
| 395 { | |
| 396 // 1. If the word ends in a consonant plus -y, change the -y into -ie and add an -s to form the plural – so reverse engineer it to get the singular | |
| 397 // e.g. enemy--enemies baby--babies family--families | |
| 398 switch (word.Substring(word.Length - 4)) | |
| 399 { | |
| 400 case "bies": | |
| 401 case "cies": | |
| 402 case "dies": | |
| 403 case "fies": | |
| 404 case "gies": | |
| 405 case "hies": | |
| 406 case "jies": | |
| 407 case "kies": | |
| 408 case "lies": | |
| 409 case "mies": | |
| 410 case "nies": | |
| 411 case "pies": | |
| 412 case "ries": | |
| 413 case "sies": | |
| 414 case "ties": | |
| 415 case "vies": | |
| 416 case "wies": | |
| 417 case "xies": | |
| 418 case "zies": | |
| 419 { | |
| 420 return word.Substring(0, word.Length - 3) + "y"; | |
| 421 } | |
| 422 //3. For words that end in a "hissing" sound (s,z,x,ch,sh), add an -es to form the plural. | |
| 423 //church--churches | |
| 424 case "ches": | |
| 425 case "shes": | |
| 426 { | |
| 427 return word.Substring(0, word.Length - 2); | |
| 428 } | |
| 429 } | |
| 430 } | |
| 431 | |
| 432 if (word.Length >= 3) | |
| 433 { | |
| 434 switch (word.Substring(word.Length - 3)) | |
| 435 { | |
| 436 //box--boxes | |
| 437 case "ses": | |
| 438 //NOTE some false positives here - For words that end in -is, change the -is to -es to make the plural form. | |
| 439 //synopsis--synopses | |
| 440 //thesis--theses | |
| 441 case "zes": | |
| 442 case "xes": | |
| 443 { | |
| 444 return word.Substring(0, word.Length - 2); | |
| 445 } | |
| 446 } | |
| 447 } | |
| 448 | |
| 449 if (word.Length >= 3) | |
| 450 { | |
| 451 switch (word.Substring(word.Length - 2)) | |
| 452 { | |
| 453 case "es": | |
| 454 { | |
| 455 return word.Substring(0, word.Length - 1); // + "is"; | |
| 456 } | |
| 457 //4. Assume add an -s to form the plural of most words. | |
| 458 default: | |
| 459 { | |
| 460 return word.Substring(0, word.Length - 1); | |
| 461 } | |
| 462 } | |
| 463 } | |
| 464 | |
| 465 return word; | |
| 466 } | |
| 467 | |
| 468 /// <summary> | |
| 469 /// test if a word is plural | |
| 470 /// </summary> | |
| 471 /// <param name="word">word to test</param> | |
| 472 /// <returns>true if a word is plural</returns> | |
| 473 static public bool TestIsPlural(string word) | |
| 474 { | |
| 475 word = word.ToLower(); | |
| 476 | |
| 477 if (word.Length <= 2) | |
| 478 { | |
| 479 return false; // not a word that can be made singular if only two letters! | |
| 480 } | |
| 481 | |
| 482 if (_dictionary.ContainsValue(word)) | |
| 483 { | |
| 484 return true; //it's definitely already a plural | |
| 485 } | |
| 486 | |
| 487 if (word.Length >= 4) | |
| 488 { | |
| 489 //1. If the word ends in a consonant plus -y, change the -y into -ie and add an -s to form the plural | |
| 490 // e.g. enemy--enemies baby--babies family--families | |
| 491 switch (word.Substring(word.Length - 4)) | |
| 492 { | |
| 493 case "bies": | |
| 494 case "cies": | |
| 495 case "dies": | |
| 496 case "fies": | |
| 497 case "gies": | |
| 498 case "hies": | |
| 499 case "jies": | |
| 500 case "kies": | |
| 501 case "lies": | |
| 502 case "mies": | |
| 503 case "nies": | |
| 504 case "pies": | |
| 505 case "ries": | |
| 506 case "sies": | |
| 507 case "ties": | |
| 508 case "vies": | |
| 509 case "wies": | |
| 510 case "xies": | |
| 511 case "zies": | |
| 512 case "ches": | |
| 513 case "shes": | |
| 514 { | |
| 515 return true; | |
| 516 } | |
| 517 } | |
| 518 } | |
| 519 | |
| 520 if (word.Length >= 3) | |
| 521 { | |
| 522 switch (word.Substring(word.Length - 3)) | |
| 523 { | |
| 524 //box--boxes | |
| 525 case "ses": | |
| 526 case "zes": | |
| 527 case "xes": | |
| 528 { | |
| 529 return true; | |
| 530 } | |
| 531 } | |
| 532 } | |
| 533 | |
| 534 if (word.Length >= 3) | |
| 535 { | |
| 536 switch (word.Substring(word.Length - 2)) | |
| 537 { | |
| 538 case "es": | |
| 539 { | |
| 540 return true; | |
| 541 } | |
| 542 } | |
| 543 } | |
| 544 | |
| 545 if (word.Substring(word.Length - 1) != "s") | |
| 546 { | |
| 547 return false; // not a plural word if it doesn't end in S | |
| 548 } | |
| 549 | |
| 550 return true; | |
| 551 } | |
| 552 | |
| 553 #endregion | |
| 554 } | |
| 555 | |
| 556 #> |
