1 module MultiMapDemo; 2 3 import std.stdio; 4 import std.conv; 5 import std.range; 6 7 import hunt.collection.ArrayList; 8 import hunt.collection.HashMap; 9 import hunt.collection.List; 10 import hunt.collection.Map; 11 import hunt.collection.MultiMap; 12 13 import hunt.Assert; 14 import hunt.text; 15 import hunt.util.TypeUtils; 16 17 // alias assertTrue = Assert.assertTrue; 18 // alias assertFalse = Assert.assertFalse; 19 // alias assertThat = Assert.assertThat; 20 // alias assertEquals = Assert.assertEquals; 21 // alias assertNull = Assert.assertNull; 22 23 class MultiMapDemo { 24 25 void testBasicOperations() { 26 MultiMap!string outdoorElements = new MultiMap!string(); 27 outdoorElements.add("fish", "walleye"); 28 outdoorElements.add("fish", "muskellunge"); 29 outdoorElements.add("fish", "bass"); 30 outdoorElements.add("insect", "ants"); 31 outdoorElements.add("insect", "water boatman"); 32 outdoorElements.add("insect", "Lord Howe Island stick insect"); 33 outdoorElements.add("tree", "oak"); 34 outdoorElements.add("tree", "birch"); 35 36 List!(string) fishies = outdoorElements.getValues("fish"); 37 38 writeln("found fishies: "); 39 foreach(string name; fishies) { 40 writeln("\t", name); 41 } 42 43 assert(fishies.size() == 3); 44 } 45 46 /** 47 * Tests {@link MultiMap#put(Object, Object)} 48 */ 49 void testPut() { 50 MultiMap!(string) mm = new MultiMap!(string)(); 51 52 string key = "formats"; 53 54 mm.put(key, "gzip"); 55 assertMapSize(mm, 1); 56 assertValues(mm, key, "gzip"); 57 } 58 59 /** 60 * Tests {@link MultiMap#put(Object, Object)} 61 */ 62 void testPut_Null_String() { 63 MultiMap!(string) mm = new MultiMap!(string)(); 64 65 string key = "formats"; 66 string val = null; 67 68 mm.put(key, val); 69 assertMapSize(mm, 1); 70 assertNullValues(mm, key); 71 } 72 73 /** 74 * Tests {@link MultiMap#put(Object, Object)} 75 */ 76 void testPut_Null_List() { 77 MultiMap!(string) mm = new MultiMap!(string)(); 78 79 string key = "formats"; 80 List!(string) vals = null; 81 82 mm.put(key, vals); 83 assertMapSize(mm, 1); 84 assertNullValues(mm, key); 85 } 86 87 /** 88 * Tests {@link MultiMap#put(Object, Object)} 89 */ 90 void testPut_Replace() { 91 MultiMap!(string) mm = new MultiMap!(string)(); 92 93 string key = "formats"; 94 List!(string) ret; 95 96 ret = mm.put(key, "gzip"); 97 assertMapSize(mm, 1); 98 assertValues(mm, key, "gzip"); 99 Assert.assertNull("Should not have replaced anything", ret); 100 List!(string) orig = mm.get(key); 101 102 // Now replace it 103 ret = mm.put(key, "jar"); 104 assertMapSize(mm, 1); 105 assertValues(mm, key, "jar"); 106 Assert.assertEquals("Should have replaced original", orig, ret); 107 } 108 109 /** 110 * Tests {@link MultiMap#putValues(string, List)} 111 */ 112 void testPutValues_List() { 113 MultiMap!(string) mm = new MultiMap!(string)(); 114 115 string key = "formats"; 116 117 List!(string) input = new ArrayList!(string)(); 118 input.add("gzip"); 119 input.add("jar"); 120 input.add("pack200"); 121 122 mm.putValues(key, input); 123 assertMapSize(mm, 1); 124 assertValues(mm, key, "gzip", "jar", "pack200"); 125 } 126 127 void testPutValues_StringArray() { 128 MultiMap!(string) mm = new MultiMap!(string)(); 129 130 string key = "formats"; 131 132 string[] input = ["gzip", "jar", "pack200" ]; 133 mm.putValues(key, input); 134 assertMapSize(mm, 1); 135 assertValues(mm, key, "gzip", "jar", "pack200"); 136 } 137 138 void testPutValues_VarArgs() { 139 MultiMap!(string) mm = new MultiMap!(string)(); 140 141 string key = "formats"; 142 143 mm.putValues(key, "gzip", "jar", "pack200"); 144 assertMapSize(mm, 1); 145 assertValues(mm, key, "gzip", "jar", "pack200"); 146 } 147 148 /** 149 * Tests {@link MultiMap#add(string, Object)} 150 */ 151 void testAdd() { 152 MultiMap!(string) mm = new MultiMap!(string)(); 153 154 string key = "formats"; 155 156 // Setup the key 157 mm.put(key, "gzip"); 158 assertMapSize(mm, 1); 159 assertValues(mm, key, "gzip"); 160 161 // Add to the key 162 mm.add(key, "jar"); 163 mm.add(key, "pack200"); 164 165 assertMapSize(mm, 1); 166 assertValues(mm, key, "gzip", "jar", "pack200"); 167 } 168 169 /** 170 * Tests {@link MultiMap#addValues(string, List)} 171 */ 172 void testAddValues_List() { 173 MultiMap!(string) mm = new MultiMap!(string)(); 174 175 string key = "formats"; 176 177 // Setup the key 178 mm.put(key, "gzip"); 179 assertMapSize(mm, 1); 180 assertValues(mm, key, "gzip"); 181 182 // Add to the key 183 List!(string) extras = new ArrayList!(string)(); 184 extras.add("jar"); 185 extras.add("pack200"); 186 extras.add("zip"); 187 mm.addValues(key, extras); 188 189 assertMapSize(mm, 1); 190 assertValues(mm, key, "gzip", "jar", "pack200", "zip"); 191 } 192 193 /** 194 * Tests {@link MultiMap#addValues(string, List)} 195 */ 196 void testAddValues_List_Empty() { 197 MultiMap!(string) mm = new MultiMap!(string)(); 198 199 string key = "formats"; 200 201 // Setup the key 202 mm.put(key, "gzip"); 203 assertMapSize(mm, 1); 204 assertValues(mm, key, "gzip"); 205 206 // Add to the key 207 List!(string) extras = new ArrayList!(string)(); 208 mm.addValues(key, extras); 209 210 assertMapSize(mm, 1); 211 assertValues(mm, key, "gzip"); 212 } 213 214 /** 215 * Tests {@link MultiMap#addValues(string, Object[])} 216 */ 217 void testAddValues_StringArray() { 218 MultiMap!(string) mm = new MultiMap!(string)(); 219 220 string key = "formats"; 221 222 // Setup the key 223 mm.put(key, "gzip"); 224 assertMapSize(mm, 1); 225 assertValues(mm, key, "gzip"); 226 227 // Add to the key 228 string[] extras = [ "jar", "pack200", "zip" ]; 229 mm.addValues(key, extras); 230 231 assertMapSize(mm, 1); 232 assertValues(mm, key, "gzip", "jar", "pack200", "zip"); 233 } 234 235 /** 236 * Tests {@link MultiMap#addValues(string, Object[])} 237 */ 238 void testAddValues_StringArray_Empty() { 239 MultiMap!(string) mm = new MultiMap!(string)(); 240 241 string key = "formats"; 242 243 // Setup the key 244 mm.put(key, "gzip"); 245 assertMapSize(mm, 1); 246 assertValues(mm, key, "gzip"); 247 248 // Add to the key 249 string[] extras = new string[0]; 250 mm.addValues(key, extras); 251 252 assertMapSize(mm, 1); 253 assertValues(mm, key, "gzip"); 254 } 255 256 /** 257 * Tests {@link MultiMap#removeValue(string, Object)} 258 */ 259 void testRemoveValue() { 260 MultiMap!(string) mm = new MultiMap!(string)(); 261 262 string key = "formats"; 263 264 // Setup the key 265 mm.putValues(key, "gzip", "jar", "pack200"); 266 assertMapSize(mm, 1); 267 assertValues(mm, key, "gzip", "jar", "pack200"); 268 269 // Remove a value 270 mm.removeValue(key, "jar"); 271 assertMapSize(mm, 1); 272 assertValues(mm, key, "gzip", "pack200"); 273 274 } 275 276 /** 277 * Tests {@link MultiMap#removeValue(string, Object)} 278 */ 279 void testRemoveValue_InvalidItem() { 280 MultiMap!(string) mm = new MultiMap!(string)(); 281 282 string key = "formats"; 283 284 // Setup the key 285 mm.putValues(key, "gzip", "jar", "pack200"); 286 assertMapSize(mm, 1); 287 assertValues(mm, key, "gzip", "jar", "pack200"); 288 289 // Remove a value that isn't there 290 mm.removeValue(key, "msi"); 291 assertMapSize(mm, 1); 292 assertValues(mm, key, "gzip", "jar", "pack200"); 293 } 294 295 /** 296 * Tests {@link MultiMap#removeValue(string, Object)} 297 */ 298 void testRemoveValue_AllItems() { 299 MultiMap!(string) mm = new MultiMap!(string)(); 300 301 string key = "formats"; 302 303 // Setup the key 304 mm.putValues(key, "gzip", "jar", "pack200"); 305 assertMapSize(mm, 1); 306 assertValues(mm, key, "gzip", "jar", "pack200"); 307 308 // Remove a value 309 mm.removeValue(key, "jar"); 310 assertMapSize(mm, 1); 311 assertValues(mm, key, "gzip", "pack200"); 312 313 // Remove another value 314 mm.removeValue(key, "gzip"); 315 assertMapSize(mm, 1); 316 assertValues(mm, key, "pack200"); 317 318 // Remove last value 319 mm.removeValue(key, "pack200"); 320 assertMapSize(mm, 0); // should be empty now 321 } 322 323 /** 324 * Tests {@link MultiMap#removeValue(string, Object)} 325 */ 326 void testRemoveValue_FromEmpty() { 327 MultiMap!(string) mm = new MultiMap!(string)(); 328 329 string key = "formats"; 330 331 // Setup the key 332 mm.putValues(key, new string[0]); 333 assertMapSize(mm, 1); 334 assertEmptyValues(mm, key); 335 336 // Remove a value that isn't in the underlying values 337 mm.removeValue(key, "jar"); 338 assertMapSize(mm, 1); 339 assertEmptyValues(mm, key); 340 } 341 342 /** 343 * Tests {@link MultiMap#putAll(java.util.Map)} 344 */ 345 void testPutAll_Map() { 346 MultiMap!(string) mm = new MultiMap!(string)(); 347 348 assertMapSize(mm, 0); // Shouldn't have anything yet. 349 350 Map!(string, string) input = new HashMap!(string, string)(); 351 input.put("food", "apple"); 352 input.put("color", "red"); 353 input.put("amount", "bushel"); 354 355 mm.putAllValues(input); 356 357 assertMapSize(mm, 3); 358 assertValues(mm, "food", "apple"); 359 assertValues(mm, "color", "red"); 360 assertValues(mm, "amount", "bushel"); 361 } 362 363 /** 364 * Tests {@link MultiMap#putAll(java.util.Map)} 365 */ 366 void testPutAll_MultiMap_Simple() { 367 MultiMap!(string) mm = new MultiMap!(string)(); 368 369 assertMapSize(mm, 0); // Shouldn't have anything yet. 370 371 MultiMap!(string) input = new MultiMap!(string)(); 372 input.put("food", "apple"); 373 input.put("color", "red"); 374 input.put("amount", "bushel"); 375 376 mm.putAll(input); 377 378 assertMapSize(mm, 3); 379 assertValues(mm, "food", "apple"); 380 assertValues(mm, "color", "red"); 381 assertValues(mm, "amount", "bushel"); 382 } 383 384 /** 385 * Tests {@link MultiMap#putAll(java.util.Map)} 386 */ 387 void testPutAll_MultiMapComplex() { 388 MultiMap!(string) mm = new MultiMap!(string)(); 389 390 assertMapSize(mm, 0); // Shouldn't have anything yet. 391 392 MultiMap!(string) input = new MultiMap!(string)(); 393 input.putValues("food", "apple", "cherry", "raspberry"); 394 input.put("color", "red"); 395 input.putValues("amount", "bushel", "pint"); 396 397 mm.putAll(input); 398 399 assertMapSize(mm, 3); 400 assertValues(mm, "food", "apple", "cherry", "raspberry"); 401 assertValues(mm, "color", "red"); 402 assertValues(mm, "amount", "bushel", "pint"); 403 } 404 405 /** 406 * Tests {@link MultiMap#toStringArrayMap()} 407 */ 408 // void testToStringArrayMap() { 409 // MultiMap!(string) mm = new MultiMap!(string)(); 410 // mm.putValues("food", "apple", "cherry", "raspberry"); 411 // mm.put("color", "red"); 412 // mm.putValues("amount", "bushel", "pint"); 413 414 // assertMapSize(mm, 3); 415 416 // Map!(string, string[]) sam = mm.toStringArrayMap(); 417 // Assert.assertEquals("string Array Map.size", 3, sam.size()); 418 419 // assertArray("toStringArrayMap(food)", sam.get("food"), "apple", "cherry", "raspberry"); 420 // assertArray("toStringArrayMap(color)", sam.get("color"), "red"); 421 // assertArray("toStringArrayMap(amount)", sam.get("amount"), "bushel", "pint"); 422 // } 423 424 /** 425 * Tests {@link MultiMap#toString()} 426 */ 427 void testToString() { 428 MultiMap!(string) mm = new MultiMap!(string)(); 429 mm.put("color", "red"); 430 431 Assert.assertEquals("{color=red}", mm.toString()); 432 433 mm.putValues("food", "apple", "cherry", "raspberry"); 434 435 // Assert.assertEquals("{color=red, food=[apple, cherry, raspberry]}", mm.toString()); 436 Assert.assertEquals("{food=[apple, cherry, raspberry], color=red}", mm.toString()); 437 } 438 439 /** 440 * Tests {@link MultiMap#clear()} 441 */ 442 void testClear() { 443 MultiMap!(string) mm = new MultiMap!(string)(); 444 mm.putValues("food", "apple", "cherry", "raspberry"); 445 mm.put("color", "red"); 446 mm.putValues("amount", "bushel", "pint"); 447 448 assertMapSize(mm, 3); 449 450 mm.clear(); 451 452 assertMapSize(mm, 0); 453 } 454 455 /** 456 * Tests {@link MultiMap#containsKey(Object)} 457 */ 458 void testContainsKey() { 459 MultiMap!(string) mm = new MultiMap!(string)(); 460 mm.putValues("food", "apple", "cherry", "raspberry"); 461 mm.put("color", "red"); 462 mm.putValues("amount", "bushel", "pint"); 463 464 Assert.assertTrue("Contains Key [color]", mm.containsKey("color")); 465 Assert.assertFalse("Contains Key [nutrition]", mm.containsKey("nutrition")); 466 } 467 468 /** 469 * Tests {@link MultiMap#containsSimpleValue(Object)} 470 */ 471 void testContainsSimpleValue() { 472 MultiMap!(string) mm = new MultiMap!(string)(); 473 mm.putValues("food", "apple", "cherry", "raspberry"); 474 mm.put("color", "red"); 475 mm.putValues("amount", "bushel", "pint"); 476 477 Assert.assertTrue("Contains Value [red]", mm.containsSimpleValue("red")); 478 // TODO: Tasks pending completion -@zxp at 9/20/2018, 4:30:01 PM 479 // 480 // Assert.assertFalse("Contains Value [nutrition]", mm.containsValue("nutrition")); 481 } 482 483 /** 484 * Tests {@link MultiMap#containsValue(Object)} 485 */ 486 void testContainsValue() { 487 MultiMap!(string) mm = new MultiMap!(string)(); 488 mm.putValues("food", "apple", "cherry", "raspberry"); 489 mm.put("color", "red"); 490 mm.putValues("amount", "bushel", "pint"); 491 492 List!(string) acr = new ArrayList!(string)(); 493 acr.add("apple"); 494 acr.add("cherry"); 495 acr.add("raspberry"); 496 Assert.assertTrue("Contains Value [apple,cherry,raspberry]", mm.containsValue(acr)); 497 // TODO: Tasks pending completion -@zxp at 9/20/2018, 4:31:24 PM 498 // 499 // Assert.assertFalse("Contains Value [nutrition]", mm.containsValue("nutrition")); 500 } 501 502 /** 503 * Tests {@link MultiMap#containsValue(Object)} 504 */ 505 // void testContainsValue_LazyList() { 506 // MultiMap!(string) mm = new MultiMap!(string)(); 507 // mm.putValues("food", "apple", "cherry", "raspberry"); 508 // mm.put("color", "red"); 509 // mm.putValues("amount", "bushel", "pint"); 510 511 // Object list = LazyList.add(null, "bushel"); 512 // list = LazyList.add(list, "pint"); 513 514 // Assert.assertTrue("Contains Value [" ~ list ~ "]", mm.containsValue(list)); 515 // } 516 517 private void assertArray(T)(string prefix, Object[] actualValues, T[] expectedValues... ) { 518 Assert.assertEquals(prefix ~ ".size", expectedValues.length, actualValues.length); 519 int len = cast(int)actualValues.length; 520 for (int i = 0; i < len; i++) { 521 Assert.assertEquals(prefix ~ "[" ~ i ~ "]", expectedValues[i], actualValues[i]); 522 } 523 } 524 525 private void assertValues(T)(MultiMap!(string) mm, string key, T[] expectedValues... ) { 526 List!(string) values = mm.getValues(key); 527 528 string prefix = "MultiMap.getValues(" ~ key ~ ")"; 529 530 Assert.assertEquals(prefix ~ ".size", expectedValues.length, values.size()); 531 int len = cast(int)expectedValues.length; 532 for (int i = 0; i < len; i++) { 533 static if(is(T == class)) { 534 if (expectedValues[i] is null) { 535 Assert.assertThat(prefix ~ "[" ~ i.to!string() ~ "]", values.get(i), null); 536 } else { 537 Assert.assertEquals(prefix ~ "[" ~ i.to!string() ~ "]", expectedValues[i], values.get(i)); 538 } 539 } else { 540 static assert(false, "unsupported type: " ~ T.stringOf); 541 } 542 } 543 } 544 545 private void assertValues(MultiMap!(string) mm, string key, string[] expectedValues... ) { 546 List!(string) values = mm.getValues(key); 547 548 string prefix = "MultiMap.getValues(" ~ key ~ ")"; 549 550 Assert.assertEquals(prefix ~ ".size", expectedValues.length, values.size()); 551 int len = cast(int)expectedValues.length; 552 for (int i = 0; i < len; i++) { 553 if (expectedValues[i] is null) { 554 Assert.assertThat(prefix ~ "[" ~ i.to!string() ~ "]", values.get(i), null); 555 } else { 556 Assert.assertEquals(prefix ~ "[" ~ i.to!string() ~ "]", expectedValues[i], values.get(i)); 557 } 558 } 559 } 560 561 private void assertNullValues(MultiMap!(string) mm, string key) { 562 List!(string) values = mm.getValues(key); 563 564 string prefix = "MultiMap.getValues(" ~ key ~ ")"; 565 566 Assert.assertThat(prefix ~ ".size", values, null); 567 } 568 569 private void assertEmptyValues(MultiMap!(string) mm, string key) { 570 List!(string) values = mm.getValues(key); 571 572 string prefix = "MultiMap.getValues(" ~ key ~ ")"; 573 574 Assert.assertEquals(prefix ~ ".size", 0, LazyList.size(values)); 575 } 576 577 private void assertMapSize(MultiMap!(string) mm, int expectedSize) { 578 Assert.assertEquals("MultiMap.size", expectedSize, mm.size()); 579 } 580 581 }