mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-01 00:00:02 -04:00
Compare commits
805 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 43ddc84986 | |||
| e682696fac | |||
| 5f190ea57d | |||
| 3ca37e4b8c | |||
| a30a032a9c | |||
| 77ebba4f7d | |||
| 456749ded8 | |||
| 47a26651b4 | |||
| 10183ef830 | |||
| 263fb75d1d | |||
| e61ec45737 | |||
| 6e063f263c | |||
| e2cf529000 | |||
| 9d1c418d8d | |||
| a7a4445ce8 | |||
| 4c1b268325 | |||
| e3c3f640a4 | |||
| ecc938a666 | |||
| 25fdfb1947 | |||
| 0c05918d8a | |||
| 4de2a38dd8 | |||
| 5b4fa64dc0 | |||
| 2ad522a9fa | |||
| 20af575fbd | |||
| 02a6ed1ac1 | |||
| 146d5926bb | |||
| 561b25022c | |||
| 4cd6b893de | |||
| dabff3abce | |||
| 1b889b1b4b | |||
| 29a3bd591d | |||
| cd79ef4409 | |||
| a604cb83fb | |||
| eb1735ab33 | |||
| 357eeb2236 | |||
| d634b9d93f | |||
| 7e3241d64b | |||
| b86d82720d | |||
| 47e90a657a | |||
| bdd8b2f1fb | |||
| 8d08c9565b | |||
| c11f61d132 | |||
| e6b38cb547 | |||
| e11d888809 | |||
| 46a399ff02 | |||
| a09629be32 | |||
| 57fb1ca1bb | |||
| c9063ca02d | |||
| 340e79eb8a | |||
| 355a916225 | |||
| 8da45b5f05 | |||
| 6c8b0cdc2f | |||
| 8af219e669 | |||
| 7e10b9242d | |||
| 36103046a5 | |||
| 95787449ea | |||
| 3223743f2c | |||
| 234c7f59d4 | |||
| 1cb0da2967 | |||
| d1525828fa | |||
| 194fd5a446 | |||
| 21e5a465b9 | |||
| 6309bc5765 | |||
| 5011e98184 | |||
| a9aa5cc66e | |||
| ac107196eb | |||
| 489a419df1 | |||
| 51891b45ea | |||
| 90e60f509d | |||
| 53e5eff0c9 | |||
| 8670e1fd8a | |||
| 6395fd33e9 | |||
| 0834a2b1be | |||
| 6c75661ab4 | |||
| 9c25c962cc | |||
| 1328dbf763 | |||
| 8bccdef371 | |||
| 2d6f7d89fa | |||
| 1afa35ccd6 | |||
| 5b184a2a8a | |||
| 39bd218085 | |||
| 87af2f6212 | |||
| 598ea1e486 | |||
| 93180e7a2d | |||
| 2cc6d1d28e | |||
| 8ea9d6f318 | |||
| 029fa843f6 | |||
| 2cb4c0a661 | |||
| bf40c81123 | |||
| 78a90fab95 | |||
| b03f7a5582 | |||
| 96470c3897 | |||
| 365b19998f | |||
| b1846e1aed | |||
| ec63fbbd85 | |||
| fbea929bc5 | |||
| 18372944f1 | |||
| 488608b312 | |||
| b3ae8a8ba6 | |||
| fc3455d2c6 | |||
| f653279c62 | |||
| 0eff483d72 | |||
| 9c044b132b | |||
| 1ec4088e49 | |||
| 5ac415d019 | |||
| 133eafc8c2 | |||
| 85346a82e1 | |||
| e718e58b65 | |||
| 13a64ed3bb | |||
| 3c6df6ad1b | |||
| 9abe154ed3 | |||
| 0e752a2d2c | |||
| 867a46d281 | |||
| 9972f966f7 | |||
| f066a48d55 | |||
| 5af87372aa | |||
| defadbbbcd | |||
| 66363f8d09 | |||
| 1bef35daba | |||
| 0be5efc534 | |||
| 35da57dfcf | |||
| 5d09bb664e | |||
| 5590072cc7 | |||
| 31117c7cea | |||
| ae0899fe76 | |||
| df51ef340d | |||
| 71d8295042 | |||
| a8f77a9a45 | |||
| eb3176b447 | |||
| 20e308dd8f | |||
| 9fa9bc5fe0 | |||
| 4da3e2e441 | |||
| 4516d84e54 | |||
| a815e5f180 | |||
| 35658a888f | |||
| 6cd6b6113d | |||
| f8b919ee58 | |||
| 8989ba07d8 | |||
| bc38ec1034 | |||
| e37c1fbb50 | |||
| 75b6de7102 | |||
| 22a16db463 | |||
| 3e93753073 | |||
| ad3cbbd86d | |||
| 076e417010 | |||
| 0b84a99954 | |||
| e2f4241a99 | |||
| 6eedaa129d | |||
| f5dbc0c2f4 | |||
| 7d79185fb2 | |||
| c885ed6dbb | |||
| e116c98db2 | |||
| be9493af20 | |||
| 5ffe3087ad | |||
| ffc7dad821 | |||
| 2a4ff2aa12 | |||
| 1e9669d6c3 | |||
| caca51d5ce | |||
| 015728a57d | |||
| 4272c6c8ed | |||
| b5582e32f6 | |||
| 76045ab0d9 | |||
| 4fc8f28cc6 | |||
| 7198a92a2e | |||
| e2fbd80c36 | |||
| 6b28cbe4a1 | |||
| 76198b0655 | |||
| f81b14df71 | |||
| da3f79f0c9 | |||
| d39418eca2 | |||
| cbbc2bc6fe | |||
| b0b423de4f | |||
| 1c4ec8d20e | |||
| ec99a8ce1f | |||
| c49a887cd3 | |||
| 14af75d191 | |||
| 0ce205638e | |||
| fe4119ca1c | |||
| c927f4c1ec | |||
| 161368084a | |||
| d958aba69e | |||
| 931429724c | |||
| dcd21db2ef | |||
| 7a3022ebf2 | |||
| 274886b1d9 | |||
| 0cf784ee60 | |||
| a797f1ea26 | |||
| baff849b6c | |||
| 408977d896 | |||
| d78e6373a8 | |||
| 9610256ddb | |||
| 34c9b9b4b5 | |||
| 9d5823d982 | |||
| 10e824df36 | |||
| 3bc90bfad1 | |||
| 543acce8a3 | |||
| a67fdd4b80 | |||
| 9c936d3f11 | |||
| fb2bff1404 | |||
| 3c605f8796 | |||
| 7817af91a3 | |||
| 1ed1076714 | |||
| a90d375422 | |||
| 815007ab2b | |||
| b3c8f53512 | |||
| d2977a18ac | |||
| 7e5e905d18 | |||
| 0fcba279f1 | |||
| d7d9552216 | |||
| e48a78aa77 | |||
| bf351c01a6 | |||
| 9bd4389142 | |||
| 984383bd56 | |||
| 77247772d0 | |||
| ae482bc7e5 | |||
| 119700487b | |||
| 5e5d530498 | |||
| 3dfc0850cc | |||
| 8f285327fc | |||
| 734b90863a | |||
| 18f31f2dd4 | |||
| a7294af89c | |||
| ea63a5bdc1 | |||
| 2cc50bbdad | |||
| f4a5f57d52 | |||
| 7fc47a338c | |||
| f8311164af | |||
| 84c10ed96d | |||
| 9c8ae4ac3e | |||
| aab7b6f7f5 | |||
| 3c01071452 | |||
| 4fc9c3513b | |||
| 59b08bfc79 | |||
| 743f1f9356 | |||
| d90b1c984c | |||
| 1160be4995 | |||
| 2978c901ae | |||
| e4b465a0d4 | |||
| 297a27c5be | |||
| 9d9593dba2 | |||
| 66683a2ead | |||
| 4be4f4e2b6 | |||
| 7f59d41b2a | |||
| a060c105e1 | |||
| f3318ee818 | |||
| afa306a787 | |||
| ed032b6c7a | |||
| 894e5dc30a | |||
| 8e02fb36e9 | |||
| 88a2e226ca | |||
| 203ad0258f | |||
| 2a1ecf80fa | |||
| 4239ce5e31 | |||
| 61ca2fc3e0 | |||
| 9e502899ac | |||
| 16fd8d1453 | |||
| 81ae64b65c | |||
| b0d5480445 | |||
| 9e989680c6 | |||
| dd174c7f7e | |||
| 72ef50b677 | |||
| a7349278b2 | |||
| 858f519f0b | |||
| d797ff0bb3 | |||
| fef4c4dd7a | |||
| a99762b5de | |||
| c7d0c902db | |||
| e8e2026d48 | |||
| f1dc50c276 | |||
| 0e615192e7 | |||
| d9b82f80ef | |||
| 41f316e621 | |||
| 5f2b0c0ccf | |||
| ee7d4ba724 | |||
| f7d4557c57 | |||
| 20d8c34dae | |||
| eaee82f3e7 | |||
| a0d87ec6d8 | |||
| ac5d4a02a9 | |||
| a26932cd70 | |||
| 7b8e5433dd | |||
| 1471af3e68 | |||
| 4f0dd84cf6 | |||
| 143e25c39c | |||
| 3d0ba82422 | |||
| 34f626914a | |||
| d6587ad292 | |||
| 46eaa72a13 | |||
| b3d48bdc50 | |||
| 981d2da1e6 | |||
| cf40b5f4a0 | |||
| 34128c66a4 | |||
| 1aa02477a7 | |||
| fa49dd93a7 | |||
| 83cff35076 | |||
| 93e3ae5ef8 | |||
| d8857c2997 | |||
| 7b119ce7dc | |||
| 3e7ad05973 | |||
| 1e574ca429 | |||
| dce193b113 | |||
| 05517e1fed | |||
| d707793211 | |||
| 39cfeedc6b | |||
| 1dcbbc39e3 | |||
| c933dbf69f | |||
| 5fc7dc1963 | |||
| f42d5e0a32 | |||
| d1c3a9bacb | |||
| 21ad54b820 | |||
| e11fc63730 | |||
| 2a70e744e0 | |||
| 60550ba8a8 | |||
| d3b16cdd35 | |||
| add7b06fa4 | |||
| b99391854d | |||
| a22188bd72 | |||
| d5f5f295f5 | |||
| d95de31908 | |||
| 4fda5af141 | |||
| b54827ae1b | |||
| 2762b9705a | |||
| 2d6248e293 | |||
| 8a43e4539c | |||
| 8ecf203263 | |||
| 8e50af2804 | |||
| 58e31aebd1 | |||
| b8e3e7825c | |||
| 155e9850fb | |||
| 0c4adf36ba | |||
| fd32bc9089 | |||
| 6ad010dc44 | |||
| c9b14ea4af | |||
| f162c873ed | |||
| c21b971655 | |||
| d1b0247055 | |||
| 6d3605c080 | |||
| a188dcf9fd | |||
| 08938c6b4d | |||
| 016ef952ce | |||
| 2844c396c8 | |||
| 2f95716b8a | |||
| cf7fce647d | |||
| 4014ae4644 | |||
| 4e46e81e3f | |||
| ec43410fa6 | |||
| 721fc5b5a5 | |||
| 0c71981158 | |||
| ac0ed5ed8f | |||
| d1b11ee1d1 | |||
| 210eeccb39 | |||
| e07e7c3685 | |||
| 611cb6cb4d | |||
| 54d9feef94 | |||
| 54b4ded602 | |||
| e360ed2a6a | |||
| 2325cef5a3 | |||
| 465eb09dd3 | |||
| feae2a0f79 | |||
| 860cb32a58 | |||
| b9bd19b950 | |||
| 3742e6ef08 | |||
| 52aa582ccd | |||
| adda52053b | |||
| 6501321fac | |||
| 57d9bfda59 | |||
| 1226375ba6 | |||
| 9c2d3058fd | |||
| e89cadd95f | |||
| 0ec299c2e6 | |||
| b91d02a562 | |||
| 2b5f897841 | |||
| e65078bdb7 | |||
| 36d8555172 | |||
| 80e3170820 | |||
| 90bc04b030 | |||
| dcba9b0667 | |||
| dc755c4c3c | |||
| 6e4f1e0739 | |||
| 7117cd1fd6 | |||
| 2b954c1067 | |||
| 77a1745106 | |||
| 0378f504e7 | |||
| 1d3a7fe812 | |||
| 8715b6b696 | |||
| a95235b422 | |||
| 9f4b09fc7d | |||
| 03455f0132 | |||
| ac5779d8d6 | |||
| fef8ff3aab | |||
| a9e4b2e262 | |||
| 7147e2dfb1 | |||
| 1680fadf83 | |||
| d1df8c13ed | |||
| 031937fe99 | |||
| 24c473ae45 | |||
| 57941cb638 | |||
| d325b6deec | |||
| 3f67430b2d | |||
| 314071dde8 | |||
| 83ad25c2dd | |||
| d7dae90e2e | |||
| ad437c2470 | |||
| dabc26bdb5 | |||
| b441298a9a | |||
| 345ca0ac13 | |||
| 9720a931c5 | |||
| 4d3f691e6a | |||
| 2e0e575183 | |||
| 2c7c47b158 | |||
| 57680f1bec | |||
| 8dc83c4e9e | |||
| 929bea6b6b | |||
| 699662d054 | |||
| 1bebee1851 | |||
| b0e8dd86bb | |||
| 5bdb0b5502 | |||
| 85d47528a3 | |||
| a7ebd66149 | |||
| f0a032a7b9 | |||
| 690cb064e7 | |||
| e65f471a8f | |||
| f2cc9faaf8 | |||
| 8bd3f4f34a | |||
| be348543d8 | |||
| 80229b8c3c | |||
| a5ee53569d | |||
| c22ada03cd | |||
| b61341ce3b | |||
| e73b0a7bcf | |||
| ea9d1c0dc5 | |||
| e0563ee7dd | |||
| 44bcd202e8 | |||
| 5b57b51ff1 | |||
| 0b5f8a071e | |||
| d3dc578936 | |||
| 2ae937b870 | |||
| 2a7763299a | |||
| a57a1d35f9 | |||
| e618805786 | |||
| e3cb923d37 | |||
| 4513b0c166 | |||
| b55d4e8c1b | |||
| 399c75f59e | |||
| a7f7d73e2d | |||
| 41a83191b7 | |||
| 49e805eeb7 | |||
| f426637fdd | |||
| 4081ff1545 | |||
| ae4fbcc726 | |||
| 66208bfa03 | |||
| e72255805e | |||
| 780ccd7916 | |||
| 957e917281 | |||
| 9daf8337ee | |||
| 89c104d59f | |||
| 8608ee76c5 | |||
| aab2d36e92 | |||
| 608b37232d | |||
| e3ebf8e0fa | |||
| 9af10625a2 | |||
| ccc4e7b411 | |||
| 439323c5e5 | |||
| 332e191d0d | |||
| 58d1a89028 | |||
| 72fe799cc8 | |||
| 18af213e27 | |||
| 9d267f352f | |||
| f8f6f9f1e4 | |||
| 2841d26785 | |||
| 98ae5967ca | |||
| da9d87a561 | |||
| d472191926 | |||
| a8472170c4 | |||
| b2f7cada21 | |||
| 2a4c152c3d | |||
| 660932b7e7 | |||
| d0a17ff3b3 | |||
| 4259903bdd | |||
| 3018d2a342 | |||
| 8f94318f28 | |||
| 60b7151eb6 | |||
| 8ad21307e8 | |||
| 8c854f1e20 | |||
| 1445ff2533 | |||
| e8f1e80d4e | |||
| 18e29e9ed5 | |||
| ec4003b1c1 | |||
| 164b8db988 | |||
| 21feace385 | |||
| ba1f754611 | |||
| 822b5da631 | |||
| c785f6932f | |||
| 43e2a27c7f | |||
| 9d50acd2fe | |||
| ba73a308d6 | |||
| 20cd259abd | |||
| 033a1423ff | |||
| 7c8c520006 | |||
| 9162458e36 | |||
| d38af3cb16 | |||
| c57e8f80fa | |||
| 4750359ada | |||
| cbe8038619 | |||
| 2d8125e69c | |||
| 57a664c093 | |||
| 7f82377fd7 | |||
| 72b9f19a51 | |||
| 0083b8e77e | |||
| 79982cd493 | |||
| f0db338f3b | |||
| 9db4e0b3ed | |||
| cd4cbdcb82 | |||
| 15dc4b3852 | |||
| a3534ecd59 | |||
| 7bb5fee23b | |||
| 6cb7424bd0 | |||
| 9aa04d311e | |||
| 967e71dc92 | |||
| 628523ddc8 | |||
| 783c28ae0e | |||
| d35d67651f | |||
| 816d48efef | |||
| 25ee21d090 | |||
| 536ea7ba88 | |||
| d2687383f5 | |||
| 3ce35e059c | |||
| 1d5359dd35 | |||
| 2699b75b79 | |||
| 4e614dfc7e | |||
| 3a2efd9491 | |||
| c5dc2e4e53 | |||
| 41460bd32a | |||
| 13b37b3839 | |||
| 6dd74070f4 | |||
| 81b358b377 | |||
| 9715f4e74c | |||
| 38256c8be0 | |||
| bf3c1fad17 | |||
| b8488ae39b | |||
| d3bea0ae38 | |||
| 9435410b1e | |||
| f74e8c8ba1 | |||
| 0ae2c2f01d | |||
| 77c81a06bc | |||
| 2bbcd88798 | |||
| 829fbe7547 | |||
| 078425eed9 | |||
| 8ddcbbd2b2 | |||
| 507cca5fd7 | |||
| a4caac0c82 | |||
| 54c07b849c | |||
| c531d4f5d3 | |||
| aa2e8e5d7e | |||
| 76a35331b0 | |||
| 6b3f1c6ee3 | |||
| c731e10e8f | |||
| 4a8c3530f7 | |||
| e8996daa12 | |||
| 9196e60c74 | |||
| eabb8fd02b | |||
| 1794e336de | |||
| ac7612b3df | |||
| 606fd53823 | |||
| 614a07e040 | |||
| 34e8d88007 | |||
| 9b727df901 | |||
| f1f98bb4a4 | |||
| b34b26e08c | |||
| 993e07ee34 | |||
| a377712bdb | |||
| e5dc6aa878 | |||
| 46b1c1cf96 | |||
| d9300b1c90 | |||
| 0a2efb9eac | |||
| 3eabc591d8 | |||
| 5cefce2dbf | |||
| 4c645c0220 | |||
| 703848ca45 | |||
| 0ebd18fcb6 | |||
| 29f7547a99 | |||
| 25cd351eee | |||
| 77c98c917e | |||
| 4bbe946f46 | |||
| 78832ed923 | |||
| 164cc11592 | |||
| 8f5c1b409f | |||
| 26981513d8 | |||
| a3a30d54d4 | |||
| 102e9cff51 | |||
| da800be8c8 | |||
| 70493bd323 | |||
| 304d050bc3 | |||
| 0443172666 | |||
| cee2663f06 | |||
| 8f44cfc43c | |||
| 8a240aac68 | |||
| 61424f33b6 | |||
| c7b9b1fadd | |||
| ab08ec1e0d | |||
| cbe78dc67f | |||
| c9e11f171f | |||
| bc2c0c2301 | |||
| 6581e2e2a1 | |||
| c2873b1f27 | |||
| 35f2f0be9f | |||
| b5856fd110 | |||
| 1919d77a45 | |||
| 37afe24aac | |||
| 081f2efea2 | |||
| 627bb1bf1f | |||
| a77b62b6ba | |||
| 2500d8cc15 | |||
| c01336fb8a | |||
| 6f9b9bee01 | |||
| b9b1a35408 | |||
| 7ed5663633 | |||
| 6458fcdcbd | |||
| 9375bfda9a | |||
| 0160fb70f8 | |||
| 29dca0f124 | |||
| c21f14efe1 | |||
| 81ba43e1e8 | |||
| a1fcfc3958 | |||
| c60116a611 | |||
| 15e6ddc1fd | |||
| 49f4e5401e | |||
| e333c7d1b2 | |||
| cda34b704b | |||
| 7c4487be04 | |||
| 5a4525aaa1 | |||
| b766420e3e | |||
| c858454c5a | |||
| 67b48ce1e3 | |||
| 6608f61353 | |||
| 326b98d5e5 | |||
| fafa58b718 | |||
| 0ed0246762 | |||
| b3004a1227 | |||
| 7ab627a754 | |||
| 008e57a7ce | |||
| 28270b4d5b | |||
| 7382151db8 | |||
| b856ce07af | |||
| 190fe87ee9 | |||
| d1872ce94f | |||
| a5c52a99b4 | |||
| 4170b393fa | |||
| 53f9ba91e0 | |||
| be2d7d5f10 | |||
| 00aec2c90e | |||
| 2b04f7205c | |||
| 7d401d0194 | |||
| 48691139a3 | |||
| bcb87c09d2 | |||
| 84a8ceeb93 | |||
| 0cb99feedf | |||
| 91493c5145 | |||
| 6ddb799a95 | |||
| 8a187f6657 | |||
| b7d865f2cf | |||
| d50fb1a51e | |||
| 8992406f50 | |||
| 44eebff62f | |||
| 8c85c4ca96 | |||
| fa5c77bff0 | |||
| d87b80deea | |||
| ae138c3b4e | |||
| ab13fdd09d | |||
| aab5b062bd | |||
| 00d6acd1bf | |||
| 0f8a7ea482 | |||
| 9fe87fe10d | |||
| a33dbaf897 | |||
| 9e2f369459 | |||
| d34b0b7fcf | |||
| 5effcb1344 | |||
| b67d687761 | |||
| d0881c8b5c | |||
| 976928f48c | |||
| e1c2f2ee73 | |||
| 92632fa2a3 | |||
| 5a563e315f | |||
| c06d47d123 | |||
| fea6beb364 | |||
| 4b951c06cc | |||
| a3e6e52c95 | |||
| 5347015cbd | |||
| 4d190892df | |||
| 60eab81709 | |||
| b400b6b157 | |||
| 499b3ef120 | |||
| 92bc9c73f6 | |||
| 2a77558cac | |||
| 816cad60a8 | |||
| 7167f81c69 | |||
| f5cfa0e619 | |||
| 73ad024833 | |||
| 379449b621 | |||
| e17faad6fb | |||
| 1271a3d55e | |||
| 1cd594d113 | |||
| b76f74e79a | |||
| 78817a489b | |||
| b8f2a80ca6 | |||
| ac8a36db1c | |||
| 7e0d8922da | |||
| 9a6b8c9bfe | |||
| eced5b8efd | |||
| 74611e4e52 | |||
| b8614eca4d | |||
| efd24456ac | |||
| 191b2371c8 | |||
| 33419ef291 | |||
| 123f0bb7fc | |||
| 99b5f28a49 | |||
| b30fb4f8c3 | |||
| dc0bdcbd5b | |||
| 0cf29c167d | |||
| 98e4b76206 | |||
| aa4b5db054 | |||
| 433311c10d | |||
| f50178bc78 | |||
| e016e970e5 | |||
| 4223d13898 | |||
| 444aeabf21 | |||
| 05507a59d6 | |||
| c4c89a0a25 | |||
| b0ad6b2a4b | |||
| 25c703f4b2 | |||
| 529c59f93f | |||
| 584b1d9b21 | |||
| 312ce364cc | |||
| 7de8231471 | |||
| 0de9f79029 | |||
| eeb56acdde | |||
| a6862cfec8 | |||
| f8284700b4 | |||
| 38caeb22e0 | |||
| b2c5915db8 | |||
| 3911191b04 | |||
| bc328419ac | |||
| da4efe98bf | |||
| 6653f4a85d | |||
| 511a29beb9 | |||
| 5617b4323c | |||
| 16d0af357d | |||
| 74927d5396 | |||
| 7e809dd834 | |||
| 7aa95a08bc | |||
| c28963ae49 | |||
| 0327f5fc1a | |||
| 1c59057c30 | |||
| 3e1f85c4dc | |||
| 11227a68a0 | |||
| 62ba73a30e | |||
| 1f33afb5a1 | |||
| 9d3f271867 | |||
| 812e12acb0 | |||
| 060b6cf852 | |||
| e68ce7ffd1 | |||
| 778cdef69c | |||
| d46a76fca8 | |||
| 105a1ee466 | |||
| aa030f526c | |||
| 976e5d6210 | |||
| 6daca00fcd | |||
| ef05872934 | |||
| 1ddab866fd | |||
| ce997a6951 | |||
| 23bf5cb7b2 | |||
| 564778f415 | |||
| e28bf8fb44 | |||
| cf8d630d01 | |||
| 0ff7224912 | |||
| 196081a317 | |||
| ff50180d86 | |||
| 8f2c482167 | |||
| eab24890ca | |||
| cd42d81817 | |||
| ba5c667b6c | |||
| 4e9fa9442c | |||
| 4d2326c18d | |||
| 94eac2d6e5 | |||
| f63a33d541 | |||
| 00f8d87f36 | |||
| 4c2ab6da7b | |||
| b5088312e2 | |||
| f04f968f12 | |||
| 8896092e31 | |||
| 2f9768a1d4 | |||
| 06bcf22242 | |||
| 20c7f8e60e | |||
| 15a9ad0a9b | |||
| 7ae2d636dc | |||
| 12e756b23c | |||
| 4e2bf131d2 | |||
| d0c4a07556 | |||
| 21059c8d5a | |||
| fa7b530809 | |||
| 790cf3b32e | |||
| b1baaad23b | |||
| 7fa704ace5 | |||
| 8d07f4fe90 | |||
| 32bba6857b |
@@ -0,0 +1 @@
|
|||||||
|
github: haraldk
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: Reported bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**Version information**
|
||||||
|
1. The version of the TwelveMonkeys ImageIO library in use.
|
||||||
|
For example: 4.0.0
|
||||||
|
|
||||||
|
2. The *exact* output of `java --version` (or `java -version` for older Java releases).
|
||||||
|
For example:
|
||||||
|
|
||||||
|
java version "1.8.0_271"
|
||||||
|
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
|
||||||
|
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)
|
||||||
|
|
||||||
|
3. Extra information about OS version, server version, standalone program or web application packaging, executable wrapper, etc. Please state exact version numbers where applicable.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
|
||||||
|
1. Compile the below sample code
|
||||||
|
2. Download the sample image file
|
||||||
|
3. Run the code with the sample file
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Example code**
|
||||||
|
Preferably as a failing JUnit test, or a standalone program with a `main` method that showcases the problem.
|
||||||
|
|
||||||
|
Less is more. Don't add your entire project, only the code required to reproduce the problem. 😀
|
||||||
|
|
||||||
|
**Sample file(s)**
|
||||||
|
Attach any sample files needed to reproduce the problem. Use a ZIP-file if the format is not directly supported by GitHub.
|
||||||
|
|
||||||
|
**Stak trace**
|
||||||
|
Always include the stack trace you experience.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
Do not add screenshots of code or stack traces. 😀
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: New feature
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a use case or a problem you are working on? Please describe.**
|
||||||
|
A clear and concise description of what the problem or use case is. Understanding the rationale is key, to be able to implemeent the right solution.
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've already considered, and why they won't work.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here, like links to specifications or sample files.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
name: Trouble shooting and programming help
|
||||||
|
about: "General programming issues will reach a wider audience at StackOverflow. Tag
|
||||||
|
questions with javax-imageio and/or twelvemonkeys \U0001F600 "
|
||||||
|
title: ''
|
||||||
|
labels: Trouble-shooting
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
General programming issues and problems will reach a much wider audience at StackOverflow, we suggest you ask them there. This will offload our work with maintaining the library, and make sure you get better help sooner.
|
||||||
|
|
||||||
|
Tag the question with `javax-imageio` and/or `twelvemonkeys` and we'll find them there.
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
**What is fixed** Add link to the issue this PR fixes.
|
||||||
|
|
||||||
|
Example: Fixes #42.
|
||||||
|
|
||||||
|
**Why is this change proposed** If this change does *not* fix an open issue, briefly describe the rationale for this PR.
|
||||||
|
|
||||||
|
**What is changed** Briefly describe the changes proposed in this pull request:
|
||||||
|
|
||||||
|
* Fixed rare exception happening in `x >= 42` case
|
||||||
|
* Small optimization of `decompress()` method
|
||||||
|
* Corrected API doc for `compress()` method to reflect current implementation
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
# Maven/Java library updates
|
||||||
|
- package-ecosystem: "maven"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
cooldown:
|
||||||
|
default-days: 7
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
# GitHub actions updates
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/.github/workflows"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
cooldown:
|
||||||
|
default-days: 7
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
- '!dependabot/**'
|
||||||
|
pull_request:
|
||||||
|
branches: [ 'master' ]
|
||||||
|
|
||||||
|
permissions: read-all
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
||||||
|
java: [ 8, 11, 17, 21, 25 ]
|
||||||
|
exclude:
|
||||||
|
- os: macos-latest
|
||||||
|
java: 8
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
permissions:
|
||||||
|
checks: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: ${{ matrix.java }}
|
||||||
|
java-package: jdk
|
||||||
|
cache: 'maven'
|
||||||
|
- name: Run Tests
|
||||||
|
run: mvn --batch-mode --no-transfer-progress test
|
||||||
|
- name: Publish Test Report
|
||||||
|
uses: mikepenz/action-junit-report@bccf2e31636835cf0874589931c4116687171386 # v5
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
with:
|
||||||
|
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||||
|
check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
|
||||||
|
|
||||||
|
test-jdk8-macos:
|
||||||
|
name: Test OpenJDK 8 on macos-14
|
||||||
|
runs-on: macos-14
|
||||||
|
permissions:
|
||||||
|
checks: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||||
|
with:
|
||||||
|
distribution: 'zulu'
|
||||||
|
java-version: '8'
|
||||||
|
java-package: jdk
|
||||||
|
cache: 'maven'
|
||||||
|
- name: Run Tests
|
||||||
|
run: mvn --batch-mode --no-transfer-progress test
|
||||||
|
- name: Publish Test Report
|
||||||
|
uses: mikepenz/action-junit-report@bccf2e31636835cf0874589931c4116687171386 # v5
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
with:
|
||||||
|
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||||
|
check_name: Unit Test Results for OpenJDK ${{ matrix.java }} on ${{ matrix.os }}
|
||||||
|
|
||||||
|
test-oracle:
|
||||||
|
name: Test Oracle JDK 8 with KCMS=${{ matrix.kcms }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
checks: write
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
kcms: [ true, false ]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
- run: |
|
||||||
|
download_url="https://javadl.oracle.com/webapps/download/AutoDL?BundleId=245038_d3c52aa6bfa54d3ca74e617f18309292"
|
||||||
|
wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
|
||||||
|
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||||
|
with:
|
||||||
|
distribution: 'jdkfile'
|
||||||
|
jdkFile: ${{ runner.temp }}/java_package.tar.gz
|
||||||
|
java-version: '8'
|
||||||
|
cache: 'maven'
|
||||||
|
- name: Set MAVEN_OPTS
|
||||||
|
if: ${{ matrix.kcms }}
|
||||||
|
run: |
|
||||||
|
echo "MAVEN_OPTS=-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider" >> $GITHUB_ENV
|
||||||
|
- name: Display Java version
|
||||||
|
run: java -version
|
||||||
|
- name: Run Tests
|
||||||
|
run: mvn --batch-mode --no-transfer-progress test
|
||||||
|
- name: Publish Test Report
|
||||||
|
uses: mikepenz/action-junit-report@bccf2e31636835cf0874589931c4116687171386 # v5
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
with:
|
||||||
|
report_paths: "**/target/surefire-reports/TEST*.xml"
|
||||||
|
check_name: Unit Test Results for Oracle JDK 8 with KCMS=${{ matrix.kcms }}
|
||||||
|
|
||||||
|
javadoc:
|
||||||
|
name: Build JavaDoc on OpenJDK ${{ matrix.java }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
java: [8, 11, 25 ] # We only need a few versions here
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: ${{ matrix.java }}
|
||||||
|
java-package: jdk
|
||||||
|
cache: 'maven'
|
||||||
|
- name: Create JavaDoc
|
||||||
|
run: mvn --batch-mode --no-transfer-progress -DskipTests package javadoc:javadoc
|
||||||
|
|
||||||
|
release:
|
||||||
|
name: Deploy
|
||||||
|
needs: [ test, test-jdk8-macos, test-oracle, javadoc ]
|
||||||
|
if: github.ref == 'refs/heads/master' # only perform on latest master
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
- name: Set up Maven Central
|
||||||
|
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||||
|
with: # running setup-java again overwrites the settings.xml
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '8'
|
||||||
|
java-package: jdk
|
||||||
|
server-id: central # Value of the distributionManagement/repository/id field of the pom.xml
|
||||||
|
server-username: MAVEN_CENTRAL_USERNAME # env variable for username in deploy (1)
|
||||||
|
server-password: MAVEN_CENTRAL_PASSWORD # env variable for token in deploy (2)
|
||||||
|
- name: Get Project Version
|
||||||
|
run: |
|
||||||
|
echo "PROJECT_VERSION=$(mvn --batch-mode help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV
|
||||||
|
- name: Publish to Maven Central
|
||||||
|
if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }}
|
||||||
|
run: mvn --batch-mode --no-transfer-progress deploy -P release -DskipTests -Dgpg.signer=bc
|
||||||
|
env:
|
||||||
|
MAVEN_CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }} # must be the same env variable name as (1)
|
||||||
|
MAVEN_CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }} # must be the same env variable name as (2)
|
||||||
|
MAVEN_GPG_KEY: ${{ secrets.GPG_KEY }} # Value of the GPG private key to import
|
||||||
|
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ "master" ]
|
||||||
|
schedule:
|
||||||
|
- cron: '26 13 * * 6'
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||||
|
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||||
|
# - https://gh.io/supported-runners-and-hardware-resources
|
||||||
|
# - https://gh.io/using-larger-runners
|
||||||
|
# Consider using larger runners for possible analysis time improvements.
|
||||||
|
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||||
|
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'java' ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
|
||||||
|
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||||
|
# queries: security-extended,security-and-quality
|
||||||
|
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
|
|
||||||
|
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||||
|
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||||
|
|
||||||
|
# - run: |
|
||||||
|
# echo "Run, Build Application using script"
|
||||||
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
|
||||||
|
with:
|
||||||
|
category: "/language:${{matrix.language}}"
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# This workflow uses actions that are not certified by GitHub. They are provided
|
||||||
|
# by a third-party and are governed by separate terms of service, privacy
|
||||||
|
# policy, and support documentation.
|
||||||
|
|
||||||
|
name: Scorecard supply-chain security
|
||||||
|
on:
|
||||||
|
# For Branch-Protection check. Only the default branch is supported. See
|
||||||
|
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
|
||||||
|
branch_protection_rule:
|
||||||
|
# To guarantee Maintained check is occasionally updated. See
|
||||||
|
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
|
||||||
|
schedule:
|
||||||
|
- cron: '38 8 * * 2'
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
|
||||||
|
permissions: read-all # Declare default permissions as read only.
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analysis:
|
||||||
|
name: Scorecard analysis
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
security-events: write # to upload the results to code-scanning dashboard.
|
||||||
|
id-token: write # to publish results and get a badge
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: "Checkout code"
|
||||||
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: "Run analysis"
|
||||||
|
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
|
||||||
|
with:
|
||||||
|
results_file: results.sarif
|
||||||
|
results_format: sarif
|
||||||
|
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
|
||||||
|
# you want to enable the Branch-Protection check on the repository
|
||||||
|
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-fine-grained-pat-optional.
|
||||||
|
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
|
||||||
|
|
||||||
|
# Publish Results:
|
||||||
|
# - Publish results to OpenSSF REST API for easy access by consumers
|
||||||
|
# - Allows the repository to include the Scorecard badge.
|
||||||
|
# - See https://github.com/ossf/scorecard-action#publishing-results.
|
||||||
|
publish_results: true
|
||||||
|
|
||||||
|
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||||
|
# format to the repository Actions tab.
|
||||||
|
- name: "Upload artifact"
|
||||||
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
|
with:
|
||||||
|
name: SARIF file
|
||||||
|
path: results.sarif
|
||||||
|
retention-days: 5
|
||||||
|
|
||||||
|
# Upload the results to GitHub's code scanning dashboard.
|
||||||
|
- name: "Upload to code-scanning"
|
||||||
|
uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
|
||||||
|
with:
|
||||||
|
sarif_file: results.sarif
|
||||||
@@ -15,3 +15,4 @@ private
|
|||||||
profiles.xml
|
profiles.xml
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
/.metadata/
|
||||||
|
|||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
dist: trusty
|
|
||||||
language: java
|
|
||||||
jdk:
|
|
||||||
- oraclejdk8 # Legacy
|
|
||||||
- oraclejdk11 # LTS
|
|
||||||
- oraclejdk15 # Latest
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
# Extra job, testing legacy CMM option
|
|
||||||
- jdk: oraclejdk8
|
|
||||||
env: MAVEN_OPTS=-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.m2
|
|
||||||
@@ -1,58 +1,63 @@
|
|||||||
[](https://travis-ci.org/haraldk/TwelveMonkeys)
|
[](https://github.com/haraldk/TwelveMonkeys/actions/workflows/ci.yml)
|
||||||
[](https://maven-badges.herokuapp.com/maven-central/com.twelvemonkeys.imageio/imageio)
|
[](https://github.com/haraldk/TwelveMonkeys/actions/workflows/codeql.yml)
|
||||||
|
[](https://securityscorecards.dev/viewer/?uri=github.com/haraldk/TwelveMonkeys)
|
||||||
|
[](https://www.bestpractices.dev/projects/7900)
|
||||||
|
|
||||||
|
[](https://search.maven.org/search?q=g:com.twelvemonkeys.imageio)
|
||||||
|
[](https://central.sonatype.com/repository/maven-snapshots/com/twelvemonkeys/imageio/imageio/maven-metadata.xml)
|
||||||
[](https://stackoverflow.com/questions/tagged/twelvemonkeys)
|
[](https://stackoverflow.com/questions/tagged/twelvemonkeys)
|
||||||
[](https://paypal.me/haraldk76/100)
|
[](https://paypal.me/haraldk76/100)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
TwelveMonkeys ImageIO is a collection of plugins and extensions for Java's ImageIO.
|
TwelveMonkeys ImageIO provides extended image file format support for the Java platform, through plugins for the `javax.imageio.*` package.
|
||||||
|
|
||||||
These plugins extend the number of image file formats supported in Java, using the `javax.imageio.*` package.
|
The main goal of this project is to provide support for file formats not covered by the JDK.
|
||||||
The main purpose of this project is to provide support for formats not covered by the JRE itself.
|
Support for these formats is important, to be able to read data found
|
||||||
|
|
||||||
Support for formats is important, both to be able to read data found
|
|
||||||
"in the wild", as well as to maintain access to data in legacy formats.
|
"in the wild", as well as to maintain access to data in legacy formats.
|
||||||
Because there is lots of legacy data out there, we see the need for open implementations of readers for popular formats.
|
As there is lots of legacy data out there, we see the need for open implementations of readers for popular formats.
|
||||||
The goal is to create a set of efficient and robust ImageIO plug-ins, that can be distributed independently.
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
## File formats supported
|
## File formats supported
|
||||||
|
|
||||||
| Plugin | Format | Description | Read | Write | Metadata | Notes |
|
| Plugin | Format | Description | R | W | Metadata | Notes |
|
||||||
| ------ | -------- | ----------- |:----:|:-----:| -------- | ----- |
|
| ------ | -------- |---------------------------------------------------------|:---:|:---:| -------- | ----- |
|
||||||
| Batik | **SVG** | Scalable Vector Graphics | ✔ | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/)
|
| Batik | **SVG** | Scalable Vector Graphics | ✔ | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/) |
|
||||||
| | WMF | MS Windows Metafile | ✔ | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/)
|
| | WMF | MS Windows Metafile | ✔ | - | - | Requires [Batik](https://xmlgraphics.apache.org/batik/) |
|
||||||
| [BMP](https://github.com/haraldk/TwelveMonkeys/wiki/BMP-Plugin) | **BMP** | MS Windows and IBM OS/2 Device Independent Bitmap | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/bmp_metadata.html) & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [BMP](https://github.com/haraldk/TwelveMonkeys/wiki/BMP-Plugin) | **BMP** | MS Windows and IBM OS/2 Device Independent Bitmap | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/bmp_metadata.html), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | CUR | MS Windows Cursor Format | ✔ | - | - |
|
| | CUR | MS Windows Cursor Format | ✔ | - | - |
|
||||||
| | ICO | MS Windows Icon Format | ✔ | ✔ | - |
|
| | ICO | MS Windows Icon Format | ✔ | ✔ | - |
|
||||||
| [HDR](https://github.com/haraldk/TwelveMonkeys/wiki/HDR-Plugin) | HDR | Radiance High Dynamic Range RGBE Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [DDS](https://github.com/haraldk/TwelveMonkeys/wiki/DDS-Plugin) | DDS | MS Direct Draw Surface Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [ICNS](https://github.com/haraldk/TwelveMonkeys/wiki/ICNS-Plugin) | ICNS | Apple Icon Image | ✔ | ✔ | - |
|
| [HDR](https://github.com/haraldk/TwelveMonkeys/wiki/HDR-Plugin) | HDR | Radiance High Dynamic Range RGBE Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [IFF](https://github.com/haraldk/TwelveMonkeys/wiki/IFF-Plugin) | IFF | Commodore Amiga/Electronic Arts Interchange File Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [ICNS](https://github.com/haraldk/TwelveMonkeys/wiki/ICNS-Plugin) | ICNS | Apple Icon Image | ✔ | ✔ | - |
|
||||||
| [JPEG](https://github.com/haraldk/TwelveMonkeys/wiki/JPEG-Plugin) | **JPEG** | Joint Photographers Expert Group | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/jpeg_metadata.html#image) & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [IFF](https://github.com/haraldk/TwelveMonkeys/wiki/IFF-Plugin) | IFF | Commodore Amiga/Electronic Arts Interchange File Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | JPEG Lossless | | ✔ | - | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/jpeg_metadata.html#image) & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [JPEG](https://github.com/haraldk/TwelveMonkeys/wiki/JPEG-Plugin) | **JPEG** | Joint Photographers Expert Group | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/jpeg_metadata.html#image), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [PCX](https://github.com/haraldk/TwelveMonkeys/wiki/PCX-Plugin) | PCX | ZSoft Paintbrush Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | JPEG Lossless | | ✔ | - | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/jpeg_metadata.html#image), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | DCX | Multi-page PCX fax document | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [PCX](https://github.com/haraldk/TwelveMonkeys/wiki/PCX-Plugin) | PCX | ZSoft Paintbrush Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [PICT](https://github.com/haraldk/TwelveMonkeys/wiki/PICT-Plugin) | PICT | Apple QuickTime Picture Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | DCX | Multi-page PCX fax document | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PNTG | Apple MacPaint Picture Format | ✔ | | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [PICT](https://github.com/haraldk/TwelveMonkeys/wiki/PICT-Plugin) | PICT | Apple QuickTime Picture Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [PNM](https://github.com/haraldk/TwelveMonkeys/wiki/PNM-Plugin) | PAM | NetPBM Portable Any Map | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PNTG | Apple MacPaint Picture Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PBM | NetPBM Portable Bit Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [PNM](https://github.com/haraldk/TwelveMonkeys/wiki/PNM-Plugin) | PAM | NetPBM Portable Any Map | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PGM | NetPBM Portable Grey Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PBM | NetPBM Portable Bit Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PPM | NetPBM Portable Pix Map | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PGM | NetPBM Portable Grey Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PFM | Portable Float Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PPM | NetPBM Portable Pix Map | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [PSD](https://github.com/haraldk/TwelveMonkeys/wiki/PSD-Plugin) | **PSD** | Adobe Photoshop Document | ✔ | - | Native & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PFM | Portable Float Map | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| | PSB | Adobe Photoshop Large Document | ✔ | - | Native & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [PSD](https://github.com/haraldk/TwelveMonkeys/wiki/PSD-Plugin) | **PSD** | Adobe Photoshop Document | ✔ | (✔) | Native, [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [SGI](https://github.com/haraldk/TwelveMonkeys/wiki/SGI-Plugin) | SGI | Silicon Graphics Image Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| | PSB | Adobe Photoshop Large Document | ✔ | - | Native, [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [TGA](https://github.com/haraldk/TwelveMonkeys/wiki/TGA-Plugin) | TGA | Truevision TGA Image Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [SGI](https://github.com/haraldk/TwelveMonkeys/wiki/SGI-Plugin) | SGI | Silicon Graphics Image Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
|ThumbsDB| Thumbs.db| MS Windows Thumbs DB | ✔ | - | - | OLE2 Compound Document based format only
|
| [TGA](https://github.com/haraldk/TwelveMonkeys/wiki/TGA-Plugin) | TGA | Truevision TGA Image Format | ✔ | ✔ | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [TIFF](https://github.com/haraldk/TwelveMonkeys/wiki/TIFF-Plugin) | **TIFF** | Aldus/Adobe Tagged Image File Format | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html#ImageMetadata) & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
|ThumbsDB| Thumbs.db| MS Windows Thumbs DB | ✔ | - | - | OLE2 Compound Document based format only |
|
||||||
| | BigTIFF | | ✔ | - | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html#ImageMetadata) & [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [TIFF](https://github.com/haraldk/TwelveMonkeys/wiki/TIFF-Plugin) | **TIFF** | Aldus/Adobe Tagged Image File Format | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html#ImageMetadata), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| [WebP](https://github.com/haraldk/TwelveMonkeys/wiki/WebP-Plugin) | **WebP** | Google WebP Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) | In progress
|
| | BigTIFF | | ✔ | ✔ | [Native](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html#ImageMetadata), [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
| XWD | XWD | X11 Window Dump Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
| [WebP](https://github.com/haraldk/TwelveMonkeys/wiki/WebP-Plugin) | **WebP** | Google WebP Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
|
| XWD | XWD | X11 Window Dump Format | ✔ | - | [Standard](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/metadata/doc-files/standard_metadata.html) |
|
||||||
|
|
||||||
|
|
||||||
**Important note on using Batik:** *Please read [The Apache™ XML Graphics Project - Security](http://xmlgraphics.apache.org/security.html),
|
**Important note on using Batik:** *Please read [The Apache™ XML Graphics Project - Security](https://xmlgraphics.apache.org/security.html),
|
||||||
and make sure you use version 1.14 or later.*
|
and make sure you use an updated and secure version.*
|
||||||
|
|
||||||
Note that GIF, PNG and WBMP formats are already supported through the ImageIO API, using the
|
Note that GIF, PNG and WBMP formats are already supported through the ImageIO API, using the
|
||||||
[JDK standard plugins](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/package-summary.html).
|
[JDK standard plugins](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/imageio/package-summary.html).
|
||||||
@@ -166,7 +171,7 @@ finally {
|
|||||||
```
|
```
|
||||||
|
|
||||||
For more advanced usage, and information on how to use the ImageIO API, I suggest you read the
|
For more advanced usage, and information on how to use the ImageIO API, I suggest you read the
|
||||||
[Java Image I/O API Guide](http://docs.oracle.com/javase/7/docs/technotes/guides/imageio/spec/imageio_guideTOC.fm.html)
|
[Java Image I/O API Guide](https://docs.oracle.com/javase/7/docs/technotes/guides/imageio/spec/imageio_guideTOC.fm.html)
|
||||||
from Oracle.
|
from Oracle.
|
||||||
|
|
||||||
#### Adobe Clipping Path support
|
#### Adobe Clipping Path support
|
||||||
@@ -218,16 +223,53 @@ BufferedImageOp ditherer = new DiffusionDither();
|
|||||||
BufferedImage output = ditherer.filter(input, null);
|
BufferedImage output = ditherer.filter(input, null);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Working with damaged images
|
||||||
|
|
||||||
|
When using the normal patterns for loading images, trying to load a damaged image will result in an `IOException` being thrown.
|
||||||
|
|
||||||
|
```java
|
||||||
|
BufferedImage image = null;
|
||||||
|
try {
|
||||||
|
image = ImageIO.read(file);
|
||||||
|
} catch (IOException exception) {
|
||||||
|
// Handle, log a warning/error etc
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this scenario, if the image is damaged, and `ImageIO.read` throws an exception, `image` is still `null` - it's not possible for a function to both return a value and throw an exception.
|
||||||
|
|
||||||
|
However, in some cases it may be possible to get usable image data from a damaged image. The way to do this is use an `ImageReadParam` to set a `BufferedImage` as a destination.
|
||||||
|
|
||||||
|
```java
|
||||||
|
int width = reader.getWidth(0);
|
||||||
|
int height = reader.getHeight(0);
|
||||||
|
ImageTypeSpecifier imageType = reader.getRawImageType(0);
|
||||||
|
BufferedImage image = imageType.createBufferedImage(width, height);
|
||||||
|
|
||||||
|
ImageReadParam param = reader.getDefaultReadParam();
|
||||||
|
param.setDestination(image);
|
||||||
|
|
||||||
|
try {
|
||||||
|
reader.read(0, param);
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
// Handle, log a warning/error etc
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In theory this should work for all plugins, but the result is very much plugin/implementation specific. With some formats and some forms of damaged file, you may get an image that is mostly useful.
|
||||||
|
However, you should be prepared for the possibility this just gives a blank or empty image.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
Download the project (using [Git](http://git-scm.com/downloads)):
|
Download the project (using [Git](https://git-scm.com/downloads)):
|
||||||
|
|
||||||
$ git clone git@github.com:haraldk/TwelveMonkeys.git
|
$ git clone git@github.com:haraldk/TwelveMonkeys.git
|
||||||
|
|
||||||
This should create a folder named `TwelveMonkeys` in your current directory. Change directory to the `TwelveMonkeys`
|
This should create a folder named `TwelveMonkeys` in your current directory. Change directory to the `TwelveMonkeys`
|
||||||
folder, and issue the command below to build.
|
folder, and issue the command below to build.
|
||||||
|
|
||||||
Build the project (using [Maven](http://maven.apache.org/download.cgi)):
|
Build the project (using [Maven](https://maven.apache.org/download.cgi)):
|
||||||
|
|
||||||
$ mvn package
|
$ mvn package
|
||||||
|
|
||||||
@@ -274,12 +316,12 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-jpeg</artifactId>
|
<artifactId>imageio-jpeg</artifactId>
|
||||||
<version>3.6.4</version>
|
<version>3.13.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-tiff</artifactId>
|
<artifactId>imageio-tiff</artifactId>
|
||||||
<version>3.6.4</version>
|
<version>3.13.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@@ -289,7 +331,17 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||||
<artifactId>servlet</artifactId>
|
<artifactId>servlet</artifactId>
|
||||||
<version>3.6.4</version>
|
<version>3.13.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Or Jakarta version, for Servlet API 5.0
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||||
|
<artifactId>servlet</artifactId>
|
||||||
|
<version>3.13.1</version>
|
||||||
|
<classifier>jakarta</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
```
|
```
|
||||||
@@ -298,18 +350,18 @@ To depend on the JPEG and TIFF plugin using Maven, add the following to your POM
|
|||||||
|
|
||||||
To depend on the JPEG and TIFF plugin in your IDE or program, add all of the following JARs to your class path:
|
To depend on the JPEG and TIFF plugin in your IDE or program, add all of the following JARs to your class path:
|
||||||
|
|
||||||
twelvemonkeys-common-lang-3.6.4.jar
|
twelvemonkeys-common-lang-3.13.1.jar
|
||||||
twelvemonkeys-common-io-3.6.4.jar
|
twelvemonkeys-common-io-3.13.1.jar
|
||||||
twelvemonkeys-common-image-3.6.4.jar
|
twelvemonkeys-common-image-3.13.1.jar
|
||||||
twelvemonkeys-imageio-core-3.6.4.jar
|
twelvemonkeys-imageio-core-3.13.1.jar
|
||||||
twelvemonkeys-imageio-metadata-3.6.4.jar
|
twelvemonkeys-imageio-metadata-3.13.1.jar
|
||||||
twelvemonkeys-imageio-jpeg-3.6.4.jar
|
twelvemonkeys-imageio-jpeg-3.13.1.jar
|
||||||
twelvemonkeys-imageio-tiff-3.6.4.jar
|
twelvemonkeys-imageio-tiff-3.13.1.jar
|
||||||
|
|
||||||
#### Deploying the plugins in a web app
|
#### Deploying the plugins in a web app
|
||||||
|
|
||||||
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it doesn't by default work well with
|
Because the `ImageIO` plugin registry (the `IIORegistry`) is "VM global", it does not work well with
|
||||||
servlet contexts. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
|
servlet contexts as-is. This is especially evident if you load plugins from the `WEB-INF/lib` or `classes` folder.
|
||||||
Unless you add `ImageIO.scanForPlugins()` somewhere in your code, the plugins might never be available at all.
|
Unless you add `ImageIO.scanForPlugins()` somewhere in your code, the plugins might never be available at all.
|
||||||
|
|
||||||
In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context).
|
In addition, servlet contexts dynamically loads and unloads classes (using a new class loader per context).
|
||||||
@@ -345,6 +397,16 @@ or other ImageIO plugins as well.
|
|||||||
|
|
||||||
Another safe option, is to place the JAR files in the application server's shared or common lib folder.
|
Another safe option, is to place the JAR files in the application server's shared or common lib folder.
|
||||||
|
|
||||||
|
##### Jakarta Servlet Support
|
||||||
|
|
||||||
|
For those transitioning from the old `javax.servlet` to the new `jakarta.servlet` package, there is a separate
|
||||||
|
dependency available. It contains exactly the same servlet classes as mentioned above, but built against the new Jakarta EE
|
||||||
|
packages. The dependency has the same group name and identifier as before, but a `jakarta` *classifier* appended, to
|
||||||
|
distinguish it from the non-Jakarta package.
|
||||||
|
|
||||||
|
See the [Maven dependency example](#maven-dependency-example) for how to enable it with Maven.
|
||||||
|
Gradle or other build tools will have similar options.
|
||||||
|
|
||||||
#### Including the plugins in a "fat" JAR
|
#### Including the plugins in a "fat" JAR
|
||||||
|
|
||||||
The recommended way to use the plugins, is just to include the JARs as-is in your project, through a Maven dependency or similar.
|
The recommended way to use the plugins, is just to include the JARs as-is in your project, through a Maven dependency or similar.
|
||||||
@@ -370,79 +432,52 @@ Other "fat" JAR bundlers will probably have similar mechanisms to merge entries
|
|||||||
|
|
||||||
### Links to prebuilt binaries
|
### Links to prebuilt binaries
|
||||||
|
|
||||||
##### Latest version (3.6.4)
|
##### Latest version (3.13.1)
|
||||||
|
|
||||||
Requires Java 7 or later.
|
The latest version that will run on Java 7 is 3.9.4. Later versions will require Java 8 or later.
|
||||||
|
|
||||||
Common dependencies
|
Common dependencies
|
||||||
* [common-lang-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.6.4/common-lang-3.6.4.jar)
|
* [common-lang-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.13.1/common-lang-3.13.1.jar)
|
||||||
* [common-io-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.6.4/common-io-3.6.4.jar)
|
* [common-io-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.13.1/common-io-3.13.1.jar)
|
||||||
* [common-image-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.6.4/common-image-3.6.4.jar)
|
* [common-image-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.13.1/common-image-3.13.1.jar)
|
||||||
|
|
||||||
ImageIO dependencies
|
ImageIO dependencies
|
||||||
* [imageio-core-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.6.4/imageio-core-3.6.4.jar)
|
* [imageio-core-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.13.1/imageio-core-3.13.1.jar)
|
||||||
* [imageio-metadata-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.6.4/imageio-metadata-3.6.4.jar)
|
* [imageio-metadata-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.13.1/imageio-metadata-3.13.1.jar)
|
||||||
|
|
||||||
ImageIO plugins
|
ImageIO plugins
|
||||||
* [imageio-bmp-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.6.4/imageio-bmp-3.6.4.jar)
|
* [imageio-bmp-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-bmp/3.13.1/imageio-bmp-3.13.1.jar)
|
||||||
* [imageio-hdr-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.6.4/imageio-hdr-3.6.4.jar)
|
* [imageio-dds-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-dds/3.13.1/imageio-dds-3.13.1.jar)
|
||||||
* [imageio-icns-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.6.4/imageio-icns-3.6.4.jar)
|
* [imageio-hdr-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-hdr/3.13.1/imageio-hdr-3.13.1.jar)
|
||||||
* [imageio-iff-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.6.4/imageio-iff-3.6.4.jar)
|
* [imageio-icns-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.13.1/imageio-icns-3.13.1.jar)
|
||||||
* [imageio-jpeg-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.6.4/imageio-jpeg-3.6.4.jar)
|
* [imageio-iff-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.13.1/imageio-iff-3.13.1.jar)
|
||||||
* [imageio-pcx-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.6.4/imageio-pcx-3.6.4.jar)
|
* [imageio-jpeg-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.13.1/imageio-jpeg-3.13.1.jar)
|
||||||
* [imageio-pict-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.6.4/imageio-pict-3.6.4.jar)
|
* [imageio-pcx-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pcx/3.13.1/imageio-pcx-3.13.1.jar)
|
||||||
* [imageio-pnm-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.6.4/imageio-pnm-3.6.4.jar)
|
* [imageio-pict-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.13.1/imageio-pict-3.13.1.jar)
|
||||||
* [imageio-psd-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.6.4/imageio-psd-3.6.4.jar)
|
* [imageio-pnm-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pnm/3.13.1/imageio-pnm-3.13.1.jar)
|
||||||
* [imageio-sgi-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.6.4/imageio-sgi-3.6.4.jar)
|
* [imageio-psd-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.13.1/imageio-psd-3.13.1.jar)
|
||||||
* [imageio-tga-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.6.4/imageio-tga-3.6.4.jar)
|
* [imageio-sgi-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-sgi/3.13.1/imageio-sgi-3.13.1.jar)
|
||||||
* [imageio-thumbsdb-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.6.4/imageio-thumbsdb-3.6.4.jar)
|
* [imageio-tga-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tga/3.13.1/imageio-tga-3.13.1.jar)
|
||||||
* [imageio-tiff-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.6.4/imageio-tiff-3.6.4.jar)
|
* [imageio-thumbsdb-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.13.1/imageio-thumbsdb-3.13.1.jar)
|
||||||
|
* [imageio-tiff-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.13.1/imageio-tiff-3.13.1.jar)
|
||||||
|
* [imageio-webp-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-webp/3.13.1/imageio-webp-3.13.1.jar)
|
||||||
|
* [imageio-xwd-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-xwd/3.13.1/imageio-xwd-3.13.1.jar)
|
||||||
|
|
||||||
ImageIO plugins requiring 3rd party libs
|
ImageIO plugins requiring 3rd party libs
|
||||||
* [imageio-batik-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.6.4/imageio-batik-3.6.4.jar)
|
* [imageio-batik-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.13.1/imageio-batik-3.13.1.jar)
|
||||||
|
|
||||||
Photoshop Path support for ImageIO
|
Photoshop Path support for ImageIO
|
||||||
* [imageio-clippath-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.6.4/imageio-clippath-3.6.4.jar)
|
* [imageio-clippath-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-clippath/3.13.1/imageio-clippath-3.13.1.jar)
|
||||||
|
|
||||||
Servlet support
|
Servlet support
|
||||||
* [servlet-3.6.4.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.6.4/servlet-3.6.4.jar)
|
* [servlet-3.13.1.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.13.1/servlet-3.13.1.jar) for legacy Java EE (javax.servlet)
|
||||||
|
* [servlet-3.13.1-jakarta.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.13.1/servlet-3.13.1-jakrta.jar) for Jakarta EE (jakarta.servlet)
|
||||||
##### Old version (3.0.x)
|
|
||||||
|
|
||||||
Use this version for projects that requires Java 6 or need the JMagick support. *Does not support Java 8 or later*.
|
|
||||||
|
|
||||||
Common dependencies
|
|
||||||
* [common-lang-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.0.2/common-lang-3.0.2.jar)
|
|
||||||
* [common-io-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.0.2/common-io-3.0.2.jar)
|
|
||||||
* [common-image-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.0.2/common-image-3.0.2.jar)
|
|
||||||
|
|
||||||
ImageIO dependencies
|
|
||||||
* [imageio-core-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.0.2/imageio-core-3.0.2.jar)
|
|
||||||
* [imageio-metadata-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.0.2/imageio-metadata-3.0.2.jar)
|
|
||||||
|
|
||||||
ImageIO plugins
|
|
||||||
* [imageio-jpeg-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.0.2/imageio-jpeg-3.0.2.jar)
|
|
||||||
* [imageio-tiff-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.0.2/imageio-tiff-3.0.2.jar)
|
|
||||||
* [imageio-psd-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.0.2/imageio-psd-3.0.2.jar)
|
|
||||||
* [imageio-pict-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.0.2/imageio-pict-3.0.2.jar)
|
|
||||||
* [imageio-iff-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.0.2/imageio-iff-3.0.2.jar)
|
|
||||||
* [imageio-icns-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.0.2/imageio-icns-3.0.2.jar)
|
|
||||||
* [imageio-ico-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-ico/3.0.2/imageio-ico-3.0.2.jar)
|
|
||||||
* [imageio-thumbsdb-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.0.2/imageio-thumbsdb-3.0.2.jar)
|
|
||||||
|
|
||||||
ImageIO plugins requiring 3rd party libs
|
|
||||||
* [imageio-batik-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.0.2/imageio-batik-3.0.2.jar)
|
|
||||||
* [imageio-jmagick-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jmagick/3.0.2/imageio-jmagick-3.0.2.jar)
|
|
||||||
|
|
||||||
Servlet support
|
|
||||||
* [servlet-3.0.2.jar](http://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.0.2/servlet-3.0.2.jar)
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is provided under the OSI approved [BSD license](http://opensource.org/licenses/BSD-3-Clause):
|
This project is provided under the OSI approved [BSD license](https://opensource.org/licenses/BSD-3-Clause):
|
||||||
|
|
||||||
Copyright (c) 2008-2020, Harald Kuhr
|
Copyright (c) 2008-2022, Harald Kuhr
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
@@ -474,8 +509,9 @@ This project is provided under the OSI approved [BSD license](http://opensource.
|
|||||||
|
|
||||||
q: How do I use it?
|
q: How do I use it?
|
||||||
|
|
||||||
a: The easiest way is to build your own project using Maven, and just add dependencies to the specific plug-ins you need.
|
a: The easiest way is to build your own project using Maven, Gradle or other build tool with dependency management,
|
||||||
If you don't use Maven, make sure you have all the necessary JARs in classpath. See the Install section above.
|
and just add dependencies to the specific plug-ins you need.
|
||||||
|
If you don't use such a build tool, make sure you have all the necessary JARs in classpath. See the Install section above.
|
||||||
|
|
||||||
|
|
||||||
q: What changes do I have to make to my code in order to use the plug-ins?
|
q: What changes do I have to make to my code in order to use the plug-ins?
|
||||||
@@ -493,27 +529,41 @@ q: How does it work?
|
|||||||
|
|
||||||
a: The TwelveMonkeys ImageIO project contains plug-ins for ImageIO. ImageIO uses a service lookup mechanism, to discover plug-ins at runtime.
|
a: The TwelveMonkeys ImageIO project contains plug-ins for ImageIO. ImageIO uses a service lookup mechanism, to discover plug-ins at runtime.
|
||||||
|
|
||||||
All you have have to do, is to make sure you have the TwelveMonkeys JARs in your classpath.
|
All you have to do, is to make sure you have the TwelveMonkeys ImageIO JARs in your classpath.
|
||||||
|
|
||||||
You can read more about the registry and the lookup mechanism in the [IIORegistry API doc](http://docs.oracle.com/javase/7/docs/api/javax/imageio/spi/IIORegistry.html).
|
You can read more about the registry and the lookup mechanism in the [IIORegistry API doc](https://docs.oracle.com/javase/7/docs/api/javax/imageio/spi/IIORegistry.html).
|
||||||
|
|
||||||
The fine print: The TwelveMonkeys service providers for JPEG, BMP and TIFF, overrides the onRegistration method, and
|
The fine print: The TwelveMonkeys service providers for JPEG, BMP and TIFF, overrides the onRegistration method, and
|
||||||
utilizes the pairwise partial ordering mechanism of the `IIOServiceRegistry` to make sure it is installed before
|
utilizes the pairwise partial ordering mechanism of the `IIOServiceRegistry` to make sure it is installed before
|
||||||
the Sun/Oracle provided `JPEGImageReader` and `BMPImageReader`, and the Apple provided `TIFFImageReader` on OS X,
|
the Sun/Oracle provided `JPEGImageReader`, `BMPImageReader` `TIFFImageReader`, and the Apple provided `TIFFImageReader` on OS X,
|
||||||
respectively. Using the pairwise ordering will not remove any functionality form these implementations, but in most
|
respectively. Using the pairwise ordering will not remove any functionality form these implementations, but in most
|
||||||
cases you'll end up using the TwelveMonkeys plug-ins instead.
|
cases you'll end up using the TwelveMonkeys plug-ins instead.
|
||||||
|
|
||||||
|
|
||||||
q: Why is there no support for common formats like GIF or PNG?
|
q: Why is there no support for common formats like GIF or PNG?
|
||||||
|
|
||||||
a: The short answer is simply that the built-in support in ImageIO for these formats are good enough as-is.
|
a: The short answer is simply that the built-in support in ImageIO for these formats are considered good enough as-is.
|
||||||
If you are looking for better PNG write performance on Java 7 and 8, see [JDK9 PNG Writer Backport](https://github.com/gredler/jdk9-png-writer-backport).
|
If you are looking for better PNG write performance on Java 7 and 8, see [JDK9 PNG Writer Backport](https://github.com/gredler/jdk9-png-writer-backport).
|
||||||
|
|
||||||
|
|
||||||
|
q: When is the next release? What is the current release schedule?
|
||||||
|
|
||||||
|
a: The goal is to make monthly releases, containing bug fixes and minor new features.
|
||||||
|
And quarterly releases with more "major" features.
|
||||||
|
|
||||||
|
|
||||||
|
q: I love this project! How can I help?
|
||||||
|
|
||||||
|
a: Have a look at the open issues, and see if there are any issues you can help fix, or provide sample file or create test cases for.
|
||||||
|
It is also possible for you or your organization to become a sponsor, through GitHub Sponsors.
|
||||||
|
Providing funding will allow us to spend more time on fixing bugs and implementing new features.
|
||||||
|
|
||||||
|
|
||||||
q: What about JAI? Several of the formats are already supported by JAI.
|
q: What about JAI? Several of the formats are already supported by JAI.
|
||||||
|
|
||||||
a: While JAI (and jai-imageio in particular) have support for some of the same formats, JAI has some major issues.
|
a: While JAI (and jai-imageio in particular) have support for some of the same formats, JAI has some major issues.
|
||||||
The most obvious being:
|
The most obvious being:
|
||||||
- It's not actively developed. No issues has been fixed for years.
|
- It's not actively developed. No issue has been fixed for years.
|
||||||
- To get full format support, you need native libs.
|
- To get full format support, you need native libs.
|
||||||
Native libs does not exist for several popular platforms/architectures, and further the native libs are not open source.
|
Native libs does not exist for several popular platforms/architectures, and further the native libs are not open source.
|
||||||
Some environments may also prevent deployment of native libs, which brings us back to square one.
|
Some environments may also prevent deployment of native libs, which brings us back to square one.
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
To report a security issue, please disclose it at [security advisory](https://github.com/haraldk/TwelveMonkeys/security/advisories/new).
|
||||||
|
|
||||||
|
Vulnerabilities will be disclosed in a best effort base.
|
||||||
+11
-1
@@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.7.0</version>
|
<version>3.13.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>com.twelvemonkeys.bom</groupId>
|
<groupId>com.twelvemonkeys.bom</groupId>
|
||||||
@@ -63,6 +63,11 @@
|
|||||||
<artifactId>imageio-hdr</artifactId>
|
<artifactId>imageio-hdr</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
|
<artifactId>imageio-dds</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-icns</artifactId>
|
<artifactId>imageio-icns</artifactId>
|
||||||
@@ -123,6 +128,11 @@
|
|||||||
<artifactId>imageio-tiff</artifactId>
|
<artifactId>imageio-tiff</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
|
<artifactId>imageio-webp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio-xwd</artifactId>
|
<artifactId>imageio-xwd</artifactId>
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.7.0</version>
|
<version>3.13.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>common-image</artifactId>
|
<artifactId>common-image</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TwelveMonkeys :: Common :: Image</name>
|
<name>TwelveMonkeys :: Common :: Image</name>
|
||||||
<description>
|
<description>
|
||||||
The TwelveMonkeys Common Image support
|
TwelveMonkeys Common image support classes.
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -28,12 +28,14 @@
|
|||||||
<artifactId>common-io</artifactId>
|
<artifactId>common-io</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>jmagick</groupId>
|
|
||||||
<artifactId>jmagick</artifactId>
|
|
||||||
<version>6.2.4</version>
|
|
||||||
<optional>true</optional>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -34,7 +34,13 @@ import java.awt.*;
|
|||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.awt.image.*;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.BufferedImageOp;
|
||||||
|
import java.awt.image.ColorModel;
|
||||||
|
import java.awt.image.ImagingOpException;
|
||||||
|
import java.awt.image.Raster;
|
||||||
|
import java.awt.image.RasterOp;
|
||||||
|
import java.awt.image.WritableRaster;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a drop-in replacement for {@link java.awt.image.AffineTransformOp}.
|
* This is a drop-in replacement for {@link java.awt.image.AffineTransformOp}.
|
||||||
@@ -70,6 +76,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp {
|
|||||||
delegate = new java.awt.image.AffineTransformOp(xform, interpolationType);
|
delegate = new java.awt.image.AffineTransformOp(xform, interpolationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
@Override
|
@Override
|
||||||
public BufferedImage filter(final BufferedImage src, BufferedImage dst) {
|
public BufferedImage filter(final BufferedImage src, BufferedImage dst) {
|
||||||
try {
|
try {
|
||||||
@@ -80,10 +87,9 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp {
|
|||||||
dst = createCompatibleDestImage(src, src.getColorModel());
|
dst = createCompatibleDestImage(src, src.getColorModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
Graphics2D g2d = null;
|
Graphics2D g2d = dst.createGraphics();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
g2d = dst.createGraphics();
|
|
||||||
int interpolationType = delegate.getInterpolationType();
|
int interpolationType = delegate.getInterpolationType();
|
||||||
|
|
||||||
if (interpolationType > 0) {
|
if (interpolationType > 0) {
|
||||||
@@ -109,9 +115,7 @@ public class AffineTransformOp implements BufferedImageOp, RasterOp {
|
|||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (g2d != null) {
|
g2d.dispose();
|
||||||
g2d.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+96
-86
@@ -79,7 +79,7 @@ public final class BufferedImageFactory {
|
|||||||
private int scanSize;
|
private int scanSize;
|
||||||
|
|
||||||
private ColorModel sourceColorModel;
|
private ColorModel sourceColorModel;
|
||||||
private Hashtable sourceProperties; // ImageConsumer API dictates Hashtable
|
private Hashtable<?, ?> sourceProperties; // ImageConsumer API dictates Hashtable
|
||||||
|
|
||||||
private Object sourcePixels;
|
private Object sourcePixels;
|
||||||
|
|
||||||
@@ -91,21 +91,21 @@ public final class BufferedImageFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code BufferedImageFactory}.
|
* Creates a {@code BufferedImageFactory}.
|
||||||
* @param pSource the source image
|
* @param source the source image
|
||||||
* @throws IllegalArgumentException if {@code pSource == null}
|
* @throws IllegalArgumentException if {@code source == null}
|
||||||
*/
|
*/
|
||||||
public BufferedImageFactory(final Image pSource) {
|
public BufferedImageFactory(final Image source) {
|
||||||
this(pSource != null ? pSource.getSource() : null);
|
this(source != null ? source.getSource() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code BufferedImageFactory}.
|
* Creates a {@code BufferedImageFactory}.
|
||||||
* @param pSource the source image producer
|
* @param source the source image producer
|
||||||
* @throws IllegalArgumentException if {@code pSource == null}
|
* @throws IllegalArgumentException if {@code source == null}
|
||||||
*/
|
*/
|
||||||
public BufferedImageFactory(final ImageProducer pSource) {
|
public BufferedImageFactory(final ImageProducer source) {
|
||||||
Validate.notNull(pSource, "source");
|
Validate.notNull(source, "source");
|
||||||
producer = pSource;
|
producer = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -155,44 +155,44 @@ public final class BufferedImageFactory {
|
|||||||
/**
|
/**
|
||||||
* Sets the source region (AOI) for the new image.
|
* Sets the source region (AOI) for the new image.
|
||||||
*
|
*
|
||||||
* @param pRegion the source region
|
* @param region the source region
|
||||||
*/
|
*/
|
||||||
public void setSourceRegion(final Rectangle pRegion) {
|
public void setSourceRegion(final Rectangle region) {
|
||||||
// Re-fetch everything, if region changed
|
// Re-fetch everything, if region changed
|
||||||
if (x != pRegion.x || y != pRegion.y || width != pRegion.width || height != pRegion.height) {
|
if (x != region.x || y != region.y || width != region.width || height != region.height) {
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
x = pRegion.x;
|
x = region.x;
|
||||||
y = pRegion.y;
|
y = region.y;
|
||||||
width = pRegion.width;
|
width = region.width;
|
||||||
height = pRegion.height;
|
height = region.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the source subsampling for the new image.
|
* Sets the source subsampling for the new image.
|
||||||
*
|
*
|
||||||
* @param pXSub horizontal subsampling factor
|
* @param xSubsampling horizontal subsampling factor
|
||||||
* @param pYSub vertical subsampling factor
|
* @param ySubsampling vertical subsampling factor
|
||||||
*/
|
*/
|
||||||
public void setSourceSubsampling(int pXSub, int pYSub) {
|
public void setSourceSubsampling(int xSubsampling, int ySubsampling) {
|
||||||
// Re-fetch everything, if subsampling changed
|
// Re-fetch everything, if subsampling changed
|
||||||
if (xSub != pXSub || ySub != pYSub) {
|
if (xSub != xSubsampling || ySub != ySubsampling) {
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pXSub > 1) {
|
if (xSubsampling > 1) {
|
||||||
xSub = pXSub;
|
xSub = xSubsampling;
|
||||||
}
|
}
|
||||||
if (pYSub > 1) {
|
if (ySubsampling > 1) {
|
||||||
ySub = pYSub;
|
ySub = ySubsampling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void doFetch(boolean pColorModelOnly) throws ImageConversionException {
|
private synchronized void doFetch(final boolean colorModelOnly) throws ImageConversionException {
|
||||||
if (!fetching && (!pColorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
|
if (!fetching && (!colorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
|
||||||
// NOTE: Subsampling is only applied if extracting full image
|
// NOTE: Subsampling is only applied if extracting full image
|
||||||
if (!pColorModelOnly && (xSub > 1 || ySub > 1)) {
|
if (!colorModelOnly && (xSub > 1 || ySub > 1)) {
|
||||||
// If only sampling a region, the region must be scaled too
|
// If only sampling a region, the region must be scaled too
|
||||||
if (width > 0 && height > 0) {
|
if (width > 0 && height > 0) {
|
||||||
width = (width + xSub - 1) / xSub;
|
width = (width + xSub - 1) / xSub;
|
||||||
@@ -207,38 +207,41 @@ public final class BufferedImageFactory {
|
|||||||
|
|
||||||
// Start fetching
|
// Start fetching
|
||||||
fetching = true;
|
fetching = true;
|
||||||
readColorModelOnly = pColorModelOnly;
|
readColorModelOnly = colorModelOnly;
|
||||||
|
|
||||||
producer.startProduction(consumer); // Note: If single-thread (synchronous), this call will block
|
producer.startProduction(consumer); // Note: If single-thread (synchronous), this call will block
|
||||||
|
|
||||||
// Wait until the producer wakes us up, by calling imageComplete
|
// Wait until the producer wakes us up, by calling imageComplete
|
||||||
while (fetching) {
|
while (fetching) {
|
||||||
try {
|
try {
|
||||||
wait(200l);
|
wait(200L);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e) {
|
catch (InterruptedException e) {
|
||||||
throw new ImageConversionException("Image conversion aborted: " + e.getMessage(), e);
|
throw new ImageConversionException("Image conversion aborted: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (consumerException != null) {
|
try {
|
||||||
throw new ImageConversionException("Image conversion failed: " + consumerException.getMessage(), consumerException);
|
if (consumerException != null) {
|
||||||
}
|
throw new ImageConversionException("Image conversion failed: " + consumerException.getMessage(), consumerException);
|
||||||
|
}
|
||||||
|
|
||||||
if (pColorModelOnly) {
|
if (colorModelOnly) {
|
||||||
createColorModel();
|
createColorModel();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
createBuffered();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
finally {
|
||||||
createBuffered();
|
// Clean up, in case any objects are copied/cloned, so we can free resources
|
||||||
|
freeResources();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createColorModel() {
|
private void createColorModel() {
|
||||||
colorModel = sourceColorModel;
|
colorModel = sourceColorModel;
|
||||||
|
|
||||||
// Clean up, in case any objects are copied/cloned, so we can free resources
|
|
||||||
freeResources();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBuffered() {
|
private void createBuffered() {
|
||||||
@@ -253,8 +256,9 @@ public final class BufferedImageFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up, in case any objects are copied/cloned, so we can free resources
|
if (buffered == null) {
|
||||||
freeResources();
|
throw new ImageConversionException("Could not create BufferedImage");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void freeResources() {
|
private void freeResources() {
|
||||||
@@ -280,27 +284,27 @@ public final class BufferedImageFactory {
|
|||||||
/**
|
/**
|
||||||
* Adds a progress listener to this factory.
|
* Adds a progress listener to this factory.
|
||||||
*
|
*
|
||||||
* @param pListener the progress listener
|
* @param listener the progress listener
|
||||||
*/
|
*/
|
||||||
public void addProgressListener(ProgressListener pListener) {
|
public void addProgressListener(ProgressListener listener) {
|
||||||
if (pListener == null) {
|
if (listener == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listeners == null) {
|
if (listeners == null) {
|
||||||
listeners = new CopyOnWriteArrayList<ProgressListener>();
|
listeners = new CopyOnWriteArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
listeners.add(pListener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a progress listener from this factory.
|
* Removes a progress listener from this factory.
|
||||||
*
|
*
|
||||||
* @param pListener the progress listener
|
* @param listener the progress listener
|
||||||
*/
|
*/
|
||||||
public void removeProgressListener(ProgressListener pListener) {
|
public void removeProgressListener(ProgressListener listener) {
|
||||||
if (pListener == null) {
|
if (listener == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +312,7 @@ public final class BufferedImageFactory {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
listeners.remove(pListener);
|
listeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -324,21 +328,22 @@ public final class BufferedImageFactory {
|
|||||||
* Converts an array of {@code int} pixels to an array of {@code short}
|
* Converts an array of {@code int} pixels to an array of {@code short}
|
||||||
* pixels. The conversion is done, by masking out the
|
* pixels. The conversion is done, by masking out the
|
||||||
* <em>higher 16 bits</em> of the {@code int}.
|
* <em>higher 16 bits</em> of the {@code int}.
|
||||||
*
|
* <p>
|
||||||
* For any given {@code int}, the {@code short} value is computed as
|
* For any given {@code int}, the {@code short} value is computed as
|
||||||
* follows:
|
* follows:
|
||||||
* <blockquote>{@code
|
* <blockquote>{@code
|
||||||
* short value = (short) (intValue & 0x0000ffff);
|
* short value = (short) (intValue & 0x0000ffff);
|
||||||
* }</blockquote>
|
* }</blockquote>
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param pPixels the pixel data to convert
|
* @param inputPixels the pixel data to convert
|
||||||
* @return an array of {@code short}s, same lenght as {@code pPixels}
|
* @return an array of {@code short}s, same length as {@code inputPixels}
|
||||||
*/
|
*/
|
||||||
private static short[] toShortPixels(int[] pPixels) {
|
private static short[] toShortPixels(int[] inputPixels) {
|
||||||
short[] pixels = new short[pPixels.length];
|
short[] pixels = new short[inputPixels.length];
|
||||||
|
|
||||||
for (int i = 0; i < pixels.length; i++) {
|
for (int i = 0; i < pixels.length; i++) {
|
||||||
pixels[i] = (short) (pPixels[i] & 0xffff);
|
pixels[i] = (short) (inputPixels[i] & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pixels;
|
return pixels;
|
||||||
@@ -351,17 +356,17 @@ public final class BufferedImageFactory {
|
|||||||
* @see BufferedImageFactory#addProgressListener
|
* @see BufferedImageFactory#addProgressListener
|
||||||
* @see BufferedImageFactory#removeProgressListener
|
* @see BufferedImageFactory#removeProgressListener
|
||||||
*/
|
*/
|
||||||
public static interface ProgressListener extends EventListener {
|
public interface ProgressListener extends EventListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports progress to this listener.
|
* Reports progress to this listener.
|
||||||
* Invoked by the {@code BufferedImageFactory} to report progress in
|
* Invoked by the {@code BufferedImageFactory} to report progress in
|
||||||
* the image decoding.
|
* the image decoding.
|
||||||
*
|
*
|
||||||
* @param pFactory the factory reporting the progress
|
* @param factory the factory reporting the progress
|
||||||
* @param pPercentage the percentage of progress
|
* @param percentage the percentage of progress
|
||||||
*/
|
*/
|
||||||
void progress(BufferedImageFactory pFactory, float pPercentage);
|
void progress(BufferedImageFactory factory, float percentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Consumer implements ImageConsumer {
|
private class Consumer implements ImageConsumer {
|
||||||
@@ -446,18 +451,18 @@ public final class BufferedImageFactory {
|
|||||||
processProgress(pY + pHeight);
|
processProgress(pY + pHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPixels(int pX, int pY, int pWidth, int pHeight, ColorModel pModel, short[] pPixels, int pOffset, int pScanSize) {
|
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, short[] pixels, int offset, int scanSize) {
|
||||||
setPixelsImpl(pX, pY, pWidth, pHeight, pModel, pPixels, pOffset, pScanSize);
|
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setColorModelOnce(final ColorModel pModel) {
|
private void setColorModelOnce(final ColorModel colorModel) {
|
||||||
// NOTE: There seems to be a "bug" in AreaAveragingScaleFilter, as it
|
// NOTE: There seems to be a "bug" in AreaAveragingScaleFilter, as it
|
||||||
// first passes the original color model through in setColorModel, then
|
// first passes the original color model through in setColorModel, then
|
||||||
// later replaces it with the default RGB in the first setPixels call
|
// later replaces it with the default RGB in the first setPixels call
|
||||||
// (this is probably allowed according to the spec, but it's a waste of time and space).
|
// (this is probably allowed according to the spec, but it's a waste of time and space).
|
||||||
if (sourceColorModel != pModel) {
|
if (sourceColorModel != colorModel) {
|
||||||
if (/*sourceColorModel == null ||*/ sourcePixels == null) {
|
if (sourcePixels == null) {
|
||||||
sourceColorModel = pModel;
|
sourceColorModel = colorModel;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new IllegalStateException("Change of ColorModel after pixel delivery not supported");
|
throw new IllegalStateException("Change of ColorModel after pixel delivery not supported");
|
||||||
@@ -470,17 +475,16 @@ public final class BufferedImageFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void imageComplete(int pStatus) {
|
@Override
|
||||||
|
public void imageComplete(int status) {
|
||||||
fetching = false;
|
fetching = false;
|
||||||
|
|
||||||
if (producer != null) {
|
if (producer != null) {
|
||||||
producer.removeConsumer(this);
|
producer.removeConsumer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pStatus) {
|
if (status == ImageConsumer.IMAGEERROR) {
|
||||||
case ImageConsumer.IMAGEERROR:
|
consumerException = new ImageConversionException("ImageConsumer.IMAGEERROR");
|
||||||
consumerException = new ImageConversionException("ImageConsumer.IMAGEERROR");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (BufferedImageFactory.this) {
|
synchronized (BufferedImageFactory.this) {
|
||||||
@@ -488,16 +492,18 @@ public final class BufferedImageFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setColorModel(ColorModel pModel) {
|
@Override
|
||||||
setColorModelOnce(pModel);
|
public void setColorModel(ColorModel colorModel) {
|
||||||
|
setColorModelOnce(colorModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDimensions(int pWidth, int pHeight) {
|
@Override
|
||||||
|
public void setDimensions(int w, int h) {
|
||||||
if (width < 0) {
|
if (width < 0) {
|
||||||
width = pWidth - x;
|
width = w - x;
|
||||||
}
|
}
|
||||||
if (height < 0) {
|
if (height < 0) {
|
||||||
height = pHeight - y;
|
height = h - y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hmm.. Special case, but is it a good idea?
|
// Hmm.. Special case, but is it a good idea?
|
||||||
@@ -506,27 +512,31 @@ public final class BufferedImageFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHints(int pHintflags) {
|
@Override
|
||||||
|
public void setHints(int hintFlags) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPixels(int pX, int pY, int pWidth, int pHeight, ColorModel pModel, byte[] pPixels, int pOffset, int pScanSize) {
|
@Override
|
||||||
setPixelsImpl(pX, pY, pWidth, pHeight, pModel, pPixels, pOffset, pScanSize);
|
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, byte[] pixels, int offset, int scanSize) {
|
||||||
|
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPixels(int pX, int pY, int pWeigth, int pHeight, ColorModel pModel, int[] pPixels, int pOffset, int pScanSize) {
|
@Override
|
||||||
if (pModel.getTransferType() == DataBuffer.TYPE_USHORT) {
|
public void setPixels(int x, int y, int width, int height, ColorModel colorModel, int[] pixels, int offset, int scanSize) {
|
||||||
|
if (colorModel.getTransferType() == DataBuffer.TYPE_USHORT) {
|
||||||
// NOTE: Workaround for limitation in ImageConsumer API
|
// NOTE: Workaround for limitation in ImageConsumer API
|
||||||
// Convert int[] to short[], to be compatible with the ColorModel
|
// Convert int[] to short[], to be compatible with the ColorModel
|
||||||
setPixelsImpl(pX, pY, pWeigth, pHeight, pModel, toShortPixels(pPixels), pOffset, pScanSize);
|
setPixelsImpl(x, y, width, height, colorModel, toShortPixels(pixels), offset, scanSize);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setPixelsImpl(pX, pY, pWeigth, pHeight, pModel, pPixels, pOffset, pScanSize);
|
setPixelsImpl(x, y, width, height, colorModel, pixels, offset, scanSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProperties(Hashtable pProperties) {
|
@Override
|
||||||
sourceProperties = pProperties;
|
public void setProperties(Hashtable properties) {
|
||||||
|
sourceProperties = properties;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ import java.awt.image.BufferedImage;
|
|||||||
*/
|
*/
|
||||||
public class BufferedImageIcon implements Icon {
|
public class BufferedImageIcon implements Icon {
|
||||||
private final BufferedImage image;
|
private final BufferedImage image;
|
||||||
private int width;
|
private final int width;
|
||||||
private int height;
|
private final int height;
|
||||||
private final boolean fast;
|
private final boolean fast;
|
||||||
|
|
||||||
public BufferedImageIcon(BufferedImage pImage) {
|
public BufferedImageIcon(BufferedImage pImage) {
|
||||||
@@ -81,11 +81,10 @@ public class BufferedImageIcon implements Icon {
|
|||||||
else {
|
else {
|
||||||
//System.out.println("Scaling using interpolation");
|
//System.out.println("Scaling using interpolation");
|
||||||
Graphics2D g2 = (Graphics2D) g;
|
Graphics2D g2 = (Graphics2D) g;
|
||||||
AffineTransform xform = AffineTransform.getTranslateInstance(x, y);
|
AffineTransform transform = AffineTransform.getTranslateInstance(x, y);
|
||||||
xform.scale(width / (double) image.getWidth(), height / (double) image.getHeight());
|
transform.scale(width / (double) image.getWidth(), height / (double) image.getHeight());
|
||||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
|
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||||
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
g2.drawImage(image, transform, null);
|
||||||
g2.drawImage(image, xform, null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ import java.util.Random;
|
|||||||
* |3|5|1|
|
* |3|5|1|
|
||||||
* - - -->
|
* - - -->
|
||||||
* </p>
|
* </p>
|
||||||
* <table border="1" cellpadding="4" cellspacing="0">
|
* <table border="1">
|
||||||
* <caption>Floyd-Steinberg error-diffusion weights</caption>
|
* <caption>Floyd-Steinberg error-diffusion weights</caption>
|
||||||
* <tr><td bgcolor="#000000"> </td><td class="TableHeadingColor"
|
* <tr><td style="background:#000000"> </td><td class="TableHeadingColor"
|
||||||
* align="center">x</td><td>7/16</td></tr>
|
* style="text-align:center">x</td><td>7/16</td></tr>
|
||||||
* <tr><td>3/16</td><td>5/16</td><td>1/16</td></tr>
|
* <tr><td>3/16</td><td>5/16</td><td>1/16</td></tr>
|
||||||
* </table>
|
* </table>
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public final class ImageUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The sharpen kernel. Uses the following 3 by 3 matrix:
|
* The sharpen kernel. Uses the following 3 by 3 matrix:
|
||||||
* <table border="1" cellspacing="0">
|
* <table border="1">
|
||||||
* <caption>Sharpen Kernel Matrix</caption>
|
* <caption>Sharpen Kernel Matrix</caption>
|
||||||
* <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
|
* <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
|
||||||
* <tr><td>-0.3</td><td>2.2</td><td>-0.3</td></tr>
|
* <tr><td>-0.3</td><td>2.2</td><td>-0.3</td></tr>
|
||||||
@@ -844,7 +844,7 @@ public final class ImageUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i > mapSize1; i++) {
|
for (int i = 0; i < mapSize1; i++) {
|
||||||
if (icm1.getRGB(i) != icm2.getRGB(i)) {
|
if (icm1.getRGB(i) != icm2.getRGB(i)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1078,7 +1078,7 @@ public final class ImageUtil {
|
|||||||
/**
|
/**
|
||||||
* Sharpens an image using a convolution matrix.
|
* Sharpens an image using a convolution matrix.
|
||||||
* The sharpen kernel used, is defined by the following 3 by 3 matrix:
|
* The sharpen kernel used, is defined by the following 3 by 3 matrix:
|
||||||
* <table border="1" cellspacing="0">
|
* <table border="1">
|
||||||
* <caption>Sharpen Kernel Matrix</caption>
|
* <caption>Sharpen Kernel Matrix</caption>
|
||||||
* <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
|
* <tr><td>0.0</td><td>-0.3</td><td>0.0</td></tr>
|
||||||
* <tr><td>-0.3</td><td>2.2</td><td>-0.3</td></tr>
|
* <tr><td>-0.3</td><td>2.2</td><td>-0.3</td></tr>
|
||||||
@@ -1100,7 +1100,7 @@ public final class ImageUtil {
|
|||||||
/**
|
/**
|
||||||
* Sharpens an image using a convolution matrix.
|
* Sharpens an image using a convolution matrix.
|
||||||
* The sharpen kernel used, is defined by the following 3 by 3 matrix:
|
* The sharpen kernel used, is defined by the following 3 by 3 matrix:
|
||||||
* <table border="1" cellspacing="0">
|
* <table border="1">
|
||||||
* <caption>Sharpen Kernel Matrix</caption>
|
* <caption>Sharpen Kernel Matrix</caption>
|
||||||
* <tr><td>0.0</td><td>-{@code pAmount}</td><td>0.0</td></tr>
|
* <tr><td>0.0</td><td>-{@code pAmount}</td><td>0.0</td></tr>
|
||||||
* <tr><td>-{@code pAmount}</td>
|
* <tr><td>-{@code pAmount}</td>
|
||||||
|
|||||||
@@ -587,6 +587,7 @@ class IndexImage {
|
|||||||
* @deprecated Use {@link #getIndexColorModel(Image,int,int)} instead!
|
* @deprecated Use {@link #getIndexColorModel(Image,int,int)} instead!
|
||||||
* This version will be removed in a later version of the API.
|
* This version will be removed in a later version of the API.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static IndexColorModel getIndexColorModel(Image pImage, int pNumberOfColors, boolean pFast) {
|
public static IndexColorModel getIndexColorModel(Image pImage, int pNumberOfColors, boolean pFast) {
|
||||||
return getIndexColorModel(pImage, pNumberOfColors, pFast ? COLOR_SELECTION_FAST : COLOR_SELECTION_QUALITY);
|
return getIndexColorModel(pImage, pNumberOfColors, pFast ? COLOR_SELECTION_FAST : COLOR_SELECTION_QUALITY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,187 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2008, Harald Kuhr
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of the copyright holder nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived from
|
|
||||||
* this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
package com.twelvemonkeys.image;
|
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.SystemUtil;
|
|
||||||
import magick.MagickImage;
|
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.awt.image.BufferedImageOp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class accelerates certain graphics operations, using
|
|
||||||
* JMagick and ImageMagick, if available.
|
|
||||||
* If those libraries are not installed, this class silently does nothing.
|
|
||||||
* <p>
|
|
||||||
* Set the system property {@code "com.twelvemonkeys.image.accel"} to
|
|
||||||
* {@code false}, to disable, even if JMagick is installed.
|
|
||||||
* Set the system property {@code "com.twelvemonkeys.image.magick.debug"} to
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
|
||||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/MagickAccelerator.java#3 $
|
|
||||||
*/
|
|
||||||
final class MagickAccelerator {
|
|
||||||
|
|
||||||
private static final boolean DEBUG = Magick.DEBUG;
|
|
||||||
private static final boolean USE_MAGICK = useMagick();
|
|
||||||
|
|
||||||
private static final int RESAMPLE_OP = 0;
|
|
||||||
|
|
||||||
private static Class[] nativeOp = new Class[1];
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
nativeOp[RESAMPLE_OP] = Class.forName("com.twelvemonkeys.image.ResampleOp");
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException e) {
|
|
||||||
System.err.println("Could not find class: " + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean useMagick() {
|
|
||||||
try {
|
|
||||||
boolean available = SystemUtil.isClassAvailable("magick.MagickImage");
|
|
||||||
|
|
||||||
if (DEBUG && !available) {
|
|
||||||
System.err.print("ImageMagick bindings not available.");
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean useMagick =
|
|
||||||
available && !"FALSE".equalsIgnoreCase(System.getProperty("com.twelvemonkeys.image.accel"));
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
System.err.println(
|
|
||||||
useMagick
|
|
||||||
? "Will use ImageMagick bindings to accelerate image resampling operations."
|
|
||||||
: "Will not use ImageMagick to accelerate image resampling operations."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return useMagick;
|
|
||||||
}
|
|
||||||
catch (Throwable t) {
|
|
||||||
// Most probably in case of a SecurityManager
|
|
||||||
System.err.println("Could not enable ImageMagick bindings: " + t);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getNativeOpIndex(Class pOpClass) {
|
|
||||||
for (int i = 0; i < nativeOp.length; i++) {
|
|
||||||
if (pOpClass == nativeOp[i]) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BufferedImage filter(BufferedImageOp pOperation, BufferedImage pInput, BufferedImage pOutput) {
|
|
||||||
if (!USE_MAGICK) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedImage result = null;
|
|
||||||
switch (getNativeOpIndex(pOperation.getClass())) {
|
|
||||||
case RESAMPLE_OP:
|
|
||||||
ResampleOp resample = (ResampleOp) pOperation;
|
|
||||||
result = resampleMagick(pInput, resample.width, resample.height, resample.filterType);
|
|
||||||
|
|
||||||
// NOTE: If output parameter is non-null, we have to return that
|
|
||||||
// image, instead of result
|
|
||||||
if (pOutput != null) {
|
|
||||||
//pOutput.setData(result.getRaster()); // Fast, but less compatible
|
|
||||||
// NOTE: For some reason, this is sometimes super-slow...?
|
|
||||||
ImageUtil.drawOnto(pOutput, result);
|
|
||||||
result = pOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Simply fall through, allowing acceleration to be added later
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BufferedImage resampleMagick(BufferedImage pSrc, int pWidth, int pHeight, int pFilterType) {
|
|
||||||
// Convert to Magick, scale and convert back
|
|
||||||
MagickImage image = null;
|
|
||||||
MagickImage scaled = null;
|
|
||||||
try {
|
|
||||||
image = MagickUtil.toMagick(pSrc);
|
|
||||||
|
|
||||||
long start = 0;
|
|
||||||
if (DEBUG) {
|
|
||||||
start = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: setFilter affects zoomImage, NOT scaleImage
|
|
||||||
image.setFilter(pFilterType);
|
|
||||||
scaled = image.zoomImage(pWidth, pHeight);
|
|
||||||
//scaled = image.scaleImage(pWidth, pHeight); // AREA_AVERAGING
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
long time = System.currentTimeMillis() - start;
|
|
||||||
System.out.println("Filtered: " + time + " ms");
|
|
||||||
}
|
|
||||||
|
|
||||||
return MagickUtil.toBuffered(scaled);
|
|
||||||
}
|
|
||||||
//catch (MagickException e) {
|
|
||||||
catch (Exception e) {
|
|
||||||
// NOTE: Stupid workaround: If MagickException is caught, a
|
|
||||||
// NoClassDefFoundError is thrown, when MagickException class is
|
|
||||||
// unavailable...
|
|
||||||
if (e instanceof RuntimeException) {
|
|
||||||
throw (RuntimeException) e;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ImageConversionException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
// NOTE: ImageMagick might be unstable after a while, if image data
|
|
||||||
// is not deallocated. The GC/finalize method handles this, but in
|
|
||||||
// special circumstances, it's not triggered often enough.
|
|
||||||
if (image != null) {
|
|
||||||
image.destroyImages();
|
|
||||||
}
|
|
||||||
if (scaled != null) {
|
|
||||||
scaled.destroyImages();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,621 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2008, Harald Kuhr
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of the copyright holder nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived from
|
|
||||||
* this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.twelvemonkeys.image;
|
|
||||||
|
|
||||||
import magick.ImageType;
|
|
||||||
import magick.MagickException;
|
|
||||||
import magick.MagickImage;
|
|
||||||
import magick.PixelPacket;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.color.ColorSpace;
|
|
||||||
import java.awt.color.ICC_ColorSpace;
|
|
||||||
import java.awt.color.ICC_Profile;
|
|
||||||
import java.awt.image.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility for converting JMagick {@code MagickImage}s to standard Java
|
|
||||||
* {@code BufferedImage}s and back.
|
|
||||||
* <p>
|
|
||||||
* <em>NOTE: This class is considered an implementation detail and not part of
|
|
||||||
* the public API. This class is subject to change without further notice.
|
|
||||||
* You have been warned. :-)</em>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
|
||||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/MagickUtil.java#4 $
|
|
||||||
*/
|
|
||||||
public final class MagickUtil {
|
|
||||||
// IMPORTANT NOTE: Disaster happens if any of these constants are used outside this class
|
|
||||||
// because you then have a dependency on MagickException (this is due to Java class loading
|
|
||||||
// and initialization magic).
|
|
||||||
// Do not use outside this class. If the constants need to be shared, move to Magick or ImageUtil.
|
|
||||||
|
|
||||||
/** Color Model usesd for bilevel (B/W) */
|
|
||||||
private static final IndexColorModel CM_MONOCHROME = MonochromeColorModel.getInstance();
|
|
||||||
|
|
||||||
/** Color Model usesd for raw ABGR */
|
|
||||||
private static final ColorModel CM_COLOR_ALPHA =
|
|
||||||
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8, 8, 8, 8},
|
|
||||||
true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
|
|
||||||
|
|
||||||
/** Color Model usesd for raw BGR */
|
|
||||||
private static final ColorModel CM_COLOR_OPAQUE =
|
|
||||||
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] {8, 8, 8},
|
|
||||||
false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
|
||||||
|
|
||||||
/** Color Model usesd for raw RGB */
|
|
||||||
//private static final ColorModel CM_COLOR_RGB = new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x0);
|
|
||||||
|
|
||||||
/** Color Model usesd for raw GRAY + ALPHA */
|
|
||||||
private static final ColorModel CM_GRAY_ALPHA =
|
|
||||||
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
|
|
||||||
true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
|
|
||||||
|
|
||||||
/** Color Model usesd for raw GRAY */
|
|
||||||
private static final ColorModel CM_GRAY_OPAQUE =
|
|
||||||
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY),
|
|
||||||
false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
|
||||||
|
|
||||||
/** Band offsets for raw ABGR */
|
|
||||||
private static final int[] BAND_OFF_TRANS = new int[] {3, 2, 1, 0};
|
|
||||||
|
|
||||||
/** Band offsets for raw BGR */
|
|
||||||
private static final int[] BAND_OFF_OPAQUE = new int[] {2, 1, 0};
|
|
||||||
|
|
||||||
/** The point at {@code 0, 0} */
|
|
||||||
private static final Point LOCATION_UPPER_LEFT = new Point(0, 0);
|
|
||||||
|
|
||||||
private static final boolean DEBUG = Magick.DEBUG;
|
|
||||||
|
|
||||||
// Only static members and methods
|
|
||||||
private MagickUtil() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a {@code MagickImage} to a {@code BufferedImage}.
|
|
||||||
* <p>
|
|
||||||
* The conversion depends on {@code pImage}'s {@code ImageType}:
|
|
||||||
* </p>
|
|
||||||
* <dl>
|
|
||||||
* <dt>{@code ImageType.BilevelType}</dt>
|
|
||||||
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY}</dd>
|
|
||||||
*
|
|
||||||
* <dt>{@code ImageType.GrayscaleType}</dt>
|
|
||||||
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_GRAY}</dd>
|
|
||||||
* <dt>{@code ImageType.GrayscaleMatteType}</dt>
|
|
||||||
* <dd>{@code BufferedImage} of type {@code TYPE_USHORT_GRAY}</dd>
|
|
||||||
*
|
|
||||||
* <dt>{@code ImageType.PaletteType}</dt>
|
|
||||||
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY} (for images
|
|
||||||
* with a palette of <= 16 colors) or {@code TYPE_BYTE_INDEXED}</dd>
|
|
||||||
* <dt>{@code ImageType.PaletteMatteType}</dt>
|
|
||||||
* <dd>{@code BufferedImage} of type {@code TYPE_BYTE_BINARY} (for images
|
|
||||||
* with a palette of <= 16 colors) or {@code TYPE_BYTE_INDEXED}</dd>
|
|
||||||
*
|
|
||||||
* <dt>{@code ImageType.TrueColorType}</dt>
|
|
||||||
* <dd>{@code BufferedImage} of type {@code TYPE_3BYTE_BGR}</dd>
|
|
||||||
* <dt>{@code ImageType.TrueColorPaletteType}</dt>
|
|
||||||
* <dd>{@code BufferedImage} of type {@code TYPE_4BYTE_ABGR}</dd>
|
|
||||||
* </dl>
|
|
||||||
*
|
|
||||||
* @param pImage the original {@code MagickImage}
|
|
||||||
* @return a new {@code BufferedImage}
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException if {@code pImage} is {@code null}
|
|
||||||
* or if the {@code ImageType} is not one mentioned above.
|
|
||||||
* @throws MagickException if an exception occurs during conversion
|
|
||||||
*
|
|
||||||
* @see BufferedImage
|
|
||||||
*/
|
|
||||||
public static BufferedImage toBuffered(MagickImage pImage) throws MagickException {
|
|
||||||
if (pImage == null) {
|
|
||||||
throw new IllegalArgumentException("image == null");
|
|
||||||
}
|
|
||||||
|
|
||||||
long start = 0L;
|
|
||||||
if (DEBUG) {
|
|
||||||
start = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedImage image = null;
|
|
||||||
try {
|
|
||||||
switch (pImage.getImageType()) {
|
|
||||||
case ImageType.BilevelType:
|
|
||||||
image = bilevelToBuffered(pImage);
|
|
||||||
break;
|
|
||||||
case ImageType.GrayscaleType:
|
|
||||||
image = grayToBuffered(pImage, false);
|
|
||||||
break;
|
|
||||||
case ImageType.GrayscaleMatteType:
|
|
||||||
image = grayToBuffered(pImage, true);
|
|
||||||
break;
|
|
||||||
case ImageType.PaletteType:
|
|
||||||
image = paletteToBuffered(pImage, false);
|
|
||||||
break;
|
|
||||||
case ImageType.PaletteMatteType:
|
|
||||||
image = paletteToBuffered(pImage, true);
|
|
||||||
break;
|
|
||||||
case ImageType.TrueColorType:
|
|
||||||
image = rgbToBuffered(pImage, false);
|
|
||||||
break;
|
|
||||||
case ImageType.TrueColorMatteType:
|
|
||||||
image = rgbToBuffered(pImage, true);
|
|
||||||
break;
|
|
||||||
case ImageType.ColorSeparationType:
|
|
||||||
image = cmykToBuffered(pImage, false);
|
|
||||||
break;
|
|
||||||
case ImageType.ColorSeparationMatteType:
|
|
||||||
image = cmykToBuffered(pImage, true);
|
|
||||||
break;
|
|
||||||
case ImageType.OptimizeType:
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unknown JMagick image type: " + pImage.getImageType());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (DEBUG) {
|
|
||||||
long time = System.currentTimeMillis() - start;
|
|
||||||
System.out.println("Converted JMagick image type: " + pImage.getImageType() + " to BufferedImage: " + image);
|
|
||||||
System.out.println("Conversion to BufferedImage: " + time + " ms");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a {@code BufferedImage} to a {@code MagickImage}.
|
|
||||||
* <p>
|
|
||||||
* The conversion depends on {@code pImage}'s {@code ColorModel}:
|
|
||||||
* </p>
|
|
||||||
* <dl>
|
|
||||||
* <dt>{@code IndexColorModel} with 1 bit b/w</dt>
|
|
||||||
* <dd>{@code MagickImage} of type {@code ImageType.BilevelType}</dd>
|
|
||||||
* <dt>{@code IndexColorModel} > 1 bit,</dt>
|
|
||||||
* <dd>{@code MagickImage} of type {@code ImageType.PaletteType}
|
|
||||||
* or {@code MagickImage} of type {@code ImageType.PaletteMatteType}
|
|
||||||
* depending on <tt>ColorModel.getAlpha()</tt></dd>
|
|
||||||
*
|
|
||||||
* <dt>{@code ColorModel.getColorSpace().getType() == ColorSpace.TYPE_GRAY}</dt>
|
|
||||||
* <dd>{@code MagickImage} of type {@code ImageType.GrayscaleType}
|
|
||||||
* or {@code MagickImage} of type {@code ImageType.GrayscaleMatteType}
|
|
||||||
* depending on <tt>ColorModel.getAlpha()</tt></dd>
|
|
||||||
*
|
|
||||||
* <dt>{@code ColorModel.getColorSpace().getType() == ColorSpace.TYPE_RGB}</dt>
|
|
||||||
* <dd>{@code MagickImage} of type {@code ImageType.TrueColorType}
|
|
||||||
* or {@code MagickImage} of type {@code ImageType.TrueColorPaletteType}</dd>
|
|
||||||
* </dl>
|
|
||||||
*
|
|
||||||
* @param pImage the original {@code BufferedImage}
|
|
||||||
* @return a new {@code MagickImage}
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException if {@code pImage} is {@code null}
|
|
||||||
* or if the {@code ColorModel} is not one mentioned above.
|
|
||||||
* @throws MagickException if an exception occurs during conversion
|
|
||||||
*
|
|
||||||
* @see BufferedImage
|
|
||||||
*/
|
|
||||||
public static MagickImage toMagick(BufferedImage pImage) throws MagickException {
|
|
||||||
if (pImage == null) {
|
|
||||||
throw new IllegalArgumentException("image == null");
|
|
||||||
}
|
|
||||||
|
|
||||||
long start = 0L;
|
|
||||||
if (DEBUG) {
|
|
||||||
start = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
ColorModel cm = pImage.getColorModel();
|
|
||||||
if (cm instanceof IndexColorModel) {
|
|
||||||
// Handles both BilevelType, PaletteType and PaletteMatteType
|
|
||||||
return indexedToMagick(pImage, (IndexColorModel) cm, cm.hasAlpha());
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (cm.getColorSpace().getType()) {
|
|
||||||
case ColorSpace.TYPE_GRAY:
|
|
||||||
// Handles GrayType and GrayMatteType
|
|
||||||
return grayToMagick(pImage, cm.hasAlpha());
|
|
||||||
case ColorSpace.TYPE_RGB:
|
|
||||||
// Handles TrueColorType and TrueColorMatteType
|
|
||||||
return rgbToMagic(pImage, cm.hasAlpha());
|
|
||||||
case ColorSpace.TYPE_CMY:
|
|
||||||
case ColorSpace.TYPE_CMYK:
|
|
||||||
case ColorSpace.TYPE_HLS:
|
|
||||||
case ColorSpace.TYPE_HSV:
|
|
||||||
// Other types not supported yet
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unknown buffered image type: " + pImage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (DEBUG) {
|
|
||||||
long time = System.currentTimeMillis() - start;
|
|
||||||
System.out.println("Conversion to MagickImage: " + time + " ms");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MagickImage rgbToMagic(BufferedImage pImage, boolean pAlpha) throws MagickException {
|
|
||||||
MagickImage image = new MagickImage();
|
|
||||||
|
|
||||||
BufferedImage buffered = ImageUtil.toBuffered(pImage, pAlpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR);
|
|
||||||
|
|
||||||
// Need to get data of sub raster, not the full data array, this is
|
|
||||||
// just a convenient way
|
|
||||||
Raster raster;
|
|
||||||
if (buffered.getRaster().getParent() != null) {
|
|
||||||
raster = buffered.getData(new Rectangle(buffered.getWidth(), buffered.getHeight()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
raster = buffered.getRaster();
|
|
||||||
}
|
|
||||||
|
|
||||||
image.constituteImage(buffered.getWidth(), buffered.getHeight(), pAlpha ? "ABGR" : "BGR",
|
|
||||||
((DataBufferByte) raster.getDataBuffer()).getData());
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MagickImage grayToMagick(BufferedImage pImage, boolean pAlpha) throws MagickException {
|
|
||||||
MagickImage image = new MagickImage();
|
|
||||||
|
|
||||||
// TODO: Make a fix for TYPE_USHORT_GRAY
|
|
||||||
// The code below does not seem to work (JMagick issues?)...
|
|
||||||
/*
|
|
||||||
if (pImage.getType() == BufferedImage.TYPE_USHORT_GRAY) {
|
|
||||||
short[] data = ((DataBufferUShort) pImage.getRaster().getDataBuffer()).getData();
|
|
||||||
int[] intData = new int[data.length];
|
|
||||||
for (int i = 0; i < data.length; i++) {
|
|
||||||
intData[i] = (data[i] & 0xffff) * 0xffff;
|
|
||||||
}
|
|
||||||
image.constituteImage(pImage.getWidth(), pImage.getHeight(), "I", intData);
|
|
||||||
|
|
||||||
System.out.println("storageClass: " + image.getStorageClass());
|
|
||||||
System.out.println("depth: " + image.getDepth());
|
|
||||||
System.out.println("imageType: " + image.getImageType());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*/
|
|
||||||
BufferedImage buffered = ImageUtil.toBuffered(pImage, pAlpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_BYTE_GRAY);
|
|
||||||
|
|
||||||
// Need to get data of sub raster, not the full data array, this is
|
|
||||||
// just a convenient way
|
|
||||||
Raster raster;
|
|
||||||
if (buffered.getRaster().getParent() != null) {
|
|
||||||
raster = buffered.getData(new Rectangle(buffered.getWidth(), buffered.getHeight()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
raster = buffered.getRaster();
|
|
||||||
}
|
|
||||||
|
|
||||||
image.constituteImage(buffered.getWidth(), buffered.getHeight(), pAlpha ? "ABGR" : "I", ((DataBufferByte) raster.getDataBuffer()).getData());
|
|
||||||
//}
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MagickImage indexedToMagick(BufferedImage pImage, IndexColorModel pColorModel, boolean pAlpha) throws MagickException {
|
|
||||||
MagickImage image = rgbToMagic(pImage, pAlpha);
|
|
||||||
|
|
||||||
int mapSize = pColorModel.getMapSize();
|
|
||||||
image.setNumberColors(mapSize);
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
public static MagickImage toMagick(BufferedImage pImage) throws MagickException {
|
|
||||||
if (pImage == null) {
|
|
||||||
throw new IllegalArgumentException("image == null");
|
|
||||||
}
|
|
||||||
|
|
||||||
final int width = pImage.getWidth();
|
|
||||||
final int height = pImage.getHeight();
|
|
||||||
|
|
||||||
// int ARGB -> byte RGBA conversion
|
|
||||||
// NOTE: This is ImageMagick Q16 compatible raw RGBA format with 16 bits/sample...
|
|
||||||
// For a Q8 build, we could probably go with half the space...
|
|
||||||
// NOTE: This is close to insanity, as it wastes extreme ammounts of memory
|
|
||||||
final int[] argb = new int[width];
|
|
||||||
final byte[] raw16 = new byte[width * height * 8];
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
// Fetch one line of ARGB data
|
|
||||||
pImage.getRGB(0, y, width, 1, argb, 0, width);
|
|
||||||
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
int pixel = (x + (y * width)) * 8;
|
|
||||||
raw16[pixel ] = (byte) ((argb[x] >> 16) & 0xff); // R
|
|
||||||
raw16[pixel + 2] = (byte) ((argb[x] >> 8) & 0xff); // G
|
|
||||||
raw16[pixel + 4] = (byte) ((argb[x] ) & 0xff); // B
|
|
||||||
raw16[pixel + 6] = (byte) ((argb[x] >> 24) & 0xff); // A
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create magick image
|
|
||||||
ImageInfo info = new ImageInfo();
|
|
||||||
info.setMagick("RGBA"); // Raw RGBA samples
|
|
||||||
info.setSize(width + "x" + height); // String?!?
|
|
||||||
|
|
||||||
MagickImage image = new MagickImage(info);
|
|
||||||
image.setImageAttribute("depth", "8");
|
|
||||||
|
|
||||||
// Set pixel data in 16 bit raw RGBA format
|
|
||||||
image.blobToImage(info, raw16);
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a bi-level {@code MagickImage} to a {@code BufferedImage}, of
|
|
||||||
* type {@code TYPE_BYTE_BINARY}.
|
|
||||||
*
|
|
||||||
* @param pImage the original {@code MagickImage}
|
|
||||||
* @return a new {@code BufferedImage}
|
|
||||||
*
|
|
||||||
* @throws MagickException if an exception occurs during conversion
|
|
||||||
*
|
|
||||||
* @see BufferedImage
|
|
||||||
*/
|
|
||||||
private static BufferedImage bilevelToBuffered(MagickImage pImage) throws MagickException {
|
|
||||||
// As there is no way to get the binary representation of the image,
|
|
||||||
// convert to gray, and the create a binary image from it
|
|
||||||
BufferedImage temp = grayToBuffered(pImage, false);
|
|
||||||
|
|
||||||
BufferedImage image = new BufferedImage(temp.getWidth(), temp.getHeight(), BufferedImage.TYPE_BYTE_BINARY, CM_MONOCHROME);
|
|
||||||
|
|
||||||
ImageUtil.drawOnto(image, temp);
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a gray {@code MagickImage} to a {@code BufferedImage}, of
|
|
||||||
* type {@code TYPE_USHORT_GRAY} or {@code TYPE_BYTE_GRAY}.
|
|
||||||
*
|
|
||||||
* @param pImage the original {@code MagickImage}
|
|
||||||
* @param pAlpha keep alpha channel
|
|
||||||
* @return a new {@code BufferedImage}
|
|
||||||
*
|
|
||||||
* @throws MagickException if an exception occurs during conversion
|
|
||||||
*
|
|
||||||
* @see BufferedImage
|
|
||||||
*/
|
|
||||||
private static BufferedImage grayToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
|
|
||||||
Dimension size = pImage.getDimension();
|
|
||||||
int length = size.width * size.height;
|
|
||||||
int bands = pAlpha ? 2 : 1;
|
|
||||||
byte[] pixels = new byte[length * bands];
|
|
||||||
|
|
||||||
// TODO: Make a fix for 16 bit TYPE_USHORT_GRAY?!
|
|
||||||
// Note: The ordering AI or I corresponds to BufferedImage
|
|
||||||
// TYPE_CUSTOM and TYPE_BYTE_GRAY respectively
|
|
||||||
pImage.dispatchImage(0, 0, size.width, size.height, pAlpha ? "AI" : "I", pixels);
|
|
||||||
|
|
||||||
// Init databuffer with array, to avoid allocation of empty array
|
|
||||||
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
|
|
||||||
|
|
||||||
int[] bandOffsets = pAlpha ? new int[] {1, 0} : new int[] {0};
|
|
||||||
|
|
||||||
WritableRaster raster =
|
|
||||||
Raster.createInterleavedRaster(buffer, size.width, size.height,
|
|
||||||
size.width * bands, bands, bandOffsets, LOCATION_UPPER_LEFT);
|
|
||||||
|
|
||||||
return new BufferedImage(pAlpha ? CM_GRAY_ALPHA : CM_GRAY_OPAQUE, raster, pAlpha, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a palette-based {@code MagickImage} to a
|
|
||||||
* {@code BufferedImage}, of type {@code TYPE_BYTE_BINARY} (for images
|
|
||||||
* with a palette of <= 16 colors) or {@code TYPE_BYTE_INDEXED}.
|
|
||||||
*
|
|
||||||
* @param pImage the original {@code MagickImage}
|
|
||||||
* @param pAlpha keep alpha channel
|
|
||||||
* @return a new {@code BufferedImage}
|
|
||||||
*
|
|
||||||
* @throws MagickException if an exception occurs during conversion
|
|
||||||
*
|
|
||||||
* @see BufferedImage
|
|
||||||
*/
|
|
||||||
private static BufferedImage paletteToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
|
|
||||||
// Create indexcolormodel for the image
|
|
||||||
IndexColorModel cm;
|
|
||||||
|
|
||||||
try {
|
|
||||||
cm = createIndexColorModel(pImage.getColormap(), pAlpha);
|
|
||||||
}
|
|
||||||
catch (MagickException e) {
|
|
||||||
// NOTE: Some MagickImages incorrecly (?) reports to be paletteType,
|
|
||||||
// but does not have a colormap, this is a workaround.
|
|
||||||
return rgbToBuffered(pImage, pAlpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
// As there is no way to get the indexes of an indexed image, convert to
|
|
||||||
// RGB, and the create an indexed image from it
|
|
||||||
BufferedImage temp = rgbToBuffered(pImage, pAlpha);
|
|
||||||
|
|
||||||
BufferedImage image;
|
|
||||||
if (cm.getMapSize() <= 16) {
|
|
||||||
image = new BufferedImage(temp.getWidth(), temp.getHeight(), BufferedImage.TYPE_BYTE_BINARY, cm);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
image = new BufferedImage(temp.getWidth(), temp.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, cm);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create transparent background for images containing alpha
|
|
||||||
if (pAlpha) {
|
|
||||||
Graphics2D g = image.createGraphics();
|
|
||||||
try {
|
|
||||||
g.setComposite(AlphaComposite.Clear);
|
|
||||||
g.fillRect(0, 0, temp.getWidth(), temp.getHeight());
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
g.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: This is (surprisingly) much faster than using g2d.drawImage()..
|
|
||||||
// (Tests shows 20-30ms, vs. 600-700ms on the same image)
|
|
||||||
BufferedImageOp op = new CopyDither(cm);
|
|
||||||
op.filter(temp, image);
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an {@code IndexColorModel} from an array of
|
|
||||||
* {@code PixelPacket}s.
|
|
||||||
*
|
|
||||||
* @param pColormap the original colormap as a {@code PixelPacket} array
|
|
||||||
* @param pAlpha keep alpha channel
|
|
||||||
*
|
|
||||||
* @return a new {@code IndexColorModel}
|
|
||||||
*/
|
|
||||||
public static IndexColorModel createIndexColorModel(PixelPacket[] pColormap, boolean pAlpha) {
|
|
||||||
int[] colors = new int[pColormap.length];
|
|
||||||
|
|
||||||
// TODO: Verify if this is correct for alpha...?
|
|
||||||
int trans = pAlpha ? colors.length - 1 : -1;
|
|
||||||
|
|
||||||
//for (int i = 0; i < pColormap.length; i++) {
|
|
||||||
for (int i = pColormap.length - 1; i != 0; i--) {
|
|
||||||
PixelPacket color = pColormap[i];
|
|
||||||
if (pAlpha) {
|
|
||||||
colors[i] = (0xff - (color.getOpacity() & 0xff)) << 24 |
|
|
||||||
(color.getRed() & 0xff) << 16 |
|
|
||||||
(color.getGreen() & 0xff) << 8 |
|
|
||||||
(color.getBlue() & 0xff);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
colors[i] = (color.getRed() & 0xff) << 16 |
|
|
||||||
(color.getGreen() & 0xff) << 8 |
|
|
||||||
(color.getBlue() & 0xff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new InverseColorMapIndexColorModel(8, colors.length, colors, 0, pAlpha, trans, DataBuffer.TYPE_BYTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an (A)RGB {@code MagickImage} to a {@code BufferedImage}, of
|
|
||||||
* type {@code TYPE_4BYTE_ABGR} or {@code TYPE_3BYTE_BGR}.
|
|
||||||
*
|
|
||||||
* @param pImage the original {@code MagickImage}
|
|
||||||
* @param pAlpha keep alpha channel
|
|
||||||
* @return a new {@code BufferedImage}
|
|
||||||
*
|
|
||||||
* @throws MagickException if an exception occurs during conversion
|
|
||||||
*
|
|
||||||
* @see BufferedImage
|
|
||||||
*/
|
|
||||||
private static BufferedImage rgbToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
|
|
||||||
Dimension size = pImage.getDimension();
|
|
||||||
int length = size.width * size.height;
|
|
||||||
int bands = pAlpha ? 4 : 3;
|
|
||||||
byte[] pixels = new byte[length * bands];
|
|
||||||
|
|
||||||
// TODO: If we do multiple dispatches (one per line, typically), we could provide listener
|
|
||||||
// feedback. But it's currently a lot slower than fetching all the pixels in one go.
|
|
||||||
|
|
||||||
// Note: The ordering ABGR or BGR corresponds to BufferedImage
|
|
||||||
// TYPE_4BYTE_ABGR and TYPE_3BYTE_BGR respectively
|
|
||||||
pImage.dispatchImage(0, 0, size.width, size.height, pAlpha ? "ABGR" : "BGR", pixels);
|
|
||||||
|
|
||||||
// Init databuffer with array, to avoid allocation of empty array
|
|
||||||
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
|
|
||||||
|
|
||||||
int[] bandOffsets = pAlpha ? BAND_OFF_TRANS : BAND_OFF_OPAQUE;
|
|
||||||
|
|
||||||
WritableRaster raster =
|
|
||||||
Raster.createInterleavedRaster(buffer, size.width, size.height,
|
|
||||||
size.width * bands, bands, bandOffsets, LOCATION_UPPER_LEFT);
|
|
||||||
|
|
||||||
return new BufferedImage(pAlpha ? CM_COLOR_ALPHA : CM_COLOR_OPAQUE, raster, pAlpha, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an {@code MagickImage} to a {@code BufferedImage} which holds an CMYK ICC profile
|
|
||||||
*
|
|
||||||
* @param pImage the original {@code MagickImage}
|
|
||||||
* @param pAlpha keep alpha channel
|
|
||||||
* @return a new {@code BufferedImage}
|
|
||||||
*
|
|
||||||
* @throws MagickException if an exception occurs during conversion
|
|
||||||
*
|
|
||||||
* @see BufferedImage
|
|
||||||
*/
|
|
||||||
private static BufferedImage cmykToBuffered(MagickImage pImage, boolean pAlpha) throws MagickException {
|
|
||||||
Dimension size = pImage.getDimension();
|
|
||||||
int length = size.width * size.height;
|
|
||||||
|
|
||||||
// Retreive the ICC profile
|
|
||||||
ICC_Profile profile = ICC_Profile.getInstance(pImage.getColorProfile().getInfo());
|
|
||||||
ColorSpace cs = new ICC_ColorSpace(profile);
|
|
||||||
|
|
||||||
int bands = cs.getNumComponents() + (pAlpha ? 1 : 0);
|
|
||||||
|
|
||||||
int[] bits = new int[bands];
|
|
||||||
for (int i = 0; i < bands; i++) {
|
|
||||||
bits[i] = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorModel cm = pAlpha ?
|
|
||||||
new ComponentColorModel(cs, bits, true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE) :
|
|
||||||
new ComponentColorModel(cs, bits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
|
|
||||||
|
|
||||||
byte[] pixels = new byte[length * bands];
|
|
||||||
|
|
||||||
// TODO: If we do multiple dispatches (one per line, typically), we could provide listener
|
|
||||||
// feedback. But it's currently a lot slower than fetching all the pixels in one go.
|
|
||||||
// TODO: handle more generic cases if profile is not CMYK
|
|
||||||
// TODO: Test "ACMYK"
|
|
||||||
pImage.dispatchImage(0, 0, size.width, size.height, pAlpha ? "ACMYK" : "CMYK", pixels);
|
|
||||||
|
|
||||||
// Init databuffer with array, to avoid allocation of empty array
|
|
||||||
DataBuffer buffer = new DataBufferByte(pixels, pixels.length);
|
|
||||||
|
|
||||||
// TODO: build array from bands variable, here it just works for CMYK
|
|
||||||
// The values has not been tested with an alpha picture actually...
|
|
||||||
int[] bandOffsets = pAlpha ? new int[] {0, 1, 2, 3, 4} : new int[] {0, 1, 2, 3};
|
|
||||||
|
|
||||||
WritableRaster raster =
|
|
||||||
Raster.createInterleavedRaster(buffer, size.width, size.height,
|
|
||||||
size.width * bands, bands, bandOffsets, LOCATION_UPPER_LEFT);
|
|
||||||
|
|
||||||
return new BufferedImage(cm, raster, pAlpha, null);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -55,9 +55,7 @@
|
|||||||
package com.twelvemonkeys.image;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.*;
|
||||||
import java.awt.geom.Point2D;
|
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,15 +101,6 @@ import java.awt.image.*;
|
|||||||
* BufferedImage scaled = new ResampleOp(w, h).filter(temp, null);
|
* BufferedImage scaled = new ResampleOp(w, h).filter(temp, null);
|
||||||
* </pre></blockquote>
|
* </pre></blockquote>
|
||||||
* <p>
|
* <p>
|
||||||
* For maximum performance, this class will use native code, through
|
|
||||||
* <a href="http://www.yeo.id.au/jmagick/">JMagick</a>, when available.
|
|
||||||
* Otherwise, the class will silently fall back to pure Java mode.
|
|
||||||
* Native code may be disabled globally, by setting the system property
|
|
||||||
* {@code com.twelvemonkeys.image.accel} to {@code false}.
|
|
||||||
* To allow debug of the native code, set the system property
|
|
||||||
* {@code com.twelvemonkeys.image.magick.debug} to {@code true}.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This {@code BufferedImageOp} is based on C example code found in
|
* This {@code BufferedImageOp} is based on C example code found in
|
||||||
* <a href="http://www.acm.org/tog/GraphicsGems/">Graphics Gems III</a>,
|
* <a href="http://www.acm.org/tog/GraphicsGems/">Graphics Gems III</a>,
|
||||||
* Filtered Image Rescaling, by Dale Schumacher (with additional improvments by
|
* Filtered Image Rescaling, by Dale Schumacher (with additional improvments by
|
||||||
@@ -139,9 +128,6 @@ import java.awt.image.*;
|
|||||||
// TODO: Consider using AffineTransformOp for more operations!?
|
// TODO: Consider using AffineTransformOp for more operations!?
|
||||||
public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
||||||
|
|
||||||
// NOTE: These MUST correspond to ImageMagick filter types, for the
|
|
||||||
// MagickAccelerator to work consistently (see magick.FilterType).
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undefined interpolation, filter method will use default filter.
|
* Undefined interpolation, filter method will use default filter.
|
||||||
*/
|
*/
|
||||||
@@ -295,11 +281,10 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
|||||||
new Value(KEY_RESAMPLE_INTERPOLATION, "Blackman-Sinc", FILTER_BLACKMAN_SINC);
|
new Value(KEY_RESAMPLE_INTERPOLATION, "Blackman-Sinc", FILTER_BLACKMAN_SINC);
|
||||||
|
|
||||||
// Member variables
|
// Member variables
|
||||||
// Package access, to allow access from MagickAccelerator
|
private final int width;
|
||||||
int width;
|
private final int height;
|
||||||
int height;
|
|
||||||
|
|
||||||
int filterType;
|
private final int filterType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RendereingHints.Key implementation, works only with Value values.
|
* RendereingHints.Key implementation, works only with Value values.
|
||||||
@@ -547,16 +532,6 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
|||||||
// Fall through
|
// Fall through
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to use native ImageMagick code
|
|
||||||
BufferedImage result = MagickAccelerator.filter(this, input, output);
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, continue in pure Java mode
|
|
||||||
|
|
||||||
// TODO: What if output != null and wrong size? Create new? Render on only a part? Document?
|
|
||||||
|
|
||||||
// If filter type != POINT or BOX and input has IndexColorModel, convert
|
// If filter type != POINT or BOX and input has IndexColorModel, convert
|
||||||
// to true color, with alpha reflecting that of the original color model.
|
// to true color, with alpha reflecting that of the original color model.
|
||||||
BufferedImage temp;
|
BufferedImage temp;
|
||||||
@@ -571,7 +546,7 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
|||||||
|
|
||||||
// Create or convert output to a suitable image
|
// Create or convert output to a suitable image
|
||||||
// TODO: OPTIMIZE: Don't really need to convert all types to same as input
|
// TODO: OPTIMIZE: Don't really need to convert all types to same as input
|
||||||
result = output != null && temp.getType() != BufferedImage.TYPE_CUSTOM ? /*output*/ ImageUtil.toBuffered(output, temp.getType()) : createCompatibleDestImage(temp, null);
|
BufferedImage result = output != null && temp.getType() != BufferedImage.TYPE_CUSTOM ? /*output*/ ImageUtil.toBuffered(output, temp.getType()) : createCompatibleDestImage(temp, null);
|
||||||
|
|
||||||
resample(temp, result, filter);
|
resample(temp, result, filter);
|
||||||
|
|
||||||
@@ -1280,12 +1255,12 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
|
|||||||
/*
|
/*
|
||||||
* image rescaling routine
|
* image rescaling routine
|
||||||
*/
|
*/
|
||||||
class Contributor {
|
static class Contributor {
|
||||||
int pixel;
|
int pixel;
|
||||||
double weight;
|
double weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ContributorList {
|
static class ContributorList {
|
||||||
int n;/* number of contributors (may be < p.length) */
|
int n;/* number of contributors (may be < p.length) */
|
||||||
Contributor[] p;/* pointer to list of contributions */
|
Contributor[] p;/* pointer to list of contributions */
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-38
@@ -30,17 +30,24 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.image;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
import org.junit.Test;
|
import static java.lang.Math.min;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
|
||||||
import java.awt.color.ColorSpace;
|
import java.awt.color.ColorSpace;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.image.*;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.BufferedImageOp;
|
||||||
|
import java.awt.image.DataBuffer;
|
||||||
|
import java.awt.image.ImagingOpException;
|
||||||
|
import java.awt.image.Raster;
|
||||||
|
import java.awt.image.RasterOp;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AffineTransformOpTest.
|
* AffineTransformOpTest.
|
||||||
@@ -101,6 +108,7 @@ public class AffineTransformOpTest {
|
|||||||
|
|
||||||
private final int width = 30;
|
private final int width = 30;
|
||||||
private final int height = 20;
|
private final int height = 20;
|
||||||
|
private final double anchor = min(width, height) / 2.0;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetPoint2D() {
|
public void testGetPoint2D() {
|
||||||
@@ -128,33 +136,33 @@ public class AffineTransformOpTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFilterRotateBIStandard() {
|
public void testFilterRotateBIStandard() {
|
||||||
BufferedImageOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
|
BufferedImageOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
|
||||||
BufferedImageOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
|
BufferedImageOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
|
||||||
|
|
||||||
for (Integer type : TYPES) {
|
for (Integer type : TYPES) {
|
||||||
BufferedImage image = new BufferedImage(width, height, type);
|
BufferedImage image = new BufferedImage(width, height, type);
|
||||||
BufferedImage jreResult = jreOp.filter(image, null);
|
BufferedImage jreResult = jreOp.filter(image, null);
|
||||||
BufferedImage tmResult = tmOp.filter(image, null);
|
BufferedImage tmResult = tmOp.filter(image, null);
|
||||||
|
|
||||||
assertNotNull("No result!", tmResult);
|
assertNotNull(tmResult, "No result!");
|
||||||
assertEquals("Bad type", jreResult.getType(), tmResult.getType());
|
assertEquals(jreResult.getType(), tmResult.getType(), "Bad type");
|
||||||
assertEquals("Incorrect color model", jreResult.getColorModel(), tmResult.getColorModel());
|
assertEquals(jreResult.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
|
||||||
|
|
||||||
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
||||||
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFilterRotateBICustom() {
|
public void testFilterRotateBICustom() {
|
||||||
BufferedImageOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
|
BufferedImageOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
|
||||||
BufferedImageOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
|
BufferedImageOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
|
||||||
|
|
||||||
for (ImageTypeSpecifier spec : SPECS) {
|
for (ImageTypeSpecifier spec : SPECS) {
|
||||||
BufferedImage image = spec.createBufferedImage(width, height);
|
BufferedImage image = spec.createBufferedImage(width, height);
|
||||||
|
|
||||||
BufferedImage tmResult = tmOp.filter(image, null);
|
BufferedImage tmResult = tmOp.filter(image, null);
|
||||||
assertNotNull("No result!", tmResult);
|
assertNotNull(tmResult, "No result!");
|
||||||
|
|
||||||
BufferedImage jreResult = null;
|
BufferedImage jreResult = null;
|
||||||
|
|
||||||
@@ -166,18 +174,18 @@ public class AffineTransformOpTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (jreResult != null) {
|
if (jreResult != null) {
|
||||||
assertEquals("Bad type", jreResult.getType(), tmResult.getType());
|
assertEquals(jreResult.getType(), tmResult.getType(), "Bad type");
|
||||||
assertEquals("Incorrect color model", jreResult.getColorModel(), tmResult.getColorModel());
|
assertEquals(jreResult.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
|
||||||
|
|
||||||
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
||||||
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals("Bad type", spec.getBufferedImageType(), tmResult.getType());
|
assertEquals(spec.getBufferedImageType(), tmResult.getType(), "Bad type");
|
||||||
assertEquals("Incorrect color model", spec.getColorModel(), tmResult.getColorModel());
|
assertEquals(spec.getColorModel(), tmResult.getColorModel(), "Incorrect color model");
|
||||||
|
|
||||||
assertEquals("Incorrect width", height, tmResult.getWidth());
|
assertEquals(height, tmResult.getWidth(), "Incorrect width");
|
||||||
assertEquals("Incorrect height", width, tmResult.getHeight());
|
assertEquals(width, tmResult.getHeight(), "Incorrect height");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,8 +205,8 @@ public class AffineTransformOpTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFilterRotateRasterStandard() {
|
public void testFilterRotateRasterStandard() {
|
||||||
RasterOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
|
RasterOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
|
||||||
RasterOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
|
RasterOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
|
||||||
|
|
||||||
for (Integer type : TYPES) {
|
for (Integer type : TYPES) {
|
||||||
Raster raster = new BufferedImage(width, height, type).getRaster();
|
Raster raster = new BufferedImage(width, height, type).getRaster();
|
||||||
@@ -221,27 +229,25 @@ public class AffineTransformOpTest {
|
|||||||
fail("No result!");
|
fail("No result!");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
System.err.println("AffineTransformOpTest.testFilterRotateRasterStandard");
|
|
||||||
System.err.println("type: " + type);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jreResult != null) {
|
if (jreResult != null) {
|
||||||
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
||||||
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals("Incorrect width", height, tmResult.getWidth());
|
assertEquals(height, tmResult.getWidth(), "Incorrect width");
|
||||||
assertEquals("Incorrect height", width, tmResult.getHeight());
|
assertEquals(width, tmResult.getHeight(), "Incorrect height");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFilterRotateRasterCustom() {
|
public void testFilterRotateRasterCustom() {
|
||||||
RasterOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
|
RasterOp jreOp = new java.awt.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
|
||||||
RasterOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, Math.min(width, height) / 2, Math.min(width, height) / 2), null);
|
RasterOp tmOp = new com.twelvemonkeys.image.AffineTransformOp(AffineTransform.getQuadrantRotateInstance(1, anchor, anchor), null);
|
||||||
|
|
||||||
for (ImageTypeSpecifier spec : SPECS) {
|
for (ImageTypeSpecifier spec : SPECS) {
|
||||||
Raster raster = spec.createBufferedImage(width, height).getRaster();
|
Raster raster = spec.createBufferedImage(width, height).getRaster();
|
||||||
@@ -264,19 +270,17 @@ public class AffineTransformOpTest {
|
|||||||
fail("No result!");
|
fail("No result!");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
System.err.println("AffineTransformOpTest.testFilterRotateRasterCustom");
|
|
||||||
System.err.println("spec: " + spec);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jreResult != null) {
|
if (jreResult != null) {
|
||||||
assertEquals("Incorrect width", jreResult.getWidth(), tmResult.getWidth());
|
assertEquals(jreResult.getWidth(), tmResult.getWidth(), "Incorrect width");
|
||||||
assertEquals("Incorrect height", jreResult.getHeight(), tmResult.getHeight());
|
assertEquals(jreResult.getHeight(), tmResult.getHeight(), "Incorrect height");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals("Incorrect width", height, tmResult.getWidth());
|
assertEquals(height, tmResult.getWidth(), "Incorrect width");
|
||||||
assertEquals("Incorrect height", width, tmResult.getHeight());
|
assertEquals(width, tmResult.getHeight(), "Incorrect height");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+48
-42
@@ -30,18 +30,16 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.image;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.color.ColorSpace;
|
import java.awt.color.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.*;
|
||||||
import java.awt.image.ColorModel;
|
|
||||||
import java.awt.image.ImageProducer;
|
|
||||||
import java.awt.image.IndexColorModel;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BufferedImageFactoryTestCase
|
* BufferedImageFactoryTestCase
|
||||||
@@ -51,50 +49,58 @@ import static org.junit.Assert.*;
|
|||||||
* @version $Id: BufferedImageFactoryTestCase.java,v 1.0 May 7, 2010 12:40:08 PM haraldk Exp$
|
* @version $Id: BufferedImageFactoryTestCase.java,v 1.0 May 7, 2010 12:40:08 PM haraldk Exp$
|
||||||
*/
|
*/
|
||||||
public class BufferedImageFactoryTest {
|
public class BufferedImageFactoryTest {
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testCreateNullImage() {
|
public void testCreateNullImage() {
|
||||||
new BufferedImageFactory((Image) null);
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
new BufferedImageFactory((Image) null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testCreateNullProducer() {
|
public void testCreateNullProducer() {
|
||||||
new BufferedImageFactory((ImageProducer) null);
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
new BufferedImageFactory((ImageProducer) null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// NPE in Toolkit, ok
|
// NPE in Toolkit, ok
|
||||||
@Test(expected = RuntimeException.class)
|
@Test
|
||||||
public void testGetBufferedImageErrorSourceByteArray() {
|
public void testGetBufferedImageErrorSourceByteArray() {
|
||||||
Image source = Toolkit.getDefaultToolkit().createImage((byte[]) null);
|
assertThrows(RuntimeException.class, () -> {
|
||||||
|
Image source = Toolkit.getDefaultToolkit().createImage((byte[]) null);
|
||||||
new BufferedImageFactory(source);
|
new BufferedImageFactory(source);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testGetBufferedImageErrorSourceImageProducer() {
|
public void testGetBufferedImageErrorSourceImageProducer() {
|
||||||
Image source = Toolkit.getDefaultToolkit().createImage((ImageProducer) null);
|
Image source = Toolkit.getDefaultToolkit().createImage((ImageProducer) null);
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
new BufferedImageFactory(source);
|
new BufferedImageFactory(source);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This is a quite serious bug, however, the bug is in the Toolkit, allowing such images in the first place...
|
// TODO: This is a quite serious bug, however, the bug is in the Toolkit, allowing such images in the first place...
|
||||||
// In any case, there's not much we can do, except until someone is bored and kills the app/thread... :-P
|
// In any case, there's not much we can do, except until someone is bored and kills the app/thread... :-P
|
||||||
@Ignore("Bug in Toolkit")
|
@Disabled("Bug in Toolkit")
|
||||||
@Test(timeout = 1000, expected = ImageConversionException.class)
|
@Test
|
||||||
public void testGetBufferedImageErrorSourceString() {
|
public void testGetBufferedImageErrorSourceString() {
|
||||||
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
|
assertTimeoutPreemptively(Duration.ofMillis(1000), () -> {
|
||||||
|
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
|
||||||
BufferedImageFactory factory = new BufferedImageFactory(source);
|
BufferedImageFactory factory = new BufferedImageFactory(source);
|
||||||
factory.getBufferedImage();
|
assertThrows(ImageConversionException.class, factory::getBufferedImage);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a little random, and it would be nicer if we could throw an IllegalArgumentException on create.
|
// This is a little random, and it would be nicer if we could throw an IllegalArgumentException on create.
|
||||||
// Unfortunately, the API doesn't allow this...
|
// Unfortunately, the API doesn't allow this...
|
||||||
@Test(timeout = 1000, expected = ImageConversionException.class)
|
@Test
|
||||||
public void testGetBufferedImageErrorSourceURL() {
|
public void testGetBufferedImageErrorSourceURL() {
|
||||||
Image source = Toolkit.getDefaultToolkit().createImage(getClass().getResource("/META-INF/MANIFEST.MF"));
|
assertTimeoutPreemptively(Duration.ofMillis(1000), () -> {
|
||||||
|
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
|
||||||
BufferedImageFactory factory = new BufferedImageFactory(source);
|
BufferedImageFactory factory = new BufferedImageFactory(source);
|
||||||
factory.getBufferedImage();
|
assertThrows(ImageConversionException.class, factory::getBufferedImage);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -166,7 +172,7 @@ public class BufferedImageFactoryTest {
|
|||||||
|
|
||||||
assertEquals(3, colorModel.getNumColorComponents());
|
assertEquals(3, colorModel.getNumColorComponents());
|
||||||
assertEquals(ColorSpace.getInstance(ColorSpace.CS_sRGB), colorModel.getColorSpace());
|
assertEquals(ColorSpace.getInstance(ColorSpace.CS_sRGB), colorModel.getColorSpace());
|
||||||
assertTrue(colorModel instanceof IndexColorModel);
|
assertInstanceOf(IndexColorModel.class, colorModel);
|
||||||
|
|
||||||
assertTrue(colorModel.hasAlpha());
|
assertTrue(colorModel.hasAlpha());
|
||||||
assertEquals(4, colorModel.getNumComponents());
|
assertEquals(4, colorModel.getNumComponents());
|
||||||
@@ -197,7 +203,7 @@ public class BufferedImageFactoryTest {
|
|||||||
|
|
||||||
for (int y = 0; y < image.getHeight(); y++) {
|
for (int y = 0; y < image.getHeight(); y++) {
|
||||||
for (int x = 0; x < image.getWidth(); x++) {
|
for (int x = 0; x < image.getWidth(); x++) {
|
||||||
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(x * 2, y * 2), image.getRGB(x, y));
|
assertEquals(original.getRGB(x * 2, y * 2), image.getRGB(x, y), "RGB[" + x + ", " + y + "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,7 +226,7 @@ public class BufferedImageFactoryTest {
|
|||||||
|
|
||||||
for (int y = 0; y < image.getHeight(); y++) {
|
for (int y = 0; y < image.getHeight(); y++) {
|
||||||
for (int x = 0; x < image.getWidth(); x++) {
|
for (int x = 0; x < image.getWidth(); x++) {
|
||||||
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(40 + x, 40 + y), image.getRGB(x, y));
|
assertEquals(original.getRGB(40 + x, 40 + y), image.getRGB(x, y), "RGB[" + x + ", " + y + "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,7 +250,7 @@ public class BufferedImageFactoryTest {
|
|||||||
|
|
||||||
for (int y = 0; y < image.getHeight(); y++) {
|
for (int y = 0; y < image.getHeight(); y++) {
|
||||||
for (int x = 0; x < image.getWidth(); x++) {
|
for (int x = 0; x < image.getWidth(); x++) {
|
||||||
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(40 + x * 2, 40 + y * 2), image.getRGB(x, y));
|
assertEquals(original.getRGB(40 + x * 2, 40 + y * 2), image.getRGB(x, y), "RGB[" + x + ", " + y + "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,9 +266,9 @@ public class BufferedImageFactoryTest {
|
|||||||
|
|
||||||
// Listener should abort ASAP
|
// Listener should abort ASAP
|
||||||
factory.addProgressListener(new BufferedImageFactory.ProgressListener() {
|
factory.addProgressListener(new BufferedImageFactory.ProgressListener() {
|
||||||
public void progress(BufferedImageFactory pFactory, float pPercentage) {
|
public void progress(BufferedImageFactory factory, float percentage) {
|
||||||
if (pPercentage > 5) {
|
if (percentage > 5) {
|
||||||
pFactory.abort();
|
factory.abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -343,7 +349,7 @@ public class BufferedImageFactoryTest {
|
|||||||
VerifyingListener listener = new VerifyingListener(factory);
|
VerifyingListener listener = new VerifyingListener(factory);
|
||||||
factory.addProgressListener(listener);
|
factory.addProgressListener(listener);
|
||||||
factory.removeProgressListener(new BufferedImageFactory.ProgressListener() {
|
factory.removeProgressListener(new BufferedImageFactory.ProgressListener() {
|
||||||
public void progress(BufferedImageFactory pFactory, float pPercentage) {
|
public void progress(BufferedImageFactory factory, float percentage) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
factory.getBufferedImage();
|
factory.getBufferedImage();
|
||||||
@@ -380,11 +386,11 @@ public class BufferedImageFactoryTest {
|
|||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void progress(BufferedImageFactory pFactory, float pPercentage) {
|
public void progress(BufferedImageFactory factory, float percentage) {
|
||||||
assertEquals(factory, pFactory);
|
assertEquals(this.factory, factory);
|
||||||
assertTrue(pPercentage >= progress && pPercentage <= 100f);
|
assertTrue(percentage >= progress && percentage <= 100f);
|
||||||
|
|
||||||
progress = pPercentage;
|
progress = percentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.image;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -39,7 +39,7 @@ import java.awt.image.IndexColorModel;
|
|||||||
import java.awt.image.RenderedImage;
|
import java.awt.image.RenderedImage;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
public class ImageUtilTest {
|
public class ImageUtilTest {
|
||||||
|
|
||||||
@@ -116,8 +116,8 @@ public class ImageUtilTest {
|
|||||||
public void testImageIsNotBufferedImage() {
|
public void testImageIsNotBufferedImage() {
|
||||||
// Should not be a buffered image
|
// Should not be a buffered image
|
||||||
assertFalse(
|
assertFalse(
|
||||||
"FOR SOME IMPLEMENTATIONS THIS MIGHT FAIL!\nIn that case, testToBufferedImage() will fail too.",
|
scaled instanceof BufferedImage,
|
||||||
scaled instanceof BufferedImage
|
"FOR SOME IMPLEMENTATIONS THIS MIGHT FAIL!\nIn that case, testToBufferedImage() will fail too."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ public class ImageUtilTest {
|
|||||||
if (original != notContrasted) { // Don't care to test if images are same
|
if (original != notContrasted) { // Don't care to test if images are same
|
||||||
for (int y = 0; y < original.getHeight(); y++) {
|
for (int y = 0; y < original.getHeight(); y++) {
|
||||||
for (int x = 0; x < original.getWidth(); x++) {
|
for (int x = 0; x < original.getWidth(); x++) {
|
||||||
assertEquals("0 constrast should not change image", original.getRGB(x, y), notContrasted.getRGB(x, y));
|
assertEquals(original.getRGB(x, y), notContrasted.getRGB(x, y), "0 constrast should not change image");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,24 +275,24 @@ public class ImageUtilTest {
|
|||||||
|
|
||||||
// RED
|
// RED
|
||||||
if (oR < 127) {
|
if (oR < 127) {
|
||||||
assertTrue("Contrast should be decreased or same", oR >= cR && cR >= dR);
|
assertTrue(oR >= cR && cR >= dR, "Contrast should be decreased or same");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue("Contrast should be increased or same", oR <= cR && cR <= dR);
|
assertTrue(oR <= cR && cR <= dR, "Contrast should be increased or same");
|
||||||
}
|
}
|
||||||
// GREEN
|
// GREEN
|
||||||
if (oG < 127) {
|
if (oG < 127) {
|
||||||
assertTrue("Contrast should be decreased or same", oG >= cG && cG >= dG);
|
assertTrue(oG >= cG && cG >= dG, "Contrast should be decreased or same");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue("Contrast should be increased or same", oG <= cG && cG <= dG);
|
assertTrue(oG <= cG && cG <= dG, "Contrast should be increased or same");
|
||||||
}
|
}
|
||||||
// BLUE
|
// BLUE
|
||||||
if (oB < 127) {
|
if (oB < 127) {
|
||||||
assertTrue("Contrast should be decreased or same", oB >= cB && cB >= dB);
|
assertTrue(oB >= cB && cB >= dB, "Contrast should be decreased or same");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue("Contrast should be increased or same", oB <= cB && cB <= dB);
|
assertTrue(oB <= cB && cB <= dB, "Contrast should be increased or same");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,9 +304,9 @@ public class ImageUtilTest {
|
|||||||
int r = rgb >> 16 & 0xFF;
|
int r = rgb >> 16 & 0xFF;
|
||||||
int g = rgb >> 8 & 0xFF;
|
int g = rgb >> 8 & 0xFF;
|
||||||
int b = rgb & 0xFF;
|
int b = rgb & 0xFF;
|
||||||
assertTrue("Max contrast should only produce primary colors", r == 0 || r == 255);
|
assertTrue(r == 0 || r == 255, "Max contrast should only produce primary colors");
|
||||||
assertTrue("Max contrast should only produce primary colors", g == 0 || g == 255);
|
assertTrue(g == 0 || g == 255, "Max contrast should only produce primary colors");
|
||||||
assertTrue("Max contrast should only produce primary colors", b == 0 || b == 255);
|
assertTrue(b == 0 || b == 255, "Max contrast should only produce primary colors");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,24 +327,24 @@ public class ImageUtilTest {
|
|||||||
|
|
||||||
// RED
|
// RED
|
||||||
if (oR >= 127) {
|
if (oR >= 127) {
|
||||||
assertTrue("Contrast should be decreased or same", oR >= cR);
|
assertTrue(oR >= cR, "Contrast should be decreased or same");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue("Contrast should be increased or same", oR <= cR);
|
assertTrue(oR <= cR, "Contrast should be increased or same");
|
||||||
}
|
}
|
||||||
// GREEN
|
// GREEN
|
||||||
if (oG >= 127) {
|
if (oG >= 127) {
|
||||||
assertTrue("Contrast should be decreased or same", oG >= cG);
|
assertTrue(oG >= cG, "Contrast should be decreased or same");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue("Contrast should be increased or same", oG <= cG);
|
assertTrue(oG <= cG, "Contrast should be increased or same");
|
||||||
}
|
}
|
||||||
// BLUE
|
// BLUE
|
||||||
if (oB >= 127) {
|
if (oB >= 127) {
|
||||||
assertTrue("Contrast should be decreased or same", oB >= cB);
|
assertTrue(oB >= cB, "Contrast should be decreased or same");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue("Contrast should be increased or same", oB <= cB);
|
assertTrue(oB <= cB, "Contrast should be increased or same");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,7 +357,7 @@ public class ImageUtilTest {
|
|||||||
int r = rgb >> 16 & 0xFF;
|
int r = rgb >> 16 & 0xFF;
|
||||||
int g = rgb >> 8 & 0xFF;
|
int g = rgb >> 8 & 0xFF;
|
||||||
int b = rgb & 0xFF;
|
int b = rgb & 0xFF;
|
||||||
assertTrue("Minimum contrast should be all gray", r == 127 && g == 127 && b == 127);
|
assertTrue(r == 127 && g == 127 && b == 127, "Minimum contrast should be all gray");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +400,7 @@ public class ImageUtilTest {
|
|||||||
if (original != notSharpened) { // Don't care to test if images are same
|
if (original != notSharpened) { // Don't care to test if images are same
|
||||||
for (int y = 0; y < original.getHeight(); y++) {
|
for (int y = 0; y < original.getHeight(); y++) {
|
||||||
for (int x = 0; x < original.getWidth(); x++) {
|
for (int x = 0; x < original.getWidth(); x++) {
|
||||||
assertEquals("0 sharpen should not change image", original.getRGB(x, y), notSharpened.getRGB(x, y));
|
assertEquals(original.getRGB(x, y), notSharpened.getRGB(x, y), "0 sharpen should not change image");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -446,13 +446,13 @@ public class ImageUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// assertEquals("Difference should not change", diffOriginal, diffSharpened);
|
// assertEquals("Difference should not change", diffOriginal, diffSharpened);
|
||||||
assertTrue("Abs difference should increase", absDiffOriginal < absDiffSharpened);
|
assertTrue(absDiffOriginal < absDiffSharpened, "Abs difference should increase");
|
||||||
// assertEquals("Difference should not change", diffOriginal, diffDefault);
|
// assertEquals("Difference should not change", diffOriginal, diffDefault);
|
||||||
assertTrue("Abs difference should increase", absDiffOriginal < absDiffDefault);
|
assertTrue(absDiffOriginal < absDiffDefault, "Abs difference should increase");
|
||||||
// assertEquals("Difference should not change", diffOriginal, diffMore);
|
// assertEquals("Difference should not change", diffOriginal, diffMore);
|
||||||
assertTrue("Abs difference should increase", absDiffOriginal < absDiffMore);
|
assertTrue(absDiffOriginal < absDiffMore, "Abs difference should increase");
|
||||||
// assertEquals("Difference should not change", diffSharpened, diffMore);
|
// assertEquals("Difference should not change", diffSharpened, diffMore);
|
||||||
assertTrue("Abs difference should increase", absDiffSharpened < absDiffMore);
|
assertTrue(absDiffSharpened < absDiffMore, "Abs difference should increase");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -466,7 +466,7 @@ public class ImageUtilTest {
|
|||||||
if (original != notBlurred) { // Don't care to test if images are same
|
if (original != notBlurred) { // Don't care to test if images are same
|
||||||
for (int y = 0; y < original.getHeight(); y++) {
|
for (int y = 0; y < original.getHeight(); y++) {
|
||||||
for (int x = 0; x < original.getWidth(); x++) {
|
for (int x = 0; x < original.getWidth(); x++) {
|
||||||
assertEquals("0 blur should not change image", original.getRGB(x, y), notBlurred.getRGB(x, y));
|
assertEquals(original.getRGB(x, y), notBlurred.getRGB(x, y), "0 blur should not change image");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -512,13 +512,13 @@ public class ImageUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// assertEquals("Difference should not change", diffOriginal, diffBlurred);
|
// assertEquals("Difference should not change", diffOriginal, diffBlurred);
|
||||||
assertTrue(String.format("Abs difference should decrease: %s <= %s", absDiffOriginal, absDiffBlurred), absDiffOriginal > absDiffBlurred);
|
assertTrue(absDiffOriginal > absDiffBlurred, String.format("Abs difference should decrease: %s <= %s", absDiffOriginal, absDiffBlurred));
|
||||||
// assertEquals("Difference should not change", diffOriginal, diffDefault);
|
// assertEquals("Difference should not change", diffOriginal, diffDefault);
|
||||||
assertTrue("Abs difference should decrease", absDiffOriginal > absDiffDefault);
|
assertTrue(absDiffOriginal > absDiffDefault, "Abs difference should decrease");
|
||||||
// assertEquals("Difference should not change", diffOriginal, diffMore);
|
// assertEquals("Difference should not change", diffOriginal, diffMore);
|
||||||
assertTrue("Abs difference should decrease", absDiffOriginal > absDiffMore);
|
assertTrue(absDiffOriginal > absDiffMore, "Abs difference should decrease");
|
||||||
// assertEquals("Difference should not change", diffBlurred, diffMore);
|
// assertEquals("Difference should not change", diffBlurred, diffMore);
|
||||||
assertTrue("Abs difference should decrease", absDiffBlurred > absDiffMore);
|
assertTrue(absDiffBlurred > absDiffMore, "Abs difference should decrease");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -528,7 +528,7 @@ public class ImageUtilTest {
|
|||||||
assertNotNull(sunflower);
|
assertNotNull(sunflower);
|
||||||
|
|
||||||
BufferedImage image = ImageUtil.createIndexed(sunflower);
|
BufferedImage image = ImageUtil.createIndexed(sunflower);
|
||||||
assertNotNull("Image was null", image);
|
assertNotNull(image, "Image was null");
|
||||||
assertTrue(image.getColorModel() instanceof IndexColorModel);
|
assertInstanceOf(IndexColorModel.class, image.getColorModel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.image;
|
package com.twelvemonkeys.image;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
@@ -40,7 +40,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ResampleOpTestCase
|
* ResampleOpTestCase
|
||||||
@@ -124,7 +124,7 @@ public class ResampleOpTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals("Filter threw exceptions: ", Collections.EMPTY_LIST, exceptions);
|
assertEquals(Collections.EMPTY_LIST, exceptions, "Filter threw exceptions: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1x1
|
// 1x1
|
||||||
@@ -358,7 +358,7 @@ public class ResampleOpTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("Not for general unit testing")
|
@Disabled("Not for general unit testing")
|
||||||
@Test
|
@Test
|
||||||
public void testTime() {
|
public void testTime() {
|
||||||
int iterations = 1000;
|
int iterations = 1000;
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
TODO:
|
|
||||||
Remove compile-time dependency on JMagick:
|
|
||||||
- Extract interface for MagickAccelerator
|
|
||||||
- Move implementation to separate module
|
|
||||||
- Instantiate impl via reflection
|
|
||||||
DONE:
|
|
||||||
@@ -4,13 +4,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.7.0</version>
|
<version>3.13.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>common-io</artifactId>
|
<artifactId>common-io</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TwelveMonkeys :: Common :: IO</name>
|
<name>TwelveMonkeys :: Common :: IO</name>
|
||||||
<description>
|
<description>
|
||||||
The TwelveMonkeys Common IO support
|
TwelveMonkeys Common I/O support classes.
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -31,4 +31,12 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ public class CompoundReader extends Reader {
|
|||||||
|
|
||||||
private int currentReader;
|
private int currentReader;
|
||||||
private int markedReader;
|
private int markedReader;
|
||||||
private int mark;
|
private long mark;
|
||||||
private int mNext;
|
private long next;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new compound reader.
|
* Create a new compound reader.
|
||||||
@@ -76,7 +76,7 @@ public class CompoundReader extends Reader {
|
|||||||
finalLock = pReaders; // NOTE: It's ok to sync on pReaders, as the
|
finalLock = pReaders; // NOTE: It's ok to sync on pReaders, as the
|
||||||
// reference can't change, only it's elements
|
// reference can't change, only it's elements
|
||||||
|
|
||||||
readers = new ArrayList<Reader>();
|
readers = new ArrayList<>();
|
||||||
|
|
||||||
boolean markSupported = true;
|
boolean markSupported = true;
|
||||||
while (pReaders.hasNext()) {
|
while (pReaders.hasNext()) {
|
||||||
@@ -101,7 +101,7 @@ public class CompoundReader extends Reader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Reset mNext for every reader, and record marked reader in mark/reset methods!
|
// NOTE: Reset mNext for every reader, and record marked reader in mark/reset methods!
|
||||||
mNext = 0;
|
next = 0;
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ public class CompoundReader extends Reader {
|
|||||||
|
|
||||||
synchronized (finalLock) {
|
synchronized (finalLock) {
|
||||||
ensureOpen();
|
ensureOpen();
|
||||||
mark = mNext;
|
mark = next;
|
||||||
markedReader = currentReader;
|
markedReader = currentReader;
|
||||||
|
|
||||||
current.mark(pReadLimit);
|
current.mark(pReadLimit);
|
||||||
@@ -158,7 +158,7 @@ public class CompoundReader extends Reader {
|
|||||||
}
|
}
|
||||||
current.reset();
|
current.reset();
|
||||||
|
|
||||||
mNext = mark;
|
next = mark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,13 +177,13 @@ public class CompoundReader extends Reader {
|
|||||||
return read(); // In case of 0-length readers
|
return read(); // In case of 0-length readers
|
||||||
}
|
}
|
||||||
|
|
||||||
mNext++;
|
next++;
|
||||||
|
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
|
public int read(char[] pBuffer, int pOffset, int pLength) throws IOException {
|
||||||
synchronized (finalLock) {
|
synchronized (finalLock) {
|
||||||
int read = current.read(pBuffer, pOffset, pLength);
|
int read = current.read(pBuffer, pOffset, pLength);
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ public class CompoundReader extends Reader {
|
|||||||
return read(pBuffer, pOffset, pLength); // In case of 0-length readers
|
return read(pBuffer, pOffset, pLength); // In case of 0-length readers
|
||||||
}
|
}
|
||||||
|
|
||||||
mNext += read;
|
next += read;
|
||||||
|
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
@@ -213,7 +213,7 @@ public class CompoundReader extends Reader {
|
|||||||
return skip(pChars); // In case of 0-length readers
|
return skip(pChars); // In case of 0-length readers
|
||||||
}
|
}
|
||||||
|
|
||||||
mNext += skipped;
|
next += skipped;
|
||||||
|
|
||||||
return skipped;
|
return skipped;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An unsynchronized {@code ByteArrayOutputStream} implementation. This version
|
* An unsynchronized {@code ByteArrayOutputStream} implementation. This version
|
||||||
@@ -42,11 +43,8 @@ import java.io.OutputStream;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: FastByteArrayOutputStream.java#2 $
|
* @version $Id: FastByteArrayOutputStream.java#2 $
|
||||||
*/
|
*/
|
||||||
// TODO: Performance test of a stream impl that uses list of fixed size blocks, rather than contiguous block
|
// TODO: Performance test of a stream impl that uses list of fixed size blocks, rather than contiguous block
|
||||||
public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
||||||
/** Max grow size (unless if writing more than this amount of bytes) */
|
|
||||||
protected int maxGrowSize = 1024 * 1024; // 1 MB
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code ByteArrayOutputStream} with the given initial buffer
|
* Creates a {@code ByteArrayOutputStream} with the given initial buffer
|
||||||
* size.
|
* size.
|
||||||
@@ -97,10 +95,8 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
|||||||
|
|
||||||
private void growIfNeeded(int pNewCount) {
|
private void growIfNeeded(int pNewCount) {
|
||||||
if (pNewCount > buf.length) {
|
if (pNewCount > buf.length) {
|
||||||
int newSize = Math.max(Math.min(buf.length << 1, buf.length + maxGrowSize), pNewCount);
|
int newSize = Math.max(buf.length << 1, pNewCount);
|
||||||
byte[] newBuf = new byte[newSize];
|
buf = Arrays.copyOf(buf, newSize);
|
||||||
System.arraycopy(buf, 0, newBuf, 0, count);
|
|
||||||
buf = newBuf;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,10 +109,7 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
|||||||
// Non-synchronized version of toByteArray
|
// Non-synchronized version of toByteArray
|
||||||
@Override
|
@Override
|
||||||
public byte[] toByteArray() {
|
public byte[] toByteArray() {
|
||||||
byte[] newBuf = new byte[count];
|
return Arrays.copyOf(buf, count);
|
||||||
System.arraycopy(buf, 0, newBuf, 0, count);
|
|
||||||
|
|
||||||
return newBuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ import java.io.FilenameFilter;
|
|||||||
* @see WildcardStringParser
|
* @see WildcardStringParser
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class FilenameMaskFilter implements FilenameFilter {
|
public class FilenameMaskFilter implements FilenameFilter {
|
||||||
|
|
||||||
// TODO: Rewrite to use regexp, or create new class
|
// TODO: Rewrite to use regexp, or create new class
|
||||||
|
|||||||
@@ -442,6 +442,7 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
|
|||||||
* @see java.io.BufferedReader#readLine()
|
* @see java.io.BufferedReader#readLine()
|
||||||
* @see java.io.DataInputStream#readLine()
|
* @see java.io.DataInputStream#readLine()
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public String readLine() throws IOException {
|
public String readLine() throws IOException {
|
||||||
DataInputStream ds = new DataInputStream(in);
|
DataInputStream ds = new DataInputStream(in);
|
||||||
return ds.readLine();
|
return ds.readLine();
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ public class StringArrayReader extends StringReader {
|
|||||||
protected final Object finalLock;
|
protected final Object finalLock;
|
||||||
private int currentSting;
|
private int currentSting;
|
||||||
private int markedString;
|
private int markedString;
|
||||||
private int mark;
|
private long mark;
|
||||||
private int next;
|
private long next;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new string array reader.
|
* Create a new string array reader.
|
||||||
@@ -151,7 +151,7 @@ public class StringArrayReader extends StringReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
|
public int read(char[] pBuffer, int pOffset, int pLength) throws IOException {
|
||||||
synchronized (finalLock) {
|
synchronized (finalLock) {
|
||||||
int read = current.read(pBuffer, pOffset, pLength);
|
int read = current.read(pBuffer, pOffset, pLength);
|
||||||
|
|
||||||
|
|||||||
@@ -41,21 +41,20 @@ import java.io.InputStream;
|
|||||||
* underlying stream.
|
* underlying stream.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/SubStream.java#2 $
|
|
||||||
*/
|
*/
|
||||||
public final class SubStream extends FilterInputStream {
|
public final class SubStream extends FilterInputStream {
|
||||||
private long bytesLeft;
|
private long bytesLeft;
|
||||||
private int markLimit;
|
private int markLimit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code SubStream} of the given {@code pStream}.
|
* Creates a {@code SubStream} of the given {@code stream}.
|
||||||
*
|
*
|
||||||
* @param pStream the underlying input stream
|
* @param stream the underlying input stream
|
||||||
* @param pLength maximum number of bytes to read drom this stream
|
* @param length maximum number of bytes to read from this stream
|
||||||
*/
|
*/
|
||||||
public SubStream(final InputStream pStream, final long pLength) {
|
public SubStream(final InputStream stream, final long length) {
|
||||||
super(Validate.notNull(pStream, "stream"));
|
super(Validate.notNull(stream, "stream"));
|
||||||
bytesLeft = pLength;
|
bytesLeft = Validate.isTrue(length >= 0, length, "length < 0: %s");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,22 +63,23 @@ public final class SubStream extends FilterInputStream {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
// NOTE: Do not close the underlying stream
|
// NOTE: Do not close the underlying stream, but consume it
|
||||||
while (bytesLeft > 0) {
|
while (bytesLeft > 0) {
|
||||||
//noinspection ResultOfMethodCallIgnored
|
if (skip(bytesLeft) <= 0 && read() < 0) {
|
||||||
skip(bytesLeft);
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int available() throws IOException {
|
public int available() throws IOException {
|
||||||
return (int) Math.min(super.available(), bytesLeft);
|
return (int) findMaxLen(super.available());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mark(int pReadLimit) {
|
public void mark(int readLimit) {
|
||||||
super.mark(pReadLimit);// This either succeeds or does nothing...
|
super.mark(readLimit);// This either succeeds or does nothing...
|
||||||
markLimit = pReadLimit;
|
markLimit = readLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -93,44 +93,42 @@ public final class SubStream extends FilterInputStream {
|
|||||||
if (bytesLeft-- <= 0) {
|
if (bytesLeft-- <= 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.read();
|
return super.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int read(byte[] pBytes) throws IOException {
|
public int read(byte[] bytes) throws IOException {
|
||||||
return read(pBytes, 0, pBytes.length);
|
return read(bytes, 0, bytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
|
public int read(final byte[] bytes, final int off, final int len) throws IOException {
|
||||||
if (bytesLeft <= 0) {
|
if (bytesLeft <= 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read = super.read(pBytes, pOffset, (int) findMaxLen(pLength));
|
int read = super.read(bytes, off, (int) findMaxLen(len));
|
||||||
bytesLeft = read < 0 ? 0 : bytesLeft - read;
|
bytesLeft = read < 0 ? 0 : bytesLeft - read;
|
||||||
|
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long skip(long length) throws IOException {
|
||||||
|
long skipped = super.skip(findMaxLen(length)); // Skips 0 or more, never -1
|
||||||
|
bytesLeft -= skipped;
|
||||||
|
|
||||||
|
return skipped;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the maximum number of bytes we can read or skip, from this stream.
|
* Finds the maximum number of bytes we can read or skip, from this stream.
|
||||||
*
|
*
|
||||||
* @param pLength the requested length
|
* @param length the requested length
|
||||||
* @return the maximum number of bytes to read
|
* @return the maximum number of bytes to read
|
||||||
*/
|
*/
|
||||||
private long findMaxLen(long pLength) {
|
private long findMaxLen(long length) {
|
||||||
if (bytesLeft < pLength) {
|
return bytesLeft < length ? Math.max(bytesLeft, 0) : length;
|
||||||
return (int) Math.max(bytesLeft, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return pLength;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long skip(long pLength) throws IOException {
|
|
||||||
long skipped = super.skip(findMaxLen(pLength));// Skips 0 or more, never -1
|
|
||||||
bytesLeft -= skipped;
|
|
||||||
return skipped;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,39 +45,39 @@ import java.nio.ByteBuffer;
|
|||||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/DecoderStream.java#2 $
|
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/DecoderStream.java#2 $
|
||||||
*/
|
*/
|
||||||
public final class DecoderStream extends FilterInputStream {
|
public final class DecoderStream extends FilterInputStream {
|
||||||
protected final ByteBuffer buffer;
|
private final ByteBuffer buffer;
|
||||||
protected final Decoder decoder;
|
private final Decoder decoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new decoder stream and chains it to the
|
* Creates a new decoder stream and chains it to the
|
||||||
* input stream specified by the {@code pStream} argument.
|
* input stream specified by the {@code stream} argument.
|
||||||
* The stream will use a default decode buffer size.
|
* The stream will use a default decode buffer size.
|
||||||
*
|
*
|
||||||
* @param pStream the underlying input stream.
|
* @param stream the underlying input stream.
|
||||||
* @param pDecoder the decoder that will be used to decode the underlying stream
|
* @param decoder the decoder that will be used to decode the underlying stream
|
||||||
*
|
*
|
||||||
* @see java.io.FilterInputStream#in
|
* @see java.io.FilterInputStream#in
|
||||||
*/
|
*/
|
||||||
public DecoderStream(final InputStream pStream, final Decoder pDecoder) {
|
public DecoderStream(final InputStream stream, final Decoder decoder) {
|
||||||
// TODO: Let the decoder decide preferred buffer size
|
// TODO: Let the decoder decide preferred buffer size
|
||||||
this(pStream, pDecoder, 1024);
|
this(stream, decoder, 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new decoder stream and chains it to the
|
* Creates a new decoder stream and chains it to the
|
||||||
* input stream specified by the {@code pStream} argument.
|
* input stream specified by the {@code stream} argument.
|
||||||
*
|
*
|
||||||
* @param pStream the underlying input stream.
|
* @param stream the underlying input stream.
|
||||||
* @param pDecoder the decoder that will be used to decode the underlying stream
|
* @param decoder the decoder that will be used to decode the underlying stream
|
||||||
* @param pBufferSize the size of the decode buffer
|
* @param bufferSize the size of the decode buffer
|
||||||
*
|
*
|
||||||
* @see java.io.FilterInputStream#in
|
* @see java.io.FilterInputStream#in
|
||||||
*/
|
*/
|
||||||
public DecoderStream(final InputStream pStream, final Decoder pDecoder, final int pBufferSize) {
|
public DecoderStream(final InputStream stream, final Decoder decoder, final int bufferSize) {
|
||||||
super(pStream);
|
super(stream);
|
||||||
|
|
||||||
decoder = pDecoder;
|
this.decoder = decoder;
|
||||||
buffer = ByteBuffer.allocate(pBufferSize);
|
buffer = ByteBuffer.allocate(bufferSize); // TODO: Allow decoder to specify minimum buffer size
|
||||||
buffer.flip();
|
buffer.flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,15 +95,15 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
return buffer.get() & 0xff;
|
return buffer.get() & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(final byte pBytes[], final int pOffset, final int pLength) throws IOException {
|
public int read(final byte[] bytes, final int offset, final int length) throws IOException {
|
||||||
if (pBytes == null) {
|
if (bytes == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
else if ((pOffset < 0) || (pOffset > pBytes.length) || (pLength < 0) ||
|
else if ((offset < 0) || (offset > bytes.length) || (length < 0) ||
|
||||||
((pOffset + pLength) > pBytes.length) || ((pOffset + pLength) < 0)) {
|
((offset + length) > bytes.length) || ((offset + length) < 0)) {
|
||||||
throw new IndexOutOfBoundsException("bytes.length=" + pBytes.length + " offset=" + pOffset + " length=" + pLength);
|
throw new IndexOutOfBoundsException("bytes.length=" + bytes.length + " offset=" + offset + " length=" + length);
|
||||||
}
|
}
|
||||||
else if (pLength == 0) {
|
else if (length == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,11 +114,11 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read until we have read pLength bytes, or have reached EOF
|
// Read until we have read length bytes, or have reached EOF
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int off = pOffset;
|
int off = offset;
|
||||||
|
|
||||||
while (pLength > count) {
|
while (length > count) {
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
if (fill() < 0) {
|
if (fill() < 0) {
|
||||||
break;
|
break;
|
||||||
@@ -126,8 +126,8 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy as many bytes as possible
|
// Copy as many bytes as possible
|
||||||
int dstLen = Math.min(pLength - count, buffer.remaining());
|
int dstLen = Math.min(length - count, buffer.remaining());
|
||||||
buffer.get(pBytes, off, dstLen);
|
buffer.get(bytes, off, dstLen);
|
||||||
|
|
||||||
// Update offset (rest)
|
// Update offset (rest)
|
||||||
off += dstLen;
|
off += dstLen;
|
||||||
@@ -139,7 +139,7 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long skip(final long pLength) throws IOException {
|
public long skip(final long length) throws IOException {
|
||||||
// End of file?
|
// End of file?
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
if (fill() < 0) {
|
if (fill() < 0) {
|
||||||
@@ -147,10 +147,10 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip until we have skipped pLength bytes, or have reached EOF
|
// Skip until we have skipped length bytes, or have reached EOF
|
||||||
long total = 0;
|
long total = 0;
|
||||||
|
|
||||||
while (total < pLength) {
|
while (total < length) {
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
if (fill() < 0) {
|
if (fill() < 0) {
|
||||||
break;
|
break;
|
||||||
@@ -158,7 +158,7 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Skipped can never be more than avail, which is an int, so the cast is safe
|
// NOTE: Skipped can never be more than avail, which is an int, so the cast is safe
|
||||||
int skipped = (int) Math.min(pLength - total, buffer.remaining());
|
int skipped = (int) Math.min(length - total, buffer.remaining());
|
||||||
buffer.position(buffer.position() + skipped);
|
buffer.position(buffer.position() + skipped);
|
||||||
total += skipped;
|
total += skipped;
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@ public final class DecoderStream extends FilterInputStream {
|
|||||||
*
|
*
|
||||||
* @throws IOException if an I/O error occurs
|
* @throws IOException if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
protected int fill() throws IOException {
|
private int fill() throws IOException {
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
int read = decoder.decode(in, buffer);
|
int read = decoder.decode(in, buffer);
|
||||||
|
|
||||||
|
|||||||
@@ -45,41 +45,39 @@ import java.nio.ByteBuffer;
|
|||||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/EncoderStream.java#2 $
|
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/EncoderStream.java#2 $
|
||||||
*/
|
*/
|
||||||
public final class EncoderStream extends FilterOutputStream {
|
public final class EncoderStream extends FilterOutputStream {
|
||||||
// TODO: This class need a test case ASAP!!!
|
|
||||||
|
|
||||||
protected final Encoder encoder;
|
private final Encoder encoder;
|
||||||
private final boolean flushOnWrite;
|
private final boolean flushOnWrite;
|
||||||
|
|
||||||
protected final ByteBuffer buffer;
|
private final ByteBuffer buffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an output stream filter built on top of the specified
|
* Creates an output stream filter built on top of the specified
|
||||||
* underlying output stream.
|
* underlying output stream.
|
||||||
*
|
*
|
||||||
* @param pStream the underlying output stream
|
* @param stream the underlying output stream
|
||||||
* @param pEncoder the encoder to use
|
* @param encoder the encoder to use
|
||||||
*/
|
*/
|
||||||
public EncoderStream(final OutputStream pStream, final Encoder pEncoder) {
|
public EncoderStream(final OutputStream stream, final Encoder encoder) {
|
||||||
this(pStream, pEncoder, false);
|
this(stream, encoder, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an output stream filter built on top of the specified
|
* Creates an output stream filter built on top of the specified
|
||||||
* underlying output stream.
|
* underlying output stream.
|
||||||
*
|
*
|
||||||
* @param pStream the underlying output stream
|
* @param stream the underlying output stream
|
||||||
* @param pEncoder the encoder to use
|
* @param encoder the encoder to use
|
||||||
* @param pFlushOnWrite if {@code true}, calls to the byte-array
|
* @param flushOnWrite if {@code true}, calls to the byte-array
|
||||||
* {@code write} methods will automatically flush the buffer.
|
* {@code write} methods will automatically flush the buffer.
|
||||||
*/
|
*/
|
||||||
public EncoderStream(final OutputStream pStream, final Encoder pEncoder, final boolean pFlushOnWrite) {
|
public EncoderStream(final OutputStream stream, final Encoder encoder, final boolean flushOnWrite) {
|
||||||
super(pStream);
|
super(stream);
|
||||||
|
|
||||||
encoder = pEncoder;
|
this.encoder = encoder;
|
||||||
flushOnWrite = pFlushOnWrite;
|
this.flushOnWrite = flushOnWrite;
|
||||||
|
|
||||||
buffer = ByteBuffer.allocate(1024);
|
buffer = ByteBuffer.allocate(1024);
|
||||||
buffer.flip();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
@@ -104,33 +102,33 @@ public final class EncoderStream extends FilterOutputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void write(final byte[] pBytes) throws IOException {
|
public void write(final byte[] bytes) throws IOException {
|
||||||
write(pBytes, 0, pBytes.length);
|
write(bytes, 0, bytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Verify that this works for the general case (it probably won't)...
|
// TODO: Verify that this works for the general case (it probably won't)...
|
||||||
// TODO: We might need a way to explicitly flush the encoder, or specify
|
// TODO: We might need a way to explicitly flush the encoder, or specify
|
||||||
// that the encoder can't buffer. In that case, the encoder should probably
|
// that the encoder can't buffer. In that case, the encoder should probably
|
||||||
// tell the EncoderStream how large buffer it prefers...
|
// tell the EncoderStream how large buffer it prefers...
|
||||||
public void write(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
|
public void write(final byte[] values, final int offset, final int length) throws IOException {
|
||||||
if (!flushOnWrite && pLength < buffer.remaining()) {
|
if (!flushOnWrite && length < buffer.remaining()) {
|
||||||
// Buffer data
|
// Buffer data
|
||||||
buffer.put(pBytes, pOffset, pLength);
|
buffer.put(values, offset, length);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Encode data already in the buffer
|
// Encode data already in the buffer
|
||||||
encodeBuffer();
|
encodeBuffer();
|
||||||
|
|
||||||
// Encode rest without buffering
|
// Encode rest without buffering
|
||||||
encoder.encode(out, ByteBuffer.wrap(pBytes, pOffset, pLength));
|
encoder.encode(out, ByteBuffer.wrap(values, offset, length));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(final int pByte) throws IOException {
|
public void write(final int value) throws IOException {
|
||||||
if (!buffer.hasRemaining()) {
|
if (!buffer.hasRemaining()) {
|
||||||
encodeBuffer(); // Resets bufferPos to 0
|
encodeBuffer(); // Resets bufferPos to 0
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.put((byte) pByte);
|
buffer.put((byte) value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,9 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.xml;
|
package com.twelvemonkeys.xml;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
import org.w3c.dom.DOMConfiguration;
|
import org.w3c.dom.DOMConfiguration;
|
||||||
import org.w3c.dom.DOMImplementationList;
|
import org.w3c.dom.DOMImplementationList;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
@@ -38,9 +41,6 @@ import org.w3c.dom.ls.DOMImplementationLS;
|
|||||||
import org.w3c.dom.ls.LSOutput;
|
import org.w3c.dom.ls.LSOutput;
|
||||||
import org.w3c.dom.ls.LSSerializer;
|
import org.w3c.dom.ls.LSSerializer;
|
||||||
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.Writer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code DOMImplementationLS} backed implementation.
|
* {@code DOMImplementationLS} backed implementation.
|
||||||
*
|
*
|
||||||
@@ -88,17 +88,6 @@ public final class DOMSerializer {
|
|||||||
output.setCharacterStream(pStream);
|
output.setCharacterStream(pStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// TODO: Is it useful?
|
|
||||||
public void setNewLine(final String pNewLine) {
|
|
||||||
serializer.setNewLine(pNewLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNewLine() {
|
|
||||||
return serializer.getNewLine();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies wether the serializer should use indentation and optimize for
|
* Specifies wether the serializer should use indentation and optimize for
|
||||||
* readability.
|
* readability.
|
||||||
@@ -169,13 +158,7 @@ public final class DOMSerializer {
|
|||||||
try {
|
try {
|
||||||
return DOMImplementationRegistry.newInstance();
|
return DOMImplementationRegistry.newInstance();
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException e) {
|
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
catch (InstantiationException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
catch (IllegalAccessException e) {
|
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,16 +30,23 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.xml;
|
package com.twelvemonkeys.xml;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
import java.io.ByteArrayInputStream;
|
||||||
import org.w3c.dom.*;
|
import java.io.ByteArrayOutputStream;
|
||||||
import org.xml.sax.SAXException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import java.io.*;
|
|
||||||
import java.nio.charset.Charset;
|
import org.w3c.dom.*;
|
||||||
import java.util.Date;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XMLSerializer
|
* XMLSerializer
|
||||||
@@ -290,7 +297,7 @@ public class XMLSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int appendAndEscape(final String pString, int pStart, final int pEnd, final StringBuilder pBuilder, final String pEntity) {
|
private static int appendAndEscape(final String pString, int pStart, final int pEnd, final StringBuilder pBuilder, final String pEntity) {
|
||||||
pBuilder.append(pString.substring(pStart, pEnd));
|
pBuilder.append(pString, pStart, pEnd);
|
||||||
pBuilder.append(pEntity);
|
pBuilder.append(pEntity);
|
||||||
return pEnd + 1;
|
return pEnd + 1;
|
||||||
}
|
}
|
||||||
@@ -527,8 +534,7 @@ public class XMLSerializer {
|
|||||||
builder = factory.newDocumentBuilder();
|
builder = factory.newDocumentBuilder();
|
||||||
}
|
}
|
||||||
catch (ParserConfigurationException e) {
|
catch (ParserConfigurationException e) {
|
||||||
//noinspection ThrowableInstanceNeverThrown BOGUS
|
throw new IOException(e);
|
||||||
throw (IOException) new IOException(e.getMessage()).initCause(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMImplementation dom = builder.getDOMImplementation();
|
DOMImplementation dom = builder.getDOMImplementation();
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ package com.twelvemonkeys.io;
|
|||||||
|
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
import com.twelvemonkeys.util.CollectionUtil;
|
import com.twelvemonkeys.util.CollectionUtil;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
@@ -40,7 +39,8 @@ import java.io.StringReader;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CompoundReaderTestCase
|
* CompoundReaderTestCase
|
||||||
|
|||||||
+2
-3
@@ -30,12 +30,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FastByteArrayOutputStreamTestCase
|
* FastByteArrayOutputStreamTestCase
|
||||||
|
|||||||
@@ -30,11 +30,10 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MemoryCacheSeekableStreamTestCase
|
* MemoryCacheSeekableStreamTestCase
|
||||||
@@ -92,13 +91,13 @@ public class FileSeekableStreamTest extends SeekableInputStreamAbstractTest {
|
|||||||
try {
|
try {
|
||||||
FileUtil.read(stream); // Read until EOF
|
FileUtil.read(stream); // Read until EOF
|
||||||
|
|
||||||
assertEquals("EOF not reached (test case broken)", -1, stream.read());
|
assertEquals(-1, stream.read(), "EOF not reached (test case broken)");
|
||||||
assertFalse("Underlying stream closed before close", closed[0]);
|
assertFalse(closed[0], "Underlying stream closed before close");
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
stream.close();
|
stream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("Underlying stream not closed", closed[0]);
|
assertTrue(closed[0], "Underlying stream not closed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,14 +46,14 @@
|
|||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InputStreamAbstractTestCase
|
* InputStreamAbstractTestCase
|
||||||
@@ -104,15 +104,15 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
int size = 5;
|
int size = 5;
|
||||||
InputStream input = makeInputStream(makeOrderedArray(size));
|
InputStream input = makeInputStream(makeOrderedArray(size));
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
assertTrue("Check Size [" + i + "]", (size - i) >= input.available());
|
assertTrue((size - i) >= input.available(), "Check Size [" + i + "]");
|
||||||
assertEquals("Check Value [" + i + "]", i, input.read());
|
assertEquals(i, input.read(), "Check Value [" + i + "]");
|
||||||
}
|
}
|
||||||
assertEquals("Available after contents all read", 0, input.available());
|
assertEquals(0, input.available(), "Available after contents all read");
|
||||||
|
|
||||||
// Test reading after the end of file
|
// Test reading after the end of file
|
||||||
try {
|
try {
|
||||||
int result = input.read();
|
int result = input.read();
|
||||||
assertEquals("Wrong value read after end of file", -1, result);
|
assertEquals( -1, result, "Wrong value read after end of file");
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
fail("Should not have thrown an IOException: " + e.getMessage());
|
fail("Should not have thrown an IOException: " + e.getMessage());
|
||||||
@@ -122,12 +122,12 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testAvailable() throws Exception {
|
public void testAvailable() throws Exception {
|
||||||
InputStream input = makeInputStream(1);
|
InputStream input = makeInputStream(1);
|
||||||
assertFalse("Unexpected EOF", input.read() < 0);
|
assertFalse(input.read() < 0, "Unexpected EOF");
|
||||||
assertEquals("Available after contents all read", 0, input.available());
|
assertEquals(0, input.available(), "Available after contents all read");
|
||||||
|
|
||||||
// Check availbale is zero after End of file
|
// Check availbale is zero after End of file
|
||||||
assertEquals("End of File", -1, input.read());
|
assertEquals(-1, input.read(), "End of File");
|
||||||
assertEquals("Available after End of File", 0, input.available());
|
assertEquals( 0, input.available(), "Available after End of File");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -138,26 +138,26 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
// Read into array
|
// Read into array
|
||||||
int count1 = input.read(bytes);
|
int count1 = input.read(bytes);
|
||||||
assertEquals("Read 1", bytes.length, count1);
|
assertEquals(bytes.length, count1, "Read 1");
|
||||||
for (int i = 0; i < count1; i++) {
|
for (int i = 0; i < count1; i++) {
|
||||||
assertEquals("Check Bytes 1", i, bytes[i]);
|
assertEquals(i, bytes[i], "Check Bytes 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read into array
|
// Read into array
|
||||||
int count2 = input.read(bytes);
|
int count2 = input.read(bytes);
|
||||||
assertEquals("Read 2", 5, count2);
|
assertEquals(5, count2, "Read 2");
|
||||||
for (int i = 0; i < count2; i++) {
|
for (int i = 0; i < count2; i++) {
|
||||||
assertEquals("Check Bytes 2", count1 + i, bytes[i]);
|
assertEquals(count1 + i, bytes[i], "Check Bytes 2");
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of File
|
// End of File
|
||||||
int count3 = input.read(bytes);
|
int count3 = input.read(bytes);
|
||||||
assertEquals("Read 3 (EOF)", -1, count3);
|
assertEquals(-1, count3, "Read 3 (EOF)");
|
||||||
|
|
||||||
// Test reading after the end of file
|
// Test reading after the end of file
|
||||||
try {
|
try {
|
||||||
int result = input.read(bytes);
|
int result = input.read(bytes);
|
||||||
assertEquals("Wrong value read after end of file", -1, result);
|
assertEquals(-1, result, "Wrong value read after end of file");
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
fail("Should not have thrown an IOException: " + e.getMessage());
|
fail("Should not have thrown an IOException: " + e.getMessage());
|
||||||
@@ -170,20 +170,20 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
int offset = 2;
|
int offset = 2;
|
||||||
int lth = 4;
|
int lth = 4;
|
||||||
int count5 = input.read(bytes, offset, lth);
|
int count5 = input.read(bytes, offset, lth);
|
||||||
assertEquals("Read 5", lth, count5);
|
assertEquals(lth, count5, "Read 5");
|
||||||
for (int i = offset; i < lth; i++) {
|
for (int i = offset; i < lth; i++) {
|
||||||
assertEquals("Check Bytes 2", i - offset, bytes[i]);
|
assertEquals(i - offset, bytes[i], "Check Bytes 2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEOF() throws Exception {
|
public void testEOF() throws Exception {
|
||||||
InputStream input = makeInputStream(makeOrderedArray(2));
|
InputStream input = makeInputStream(makeOrderedArray(2));
|
||||||
assertEquals("Read 1", 0, input.read());
|
assertEquals(0, input.read(), "Read 1");
|
||||||
assertEquals("Read 2", 1, input.read());
|
assertEquals(1, input.read(), "Read 2");
|
||||||
assertEquals("Read 3", -1, input.read());
|
assertEquals(-1, input.read(), "Read 3");
|
||||||
assertEquals("Read 4", -1, input.read());
|
assertEquals(-1, input.read(), "Read 4");
|
||||||
assertEquals("Read 5", -1, input.read());
|
assertEquals(-1, input.read(), "Read 5");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -205,7 +205,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
fail("Should throw IOException");
|
fail("Should throw IOException");
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
assertTrue("Wrong messge: " + e.getMessage(), e.getMessage().contains("reset"));
|
assertTrue(e.getMessage().contains("reset"), "Wrong messge: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,10 +223,10 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
// No mark may either throw exception, or reset to beginning of stream.
|
// No mark may either throw exception, or reset to beginning of stream.
|
||||||
try {
|
try {
|
||||||
input.reset();
|
input.reset();
|
||||||
assertEquals("Re-read of reset data should be same", 0, input.read());
|
assertEquals(0, input.read(), "Re-read of reset data should be same");
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
assertTrue("Wrong no mark IOException message", e.getMessage().contains("mark"));
|
assertTrue(e.getMessage().contains("mark"), "Wrong no mark IOException message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
// Read further
|
// Read further
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
assertEquals("Read After Mark [" + i + "]", (position + i), input.read());
|
assertEquals((position + i), input.read(), "Read After Mark [" + i + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset
|
// Reset
|
||||||
@@ -257,7 +257,7 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
// Read from marked position
|
// Read from marked position
|
||||||
for (int i = 0; i < readlimit + 1; i++) {
|
for (int i = 0; i < readlimit + 1; i++) {
|
||||||
assertEquals("Read After Reset [" + i + "]", (position + i), input.read());
|
assertEquals((position + i), input.read(), "Read After Reset [" + i + "]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,16 +280,16 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
// Read past marked position
|
// Read past marked position
|
||||||
for (int i = 0; i < readlimit + 1; i++) {
|
for (int i = 0; i < readlimit + 1; i++) {
|
||||||
assertEquals("Read After Reset [" + i + "]", (position + i), input.read());
|
assertEquals((position + i), input.read(), "Read After Reset [" + i + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset after read limit passed, may either throw exception, or reset to last mark
|
// Reset after read limit passed, may either throw exception, or reset to last mark
|
||||||
try {
|
try {
|
||||||
input.reset();
|
input.reset();
|
||||||
assertEquals("Re-read of reset data should be same", 1, input.read());
|
assertEquals(1, input.read(), "Re-read of reset data should be same");
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
assertTrue("Wrong read-limit IOException message", e.getMessage().contains("mark"));
|
assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,29 +302,29 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int first = input.read();
|
int first = input.read();
|
||||||
assertTrue("Expected to read positive value", first >= 0);
|
assertTrue(first >= 0, "Expected to read positive value");
|
||||||
|
|
||||||
int readlimit = 5;
|
int readlimit = 5;
|
||||||
|
|
||||||
// Mark
|
// Mark
|
||||||
input.mark(readlimit);
|
input.mark(readlimit);
|
||||||
int read = input.read();
|
int read = input.read();
|
||||||
assertTrue("Expected to read positive value", read >= 0);
|
assertTrue(read >= 0, "Expected to read positive value");
|
||||||
|
|
||||||
assertTrue(input.read() >= 0);
|
assertTrue(input.read() >= 0);
|
||||||
assertTrue(input.read() >= 0);
|
assertTrue(input.read() >= 0);
|
||||||
|
|
||||||
input.reset();
|
input.reset();
|
||||||
assertEquals("Expected value read differs from actual", read, input.read());
|
assertEquals(read, input.read(), "Expected value read differs from actual");
|
||||||
|
|
||||||
// Reset after read limit passed, may either throw exception, or reset to last good mark
|
// Reset after read limit passed, may either throw exception, or reset to last good mark
|
||||||
try {
|
try {
|
||||||
input.reset();
|
input.reset();
|
||||||
int reRead = input.read();
|
int reRead = input.read();
|
||||||
assertTrue("Re-read of reset data should be same as initially marked or first", reRead == read || reRead == first);
|
assertTrue(reRead == read || reRead == first, "Re-read of reset data should be same as initially marked or first");
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
assertTrue("Wrong read-limit IOException message", e.getMessage().contains("mark"));
|
assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,17 +332,17 @@ public abstract class InputStreamAbstractTest extends ObjectAbstractTest {
|
|||||||
public void testSkip() throws Exception {
|
public void testSkip() throws Exception {
|
||||||
InputStream input = makeInputStream(makeOrderedArray(10));
|
InputStream input = makeInputStream(makeOrderedArray(10));
|
||||||
|
|
||||||
assertEquals("Unexpected value read", 0, input.read());
|
assertEquals(0, input.read(), "Unexpected value read");
|
||||||
assertEquals("Unexpected value read", 1, input.read());
|
assertEquals(1, input.read(), "Unexpected value read");
|
||||||
assertEquals("Unexpected number of bytes skipped", 5, input.skip(5));
|
assertEquals(5, input.skip(5), "Unexpected number of bytes skipped");
|
||||||
assertEquals("Unexpected value read", 7, input.read());
|
assertEquals(7, input.read(), "Unexpected value read");
|
||||||
|
|
||||||
assertEquals("Unexpected number of bytes skipped", 2, input.skip(5)); // only 2 left to skip
|
assertEquals(2, input.skip(5), "Unexpected number of bytes skipped"); // only 2 left to skip
|
||||||
assertEquals("Unexpected value read after EOF", -1, input.read());
|
assertEquals(-1, input.read(), "Unexpected value read after EOF");
|
||||||
|
|
||||||
// Spec says skip might return 0 or negative after EOF...
|
// Spec says skip might return 0 or negative after EOF...
|
||||||
assertTrue("Positive value skipped after EOF", input.skip(5) <= 0); // End of file
|
assertTrue(input.skip(5) <= 0, "Positive value skipped after EOF"); // End of file
|
||||||
assertEquals("Unexpected value read after EOF", -1, input.read());
|
assertEquals(-1, input.read(), "Unexpected value read after EOF");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+2
-3
@@ -30,12 +30,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LittleEndianDataInputStreamTest
|
* LittleEndianDataInputStreamTest
|
||||||
|
|||||||
@@ -31,13 +31,12 @@
|
|||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InputStreamAbstractTestCase
|
* InputStreamAbstractTestCase
|
||||||
|
|||||||
@@ -31,12 +31,12 @@
|
|||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ReaderAbstractTestCase
|
* ReaderAbstractTestCase
|
||||||
@@ -112,7 +112,7 @@ public abstract class ReaderAbstractTest extends ObjectAbstractTest {
|
|||||||
int toSkip = mInput.length();
|
int toSkip = mInput.length();
|
||||||
while (toSkip > 0) {
|
while (toSkip > 0) {
|
||||||
long skipped = reader.skip(toSkip);
|
long skipped = reader.skip(toSkip);
|
||||||
assertFalse("Skipped < 0", skipped < 0);
|
assertFalse(skipped < 0, "Skipped < 0");
|
||||||
toSkip -= skipped;
|
toSkip -= skipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,10 +30,8 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SeekableAbstractTestCase
|
* SeekableAbstractTestCase
|
||||||
|
|||||||
+22
-23
@@ -30,14 +30,13 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SeekableInputStreamAbstractTest
|
* SeekableInputStreamAbstractTest
|
||||||
@@ -79,25 +78,25 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
return; // Not supported, skip test
|
return; // Not supported, skip test
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("Expected to read positive value", input.read() >= 0);
|
assertTrue(input.read() >= 0, "Expected to read positive value");
|
||||||
|
|
||||||
int readlimit = 5;
|
int readlimit = 5;
|
||||||
|
|
||||||
// Mark
|
// Mark
|
||||||
input.mark(readlimit);
|
input.mark(readlimit);
|
||||||
int read = input.read();
|
int read = input.read();
|
||||||
assertTrue("Expected to read positive value", read >= 0);
|
assertTrue(read >= 0, "Expected to read positive value");
|
||||||
|
|
||||||
input.reset();
|
input.reset();
|
||||||
assertEquals("Expected value read differs from actual", read, input.read());
|
assertEquals(read, input.read(), "Expected value read differs from actual");
|
||||||
|
|
||||||
// Reset after read limit passed, may either throw exception, or reset to last good mark
|
// Reset after read limit passed, may either throw exception, or reset to last good mark
|
||||||
try {
|
try {
|
||||||
input.reset();
|
input.reset();
|
||||||
assertEquals("Re-read of reset data should be first", 0, input.read());
|
assertEquals(0, input.read(), "Re-read of reset data should be first");
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
assertTrue("Wrong read-limit IOException message", e.getMessage().contains("mark"));
|
assertTrue(e.getMessage().contains("mark"), "Wrong read-limit IOException message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +126,7 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
|
|
||||||
seekable.seek(pos);
|
seekable.seek(pos);
|
||||||
long streamPos = seekable.getStreamPosition();
|
long streamPos = seekable.getStreamPosition();
|
||||||
assertEquals("Stream positon should match seeked position", pos, streamPos);
|
assertEquals(pos, streamPos, "Stream positon should match seeked position");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -137,7 +136,7 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
seekable.seek(pos);
|
seekable.seek(pos);
|
||||||
seekable.flushBefore(pos);
|
seekable.flushBefore(pos);
|
||||||
long flushedPos = seekable.getFlushedPosition();
|
long flushedPos = seekable.getFlushedPosition();
|
||||||
assertEquals("Flushed positon should match position", pos, flushedPos);
|
assertEquals(pos, flushedPos, "Flushed positon should match position");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
seekable.seek(pos - 1);
|
seekable.seek(pos - 1);
|
||||||
@@ -382,13 +381,13 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
int val;
|
int val;
|
||||||
|
|
||||||
val = stream.read();
|
val = stream.read();
|
||||||
assertFalse("Unexepected EOF", val == -1);
|
assertFalse(val == -1, "Unexepected EOF");
|
||||||
val = stream.read();
|
val = stream.read();
|
||||||
assertFalse("Unexepected EOF", val == -1);
|
assertFalse(val == -1, "Unexepected EOF");
|
||||||
val = stream.read();
|
val = stream.read();
|
||||||
assertFalse("Unexepected EOF", val == -1);
|
assertFalse(val == -1, "Unexepected EOF");
|
||||||
val = stream.read();
|
val = stream.read();
|
||||||
assertFalse("Unexepected EOF", val == -1);
|
assertFalse(val == -1, "Unexepected EOF");
|
||||||
|
|
||||||
stream.seek(0);
|
stream.seek(0);
|
||||||
|
|
||||||
@@ -422,19 +421,19 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
|
|
||||||
stream.seek(0);
|
stream.seek(0);
|
||||||
for (int i = 0; i < bytes.length; i += 2) {
|
for (int i = 0; i < bytes.length; i += 2) {
|
||||||
assertEquals("Wrong stream position", i, stream.getStreamPosition());
|
assertEquals(i, stream.getStreamPosition(), "Wrong stream position");
|
||||||
int count = stream.read(buffer, 0, 2);
|
int count = stream.read(buffer, 0, 2);
|
||||||
assertEquals(2, count);
|
assertEquals(2, count);
|
||||||
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i], buffer[0]);
|
assertEquals(bytes[i], buffer[0], String.format("Wrong value read at pos %d", stream.getStreamPosition()));
|
||||||
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i + 1], buffer[1]);
|
assertEquals(bytes[i + 1], buffer[1], String.format("Wrong value read at pos %d", stream.getStreamPosition()));
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.seek(0);
|
stream.seek(0);
|
||||||
for (int i = 0; i < bytes.length; i++) {
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
assertEquals("Wrong stream position", i, stream.getStreamPosition());
|
assertEquals(i, stream.getStreamPosition(), "Wrong stream position");
|
||||||
int actual = stream.read();
|
int actual = stream.read();
|
||||||
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i] & 0xff, actual);
|
assertEquals(bytes[i] & 0xff, actual, String.format("Wrong value read at pos %d", stream.getStreamPosition()));
|
||||||
assertEquals(String.format("Wrong value read at pos %d", stream.getStreamPosition()), bytes[i], (byte) actual);
|
assertEquals(bytes[i], (byte) actual, String.format("Wrong value read at pos %d", stream.getStreamPosition()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -456,14 +455,14 @@ public abstract class SeekableInputStreamAbstractTest extends InputStreamAbstrac
|
|||||||
try {
|
try {
|
||||||
FileUtil.read(stream); // Read until EOF
|
FileUtil.read(stream); // Read until EOF
|
||||||
|
|
||||||
assertEquals("EOF not reached (test case broken)", -1, stream.read());
|
assertEquals(-1, stream.read(), "EOF not reached (test case broken)");
|
||||||
assertFalse("Underlying stream closed before close", closed[0]);
|
assertFalse(closed[0], "Underlying stream closed before close");
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
stream.close();
|
stream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("Underlying stream not closed", closed[0]);
|
assertTrue(closed[0], "Underlying stream not closed");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,12 +31,12 @@
|
|||||||
package com.twelvemonkeys.io;
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StringArrayReaderTestCase
|
* StringArrayReaderTestCase
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package com.twelvemonkeys.io;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SubStreamTest.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
|
* @author last modified by $Author: haraldk$
|
||||||
|
* @version $Id: SubStreamTest.java,v 1.0 07/11/2023 haraldk Exp$
|
||||||
|
*/
|
||||||
|
public class SubStreamTest {
|
||||||
|
|
||||||
|
private final Random rng = new Random(2918475687L);
|
||||||
|
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
@Test
|
||||||
|
public void testCreateNullStream() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
new SubStream(null, 42);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateNegativeLength() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
new SubStream(new ByteArrayInputStream(new byte[1]), -1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadAll() throws IOException {
|
||||||
|
byte[] buf = new byte[128];
|
||||||
|
rng.nextBytes(buf);
|
||||||
|
|
||||||
|
try (InputStream stream = new SubStream(new ByteArrayInputStream(buf), buf.length)) {
|
||||||
|
for (byte b : buf) {
|
||||||
|
assertEquals(b, (byte) stream.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(-1, stream.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadAllArray() throws IOException {
|
||||||
|
byte[] buf = new byte[128];
|
||||||
|
rng.nextBytes(buf);
|
||||||
|
|
||||||
|
try (InputStream stream = new SubStream(new ByteArrayInputStream(buf), buf.length)) {
|
||||||
|
byte[] temp = new byte[buf.length / 4];
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
assertEquals(temp.length, stream.read(temp)); // Depends on ByteArrayInputStream specifics...
|
||||||
|
assertArrayEquals(Arrays.copyOfRange(buf, i * temp.length, (i + 1) * temp.length), temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(-1, stream.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSkipAll() throws IOException {
|
||||||
|
byte[] buf = new byte[128];
|
||||||
|
|
||||||
|
try (InputStream stream = new SubStream(new ByteArrayInputStream(buf), buf.length)) {
|
||||||
|
assertEquals(128, stream.skip(buf.length)); // Depends on ByteArrayInputStream specifics...
|
||||||
|
assertEquals(-1, stream.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("EmptyTryBlock")
|
||||||
|
@Test
|
||||||
|
public void testCloseConsumesAll() throws IOException {
|
||||||
|
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[128]);
|
||||||
|
|
||||||
|
try (InputStream ignore = new SubStream(stream, 128)) {
|
||||||
|
// Nothing here...
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(0, stream.available());
|
||||||
|
assertEquals(-1, stream.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("EmptyTryBlock")
|
||||||
|
@Test
|
||||||
|
public void testCloseConsumesAllLongStream() throws IOException {
|
||||||
|
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[256]);
|
||||||
|
|
||||||
|
try (InputStream ignore = new SubStream(stream, 128)) {
|
||||||
|
// Nothing here...
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(128, stream.available());
|
||||||
|
assertEquals(0, stream.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("EmptyTryBlock")
|
||||||
|
@Test
|
||||||
|
public void testCloseConsumesAllShortStream() throws IOException {
|
||||||
|
assertTimeoutPreemptively(Duration.ofMillis(500), () -> {
|
||||||
|
ByteArrayInputStream stream = new ByteArrayInputStream(new byte[13]);
|
||||||
|
|
||||||
|
try (InputStream ignore = new SubStream(stream, 42)) {
|
||||||
|
// Nothing here...
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(0, stream.available());
|
||||||
|
assertEquals(-1, stream.read());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,15 +31,13 @@
|
|||||||
package com.twelvemonkeys.io.enc;
|
package com.twelvemonkeys.io.enc;
|
||||||
|
|
||||||
import com.twelvemonkeys.io.FileUtil;
|
import com.twelvemonkeys.io.FileUtil;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base64DecoderTest
|
* Base64DecoderTest
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -66,7 +64,7 @@ public class Base64DecoderTest extends DecoderAbstractTest {
|
|||||||
|
|
||||||
FileUtil.copy(in, bytes);
|
FileUtil.copy(in, bytes);
|
||||||
|
|
||||||
assertEquals("Strings does not match", "", new String(bytes.toByteArray()));
|
assertEquals("", new String(bytes.toByteArray()), "Strings does not match");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -78,7 +76,7 @@ public class Base64DecoderTest extends DecoderAbstractTest {
|
|||||||
|
|
||||||
FileUtil.copy(in, bytes);
|
FileUtil.copy(in, bytes);
|
||||||
|
|
||||||
assertEquals("Strings does not match", "test", new String(bytes.toByteArray()));
|
assertEquals("test", new String(bytes.toByteArray()), "Strings does not match");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -93,11 +91,12 @@ public class Base64DecoderTest extends DecoderAbstractTest {
|
|||||||
|
|
||||||
FileUtil.copy(in, bytes);
|
FileUtil.copy(in, bytes);
|
||||||
|
|
||||||
assertEquals("Strings does not match",
|
assertEquals(
|
||||||
"Lorem ipsum dolor sit amet, consectetuer adipiscing " +
|
"Lorem ipsum dolor sit amet, consectetuer adipiscing " +
|
||||||
"elit. Fusce est. Morbi luctus consectetuer justo. Vivamus " +
|
"elit. Fusce est. Morbi luctus consectetuer justo. Vivamus " +
|
||||||
"dapibus laoreet purus. Nunc viverra dictum nisl. Integer " +
|
"dapibus laoreet purus. Nunc viverra dictum nisl. Integer " +
|
||||||
"ullamcorper, nisi in dictum amet.",
|
"ullamcorper, nisi in dictum amet.",
|
||||||
new String(bytes.toByteArray()));
|
new String(bytes.toByteArray()),
|
||||||
|
"Strings does not match");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,13 +30,12 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.io.enc;
|
package com.twelvemonkeys.io.enc;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base64EncoderTest
|
* Base64EncoderTest
|
||||||
@@ -63,7 +62,7 @@ public class Base64EncoderTest extends EncoderAbstractTest {
|
|||||||
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
||||||
out.write(data.getBytes());
|
out.write(data.getBytes());
|
||||||
|
|
||||||
assertEquals("Strings does not match", "", new String(bytes.toByteArray()));
|
assertEquals("", new String(bytes.toByteArray()), "Strings does not match");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -74,7 +73,7 @@ public class Base64EncoderTest extends EncoderAbstractTest {
|
|||||||
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
||||||
out.write(data.getBytes());
|
out.write(data.getBytes());
|
||||||
|
|
||||||
assertEquals("Strings does not match", "dGVzdA==", new String(bytes.toByteArray()));
|
assertEquals("dGVzdA==", new String(bytes.toByteArray()), "Strings does not match");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -88,11 +87,12 @@ public class Base64EncoderTest extends EncoderAbstractTest {
|
|||||||
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
OutputStream out = new EncoderStream(bytes, createEncoder(), true);
|
||||||
out.write(data.getBytes());
|
out.write(data.getBytes());
|
||||||
|
|
||||||
assertEquals("Strings does not match",
|
assertEquals(
|
||||||
"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVlciBhZGlwaXNjaW5nIGVsaXQuIEZ1" +
|
"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVlciBhZGlwaXNjaW5nIGVsaXQuIEZ1" +
|
||||||
"c2NlIGVzdC4gTW9yYmkgbHVjdHVzIGNvbnNlY3RldHVlciBqdXN0by4gVml2YW11cyBkYXBpYnVzIGxh" +
|
"c2NlIGVzdC4gTW9yYmkgbHVjdHVzIGNvbnNlY3RldHVlciBqdXN0by4gVml2YW11cyBkYXBpYnVzIGxh" +
|
||||||
"b3JlZXQgcHVydXMuIE51bmMgdml2ZXJyYSBkaWN0dW0gbmlzbC4gSW50ZWdlciB1bGxhbWNvcnBlciwg" +
|
"b3JlZXQgcHVydXMuIE51bmMgdml2ZXJyYSBkaWN0dW0gbmlzbC4gSW50ZWdlciB1bGxhbWNvcnBlciwg" +
|
||||||
"bmlzaSBpbiBkaWN0dW0gYW1ldC4=",
|
"bmlzaSBpbiBkaWN0dW0gYW1ldC4=",
|
||||||
new String(bytes.toByteArray()));
|
new String(bytes.toByteArray()),
|
||||||
|
"Strings does not match");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,13 @@ package com.twelvemonkeys.io.enc;
|
|||||||
|
|
||||||
import com.twelvemonkeys.io.FileUtil;
|
import com.twelvemonkeys.io.FileUtil;
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
|
import java.awt.image.ImageProducer;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractDecoderTest
|
* AbstractDecoderTest
|
||||||
@@ -55,13 +56,13 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
|||||||
return createDecoder();
|
return createDecoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = NullPointerException.class)
|
@Test
|
||||||
public final void testNullDecode() throws IOException {
|
public final void testNullDecode() throws IOException {
|
||||||
Decoder decoder = createDecoder();
|
Decoder decoder = createDecoder();
|
||||||
ByteArrayInputStream bytes = new ByteArrayInputStream(new byte[20]);
|
ByteArrayInputStream bytes = new ByteArrayInputStream(new byte[20]);
|
||||||
|
assertThrows(NullPointerException.class, () -> {
|
||||||
decoder.decode(bytes, null);
|
decoder.decode(bytes, null);
|
||||||
fail("null should throw NullPointerException");
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -71,7 +72,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
int count = decoder.decode(bytes, ByteBuffer.allocate(128));
|
int count = decoder.decode(bytes, ByteBuffer.allocate(128));
|
||||||
assertEquals("Should not be able to read any bytes", 0, count);
|
assertEquals( 0, count, "Should not be able to read any bytes");
|
||||||
}
|
}
|
||||||
catch (EOFException allowed) {
|
catch (EOFException allowed) {
|
||||||
// Okay
|
// Okay
|
||||||
@@ -94,7 +95,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
|||||||
byte[] encoded = outBytes.toByteArray();
|
byte[] encoded = outBytes.toByteArray();
|
||||||
|
|
||||||
byte[] decoded = FileUtil.read(new DecoderStream(new ByteArrayInputStream(encoded), createDecoder()));
|
byte[] decoded = FileUtil.read(new DecoderStream(new ByteArrayInputStream(encoded), createDecoder()));
|
||||||
assertArrayEquals(String.format("Data %d", pLength), data, decoded);
|
assertArrayEquals(data, decoded, String.format("Data %d", pLength));
|
||||||
|
|
||||||
InputStream in = new DecoderStream(new ByteArrayInputStream(encoded), createDecoder());
|
InputStream in = new DecoderStream(new ByteArrayInputStream(encoded), createDecoder());
|
||||||
outBytes = new ByteArrayOutputStream();
|
outBytes = new ByteArrayOutputStream();
|
||||||
@@ -103,7 +104,7 @@ public abstract class DecoderAbstractTest extends ObjectAbstractTest {
|
|||||||
in.close();
|
in.close();
|
||||||
|
|
||||||
decoded = outBytes.toByteArray();
|
decoded = outBytes.toByteArray();
|
||||||
assertArrayEquals(String.format("Data %d", pLength), data, decoded);
|
assertArrayEquals(data, decoded, String.format("Data %d", pLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Harald Kuhr
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of the copyright holder nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.twelvemonkeys.io.enc;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class DecoderStreamTest {
|
||||||
|
|
||||||
|
private final Random rng = new Random(5467809876546L);
|
||||||
|
|
||||||
|
private byte[] createData(final int length) {
|
||||||
|
byte[] data = new byte[length];
|
||||||
|
rng.nextBytes(data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDecodeSingleBytes() throws IOException {
|
||||||
|
byte[] data = createData(1327);
|
||||||
|
|
||||||
|
InputStream source = new ByteArrayInputStream(data);
|
||||||
|
try (InputStream stream = new DecoderStream(source, new NullDecoder())) {
|
||||||
|
for (byte datum : data) {
|
||||||
|
int read = stream.read();
|
||||||
|
assertNotEquals(-1, read);
|
||||||
|
assertEquals(datum, (byte) read);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(-1, stream.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDecodeArray() throws IOException {
|
||||||
|
int length = 793;
|
||||||
|
byte[] data = createData(length * 10);
|
||||||
|
|
||||||
|
InputStream source = new ByteArrayInputStream(data);
|
||||||
|
byte[] result = new byte[477];
|
||||||
|
|
||||||
|
try (InputStream stream = new DecoderStream(source, new NullDecoder())) {
|
||||||
|
int dataOffset = 0;
|
||||||
|
while (dataOffset < data.length) {
|
||||||
|
int count = stream.read(result);
|
||||||
|
|
||||||
|
assertFalse(count <= 0);
|
||||||
|
assertArrayEquals(Arrays.copyOfRange(data, dataOffset, dataOffset + count), Arrays.copyOfRange(result, 0, count));
|
||||||
|
|
||||||
|
dataOffset += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(-1, stream.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDecodeArrayOffset() throws IOException {
|
||||||
|
int length = 793;
|
||||||
|
byte[] data = createData(length * 10);
|
||||||
|
|
||||||
|
InputStream source = new ByteArrayInputStream(data);
|
||||||
|
byte[] result = new byte[477];
|
||||||
|
|
||||||
|
try (InputStream stream = new DecoderStream(source, new NullDecoder())) {
|
||||||
|
int dataOffset = 0;
|
||||||
|
while (dataOffset < data.length) {
|
||||||
|
int resultOffset = dataOffset % result.length;
|
||||||
|
int count = stream.read(result, resultOffset, result.length - resultOffset);
|
||||||
|
|
||||||
|
assertFalse(count <= 0);
|
||||||
|
assertArrayEquals(Arrays.copyOfRange(data, dataOffset + resultOffset, dataOffset + count), Arrays.copyOfRange(result, resultOffset, count));
|
||||||
|
|
||||||
|
dataOffset += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(-1, stream.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class NullDecoder implements Decoder {
|
||||||
|
@Override
|
||||||
|
public int decode(InputStream stream, ByteBuffer buffer) throws IOException {
|
||||||
|
int read = stream.read(buffer.array(), buffer.arrayOffset(), buffer.remaining());
|
||||||
|
|
||||||
|
if (read > 0) {
|
||||||
|
// Set position, should be equivalent to using buffer.put(stream.read()) until EOF or buffer full
|
||||||
|
buffer.position(read);
|
||||||
|
}
|
||||||
|
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,13 +33,12 @@ package com.twelvemonkeys.io.enc;
|
|||||||
import com.twelvemonkeys.io.FileUtil;
|
import com.twelvemonkeys.io.FileUtil;
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractEncoderTest
|
* AbstractEncoderTest
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, Harald Kuhr
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of the copyright holder nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.twelvemonkeys.io.enc;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class EncoderStreamTest {
|
||||||
|
|
||||||
|
private final Random rng = new Random(5467809876546L);
|
||||||
|
|
||||||
|
private byte[] createData(final int length) {
|
||||||
|
byte[] data = new byte[length];
|
||||||
|
rng.nextBytes(data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeSingleBytes() throws IOException {
|
||||||
|
byte[] data = createData(1327);
|
||||||
|
|
||||||
|
ByteArrayOutputStream result = new ByteArrayOutputStream();
|
||||||
|
try (OutputStream stream = new EncoderStream(result, new NullEncoder())) {
|
||||||
|
for (byte datum : data) {
|
||||||
|
stream.write(datum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertArrayEquals(data, result.toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeArray() throws IOException {
|
||||||
|
byte[] data = createData(1793);
|
||||||
|
|
||||||
|
ByteArrayOutputStream result = new ByteArrayOutputStream();
|
||||||
|
try (OutputStream stream = new EncoderStream(result, new NullEncoder())) {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
stream.write(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] encoded = result.toByteArray();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
assertArrayEquals(data, Arrays.copyOfRange(encoded, i * data.length, (i + 1) * data.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeArrayOffset() throws IOException {
|
||||||
|
byte[] data = createData(87);
|
||||||
|
|
||||||
|
ByteArrayOutputStream result = new ByteArrayOutputStream();
|
||||||
|
try (OutputStream stream = new EncoderStream(result, new NullEncoder())) {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
stream.write(data, 13, 59);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] original = Arrays.copyOfRange(data, 13, 13 + 59);
|
||||||
|
byte[] encoded = result.toByteArray();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
assertArrayEquals(original, Arrays.copyOfRange(encoded, i * original.length, (i + 1) * original.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class NullEncoder implements Encoder {
|
||||||
|
@Override
|
||||||
|
public void encode(OutputStream stream, ByteBuffer buffer) throws IOException {
|
||||||
|
stream.write(buffer.array(), buffer.arrayOffset(), buffer.remaining());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
-16
@@ -31,9 +31,9 @@
|
|||||||
package com.twelvemonkeys.io.ole2;
|
package com.twelvemonkeys.io.ole2;
|
||||||
|
|
||||||
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
|
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||||
|
import java.awt.image.ImageProducer;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -43,8 +43,8 @@ import java.nio.ByteOrder;
|
|||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
/**
|
/**
|
||||||
* CompoundDocumentTestCase
|
* CompoundDocumentTestCase
|
||||||
*
|
*
|
||||||
@@ -59,8 +59,8 @@ public class CompoundDocumentTest {
|
|||||||
protected final CompoundDocument createTestDocument() throws IOException {
|
protected final CompoundDocument createTestDocument() throws IOException {
|
||||||
URL input = getClass().getResource(SAMPLE_DATA);
|
URL input = getClass().getResource(SAMPLE_DATA);
|
||||||
|
|
||||||
assertNotNull("Missing test resource!", input);
|
assertNotNull(input, "Missing test resource!");
|
||||||
assertEquals("Test resource not a file:// resource", "file", input.getProtocol());
|
assertEquals( "file", input.getProtocol(), "Test resource not a file:// resource");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new CompoundDocument(new File(input.toURI()));
|
return new CompoundDocument(new File(input.toURI()));
|
||||||
@@ -103,7 +103,7 @@ public class CompoundDocumentTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = UnsupportedOperationException.class)
|
@Test
|
||||||
public void testChildEntriesUnmodifiable() throws IOException {
|
public void testChildEntriesUnmodifiable() throws IOException {
|
||||||
try (CompoundDocument document = createTestDocument()) {
|
try (CompoundDocument document = createTestDocument()) {
|
||||||
Entry root = document.getRootEntry();
|
Entry root = document.getRootEntry();
|
||||||
@@ -111,9 +111,10 @@ public class CompoundDocumentTest {
|
|||||||
assertNotNull(root);
|
assertNotNull(root);
|
||||||
|
|
||||||
SortedSet<Entry> children = root.getChildEntries();
|
SortedSet<Entry> children = root.getChildEntries();
|
||||||
|
assertThrows(UnsupportedOperationException.class, () -> {
|
||||||
// Should not be allowed, as it modifies the internal structure
|
// Should not be allowed, as it modifies the internal structure
|
||||||
children.remove(children.first());
|
children.remove(children.first());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +129,7 @@ public class CompoundDocumentTest {
|
|||||||
Entry catalog = root.getChildEntry("Catalog");
|
Entry catalog = root.getChildEntry("Catalog");
|
||||||
|
|
||||||
assertNotNull(catalog);
|
assertNotNull(catalog);
|
||||||
assertNotNull("Input stream may not be null", catalog.getInputStream());
|
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +137,7 @@ public class CompoundDocumentTest {
|
|||||||
public void testReadCatalogInputStream() throws IOException {
|
public void testReadCatalogInputStream() throws IOException {
|
||||||
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
||||||
|
|
||||||
assertNotNull("Missing test resource!", input);
|
assertNotNull(input, "Missing test resource!");
|
||||||
|
|
||||||
CompoundDocument document = new CompoundDocument(input);
|
CompoundDocument document = new CompoundDocument(input);
|
||||||
Entry root = document.getRootEntry();
|
Entry root = document.getRootEntry();
|
||||||
@@ -145,14 +146,14 @@ public class CompoundDocumentTest {
|
|||||||
|
|
||||||
Entry catalog = root.getChildEntry("Catalog");
|
Entry catalog = root.getChildEntry("Catalog");
|
||||||
assertNotNull(catalog);
|
assertNotNull(catalog);
|
||||||
assertNotNull("Input stream may not be null", catalog.getInputStream());
|
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadCatalogSeekableStream() throws IOException {
|
public void testReadCatalogSeekableStream() throws IOException {
|
||||||
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
||||||
|
|
||||||
assertNotNull("Missing test resource!", input);
|
assertNotNull(input, "Missing test resource!");
|
||||||
|
|
||||||
CompoundDocument document = new CompoundDocument(new MemoryCacheSeekableStream(input));
|
CompoundDocument document = new CompoundDocument(new MemoryCacheSeekableStream(input));
|
||||||
Entry root = document.getRootEntry();
|
Entry root = document.getRootEntry();
|
||||||
@@ -161,14 +162,14 @@ public class CompoundDocumentTest {
|
|||||||
|
|
||||||
Entry catalog = root.getChildEntry("Catalog");
|
Entry catalog = root.getChildEntry("Catalog");
|
||||||
assertNotNull(catalog);
|
assertNotNull(catalog);
|
||||||
assertNotNull("Input stream may not be null", catalog.getInputStream());
|
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadCatalogImageInputStream() throws IOException {
|
public void testReadCatalogImageInputStream() throws IOException {
|
||||||
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
InputStream input = getClass().getResourceAsStream(SAMPLE_DATA);
|
||||||
|
|
||||||
assertNotNull("Missing test resource!", input);
|
assertNotNull(input, "Missing test resource!");
|
||||||
|
|
||||||
MemoryCacheImageInputStream stream = new MemoryCacheImageInputStream(input);
|
MemoryCacheImageInputStream stream = new MemoryCacheImageInputStream(input);
|
||||||
stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
||||||
@@ -183,6 +184,6 @@ public class CompoundDocumentTest {
|
|||||||
Entry catalog = root.getChildEntry("Catalog");
|
Entry catalog = root.getChildEntry("Catalog");
|
||||||
|
|
||||||
assertNotNull(catalog);
|
assertNotNull(catalog);
|
||||||
assertNotNull("Input stream may not be null", catalog.getInputStream());
|
assertNotNull(catalog.getInputStream(), "Input stream may not be null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@
|
|||||||
package com.twelvemonkeys.io.ole2;
|
package com.twelvemonkeys.io.ole2;
|
||||||
|
|
||||||
import com.twelvemonkeys.io.*;
|
import com.twelvemonkeys.io.*;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -33,7 +33,6 @@ package com.twelvemonkeys.io.ole2;
|
|||||||
import com.twelvemonkeys.io.InputStreamAbstractTest;
|
import com.twelvemonkeys.io.InputStreamAbstractTest;
|
||||||
import com.twelvemonkeys.io.LittleEndianDataOutputStream;
|
import com.twelvemonkeys.io.LittleEndianDataOutputStream;
|
||||||
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
|
import com.twelvemonkeys.io.MemoryCacheSeekableStream;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@@ -42,7 +41,8 @@ import java.io.InputStream;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CompoundDocument_StreamTestCase
|
* CompoundDocument_StreamTestCase
|
||||||
@@ -165,8 +165,8 @@ public class CompoundDocument_StreamTest extends InputStreamAbstractTest {
|
|||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertFalse("Short stream", count < 32);
|
assertFalse(count < 32, "Short stream");
|
||||||
assertFalse("Stream overrun", count > 32);
|
assertFalse(count > 32, "Stream overrun");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -30,9 +30,8 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.net;
|
package com.twelvemonkeys.net;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTPUtilTest
|
* HTTPUtilTest
|
||||||
|
|||||||
@@ -4,17 +4,25 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<version>3.7.0</version>
|
<version>3.13.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>common-lang</artifactId>
|
<artifactId>common-lang</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>TwelveMonkeys :: Common :: Language support</name>
|
<name>TwelveMonkeys :: Common :: Language support</name>
|
||||||
<description>
|
<description>
|
||||||
The TwelveMonkeys Common Language support
|
TwelveMonkeys Common language support classes.
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.jpms.module.name>com.twelvemonkeys.common.lang</project.jpms.module.name>
|
<project.jpms.module.name>com.twelvemonkeys.common.lang</project.jpms.module.name>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -770,6 +770,7 @@ public final class StringUtil {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*public*/
|
/*public*/
|
||||||
|
@Deprecated
|
||||||
static String formatNumber(long pNum, int pLen) throws IllegalArgumentException {
|
static String formatNumber(long pNum, int pLen) throws IllegalArgumentException {
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
|
|
||||||
@@ -903,7 +904,7 @@ public final class StringUtil {
|
|||||||
}
|
}
|
||||||
catch (ParseException pe) {
|
catch (ParseException pe) {
|
||||||
// Wrap in RuntimeException
|
// Wrap in RuntimeException
|
||||||
throw new IllegalArgumentException(pe.getMessage());
|
throw new IllegalArgumentException(pe.getMessage() + " at pos " + pe.getErrorOffset());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1464,6 +1465,7 @@ public final class StringUtil {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*public*/
|
/*public*/
|
||||||
|
@Deprecated
|
||||||
static String removeSubstring(final String pSource, final char pBeginBoundaryChar, final char pEndBoundaryChar, final int pOffset) {
|
static String removeSubstring(final String pSource, final char pBeginBoundaryChar, final char pEndBoundaryChar, final int pOffset) {
|
||||||
StringBuilder filteredString = new StringBuilder();
|
StringBuilder filteredString = new StringBuilder();
|
||||||
boolean insideDemarcatedArea = false;
|
boolean insideDemarcatedArea = false;
|
||||||
@@ -1763,12 +1765,11 @@ public final class StringUtil {
|
|||||||
* expression.
|
* expression.
|
||||||
* <p>
|
* <p>
|
||||||
* An invocation of this method of the form
|
* An invocation of this method of the form
|
||||||
* <tt>matches(<i>str</i>, <i>regex</i>)</tt> yields exactly the
|
* {@code matches(str, regex)} yields exactly the
|
||||||
* same result as the expression
|
* same result as the expression
|
||||||
* </p>
|
* </p>
|
||||||
* <blockquote><tt> {@link Pattern}.
|
* <blockquote>{@link Pattern}.
|
||||||
* {@link Pattern#matches(String, CharSequence) matches}
|
* {@link Pattern#matches(String, CharSequence) matches(regex, str)}</blockquote>
|
||||||
* (<i>regex</i>, <i>str</i>)</tt></blockquote>
|
|
||||||
*
|
*
|
||||||
* @param pString the string
|
* @param pString the string
|
||||||
* @param pRegex the regular expression to which this string is to be matched
|
* @param pRegex the regular expression to which this string is to be matched
|
||||||
@@ -1787,16 +1788,14 @@ public final class StringUtil {
|
|||||||
* regular expression with the given pReplacement.
|
* regular expression with the given pReplacement.
|
||||||
* <p>
|
* <p>
|
||||||
* An invocation of this method of the form
|
* An invocation of this method of the form
|
||||||
* <tt>
|
* {@code replaceFirst(str, regex, repl)}
|
||||||
* replaceFirst(<i>str</i>, <i>regex</i>, <i>repl</i>)
|
|
||||||
* </tt>
|
|
||||||
* yields exactly the same result as the expression:
|
* yields exactly the same result as the expression:
|
||||||
* </p>
|
* </p>
|
||||||
* <blockquote><tt>
|
* <blockquote>
|
||||||
* {@link Pattern}.{@link Pattern#compile(String) compile}(<i>regex</i>).
|
* {@link Pattern#compile(String) Pattern.compile(regex)}
|
||||||
* {@link Pattern#matcher matcher}(<i>str</i>).
|
* {@link Pattern#matcher .matcher(str)}
|
||||||
* {@link java.util.regex.Matcher#replaceFirst replaceFirst}(<i>repl</i>)
|
* {@link java.util.regex.Matcher#replaceFirst .replaceFirst(repl)}
|
||||||
* </tt></blockquote>
|
* </blockquote>
|
||||||
*
|
*
|
||||||
* @param pString the string
|
* @param pString the string
|
||||||
* @param pRegex the regular expression to which this string is to be matched
|
* @param pRegex the regular expression to which this string is to be matched
|
||||||
@@ -1815,14 +1814,14 @@ public final class StringUtil {
|
|||||||
* regular expression with the given pReplacement.
|
* regular expression with the given pReplacement.
|
||||||
* <p>
|
* <p>
|
||||||
* An invocation of this method of the form
|
* An invocation of this method of the form
|
||||||
* <tt>replaceAll(<i>str</i>, <i>pRegex</i>, <i>repl</i>)</tt>
|
* {@code replaceAll(str, pRegex, repl)}
|
||||||
* yields exactly the same result as the expression
|
* yields exactly the same result as the expression
|
||||||
* </p>
|
* </p>
|
||||||
* <blockquote><tt>
|
* <blockquote>
|
||||||
* {@link Pattern}.{@link Pattern#compile(String) compile}(<i>pRegex</i>).
|
* {@link Pattern#compile(String) Pattern.compile(pRegex)}
|
||||||
* {@link Pattern#matcher matcher}(<i>str</i>{@code ).
|
* {@link Pattern#matcher .matcher(str)}
|
||||||
* {@link java.util.regex.Matcher#replaceAll replaceAll}(}<i>repl</i>{@code )}
|
* {@link java.util.regex.Matcher#replaceAll .replaceAll(repl)}
|
||||||
* </tt></blockquote>
|
* </blockquote>
|
||||||
*
|
*
|
||||||
* @param pString the string
|
* @param pString the string
|
||||||
* @param pRegex the regular expression to which this string is to be matched
|
* @param pRegex the regular expression to which this string is to be matched
|
||||||
@@ -1860,12 +1859,12 @@ public final class StringUtil {
|
|||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* An invocation of this method of the form
|
* An invocation of this method of the form
|
||||||
* <tt>split(<i>str</i>, <i>regex</i>, <i>n</i>)</tt>
|
* {@code split(str, regex, n)}
|
||||||
* yields the same result as the expression:
|
* yields the same result as the expression:
|
||||||
* </p>
|
* </p>
|
||||||
* <blockquote>{@link Pattern}.
|
* <blockquote>{@link Pattern}.
|
||||||
* {@link Pattern#compile(String) compile}<tt>(<i>regex</i>).
|
* {@link Pattern#compile(String) compile(regex)}.
|
||||||
* {@link Pattern#split(CharSequence,int) split}(<i>str</i>, <i>n</i>)</tt>
|
* {@link Pattern#split(CharSequence,int) split(str, n)}
|
||||||
* </blockquote>
|
* </blockquote>
|
||||||
*
|
*
|
||||||
* @param pString the string
|
* @param pString the string
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ public class Time {
|
|||||||
* @see #parseTime(String)
|
* @see #parseTime(String)
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public String toString(String pFormatStr) {
|
public String toString(String pFormatStr) {
|
||||||
TimeFormat tf = new TimeFormat(pFormatStr);
|
TimeFormat tf = new TimeFormat(pFormatStr);
|
||||||
|
|
||||||
@@ -174,6 +175,7 @@ public class Time {
|
|||||||
* @see #toString(String)
|
* @see #toString(String)
|
||||||
* @deprecated
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static Time parseTime(String pStr) {
|
public static Time parseTime(String pStr) {
|
||||||
TimeFormat tf = TimeFormat.getInstance();
|
TimeFormat tf = TimeFormat.getInstance();
|
||||||
|
|
||||||
|
|||||||
+1
@@ -111,6 +111,7 @@ import java.io.PrintStream;
|
|||||||
* @author <a href="mailto:eirik.torske@iconmedialab.no">Eirik Torske</a>
|
* @author <a href="mailto:eirik.torske@iconmedialab.no">Eirik Torske</a>
|
||||||
* @deprecated Will probably be removed in the near future
|
* @deprecated Will probably be removed in the near future
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class WildcardStringParser {
|
public class WildcardStringParser {
|
||||||
// TODO: Get rid of this class
|
// TODO: Get rid of this class
|
||||||
|
|
||||||
|
|||||||
@@ -30,14 +30,13 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.lang;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BeanUtilTestCase
|
* BeanUtilTestCase
|
||||||
@@ -161,10 +160,8 @@ public class BeanUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertNotNull(bean.getAmbiguous());
|
assertNotNull(bean.getAmbiguous());
|
||||||
assertEquals("String converted rather than invoking setAmbiguous(String), ordering not predictable",
|
assertEquals("one", bean.getAmbiguous(), "String converted rather than invoking setAmbiguous(String), ordering not predictable");
|
||||||
"one", bean.getAmbiguous());
|
assertSame(value, bean.getAmbiguous(), "String converted rather than invoking setAmbiguous(String), ordering not predictable");
|
||||||
assertSame("String converted rather than invoking setAmbiguous(String), ordering not predictable",
|
|
||||||
value, bean.getAmbiguous());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -184,10 +181,10 @@ public class BeanUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertNotNull(bean.getAmbiguous());
|
assertNotNull(bean.getAmbiguous());
|
||||||
assertEquals("Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable",
|
assertEquals(2, bean.getAmbiguous(),
|
||||||
2, bean.getAmbiguous());
|
"Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable");
|
||||||
assertSame("Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable",
|
assertSame(value, bean.getAmbiguous(),
|
||||||
value, bean.getAmbiguous());
|
"Integer converted rather than invoking setAmbiguous(Integer), ordering not predictable");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -207,10 +204,8 @@ public class BeanUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertNotNull(bean.getAmbiguous());
|
assertNotNull(bean.getAmbiguous());
|
||||||
assertEquals("Object converted rather than invoking setAmbiguous(Object), ordering not predictable",
|
assertEquals(value.getClass(), bean.getAmbiguous().getClass(), "Object converted rather than invoking setAmbiguous(Object), ordering not predictable");
|
||||||
value.getClass(), bean.getAmbiguous().getClass());
|
assertSame(value, bean.getAmbiguous(), "Object converted rather than invoking setAmbiguous(Object), ordering not predictable");
|
||||||
assertSame("Object converted rather than invoking setAmbiguous(Object), ordering not predictable",
|
|
||||||
value, bean.getAmbiguous());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TestBean {
|
static class TestBean {
|
||||||
|
|||||||
@@ -30,16 +30,16 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.lang;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DateUtilTest
|
* DateUtilTest
|
||||||
@@ -48,12 +48,9 @@ import static org.junit.Assert.assertEquals;
|
|||||||
* @author last modified by $Author: haraldk$
|
* @author last modified by $Author: haraldk$
|
||||||
* @version $Id: DateUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
* @version $Id: DateUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
||||||
*/
|
*/
|
||||||
@RunWith(Parameterized.class)
|
|
||||||
public class DateUtilTest {
|
public class DateUtilTest {
|
||||||
|
|
||||||
private final TimeZone timeZone;
|
|
||||||
|
|
||||||
@Parameterized.Parameters
|
|
||||||
public static List<Object[]> timeZones() {
|
public static List<Object[]> timeZones() {
|
||||||
return Arrays.asList(new Object[][] {
|
return Arrays.asList(new Object[][] {
|
||||||
{TimeZone.getTimeZone("UTC")},
|
{TimeZone.getTimeZone("UTC")},
|
||||||
@@ -62,10 +59,6 @@ public class DateUtilTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateUtilTest(final TimeZone timeZone) {
|
|
||||||
this.timeZone = timeZone;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Calendar getCalendar(long time) {
|
private Calendar getCalendar(long time) {
|
||||||
return getCalendar(time, TimeZone.getDefault());
|
return getCalendar(time, TimeZone.getDefault());
|
||||||
}
|
}
|
||||||
@@ -101,8 +94,9 @@ public class DateUtilTest {
|
|||||||
assertEquals(0, calendar.get(Calendar.MINUTE));
|
assertEquals(0, calendar.get(Calendar.MINUTE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testRoundToHourTZ() {
|
@MethodSource("timeZones")
|
||||||
|
public void testRoundToHourTZ(TimeZone timeZone) {
|
||||||
Calendar calendar = getCalendar(DateUtil.roundToHour(System.currentTimeMillis(), timeZone), timeZone);
|
Calendar calendar = getCalendar(DateUtil.roundToHour(System.currentTimeMillis(), timeZone), timeZone);
|
||||||
|
|
||||||
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
||||||
@@ -120,8 +114,9 @@ public class DateUtilTest {
|
|||||||
assertEquals(0, calendar.get(Calendar.HOUR_OF_DAY));
|
assertEquals(0, calendar.get(Calendar.HOUR_OF_DAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void testRoundToDayTZ() {
|
@MethodSource("timeZones")
|
||||||
|
public void testRoundToDayTZ(TimeZone timeZone) {
|
||||||
Calendar calendar = getCalendar(DateUtil.roundToDay(System.currentTimeMillis(), timeZone), timeZone);
|
Calendar calendar = getCalendar(DateUtil.roundToDay(System.currentTimeMillis(), timeZone), timeZone);
|
||||||
|
|
||||||
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
||||||
|
|||||||
@@ -30,12 +30,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.lang;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AbstractObjectTestCase
|
* AbstractObjectTestCase
|
||||||
@@ -79,10 +78,10 @@ public abstract class ObjectAbstractTest {
|
|||||||
|
|
||||||
Class cl = obj.getClass();
|
Class cl = obj.getClass();
|
||||||
if (isEqualsOverriden(cl)) {
|
if (isEqualsOverriden(cl)) {
|
||||||
assertTrue("Class " + cl.getName() + " implements equals but not hashCode", isHashCodeOverriden(cl));
|
assertTrue(isHashCodeOverriden(cl), "Class " + cl.getName() + " implements equals but not hashCode");
|
||||||
}
|
}
|
||||||
else if (isHashCodeOverriden(cl)) {
|
else if (isHashCodeOverriden(cl)) {
|
||||||
assertTrue("Class " + cl.getName() + " implements hashCode but not equals", isEqualsOverriden(cl));
|
assertTrue(isEqualsOverriden(cl), "Class " + cl.getName() + " implements hashCode but not equals");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -107,7 +106,7 @@ public abstract class ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testObjectEqualsSelf() {
|
public void testObjectEqualsSelf() {
|
||||||
Object obj = makeObject();
|
Object obj = makeObject();
|
||||||
assertEquals("An Object should equal itself", obj, obj);
|
assertEquals(obj, obj, "An Object should equal itself");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -115,32 +114,26 @@ public abstract class ObjectAbstractTest {
|
|||||||
Object obj = makeObject();
|
Object obj = makeObject();
|
||||||
// NOTE: Makes sure this doesn't throw NPE either
|
// NOTE: Makes sure this doesn't throw NPE either
|
||||||
//noinspection ObjectEqualsNull
|
//noinspection ObjectEqualsNull
|
||||||
assertFalse("An object should never equal null", obj.equals(null));
|
assertFalse(obj.equals(null), "An object should never equal null");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testObjectHashCodeEqualsSelfHashCode() {
|
public void testObjectHashCodeEqualsSelfHashCode() {
|
||||||
Object obj = makeObject();
|
Object obj = makeObject();
|
||||||
assertEquals("hashCode should be repeatable", obj.hashCode(), obj.hashCode());
|
assertEquals(obj.hashCode(), obj.hashCode(), "hashCode should be repeatable");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testObjectHashCodeEqualsContract() {
|
public void testObjectHashCodeEqualsContract() {
|
||||||
Object obj1 = makeObject();
|
Object obj1 = makeObject();
|
||||||
if (obj1.equals(obj1)) {
|
if (obj1.equals(obj1)) {
|
||||||
assertEquals(
|
assertEquals(obj1.hashCode(), obj1.hashCode(), "[1] When two objects are equal, their hashCodes should be also.");
|
||||||
"[1] When two objects are equal, their hashCodes should be also.",
|
|
||||||
obj1.hashCode(), obj1.hashCode());
|
|
||||||
}
|
}
|
||||||
// TODO: Make sure we create at least one equal object, and one different object
|
// TODO: Make sure we create at least one equal object, and one different object
|
||||||
Object obj2 = makeObject();
|
Object obj2 = makeObject();
|
||||||
if (obj1.equals(obj2)) {
|
if (obj1.equals(obj2)) {
|
||||||
assertEquals(
|
assertEquals(obj1.hashCode(), obj2.hashCode(), "[2] When two objects are equal, their hashCodes should be also.");
|
||||||
"[2] When two objects are equal, their hashCodes should be also.",
|
assertTrue(obj2.equals(obj1), "When obj1.equals(obj2) is true, then obj2.equals(obj1) should also be true");
|
||||||
obj1.hashCode(), obj2.hashCode());
|
|
||||||
assertTrue(
|
|
||||||
"When obj1.equals(obj2) is true, then obj2.equals(obj1) should also be true",
|
|
||||||
obj2.equals(obj1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,14 +162,14 @@ public abstract class ObjectAbstractTest {
|
|||||||
|
|
||||||
Object cloned = clone.invoke(obj);
|
Object cloned = clone.invoke(obj);
|
||||||
|
|
||||||
assertNotNull("Cloned object should never be null", cloned);
|
assertNotNull(cloned, "Cloned object should never be null");
|
||||||
|
|
||||||
// TODO: This can only be asserted if equals() test is based on
|
// TODO: This can only be asserted if equals() test is based on
|
||||||
// value equality, not reference (identity) equality
|
// value equality, not reference (identity) equality
|
||||||
// Maybe it's possible to do a reflective introspection of
|
// Maybe it's possible to do a reflective introspection of
|
||||||
// the objects fields?
|
// the objects fields?
|
||||||
if (isHashCodeOverriden(cl)) {
|
if (isHashCodeOverriden(cl)) {
|
||||||
assertEquals("Cloned object not equal", obj, cloned);
|
assertEquals(obj, cloned, "Cloned object not equal");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,7 +228,7 @@ public abstract class ObjectAbstractTest {
|
|||||||
// Maybe it's possible to do a reflective introspection of
|
// Maybe it's possible to do a reflective introspection of
|
||||||
// the objects fields?
|
// the objects fields?
|
||||||
if (isEqualsOverriden(obj.getClass())) {
|
if (isEqualsOverriden(obj.getClass())) {
|
||||||
assertEquals("obj != deserialize(serialize(obj))", obj, dest);
|
assertEquals(obj, dest, "obj != deserialize(serialize(obj))");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,13 +30,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.lang;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PlatformTest
|
* PlatformTest
|
||||||
@@ -121,7 +119,7 @@ public class PlatformTest {
|
|||||||
assertEquals(Platform.Architecture.X86, platform.getArchitecture());
|
assertEquals(Platform.Architecture.X86, platform.getArchitecture());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("Known issue, needs resolve")
|
@Disabled("Known issue, needs resolve")
|
||||||
@Test
|
@Test
|
||||||
public void testCreateWindows686() {
|
public void testCreateWindows686() {
|
||||||
Platform platform = new Platform(createProperties("Windows", "5.1", "686"));
|
Platform platform = new Platform(createProperties("Windows", "5.1", "686"));
|
||||||
@@ -129,7 +127,7 @@ public class PlatformTest {
|
|||||||
assertEquals(Platform.Architecture.X86, platform.getArchitecture());
|
assertEquals(Platform.Architecture.X86, platform.getArchitecture());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("Known issue, needs resolve")
|
@Disabled("Known issue, needs resolve")
|
||||||
@Test
|
@Test
|
||||||
public void testCreateLinuxX86() {
|
public void testCreateLinuxX86() {
|
||||||
Platform platform = new Platform(createProperties("Linux", "3.0.18", "x86"));
|
Platform platform = new Platform(createProperties("Linux", "3.0.18", "x86"));
|
||||||
|
|||||||
@@ -30,8 +30,6 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.lang;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
@@ -41,8 +39,8 @@ import java.util.Date;
|
|||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
/**
|
/**
|
||||||
* StringUtilTestCase
|
* StringUtilTestCase
|
||||||
*
|
*
|
||||||
@@ -165,10 +163,10 @@ public class StringUtilTest {
|
|||||||
// Test all alpha-chars
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if (TEST_STRING.indexOf(i) < 0) {
|
if (TEST_STRING.indexOf(i) < 0) {
|
||||||
assertFalse(TEST_STRING + " seems to contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), StringUtil.contains(TEST_STRING, i));
|
assertFalse(StringUtil.contains(TEST_STRING, i), TEST_STRING + " seems to contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), StringUtil.contains(TEST_STRING, i));
|
assertTrue(StringUtil.contains(TEST_STRING, i), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,10 +197,10 @@ public class StringUtilTest {
|
|||||||
// Test all alpha-chars
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
||||||
assertFalse(TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))), StringUtil.containsIgnoreCase(TEST_STRING, i));
|
assertFalse(StringUtil.containsIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), StringUtil.containsIgnoreCase(TEST_STRING, i));
|
assertTrue(StringUtil.containsIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,10 +348,10 @@ public class StringUtilTest {
|
|||||||
// Test all alpha-chars
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
||||||
assertEquals(TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))), -1, StringUtil.indexOfIgnoreCase(TEST_STRING, i));
|
assertEquals(-1, StringUtil.indexOfIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), 0 <= StringUtil.indexOfIgnoreCase(TEST_STRING, i));
|
assertTrue(0 <= StringUtil.indexOfIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -385,10 +383,10 @@ public class StringUtilTest {
|
|||||||
// Test all alpha-chars
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
||||||
assertEquals(TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))), -1, StringUtil.indexOfIgnoreCase(TEST_STRING, i, 0));
|
assertEquals(-1, StringUtil.indexOfIgnoreCase(TEST_STRING, i, 0), TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), 0 <= StringUtil.indexOfIgnoreCase(TEST_STRING, i, 0));
|
assertTrue(0 <= StringUtil.indexOfIgnoreCase(TEST_STRING, i, 0), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -420,10 +418,10 @@ public class StringUtilTest {
|
|||||||
// Test all alpha-chars
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
||||||
assertEquals(TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))), -1, StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i));
|
assertEquals(-1, StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), 0 <= StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i));
|
assertTrue(0 <= StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,10 +453,10 @@ public class StringUtilTest {
|
|||||||
// Test all alpha-chars
|
// Test all alpha-chars
|
||||||
for (int i = 'a'; i < 'z'; i++) {
|
for (int i = 'a'; i < 'z'; i++) {
|
||||||
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
if ((TEST_STRING.indexOf(i) < 0) && (TEST_STRING.indexOf(Character.toUpperCase((char) i)) < 0)) {
|
||||||
assertEquals(TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))), -1, StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i, TEST_STRING.length()));
|
assertEquals(-1, StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i, TEST_STRING.length()), TEST_STRING + " seems to contain '" + (char) i + "', at index " + Math.max(TEST_STRING.indexOf(i), TEST_STRING.indexOf(Character.toUpperCase((char) i))));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertTrue(TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i), 0 <= StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i, TEST_STRING.length()));
|
assertTrue(0 <= StringUtil.lastIndexOfIgnoreCase(TEST_STRING, i, TEST_STRING.length()), TEST_STRING + " seems to not contain '" + (char) i + "', at index " + TEST_STRING.indexOf(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -593,8 +591,8 @@ public class StringUtilTest {
|
|||||||
cal.clear();
|
cal.clear();
|
||||||
cal.set(Calendar.HOUR, 1);
|
cal.set(Calendar.HOUR, 1);
|
||||||
cal.set(Calendar.MINUTE, 2);
|
cal.set(Calendar.MINUTE, 2);
|
||||||
date = StringUtil.toDate("1:02 am",
|
format = new SimpleDateFormat("HH:mm");
|
||||||
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US));
|
date = StringUtil.toDate("1:02", format);
|
||||||
assertNotNull(date);
|
assertNotNull(date);
|
||||||
assertEquals(cal.getTime(), date);
|
assertEquals(cal.getTime(), date);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.lang;
|
package com.twelvemonkeys.lang;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SystemUtilTest
|
* SystemUtilTest
|
||||||
@@ -39,6 +39,6 @@ import org.junit.Ignore;
|
|||||||
* @author last modified by $Author: haraldk$
|
* @author last modified by $Author: haraldk$
|
||||||
* @version $Id: SystemUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
* @version $Id: SystemUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
||||||
*/
|
*/
|
||||||
@Ignore
|
@Disabled
|
||||||
public class SystemUtilTest {
|
public class SystemUtilTest {
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+91
-137
@@ -45,12 +45,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract test class for {@link java.util.Collection} methods and contracts.
|
* Abstract test class for {@link java.util.Collection} methods and contracts.
|
||||||
@@ -251,11 +250,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
*/
|
*/
|
||||||
public void verifyAll() {
|
public void verifyAll() {
|
||||||
int confirmedSize = confirmed.size();
|
int confirmedSize = confirmed.size();
|
||||||
assertEquals("Collection size should match confirmed collection's",
|
assertEquals(confirmedSize, collection.size(), "Collection size should match confirmed collection's");
|
||||||
confirmedSize, collection.size());
|
assertEquals(confirmed.isEmpty(), collection.isEmpty(), "Collection isEmpty() result should match confirmed collection's");
|
||||||
assertEquals("Collection isEmpty() result should match confirmed " +
|
|
||||||
" collection's",
|
|
||||||
confirmed.isEmpty(), collection.isEmpty());
|
|
||||||
|
|
||||||
// verify the collections are the same by attempting to match each
|
// verify the collections are the same by attempting to match each
|
||||||
// object in the collection and confirmed collection. To account for
|
// object in the collection and confirmed collection. To account for
|
||||||
@@ -521,8 +517,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
boolean r = collection.add(elements[i]);
|
boolean r = collection.add(elements[i]);
|
||||||
confirmed.add(elements[i]);
|
confirmed.add(elements[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertTrue("Empty collection changed after add", r);
|
assertTrue(r, "Empty collection changed after add");
|
||||||
assertEquals("Collection size is 1 after first add", 1, collection.size());
|
assertEquals(1, collection.size(), "Collection size is 1 after first add");
|
||||||
}
|
}
|
||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
@@ -532,10 +528,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
confirmed.add(elements[i]);
|
confirmed.add(elements[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
if (r) size++;
|
if (r) size++;
|
||||||
assertEquals("Collection size should grow after add",
|
assertEquals(size, collection.size(), "Collection size should grow after add");
|
||||||
size, collection.size());
|
assertTrue(collection.contains(elements[i]), "Collection should contain added element");
|
||||||
assertTrue("Collection should contain added element",
|
|
||||||
collection.contains(elements[i]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,10 +546,9 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
boolean r = collection.addAll(Arrays.asList(elements));
|
boolean r = collection.addAll(Arrays.asList(elements));
|
||||||
confirmed.addAll(Arrays.asList(elements));
|
confirmed.addAll(Arrays.asList(elements));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertTrue("Empty collection should change after addAll", r);
|
assertTrue(r, "Empty collection should change after addAll");
|
||||||
for (int i = 0; i < elements.length; i++) {
|
for (int i = 0; i < elements.length; i++) {
|
||||||
assertTrue("Collection should contain added element",
|
assertTrue(collection.contains(elements[i]), "Collection should contain added element");
|
||||||
collection.contains(elements[i]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
@@ -564,13 +557,11 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
r = collection.addAll(Arrays.asList(elements));
|
r = collection.addAll(Arrays.asList(elements));
|
||||||
confirmed.addAll(Arrays.asList(elements));
|
confirmed.addAll(Arrays.asList(elements));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertTrue("Full collection should change after addAll", r);
|
assertTrue(r, "Full collection should change after addAll");
|
||||||
for (int i = 0; i < elements.length; i++) {
|
for (int i = 0; i < elements.length; i++) {
|
||||||
assertTrue("Full collection should contain added element",
|
assertTrue(collection.contains(elements[i]), "Full collection should contain added element");
|
||||||
collection.contains(elements[i]));
|
|
||||||
}
|
}
|
||||||
assertEquals("Size should increase after addAll",
|
assertEquals(size + elements.length, collection.size(), "Size should increase after addAll");
|
||||||
size + elements.length, collection.size());
|
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
size = collection.size();
|
size = collection.size();
|
||||||
@@ -578,11 +569,9 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
confirmed.addAll(Arrays.asList(getFullElements()));
|
confirmed.addAll(Arrays.asList(getFullElements()));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
if (r) {
|
if (r) {
|
||||||
assertTrue("Size should increase if addAll returns true",
|
assertTrue(size < collection.size(), "Size should increase if addAll returns true");
|
||||||
size < collection.size());
|
|
||||||
} else {
|
} else {
|
||||||
assertEquals("Size should not change if addAll returns false",
|
assertEquals(size, collection.size(), "Size should not change if addAll returns false");
|
||||||
size, collection.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,16 +655,14 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
resetEmpty();
|
resetEmpty();
|
||||||
elements = getFullElements();
|
elements = getFullElements();
|
||||||
for(int i = 0; i < elements.length; i++) {
|
for(int i = 0; i < elements.length; i++) {
|
||||||
assertTrue("Empty collection shouldn't contain element[" + i + "]",
|
assertTrue(!collection.contains(elements[i]), "Empty collection shouldn't contain element[" + i + "]");
|
||||||
!collection.contains(elements[i]));
|
|
||||||
}
|
}
|
||||||
// make sure calls to "contains" don't change anything
|
// make sure calls to "contains" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
elements = getOtherElements();
|
elements = getOtherElements();
|
||||||
for(int i = 0; i < elements.length; i++) {
|
for(int i = 0; i < elements.length; i++) {
|
||||||
assertTrue("Empty collection shouldn't contain element[" + i + "]",
|
assertTrue(!collection.contains(elements[i]), "Empty collection shouldn't contain element[" + i + "]");
|
||||||
!collection.contains(elements[i]));
|
|
||||||
}
|
}
|
||||||
// make sure calls to "contains" don't change anything
|
// make sure calls to "contains" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
@@ -683,8 +670,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
resetFull();
|
resetFull();
|
||||||
elements = getFullElements();
|
elements = getFullElements();
|
||||||
for(int i = 0; i < elements.length; i++) {
|
for(int i = 0; i < elements.length; i++) {
|
||||||
assertTrue("Full collection should contain element[" + i + "]",
|
assertTrue(collection.contains(elements[i]), "Full collection should contain element[" + i + "]");
|
||||||
collection.contains(elements[i]));
|
|
||||||
}
|
}
|
||||||
// make sure calls to "contains" don't change anything
|
// make sure calls to "contains" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
@@ -692,8 +678,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
resetFull();
|
resetFull();
|
||||||
elements = getOtherElements();
|
elements = getOtherElements();
|
||||||
for(int i = 0; i < elements.length; i++) {
|
for(int i = 0; i < elements.length; i++) {
|
||||||
assertTrue("Full collection shouldn't contain element",
|
assertTrue(!collection.contains(elements[i]), "Full collection shouldn't contain element");
|
||||||
!collection.contains(elements[i]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,22 +690,22 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
public void testCollectionContainsAll() {
|
public void testCollectionContainsAll() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
Collection col = new HashSet();
|
Collection col = new HashSet();
|
||||||
assertTrue("Every Collection should contain all elements of an " +
|
assertTrue(collection.containsAll(col),
|
||||||
"empty Collection.", collection.containsAll(col));
|
"Every Collection should contain all elements of an " +
|
||||||
|
"empty Collection.");
|
||||||
col.addAll(Arrays.asList(getOtherElements()));
|
col.addAll(Arrays.asList(getOtherElements()));
|
||||||
assertTrue("Empty Collection shouldn't contain all elements of " +
|
assertTrue(!collection.containsAll(col),
|
||||||
"a non-empty Collection.", !collection.containsAll(col));
|
"Empty Collection shouldn't contain all elements of " +
|
||||||
|
"a non-empty Collection.");
|
||||||
// make sure calls to "containsAll" don't change anything
|
// make sure calls to "containsAll" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("Full collection shouldn't contain other elements",
|
assertTrue(!collection.containsAll(col), "Full collection shouldn't contain other elements");
|
||||||
!collection.containsAll(col));
|
|
||||||
|
|
||||||
col.clear();
|
col.clear();
|
||||||
col.addAll(Arrays.asList(getFullElements()));
|
col.addAll(Arrays.asList(getFullElements()));
|
||||||
assertTrue("Full collection should containAll full elements",
|
assertTrue(collection.containsAll(col), "Full collection should containAll full elements");
|
||||||
collection.containsAll(col));
|
|
||||||
// make sure calls to "containsAll" don't change anything
|
// make sure calls to "containsAll" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
@@ -728,18 +713,17 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
int max = (getFullElements().length == 1 ? 1 :
|
int max = (getFullElements().length == 1 ? 1 :
|
||||||
(getFullElements().length <= 5 ? getFullElements().length - 1 : 5));
|
(getFullElements().length <= 5 ? getFullElements().length - 1 : 5));
|
||||||
col = Arrays.asList(getFullElements()).subList(min, max);
|
col = Arrays.asList(getFullElements()).subList(min, max);
|
||||||
assertTrue("Full collection should containAll partial full " +
|
assertTrue(collection.containsAll(col), "Full collection should containAll partial full " +
|
||||||
"elements", collection.containsAll(col));
|
"elements");
|
||||||
assertTrue("Full collection should containAll itself",
|
assertTrue(collection.containsAll(collection), "Full collection should containAll itself");
|
||||||
collection.containsAll(collection));
|
|
||||||
// make sure calls to "containsAll" don't change anything
|
// make sure calls to "containsAll" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
col = new ArrayList();
|
col = new ArrayList();
|
||||||
col.addAll(Arrays.asList(getFullElements()));
|
col.addAll(Arrays.asList(getFullElements()));
|
||||||
col.addAll(Arrays.asList(getFullElements()));
|
col.addAll(Arrays.asList(getFullElements()));
|
||||||
assertTrue("Full collection should containAll duplicate full " +
|
assertTrue(collection.containsAll(col), "Full collection should containAll duplicate full " +
|
||||||
"elements", collection.containsAll(col));
|
"elements");
|
||||||
|
|
||||||
// make sure calls to "containsAll" don't change anything
|
// make sure calls to "containsAll" don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
@@ -751,14 +735,12 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCollectionIsEmpty() {
|
public void testCollectionIsEmpty() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals("New Collection should be empty.",
|
assertEquals(true, collection.isEmpty(), "New Collection should be empty.");
|
||||||
true, collection.isEmpty());
|
|
||||||
// make sure calls to "isEmpty() don't change anything
|
// make sure calls to "isEmpty() don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertEquals("Full collection shouldn't be empty",
|
assertEquals(false, collection.isEmpty(), "Full collection shouldn't be empty");
|
||||||
false, collection.isEmpty());
|
|
||||||
// make sure calls to "isEmpty() don't change anything
|
// make sure calls to "isEmpty() don't change anything
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -771,8 +753,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
public void testCollectionIterator() {
|
public void testCollectionIterator() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
Iterator it1 = collection.iterator();
|
Iterator it1 = collection.iterator();
|
||||||
assertEquals("Iterator for empty Collection shouldn't have next.",
|
assertEquals(false, it1.hasNext(), "Iterator for empty Collection shouldn't have next.");
|
||||||
false, it1.hasNext());
|
|
||||||
try {
|
try {
|
||||||
it1.next();
|
it1.next();
|
||||||
fail("Iterator at end of Collection should throw " +
|
fail("Iterator at end of Collection should throw " +
|
||||||
@@ -786,18 +767,17 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
resetFull();
|
resetFull();
|
||||||
it1 = collection.iterator();
|
it1 = collection.iterator();
|
||||||
for (int i = 0; i < collection.size(); i++) {
|
for (int i = 0; i < collection.size(); i++) {
|
||||||
assertTrue("Iterator for full collection should haveNext",
|
assertTrue(it1.hasNext(), "Iterator for full collection should haveNext");
|
||||||
it1.hasNext());
|
|
||||||
it1.next();
|
it1.next();
|
||||||
}
|
}
|
||||||
assertTrue("Iterator should be finished", !it1.hasNext());
|
assertTrue(!it1.hasNext(), "Iterator should be finished");
|
||||||
|
|
||||||
ArrayList list = new ArrayList();
|
ArrayList list = new ArrayList();
|
||||||
it1 = collection.iterator();
|
it1 = collection.iterator();
|
||||||
for (int i = 0; i < collection.size(); i++) {
|
for (int i = 0; i < collection.size(); i++) {
|
||||||
Object next = it1.next();
|
Object next = it1.next();
|
||||||
assertTrue("Collection should contain element returned by " +
|
assertTrue(collection.contains(next), "Collection should contain element returned by " +
|
||||||
"its iterator", collection.contains(next));
|
"its iterator");
|
||||||
list.add(next);
|
list.add(next);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -865,11 +845,10 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size--;
|
size--;
|
||||||
assertEquals("Collection should shrink by one after " +
|
assertEquals(size, collection.size(), "Collection should shrink by one after " +
|
||||||
"iterator.remove", size, collection.size());
|
"iterator.remove");
|
||||||
}
|
}
|
||||||
assertTrue("Collection should be empty after iterator purge",
|
assertTrue(collection.isEmpty(), "Collection should be empty after iterator purge");
|
||||||
collection.isEmpty());
|
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
iter = collection.iterator();
|
iter = collection.iterator();
|
||||||
@@ -894,8 +873,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
resetEmpty();
|
resetEmpty();
|
||||||
Object[] elements = getFullElements();
|
Object[] elements = getFullElements();
|
||||||
for (int i = 0; i < elements.length; i++) {
|
for (int i = 0; i < elements.length; i++) {
|
||||||
assertTrue("Shouldn't remove nonexistent element",
|
assertTrue(!collection.remove(elements[i]), "Shouldn't remove nonexistent element");
|
||||||
!collection.remove(elements[i]));
|
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -903,16 +881,14 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
for (int i = 0; i < other.length; i++) {
|
for (int i = 0; i < other.length; i++) {
|
||||||
assertTrue("Shouldn't remove nonexistent other element",
|
assertTrue(!collection.remove(other[i]), "Shouldn't remove nonexistent other element");
|
||||||
!collection.remove(other[i]));
|
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
int size = collection.size();
|
int size = collection.size();
|
||||||
for (int i = 0; i < elements.length; i++) {
|
for (int i = 0; i < elements.length; i++) {
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("Collection should remove extant element: " + elements[i],
|
assertTrue(collection.remove(elements[i]), "Collection should remove extant element: " + elements[i]);
|
||||||
collection.remove(elements[i]));
|
|
||||||
|
|
||||||
// if the elements aren't distinguishable, we can just remove a
|
// if the elements aren't distinguishable, we can just remove a
|
||||||
// matching element from the confirmed collection and verify
|
// matching element from the confirmed collection and verify
|
||||||
@@ -927,8 +903,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals("Collection should shrink after remove",
|
assertEquals(size - 1, collection.size(), "Collection should shrink after remove");
|
||||||
size - 1, collection.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -941,28 +916,28 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
if (!isRemoveSupported()) return;
|
if (!isRemoveSupported()) return;
|
||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue("Emtpy collection removeAll should return false for " +
|
assertTrue(!collection.removeAll(Collections.EMPTY_SET),
|
||||||
"empty input",
|
"Emtpy collection removeAll should return false for " +
|
||||||
!collection.removeAll(Collections.EMPTY_SET));
|
"empty input");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
assertTrue("Emtpy collection removeAll should return false for " +
|
assertTrue(!collection.removeAll(new ArrayList(collection)),
|
||||||
"nonempty input",
|
"Emtpy collection removeAll should return false for " +
|
||||||
!collection.removeAll(new ArrayList(collection)));
|
"nonempty input");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("Full collection removeAll should return false for " +
|
assertTrue(!collection.removeAll(Collections.EMPTY_SET),
|
||||||
"empty input",
|
"Full collection removeAll should return false for " +
|
||||||
!collection.removeAll(Collections.EMPTY_SET));
|
"empty input");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
assertTrue("Full collection removeAll should return false for other elements",
|
assertTrue(!collection.removeAll(Arrays.asList(getOtherElements())),
|
||||||
!collection.removeAll(Arrays.asList(getOtherElements())));
|
"Full collection removeAll should return false for other elements");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
assertTrue("Full collection removeAll should return true for full elements",
|
assertTrue(collection.removeAll(new HashSet(collection)),
|
||||||
collection.removeAll(new HashSet(collection)));
|
"Full collection removeAll should return true for full elements");
|
||||||
confirmed.removeAll(new HashSet(confirmed));
|
confirmed.removeAll(new HashSet(confirmed));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
@@ -972,17 +947,14 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
int max = (getFullElements().length == 1 ? 1 :
|
int max = (getFullElements().length == 1 ? 1 :
|
||||||
(getFullElements().length <= 5 ? getFullElements().length - 1 : 5));
|
(getFullElements().length <= 5 ? getFullElements().length - 1 : 5));
|
||||||
Collection all = Arrays.asList(getFullElements()).subList(min, max);
|
Collection all = Arrays.asList(getFullElements()).subList(min, max);
|
||||||
assertTrue("Full collection removeAll should work",
|
assertTrue(collection.removeAll(all), "Full collection removeAll should work");
|
||||||
collection.removeAll(all));
|
|
||||||
confirmed.removeAll(all);
|
confirmed.removeAll(all);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
assertTrue("Collection should shrink after removeAll",
|
assertTrue(collection.size() < size, "Collection should shrink after removeAll");
|
||||||
collection.size() < size);
|
|
||||||
Iterator iter = all.iterator();
|
Iterator iter = all.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
assertTrue("Collection shouldn't contain removed element",
|
assertTrue(!collection.contains(iter.next()), "Collection shouldn't contain removed element");
|
||||||
!collection.contains(iter.next()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -998,59 +970,51 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
List elements = Arrays.asList(getFullElements());
|
List elements = Arrays.asList(getFullElements());
|
||||||
List other = Arrays.asList(getOtherElements());
|
List other = Arrays.asList(getOtherElements());
|
||||||
|
|
||||||
assertTrue("Empty retainAll() should return false",
|
assertTrue(!collection.retainAll(Collections.EMPTY_SET), "Empty retainAll() should return false");
|
||||||
!collection.retainAll(Collections.EMPTY_SET));
|
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
assertTrue("Empty retainAll() should return false",
|
assertTrue(!collection.retainAll(elements), "Empty retainAll() should return false");
|
||||||
!collection.retainAll(elements));
|
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("Collection should change from retainAll empty",
|
assertTrue(collection.retainAll(Collections.EMPTY_SET), "Collection should change from retainAll empty");
|
||||||
collection.retainAll(Collections.EMPTY_SET));
|
|
||||||
confirmed.retainAll(Collections.EMPTY_SET);
|
confirmed.retainAll(Collections.EMPTY_SET);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("Collection changed from retainAll other",
|
assertTrue(collection.retainAll(other), "Collection changed from retainAll other");
|
||||||
collection.retainAll(other));
|
|
||||||
confirmed.retainAll(other);
|
confirmed.retainAll(other);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
int size = collection.size();
|
int size = collection.size();
|
||||||
assertTrue("Collection shouldn't change from retainAll elements",
|
assertTrue(!collection.retainAll(elements), "Collection shouldn't change from retainAll elements");
|
||||||
!collection.retainAll(elements));
|
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertEquals("Collection size shouldn't change", size,
|
assertEquals(size, collection.size(), "Collection size shouldn't change");
|
||||||
collection.size());
|
|
||||||
|
|
||||||
if (getFullElements().length > 1) {
|
if (getFullElements().length > 1) {
|
||||||
resetFull();
|
resetFull();
|
||||||
size = collection.size();
|
size = collection.size();
|
||||||
int min = (getFullElements().length < 2 ? 0 : 2);
|
int min = (getFullElements().length < 2 ? 0 : 2);
|
||||||
int max = (getFullElements().length <= 5 ? getFullElements().length - 1 : 5);
|
int max = (getFullElements().length <= 5 ? getFullElements().length - 1 : 5);
|
||||||
assertTrue("Collection should changed by partial retainAll",
|
assertTrue(collection.retainAll(elements.subList(min, max)), "Collection should changed by partial retainAll");
|
||||||
collection.retainAll(elements.subList(min, max)));
|
|
||||||
confirmed.retainAll(elements.subList(min, max));
|
confirmed.retainAll(elements.subList(min, max));
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
Iterator iter = collection.iterator();
|
Iterator iter = collection.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
assertTrue("Collection only contains retained element",
|
assertTrue(elements.subList(min, max).contains(iter.next()), "Collection only contains retained element");
|
||||||
elements.subList(min, max).contains(iter.next()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
HashSet set = new HashSet(elements);
|
HashSet set = new HashSet(elements);
|
||||||
size = collection.size();
|
size = collection.size();
|
||||||
assertTrue("Collection shouldn't change from retainAll without " +
|
assertTrue(!collection.retainAll(set),
|
||||||
"duplicate elements", !collection.retainAll(set));
|
"Collection shouldn't change from retainAll without duplicate elements");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertEquals("Collection size didn't change from nonduplicate " +
|
assertEquals( size, collection.size(),
|
||||||
"retainAll", size, collection.size());
|
"Collection size didn't change from nonduplicate retainAll");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1060,11 +1024,10 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCollectionSize() {
|
public void testCollectionSize() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals("Size of new Collection is 0.", 0, collection.size());
|
assertEquals(0, collection.size(), "Size of new Collection is 0.");
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("Size of full collection should be greater than zero",
|
assertTrue(collection.size() > 0, "Size of full collection should be greater than zero");
|
||||||
collection.size() > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1073,22 +1036,18 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
*/
|
*/
|
||||||
public void testCollectionToArray() {
|
public void testCollectionToArray() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals("Empty Collection should return empty array for toArray",
|
assertEquals(0, collection.toArray().length, "Empty Collection should return empty array for toArray");
|
||||||
0, collection.toArray().length);
|
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
Object[] array = collection.toArray();
|
Object[] array = collection.toArray();
|
||||||
assertEquals("Full collection toArray should be same size as " +
|
assertEquals(array.length, collection.size(), "Full collection toArray should be same size as collection");
|
||||||
"collection", array.length, collection.size());
|
|
||||||
Object[] confirmedArray = confirmed.toArray();
|
Object[] confirmedArray = confirmed.toArray();
|
||||||
assertEquals("length of array from confirmed collection should " +
|
assertEquals(confirmedArray.length, array.length,
|
||||||
"match the length of the collection's array",
|
"length of array from confirmed collection should match the length of the collection's array");
|
||||||
confirmedArray.length, array.length);
|
|
||||||
boolean[] matched = new boolean[array.length];
|
boolean[] matched = new boolean[array.length];
|
||||||
|
|
||||||
for (int i = 0; i < array.length; i++) {
|
for (int i = 0; i < array.length; i++) {
|
||||||
assertTrue("Collection should contain element in toArray",
|
assertTrue(collection.contains(array[i]), "Collection should contain element in toArray");
|
||||||
collection.contains(array[i]));
|
|
||||||
|
|
||||||
boolean match = false;
|
boolean match = false;
|
||||||
// find a match in the confirmed array
|
// find a match in the confirmed array
|
||||||
@@ -1108,8 +1067,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int i = 0; i < matched.length; i++) {
|
for(int i = 0; i < matched.length; i++) {
|
||||||
assertEquals("Collection should return all its elements in " +
|
assertEquals(true, matched[i], "Collection should return all its elements in toArray");
|
||||||
"toArray", true, matched[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1123,8 +1081,8 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
resetEmpty();
|
resetEmpty();
|
||||||
Object[] a = new Object[] { new Object(), null, null };
|
Object[] a = new Object[] { new Object(), null, null };
|
||||||
Object[] array = collection.toArray(a);
|
Object[] array = collection.toArray(a);
|
||||||
assertArrayEquals("Given array shouldn't shrink", array, a);
|
assertArrayEquals(array, a, "Given array shouldn't shrink");
|
||||||
assertNull("Last element should be set to null", a[0]);
|
assertNull(a[0], "Last element should be set to null");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
@@ -1146,8 +1104,7 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
array = collection.toArray(new Object[0]);
|
array = collection.toArray(new Object[0]);
|
||||||
a = collection.toArray();
|
a = collection.toArray();
|
||||||
assertEquals("toArrays should be equal",
|
assertEquals(Arrays.asList(array), Arrays.asList(a), "toArrays should be equal");
|
||||||
Arrays.asList(array), Arrays.asList(a));
|
|
||||||
|
|
||||||
// Figure out if they're all the same class
|
// Figure out if they're all the same class
|
||||||
// TODO: It'd be nicer to detect a common superclass
|
// TODO: It'd be nicer to detect a common superclass
|
||||||
@@ -1163,11 +1120,10 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
}
|
}
|
||||||
a = (Object[])Array.newInstance(cl, 0);
|
a = (Object[])Array.newInstance(cl, 0);
|
||||||
array = collection.toArray(a);
|
array = collection.toArray(a);
|
||||||
assertEquals("toArray(Object[]) should return correct array type",
|
assertEquals(a.getClass(), array.getClass(), "toArray(Object[]) should return correct array type");
|
||||||
a.getClass(), array.getClass());
|
assertEquals(Arrays.asList(array),
|
||||||
assertEquals("type-specific toArrays should be equal",
|
Arrays.asList(collection.toArray()),
|
||||||
Arrays.asList(array),
|
"type-specific toArrays should be equal");
|
||||||
Arrays.asList(collection.toArray()));
|
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1178,12 +1134,10 @@ public abstract class CollectionAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCollectionToString() {
|
public void testCollectionToString() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue("toString shouldn't return null",
|
assertTrue(collection.toString() != null, "toString shouldn't return null");
|
||||||
collection.toString() != null);
|
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("toString shouldn't return null",
|
assertTrue(collection.toString() != null, "toString shouldn't return null");
|
||||||
collection.toString() != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,13 +30,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
/**
|
/**
|
||||||
* CollectionUtilTest
|
* CollectionUtilTest
|
||||||
*
|
*
|
||||||
@@ -61,44 +59,60 @@ public class CollectionUtilTest {
|
|||||||
assertArrayEquals(new Object[] {"bar", "baz", 3}, merged);
|
assertArrayEquals(new Object[] {"bar", "baz", 3}, merged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IndexOutOfBoundsException.class)
|
@Test
|
||||||
public void testMergeArraysObjectBadOffset() {
|
public void testMergeArraysObjectBadOffset() {
|
||||||
CollectionUtil.mergeArrays(stringObjects, 4, 2, integerObjects, 2, 1);
|
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||||
|
CollectionUtil.mergeArrays(stringObjects, 4, 2, integerObjects, 2, 1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IndexOutOfBoundsException.class)
|
@Test
|
||||||
public void testMergeArraysObjectBadSecondOffset() {
|
public void testMergeArraysObjectBadSecondOffset() {
|
||||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 4, 1);
|
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||||
|
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 4, 1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IndexOutOfBoundsException.class)
|
@Test
|
||||||
public void testMergeArraysObjectBadLength() {
|
public void testMergeArraysObjectBadLength() {
|
||||||
CollectionUtil.mergeArrays(stringObjects, 1, 4, integerObjects, 2, 1);
|
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||||
|
CollectionUtil.mergeArrays(stringObjects, 1, 4, integerObjects, 2, 1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IndexOutOfBoundsException.class)
|
@Test
|
||||||
public void testMergeArraysObjectBadSecondLength() {
|
public void testMergeArraysObjectBadSecondLength() {
|
||||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 2, 2);
|
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||||
|
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 2, 2);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IndexOutOfBoundsException.class)
|
@Test
|
||||||
public void testMergeArraysObjectNegativeOffset() {
|
public void testMergeArraysObjectNegativeOffset() {
|
||||||
CollectionUtil.mergeArrays(stringObjects, -1, 2, integerObjects, 2, 1);
|
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||||
|
CollectionUtil.mergeArrays(stringObjects, -1, 2, integerObjects, 2, 1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IndexOutOfBoundsException.class)
|
@Test
|
||||||
public void testMergeArraysObjectNegativeSecondOffset() {
|
public void testMergeArraysObjectNegativeSecondOffset() {
|
||||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, -1, 1);
|
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||||
|
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, -1, 1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IndexOutOfBoundsException.class)
|
@Test
|
||||||
public void testMergeArraysObjectNegativeLength() {
|
public void testMergeArraysObjectNegativeLength() {
|
||||||
CollectionUtil.mergeArrays(stringObjects, 1, -1, integerObjects, 2, 1);
|
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||||
|
CollectionUtil.mergeArrays(stringObjects, 1, -1, integerObjects, 2, 1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IndexOutOfBoundsException.class)
|
@Test
|
||||||
public void testMergeArraysObjectNegativeSecondLength() {
|
public void testMergeArraysObjectNegativeSecondLength() {
|
||||||
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 2, -1);
|
assertThrows(IndexOutOfBoundsException.class, () -> {
|
||||||
|
CollectionUtil.mergeArrays(stringObjects, 1, 2, integerObjects, 2, -1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -109,20 +123,24 @@ public class CollectionUtilTest {
|
|||||||
assertArrayEquals(new Object[] {"foo", "bar", "baz", 1, 2, 3}, merged);
|
assertArrayEquals(new Object[] {"foo", "bar", "baz", 1, 2, 3}, merged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = ArrayStoreException.class)
|
@Test
|
||||||
public void testMergeArraysObjectIllegalType() {
|
public void testMergeArraysObjectIllegalType() {
|
||||||
String[] strings = {"foo", "bar", "baz"};
|
String[] strings = {"foo", "bar", "baz"};
|
||||||
Integer[] integers = {1, 2, 3}; // Integer not assignable to String
|
Integer[] integers = {1, 2, 3}; // Integer not assignable to String
|
||||||
|
|
||||||
CollectionUtil.mergeArrays(strings, integers);
|
assertThrows(ArrayStoreException.class, () -> {
|
||||||
|
CollectionUtil.mergeArrays(strings, integers);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = ArrayStoreException.class)
|
@Test
|
||||||
public void testMergeArraysNativeIllegalType() {
|
public void testMergeArraysNativeIllegalType() {
|
||||||
char[] chars = {'a', 'b', 'c'};
|
char[] chars = {'a', 'b', 'c'};
|
||||||
int[] integers = {1, 2, 3}; // Integer not assignable to String
|
int[] integers = {1, 2, 3}; // Integer not assignable to String
|
||||||
|
|
||||||
CollectionUtil.mergeArrays(chars, integers);
|
assertThrows(ArrayStoreException.class, () -> {
|
||||||
|
CollectionUtil.mergeArrays(chars, integers);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,9 +165,11 @@ public class CollectionUtilTest {
|
|||||||
assertArrayEquals(new int[] {2, 3, 4}, numbers);
|
assertArrayEquals(new int[] {2, 3, 4}, numbers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testEnumIteratorNull() {
|
public void testEnumIteratorNull() {
|
||||||
CollectionUtil.iterator((Enumeration<Object>) null);
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
CollectionUtil.iterator((Enumeration<Object>) null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -183,9 +203,11 @@ public class CollectionUtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testArrayIteratorNull() {
|
public void testArrayIteratorNull() {
|
||||||
CollectionUtil.iterator((Object[]) null);
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
CollectionUtil.iterator((Object[]) null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -262,7 +284,7 @@ public class CollectionUtilTest {
|
|||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Object element : elements) {
|
for (Object element : elements) {
|
||||||
assertTrue("No next element for element '" + element + "' at index: " + count, iterator.hasNext());
|
assertTrue(iterator.hasNext(), "No next element for element '" + element + "' at index: " + count);
|
||||||
assertEquals(count > 0, iterator.hasPrevious());
|
assertEquals(count > 0, iterator.hasPrevious());
|
||||||
assertEquals(count, iterator.nextIndex());
|
assertEquals(count, iterator.nextIndex());
|
||||||
assertEquals(count - 1, iterator.previousIndex());
|
assertEquals(count - 1, iterator.previousIndex());
|
||||||
@@ -318,7 +340,7 @@ public class CollectionUtilTest {
|
|||||||
assertEquals(elements.length, iterator.nextIndex());
|
assertEquals(elements.length, iterator.nextIndex());
|
||||||
|
|
||||||
for (int i = count; i > 0; i--) {
|
for (int i = count; i > 0; i--) {
|
||||||
assertTrue("No previous element for element '" + elements[i - 1] + "' at index: " + (i - 1), iterator.hasPrevious());
|
assertTrue(iterator.hasPrevious(), "No previous element for element '" + elements[i - 1] + "' at index: " + (i - 1));
|
||||||
assertEquals(i < elements.length, iterator.hasNext());
|
assertEquals(i < elements.length, iterator.hasNext());
|
||||||
assertEquals(i - 1, iterator.previousIndex());
|
assertEquals(i - 1, iterator.previousIndex());
|
||||||
assertEquals(i, iterator.nextIndex());
|
assertEquals(i, iterator.nextIndex());
|
||||||
@@ -339,18 +361,24 @@ public class CollectionUtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testArrayIteratorRangeNull() {
|
public void testArrayIteratorRangeNull() {
|
||||||
CollectionUtil.iterator(null, 0, 0);
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
CollectionUtil.iterator(null, 0, 0);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testArrayIteratorRangeBadStart() {
|
public void testArrayIteratorRangeBadStart() {
|
||||||
CollectionUtil.iterator(stringObjects, stringObjects.length + 1, 2);
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
CollectionUtil.iterator(stringObjects, stringObjects.length + 1, 2);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testArrayIteratorRangeBadLength() {
|
public void testArrayIteratorRangeBadLength() {
|
||||||
CollectionUtil.iterator(stringObjects, 1, stringObjects.length);
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
CollectionUtil.iterator(stringObjects, 1, stringObjects.length);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -379,9 +407,11 @@ public class CollectionUtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testReverseOrderNull() {
|
public void testReverseOrderNull() {
|
||||||
CollectionUtil.reverseOrder(null);
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
CollectionUtil.reverseOrder(null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -431,7 +461,7 @@ public class CollectionUtilTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("For development only")
|
@Disabled("For development only")
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings({"UnusedDeclaration"})
|
@SuppressWarnings({"UnusedDeclaration"})
|
||||||
public void testGenerify() {
|
public void testGenerify() {
|
||||||
|
|||||||
@@ -45,11 +45,10 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import org.junit.jupiter.api.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests LRUMap.
|
* Tests LRUMap.
|
||||||
@@ -81,8 +80,8 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
map2.put(4,"foo"); // removes 1 since max size exceeded
|
map2.put(4,"foo"); // removes 1 since max size exceeded
|
||||||
map2.removeLRU(); // should be Integer(2)
|
map2.removeLRU(); // should be Integer(2)
|
||||||
|
|
||||||
assertTrue("Second to last value should exist",map2.get(new Integer(3)).equals("foo"));
|
assertTrue(map2.get(new Integer(3)).equals("foo"), "Second to last value should exist");
|
||||||
assertTrue("First value inserted should not exist", map2.get(new Integer(1)) == null);
|
assertTrue(map2.get(new Integer(1)) == null, "First value inserted should not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -93,8 +92,8 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
map2.put(3,"foo");
|
map2.put(3,"foo");
|
||||||
map2.put(4,"bar");
|
map2.put(4,"bar");
|
||||||
|
|
||||||
assertTrue("last value should exist",map2.get(new Integer(4)).equals("bar"));
|
assertTrue(map2.get(new Integer(4)).equals("bar"), "last value should exist");
|
||||||
assertTrue("LRU should not exist", map2.get(new Integer(1)) == null);
|
assertTrue(map2.get(new Integer(1)) == null, "LRU should not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,10 +112,8 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
|
|
||||||
map2.putAll(hashMap);
|
map2.putAll(hashMap);
|
||||||
|
|
||||||
assertTrue("max size is 3, but actual size is " + map2.size(),
|
assertTrue(map2.size() == 3, "max size is 3, but actual size is " + map2.size());
|
||||||
map2.size() == 3);
|
assertTrue(map2.containsKey(new Integer(4)), "map should contain the Integer(4) object");
|
||||||
assertTrue("map should contain the Integer(4) object",
|
|
||||||
map2.containsKey(new Integer(4)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,8 +131,7 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
map.put("6","6");
|
map.put("6","6");
|
||||||
map.setMaxSize(3);
|
map.setMaxSize(3);
|
||||||
|
|
||||||
assertTrue("map should have size = 3, but actually = " + map.size(),
|
assertTrue(map.size() == 3, "map should have size = 3, but actually = " + map.size());
|
||||||
map.size() == 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -160,9 +156,9 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
keys[i] = keyIterator.next();
|
keys[i] = keyIterator.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("first evicted should be 3, was " + keys[0], keys[0].equals("3"));
|
assertTrue(keys[0].equals("3"), "first evicted should be 3, was " + keys[0]);
|
||||||
assertTrue("second evicted should be 1, was " + keys[1], keys[1].equals("1"));
|
assertTrue(keys[1].equals("1"), "second evicted should be 1, was " + keys[1]);
|
||||||
assertTrue("third evicted should be 4, was " + keys[2], keys[2].equals("4"));
|
assertTrue(keys[2].equals("4"), "third evicted should be 4, was " + keys[2]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,13 +188,12 @@ public class LRUMapTest extends LinkedMapTest {
|
|||||||
// 4 2
|
// 4 2
|
||||||
counter.remove("5");
|
counter.remove("5");
|
||||||
|
|
||||||
assertTrue("size should be 2, but was " + counter.size(), counter.size() == 2);
|
assertTrue(counter.size() == 2, "size should be 2, but was " + counter.size());
|
||||||
assertTrue("removedCount should be 3 but was " + counter.removedCount,
|
assertTrue(counter.removedCount == 3, "removedCount should be 3 but was " + counter.removedCount);
|
||||||
counter.removedCount == 3);
|
|
||||||
|
|
||||||
assertTrue("first removed was '2'",counter.list.get(0).equals("2"));
|
assertTrue(counter.list.get(0).equals("2"), "first removed was '2'");
|
||||||
assertTrue("second removed was '3'",counter.list.get(1).equals("3"));
|
assertTrue(counter.list.get(1).equals("3"), "second removed was '3'");
|
||||||
assertTrue("third removed was '1'",counter.list.get(2).equals("1"));
|
assertTrue(counter.list.get(2).equals("1"), "third removed was '1'");
|
||||||
|
|
||||||
//assertTrue("oldest key is '4'",counter.get(0).equals("4"));
|
//assertTrue("oldest key is '4'",counter.get(0).equals("4"));
|
||||||
//assertTrue("newest key is '2'",counter.get(1).equals("2"));
|
//assertTrue("newest key is '2'",counter.get(1).equals("2"));
|
||||||
|
|||||||
@@ -45,15 +45,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.jupiter.api.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests
|
* Unit tests
|
||||||
@@ -74,7 +70,7 @@ public class LinkedMapTest extends MapAbstractTest {
|
|||||||
*/
|
*/
|
||||||
protected LinkedMap labRat;
|
protected LinkedMap labRat;
|
||||||
|
|
||||||
@Before
|
@BeforeEach
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
// use makeMap and cast the result to a SeqHashMap
|
// use makeMap and cast the result to a SeqHashMap
|
||||||
// so that subclasses of SeqHashMap can share these tests
|
// so that subclasses of SeqHashMap can share these tests
|
||||||
@@ -103,27 +99,21 @@ public class LinkedMapTest extends MapAbstractTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test size().
|
// Test size().
|
||||||
assertEquals("size() does not match expected size",
|
assertEquals(expectedSize, labRat.size(), "size() does not match expected size");
|
||||||
expectedSize, labRat.size());
|
|
||||||
|
|
||||||
// Test clone(), iterator(), and get(Object).
|
// Test clone(), iterator(), and get(Object).
|
||||||
LinkedMap clone = (LinkedMap) labRat.clone();
|
LinkedMap clone = (LinkedMap) labRat.clone();
|
||||||
assertEquals("Size of clone does not match original",
|
assertEquals(labRat.size(), clone.size(), "Size of clone does not match original");
|
||||||
labRat.size(), clone.size());
|
|
||||||
Iterator origEntries = labRat.entrySet().iterator();
|
Iterator origEntries = labRat.entrySet().iterator();
|
||||||
Iterator copiedEntries = clone.entrySet().iterator();
|
Iterator copiedEntries = clone.entrySet().iterator();
|
||||||
while (origEntries.hasNext()) {
|
while (origEntries.hasNext()) {
|
||||||
Map.Entry origEntry = (Map.Entry)origEntries.next();
|
Map.Entry origEntry = (Map.Entry)origEntries.next();
|
||||||
Map.Entry copiedEntry = (Map.Entry)copiedEntries.next();
|
Map.Entry copiedEntry = (Map.Entry)copiedEntries.next();
|
||||||
assertEquals("Cloned key does not match original",
|
assertEquals(origEntry.getKey(), copiedEntry.getKey(), "Cloned key does not match original");
|
||||||
origEntry.getKey(), copiedEntry.getKey());
|
assertEquals(origEntry.getValue(), copiedEntry.getValue(), "Cloned value does not match original");
|
||||||
assertEquals("Cloned value does not match original",
|
assertEquals(origEntry, copiedEntry, "Cloned entry does not match original");
|
||||||
origEntry.getValue(), copiedEntry.getValue());
|
|
||||||
assertEquals("Cloned entry does not match original",
|
|
||||||
origEntry, copiedEntry);
|
|
||||||
}
|
}
|
||||||
assertTrue("iterator() returned different number of elements than keys()",
|
assertTrue(!copiedEntries.hasNext(), "iterator() returned different number of elements than keys()");
|
||||||
!copiedEntries.hasNext());
|
|
||||||
|
|
||||||
// Test sequence()
|
// Test sequence()
|
||||||
/*
|
/*
|
||||||
@@ -207,7 +197,7 @@ public class LinkedMapTest extends MapAbstractTest {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@After
|
@AfterEach
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
labRat = null;
|
labRat = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,12 +45,10 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract test class for {@link java.util.Map} methods and contracts.
|
* Abstract test class for {@link java.util.Map} methods and contracts.
|
||||||
@@ -390,19 +388,19 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
m.put(keys[i], values[i]);
|
m.put(keys[i], values[i]);
|
||||||
}
|
}
|
||||||
catch (NullPointerException exception) {
|
catch (NullPointerException exception) {
|
||||||
assertTrue("NullPointerException only allowed to be thrown if either the key or value is null.",
|
assertTrue(keys[i] == null || values[i] == null,
|
||||||
keys[i] == null || values[i] == null);
|
"NullPointerException only allowed to be thrown if either the key or value is null.");
|
||||||
|
|
||||||
assertTrue("NullPointerException on null key, but isAllowNullKey is not overridden to return false.",
|
assertTrue(keys[i] == null || !isAllowNullKey(),
|
||||||
keys[i] == null || !isAllowNullKey());
|
"NullPointerException on null key, but isAllowNullKey is not overridden to return false.");
|
||||||
|
|
||||||
assertTrue("NullPointerException on null value, but isAllowNullValue is not overridden to return false.",
|
assertTrue(values[i] == null || !isAllowNullValue(),
|
||||||
values[i] == null || !isAllowNullValue());
|
"NullPointerException on null value, but isAllowNullValue is not overridden to return false.");
|
||||||
|
|
||||||
assertTrue("Unknown reason for NullPointer.", false);
|
fail("Unknown reason for NullPointer.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertEquals("size must reflect number of mappings added.", keys.length, m.size());
|
assertEquals(keys.length, m.size(), "size must reflect number of mappings added.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
@@ -481,27 +479,26 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
Object[] values = getSampleValues();
|
Object[] values = getSampleValues();
|
||||||
Object[] newValues = getNewSampleValues();
|
Object[] newValues = getNewSampleValues();
|
||||||
|
|
||||||
assertTrue("failure in test: Must have keys returned from getSampleKeys.", keys != null);
|
assertTrue(keys != null, "failure in test: Must have keys returned from getSampleKeys.");
|
||||||
assertTrue("failure in test: Must have values returned from getSampleValues.", values != null);
|
assertTrue(values != null, "failure in test: Must have values returned from getSampleValues.");
|
||||||
|
|
||||||
// verify keys and values have equivalent lengths (in case getSampleX are
|
// verify keys and values have equivalent lengths (in case getSampleX are
|
||||||
// overridden)
|
// overridden)
|
||||||
assertEquals("failure in test: not the same number of sample keys and values.", keys.length, values.length);
|
assertEquals(keys.length, values.length, "failure in test: not the same number of sample keys and values.");
|
||||||
assertEquals("failure in test: not the same number of values and new values.", values.length, newValues.length);
|
assertEquals(values.length, newValues.length, "failure in test: not the same number of values and new values.");
|
||||||
|
|
||||||
// verify there aren't duplicate keys, and check values
|
// verify there aren't duplicate keys, and check values
|
||||||
for (int i = 0; i < keys.length - 1; i++) {
|
for (int i = 0; i < keys.length - 1; i++) {
|
||||||
for (int j = i + 1; j < keys.length; j++) {
|
for (int j = i + 1; j < keys.length; j++) {
|
||||||
assertTrue("failure in test: duplicate null keys.", (keys[i] != null || keys[j] != null));
|
assertTrue((keys[i] != null || keys[j] != null), "failure in test: duplicate null keys.");
|
||||||
assertTrue("failure in test: duplicate non-null key.",
|
assertTrue((keys[i] == null || keys[j] == null || (!keys[i].equals(keys[j]) && !keys[j].equals(keys[i]))),
|
||||||
(keys[i] == null || keys[j] == null || (!keys[i].equals(keys[j]) && !keys[j].equals(keys[i]))));
|
"failure in test: duplicate non-null key.");
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("failure in test: found null key, but isNullKeySupported is false.", keys[i] != null || isAllowNullKey());
|
assertTrue(keys[i] != null || isAllowNullKey(),"failure in test: found null key, but isNullKeySupported is false.");
|
||||||
assertTrue("failure in test: found null value, but isNullValueSupported is false.", values[i] != null || isAllowNullValue());
|
assertTrue(values[i] != null || isAllowNullValue(),"failure in test: found null value, but isNullValueSupported is false.");
|
||||||
assertTrue("failure in test: found null new value, but isNullValueSupported is false.", newValues[i] != null || isAllowNullValue());
|
assertTrue(newValues[i] != null || isAllowNullValue(), "failure in test: found null new value, but isNullValueSupported is false.");
|
||||||
assertTrue("failure in test: values should not be the same as new value",
|
assertTrue(values[i] != newValues[i] && (values[i] == null || !values[i].equals(newValues[i])), "failure in test: values should not be the same as new value");
|
||||||
values[i] != newValues[i] && (values[i] == null || !values[i].equals(newValues[i])));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,18 +514,18 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMakeMap() {
|
public void testMakeMap() {
|
||||||
Map em = makeEmptyMap();
|
Map em = makeEmptyMap();
|
||||||
assertTrue("failure in test: makeEmptyMap must return a non-null map.", em != null);
|
assertTrue(em != null, "failure in test: makeEmptyMap must return a non-null map.");
|
||||||
|
|
||||||
Map em2 = makeEmptyMap();
|
Map em2 = makeEmptyMap();
|
||||||
assertTrue("failure in test: makeEmptyMap must return a non-null map.", em2 != null);
|
assertTrue(em2 != null, "failure in test: makeEmptyMap must return a non-null map.");
|
||||||
assertTrue("failure in test: makeEmptyMap must return a new map with each invocation.", em != em2);
|
assertTrue(em != em2, "failure in test: makeEmptyMap must return a new map with each invocation.");
|
||||||
|
|
||||||
Map fm = makeFullMap();
|
Map fm = makeFullMap();
|
||||||
assertTrue("failure in test: makeFullMap must return a non-null map.", fm != null);
|
assertTrue(fm != null, "failure in test: makeFullMap must return a non-null map.");
|
||||||
|
|
||||||
Map fm2 = makeFullMap();
|
Map fm2 = makeFullMap();
|
||||||
assertTrue("failure in test: makeFullMap must return a non-null map.", fm2 != null);
|
assertTrue(fm2 != null, "failure in test: makeFullMap must return a non-null map.");
|
||||||
assertTrue("failure in test: makeFullMap must return a new map with each invocation.", fm != fm2);
|
assertTrue(fm != fm2, "failure in test: makeFullMap must return a new map with each invocation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -537,11 +534,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMapIsEmpty() {
|
public void testMapIsEmpty() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals("Map.isEmpty() should return true with an empty map", true, map.isEmpty());
|
assertEquals(true, map.isEmpty(), "Map.isEmpty() should return true with an empty map");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertEquals("Map.isEmpty() should return false with a non-empty map", false, map.isEmpty());
|
assertEquals(false, map.isEmpty(), "Map.isEmpty() should return false with a non-empty map");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,11 +548,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMapSize() {
|
public void testMapSize() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals("Map.size() should be 0 with an empty map", 0, map.size());
|
assertEquals(0, map.size(), "Map.size() should be 0 with an empty map");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertEquals("Map.size() should equal the number of entries in the map", getSampleKeys().length, map.size());
|
assertEquals(getSampleKeys().length, map.size(), "Map.size() should equal the number of entries in the map");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,13 +599,13 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
for (Object key : keys) {
|
for (Object key : keys) {
|
||||||
assertTrue("Map must not contain key when map is empty", !map.containsKey(key));
|
assertTrue(!map.containsKey(key), "Map must not contain key when map is empty");
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
for (Object key : keys) {
|
for (Object key : keys) {
|
||||||
assertTrue("Map must contain key for a mapping in the map. Missing: " + key, map.containsKey(key));
|
assertTrue(map.containsKey(key), "Map must contain key for a mapping in the map. Missing: " + key);
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -624,13 +621,13 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
for (Object value : values) {
|
for (Object value : values) {
|
||||||
assertTrue("Empty map must not contain value", !map.containsValue(value));
|
assertTrue(!map.containsValue(value), "Empty map must not contain value");
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
for (Object value : values) {
|
for (Object value : values) {
|
||||||
assertTrue("Map must contain value for a mapping in the map.", map.containsValue(value));
|
assertTrue(map.containsValue(value), "Map must contain value for a mapping in the map.");
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -641,11 +638,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMapEquals() {
|
public void testMapEquals() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue("Empty maps unequal.", map.equals(confirmed));
|
assertTrue(map.equals(confirmed), "Empty maps unequal.");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("Full maps unequal.", map.equals(confirmed));
|
assertTrue(map.equals(confirmed), "Full maps unequal.");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
@@ -654,11 +651,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
Iterator iter = confirmed.keySet().iterator();
|
Iterator iter = confirmed.keySet().iterator();
|
||||||
iter.next();
|
iter.next();
|
||||||
iter.remove();
|
iter.remove();
|
||||||
assertTrue("Different maps equal.", !map.equals(confirmed));
|
assertTrue(!map.equals(confirmed), "Different maps equal.");
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("equals(null) returned true.", !map.equals(null));
|
assertTrue(!map.equals(null), "equals(null) returned true.");
|
||||||
assertTrue("equals(new Object()) returned true.", !map.equals(new Object()));
|
assertTrue(!map.equals(new Object()), "equals(new Object()) returned true.");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,14 +670,14 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
Object[] values = getSampleValues();
|
Object[] values = getSampleValues();
|
||||||
|
|
||||||
for (Object key : keys) {
|
for (Object key : keys) {
|
||||||
assertTrue("Empty map.get() should return null.", map.get(key) == null);
|
assertTrue(map.get(key) == null, "Empty map.get() should return null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
for (int i = 0; i < keys.length; i++) {
|
for (int i = 0; i < keys.length; i++) {
|
||||||
assertEquals("Full map.get() should return value from mapping.", values[i], map.get(keys[i]));
|
assertEquals(values[i], map.get(keys[i]), "Full map.get() should return value from mapping.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,10 +687,10 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMapHashCode() {
|
public void testMapHashCode() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue("Empty maps have different hashCodes.", map.hashCode() == confirmed.hashCode());
|
assertTrue(map.hashCode() == confirmed.hashCode(), "Empty maps have different hashCodes.");
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("Equal maps have different hashCodes.", map.hashCode() == confirmed.hashCode());
|
assertTrue(map.hashCode() == confirmed.hashCode(), "Equal maps have different hashCodes.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -708,11 +705,11 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testMapToString() {
|
public void testMapToString() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue("Empty map toString() should not return null", map.toString() != null);
|
assertTrue(map.toString() != null, "Empty map toString() should not return null");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertTrue("Empty map toString() should not return null", map.toString() != null);
|
assertTrue(map.toString() != null, "Empty map toString() should not return null");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -776,29 +773,23 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
Object o = map.put(keys[i], values[i]);
|
Object o = map.put(keys[i], values[i]);
|
||||||
confirmed.put(keys[i], values[i]);
|
confirmed.put(keys[i], values[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertTrue("First map.put should return null", o == null);
|
assertTrue(o == null, "First map.put should return null");
|
||||||
assertTrue("Map should contain key after put",
|
assertTrue(map.containsKey(keys[i]), "Map should contain key after put");
|
||||||
map.containsKey(keys[i]));
|
assertTrue(map.containsValue(values[i]), "Map should contain value after put");
|
||||||
assertTrue("Map should contain value after put",
|
|
||||||
map.containsValue(values[i]));
|
|
||||||
}
|
}
|
||||||
if (isPutChangeSupported()) {
|
if (isPutChangeSupported()) {
|
||||||
for (int i = 0; i < keys.length; i++) {
|
for (int i = 0; i < keys.length; i++) {
|
||||||
Object o = map.put(keys[i], newValues[i]);
|
Object o = map.put(keys[i], newValues[i]);
|
||||||
confirmed.put(keys[i], newValues[i]);
|
confirmed.put(keys[i], newValues[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertEquals("Map.put should return previous value when changed",
|
assertEquals(values[i], o, "Map.put should return previous value when changed");
|
||||||
values[i], o);
|
assertTrue(map.containsKey(keys[i]), "Map should still contain key after put when changed");
|
||||||
assertTrue("Map should still contain key after put when changed",
|
assertTrue(map.containsValue(newValues[i]), "Map should contain new value after put when changed");
|
||||||
map.containsKey(keys[i]));
|
|
||||||
assertTrue("Map should contain new value after put when changed",
|
|
||||||
map.containsValue(newValues[i]));
|
|
||||||
|
|
||||||
// if duplicates are allowed, we're not guaranteed that the value
|
// if duplicates are allowed, we're not guaranteed that the value
|
||||||
// no longer exists, so don't try checking that.
|
// no longer exists, so don't try checking that.
|
||||||
if (!isAllowDuplicateValues()) {
|
if (!isAllowDuplicateValues()) {
|
||||||
assertTrue("Map should not contain old value after put when changed",
|
assertTrue(!map.containsValue(values[i]), "Map should not contain old value after put when changed");
|
||||||
!map.containsValue(values[i]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -832,18 +823,14 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
Object o = map.put(key, newValues[i]);
|
Object o = map.put(key, newValues[i]);
|
||||||
Object value = confirmed.put(key, newValues[i]);
|
Object value = confirmed.put(key, newValues[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertEquals("Map.put should return previous value when changed",
|
assertEquals(value, o, "Map.put should return previous value when changed");
|
||||||
value, o);
|
assertTrue(map.containsKey(key), "Map should still contain key after put when changed");
|
||||||
assertTrue("Map should still contain key after put when changed",
|
assertTrue(map.containsValue(newValues[i]), "Map should contain new value after put when changed");
|
||||||
map.containsKey(key));
|
|
||||||
assertTrue("Map should contain new value after put when changed",
|
|
||||||
map.containsValue(newValues[i]));
|
|
||||||
|
|
||||||
// if duplicates are allowed, we're not guaranteed that the value
|
// if duplicates are allowed, we're not guaranteed that the value
|
||||||
// no longer exists, so don't try checking that.
|
// no longer exists, so don't try checking that.
|
||||||
if (!isAllowDuplicateValues()) {
|
if (!isAllowDuplicateValues()) {
|
||||||
assertTrue("Map should not contain old value after put when changed",
|
assertTrue(!map.containsValue(values[i]), "Map should not contain old value after put when changed");
|
||||||
!map.containsValue(values[i]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -970,7 +957,7 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
Object[] values = getSampleValues();
|
Object[] values = getSampleValues();
|
||||||
for (int i = 0; i < keys.length; i++) {
|
for (int i = 0; i < keys.length; i++) {
|
||||||
Object o = map.remove(keys[i]);
|
Object o = map.remove(keys[i]);
|
||||||
assertTrue("First map.remove should return null", o == null);
|
assertTrue(o == null, "First map.remove should return null");
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
@@ -981,8 +968,7 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
confirmed.remove(keys[i]);
|
confirmed.remove(keys[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
assertEquals("map.remove with valid key should return value",
|
assertEquals(values[i], o, "map.remove with valid key should return value");
|
||||||
values[i], o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object[] other = getOtherKeys();
|
Object[] other = getOtherKeys();
|
||||||
@@ -991,10 +977,8 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
int size = map.size();
|
int size = map.size();
|
||||||
for (int i = 0; i < other.length; i++) {
|
for (int i = 0; i < other.length; i++) {
|
||||||
Object o = map.remove(other[i]);
|
Object o = map.remove(other[i]);
|
||||||
assertEquals("map.remove for nonexistent key should return null",
|
assertEquals(o, null, "map.remove for nonexistent key should return null");
|
||||||
o, null);
|
assertEquals(size, map.size(), "map.remove for nonexistent key should not shrink map");
|
||||||
assertEquals("map.remove for nonexistent key should not " +
|
|
||||||
"shrink map", size, map.size());
|
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -1204,10 +1188,9 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
}
|
}
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
assertTrue("values().remove(obj) is broken", j < 10000);
|
assertTrue(j < 10000, "values().remove(obj) is broken");
|
||||||
assertTrue(
|
assertTrue(!map.containsValue(sampleValues[i]),
|
||||||
"Value should have been removed from the underlying map.",
|
"Value should have been removed from the underlying map.");
|
||||||
!map.containsValue(sampleValues[i]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1230,9 +1213,8 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
// if key.remove is unsupported, just skip this test
|
// if key.remove is unsupported, just skip this test
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assertTrue(
|
assertTrue(!map.containsKey(sampleKeys[i]),
|
||||||
"Key should have been removed from the underlying map.",
|
"Key should have been removed from the underlying map.");
|
||||||
!map.containsKey(sampleKeys[i]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1413,7 +1395,7 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertNotNull("No matching entry in map for key '" + key + "'", entry);
|
assertNotNull(entry, "No matching entry in map for key '" + key + "'");
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1638,14 +1620,14 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
public void verifyMap() {
|
public void verifyMap() {
|
||||||
int size = confirmed.size();
|
int size = confirmed.size();
|
||||||
boolean empty = confirmed.isEmpty();
|
boolean empty = confirmed.isEmpty();
|
||||||
assertEquals("Map should be same size as HashMap", size, map.size());
|
assertEquals(size, map.size(), "Map should be same size as HashMap");
|
||||||
assertEquals("Map should be empty if HashMap is", empty, map.isEmpty());
|
assertEquals(empty, map.isEmpty(), "Map should be empty if HashMap is");
|
||||||
assertEquals("hashCodes should be the same", confirmed.hashCode(), map.hashCode());
|
assertEquals(confirmed.hashCode(), map.hashCode(), "hashCodes should be the same");
|
||||||
// this fails for LRUMap because confirmed.equals() somehow modifies
|
// this fails for LRUMap because confirmed.equals() somehow modifies
|
||||||
// map, causing concurrent modification exceptions.
|
// map, causing concurrent modification exceptions.
|
||||||
//assertEquals("Map should still equal HashMap", confirmed, map);
|
//assertEquals("Map should still equal HashMap", confirmed, map);
|
||||||
// this works though and performs the same verification:
|
// this works though and performs the same verification:
|
||||||
assertTrue("Map should still equal HashMap", map.equals(confirmed));
|
assertTrue(map.equals(confirmed), "Map should still equal HashMap");
|
||||||
// TODO: this should really be reexamined to figure out why LRU map
|
// TODO: this should really be reexamined to figure out why LRU map
|
||||||
// behaves like it does (the equals shouldn't modify since all accesses
|
// behaves like it does (the equals shouldn't modify since all accesses
|
||||||
// by the confirmed collection should be through an iterator, thus not
|
// by the confirmed collection should be through an iterator, thus not
|
||||||
@@ -1655,29 +1637,29 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
public void verifyEntrySet() {
|
public void verifyEntrySet() {
|
||||||
int size = confirmed.size();
|
int size = confirmed.size();
|
||||||
boolean empty = confirmed.isEmpty();
|
boolean empty = confirmed.isEmpty();
|
||||||
assertEquals("entrySet should be same size as HashMap's\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
assertEquals(size, entrySet.size(),
|
||||||
size, entrySet.size());
|
"entrySet should be same size as HashMap's\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
||||||
assertEquals("entrySet should be empty if HashMap is\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
assertEquals(empty, entrySet.isEmpty(),
|
||||||
empty, entrySet.isEmpty());
|
"entrySet should be empty if HashMap is\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
||||||
assertTrue("entrySet should contain all HashMap's elements\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
assertTrue(entrySet.containsAll(confirmed.entrySet()),
|
||||||
entrySet.containsAll(confirmed.entrySet()));
|
"entrySet should contain all HashMap's elements\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
||||||
assertEquals("entrySet hashCodes should be the same\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
|
assertEquals(confirmed.entrySet().hashCode(), entrySet.hashCode(),
|
||||||
confirmed.entrySet().hashCode(), entrySet.hashCode());
|
"entrySet hashCodes should be the same\nTest: " + entrySet + "\nReal: " + confirmed.entrySet());
|
||||||
assertEquals("Map's entry set should still equal HashMap's", confirmed.entrySet(), entrySet);
|
assertEquals(confirmed.entrySet(), entrySet,"Map's entry set should still equal HashMap's");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyKeySet() {
|
public void verifyKeySet() {
|
||||||
int size = confirmed.size();
|
int size = confirmed.size();
|
||||||
boolean empty = confirmed.isEmpty();
|
boolean empty = confirmed.isEmpty();
|
||||||
assertEquals("keySet should be same size as HashMap's\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
assertEquals(size, keySet.size(),
|
||||||
size, keySet.size());
|
"keySet should be same size as HashMap's\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
||||||
assertEquals("keySet should be empty if HashMap is\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
assertEquals(empty, keySet.isEmpty(),
|
||||||
empty, keySet.isEmpty());
|
"keySet should be empty if HashMap is\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
||||||
assertTrue("keySet should contain all HashMap's elements\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
assertTrue(keySet.containsAll(confirmed.keySet()),
|
||||||
keySet.containsAll(confirmed.keySet()));
|
"keySet should contain all HashMap's elements\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
||||||
assertEquals("keySet hashCodes should be the same\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
|
assertEquals(confirmed.keySet().hashCode(), keySet.hashCode(),
|
||||||
confirmed.keySet().hashCode(), keySet.hashCode());
|
"keySet hashCodes should be the same\nTest: " + keySet + "\nReal: " + confirmed.keySet());
|
||||||
assertEquals("Map's key set should still equal HashMap's", confirmed.keySet(), keySet);
|
assertEquals(confirmed.keySet(), keySet, "Map's key set should still equal HashMap's");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyValues() {
|
public void verifyValues() {
|
||||||
@@ -1687,23 +1669,23 @@ public abstract class MapAbstractTest extends ObjectAbstractTest {
|
|||||||
int size = confirmed.size();
|
int size = confirmed.size();
|
||||||
boolean empty = confirmed.isEmpty();
|
boolean empty = confirmed.isEmpty();
|
||||||
|
|
||||||
assertEquals("values should be same size as HashMap's\nTest: " + test + "\nReal: " + known, size, values.size());
|
assertEquals(size, values.size(), "values should be same size as HashMap's\nTest: " + test + "\nReal: " + known);
|
||||||
assertEquals("values should be empty if HashMap is\nTest: " + test + "\nReal: " + known, empty, values.isEmpty());
|
assertEquals(empty, values.isEmpty(), "values should be empty if HashMap is\nTest: " + test + "\nReal: " + known);
|
||||||
assertTrue("values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known, test.containsAll(known));
|
assertTrue(test.containsAll(known), "values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known);
|
||||||
assertTrue("values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known, known.containsAll(test));
|
assertTrue(known.containsAll(test), "values should contain all HashMap's elements\nTest: " + test + "\nReal: " + known);
|
||||||
|
|
||||||
for (Object aKnown : known) {
|
for (Object aKnown : known) {
|
||||||
boolean removed = test.remove(aKnown);
|
boolean removed = test.remove(aKnown);
|
||||||
assertTrue("Map's values should still equal HashMap's", removed);
|
assertTrue(removed, "Map's values should still equal HashMap's");
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("Map's values should still equal HashMap's", test.isEmpty());
|
assertTrue(test.isEmpty(), "Map's values should still equal HashMap's");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erases any leftover instance variables by setting them to null.
|
* Erases any leftover instance variables by setting them to null.
|
||||||
*/
|
*/
|
||||||
@After
|
@AfterEach
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
map = null;
|
map = null;
|
||||||
keySet = null;
|
keySet = null;
|
||||||
|
|||||||
@@ -30,13 +30,11 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.jupiter.api.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: This TestCase is written especially for NullMap, and is full of dirty
|
* NOTE: This TestCase is written especially for NullMap, and is full of dirty
|
||||||
@@ -83,12 +81,12 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
@Override
|
@Override
|
||||||
public void testMapIsEmpty() {
|
public void testMapIsEmpty() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals("Map.isEmpty() should return true with an empty map",
|
assertEquals(true, map.isEmpty(),
|
||||||
true, map.isEmpty());
|
"Map.isEmpty() should return true with an empty map");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
resetFull();
|
resetFull();
|
||||||
assertEquals("Map.isEmpty() should return true with a full map",
|
assertEquals(true, map.isEmpty(),
|
||||||
true, map.isEmpty());
|
"Map.isEmpty() should return true with a full map");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overriden, as this map is always empty
|
// Overriden, as this map is always empty
|
||||||
@@ -96,13 +94,13 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
@Override
|
@Override
|
||||||
public void testMapSize() {
|
public void testMapSize() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals("Map.size() should be 0 with an empty map",
|
assertEquals(0, map.size(),
|
||||||
0, map.size());
|
"Map.size() should be 0 with an empty map");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertEquals("Map.size() should equal the number of entries " +
|
assertEquals(0, map.size(),
|
||||||
"in the map", 0, map.size());
|
"Map.size() should equal the number of entries in the map");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -112,7 +110,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
for (Object key : keys) {
|
for (Object key : keys) {
|
||||||
assertTrue("Map must not contain key when map is empty", !map.containsKey(key));
|
assertTrue(!map.containsKey(key),"Map must not contain key when map is empty");
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -124,7 +122,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
|
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
for (Object value : values) {
|
for (Object value : values) {
|
||||||
assertTrue("Empty map must not contain value", !map.containsValue(value));
|
assertTrue(!map.containsValue(value), "Empty map must not contain value");
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -133,7 +131,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
@Override
|
@Override
|
||||||
public void testMapEquals() {
|
public void testMapEquals() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue("Empty maps unequal.", map.equals(confirmed));
|
assertTrue(map.equals(confirmed), "Empty maps unequal.");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,8 +139,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
@Override
|
@Override
|
||||||
public void testMapHashCode() {
|
public void testMapHashCode() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue("Empty maps have different hashCodes.",
|
assertTrue(map.hashCode() == confirmed.hashCode(), "Empty maps have different hashCodes.");
|
||||||
map.hashCode() == confirmed.hashCode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -153,7 +150,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
Object[] keys = getSampleKeys();
|
Object[] keys = getSampleKeys();
|
||||||
|
|
||||||
for (Object key : keys) {
|
for (Object key : keys) {
|
||||||
assertTrue("Empty map.get() should return null.", map.get(key) == null);
|
assertTrue(map.get(key) == null, "Empty map.get() should return null.");
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
@@ -170,7 +167,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
Object o = map.put(keys[i], values[i]);
|
Object o = map.put(keys[i], values[i]);
|
||||||
//confirmed.put(keys[i], values[i]);
|
//confirmed.put(keys[i], values[i]);
|
||||||
verifyAll();
|
verifyAll();
|
||||||
assertTrue("First map.put should return null", o == null);
|
assertTrue(o == null, "First map.put should return null");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < keys.length; i++) {
|
for (int i = 0; i < keys.length; i++) {
|
||||||
map.put(keys[i], newValues[i]);
|
map.put(keys[i], newValues[i]);
|
||||||
@@ -183,8 +180,8 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
@Override
|
@Override
|
||||||
public void testMapToString() {
|
public void testMapToString() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertTrue("Empty map toString() should not return null",
|
assertTrue(map.toString() != null,
|
||||||
map.toString() != null);
|
"Empty map toString() should not return null");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +199,7 @@ public class NullMapTest extends MapAbstractTest {
|
|||||||
Object[] keys = getSampleKeys();
|
Object[] keys = getSampleKeys();
|
||||||
for(int i = 0; i < keys.length; i++) {
|
for(int i = 0; i < keys.length; i++) {
|
||||||
Object o = map.remove(keys[i]);
|
Object o = map.remove(keys[i]);
|
||||||
assertTrue("First map.remove should return null", o == null);
|
assertTrue(o == null, "First map.remove should return null");
|
||||||
}
|
}
|
||||||
verifyAll();
|
verifyAll();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,12 +44,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.jupiter.api.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract test class for {@link Object} methods and contracts.
|
* Abstract test class for {@link Object} methods and contracts.
|
||||||
@@ -119,7 +117,7 @@ public abstract class ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testObjectEqualsSelf() {
|
public void testObjectEqualsSelf() {
|
||||||
Object obj = makeObject();
|
Object obj = makeObject();
|
||||||
assertEquals("A Object should equal itself", obj, obj);
|
assertEquals(obj, obj, "A Object should equal itself");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -131,25 +129,24 @@ public abstract class ObjectAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testObjectHashCodeEqualsSelfHashCode() {
|
public void testObjectHashCodeEqualsSelfHashCode() {
|
||||||
Object obj = makeObject();
|
Object obj = makeObject();
|
||||||
assertEquals("hashCode should be repeatable", obj.hashCode(), obj.hashCode());
|
assertEquals(obj.hashCode(), obj.hashCode(), "hashCode should be repeatable");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testObjectHashCodeEqualsContract() {
|
public void testObjectHashCodeEqualsContract() {
|
||||||
Object obj1 = makeObject();
|
Object obj1 = makeObject();
|
||||||
if (obj1.equals(obj1)) {
|
if (obj1.equals(obj1)) {
|
||||||
assertEquals(
|
assertEquals(obj1.hashCode(), obj1.hashCode(),
|
||||||
"[1] When two objects are equal, their hashCodes should be also.",
|
"[1] When two objects are equal, their hashCodes should be also.");
|
||||||
obj1.hashCode(), obj1.hashCode());
|
|
||||||
}
|
}
|
||||||
Object obj2 = makeObject();
|
Object obj2 = makeObject();
|
||||||
if (obj1.equals(obj2)) {
|
if (obj1.equals(obj2)) {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
"[2] When two objects are equal, their hashCodes should be also.",
|
obj1.hashCode(), obj2.hashCode(),
|
||||||
obj1.hashCode(), obj2.hashCode());
|
"[2] When two objects are equal, their hashCodes should be also.");
|
||||||
assertTrue(
|
assertTrue(
|
||||||
"When obj1.equals(obj2) is true, then obj2.equals(obj1) should also be true",
|
obj2.equals(obj1),
|
||||||
obj2.equals(obj1));
|
"When obj1.equals(obj2) is true, then obj2.equals(obj1) should also be true");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +163,7 @@ public abstract class ObjectAbstractTest {
|
|||||||
Object dest = in.readObject();
|
Object dest = in.readObject();
|
||||||
in.close();
|
in.close();
|
||||||
if (isEqualsCheckable()) {
|
if (isEqualsCheckable()) {
|
||||||
assertEquals("obj != deserialize(serialize(obj))", obj, dest);
|
assertEquals(obj, dest, "obj != deserialize(serialize(obj))");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,8 +196,8 @@ public abstract class ObjectAbstractTest {
|
|||||||
if (object instanceof Serializable) {
|
if (object instanceof Serializable) {
|
||||||
String name = getCanonicalEmptyCollectionName(object);
|
String name = getCanonicalEmptyCollectionName(object);
|
||||||
assertTrue(
|
assertTrue(
|
||||||
"Canonical empty collection (" + name + ") is not in CVS",
|
new File(name).exists(),
|
||||||
new File(name).exists());
|
"Canonical empty collection (" + name + ") is not in CVS");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,8 +213,8 @@ public abstract class ObjectAbstractTest {
|
|||||||
if (object instanceof Serializable) {
|
if (object instanceof Serializable) {
|
||||||
String name = getCanonicalFullCollectionName(object);
|
String name = getCanonicalFullCollectionName(object);
|
||||||
assertTrue(
|
assertTrue(
|
||||||
"Canonical full collection (" + name + ") is not in CVS",
|
new File(name).exists(),
|
||||||
new File(name).exists());
|
"Canonical full collection (" + name + ") is not in CVS");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,12 +44,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.jupiter.api.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract test class for {@link Set} methods and contracts.
|
* Abstract test class for {@link Set} methods and contracts.
|
||||||
@@ -79,14 +77,12 @@ public abstract class SetAbstractTest extends CollectionAbstractTest {
|
|||||||
public void verifyAll() {
|
public void verifyAll() {
|
||||||
super.verifyAll();
|
super.verifyAll();
|
||||||
|
|
||||||
assertEquals("Sets should be equal", confirmed, collection);
|
assertEquals(confirmed, collection, "Sets should be equal");
|
||||||
assertEquals("Sets should have equal hashCodes",
|
assertEquals(confirmed.hashCode(), collection.hashCode(), "Sets should have equal hashCodes");
|
||||||
confirmed.hashCode(), collection.hashCode());
|
|
||||||
Collection set = makeConfirmedCollection();
|
Collection set = makeConfirmedCollection();
|
||||||
Iterator iterator = collection.iterator();
|
Iterator iterator = collection.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
assertTrue("Set.iterator should only return unique elements",
|
assertTrue(set.add(iterator.next()), "Set.iterator should only return unique elements");
|
||||||
set.add(iterator.next()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,23 +176,20 @@ public abstract class SetAbstractTest extends CollectionAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSetEquals() {
|
public void testSetEquals() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals("Empty sets should be equal",
|
assertEquals(getSet(), getConfirmedSet(), "Empty sets should be equal");
|
||||||
getSet(), getConfirmedSet());
|
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
Collection set2 = makeConfirmedCollection();
|
Collection set2 = makeConfirmedCollection();
|
||||||
set2.add("foo");
|
set2.add("foo");
|
||||||
assertTrue("Empty set shouldn't equal nonempty set",
|
assertTrue(!getSet().equals(set2), "Empty set shouldn't equal nonempty set");
|
||||||
!getSet().equals(set2));
|
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertEquals("Full sets should be equal", getSet(), getConfirmedSet());
|
assertEquals(getSet(), getConfirmedSet(), "Full sets should be equal");
|
||||||
verifyAll();
|
verifyAll();
|
||||||
|
|
||||||
set2.clear();
|
set2.clear();
|
||||||
set2.addAll(Arrays.asList(getOtherElements()));
|
set2.addAll(Arrays.asList(getOtherElements()));
|
||||||
assertTrue("Sets with different contents shouldn't be equal",
|
assertTrue(!getSet().equals(set2), "Sets with different contents shouldn't be equal");
|
||||||
!getSet().equals(set2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -205,11 +198,9 @@ public abstract class SetAbstractTest extends CollectionAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSetHashCode() {
|
public void testSetHashCode() {
|
||||||
resetEmpty();
|
resetEmpty();
|
||||||
assertEquals("Empty sets have equal hashCodes",
|
assertEquals(getSet().hashCode(), getConfirmedSet().hashCode(), "Empty sets have equal hashCodes");
|
||||||
getSet().hashCode(), getConfirmedSet().hashCode());
|
|
||||||
|
|
||||||
resetFull();
|
resetFull();
|
||||||
assertEquals("Equal sets have equal hashCodes",
|
assertEquals(getSet().hashCode(), getConfirmedSet().hashCode(), "Equal sets have equal hashCodes");
|
||||||
getSet().hashCode(), getConfirmedSet().hashCode());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-32
@@ -30,12 +30,10 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StringTokenIteratorTestCase
|
* StringTokenIteratorTestCase
|
||||||
@@ -56,88 +54,88 @@ public class StringTokenIteratorTest extends TokenIteratorAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testEmptyDelimiter() {
|
public void testEmptyDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("", "");
|
Iterator iterator = createTokenIterator("", "");
|
||||||
assertFalse("Empty string has elements", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "Empty string has elements");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleToken() {
|
public void testSingleToken() {
|
||||||
Iterator iterator = createTokenIterator("A");
|
Iterator iterator = createTokenIterator("A");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleTokenEmptyDelimiter() {
|
public void testSingleTokenEmptyDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A", "");
|
Iterator iterator = createTokenIterator("A", "");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleTokenSingleDelimiter() {
|
public void testSingleTokenSingleDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A", ",");
|
Iterator iterator = createTokenIterator("A", ",");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleSeparatorDefaultDelimiter() {
|
public void testSingleSeparatorDefaultDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A B C D");
|
Iterator iterator = createTokenIterator("A B C D");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleSeparator() {
|
public void testSingleSeparator() {
|
||||||
Iterator iterator = createTokenIterator("A,B,C", ",");
|
Iterator iterator = createTokenIterator("A,B,C", ",");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleSeparatorDefaultDelimiter() {
|
public void testMultipleSeparatorDefaultDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A B C\nD\t\t \nE");
|
Iterator iterator = createTokenIterator("A B C\nD\t\t \nE");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("E", iterator.next());
|
assertEquals("E", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleSeparator() {
|
public void testMultipleSeparator() {
|
||||||
Iterator iterator = createTokenIterator("A,B,;,C...D, ., ,E", " ,.;:");
|
Iterator iterator = createTokenIterator("A,B,;,C...D, ., ,E", " ,.;:");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("E", iterator.next());
|
assertEquals("E", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,12 +30,10 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
/**
|
/**
|
||||||
* TimeoutMapTest
|
* TimeoutMapTest
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -541,7 +539,7 @@ public class TimeoutMapTest extends MapAbstractTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("Elements expired too early, test did not run as expected.", count > 0);
|
assertTrue(count > 0, "Elements expired too early, test did not run as expected.");
|
||||||
//assertEquals("Elements did not expire as expected.", 1, count);
|
//assertEquals("Elements did not expire as expected.", 1, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +571,7 @@ public class TimeoutMapTest extends MapAbstractTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("Elements expired too early, test did not run as expected.", count > 0);
|
assertTrue(count > 0, "Elements expired too early, test did not run as expected.");
|
||||||
//assertEquals("Elements did not expire as expected.", 1, count);
|
//assertEquals("Elements did not expire as expected.", 1, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +611,7 @@ public class TimeoutMapTest extends MapAbstractTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("Elements expired too early, test did not run as expected.", count > 0);
|
assertTrue(count > 0, "Elements expired too early, test did not run as expected.");
|
||||||
//assertEquals("Elements did not expire as expected.", 1, count);
|
//assertEquals("Elements did not expire as expected.", 1, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,7 +628,7 @@ public class TimeoutMapTest extends MapAbstractTest {
|
|||||||
Object removedKey = null;
|
Object removedKey = null;
|
||||||
Object otherKey = null;
|
Object otherKey = null;
|
||||||
Iterator iterator = map.entrySet().iterator();
|
Iterator iterator = map.entrySet().iterator();
|
||||||
assertTrue("Iterator was empty", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "Iterator was empty");
|
||||||
try {
|
try {
|
||||||
Map.Entry entry = (Map.Entry) iterator.next();
|
Map.Entry entry = (Map.Entry) iterator.next();
|
||||||
assertNotNull(entry);
|
assertNotNull(entry);
|
||||||
@@ -648,8 +646,8 @@ public class TimeoutMapTest extends MapAbstractTest {
|
|||||||
fail("Elements expired between Interator.hasNext() and Iterator.remove()");
|
fail("Elements expired between Interator.hasNext() and Iterator.remove()");
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue("Wrong entry removed, keySet().iterator() is broken.", !map.containsKey(removedKey));
|
assertTrue(!map.containsKey(removedKey), "Wrong entry removed, keySet().iterator() is broken.");
|
||||||
assertTrue("Wrong entry removed, keySet().iterator() is broken.", map.containsKey(otherKey));
|
assertTrue(map.containsKey(otherKey), "Wrong entry removed, keySet().iterator() is broken.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-5
@@ -30,12 +30,10 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util;
|
package com.twelvemonkeys.util;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import org.junit.jupiter.api.*;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TokenIteratorAbstractTestCase
|
* TokenIteratorAbstractTestCase
|
||||||
@@ -80,7 +78,7 @@ public abstract class TokenIteratorAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testEmptyString() {
|
public void testEmptyString() {
|
||||||
Iterator iterator = createTokenIterator("");
|
Iterator iterator = createTokenIterator("");
|
||||||
assertFalse("Empty string has elements", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "Empty string has elements");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util.convert;
|
package com.twelvemonkeys.util.convert;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConverterTest
|
* ConverterTest
|
||||||
@@ -43,7 +43,7 @@ import org.junit.Test;
|
|||||||
*/
|
*/
|
||||||
public class ConverterTest {
|
public class ConverterTest {
|
||||||
|
|
||||||
@Ignore("Not implemented")
|
@Disabled("Not implemented")
|
||||||
@Test
|
@Test
|
||||||
public void testMe() {
|
public void testMe() {
|
||||||
// TODO: Implement tests
|
// TODO: Implement tests
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,7 @@
|
|||||||
package com.twelvemonkeys.util.convert;
|
package com.twelvemonkeys.util.convert;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.DateUtil;
|
import com.twelvemonkeys.lang.DateUtil;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|||||||
+4
-4
@@ -31,13 +31,13 @@
|
|||||||
package com.twelvemonkeys.util.convert;
|
package com.twelvemonkeys.util.convert;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.Validate;
|
import com.twelvemonkeys.lang.Validate;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DefaultConverterTest
|
* DefaultConverterTest
|
||||||
@@ -138,7 +138,7 @@ public class DefaultConverterTest extends PropertyConverterAbstractTest {
|
|||||||
assertEquals(-2.3456, (Double) converter.toObject("-2.3456", Double.TYPE, null), 0);
|
assertEquals(-2.3456, (Double) converter.toObject("-2.3456", Double.TYPE, null), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("Known issue. Why would anyone do something like this?")
|
@Disabled("Known issue. Why would anyone do something like this?")
|
||||||
@Test
|
@Test
|
||||||
public void testConvertCharPrimitive() {
|
public void testConvertCharPrimitive() {
|
||||||
PropertyConverter converter = makePropertyConverter();
|
PropertyConverter converter = makePropertyConverter();
|
||||||
|
|||||||
+16
-16
@@ -32,11 +32,11 @@ package com.twelvemonkeys.util.convert;
|
|||||||
|
|
||||||
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
import com.twelvemonkeys.lang.ObjectAbstractTest;
|
||||||
import com.twelvemonkeys.lang.Validate;
|
import com.twelvemonkeys.lang.Validate;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PropertyConverterAbstractTest
|
* PropertyConverterAbstractTest
|
||||||
@@ -66,26 +66,26 @@ public abstract class PropertyConverterAbstractTest extends ObjectAbstractTest {
|
|||||||
try {
|
try {
|
||||||
obj = converter.toObject(test.original(), test.type(), test.format());
|
obj = converter.toObject(test.original(), test.type(), test.format());
|
||||||
|
|
||||||
assertEquals(String.format("'%s' converted to incorrect type", test.original()), test.type(), obj.getClass());
|
assertEquals(test.type(), obj.getClass(), String.format("'%s' converted to incorrect type", test.original()));
|
||||||
if (test.type().isArray()) {
|
if (test.type().isArray()) {
|
||||||
assertArrayEquals0(String.format("'%s' not converted", test.original()), test.value(), obj);
|
assertArrayEquals0(String.format("'%s' not converted", test.original()), test.value(), obj);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals(String.format("'%s' not converted", test.original()), test.value(), obj);
|
assertEquals(test.value(), obj, String.format("'%s' not converted", test.original()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String result = converter.toString(test.value(), test.format());
|
String result = converter.toString(test.value(), test.format());
|
||||||
|
|
||||||
assertEquals(String.format("'%s' does not match", test.converted()), test.converted(), result);
|
assertEquals(test.converted(), result, String.format("'%s' does not match", test.converted()));
|
||||||
|
|
||||||
obj = converter.toObject(result, test.type(), test.format());
|
obj = converter.toObject(result, test.type(), test.format());
|
||||||
assertEquals(String.format("'%s' converted to incorrect type", test.original()), test.type(), obj.getClass());
|
assertEquals(test.type(), obj.getClass(), String.format("'%s' converted to incorrect type", test.original()));
|
||||||
|
|
||||||
if (test.type().isArray()) {
|
if (test.type().isArray()) {
|
||||||
assertArrayEquals0(String.format("'%s' did not survive round trip conversion", test.original()), test.value(), obj);
|
assertArrayEquals0(String.format("'%s' did not survive round trip conversion", test.original()), test.value(), obj);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertEquals(String.format("'%s' did not survive round trip conversion", test.original()), test.value(), obj);
|
assertEquals(test.value(), obj, String.format("'%s' did not survive round trip conversion", test.original()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ConversionException e) {
|
catch (ConversionException e) {
|
||||||
@@ -98,35 +98,35 @@ public abstract class PropertyConverterAbstractTest extends ObjectAbstractTest {
|
|||||||
Class<?> componentType = left.getClass().getComponentType();
|
Class<?> componentType = left.getClass().getComponentType();
|
||||||
if (componentType.isPrimitive()) {
|
if (componentType.isPrimitive()) {
|
||||||
if (int.class == componentType) {
|
if (int.class == componentType) {
|
||||||
assertArrayEquals(message, (int[]) left, (int[]) right);
|
assertArrayEquals((int[]) left, (int[]) right, message);
|
||||||
}
|
}
|
||||||
else if (short.class == componentType) {
|
else if (short.class == componentType) {
|
||||||
assertArrayEquals(message, (short[]) left, (short[]) right);
|
assertArrayEquals((short[]) left, (short[]) right, message);
|
||||||
}
|
}
|
||||||
else if (long.class == componentType) {
|
else if (long.class == componentType) {
|
||||||
assertArrayEquals(message, (long[]) left, (long[]) right);
|
assertArrayEquals((long[]) left, (long[]) right, message);
|
||||||
}
|
}
|
||||||
else if (float.class == componentType) {
|
else if (float.class == componentType) {
|
||||||
assertArrayEquals(message, (float[]) left, (float[]) right, 0f);
|
assertArrayEquals((float[]) left, (float[]) right, 0f, message);
|
||||||
}
|
}
|
||||||
else if (double.class == componentType) {
|
else if (double.class == componentType) {
|
||||||
assertArrayEquals(message, (double[]) left, (double[]) right, 0d);
|
assertArrayEquals((double[]) left, (double[]) right, 0d, message);
|
||||||
}
|
}
|
||||||
else if (boolean.class == componentType) {
|
else if (boolean.class == componentType) {
|
||||||
assertTrue(message, Arrays.equals((boolean[]) left, (boolean[]) right));
|
assertTrue(Arrays.equals((boolean[]) left, (boolean[]) right), message);
|
||||||
}
|
}
|
||||||
else if (byte.class == componentType) {
|
else if (byte.class == componentType) {
|
||||||
assertArrayEquals(message, (byte[]) left, (byte[]) right);
|
assertArrayEquals((byte[]) left, (byte[]) right, message);
|
||||||
}
|
}
|
||||||
else if (char.class == componentType) {
|
else if (char.class == componentType) {
|
||||||
assertArrayEquals(message, (char[]) left, (char[]) right);
|
assertArrayEquals((char[]) left, (char[]) right, message);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fail(String.format("Unknown primitive type: %s", componentType));
|
fail(String.format("Unknown primitive type: %s", componentType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertArrayEquals(message, (Object[]) left, (Object[]) right);
|
assertArrayEquals((Object[]) left, (Object[]) right, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-28
@@ -32,12 +32,11 @@ package com.twelvemonkeys.util.regex;
|
|||||||
|
|
||||||
import com.twelvemonkeys.util.TokenIterator;
|
import com.twelvemonkeys.util.TokenIterator;
|
||||||
import com.twelvemonkeys.util.TokenIteratorAbstractTest;
|
import com.twelvemonkeys.util.TokenIteratorAbstractTest;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
/**
|
/**
|
||||||
* StringTokenIteratorTestCase
|
* StringTokenIteratorTestCase
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -68,9 +67,9 @@ public class RegExTokenIteratorTest extends TokenIteratorAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSingleToken() {
|
public void testSingleToken() {
|
||||||
Iterator iterator = createTokenIterator("A");
|
Iterator iterator = createTokenIterator("A");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -87,67 +86,67 @@ public class RegExTokenIteratorTest extends TokenIteratorAbstractTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSingleTokenSingleDelimiter() {
|
public void testSingleTokenSingleDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A", "[^,]+");
|
Iterator iterator = createTokenIterator("A", "[^,]+");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleSeparatorDefaultDelimiter() {
|
public void testSingleSeparatorDefaultDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A B C D");
|
Iterator iterator = createTokenIterator("A B C D");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleSeparator() {
|
public void testSingleSeparator() {
|
||||||
Iterator iterator = createTokenIterator("A,B,C", "[^,]+");
|
Iterator iterator = createTokenIterator("A,B,C", "[^,]+");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleSeparatorDefaultDelimiter() {
|
public void testMultipleSeparatorDefaultDelimiter() {
|
||||||
Iterator iterator = createTokenIterator("A B C\nD\t\t \nE");
|
Iterator iterator = createTokenIterator("A B C\nD\t\t \nE");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("A", iterator.next());
|
assertEquals("A", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("E", iterator.next());
|
assertEquals("E", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultipleSeparator() {
|
public void testMultipleSeparator() {
|
||||||
Iterator iterator = createTokenIterator("A,B,;,C...D, ., ,E", "[^ ,.;:]+");
|
Iterator iterator = createTokenIterator("A,B,;,C...D, ., ,E", "[^ ,.;:]+");
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
Object o = iterator.next();
|
Object o = iterator.next();
|
||||||
assertEquals("A", o);
|
assertEquals("A", o);
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("B", iterator.next());
|
assertEquals("B", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("C", iterator.next());
|
assertEquals("C", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("D", iterator.next());
|
assertEquals("D", iterator.next());
|
||||||
assertTrue("String has no elements", iterator.hasNext());
|
assertTrue(iterator.hasNext(), "String has no elements");
|
||||||
assertEquals("E", iterator.next());
|
assertEquals("E", iterator.next());
|
||||||
assertFalse("String has more than one element", iterator.hasNext());
|
assertFalse(iterator.hasNext(), "String has more than one element");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-8
@@ -30,12 +30,13 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.util.service;
|
package com.twelvemonkeys.util.service;
|
||||||
|
|
||||||
|
import com.twelvemonkeys.lang.Validate;
|
||||||
import com.twelvemonkeys.util.CollectionUtil;
|
import com.twelvemonkeys.util.CollectionUtil;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ServiceRegistryTest
|
* ServiceRegistryTest
|
||||||
@@ -48,9 +49,11 @@ public class ServiceRegistryTest {
|
|||||||
|
|
||||||
private final TestRegistry registry = new TestRegistry();
|
private final TestRegistry registry = new TestRegistry();
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test
|
||||||
public void testCreateNull() {
|
public void testCreateNull() {
|
||||||
new ServiceRegistry(null);
|
assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
new ServiceRegistry(null);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -64,11 +67,12 @@ public class ServiceRegistryTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = ServiceConfigurationError.class)
|
@Test
|
||||||
public void testCreateBadConfig() {
|
public void testCreateBadConfig() {
|
||||||
@SuppressWarnings("unchecked")
|
assertThrows(ServiceConfigurationError.class, () -> {
|
||||||
ServiceRegistry registry = new ServiceRegistry(Arrays.asList(BadSPI.class).iterator());
|
ServiceRegistry registry = new ServiceRegistry(Arrays.asList(BadSPI.class).iterator());
|
||||||
registry.registerApplicationClasspathSPIs();
|
registry.registerApplicationClasspathSPIs();
|
||||||
|
});
|
||||||
|
|
||||||
// DONE: Test non-class
|
// DONE: Test non-class
|
||||||
|
|
||||||
|
|||||||
+15
-4
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.7.0</version>
|
<version>3.13.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
@@ -20,6 +20,10 @@
|
|||||||
<module>common-image</module>
|
<module>common-image</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<junit.jupiter.version>5.14.3</junit.jupiter.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -43,11 +47,18 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
<version>4.13.1</version>
|
<version>${junit.jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
|
<version>${junit.jupiter.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
+25
-6
@@ -4,15 +4,20 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys</groupId>
|
<groupId>com.twelvemonkeys</groupId>
|
||||||
<artifactId>twelvemonkeys</artifactId>
|
<artifactId>twelvemonkeys</artifactId>
|
||||||
<version>3.7.0</version>
|
<version>3.13.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<groupId>com.twelvemonkeys.contrib</groupId>
|
<groupId>com.twelvemonkeys.contrib</groupId>
|
||||||
<artifactId>contrib</artifactId>
|
<artifactId>contrib</artifactId>
|
||||||
<name>TwelveMonkeys :: Contrib</name>
|
<name>TwelveMonkeys :: Contrib</name>
|
||||||
<description>
|
<description>
|
||||||
Contributions to TwelveMonkeys which are not matching into the ImageIO plug-ins.
|
Contributions to TwelveMonkeys and code that doesn't fit anywhere else.
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<junit.jupiter.version>5.14.3</junit.jupiter.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.twelvemonkeys.common</groupId>
|
<groupId>com.twelvemonkeys.common</groupId>
|
||||||
@@ -61,12 +66,26 @@
|
|||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
<version>4.13.1</version>
|
<version>${junit.jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>${junit.jupiter.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -30,9 +30,14 @@ import static com.twelvemonkeys.contrib.tiff.TIFFUtilities.applyOrientation;
|
|||||||
public class EXIFUtilities {
|
public class EXIFUtilities {
|
||||||
/**
|
/**
|
||||||
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
|
* The returned {@code IIOImage} will always contain an image and no raster, and
|
||||||
|
* the {@code RenderedImage} may be safely cast to a {@code BufferedImage}.
|
||||||
|
*
|
||||||
|
* If no registered {@code ImageReader} claims to be able to read the input, {@code null} is returned.
|
||||||
*
|
*
|
||||||
* @param input a {@code URL}
|
* @param input a {@code URL}
|
||||||
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info, or
|
||||||
|
* {@code null}.
|
||||||
* @throws IOException if an error occurs during reading.
|
* @throws IOException if an error occurs during reading.
|
||||||
*/
|
*/
|
||||||
public static IIOImage readWithOrientation(final URL input) throws IOException {
|
public static IIOImage readWithOrientation(final URL input) throws IOException {
|
||||||
@@ -43,9 +48,14 @@ public class EXIFUtilities {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
|
* The returned {@code IIOImage} will always contain an image and no raster, and
|
||||||
|
* the {@code RenderedImage} may be safely cast to a {@code BufferedImage}.
|
||||||
|
*
|
||||||
|
* If no registered {@code ImageReader} claims to be able to read the input, {@code null} is returned.
|
||||||
*
|
*
|
||||||
* @param input an {@code InputStream}
|
* @param input an {@code InputStream}
|
||||||
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info, or
|
||||||
|
* {@code null}.
|
||||||
* @throws IOException if an error occurs during reading.
|
* @throws IOException if an error occurs during reading.
|
||||||
*/
|
*/
|
||||||
public static IIOImage readWithOrientation(final InputStream input) throws IOException {
|
public static IIOImage readWithOrientation(final InputStream input) throws IOException {
|
||||||
@@ -56,9 +66,14 @@ public class EXIFUtilities {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
|
* The returned {@code IIOImage} will always contain an image and no raster, and
|
||||||
|
* the {@code RenderedImage} may be safely cast to a {@code BufferedImage}.
|
||||||
|
*
|
||||||
|
* If no registered {@code ImageReader} claims to be able to read the input, {@code null} is returned.
|
||||||
*
|
*
|
||||||
* @param input a {@code File}
|
* @param input a {@code File}
|
||||||
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info or
|
||||||
|
* {@code null}.
|
||||||
* @throws IOException if an error occurs during reading.
|
* @throws IOException if an error occurs during reading.
|
||||||
*/
|
*/
|
||||||
public static IIOImage readWithOrientation(final File input) throws IOException {
|
public static IIOImage readWithOrientation(final File input) throws IOException {
|
||||||
@@ -69,9 +84,14 @@ public class EXIFUtilities {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
* Reads image and metadata, applies Exif orientation to image, and returns everything as an {@code IIOImage}.
|
||||||
|
* The returned {@code IIOImage} will always contain an image and no raster, and
|
||||||
|
* the {@code RenderedImage} may be safely cast to a {@code BufferedImage}.
|
||||||
|
*
|
||||||
|
* If no registered {@code ImageReader} claims to be able to read the input, {@code null} is returned.
|
||||||
*
|
*
|
||||||
* @param input an {@code ImageInputStream}
|
* @param input an {@code ImageInputStream}
|
||||||
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info.
|
* @return an {@code IIOImage} containing the correctly oriented image and metadata including rotation info, or
|
||||||
|
* {@code null}.
|
||||||
* @throws IOException if an error occurs during reading.
|
* @throws IOException if an error occurs during reading.
|
||||||
*/
|
*/
|
||||||
public static IIOImage readWithOrientation(final ImageInputStream input) throws IOException {
|
public static IIOImage readWithOrientation(final ImageInputStream input) throws IOException {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.twelvemonkeys.contrib.exif;
|
package com.twelvemonkeys.contrib.exif;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static com.twelvemonkeys.contrib.exif.Orientation.*;
|
import static com.twelvemonkeys.contrib.exif.Orientation.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OrientationTest.
|
* OrientationTest.
|
||||||
|
|||||||
@@ -31,10 +31,9 @@
|
|||||||
package com.twelvemonkeys.contrib.tiff;
|
package com.twelvemonkeys.contrib.tiff;
|
||||||
|
|
||||||
import com.twelvemonkeys.contrib.tiff.TIFFUtilities.TIFFExtension;
|
import com.twelvemonkeys.contrib.tiff.TIFFUtilities.TIFFExtension;
|
||||||
import com.twelvemonkeys.imageio.plugins.tiff.TIFFMedataFormat;
|
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadataFormat;
|
||||||
import com.twelvemonkeys.io.FileUtil;
|
import com.twelvemonkeys.io.FileUtil;
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
@@ -53,6 +52,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TIFFUtilitiesTest
|
* TIFFUtilitiesTest
|
||||||
*
|
*
|
||||||
@@ -94,7 +96,7 @@ public class TIFFUtilitiesTest {
|
|||||||
ImageInputStream iis = ImageIO.createImageInputStream(output);
|
ImageInputStream iis = ImageIO.createImageInputStream(output);
|
||||||
ImageReader reader = ImageIO.getImageReaders(iis).next();
|
ImageReader reader = ImageIO.getImageReaders(iis).next();
|
||||||
reader.setInput(iis);
|
reader.setInput(iis);
|
||||||
Assert.assertEquals(3, reader.getNumImages(true));
|
assertEquals(3, reader.getNumImages(true));
|
||||||
|
|
||||||
iis.close();
|
iis.close();
|
||||||
output.delete();
|
output.delete();
|
||||||
@@ -118,11 +120,11 @@ public class TIFFUtilitiesTest {
|
|||||||
ImageReader reader = ImageIO.getImageReadersByFormatName("TIF").next();
|
ImageReader reader = ImageIO.getImageReadersByFormatName("TIF").next();
|
||||||
|
|
||||||
File[] outputFiles = outputDirectory.listFiles();
|
File[] outputFiles = outputDirectory.listFiles();
|
||||||
Assert.assertEquals(3, outputFiles.length);
|
assertEquals(3, outputFiles.length);
|
||||||
for (File outputFile : outputFiles) {
|
for (File outputFile : outputFiles) {
|
||||||
ImageInputStream iis = ImageIO.createImageInputStream(outputFile);
|
ImageInputStream iis = ImageIO.createImageInputStream(outputFile);
|
||||||
reader.setInput(iis);
|
reader.setInput(iis);
|
||||||
Assert.assertEquals(1, reader.getNumImages(true));
|
assertEquals(1, reader.getNumImages(true));
|
||||||
iis.close();
|
iis.close();
|
||||||
outputFile.delete();
|
outputFile.delete();
|
||||||
}
|
}
|
||||||
@@ -154,9 +156,9 @@ public class TIFFUtilitiesTest {
|
|||||||
reader.setInput(checkTest1);
|
reader.setInput(checkTest1);
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
Node metaData = reader.getImageMetadata(i)
|
Node metaData = reader.getImageMetadata(i)
|
||||||
.getAsTree(TIFFMedataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME);
|
.getAsTree(TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME);
|
||||||
short orientation = ((Number) expression.evaluate(metaData, XPathConstants.NUMBER)).shortValue();
|
short orientation = ((Number) expression.evaluate(metaData, XPathConstants.NUMBER)).shortValue();
|
||||||
Assert.assertEquals(orientation, TIFFExtension.ORIENTATION_RIGHTTOP);
|
assertEquals(orientation, TIFFExtension.ORIENTATION_RIGHTTOP);
|
||||||
}
|
}
|
||||||
checkTest1.close();
|
checkTest1.close();
|
||||||
|
|
||||||
@@ -171,9 +173,9 @@ public class TIFFUtilitiesTest {
|
|||||||
reader.setInput(checkTest2);
|
reader.setInput(checkTest2);
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
Node metaData = reader.getImageMetadata(i)
|
Node metaData = reader.getImageMetadata(i)
|
||||||
.getAsTree(TIFFMedataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME);
|
.getAsTree(TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME);
|
||||||
short orientation = ((Number) expression.evaluate(metaData, XPathConstants.NUMBER)).shortValue();
|
short orientation = ((Number) expression.evaluate(metaData, XPathConstants.NUMBER)).shortValue();
|
||||||
Assert.assertEquals(orientation, i == 1
|
assertEquals(orientation, i == 1
|
||||||
? TIFFExtension.ORIENTATION_BOTRIGHT
|
? TIFFExtension.ORIENTATION_BOTRIGHT
|
||||||
: TIFFExtension.ORIENTATION_RIGHTTOP);
|
: TIFFExtension.ORIENTATION_RIGHTTOP);
|
||||||
}
|
}
|
||||||
@@ -198,7 +200,7 @@ public class TIFFUtilitiesTest {
|
|||||||
byte[] original = ((DataBufferByte) image.getData().getDataBuffer()).getData();
|
byte[] original = ((DataBufferByte) image.getData().getDataBuffer()).getData();
|
||||||
byte[] rotated = ((DataBufferByte) image360.getData().getDataBuffer()).getData();
|
byte[] rotated = ((DataBufferByte) image360.getData().getDataBuffer()).getData();
|
||||||
|
|
||||||
Assert.assertArrayEquals(original, rotated);
|
assertArrayEquals(original, rotated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||||
<artifactId>imageio</artifactId>
|
<artifactId>imageio</artifactId>
|
||||||
<version>3.7.0</version>
|
<version>3.13.2-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>imageio-batik</artifactId>
|
<artifactId>imageio-batik</artifactId>
|
||||||
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
|
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.jpms.module.name>com.twelvemonkeys.imageio.batik</project.jpms.module.name>
|
<project.jpms.module.name>com.twelvemonkeys.imageio.batik</project.jpms.module.name>
|
||||||
<batik.version>1.14</batik.version>
|
<batik.version>1.19</batik.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@@ -27,12 +27,24 @@
|
|||||||
<artifactId>maven-surefire-plugin</artifactId>
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<com.twelvemonkeys.imageio.plugins.svg.allowexternalresources>
|
<com.twelvemonkeys.imageio.plugins.svg.allowExternalResources>
|
||||||
true
|
true
|
||||||
</com.twelvemonkeys.imageio.plugins.svg.allowexternalresources>
|
</com.twelvemonkeys.imageio.plugins.svg.allowExternalResources>
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Provide-Capability>
|
||||||
|
osgi.serviceloader;
|
||||||
|
osgi.serviceloader=javax.imageio.spi.ImageReaderSpi
|
||||||
|
</Provide-Capability>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
@@ -48,6 +60,13 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>2.22.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.xmlgraphics</groupId>
|
<groupId>org.apache.xmlgraphics</groupId>
|
||||||
<artifactId>batik-rasterizer-ext</artifactId>
|
<artifactId>batik-rasterizer-ext</artifactId>
|
||||||
@@ -68,13 +87,6 @@
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.xmlgraphics</groupId>
|
|
||||||
<artifactId>xmlgraphics-commons</artifactId>
|
|
||||||
<version>2.2</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.xmlgraphics</groupId>
|
<groupId>org.apache.xmlgraphics</groupId>
|
||||||
<artifactId>batik-anim</artifactId>
|
<artifactId>batik-anim</artifactId>
|
||||||
@@ -98,7 +110,7 @@
|
|||||||
<!--
|
<!--
|
||||||
There seems to be some weirdness in the
|
There seems to be some weirdness in the
|
||||||
Batik/FOP poms (Batik depends on FOP 0.20-5) that screws things up,
|
Batik/FOP poms (Batik depends on FOP 0.20-5) that screws things up,
|
||||||
making everything end up depending on Batik 1.5, not 1.6
|
making everything end up depending on Batik 1.5, not the specified version
|
||||||
-->
|
-->
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
|
|||||||
+134
-124
@@ -33,11 +33,12 @@ package com.twelvemonkeys.imageio.plugins.svg;
|
|||||||
import com.twelvemonkeys.image.ImageUtil;
|
import com.twelvemonkeys.image.ImageUtil;
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
|
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||||
import com.twelvemonkeys.lang.StringUtil;
|
import com.twelvemonkeys.lang.StringUtil;
|
||||||
|
|
||||||
import org.apache.batik.anim.dom.SVGDOMImplementation;
|
import org.apache.batik.anim.dom.SVGDOMImplementation;
|
||||||
import org.apache.batik.anim.dom.SVGOMDocument;
|
import org.apache.batik.anim.dom.SVGOMDocument;
|
||||||
import org.apache.batik.bridge.*;
|
import org.apache.batik.bridge.*;
|
||||||
import org.apache.batik.css.parser.CSSLexicalUnit;
|
|
||||||
import org.apache.batik.dom.util.DOMUtilities;
|
import org.apache.batik.dom.util.DOMUtilities;
|
||||||
import org.apache.batik.ext.awt.image.GraphicsUtil;
|
import org.apache.batik.ext.awt.image.GraphicsUtil;
|
||||||
import org.apache.batik.gvt.CanvasGraphicsNode;
|
import org.apache.batik.gvt.CanvasGraphicsNode;
|
||||||
@@ -45,11 +46,14 @@ import org.apache.batik.gvt.GraphicsNode;
|
|||||||
import org.apache.batik.gvt.renderer.ConcreteImageRendererFactory;
|
import org.apache.batik.gvt.renderer.ConcreteImageRendererFactory;
|
||||||
import org.apache.batik.gvt.renderer.ImageRenderer;
|
import org.apache.batik.gvt.renderer.ImageRenderer;
|
||||||
import org.apache.batik.gvt.renderer.ImageRendererFactory;
|
import org.apache.batik.gvt.renderer.ImageRendererFactory;
|
||||||
import org.apache.batik.transcoder.*;
|
import org.apache.batik.transcoder.SVGAbstractTranscoder;
|
||||||
|
import org.apache.batik.transcoder.TranscoderException;
|
||||||
|
import org.apache.batik.transcoder.TranscoderInput;
|
||||||
|
import org.apache.batik.transcoder.TranscoderOutput;
|
||||||
|
import org.apache.batik.transcoder.TranscodingHints;
|
||||||
import org.apache.batik.transcoder.image.ImageTranscoder;
|
import org.apache.batik.transcoder.image.ImageTranscoder;
|
||||||
import org.apache.batik.util.ParsedURL;
|
import org.apache.batik.util.ParsedURL;
|
||||||
import org.apache.batik.util.SVGConstants;
|
import org.apache.batik.util.SVGConstants;
|
||||||
import org.apache.batik.xml.LexicalUnits;
|
|
||||||
import org.w3c.dom.DOMImplementation;
|
import org.w3c.dom.DOMImplementation;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.svg.SVGSVGElement;
|
import org.w3c.dom.svg.SVGSVGElement;
|
||||||
@@ -59,10 +63,8 @@ import javax.imageio.ImageReadParam;
|
|||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.*;
|
||||||
import java.awt.geom.Dimension2D;
|
import java.awt.image.*;
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@@ -76,12 +78,13 @@ import java.util.Map;
|
|||||||
* @author Harald Kuhr
|
* @author Harald Kuhr
|
||||||
* @author Inpspired by code from the Batik Team
|
* @author Inpspired by code from the Batik Team
|
||||||
* @version $Id: $
|
* @version $Id: $
|
||||||
* @see <A href="http://www.mail-archive.com/batik-dev@xml.apache.org/msg00992.html">batik-dev</A>
|
* @see <a href="http://www.mail-archive.com/batik-dev@xml.apache.org/msg00992.html">batik-dev</a>
|
||||||
*/
|
*/
|
||||||
public class SVGImageReader extends ImageReaderBase {
|
public class SVGImageReader extends ImageReaderBase {
|
||||||
|
|
||||||
final static boolean DEFAULT_ALLOW_EXTERNAL_RESOURCES =
|
final static boolean DEFAULT_ALLOW_EXTERNAL_RESOURCES =
|
||||||
"true".equalsIgnoreCase(System.getProperty("com.twelvemonkeys.imageio.plugins.svg.allowexternalresources"));
|
"true".equalsIgnoreCase(System.getProperty("com.twelvemonkeys.imageio.plugins.svg.allowExternalResources",
|
||||||
|
System.getProperty("com.twelvemonkeys.imageio.plugins.svg.allowexternalresources")));
|
||||||
|
|
||||||
private Rasterizer rasterizer;
|
private Rasterizer rasterizer;
|
||||||
private boolean allowExternalResources = DEFAULT_ALLOW_EXTERNAL_RESOURCES;
|
private boolean allowExternalResources = DEFAULT_ALLOW_EXTERNAL_RESOURCES;
|
||||||
@@ -89,10 +92,10 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
/**
|
/**
|
||||||
* Creates an {@code SVGImageReader}.
|
* Creates an {@code SVGImageReader}.
|
||||||
*
|
*
|
||||||
* @param pProvider the provider
|
* @param provider the provider
|
||||||
*/
|
*/
|
||||||
public SVGImageReader(final ImageReaderSpi pProvider) {
|
public SVGImageReader(final ImageReaderSpi provider) {
|
||||||
super(pProvider);
|
super(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void resetMembers() {
|
protected void resetMembers() {
|
||||||
@@ -106,20 +109,20 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInput(Object pInput, boolean seekForwardOnly, boolean ignoreMetadata) {
|
public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) {
|
||||||
super.setInput(pInput, seekForwardOnly, ignoreMetadata);
|
super.setInput(input, seekForwardOnly, ignoreMetadata);
|
||||||
|
|
||||||
if (imageInput != null) {
|
if (imageInput != null) {
|
||||||
TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
|
TranscoderInput transcoderInput = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
|
||||||
rasterizer.setInput(input);
|
rasterizer.setInput(transcoderInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
|
||||||
checkBounds(pIndex);
|
checkBounds(imageIndex);
|
||||||
|
|
||||||
if (pParam instanceof SVGReadParam) {
|
if (param instanceof SVGReadParam) {
|
||||||
SVGReadParam svgParam = (SVGReadParam) pParam;
|
SVGReadParam svgParam = (SVGReadParam) param;
|
||||||
|
|
||||||
// set the external-resource-resolution preference
|
// set the external-resource-resolution preference
|
||||||
allowExternalResources = svgParam.isAllowExternalResources();
|
allowExternalResources = svgParam.isAllowExternalResources();
|
||||||
@@ -132,43 +135,38 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
// Set ImageReadParams as hints
|
// Set ImageReadParams as hints
|
||||||
// Note: The cast to Map invokes a different method that preserves
|
// Note: The cast to Map invokes a different method that preserves
|
||||||
// unset defaults, DO NOT REMOVE!
|
// unset defaults, DO NOT REMOVE!
|
||||||
|
//noinspection rawtypes
|
||||||
rasterizer.setTranscodingHints((Map) paramsToHints(svgParam));
|
rasterizer.setTranscodingHints((Map) paramsToHints(svgParam));
|
||||||
}
|
}
|
||||||
|
|
||||||
Dimension size = null;
|
Dimension size = null;
|
||||||
if (pParam != null) {
|
if (param != null) {
|
||||||
size = pParam.getSourceRenderSize();
|
size = param.getSourceRenderSize();
|
||||||
}
|
}
|
||||||
if (size == null) {
|
if (size == null) {
|
||||||
size = new Dimension(getWidth(pIndex), getHeight(pIndex));
|
size = new Dimension(getWidth(imageIndex), getHeight(imageIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferedImage destination = getDestination(pParam, getImageTypes(pIndex), size.width, size.height);
|
BufferedImage destination = getDestination(param, getImageTypes(imageIndex), size.width, size.height);
|
||||||
|
|
||||||
// Read in the image, using the Batik Transcoder
|
// Read in the image, using the Batik Transcoder
|
||||||
|
processImageStarted(imageIndex);
|
||||||
|
|
||||||
|
BufferedImage image = rasterizer.getImage();
|
||||||
|
|
||||||
|
Graphics2D g = destination.createGraphics();
|
||||||
try {
|
try {
|
||||||
processImageStarted(pIndex);
|
g.setComposite(AlphaComposite.Src);
|
||||||
|
g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
|
||||||
BufferedImage image = rasterizer.getImage();
|
g.drawImage(image, 0, 0, null); // TODO: Dest offset?
|
||||||
|
|
||||||
Graphics2D g = destination.createGraphics();
|
|
||||||
try {
|
|
||||||
g.setComposite(AlphaComposite.Src);
|
|
||||||
g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
|
|
||||||
g.drawImage(image, 0, 0, null); // TODO: Dest offset?
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
g.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
processImageComplete();
|
|
||||||
|
|
||||||
return destination;
|
|
||||||
}
|
}
|
||||||
catch (TranscoderException e) {
|
finally {
|
||||||
Throwable cause = unwrapException(e);
|
g.dispose();
|
||||||
throw new IIOException(cause.getMessage(), cause);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processImageComplete();
|
||||||
|
|
||||||
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Throwable unwrapException(TranscoderException ex) {
|
private static Throwable unwrapException(TranscoderException ex) {
|
||||||
@@ -176,18 +174,18 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return ex.getException() != null ? ex.getException() : ex;
|
return ex.getException() != null ? ex.getException() : ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TranscodingHints paramsToHints(SVGReadParam pParam) throws IOException {
|
private TranscodingHints paramsToHints(SVGReadParam param) throws IOException {
|
||||||
TranscodingHints hints = new TranscodingHints();
|
TranscodingHints hints = new TranscodingHints();
|
||||||
// Note: We must allow generic ImageReadParams, so converting to
|
// Note: We must allow generic ImageReadParams, so converting to
|
||||||
// TanscodingHints should be done outside the SVGReadParam class.
|
// TanscodingHints should be done outside the SVGReadParam class.
|
||||||
|
|
||||||
// Set dimensions
|
// Set dimensions
|
||||||
Dimension size = pParam.getSourceRenderSize();
|
Dimension size = param.getSourceRenderSize();
|
||||||
Dimension origSize = new Dimension(getWidth(0), getHeight(0));
|
Rectangle viewBox = rasterizer.getViewBox();
|
||||||
if (size == null) {
|
if (size == null) {
|
||||||
// SVG is not a pixel based format, but we'll scale it, according to
|
// SVG is not a pixel based format, but we'll scale it, according to
|
||||||
// the subsampling for compatibility
|
// the subsampling for compatibility
|
||||||
size = getSourceRenderSizeFromSubsamping(pParam, origSize);
|
size = getSourceRenderSizeFromSubsamping(param, viewBox.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size != null) {
|
if (size != null) {
|
||||||
@@ -196,7 +194,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set area of interest
|
// Set area of interest
|
||||||
Rectangle region = pParam.getSourceRegion();
|
Rectangle region = param.getSourceRegion();
|
||||||
if (region != null) {
|
if (region != null) {
|
||||||
hints.put(ImageTranscoder.KEY_AOI, region);
|
hints.put(ImageTranscoder.KEY_AOI, region);
|
||||||
|
|
||||||
@@ -207,8 +205,8 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Need to resize here...
|
// Need to resize here...
|
||||||
double xScale = size.getWidth() / origSize.getWidth();
|
double xScale = size.getWidth() / viewBox.getWidth();
|
||||||
double yScale = size.getHeight() / origSize.getHeight();
|
double yScale = size.getHeight() / viewBox.getHeight();
|
||||||
|
|
||||||
hints.put(ImageTranscoder.KEY_WIDTH, (float) (region.getWidth() * xScale));
|
hints.put(ImageTranscoder.KEY_WIDTH, (float) (region.getWidth() * xScale));
|
||||||
hints.put(ImageTranscoder.KEY_HEIGHT, (float) (region.getHeight() * yScale));
|
hints.put(ImageTranscoder.KEY_HEIGHT, (float) (region.getHeight() * yScale));
|
||||||
@@ -216,11 +214,11 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
else if (size != null) {
|
else if (size != null) {
|
||||||
// Allow non-uniform scaling
|
// Allow non-uniform scaling
|
||||||
hints.put(ImageTranscoder.KEY_AOI, new Rectangle(origSize));
|
hints.put(ImageTranscoder.KEY_AOI, viewBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Background color
|
// Background color
|
||||||
Paint bg = pParam.getBackgroundColor();
|
Paint bg = param.getBackgroundColor();
|
||||||
if (bg != null) {
|
if (bg != null) {
|
||||||
hints.put(ImageTranscoder.KEY_BACKGROUND_COLOR, bg);
|
hints.put(ImageTranscoder.KEY_BACKGROUND_COLOR, bg);
|
||||||
}
|
}
|
||||||
@@ -228,10 +226,10 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return hints;
|
return hints;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam pParam, Dimension pOrigSize) {
|
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam param, Dimension origSize) {
|
||||||
if (pParam.getSourceXSubsampling() > 1 || pParam.getSourceYSubsampling() > 1) {
|
if (param.getSourceXSubsampling() > 1 || param.getSourceYSubsampling() > 1) {
|
||||||
return new Dimension((int) (pOrigSize.width / (float) pParam.getSourceXSubsampling()),
|
return new Dimension((int) (origSize.width / (float) param.getSourceXSubsampling()),
|
||||||
(int) (pOrigSize.height / (float) pParam.getSourceYSubsampling()));
|
(int) (origSize.height / (float) param.getSourceYSubsampling()));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -240,28 +238,19 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return new SVGReadParam();
|
return new SVGReadParam();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth(int pIndex) throws IOException {
|
public int getWidth(int imageIndex) throws IOException {
|
||||||
checkBounds(pIndex);
|
checkBounds(imageIndex);
|
||||||
try {
|
|
||||||
return rasterizer.getDefaultWidth();
|
return rasterizer.getDefaultWidth();
|
||||||
}
|
|
||||||
catch (TranscoderException e) {
|
|
||||||
throw new IIOException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getHeight(int pIndex) throws IOException {
|
public int getHeight(int imageIndex) throws IOException {
|
||||||
checkBounds(pIndex);
|
checkBounds(imageIndex);
|
||||||
try {
|
return rasterizer.getDefaultHeight();
|
||||||
return rasterizer.getDefaultHeight();
|
|
||||||
}
|
|
||||||
catch (TranscoderException e) {
|
|
||||||
throw new IIOException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
|
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) {
|
||||||
return Collections.singleton(ImageTypeSpecifier.createFromRenderedImage(rasterizer.createImage(1, 1))).iterator();
|
return Collections.singleton(ImageTypeSpecifiers.createFromRenderedImage(rasterizer.createImage(1, 1))).iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -271,12 +260,11 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
* and needs major refactoring!
|
* and needs major refactoring!
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
private class Rasterizer extends SVGAbstractTranscoder /*ImageTranscoder*/ {
|
private class Rasterizer extends SVGAbstractTranscoder {
|
||||||
|
|
||||||
private BufferedImage image;
|
private BufferedImage image;
|
||||||
private TranscoderInput transcoderInput;
|
private TranscoderInput transcoderInput;
|
||||||
private float defaultWidth;
|
private final Rectangle2D viewBox = new Rectangle2D.Float();
|
||||||
private float defaultHeight;
|
private final Dimension defaultSize = new Dimension();
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
private SVGOMDocument document;
|
private SVGOMDocument document;
|
||||||
private String uri;
|
private String uri;
|
||||||
@@ -289,7 +277,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is cheating... We don't fully transcode after all
|
// This is cheating... We don't fully transcode after all
|
||||||
protected void transcode(Document document, final String uri, final TranscoderOutput output) throws TranscoderException {
|
protected void transcode(Document document, final String uri, final TranscoderOutput output) {
|
||||||
// Sets up root, curTxf & curAoi
|
// Sets up root, curTxf & curAoi
|
||||||
// ----
|
// ----
|
||||||
if (document != null) {
|
if (document != null) {
|
||||||
@@ -337,54 +325,66 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
// ----
|
// ----
|
||||||
SVGSVGElement rootElement = svgDoc.getRootElement();
|
SVGSVGElement rootElement = svgDoc.getRootElement();
|
||||||
|
|
||||||
// get the 'width' and 'height' attributes of the SVG document
|
// Get the viewBox
|
||||||
UnitProcessor.Context uctx
|
String viewBoxStr = rootElement.getAttributeNS(null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
|
||||||
= UnitProcessor.createContext(ctx, rootElement);
|
if (viewBoxStr.length() != 0) {
|
||||||
|
float[] rect = ViewBox.parseViewBoxAttribute(rootElement, viewBoxStr, null);
|
||||||
|
viewBox.setFrame(rect[0], rect[1], rect[2], rect[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the 'width' and 'height' attributes of the SVG document
|
||||||
|
double width = 0;
|
||||||
|
double height = 0;
|
||||||
|
UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, rootElement);
|
||||||
String widthStr = rootElement.getAttributeNS(null, SVGConstants.SVG_WIDTH_ATTRIBUTE);
|
String widthStr = rootElement.getAttributeNS(null, SVGConstants.SVG_WIDTH_ATTRIBUTE);
|
||||||
String heightStr = rootElement.getAttributeNS(null, SVGConstants.SVG_HEIGHT_ATTRIBUTE);
|
String heightStr = rootElement.getAttributeNS(null, SVGConstants.SVG_HEIGHT_ATTRIBUTE);
|
||||||
if (!StringUtil.isEmpty(widthStr)) {
|
if (!StringUtil.isEmpty(widthStr)) {
|
||||||
defaultWidth = UnitProcessor.svgToUserSpace(widthStr, SVGConstants.SVG_WIDTH_ATTRIBUTE, UnitProcessor.HORIZONTAL_LENGTH, uctx);
|
width = UnitProcessor.svgToUserSpace(widthStr, SVGConstants.SVG_WIDTH_ATTRIBUTE, UnitProcessor.HORIZONTAL_LENGTH, uctx);
|
||||||
}
|
}
|
||||||
if(!StringUtil.isEmpty(heightStr)){
|
if (!StringUtil.isEmpty(heightStr)) {
|
||||||
defaultHeight = UnitProcessor.svgToUserSpace(heightStr, SVGConstants.SVG_HEIGHT_ATTRIBUTE, UnitProcessor.VERTICAL_LENGTH, uctx);
|
height = UnitProcessor.svgToUserSpace(heightStr, SVGConstants.SVG_HEIGHT_ATTRIBUTE, UnitProcessor.VERTICAL_LENGTH, uctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasWidth = defaultWidth > 0.0;
|
boolean hasWidth = width > 0.0;
|
||||||
boolean hasHeight = defaultHeight > 0.0;
|
boolean hasHeight = height > 0.0;
|
||||||
|
|
||||||
if (!hasWidth || !hasHeight) {
|
if (!hasWidth || !hasHeight) {
|
||||||
String viewBoxStr = rootElement.getAttributeNS
|
if (!viewBox.isEmpty()) {
|
||||||
(null, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE);
|
// If one dimension is given, calculate other by aspect ratio in viewBox
|
||||||
if (viewBoxStr.length() != 0) {
|
|
||||||
float[] rect = ViewBox.parseViewBoxAttribute(rootElement, viewBoxStr, null);
|
|
||||||
// if one dimension is given, calculate other by aspect ratio in viewBox
|
|
||||||
// or use viewBox if no dimension is given
|
|
||||||
if (hasWidth) {
|
if (hasWidth) {
|
||||||
defaultHeight = defaultWidth * rect[3] / rect[2];
|
height = width * viewBox.getHeight() / viewBox.getWidth();
|
||||||
}
|
}
|
||||||
else if (hasHeight) {
|
else if (hasHeight) {
|
||||||
defaultWidth = defaultHeight * rect[2] / rect[3];
|
width = height * viewBox.getWidth() / viewBox.getHeight();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
defaultWidth = rect[2];
|
// ...or use viewBox if no dimension is given
|
||||||
defaultHeight = rect[3];
|
width = viewBox.getWidth();
|
||||||
|
height = viewBox.getHeight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// No viewBox, just assume square size
|
||||||
if (hasHeight) {
|
if (hasHeight) {
|
||||||
defaultWidth = defaultHeight;
|
width = height;
|
||||||
}
|
}
|
||||||
else if (hasWidth) {
|
else if (hasWidth) {
|
||||||
defaultHeight = defaultWidth;
|
height = width;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// fallback to batik default sizes
|
// ...or finally fall back to Batik default sizes
|
||||||
defaultWidth = 400;
|
width = 400;
|
||||||
defaultHeight = 400;
|
height = 400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We now have a size, in the rare case we don't have a viewBox; set it to this size
|
||||||
|
defaultSize.setSize(width, height);
|
||||||
|
if (viewBox.isEmpty()) {
|
||||||
|
viewBox.setRect(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
// Hack to work around exception above
|
// Hack to work around exception above
|
||||||
if (root != null) {
|
if (root != null) {
|
||||||
gvtRoot = root;
|
gvtRoot = root;
|
||||||
@@ -397,7 +397,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
ctx = null;
|
ctx = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferedImage readImage() throws TranscoderException {
|
private BufferedImage readImage() throws IOException {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
@@ -422,7 +422,8 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gvtRoot == null) {
|
if (gvtRoot == null) {
|
||||||
throw exception;
|
Throwable cause = unwrapException(exception);
|
||||||
|
throw new IIOException(cause.getMessage(), cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx = context;
|
ctx = context;
|
||||||
@@ -440,7 +441,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
setImageSize(defaultWidth, defaultHeight);
|
setImageSize(defaultSize.width, defaultSize.height);
|
||||||
|
|
||||||
if (abortRequested()) {
|
if (abortRequested()) {
|
||||||
processReadAborted();
|
processReadAborted();
|
||||||
@@ -454,18 +455,17 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Px = ViewBox.getViewTransform(ref, root, width, height, null);
|
Px = ViewBox.getViewTransform(ref, root, width, height, null);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (BridgeException ex) {
|
catch (BridgeException ex) {
|
||||||
throw new TranscoderException(ex);
|
throw new IIOException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Px.isIdentity() && (width != defaultWidth || height != defaultHeight)) {
|
if (Px.isIdentity() && (width != defaultSize.width || height != defaultSize.height)) {
|
||||||
// The document has no viewBox, we need to resize it by hand.
|
// The document has no viewBox, we need to resize it by hand.
|
||||||
// we want to keep the document size ratio
|
// we want to keep the document size ratio
|
||||||
float xscale, yscale;
|
float xscale, yscale;
|
||||||
xscale = width / defaultWidth;
|
xscale = width / defaultSize.width;
|
||||||
yscale = height / defaultHeight;
|
yscale = height / defaultSize.height;
|
||||||
float scale = Math.min(xscale, yscale);
|
float scale = Math.min(xscale, yscale);
|
||||||
Px = AffineTransform.getScaleInstance(scale, scale);
|
Px = AffineTransform.getScaleInstance(scale, scale);
|
||||||
}
|
}
|
||||||
@@ -515,7 +515,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (BridgeException ex) {
|
catch (BridgeException ex) {
|
||||||
throw new TranscoderException(ex);
|
throw new IIOException(ex.getMessage(), ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.root = gvtRoot;
|
this.root = gvtRoot;
|
||||||
@@ -584,9 +584,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
TranscoderException exception = new TranscoderException(ex.getMessage());
|
throw new IIOException(ex.getMessage(), ex);
|
||||||
exception.initCause(ex);
|
|
||||||
throw exception;
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
@@ -595,7 +593,7 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void init() throws TranscoderException {
|
private synchronized void init() throws IIOException {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
if (transcoderInput == null) {
|
if (transcoderInput == null) {
|
||||||
throw new IllegalStateException("input == null");
|
throw new IllegalStateException("input == null");
|
||||||
@@ -603,11 +601,18 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
super.transcode(transcoderInput, null);
|
try {
|
||||||
|
super.addTranscodingHint(SVGAbstractTranscoder.KEY_ALLOW_EXTERNAL_RESOURCES, allowExternalResources);
|
||||||
|
super.transcode(transcoderInput, null);
|
||||||
|
}
|
||||||
|
catch (TranscoderException e) {
|
||||||
|
Throwable cause = unwrapException(e);
|
||||||
|
throw new IIOException(cause.getMessage(), cause);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BufferedImage getImage() throws TranscoderException {
|
private BufferedImage getImage() throws IOException {
|
||||||
if (image == null) {
|
if (image == null) {
|
||||||
image = readImage();
|
image = readImage();
|
||||||
}
|
}
|
||||||
@@ -615,18 +620,23 @@ public class SVGImageReader extends ImageReaderBase {
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getDefaultWidth() throws TranscoderException {
|
int getDefaultWidth() throws IOException {
|
||||||
init();
|
init();
|
||||||
return (int) Math.ceil(defaultWidth);
|
return defaultSize.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getDefaultHeight() throws TranscoderException {
|
int getDefaultHeight() throws IOException {
|
||||||
init();
|
init();
|
||||||
return (int) Math.ceil(defaultHeight);
|
return defaultSize.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInput(final TranscoderInput pInput) {
|
Rectangle getViewBox() throws IOException {
|
||||||
transcoderInput = pInput;
|
init();
|
||||||
|
return viewBox.getBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setInput(final TranscoderInput input) {
|
||||||
|
transcoderInput = input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+60
-15
@@ -36,9 +36,11 @@ import com.twelvemonkeys.lang.SystemUtil;
|
|||||||
import javax.imageio.ImageReader;
|
import javax.imageio.ImageReader;
|
||||||
import javax.imageio.spi.ServiceRegistry;
|
import javax.imageio.spi.ServiceRegistry;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import static com.twelvemonkeys.imageio.util.IIOUtil.deregisterProvider;
|
import static com.twelvemonkeys.imageio.util.IIOUtil.deregisterProvider;
|
||||||
|
|
||||||
@@ -60,22 +62,22 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
super(new SVGProviderInfo());
|
super(new SVGProviderInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canDecodeInput(final Object pSource) throws IOException {
|
public boolean canDecodeInput(final Object source) throws IOException {
|
||||||
return pSource instanceof ImageInputStream && canDecode((ImageInputStream) pSource);
|
return source instanceof ImageInputStream && canDecode((ImageInputStream) source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("StatementWithEmptyBody")
|
@SuppressWarnings("StatementWithEmptyBody")
|
||||||
private static boolean canDecode(final ImageInputStream pInput) throws IOException {
|
private static boolean canDecode(final ImageInputStream input) throws IOException {
|
||||||
// NOTE: This test is quite quick as it does not involve any parsing,
|
// NOTE: This test is quite quick as it does not involve any parsing,
|
||||||
// however it may not recognize all kinds of SVG documents.
|
// however it may not recognize all kinds of SVG documents.
|
||||||
try {
|
try {
|
||||||
pInput.mark();
|
input.mark();
|
||||||
|
|
||||||
// TODO: This is not ok for UTF-16 and other wide encodings
|
// TODO: This is not ok for UTF-16 and other wide encodings
|
||||||
// TODO: Use an XML (encoding) aware Reader instance instead
|
// TODO: Use an XML (encoding) aware Reader instance instead
|
||||||
// Need to figure out pretty fast if this is XML or not
|
// Need to figure out pretty fast if this is XML or not
|
||||||
int b;
|
int b;
|
||||||
while (Character.isWhitespace((char) (b = pInput.read()))) {
|
while (Character.isWhitespace((char) (b = input.read()))) {
|
||||||
// Skip over leading WS
|
// Skip over leading WS
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,30 +97,30 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
|
|
||||||
byte[] buffer = new byte[4];
|
byte[] buffer = new byte[4];
|
||||||
while (true) {
|
while (true) {
|
||||||
pInput.readFully(buffer);
|
input.readFully(buffer);
|
||||||
|
|
||||||
if (buffer[0] == '?') {
|
if (buffer[0] == '?') {
|
||||||
// This is the XML declaration or a processing instruction
|
// This is the XML declaration or a processing instruction
|
||||||
while (!((pInput.readByte() & 0xFF) == '?' && pInput.read() == '>')) {
|
while (!((input.readByte() & 0xFF) == '?' && input.read() == '>')) {
|
||||||
// Skip until end of XML declaration or processing instruction or EOF
|
// Skip until end of XML declaration or processing instruction or EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (buffer[0] == '!') {
|
else if (buffer[0] == '!') {
|
||||||
if (buffer[1] == '-' && buffer[2] == '-') {
|
if (buffer[1] == '-' && buffer[2] == '-') {
|
||||||
// This is a comment
|
// This is a comment
|
||||||
while (!((pInput.readByte() & 0xFF) == '-' && pInput.read() == '-' && pInput.read() == '>')) {
|
while (!((input.readByte() & 0xFF) == '-' && input.read() == '-' && input.read() == '>')) {
|
||||||
// Skip until end of comment or EOF
|
// Skip until end of comment or EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (buffer[1] == 'D' && buffer[2] == 'O' && buffer[3] == 'C'
|
else if (buffer[1] == 'D' && buffer[2] == 'O' && buffer[3] == 'C'
|
||||||
&& pInput.read() == 'T' && pInput.read() == 'Y'
|
&& input.read() == 'T' && input.read() == 'Y'
|
||||||
&& pInput.read() == 'P' && pInput.read() == 'E') {
|
&& input.read() == 'P' && input.read() == 'E') {
|
||||||
// This is the DOCTYPE declaration
|
// This is the DOCTYPE declaration
|
||||||
while (Character.isWhitespace((char) (b = pInput.read()))) {
|
while (Character.isWhitespace((char) (b = input.read()))) {
|
||||||
// Skip over WS
|
// Skip over WS
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b == 's' && pInput.read() == 'v' && pInput.read() == 'g') {
|
if (b == 's' && input.read() == 'v' && input.read() == 'g') {
|
||||||
// It's SVG, identified by DOCTYPE
|
// It's SVG, identified by DOCTYPE
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -134,15 +136,47 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
if (buffer[0] == 's' && buffer[1] == 'v' && buffer[2] == 'g'
|
if (buffer[0] == 's' && buffer[1] == 'v' && buffer[2] == 'g'
|
||||||
&& (Character.isWhitespace((char) buffer[3]) || buffer[3] == ':')) {
|
&& (Character.isWhitespace((char) buffer[3]) || buffer[3] == ':')) {
|
||||||
// It's SVG, identified by root tag
|
// It's SVG, identified by root tag
|
||||||
// TODO: Support svg with prefix + recognize namespace (http://www.w3.org/2000/svg)!
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read the full tag name (may contain a prefix of any length)
|
||||||
|
final int MAX_TAG_NAME = 256;
|
||||||
|
ByteArrayOutputStream nameBuf = new ByteArrayOutputStream(MAX_TAG_NAME);
|
||||||
|
|
||||||
|
// We already have 4 bytes in 'buffer' (from input.readFully(buffer))
|
||||||
|
int consumedFromBuffer = 0;
|
||||||
|
for (; consumedFromBuffer < buffer.length; consumedFromBuffer++) {
|
||||||
|
byte bb = buffer[consumedFromBuffer];
|
||||||
|
if (bb == '>' || Character.isWhitespace((char) bb) || bb == '/') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nameBuf.write(bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If tag name not terminated yet, keep reading bytes (within limit)
|
||||||
|
final boolean incompleteTagName = consumedFromBuffer == buffer.length;
|
||||||
|
readBuffer(input, nameBuf, output -> incompleteTagName && output.size() < MAX_TAG_NAME,
|
||||||
|
bb -> bb == '>' || Character.isWhitespace(bb) || bb == '/');
|
||||||
|
|
||||||
|
final String name = nameBuf.toString("US-ASCII");
|
||||||
|
if (name.toLowerCase(Locale.ENGLISH).endsWith(":svg")) {
|
||||||
|
// Scan the rest of the tag attributes until '>' to find the SVG namespace URI
|
||||||
|
ByteArrayOutputStream attrBuf = new ByteArrayOutputStream();
|
||||||
|
final int MAX_ATTR_SCAN = 1024; // safe upper bound to keep it fast
|
||||||
|
readBuffer(input, attrBuf, output -> output.size() < MAX_ATTR_SCAN, bb -> bb == '>');
|
||||||
|
|
||||||
|
// If the tag contains the SVG namespace, it's SVG.
|
||||||
|
if (attrBuf.toString("US-ASCII").matches(
|
||||||
|
".*xmlns:" + name.split(":")[0] + "\\s*=\\s*\"http://www.w3.org/2000/svg\".*")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the tag is not "svg", this isn't SVG
|
// If the tag is not "svg", this isn't SVG
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((pInput.readByte() & 0xFF) != '<') {
|
while ((input.readByte() & 0xFF) != '<') {
|
||||||
// Skip over, until next begin tag or EOF
|
// Skip over, until next begin tag or EOF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +187,18 @@ public final class SVGImageReaderSpi extends ImageReaderSpiBase {
|
|||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
//noinspection ThrowFromFinallyBlock
|
//noinspection ThrowFromFinallyBlock
|
||||||
pInput.reset();
|
input.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void readBuffer(final ImageInputStream input, final ByteArrayOutputStream buffer,
|
||||||
|
final Predicate<ByteArrayOutputStream> loopCondition, Predicate<Byte> breakCondition) throws IOException {
|
||||||
|
while (loopCondition.test(buffer)) {
|
||||||
|
byte bb = input.readByte();
|
||||||
|
if (breakCondition.test(bb)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buffer.write(bb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -51,16 +51,16 @@ public class SVGReadParam extends ImageReadParam {
|
|||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBackgroundColor(Paint pColor) {
|
public void setBackgroundColor(Paint color) {
|
||||||
background = pColor;
|
background = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBaseURI() {
|
public String getBaseURI() {
|
||||||
return baseURI;
|
return baseURI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBaseURI(String pBaseURI) {
|
public void setBaseURI(String baseURI) {
|
||||||
baseURI = pBaseURI;
|
this.baseURI = baseURI;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAllowExternalResources(boolean allow) {
|
public void setAllowExternalResources(boolean allow) {
|
||||||
|
|||||||
+143
-141
@@ -1,141 +1,143 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, Harald Kuhr
|
* Copyright (c) 2008, Harald Kuhr
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
*
|
*
|
||||||
* * Redistributions of source code must retain the above copyright notice, this
|
* * Redistributions of source code must retain the above copyright notice, this
|
||||||
* list of conditions and the following disclaimer.
|
* list of conditions and the following disclaimer.
|
||||||
*
|
*
|
||||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
* and/or other materials provided with the distribution.
|
* and/or other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* * Neither the name of the copyright holder nor the names of its
|
* * Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from
|
* contributors may be used to endorse or promote products derived from
|
||||||
* this software without specific prior written permission.
|
* this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.wmf;
|
package com.twelvemonkeys.imageio.plugins.wmf;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||||
import com.twelvemonkeys.imageio.plugins.svg.SVGImageReader;
|
import com.twelvemonkeys.imageio.plugins.svg.SVGImageReader;
|
||||||
import com.twelvemonkeys.imageio.plugins.svg.SVGReadParam;
|
import com.twelvemonkeys.imageio.plugins.svg.SVGReadParam;
|
||||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||||
import org.apache.batik.transcoder.TranscoderException;
|
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||||
import org.apache.batik.transcoder.TranscoderInput;
|
|
||||||
import org.apache.batik.transcoder.TranscoderOutput;
|
import org.apache.batik.transcoder.TranscoderException;
|
||||||
import org.apache.batik.transcoder.wmf.tosvg.WMFTranscoder;
|
import org.apache.batik.transcoder.TranscoderInput;
|
||||||
|
import org.apache.batik.transcoder.TranscoderOutput;
|
||||||
import javax.imageio.IIOException;
|
import org.apache.batik.transcoder.wmf.tosvg.WMFTranscoder;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import javax.imageio.ImageReadParam;
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageReadParam;
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
import java.awt.image.BufferedImage;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import java.io.*;
|
import java.awt.image.*;
|
||||||
import java.util.Iterator;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
/**
|
import java.io.OutputStreamWriter;
|
||||||
* WMFImageReader class description.
|
import java.io.Writer;
|
||||||
*
|
import java.nio.charset.StandardCharsets;
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
import java.util.Iterator;
|
||||||
* @author last modified by $Author: haku $
|
|
||||||
* @version $Id: WMFImageReader.java,v 1.0 29.jul.2004 13:00:59 haku Exp $
|
/**
|
||||||
*/
|
* WMFImageReader class description.
|
||||||
// TODO: Probably possible to do less wrapping/unwrapping of data...
|
*
|
||||||
// TODO: Consider using temp file instead of in-memory stream
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
public final class WMFImageReader extends ImageReaderBase {
|
* @author last modified by $Author: haku $
|
||||||
|
* @version $Id: WMFImageReader.java,v 1.0 29.jul.2004 13:00:59 haku Exp $
|
||||||
private SVGImageReader reader = null;
|
*/
|
||||||
|
// TODO: Probably possible to do less wrapping/unwrapping of data...
|
||||||
public WMFImageReader(final ImageReaderSpi pProvider) {
|
public final class WMFImageReader extends ImageReaderBase {
|
||||||
super(pProvider);
|
|
||||||
}
|
private SVGImageReader reader = null;
|
||||||
|
|
||||||
protected void resetMembers() {
|
public WMFImageReader(final ImageReaderSpi pProvider) {
|
||||||
if (reader != null) {
|
super(pProvider);
|
||||||
reader.dispose();
|
}
|
||||||
}
|
|
||||||
|
protected void resetMembers() {
|
||||||
reader = null;
|
if (reader != null) {
|
||||||
}
|
reader.dispose();
|
||||||
|
}
|
||||||
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
|
||||||
init();
|
reader = null;
|
||||||
|
}
|
||||||
processImageStarted(pIndex);
|
|
||||||
|
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
||||||
BufferedImage image = reader.read(pIndex, pParam);
|
init();
|
||||||
if (abortRequested()) {
|
|
||||||
processReadAborted();
|
processImageStarted(pIndex);
|
||||||
return image;
|
|
||||||
}
|
BufferedImage image = reader.read(pIndex, pParam);
|
||||||
processImageProgress(100f);
|
if (abortRequested()) {
|
||||||
|
processReadAborted();
|
||||||
processImageComplete();
|
return image;
|
||||||
|
}
|
||||||
return image;
|
processImageProgress(100f);
|
||||||
}
|
|
||||||
|
processImageComplete();
|
||||||
private synchronized void init() throws IOException {
|
|
||||||
// Need the extra test, to avoid throwing an IOException from the Transcoder
|
return image;
|
||||||
if (imageInput == null) {
|
}
|
||||||
throw new IllegalStateException("input == null");
|
|
||||||
}
|
private void init() throws IOException {
|
||||||
|
// Need the extra test, to avoid throwing an IOException from the Transcoder
|
||||||
if (reader == null) {
|
if (imageInput == null) {
|
||||||
WMFTranscoder transcoder = new WMFTranscoder();
|
throw new IllegalStateException("input == null");
|
||||||
|
}
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
|
||||||
Writer writer = new OutputStreamWriter(output, "UTF8");
|
if (reader == null) {
|
||||||
try {
|
WMFTranscoder transcoder = new WMFTranscoder();
|
||||||
TranscoderInput in = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
|
ByteArrayOutputStream output = new ByteArrayOutputStream(8192);
|
||||||
TranscoderOutput out = new TranscoderOutput(writer);
|
|
||||||
|
try (Writer writer = new OutputStreamWriter(output, StandardCharsets.UTF_8)) {
|
||||||
// TODO: Transcodinghints?
|
TranscoderInput in = new TranscoderInput(IIOUtil.createStreamAdapter(imageInput));
|
||||||
|
TranscoderOutput out = new TranscoderOutput(writer);
|
||||||
transcoder.transcode(in, out);
|
|
||||||
}
|
// TODO: Transcodinghints?
|
||||||
catch (TranscoderException e) {
|
|
||||||
throw new IIOException(e.getMessage(), e);
|
transcoder.transcode(in, out);
|
||||||
}
|
}
|
||||||
|
catch (TranscoderException e) {
|
||||||
reader = new SVGImageReader(getOriginatingProvider());
|
throw new IIOException(e.getMessage(), e);
|
||||||
reader.setInput(ImageIO.createImageInputStream(new ByteArrayInputStream(output.toByteArray())));
|
}
|
||||||
}
|
|
||||||
}
|
reader = new SVGImageReader(getOriginatingProvider());
|
||||||
|
reader.setInput(new ByteArrayImageInputStream(output.toByteArray()));
|
||||||
@Override
|
}
|
||||||
public ImageReadParam getDefaultReadParam() {
|
}
|
||||||
return new SVGReadParam();
|
|
||||||
}
|
@Override
|
||||||
|
public ImageReadParam getDefaultReadParam() {
|
||||||
public int getWidth(int pIndex) throws IOException {
|
return new SVGReadParam();
|
||||||
init();
|
}
|
||||||
return reader.getWidth(pIndex);
|
|
||||||
}
|
public int getWidth(int pIndex) throws IOException {
|
||||||
|
init();
|
||||||
public int getHeight(int pIndex) throws IOException {
|
return reader.getWidth(pIndex);
|
||||||
init();
|
}
|
||||||
return reader.getHeight(pIndex);
|
|
||||||
}
|
public int getHeight(int pIndex) throws IOException {
|
||||||
|
init();
|
||||||
public Iterator<ImageTypeSpecifier> getImageTypes(final int pImageIndex) throws IOException {
|
return reader.getHeight(pIndex);
|
||||||
init();
|
}
|
||||||
return reader.getImageTypes(pImageIndex);
|
|
||||||
}
|
public Iterator<ImageTypeSpecifier> getImageTypes(final int pImageIndex) throws IOException {
|
||||||
|
init();
|
||||||
}
|
return reader.getImageTypes(pImageIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+15
-10
@@ -32,16 +32,16 @@ package com.twelvemonkeys.imageio.plugins.svg;
|
|||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||||
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.imageio.spi.IIORegistry;
|
import javax.imageio.spi.IIORegistry;
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SVGImageReaderSpiTest.
|
* SVGImageReaderSpiTest.
|
||||||
@@ -56,7 +56,7 @@ public class SVGImageReaderSpiTest {
|
|||||||
"/svg/Android_robot.svg", // Minimal, no xml dec, no namespace
|
"/svg/Android_robot.svg", // Minimal, no xml dec, no namespace
|
||||||
"/svg/batikLogo.svg", // xml dec, comments, namespace
|
"/svg/batikLogo.svg", // xml dec, comments, namespace
|
||||||
"/svg/blue-square.svg", // xml dec, namespace
|
"/svg/blue-square.svg", // xml dec, namespace
|
||||||
"/svg/red-square.svg",
|
"/svg/red-square.svg", // prefixed namespace
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final String[] INVALID_INPUTS = {
|
private static final String[] INVALID_INPUTS = {
|
||||||
@@ -70,6 +70,9 @@ public class SVGImageReaderSpiTest {
|
|||||||
"<!-- ", // #275 Infinite loop issue
|
"<!-- ", // #275 Infinite loop issue
|
||||||
"<?123?>", // #275 Infinite loop issue
|
"<?123?>", // #275 Infinite loop issue
|
||||||
"<svg",
|
"<svg",
|
||||||
|
"<ns0:svg>", // namespace prefix undefined
|
||||||
|
"<ns0:svg xmlns:ns0=\"foo\">", // not the official svg namespace
|
||||||
|
"<ns0:svg xmlns:ns1=\"http://www.w3.org/2000/svg\">", // mismatching prefix
|
||||||
};
|
};
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -83,18 +86,20 @@ public class SVGImageReaderSpiTest {
|
|||||||
public void canDecodeInput() throws Exception {
|
public void canDecodeInput() throws Exception {
|
||||||
for (String validInput : VALID_INPUTS) {
|
for (String validInput : VALID_INPUTS) {
|
||||||
try (ImageInputStream input = ImageIO.createImageInputStream(getClass().getResource(validInput))) {
|
try (ImageInputStream input = ImageIO.createImageInputStream(getClass().getResource(validInput))) {
|
||||||
assertTrue("Can't read valid input: " + validInput, provider.canDecodeInput(input));
|
assertTrue(provider.canDecodeInput(input), "Can't read valid input: " + validInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test will time out, if EOFs are not properly detected, see #275
|
// Test will time out, if EOFs are not properly detected, see #275
|
||||||
@Test(timeout = 5000)
|
@Test
|
||||||
public void canDecodeInputInvalid() throws Exception {
|
public void canDecodeInputInvalid() throws Exception {
|
||||||
for (String invalidInput : INVALID_INPUTS) {
|
assertTimeoutPreemptively(Duration.ofMillis(5000), () -> {
|
||||||
try (ImageInputStream input = new ByteArrayImageInputStream(invalidInput.getBytes(StandardCharsets.UTF_8))) {
|
for (String invalidInput : INVALID_INPUTS) {
|
||||||
assertFalse("Claims to read invalid input:" + invalidInput, provider.canDecodeInput(input));
|
try (ImageInputStream input = new ByteArrayImageInputStream(invalidInput.getBytes(StandardCharsets.UTF_8))) {
|
||||||
|
assertFalse(provider.canDecodeInput(input), "Claims to read invalid input:" + invalidInput);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user