From 2eee97c9e64dca79fc6b1614b304b398d25a7f4b Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 27 Mar 2021 16:36:39 -0500 Subject: Added automatic building with Gradle --- .classpath | 35 +- .gitattributes | 6 + .gitignore | 10 +- .project | 8 +- .settings/org.eclipse.buildship.core.prefs | 2 + .settings/org.eclipse.jdt.apt.core.prefs | 2 - .settings/org.eclipse.jdt.core.prefs | 12 - .settings/org.eclipse.m2e.core.prefs | 4 - bin/main/.gitignore | 2 + bin/test/.gitignore | 1 + build.gradle | 30 + doc/allclasses-frame.html | 45 - doc/allclasses-index.html | 257 - doc/allclasses-noframe.html | 45 - doc/allclasses.html | 45 - doc/allpackages-index.html | 187 - doc/constant-values.html | 186 - doc/deprecated-list.html | 124 - doc/element-list | 4 - doc/help-doc.html | 229 - doc/index-files/index-1.html | 185 - doc/index-files/index-10.html | 129 - doc/index-files/index-11.html | 147 - doc/index-files/index-12.html | 167 - doc/index-files/index-13.html | 175 - doc/index-files/index-14.html | 141 - doc/index-files/index-15.html | 209 - doc/index-files/index-16.html | 175 - doc/index-files/index-17.html | 137 - doc/index-files/index-18.html | 137 - doc/index-files/index-19.html | 197 - doc/index-files/index-2.html | 183 - doc/index-files/index-20.html | 205 - doc/index-files/index-21.html | 175 - doc/index-files/index-22.html | 167 - doc/index-files/index-23.html | 145 - doc/index-files/index-24.html | 137 - doc/index-files/index-25.html | 131 - doc/index-files/index-3.html | 243 - doc/index-files/index-4.html | 185 - doc/index-files/index-5.html | 195 - doc/index-files/index-6.html | 181 - doc/index-files/index-7.html | 209 - doc/index-files/index-8.html | 165 - doc/index-files/index-9.html | 145 - doc/index.html | 75 - doc/jquery/external/jquery/jquery.js | 10364 ----------------- doc/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 335 -> 0 bytes doc/jquery/images/ui-bg_glass_65_dadada_1x400.png | Bin 262 -> 0 bytes doc/jquery/images/ui-bg_glass_75_dadada_1x400.png | Bin 262 -> 0 bytes doc/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 262 -> 0 bytes doc/jquery/images/ui-bg_glass_95_fef1ec_1x400.png | Bin 332 -> 0 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 280 -> 0 bytes doc/jquery/images/ui-icons_222222_256x240.png | Bin 6922 -> 0 bytes doc/jquery/images/ui-icons_2e83ff_256x240.png | Bin 4549 -> 0 bytes doc/jquery/images/ui-icons_454545_256x240.png | Bin 6992 -> 0 bytes doc/jquery/images/ui-icons_888888_256x240.png | Bin 6999 -> 0 bytes doc/jquery/images/ui-icons_cd0a0a_256x240.png | Bin 4549 -> 0 bytes doc/jquery/jquery-3.3.1.js | 10364 ----------------- doc/jquery/jquery-migrate-3.0.1.js | 628 - doc/jquery/jquery-ui.css | 582 - doc/jquery/jquery-ui.js | 2659 ----- doc/jquery/jquery-ui.min.css | 7 - doc/jquery/jquery-ui.min.js | 6 - doc/jquery/jquery-ui.structure.css | 156 - doc/jquery/jquery-ui.structure.min.css | 5 - doc/jquery/jszip-utils/dist/jszip-utils-ie.js | 56 - doc/jquery/jszip-utils/dist/jszip-utils-ie.min.js | 10 - doc/jquery/jszip-utils/dist/jszip-utils.js | 118 - doc/jquery/jszip-utils/dist/jszip-utils.min.js | 10 - doc/jquery/jszip/dist/jszip.js | 11623 ------------------- doc/jquery/jszip/dist/jszip.min.js | 15 - doc/member-search-index.js | 1 - doc/member-search-index.zip | Bin 2500 -> 0 bytes .../converterGUI/DelegateListModel.html | 959 -- .../converterGUI/FilterComparator.html | 489 - .../unitConverter/converterGUI/GridBagBuilder.html | 1140 -- .../converterGUI/MutablePredicate.html | 428 - .../unitConverter/converterGUI/SearchBoxList.html | 902 -- .../converterGUI/UnitConverterGUI.Presenter.html | 717 -- .../converterGUI/UnitConverterGUI.View.html | 853 -- .../converterGUI/UnitConverterGUI.html | 341 - .../converterGUI/class-use/DelegateListModel.html | 195 - .../converterGUI/class-use/FilterComparator.html | 149 - .../converterGUI/class-use/GridBagBuilder.html | 225 - .../converterGUI/class-use/MutablePredicate.html | 149 - .../converterGUI/class-use/SearchBoxList.html | 218 - .../class-use/UnitConverterGUI.Presenter.html | 197 - .../class-use/UnitConverterGUI.View.html | 212 - .../converterGUI/class-use/UnitConverterGUI.html | 149 - .../unitConverter/converterGUI/package-frame.html | 14 - .../converterGUI/package-summary.html | 139 - .../unitConverter/converterGUI/package-tree.html | 127 - .../unitConverter/converterGUI/package-use.html | 124 - ...Collections.ConditionalExistenceCollection.html | 532 - ...ceCollections.ConditionalExistenceIterator.html | 493 - ...istenceCollections.ConditionalExistenceMap.html | 570 - ...istenceCollections.ConditionalExistenceSet.html | 565 - .../math/ConditionalExistenceCollections.html | 397 - .../math/ConditionalExistenceCollectionsTest.html | 469 - doc/org/unitConverter/math/DecimalComparison.html | 492 - .../math/ExpressionParser.Builder.html | 391 - .../ExpressionParser.PriorityBinaryOperator.html | 425 - .../ExpressionParser.PriorityUnaryOperator.html | 425 - .../math/ExpressionParser.TokenType.html | 445 - doc/org/unitConverter/math/ExpressionParser.html | 349 - .../unitConverter/math/ExpressionParserTest.html | 360 - doc/org/unitConverter/math/ObjectProduct.html | 553 - doc/org/unitConverter/math/ObjectProductTest.html | 366 - ...Collections.ConditionalExistenceCollection.html | 149 - ...ceCollections.ConditionalExistenceIterator.html | 197 - ...istenceCollections.ConditionalExistenceMap.html | 149 - ...istenceCollections.ConditionalExistenceSet.html | 149 - .../class-use/ConditionalExistenceCollections.html | 124 - .../ConditionalExistenceCollectionsTest.html | 149 - .../math/class-use/DecimalComparison.html | 124 - .../math/class-use/ExpressionParser.Builder.html | 184 - .../ExpressionParser.PriorityBinaryOperator.html | 221 - .../ExpressionParser.PriorityUnaryOperator.html | 239 - .../math/class-use/ExpressionParser.TokenType.html | 212 - .../math/class-use/ExpressionParser.html | 166 - .../math/class-use/ExpressionParserTest.html | 149 - .../math/class-use/ObjectProduct.html | 515 - .../math/class-use/ObjectProductTest.html | 149 - doc/org/unitConverter/math/package-frame.html | 24 - doc/org/unitConverter/math/package-summary.html | 183 - doc/org/unitConverter/math/package-tree.html | 141 - doc/org/unitConverter/math/package-use.html | 194 - doc/org/unitConverter/package-frame.html | 14 - doc/org/unitConverter/package-summary.html | 141 - doc/org/unitConverter/package-tree.html | 127 - doc/org/unitConverter/package-use.html | 124 - doc/org/unitConverter/unit/BaseDimension.html | 313 - doc/org/unitConverter/unit/BaseUnit.html | 452 - .../unitConverter/unit/BritishImperial.Area.html | 349 - .../unitConverter/unit/BritishImperial.Length.html | 443 - .../unitConverter/unit/BritishImperial.Mass.html | 388 - .../unitConverter/unit/BritishImperial.Volume.html | 414 - doc/org/unitConverter/unit/BritishImperial.html | 384 - doc/org/unitConverter/unit/FunctionalUnit.html | 504 - doc/org/unitConverter/unit/LinearUnit.html | 800 -- doc/org/unitConverter/unit/NameSymbol.html | 641 - doc/org/unitConverter/unit/SI.BaseDimensions.html | 347 - doc/org/unitConverter/unit/SI.BaseUnits.html | 347 - doc/org/unitConverter/unit/SI.Constants.html | 284 - doc/org/unitConverter/unit/SI.Dimensions.html | 789 -- doc/org/unitConverter/unit/SI.html | 1313 --- doc/org/unitConverter/unit/USCustomary.Area.html | 336 - doc/org/unitConverter/unit/USCustomary.Length.html | 492 - doc/org/unitConverter/unit/USCustomary.Mass.html | 388 - doc/org/unitConverter/unit/USCustomary.Volume.html | 583 - doc/org/unitConverter/unit/USCustomary.html | 423 - doc/org/unitConverter/unit/Unit.html | 632 - ...Map.PrefixedUnitEntrySet.PrefixedUnitEntry.html | 499 - ...ixedUnitEntrySet.PrefixedUnitEntryIterator.html | 542 - ...abase.PrefixedUnitMap.PrefixedUnitEntrySet.html | 761 -- ...efixedUnitNameSet.PrefixedUnitNameIterator.html | 542 - ...tabase.PrefixedUnitMap.PrefixedUnitNameSet.html | 754 -- .../unit/UnitDatabase.PrefixedUnitMap.html | 930 -- doc/org/unitConverter/unit/UnitDatabase.html | 789 -- doc/org/unitConverter/unit/UnitDatabaseTest.html | 643 - doc/org/unitConverter/unit/UnitPrefix.html | 570 - doc/org/unitConverter/unit/UnitTest.html | 420 - .../unit/class-use/BaseDimension.html | 470 - doc/org/unitConverter/unit/class-use/BaseUnit.html | 296 - .../unit/class-use/BritishImperial.Area.html | 124 - .../unit/class-use/BritishImperial.Length.html | 124 - .../unit/class-use/BritishImperial.Mass.html | 124 - .../unit/class-use/BritishImperial.Volume.html | 124 - .../unit/class-use/BritishImperial.html | 124 - .../unit/class-use/FunctionalUnit.html | 199 - .../unitConverter/unit/class-use/LinearUnit.html | 926 -- .../unitConverter/unit/class-use/NameSymbol.html | 324 - .../unit/class-use/SI.BaseDimensions.html | 124 - .../unitConverter/unit/class-use/SI.BaseUnits.html | 124 - .../unitConverter/unit/class-use/SI.Constants.html | 124 - .../unit/class-use/SI.Dimensions.html | 124 - doc/org/unitConverter/unit/class-use/SI.html | 124 - .../unit/class-use/USCustomary.Area.html | 124 - .../unit/class-use/USCustomary.Length.html | 124 - .../unit/class-use/USCustomary.Mass.html | 124 - .../unit/class-use/USCustomary.Volume.html | 124 - .../unitConverter/unit/class-use/USCustomary.html | 124 - doc/org/unitConverter/unit/class-use/Unit.html | 312 - ...Map.PrefixedUnitEntrySet.PrefixedUnitEntry.html | 149 - ...ixedUnitEntrySet.PrefixedUnitEntryIterator.html | 149 - ...abase.PrefixedUnitMap.PrefixedUnitEntrySet.html | 149 - ...efixedUnitNameSet.PrefixedUnitNameIterator.html | 149 - ...tabase.PrefixedUnitMap.PrefixedUnitNameSet.html | 149 - .../class-use/UnitDatabase.PrefixedUnitMap.html | 233 - .../unitConverter/unit/class-use/UnitDatabase.html | 124 - .../unit/class-use/UnitDatabaseTest.html | 149 - .../unitConverter/unit/class-use/UnitPrefix.html | 381 - doc/org/unitConverter/unit/class-use/UnitTest.html | 149 - doc/org/unitConverter/unit/package-frame.html | 41 - doc/org/unitConverter/unit/package-summary.html | 279 - doc/org/unitConverter/unit/package-tree.html | 161 - doc/org/unitConverter/unit/package-use.html | 186 - doc/overview-frame.html | 24 - doc/overview-summary.html | 155 - doc/overview-tree.html | 169 - doc/package-list | 4 - doc/package-search-index.js | 1 - doc/package-search-index.zip | Bin 252 -> 0 bytes doc/resources/glass.png | Bin 499 -> 0 bytes doc/resources/x.png | Bin 394 -> 0 bytes doc/script.js | 30 - doc/search.js | 326 - doc/stylesheet.css | 906 -- doc/type-search-index.js | 1 - doc/type-search-index.zip | Bin 397 -> 0 bytes gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58694 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 183 + gradlew.bat | 103 + pom.xml | 55 - settings.gradle | 10 + settings.txt | 4 + src/about.txt | 12 - .../converterGUI/DefaultPrefixRepetitionRule.java | 95 + .../converterGUI/DelegateListModel.java | 242 + .../converterGUI/FilterComparator.java | 129 + .../unitConverter/converterGUI/GridBagBuilder.java | 479 + .../converterGUI/MutablePredicate.java | 70 + .../unitConverter/converterGUI/SearchBoxList.java | 307 + .../converterGUI/UnitConverterGUI.java | 1426 +++ .../unitConverter/converterGUI/package-info.java | 24 + .../math/ConditionalExistenceCollections.java | 468 + .../org/unitConverter/math/DecimalComparison.java | 256 + .../org/unitConverter/math/ExpressionParser.java | 708 ++ .../java/org/unitConverter/math/ObjectProduct.java | 284 + .../org/unitConverter/math/UncertainDouble.java | 419 + .../java/org/unitConverter/math/package-info.java | 24 + src/main/java/org/unitConverter/package-info.java | 24 + .../java/org/unitConverter/unit/BaseDimension.java | 87 + src/main/java/org/unitConverter/unit/BaseUnit.java | 133 + .../org/unitConverter/unit/BritishImperial.java | 116 + .../org/unitConverter/unit/FunctionalUnit.java | 109 + .../org/unitConverter/unit/FunctionalUnitlike.java | 72 + .../java/org/unitConverter/unit/LinearUnit.java | 441 + .../org/unitConverter/unit/LinearUnitValue.java | 341 + .../java/org/unitConverter/unit/MultiUnit.java | 160 + .../java/org/unitConverter/unit/NameSymbol.java | 280 + src/main/java/org/unitConverter/unit/Nameable.java | 59 + src/main/java/org/unitConverter/unit/SI.java | 479 + .../java/org/unitConverter/unit/USCustomary.java | 135 + src/main/java/org/unitConverter/unit/Unit.java | 377 + .../java/org/unitConverter/unit/UnitDatabase.java | 1991 ++++ .../java/org/unitConverter/unit/UnitPrefix.java | 242 + .../java/org/unitConverter/unit/UnitValue.java | 172 + src/main/java/org/unitConverter/unit/Unitlike.java | 260 + .../java/org/unitConverter/unit/UnitlikeValue.java | 174 + .../java/org/unitConverter/unit/package-info.java | 24 + src/main/resources/about.txt | 12 + .../converterGUI/DefaultPrefixRepetitionRule.java | 95 - .../converterGUI/DelegateListModel.java | 242 - .../converterGUI/FilterComparator.java | 129 - .../unitConverter/converterGUI/GridBagBuilder.java | 479 - .../converterGUI/MutablePredicate.java | 70 - .../unitConverter/converterGUI/SearchBoxList.java | 307 - .../converterGUI/UnitConverterGUI.java | 1424 --- .../unitConverter/converterGUI/package-info.java | 24 - .../math/ConditionalExistenceCollections.java | 468 - .../math/ConditionalExistenceCollectionsTest.java | 159 - src/org/unitConverter/math/DecimalComparison.java | 256 - src/org/unitConverter/math/ExpressionParser.java | 708 -- .../unitConverter/math/ExpressionParserTest.java | 52 - src/org/unitConverter/math/ObjectProduct.java | 284 - src/org/unitConverter/math/ObjectProductTest.java | 78 - src/org/unitConverter/math/UncertainDouble.java | 419 - src/org/unitConverter/math/package-info.java | 24 - src/org/unitConverter/package-info.java | 24 - src/org/unitConverter/unit/BaseDimension.java | 87 - src/org/unitConverter/unit/BaseUnit.java | 133 - src/org/unitConverter/unit/BritishImperial.java | 116 - src/org/unitConverter/unit/FunctionalUnit.java | 109 - src/org/unitConverter/unit/FunctionalUnitlike.java | 72 - src/org/unitConverter/unit/LinearUnit.java | 441 - src/org/unitConverter/unit/LinearUnitValue.java | 341 - src/org/unitConverter/unit/MultiUnit.java | 160 - src/org/unitConverter/unit/MultiUnitTest.java | 106 - src/org/unitConverter/unit/NameSymbol.java | 280 - src/org/unitConverter/unit/Nameable.java | 59 - src/org/unitConverter/unit/SI.java | 479 - src/org/unitConverter/unit/USCustomary.java | 135 - src/org/unitConverter/unit/Unit.java | 377 - src/org/unitConverter/unit/UnitDatabase.java | 1991 ---- src/org/unitConverter/unit/UnitDatabaseTest.java | 309 - src/org/unitConverter/unit/UnitPrefix.java | 242 - src/org/unitConverter/unit/UnitTest.java | 146 - src/org/unitConverter/unit/UnitValue.java | 172 - src/org/unitConverter/unit/Unitlike.java | 260 - src/org/unitConverter/unit/UnitlikeValue.java | 174 - src/org/unitConverter/unit/package-info.java | 24 - .../math/ConditionalExistenceCollectionsTest.java | 159 + .../unitConverter/math/ExpressionParserTest.java | 52 + .../org/unitConverter/math/ObjectProductTest.java | 78 + .../java/org/unitConverter/unit/MultiUnitTest.java | 106 + .../org/unitConverter/unit/UnitDatabaseTest.java | 309 + src/test/java/org/unitConverter/unit/UnitTest.java | 146 + 300 files changed, 11841 insertions(+), 97539 deletions(-) create mode 100644 .gitattributes create mode 100644 .settings/org.eclipse.buildship.core.prefs delete mode 100644 .settings/org.eclipse.jdt.apt.core.prefs delete mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 bin/main/.gitignore create mode 100644 bin/test/.gitignore create mode 100644 build.gradle delete mode 100644 doc/allclasses-frame.html delete mode 100644 doc/allclasses-index.html delete mode 100644 doc/allclasses-noframe.html delete mode 100644 doc/allclasses.html delete mode 100644 doc/allpackages-index.html delete mode 100644 doc/constant-values.html delete mode 100644 doc/deprecated-list.html delete mode 100644 doc/element-list delete mode 100644 doc/help-doc.html delete mode 100644 doc/index-files/index-1.html delete mode 100644 doc/index-files/index-10.html delete mode 100644 doc/index-files/index-11.html delete mode 100644 doc/index-files/index-12.html delete mode 100644 doc/index-files/index-13.html delete mode 100644 doc/index-files/index-14.html delete mode 100644 doc/index-files/index-15.html delete mode 100644 doc/index-files/index-16.html delete mode 100644 doc/index-files/index-17.html delete mode 100644 doc/index-files/index-18.html delete mode 100644 doc/index-files/index-19.html delete mode 100644 doc/index-files/index-2.html delete mode 100644 doc/index-files/index-20.html delete mode 100644 doc/index-files/index-21.html delete mode 100644 doc/index-files/index-22.html delete mode 100644 doc/index-files/index-23.html delete mode 100644 doc/index-files/index-24.html delete mode 100644 doc/index-files/index-25.html delete mode 100644 doc/index-files/index-3.html delete mode 100644 doc/index-files/index-4.html delete mode 100644 doc/index-files/index-5.html delete mode 100644 doc/index-files/index-6.html delete mode 100644 doc/index-files/index-7.html delete mode 100644 doc/index-files/index-8.html delete mode 100644 doc/index-files/index-9.html delete mode 100644 doc/index.html delete mode 100644 doc/jquery/external/jquery/jquery.js delete mode 100644 doc/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png delete mode 100644 doc/jquery/images/ui-bg_glass_65_dadada_1x400.png delete mode 100644 doc/jquery/images/ui-bg_glass_75_dadada_1x400.png delete mode 100644 doc/jquery/images/ui-bg_glass_75_e6e6e6_1x400.png delete mode 100644 doc/jquery/images/ui-bg_glass_95_fef1ec_1x400.png delete mode 100644 doc/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png delete mode 100644 doc/jquery/images/ui-icons_222222_256x240.png delete mode 100644 doc/jquery/images/ui-icons_2e83ff_256x240.png delete mode 100644 doc/jquery/images/ui-icons_454545_256x240.png delete mode 100644 doc/jquery/images/ui-icons_888888_256x240.png delete mode 100644 doc/jquery/images/ui-icons_cd0a0a_256x240.png delete mode 100644 doc/jquery/jquery-3.3.1.js delete mode 100644 doc/jquery/jquery-migrate-3.0.1.js delete mode 100644 doc/jquery/jquery-ui.css delete mode 100644 doc/jquery/jquery-ui.js delete mode 100644 doc/jquery/jquery-ui.min.css delete mode 100644 doc/jquery/jquery-ui.min.js delete mode 100644 doc/jquery/jquery-ui.structure.css delete mode 100644 doc/jquery/jquery-ui.structure.min.css delete mode 100644 doc/jquery/jszip-utils/dist/jszip-utils-ie.js delete mode 100644 doc/jquery/jszip-utils/dist/jszip-utils-ie.min.js delete mode 100644 doc/jquery/jszip-utils/dist/jszip-utils.js delete mode 100644 doc/jquery/jszip-utils/dist/jszip-utils.min.js delete mode 100644 doc/jquery/jszip/dist/jszip.js delete mode 100644 doc/jquery/jszip/dist/jszip.min.js delete mode 100644 doc/member-search-index.js delete mode 100644 doc/member-search-index.zip delete mode 100644 doc/org/unitConverter/converterGUI/DelegateListModel.html delete mode 100644 doc/org/unitConverter/converterGUI/FilterComparator.html delete mode 100644 doc/org/unitConverter/converterGUI/GridBagBuilder.html delete mode 100644 doc/org/unitConverter/converterGUI/MutablePredicate.html delete mode 100644 doc/org/unitConverter/converterGUI/SearchBoxList.html delete mode 100644 doc/org/unitConverter/converterGUI/UnitConverterGUI.Presenter.html delete mode 100644 doc/org/unitConverter/converterGUI/UnitConverterGUI.View.html delete mode 100644 doc/org/unitConverter/converterGUI/UnitConverterGUI.html delete mode 100644 doc/org/unitConverter/converterGUI/class-use/DelegateListModel.html delete mode 100644 doc/org/unitConverter/converterGUI/class-use/FilterComparator.html delete mode 100644 doc/org/unitConverter/converterGUI/class-use/GridBagBuilder.html delete mode 100644 doc/org/unitConverter/converterGUI/class-use/MutablePredicate.html delete mode 100644 doc/org/unitConverter/converterGUI/class-use/SearchBoxList.html delete mode 100644 doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.Presenter.html delete mode 100644 doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.View.html delete mode 100644 doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.html delete mode 100644 doc/org/unitConverter/converterGUI/package-frame.html delete mode 100644 doc/org/unitConverter/converterGUI/package-summary.html delete mode 100644 doc/org/unitConverter/converterGUI/package-tree.html delete mode 100644 doc/org/unitConverter/converterGUI/package-use.html delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceCollection.html delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceIterator.html delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceMap.html delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceSet.html delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollections.html delete mode 100644 doc/org/unitConverter/math/ConditionalExistenceCollectionsTest.html delete mode 100644 doc/org/unitConverter/math/DecimalComparison.html delete mode 100644 doc/org/unitConverter/math/ExpressionParser.Builder.html delete mode 100644 doc/org/unitConverter/math/ExpressionParser.PriorityBinaryOperator.html delete mode 100644 doc/org/unitConverter/math/ExpressionParser.PriorityUnaryOperator.html delete mode 100644 doc/org/unitConverter/math/ExpressionParser.TokenType.html delete mode 100644 doc/org/unitConverter/math/ExpressionParser.html delete mode 100644 doc/org/unitConverter/math/ExpressionParserTest.html delete mode 100644 doc/org/unitConverter/math/ObjectProduct.html delete mode 100644 doc/org/unitConverter/math/ObjectProductTest.html delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceCollection.html delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceIterator.html delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceMap.html delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceSet.html delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.html delete mode 100644 doc/org/unitConverter/math/class-use/ConditionalExistenceCollectionsTest.html delete mode 100644 doc/org/unitConverter/math/class-use/DecimalComparison.html delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParser.Builder.html delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParser.PriorityBinaryOperator.html delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParser.PriorityUnaryOperator.html delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParser.TokenType.html delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParser.html delete mode 100644 doc/org/unitConverter/math/class-use/ExpressionParserTest.html delete mode 100644 doc/org/unitConverter/math/class-use/ObjectProduct.html delete mode 100644 doc/org/unitConverter/math/class-use/ObjectProductTest.html delete mode 100644 doc/org/unitConverter/math/package-frame.html delete mode 100644 doc/org/unitConverter/math/package-summary.html delete mode 100644 doc/org/unitConverter/math/package-tree.html delete mode 100644 doc/org/unitConverter/math/package-use.html delete mode 100644 doc/org/unitConverter/package-frame.html delete mode 100644 doc/org/unitConverter/package-summary.html delete mode 100644 doc/org/unitConverter/package-tree.html delete mode 100644 doc/org/unitConverter/package-use.html delete mode 100644 doc/org/unitConverter/unit/BaseDimension.html delete mode 100644 doc/org/unitConverter/unit/BaseUnit.html delete mode 100644 doc/org/unitConverter/unit/BritishImperial.Area.html delete mode 100644 doc/org/unitConverter/unit/BritishImperial.Length.html delete mode 100644 doc/org/unitConverter/unit/BritishImperial.Mass.html delete mode 100644 doc/org/unitConverter/unit/BritishImperial.Volume.html delete mode 100644 doc/org/unitConverter/unit/BritishImperial.html delete mode 100644 doc/org/unitConverter/unit/FunctionalUnit.html delete mode 100644 doc/org/unitConverter/unit/LinearUnit.html delete mode 100644 doc/org/unitConverter/unit/NameSymbol.html delete mode 100644 doc/org/unitConverter/unit/SI.BaseDimensions.html delete mode 100644 doc/org/unitConverter/unit/SI.BaseUnits.html delete mode 100644 doc/org/unitConverter/unit/SI.Constants.html delete mode 100644 doc/org/unitConverter/unit/SI.Dimensions.html delete mode 100644 doc/org/unitConverter/unit/SI.html delete mode 100644 doc/org/unitConverter/unit/USCustomary.Area.html delete mode 100644 doc/org/unitConverter/unit/USCustomary.Length.html delete mode 100644 doc/org/unitConverter/unit/USCustomary.Mass.html delete mode 100644 doc/org/unitConverter/unit/USCustomary.Volume.html delete mode 100644 doc/org/unitConverter/unit/USCustomary.html delete mode 100644 doc/org/unitConverter/unit/Unit.html delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry.html delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator.html delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.html delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.html delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.html delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.html delete mode 100644 doc/org/unitConverter/unit/UnitDatabase.html delete mode 100644 doc/org/unitConverter/unit/UnitDatabaseTest.html delete mode 100644 doc/org/unitConverter/unit/UnitPrefix.html delete mode 100644 doc/org/unitConverter/unit/UnitTest.html delete mode 100644 doc/org/unitConverter/unit/class-use/BaseDimension.html delete mode 100644 doc/org/unitConverter/unit/class-use/BaseUnit.html delete mode 100644 doc/org/unitConverter/unit/class-use/BritishImperial.Area.html delete mode 100644 doc/org/unitConverter/unit/class-use/BritishImperial.Length.html delete mode 100644 doc/org/unitConverter/unit/class-use/BritishImperial.Mass.html delete mode 100644 doc/org/unitConverter/unit/class-use/BritishImperial.Volume.html delete mode 100644 doc/org/unitConverter/unit/class-use/BritishImperial.html delete mode 100644 doc/org/unitConverter/unit/class-use/FunctionalUnit.html delete mode 100644 doc/org/unitConverter/unit/class-use/LinearUnit.html delete mode 100644 doc/org/unitConverter/unit/class-use/NameSymbol.html delete mode 100644 doc/org/unitConverter/unit/class-use/SI.BaseDimensions.html delete mode 100644 doc/org/unitConverter/unit/class-use/SI.BaseUnits.html delete mode 100644 doc/org/unitConverter/unit/class-use/SI.Constants.html delete mode 100644 doc/org/unitConverter/unit/class-use/SI.Dimensions.html delete mode 100644 doc/org/unitConverter/unit/class-use/SI.html delete mode 100644 doc/org/unitConverter/unit/class-use/USCustomary.Area.html delete mode 100644 doc/org/unitConverter/unit/class-use/USCustomary.Length.html delete mode 100644 doc/org/unitConverter/unit/class-use/USCustomary.Mass.html delete mode 100644 doc/org/unitConverter/unit/class-use/USCustomary.Volume.html delete mode 100644 doc/org/unitConverter/unit/class-use/USCustomary.html delete mode 100644 doc/org/unitConverter/unit/class-use/Unit.html delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry.html delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator.html delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.html delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.html delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.html delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.html delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabase.html delete mode 100644 doc/org/unitConverter/unit/class-use/UnitDatabaseTest.html delete mode 100644 doc/org/unitConverter/unit/class-use/UnitPrefix.html delete mode 100644 doc/org/unitConverter/unit/class-use/UnitTest.html delete mode 100644 doc/org/unitConverter/unit/package-frame.html delete mode 100644 doc/org/unitConverter/unit/package-summary.html delete mode 100644 doc/org/unitConverter/unit/package-tree.html delete mode 100644 doc/org/unitConverter/unit/package-use.html delete mode 100644 doc/overview-frame.html delete mode 100644 doc/overview-summary.html delete mode 100644 doc/overview-tree.html delete mode 100644 doc/package-list delete mode 100644 doc/package-search-index.js delete mode 100644 doc/package-search-index.zip delete mode 100644 doc/resources/glass.png delete mode 100644 doc/resources/x.png delete mode 100644 doc/script.js delete mode 100644 doc/search.js delete mode 100644 doc/stylesheet.css delete mode 100644 doc/type-search-index.js delete mode 100644 doc/type-search-index.zip create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat delete mode 100644 pom.xml create mode 100644 settings.gradle create mode 100644 settings.txt delete mode 100644 src/about.txt create mode 100644 src/main/java/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java create mode 100644 src/main/java/org/unitConverter/converterGUI/DelegateListModel.java create mode 100644 src/main/java/org/unitConverter/converterGUI/FilterComparator.java create mode 100644 src/main/java/org/unitConverter/converterGUI/GridBagBuilder.java create mode 100644 src/main/java/org/unitConverter/converterGUI/MutablePredicate.java create mode 100644 src/main/java/org/unitConverter/converterGUI/SearchBoxList.java create mode 100644 src/main/java/org/unitConverter/converterGUI/UnitConverterGUI.java create mode 100644 src/main/java/org/unitConverter/converterGUI/package-info.java create mode 100644 src/main/java/org/unitConverter/math/ConditionalExistenceCollections.java create mode 100644 src/main/java/org/unitConverter/math/DecimalComparison.java create mode 100644 src/main/java/org/unitConverter/math/ExpressionParser.java create mode 100644 src/main/java/org/unitConverter/math/ObjectProduct.java create mode 100644 src/main/java/org/unitConverter/math/UncertainDouble.java create mode 100644 src/main/java/org/unitConverter/math/package-info.java create mode 100644 src/main/java/org/unitConverter/package-info.java create mode 100644 src/main/java/org/unitConverter/unit/BaseDimension.java create mode 100644 src/main/java/org/unitConverter/unit/BaseUnit.java create mode 100644 src/main/java/org/unitConverter/unit/BritishImperial.java create mode 100644 src/main/java/org/unitConverter/unit/FunctionalUnit.java create mode 100644 src/main/java/org/unitConverter/unit/FunctionalUnitlike.java create mode 100644 src/main/java/org/unitConverter/unit/LinearUnit.java create mode 100644 src/main/java/org/unitConverter/unit/LinearUnitValue.java create mode 100644 src/main/java/org/unitConverter/unit/MultiUnit.java create mode 100644 src/main/java/org/unitConverter/unit/NameSymbol.java create mode 100644 src/main/java/org/unitConverter/unit/Nameable.java create mode 100644 src/main/java/org/unitConverter/unit/SI.java create mode 100644 src/main/java/org/unitConverter/unit/USCustomary.java create mode 100644 src/main/java/org/unitConverter/unit/Unit.java create mode 100644 src/main/java/org/unitConverter/unit/UnitDatabase.java create mode 100644 src/main/java/org/unitConverter/unit/UnitPrefix.java create mode 100644 src/main/java/org/unitConverter/unit/UnitValue.java create mode 100644 src/main/java/org/unitConverter/unit/Unitlike.java create mode 100644 src/main/java/org/unitConverter/unit/UnitlikeValue.java create mode 100644 src/main/java/org/unitConverter/unit/package-info.java create mode 100644 src/main/resources/about.txt delete mode 100644 src/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java delete mode 100644 src/org/unitConverter/converterGUI/DelegateListModel.java delete mode 100644 src/org/unitConverter/converterGUI/FilterComparator.java delete mode 100644 src/org/unitConverter/converterGUI/GridBagBuilder.java delete mode 100644 src/org/unitConverter/converterGUI/MutablePredicate.java delete mode 100644 src/org/unitConverter/converterGUI/SearchBoxList.java delete mode 100644 src/org/unitConverter/converterGUI/UnitConverterGUI.java delete mode 100644 src/org/unitConverter/converterGUI/package-info.java delete mode 100644 src/org/unitConverter/math/ConditionalExistenceCollections.java delete mode 100644 src/org/unitConverter/math/ConditionalExistenceCollectionsTest.java delete mode 100644 src/org/unitConverter/math/DecimalComparison.java delete mode 100644 src/org/unitConverter/math/ExpressionParser.java delete mode 100644 src/org/unitConverter/math/ExpressionParserTest.java delete mode 100644 src/org/unitConverter/math/ObjectProduct.java delete mode 100644 src/org/unitConverter/math/ObjectProductTest.java delete mode 100644 src/org/unitConverter/math/UncertainDouble.java delete mode 100644 src/org/unitConverter/math/package-info.java delete mode 100644 src/org/unitConverter/package-info.java delete mode 100644 src/org/unitConverter/unit/BaseDimension.java delete mode 100644 src/org/unitConverter/unit/BaseUnit.java delete mode 100644 src/org/unitConverter/unit/BritishImperial.java delete mode 100644 src/org/unitConverter/unit/FunctionalUnit.java delete mode 100644 src/org/unitConverter/unit/FunctionalUnitlike.java delete mode 100644 src/org/unitConverter/unit/LinearUnit.java delete mode 100644 src/org/unitConverter/unit/LinearUnitValue.java delete mode 100644 src/org/unitConverter/unit/MultiUnit.java delete mode 100644 src/org/unitConverter/unit/MultiUnitTest.java delete mode 100644 src/org/unitConverter/unit/NameSymbol.java delete mode 100644 src/org/unitConverter/unit/Nameable.java delete mode 100644 src/org/unitConverter/unit/SI.java delete mode 100644 src/org/unitConverter/unit/USCustomary.java delete mode 100644 src/org/unitConverter/unit/Unit.java delete mode 100644 src/org/unitConverter/unit/UnitDatabase.java delete mode 100644 src/org/unitConverter/unit/UnitDatabaseTest.java delete mode 100644 src/org/unitConverter/unit/UnitPrefix.java delete mode 100644 src/org/unitConverter/unit/UnitTest.java delete mode 100644 src/org/unitConverter/unit/UnitValue.java delete mode 100644 src/org/unitConverter/unit/Unitlike.java delete mode 100644 src/org/unitConverter/unit/UnitlikeValue.java delete mode 100644 src/org/unitConverter/unit/package-info.java create mode 100644 src/test/java/org/unitConverter/math/ConditionalExistenceCollectionsTest.java create mode 100644 src/test/java/org/unitConverter/math/ExpressionParserTest.java create mode 100644 src/test/java/org/unitConverter/math/ObjectProductTest.java create mode 100644 src/test/java/org/unitConverter/unit/MultiUnitTest.java create mode 100644 src/test/java/org/unitConverter/unit/UnitDatabaseTest.java create mode 100644 src/test/java/org/unitConverter/unit/UnitTest.java diff --git a/.classpath b/.classpath index a6325e3..66f8050 100644 --- a/.classpath +++ b/.classpath @@ -1,33 +1,32 @@ - - - + - - + + - + - + + - + - - - - + + + - + - - - - + + + - + + + diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..00a51af --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/.gitignore b/.gitignore index 1d7e13f..1b6985c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -bin/ -target/ -*.class -*~ -settings.txt \ No newline at end of file +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/.project b/.project index 56f686e..2debd0a 100644 --- a/.project +++ b/.project @@ -1,7 +1,7 @@ - Unit Converter - + UnitConverter + Project UnitConverter created by Buildship. @@ -11,13 +11,13 @@ - org.eclipse.m2e.core.maven2Builder + org.eclipse.buildship.core.gradleprojectbuilder - org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..e889521 --- /dev/null +++ b/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/.settings/org.eclipse.jdt.apt.core.prefs b/.settings/org.eclipse.jdt.apt.core.prefs deleted file mode 100644 index d4313d4..0000000 --- a/.settings/org.eclipse.jdt.apt.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.apt.aptEnabled=false diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 01cf56c..18ad895 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,16 +1,4 @@ eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=11 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning -org.eclipse.jdt.core.compiler.processAnnotations=disabled -org.eclipse.jdt.core.compiler.release=enabled org.eclipse.jdt.core.compiler.source=11 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f..0000000 --- a/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/bin/main/.gitignore b/bin/main/.gitignore new file mode 100644 index 0000000..b2d0b77 --- /dev/null +++ b/bin/main/.gitignore @@ -0,0 +1,2 @@ +/about.txt +/org/ diff --git a/bin/test/.gitignore b/bin/test/.gitignore new file mode 100644 index 0000000..cf1db2e --- /dev/null +++ b/bin/test/.gitignore @@ -0,0 +1 @@ +/org/ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..9d054c3 --- /dev/null +++ b/build.gradle @@ -0,0 +1,30 @@ +plugins { + id "java" + id "application" +} + +java { + sourceCompatibility = JavaVersion.VERSION_11 +} + +mainClassName = "org.unitConverter.converterGUI.UnitConverterGUI" + +repositories { + mavenCentral() +} + +dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' +} + +test { + useJUnitPlatform() + testLogging { + events 'passed', 'skipped', 'failed' + } +} + +run { +} \ No newline at end of file diff --git a/doc/allclasses-frame.html b/doc/allclasses-frame.html deleted file mode 100644 index d043203..0000000 --- a/doc/allclasses-frame.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - -All Classes - - - - - -

All Classes

-
- -
- - diff --git a/doc/allclasses-index.html b/doc/allclasses-index.html deleted file mode 100644 index c9afff4..0000000 --- a/doc/allclasses-index.html +++ /dev/null @@ -1,257 +0,0 @@ - - - - - -All Classes - - - - - - - - - - - - - - - -
- -
-
-
-

All Classes

-
-
-
    -
  • - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Class Summary 
    ClassDescription
    BaseDimension -
    A dimension that defines a BaseUnit
    -
    BaseUnit -
    A unit that other units are defined by.
    -
    BritishImperial -
    A static utility class that contains units in the British Imperial system.
    -
    ConditionalExistenceCollections -
    Elements in these wrapper collections only exist if they pass a condition.
    -
    DecimalComparison -
    A class that contains methods to compare float and double values.
    -
    ExpressionParser<T> -
    An object that can parse expressions with unary or binary operators.
    -
    ExpressionParser.Builder<T> -
    A builder that can create ExpressionParser<T> instances.
    -
    LinearUnit -
    A unit that can be expressed as a product of its base and a number.
    -
    ObjectProduct<T> -
    An immutable product of multiple objects of a type, such as base units.
    -
    SI -
    All of the units, prefixes and dimensions that are used by the SI, as well as some outside the SI.
    -
    SI.BaseDimensions 
    SI.BaseUnits 
    SI.Dimensions 
    Unit -
    A unit that is composed of base units.
    -
    UnitDatabase -
    A database of units, prefixes and dimensions, and their names.
    -
    UnitPrefix -
    A prefix that can be applied to a LinearUnit to multiply it by some value
    -
    USCustomary -
    A static utility class that contains units in the US Customary system.
    -
    -
  • -
-
-
- - - diff --git a/doc/allclasses-noframe.html b/doc/allclasses-noframe.html deleted file mode 100644 index 38b4779..0000000 --- a/doc/allclasses-noframe.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - -All Classes - - - - - -

All Classes

-
- -
- - diff --git a/doc/allclasses.html b/doc/allclasses.html deleted file mode 100644 index 93a1588..0000000 --- a/doc/allclasses.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - -All Classes - - - - - - - - - - - - - -

All Classes

-
- -
- - diff --git a/doc/allpackages-index.html b/doc/allpackages-index.html deleted file mode 100644 index 3ca22c6..0000000 --- a/doc/allpackages-index.html +++ /dev/null @@ -1,187 +0,0 @@ - - - - - -All Packages - - - - - - - - - - - - - - - -
- -
-
-
-

All Packages

-
-
- -
-
- - - diff --git a/doc/constant-values.html b/doc/constant-values.html deleted file mode 100644 index 9f6471d..0000000 --- a/doc/constant-values.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - -Constant Field Values - - - - - - - - -
- - - - - - - -
- - -
-

Constant Field Values

-

Contents

- -
-
- - -

org.unitConverter.*

- -
- -
- - - - - - - -
- - - - diff --git a/doc/deprecated-list.html b/doc/deprecated-list.html deleted file mode 100644 index 5a10f79..0000000 --- a/doc/deprecated-list.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Deprecated List - - - - - - - - -
- - - - - - - -
- - -
-

Deprecated API

-

Contents

-
- -
- - - - - - - -
- - - - diff --git a/doc/element-list b/doc/element-list deleted file mode 100644 index 82e9a56..0000000 --- a/doc/element-list +++ /dev/null @@ -1,4 +0,0 @@ -org.unitConverter -org.unitConverter.converterGUI -org.unitConverter.math -org.unitConverter.unit diff --git a/doc/help-doc.html b/doc/help-doc.html deleted file mode 100644 index 4cb7311..0000000 --- a/doc/help-doc.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - - -API Help - - - - - - - - -
- - - - - - - -
- - -
-

How This API Document Is Organized

-
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
-
-
- -This help file applies to API documentation generated using the standard doclet.
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-1.html b/doc/index-files/index-1.html deleted file mode 100644 index bd4d817..0000000 --- a/doc/index-files/index-1.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - -A-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

A

-
-
ACCELERATION - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
ACRE - Static variable in class org.unitConverter.unit.BritishImperial.Area
-
 
-
ACRE - Static variable in class org.unitConverter.unit.USCustomary.Area
-
 
-
ACRE_FOOT - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
ACRE_FOOT - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
addBinaryOperator(String, BinaryOperator<T>, int) - Method in class org.unitConverter.math.ExpressionParser.Builder
-
-
Adds a binary operator to the builder.
-
-
addDimension(String, ObjectProduct<BaseDimension>) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Adds a unit dimension to the database.
-
-
addPrefix(String, UnitPrefix) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Adds a unit prefix to the database.
-
-
addSpaceFunction(String) - Method in class org.unitConverter.math.ExpressionParser.Builder
-
-
Adds a function for spaces.
-
-
addUnaryOperator(String, UnaryOperator<T>, int) - Method in class org.unitConverter.math.ExpressionParser.Builder
-
-
Adds a unary operator to the builder.
-
-
addUnit(String, Unit) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Adds a unit to the database.
-
-
AMPERE - Static variable in class org.unitConverter.unit.SI
-
 
-
AMPERE - Static variable in class org.unitConverter.unit.SI.BaseUnits
-
 
-
ANGLE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
ARCMINUTE - Static variable in class org.unitConverter.unit.SI
-
 
-
ARCSECOND - Static variable in class org.unitConverter.unit.SI
-
 
-
Area() - Constructor for class org.unitConverter.unit.BritishImperial.Area
-
 
-
AREA - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
Area() - Constructor for class org.unitConverter.unit.USCustomary.Area
-
 
-
asLinearUnit() - Method in class org.unitConverter.unit.BaseUnit
-
-
Returns a LinearUnit with this unit as a base and a conversion factor of 1.
-
-
ASTRONOMICAL_UNIT - Static variable in class org.unitConverter.unit.SI
-
 
-
ATTO - Static variable in class org.unitConverter.unit.SI
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-10.html b/doc/index-files/index-10.html deleted file mode 100644 index 990b359..0000000 --- a/doc/index-files/index-10.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - -J-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

J

-
-
JOULE - Static variable in class org.unitConverter.unit.SI
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-11.html b/doc/index-files/index-11.html deleted file mode 100644 index 1fec27f..0000000 --- a/doc/index-files/index-11.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - -K-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

K

-
-
KATAL - Static variable in class org.unitConverter.unit.SI
-
 
-
KELVIN - Static variable in class org.unitConverter.unit.SI.BaseUnits
-
 
-
KELVIN - Static variable in class org.unitConverter.unit.SI
-
 
-
KIBI - Static variable in class org.unitConverter.unit.SI
-
 
-
KILO - Static variable in class org.unitConverter.unit.SI
-
 
-
KILOCALORIE - Static variable in class org.unitConverter.unit.BritishImperial
-
 
-
KILOCALORIE - Static variable in class org.unitConverter.unit.USCustomary
-
 
-
KILOGRAM - Static variable in class org.unitConverter.unit.SI.BaseUnits
-
 
-
KILOGRAM - Static variable in class org.unitConverter.unit.SI
-
 
-
KILOMETRE_PER_HOUR - Static variable in class org.unitConverter.unit.SI
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-12.html b/doc/index-files/index-12.html deleted file mode 100644 index e2c52a6..0000000 --- a/doc/index-files/index-12.html +++ /dev/null @@ -1,167 +0,0 @@ - - - - - -L-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

L

-
-
LEAGUE - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
Length() - Constructor for class org.unitConverter.unit.BritishImperial.Length
-
 
-
LENGTH - Static variable in class org.unitConverter.unit.SI.BaseDimensions
-
 
-
LENGTH - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
Length() - Constructor for class org.unitConverter.unit.USCustomary.Length
-
 
-
LinearUnit - Class in org.unitConverter.unit
-
-
A unit that can be expressed as a product of its base and a number.
-
-
LINK - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
LITRE - Static variable in class org.unitConverter.unit.SI
-
 
-
loadDimensionFile(File) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Adds all dimensions from a file, using data from the database to parse them.
-
-
loadUnitsFile(File) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Adds all units from a file, using data from the database to parse them.
-
-
LONG_TON - Static variable in class org.unitConverter.unit.BritishImperial.Mass
-
 
-
LUMEN - Static variable in class org.unitConverter.unit.SI
-
 
-
LUMINANCE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
LUMINOUS_FLUX - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
LUMINOUS_INTENSITY - Static variable in class org.unitConverter.unit.SI.BaseDimensions
-
 
-
LUMINOUS_INTENSITY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
LUX - Static variable in class org.unitConverter.unit.SI
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-13.html b/doc/index-files/index-13.html deleted file mode 100644 index b11a71d..0000000 --- a/doc/index-files/index-13.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - -M-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

M

-
-
MAGNETIC_FIELD_STRENGTH - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
MAGNETIC_FLUX - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
MAGNETIC_FLUX_DENSITY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
Mass() - Constructor for class org.unitConverter.unit.BritishImperial.Mass
-
 
-
MASS - Static variable in class org.unitConverter.unit.SI.BaseDimensions
-
 
-
MASS - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
Mass() - Constructor for class org.unitConverter.unit.USCustomary.Mass
-
 
-
MASS_CONCENTRATION - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
MASS_DENSITY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
MEBI - Static variable in class org.unitConverter.unit.SI
-
 
-
MEGA - Static variable in class org.unitConverter.unit.SI
-
 
-
METRE - Static variable in class org.unitConverter.unit.SI.BaseUnits
-
 
-
METRE - Static variable in class org.unitConverter.unit.SI
-
 
-
METRE_PER_SECOND - Static variable in class org.unitConverter.unit.SI
-
 
-
MICRO - Static variable in class org.unitConverter.unit.SI
-
 
-
MILE - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
MILE - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
MILLI - Static variable in class org.unitConverter.unit.SI
-
 
-
MINIM - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
minus(LinearUnit) - Method in class org.unitConverter.unit.LinearUnit
-
-
Returns the difference of this unit and another.
-
-
MINUTE - Static variable in class org.unitConverter.unit.SI
-
 
-
MOLE - Static variable in class org.unitConverter.unit.SI.BaseUnits
-
 
-
MOLE - Static variable in class org.unitConverter.unit.SI
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-14.html b/doc/index-files/index-14.html deleted file mode 100644 index 21635ed..0000000 --- a/doc/index-files/index-14.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - -N-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

N

-
-
NameSymbol - Class in org.unitConverter.unit
-
-
A class that can be used to specify names and a symbol for a unit.
-
-
NANO - Static variable in class org.unitConverter.unit.SI
-
 
-
NAUTICAL_MILE - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
NAUTICAL_MILE - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
NEPER - Static variable in class org.unitConverter.unit.SI
-
 
-
NEWTON - Static variable in class org.unitConverter.unit.SI
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-15.html b/doc/index-files/index-15.html deleted file mode 100644 index 55a7057..0000000 --- a/doc/index-files/index-15.html +++ /dev/null @@ -1,209 +0,0 @@ - - - - - -O-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

O

-
-
ObjectProduct<T> - Class in org.unitConverter.math
-
-
An immutable product of multiple objects of a type, such as base units.
-
-
of(String, String) - Static method in class org.unitConverter.unit.NameSymbol
-
-
Gets a NameSymbol with a primary name, a symbol and no other names.
-
-
of(String, String, Set<String>) - Static method in class org.unitConverter.unit.NameSymbol
-
-
Gets a NameSymbol with a primary name, a symbol and additional names.
-
-
of(String, String, String...) - Static method in class org.unitConverter.unit.NameSymbol
-
-
h * Gets a NameSymbol with a primary name, a symbol and additional names.
-
-
of(String, String, String) - Static method in class org.unitConverter.unit.NameSymbol
-
-
Gets a NameSymbol with a primary name, a symbol and an additional name.
-
-
of(String, String, String, String) - Static method in class org.unitConverter.unit.NameSymbol
-
-
Gets a NameSymbol with a primary name, a symbol and additional names.
-
-
of(String, String, String, String, String) - Static method in class org.unitConverter.unit.NameSymbol
-
-
Gets a NameSymbol with a primary name, a symbol and additional names.
-
-
ofName(String) - Static method in class org.unitConverter.unit.NameSymbol
-
-
Gets a NameSymbol with a primary name, no symbol, and no other names.
-
-
ofNullable(String, String, Set<String>) - Static method in class org.unitConverter.unit.NameSymbol
-
-
Gets a NameSymbol with a primary name, a symbol and additional names.
-
-
ofNullable(String, String, String...) - Static method in class org.unitConverter.unit.NameSymbol
-
-
h * Gets a NameSymbol with a primary name, a symbol and additional names.
-
-
ofSymbol(String) - Static method in class org.unitConverter.unit.NameSymbol
-
-
Gets a NameSymbol with a symbol and no names.
-
-
OHM - Static variable in class org.unitConverter.unit.SI
-
 
-
OIL_BARREL - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
ONE - Static variable in class org.unitConverter.unit.SI
-
 
-
oneOf(T) - Static method in class org.unitConverter.math.ObjectProduct
-
-
Gets an ObjectProduct that has one of the inputted argument, and nothing else.
-
-
OPENING_BRACKET - Static variable in class org.unitConverter.math.ExpressionParser
-
-
The opening bracket.
-
-
org.unitConverter - package org.unitConverter
-
-
A program that converts units.
-
-
org.unitConverter.converterGUI - package org.unitConverter.converterGUI
-
-
The GUI interface of the Unit Converter.
-
-
org.unitConverter.math - package org.unitConverter.math
-
-
Supplementary classes that are not related to units, but are necessary for their function.
-
-
org.unitConverter.unit - package org.unitConverter.unit
-
-
Everything to do with the units that make up Unit Converter.
-
-
OUNCE - Static variable in class org.unitConverter.unit.BritishImperial.Mass
-
 
-
OUNCE - Static variable in class org.unitConverter.unit.USCustomary.Mass
-
 
-
OUNCE_FORCE - Static variable in class org.unitConverter.unit.BritishImperial
-
 
-
OUNCE_FORCE - Static variable in class org.unitConverter.unit.USCustomary
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-16.html b/doc/index-files/index-16.html deleted file mode 100644 index 7df017a..0000000 --- a/doc/index-files/index-16.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - -P-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

P

-
-
PARSEC - Static variable in class org.unitConverter.unit.SI
-
 
-
parseExpression(String) - Method in class org.unitConverter.math.ExpressionParser
-
-
Parses an expression.
-
-
PASCAL - Static variable in class org.unitConverter.unit.SI
-
 
-
PEBI - Static variable in class org.unitConverter.unit.SI
-
 
-
PECK - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
PECK - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
PENNYWEIGHT - Static variable in class org.unitConverter.unit.USCustomary.Mass
-
 
-
PERCH - Static variable in class org.unitConverter.unit.BritishImperial.Area
-
 
-
PETA - Static variable in class org.unitConverter.unit.SI
-
 
-
PICA - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
PICO - Static variable in class org.unitConverter.unit.SI
-
 
-
PINT - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
PINT - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
plus(LinearUnit) - Method in class org.unitConverter.unit.LinearUnit
-
-
Returns the sum of this unit and another.
-
-
POINT - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
POUND - Static variable in class org.unitConverter.unit.BritishImperial.Mass
-
 
-
POUND - Static variable in class org.unitConverter.unit.USCustomary.Mass
-
 
-
POUND_FORCE - Static variable in class org.unitConverter.unit.BritishImperial
-
 
-
POUND_FORCE - Static variable in class org.unitConverter.unit.USCustomary
-
 
-
POUND_PER_SQUARE_INCH - Static variable in class org.unitConverter.unit.USCustomary
-
 
-
POWER - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
prefixMap() - Method in class org.unitConverter.unit.UnitDatabase
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-17.html b/doc/index-files/index-17.html deleted file mode 100644 index ce5025c..0000000 --- a/doc/index-files/index-17.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - -Q-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

Q

-
-
QUANTITY - Static variable in class org.unitConverter.unit.SI.BaseDimensions
-
 
-
QUANTITY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
QUART - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
QUART - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
QUARTER - Static variable in class org.unitConverter.unit.BritishImperial.Mass
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-18.html b/doc/index-files/index-18.html deleted file mode 100644 index 087b5ae..0000000 --- a/doc/index-files/index-18.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - -R-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

R

-
-
RADIAN - Static variable in class org.unitConverter.unit.SI
-
 
-
REFLACTIVE_PERMEABILITY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
REFRACTIVE_INDEX - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
ROD - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
ROOD - Static variable in class org.unitConverter.unit.BritishImperial.Area
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-19.html b/doc/index-files/index-19.html deleted file mode 100644 index bfa47d9..0000000 --- a/doc/index-files/index-19.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - -S-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

S

-
-
SECOND - Static variable in class org.unitConverter.unit.SI.BaseUnits
-
 
-
SECOND - Static variable in class org.unitConverter.unit.SI
-
 
-
SECTION - Static variable in class org.unitConverter.unit.USCustomary.Area
-
 
-
SHORT_TON - Static variable in class org.unitConverter.unit.USCustomary.Mass
-
 
-
SHOT - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
SI - Class in org.unitConverter.unit
-
-
All of the units, prefixes and dimensions that are used by the SI, as well as some outside the SI.
-
-
SI.BaseDimensions - Class in org.unitConverter.unit
-
 
-
SI.BaseUnits - Class in org.unitConverter.unit
-
 
-
SI.Constants - Class in org.unitConverter.unit
-
-
Constants that relate to the SI or other systems.
-
-
SI.Dimensions - Class in org.unitConverter.unit
-
 
-
SIEMENS - Static variable in class org.unitConverter.unit.SI
-
 
-
SIEVERT - Static variable in class org.unitConverter.unit.SI
-
 
-
SLUG - Static variable in class org.unitConverter.unit.BritishImperial.Mass
-
 
-
SOLID_ANGLE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
SPECIFIC_ENERGY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
SPECIFIC_VOLUME - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
SQUARE_CHAIN - Static variable in class org.unitConverter.unit.USCustomary.Area
-
 
-
SQUARE_FOOT - Static variable in class org.unitConverter.unit.BritishImperial.Area
-
 
-
SQUARE_METRE - Static variable in class org.unitConverter.unit.SI
-
 
-
SQUARE_MILE - Static variable in class org.unitConverter.unit.BritishImperial.Area
-
 
-
SQUARE_SURVEY_FOOT - Static variable in class org.unitConverter.unit.USCustomary.Area
-
 
-
SQUARE_YARD - Static variable in class org.unitConverter.unit.BritishImperial.Area
-
 
-
STERADIAN - Static variable in class org.unitConverter.unit.SI
-
 
-
STONE - Static variable in class org.unitConverter.unit.BritishImperial.Mass
-
 
-
SURFACE_DENSITY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
SURVEY_CHAIN - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
SURVEY_FOOT - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
SURVEY_FURLONG - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
SURVEY_LEAGUE - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
SURVEY_LINK - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
SURVEY_MILE - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
SURVEY_ROD - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
SURVEY_TOWNSHIP - Static variable in class org.unitConverter.unit.USCustomary.Area
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-2.html b/doc/index-files/index-2.html deleted file mode 100644 index 9c7eab9..0000000 --- a/doc/index-files/index-2.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - -B-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

B

-
-
BARREL - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
BaseDimension - Class in org.unitConverter.unit
-
-
A dimension that defines a BaseUnit
-
-
BaseUnit - Class in org.unitConverter.unit
-
-
A unit that other units are defined by.
-
-
BEL - Static variable in class org.unitConverter.unit.SI
-
 
-
BEQUEREL - Static variable in class org.unitConverter.unit.SI
-
 
-
BIT - Static variable in class org.unitConverter.unit.SI.BaseUnits
-
 
-
BIT - Static variable in class org.unitConverter.unit.SI
-
 
-
BRITISH_THERMAL_UNIT - Static variable in class org.unitConverter.unit.BritishImperial
-
 
-
BRITISH_THERMAL_UNIT - Static variable in class org.unitConverter.unit.USCustomary
-
 
-
BritishImperial - Class in org.unitConverter.unit
-
-
A static utility class that contains units in the British Imperial system.
-
-
BritishImperial() - Constructor for class org.unitConverter.unit.BritishImperial
-
 
-
BritishImperial.Area - Class in org.unitConverter.unit
-
-
Imperial units that measure area
-
-
BritishImperial.Length - Class in org.unitConverter.unit
-
-
Imperial units that measure length
-
-
BritishImperial.Mass - Class in org.unitConverter.unit
-
-
British Imperial units that measure mass.
-
-
BritishImperial.Volume - Class in org.unitConverter.unit
-
-
British Imperial units that measure volume
-
-
build() - Method in class org.unitConverter.math.ExpressionParser.Builder
-
 
-
Builder(Function<String, ? extends T>) - Constructor for class org.unitConverter.math.ExpressionParser.Builder
-
-
Creates the Builder.
-
-
BUSHEL - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
BUSHEL - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
BYTE - Static variable in class org.unitConverter.unit.SI
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-20.html b/doc/index-files/index-20.html deleted file mode 100644 index 4b290ee..0000000 --- a/doc/index-files/index-20.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - -T-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

T

-
-
TABLESPOON - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
TEASPOON - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
TEBI - Static variable in class org.unitConverter.unit.SI
-
 
-
TEMPERATURE - Static variable in class org.unitConverter.unit.SI.BaseDimensions
-
 
-
TEMPERATURE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
TERA - Static variable in class org.unitConverter.unit.SI
-
 
-
TESLA - Static variable in class org.unitConverter.unit.SI
-
 
-
THOU - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
TIME - Static variable in class org.unitConverter.unit.SI.BaseDimensions
-
 
-
TIME - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
times(ObjectProduct<T>) - Method in class org.unitConverter.math.ObjectProduct
-
-
Multiplies this product by another
-
-
times(double) - Method in class org.unitConverter.unit.LinearUnit
-
-
Multiplies this unit by a scalar.
-
-
times(LinearUnit) - Method in class org.unitConverter.unit.LinearUnit
-
-
Returns the product of this unit and another.
-
-
times(double) - Method in class org.unitConverter.unit.UnitPrefix
-
-
Multiplies this prefix by a scalar
-
-
times(UnitPrefix) - Method in class org.unitConverter.unit.UnitPrefix
-
-
Multiplies this prefix by other.
-
-
toExponent(int) - Method in class org.unitConverter.math.ObjectProduct
-
-
Returns this product, but to an exponent
-
-
toExponent(int) - Method in class org.unitConverter.unit.LinearUnit
-
-
Returns this unit but to an exponent.
-
-
toExponent(double) - Method in class org.unitConverter.unit.UnitPrefix
-
-
Raises this prefix to an exponent.
-
-
TONNE - Static variable in class org.unitConverter.unit.SI
-
 
-
toString() - Method in class org.unitConverter.math.ObjectProduct
-
-
Converts this product to a string using the objects' Object.toString() method.
-
-
toString(Function<T, String>) - Method in class org.unitConverter.math.ObjectProduct
-
-
Converts this product to a string.
-
-
toString() - Method in class org.unitConverter.unit.BaseDimension
-
 
-
toString() - Method in class org.unitConverter.unit.BaseUnit
-
 
-
toString() - Method in class org.unitConverter.unit.LinearUnit
-
 
-
toString() - Method in class org.unitConverter.unit.Unit
-
 
-
toString() - Method in class org.unitConverter.unit.UnitDatabase
-
 
-
toString() - Method in class org.unitConverter.unit.UnitPrefix
-
 
-
TROY_OUNCE - Static variable in class org.unitConverter.unit.USCustomary.Mass
-
 
-
TROY_POUND - Static variable in class org.unitConverter.unit.USCustomary.Mass
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-21.html b/doc/index-files/index-21.html deleted file mode 100644 index a89f806..0000000 --- a/doc/index-files/index-21.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - -U-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

U

-
-
Unit - Class in org.unitConverter.unit
-
-
A unit that is composed of base units.
-
-
Unit(ObjectProduct<BaseUnit>, NameSymbol) - Constructor for class org.unitConverter.unit.Unit
-
-
Creates the AbstractUnit.
-
-
UnitDatabase - Class in org.unitConverter.unit
-
-
A database of units, prefixes and dimensions, and their names.
-
-
UnitDatabase() - Constructor for class org.unitConverter.unit.UnitDatabase
-
-
Creates the UnitsDatabase.
-
-
unitMap() - Method in class org.unitConverter.unit.UnitDatabase
-
-
Returns a map mapping unit names to units, including units with prefixes.
-
-
unitMapPrefixless() - Method in class org.unitConverter.unit.UnitDatabase
-
 
-
UnitPrefix - Class in org.unitConverter.unit
-
-
A prefix that can be applied to a LinearUnit to multiply it by some value
-
-
USCustomary - Class in org.unitConverter.unit
-
-
A static utility class that contains units in the US Customary system.
-
-
USCustomary() - Constructor for class org.unitConverter.unit.USCustomary
-
 
-
USCustomary.Area - Class in org.unitConverter.unit
-
-
US Customary units that measure area
-
-
USCustomary.Length - Class in org.unitConverter.unit
-
-
US Customary units that measure length
-
-
USCustomary.Mass - Class in org.unitConverter.unit
-
-
mass units
-
-
USCustomary.Volume - Class in org.unitConverter.unit
-
-
Volume units
-
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-22.html b/doc/index-files/index-22.html deleted file mode 100644 index 91fdc86..0000000 --- a/doc/index-files/index-22.html +++ /dev/null @@ -1,167 +0,0 @@ - - - - - -V-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

V

-
-
valueOf(String, String) - Static method in class org.unitConverter.unit.BaseDimension
-
-
Gets a BaseDimension with the provided name and symbol.
-
-
valueOf(BaseDimension, String, String) - Static method in class org.unitConverter.unit.BaseUnit
-
-
Gets a base unit from the dimension it measures, its name and its symbol.
-
-
valueOf(BaseDimension, String, String, Set<String>) - Static method in class org.unitConverter.unit.BaseUnit
-
-
Gets a base unit from the dimension it measures, its name and its symbol.
-
-
valueOf(ObjectProduct<BaseUnit>, double) - Static method in class org.unitConverter.unit.LinearUnit
-
-
Gets a LinearUnit from a unit base and a conversion factor.
-
-
valueOf(ObjectProduct<BaseUnit>, double, NameSymbol) - Static method in class org.unitConverter.unit.LinearUnit
-
-
Gets a LinearUnit from a unit base and a conversion factor.
-
-
valueOf(double) - Static method in class org.unitConverter.unit.UnitPrefix
-
-
Gets a UnitPrefix from a multiplier
-
-
valueOf(double, NameSymbol) - Static method in class org.unitConverter.unit.UnitPrefix
-
-
Gets a UnitPrefix from a multiplier and a name
-
-
VELOCITY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
VOLT - Static variable in class org.unitConverter.unit.SI
-
 
-
VOLTAGE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
Volume() - Constructor for class org.unitConverter.unit.BritishImperial.Volume
-
 
-
VOLUME - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
Volume() - Constructor for class org.unitConverter.unit.USCustomary.Volume
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-23.html b/doc/index-files/index-23.html deleted file mode 100644 index 18495df..0000000 --- a/doc/index-files/index-23.html +++ /dev/null @@ -1,145 +0,0 @@ - - - - - -W-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

W

-
-
WATT - Static variable in class org.unitConverter.unit.SI
-
 
-
WAVENUMBER - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
WEBER - Static variable in class org.unitConverter.unit.SI
-
 
-
withName(NameSymbol) - Method in class org.unitConverter.unit.BaseUnit
-
 
-
withName(NameSymbol) - Method in class org.unitConverter.unit.LinearUnit
-
 
-
withName(NameSymbol) - Method in class org.unitConverter.unit.Unit
-
 
-
withName(NameSymbol) - Method in class org.unitConverter.unit.UnitPrefix
-
 
-
withPrefix(UnitPrefix) - Method in class org.unitConverter.unit.LinearUnit
-
-
Returns the result of applying prefix to this unit.
-
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-24.html b/doc/index-files/index-24.html deleted file mode 100644 index 34d726e..0000000 --- a/doc/index-files/index-24.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - -Y-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

Y

-
-
YARD - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
-
According to the International Yard and Pound of 1959, a yard is defined as exactly 0.9144 metres.
-
-
YARD - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
YOCTO - Static variable in class org.unitConverter.unit.SI
-
 
-
YOTTA - Static variable in class org.unitConverter.unit.SI
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-25.html b/doc/index-files/index-25.html deleted file mode 100644 index 51be99c..0000000 --- a/doc/index-files/index-25.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - -Z-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

Z

-
-
ZEPTO - Static variable in class org.unitConverter.unit.SI
-
 
-
ZETTA - Static variable in class org.unitConverter.unit.SI
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-3.html b/doc/index-files/index-3.html deleted file mode 100644 index fa9bf6d..0000000 --- a/doc/index-files/index-3.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - -C-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

C

-
-
CABLE - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
CABLE - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
CALORIE - Static variable in class org.unitConverter.unit.BritishImperial
-
 
-
CALORIE - Static variable in class org.unitConverter.unit.USCustomary
-
 
-
canConvertTo(Unit) - Method in class org.unitConverter.unit.Unit
-
-
Checks if a value expressed in this unit can be converted to a value expressed in other
-
-
CANDELA - Static variable in class org.unitConverter.unit.SI.BaseUnits
-
 
-
CANDELA - Static variable in class org.unitConverter.unit.SI
-
 
-
CAPACITANCE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
CATALYTIC_ACTIVITY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
CELSIUS - Static variable in class org.unitConverter.unit.SI
-
 
-
CENTI - Static variable in class org.unitConverter.unit.SI
-
 
-
CHAIN - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
CLOSING_BRACKET - Static variable in class org.unitConverter.math.ExpressionParser
-
-
The closing bracket.
-
-
CONCENTRATION - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
conditionalExistenceCollection(Collection<E>, Predicate<E>) - Static method in class org.unitConverter.math.ConditionalExistenceCollections
-
-
Elements in the returned wrapper collection are ignored if they don't pass a condition.
-
-
ConditionalExistenceCollections - Class in org.unitConverter.math
-
-
Elements in these wrapper collections only exist if they pass a condition.
-
-
ConditionalExistenceCollections() - Constructor for class org.unitConverter.math.ConditionalExistenceCollections
-
 
-
conditionalExistenceIterator(Iterator<E>, Predicate<E>) - Static method in class org.unitConverter.math.ConditionalExistenceCollections
-
-
Elements in the returned wrapper iterator are ignored if they don't pass a condition.
-
-
conditionalExistenceMap(Map<K, V>, Predicate<Map.Entry<K, V>>) - Static method in class org.unitConverter.math.ConditionalExistenceCollections
-
-
Mappings in the returned wrapper map are ignored if the corresponding entry doesn't pass a condition
-
-
conditionalExistenceSet(Set<E>, Predicate<E>) - Static method in class org.unitConverter.math.ConditionalExistenceCollections
-
-
Elements in the returned wrapper set are ignored if they don't pass a condition.
-
-
Constants() - Constructor for class org.unitConverter.unit.SI.Constants
-
 
-
containsDimensionName(String) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Tests if the database has a unit dimension with this name.
-
-
containsPrefixName(String) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Tests if the database has a unit prefix with this name.
-
-
containsUnitName(String) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Tests if the database has a unit with this name, taking prefixes into consideration
-
-
convertFromBase(double) - Method in class org.unitConverter.unit.BaseUnit
-
 
-
convertFromBase(double) - Method in class org.unitConverter.unit.LinearUnit
-
-
Converts from a value expressed in this unit's base unit to a value expressed in this unit.
-
-
convertFromBase(double) - Method in class org.unitConverter.unit.Unit
-
-
Converts from a value expressed in this unit's base unit to a value expressed in this unit.
-
-
convertTo(Unit, double) - Method in class org.unitConverter.unit.Unit
-
-
Converts a value expressed in this unit to a value expressed in other.
-
-
convertToBase(double) - Method in class org.unitConverter.unit.BaseUnit
-
 
-
convertToBase(double) - Method in class org.unitConverter.unit.LinearUnit
-
-
Converts from a value expressed in this unit to a value expressed in this unit's base unit.
-
-
convertToBase(double) - Method in class org.unitConverter.unit.Unit
-
-
Converts from a value expressed in this unit to a value expressed in this unit's base unit.
-
-
COULOMB - Static variable in class org.unitConverter.unit.SI
-
 
-
CUBIC_FOOT - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
CUBIC_FOOT - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
CUBIC_INCH - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
CUBIC_INCH - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
CUBIC_METRE - Static variable in class org.unitConverter.unit.SI
-
 
-
CUBIC_YARD - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
CUBIC_YARD - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
CUP - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
CURRENCY - Static variable in class org.unitConverter.unit.SI.BaseDimensions
-
 
-
CURRENCY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
CURRENT_DENSITY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-4.html b/doc/index-files/index-4.html deleted file mode 100644 index 5dc0100..0000000 --- a/doc/index-files/index-4.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - -D-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

D

-
-
DALTON - Static variable in class org.unitConverter.unit.SI
-
 
-
DAY - Static variable in class org.unitConverter.unit.SI
-
 
-
DECI - Static variable in class org.unitConverter.unit.SI
-
 
-
DECIBEL - Static variable in class org.unitConverter.unit.SI
-
 
-
DecimalComparison - Class in org.unitConverter.math
-
-
A class that contains methods to compare float and double values.
-
-
DEGREE - Static variable in class org.unitConverter.unit.SI
-
 
-
DEKA - Static variable in class org.unitConverter.unit.SI
-
 
-
dimensionMap() - Method in class org.unitConverter.unit.UnitDatabase
-
 
-
dividedBy(ObjectProduct<T>) - Method in class org.unitConverter.math.ObjectProduct
-
-
Calculates the quotient of two products
-
-
dividedBy(double) - Method in class org.unitConverter.unit.LinearUnit
-
-
Divides this unit by a scalar.
-
-
dividedBy(LinearUnit) - Method in class org.unitConverter.unit.LinearUnit
-
-
Returns the quotient of this unit and another.
-
-
dividedBy(double) - Method in class org.unitConverter.unit.UnitPrefix
-
-
Divides this prefix by a scalar
-
-
dividedBy(UnitPrefix) - Method in class org.unitConverter.unit.UnitPrefix
-
-
Divides this prefix by other.
-
-
DOLLAR - Static variable in class org.unitConverter.unit.SI.BaseUnits
-
 
-
DOLLAR - Static variable in class org.unitConverter.unit.SI
-
 
-
DOUBLE_EPSILON - Static variable in class org.unitConverter.math.DecimalComparison
-
-
The value used for double comparison.
-
-
DRACHM - Static variable in class org.unitConverter.unit.BritishImperial.Mass
-
 
-
DRAM - Static variable in class org.unitConverter.unit.USCustomary.Mass
-
 
-
DRY_BARREL - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
DRY_GALLON - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
DRY_PINT - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
DRY_QUART - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-5.html b/doc/index-files/index-5.html deleted file mode 100644 index e939675..0000000 --- a/doc/index-files/index-5.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - - -E-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

E

-
-
EARTH_GRAVITY - Static variable in class org.unitConverter.unit.SI.Constants
-
 
-
ELECTRIC_CHARGE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
ELECTRIC_CONDUCTANCE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
ELECTRIC_CURRENT - Static variable in class org.unitConverter.unit.SI.BaseDimensions
-
 
-
ELECTRIC_CURRENT - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
ELECTRIC_RESISTANCE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
ELECTRONVOLT - Static variable in class org.unitConverter.unit.SI
-
 
-
empty() - Static method in class org.unitConverter.math.ObjectProduct
-
-
Returns an empty ObjectProduct of a certain type
-
-
EMPTY - Static variable in class org.unitConverter.unit.NameSymbol
-
 
-
EMPTY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
ENERGY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
equals(double, double) - Static method in class org.unitConverter.math.DecimalComparison
-
-
Tests for equality of double values using DecimalComparison.DOUBLE_EPSILON.
-
-
equals(double, double, double) - Static method in class org.unitConverter.math.DecimalComparison
-
-
Tests for double equality using a custom epsilon value.
-
-
equals(float, float) - Static method in class org.unitConverter.math.DecimalComparison
-
-
Tests for equality of float values using DecimalComparison.FLOAT_EPSILON.
-
-
equals(float, float, float) - Static method in class org.unitConverter.math.DecimalComparison
-
-
Tests for float equality using a custom epsilon value.
-
-
equals(Object) - Method in class org.unitConverter.math.ObjectProduct
-
 
-
equals(Object) - Method in class org.unitConverter.unit.LinearUnit
-
-
- - Uses the base and conversion factor of units to test for equality.
-
-
equals(Object) - Method in class org.unitConverter.unit.UnitPrefix
-
-
- - Uses the prefix's multiplier to determine equality.
-
-
EXA - Static variable in class org.unitConverter.unit.SI
-
 
-
EXBI - Static variable in class org.unitConverter.unit.SI
-
 
-
exponentMap() - Method in class org.unitConverter.math.ObjectProduct
-
 
-
ExpressionParser<T> - Class in org.unitConverter.math
-
-
An object that can parse expressions with unary or binary operators.
-
-
ExpressionParser.Builder<T> - Class in org.unitConverter.math
-
-
A builder that can create ExpressionParser<T> instances.
-
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-6.html b/doc/index-files/index-6.html deleted file mode 100644 index 627d49d..0000000 --- a/doc/index-files/index-6.html +++ /dev/null @@ -1,181 +0,0 @@ - - - - - -F-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

F

-
-
FAHRENHEIT - Static variable in class org.unitConverter.unit.BritishImperial
-
 
-
FAHRENHEIT - Static variable in class org.unitConverter.unit.USCustomary
-
 
-
FARAD - Static variable in class org.unitConverter.unit.SI
-
 
-
FATHOM - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
FATHOM - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
FEMTO - Static variable in class org.unitConverter.unit.SI
-
 
-
FLOAT_EPSILON - Static variable in class org.unitConverter.math.DecimalComparison
-
-
The value used for float comparison.
-
-
FLUID_DRAM - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
FLUID_OUNCE - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
FLUID_OUNCE - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
FOOT - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
FOOT - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
FOOT_POUND - Static variable in class org.unitConverter.unit.USCustomary
-
 
-
FORCE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
FREQUENCY - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
fromConversionFunctions(ObjectProduct<BaseUnit>, DoubleUnaryOperator, DoubleUnaryOperator) - Static method in class org.unitConverter.unit.Unit
-
-
Returns a unit from its base and the functions it uses to convert to and from its base.
-
-
fromConversionFunctions(ObjectProduct<BaseUnit>, DoubleUnaryOperator, DoubleUnaryOperator, NameSymbol) - Static method in class org.unitConverter.unit.Unit
-
-
Returns a unit from its base and the functions it uses to convert to and from its base.
-
-
fromExponentMapping(Map<T, Integer>) - Static method in class org.unitConverter.math.ObjectProduct
-
-
Gets an ObjectProduct from an object-to-integer mapping
-
-
fromUnitValue(Unit, double) - Static method in class org.unitConverter.unit.LinearUnit
-
-
Gets a LinearUnit from a unit and a value.
-
-
fromUnitValue(Unit, double, NameSymbol) - Static method in class org.unitConverter.unit.LinearUnit
-
-
Gets a LinearUnit from a unit and a value.
-
-
FURLONG - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-7.html b/doc/index-files/index-7.html deleted file mode 100644 index 9ba3b81..0000000 --- a/doc/index-files/index-7.html +++ /dev/null @@ -1,209 +0,0 @@ - - - - - -G-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

G

-
-
GALLON - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
GALLON - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
getBase() - Method in class org.unitConverter.unit.Unit
-
 
-
getBaseDimension() - Method in class org.unitConverter.unit.BaseUnit
-
 
-
getBaseSet() - Method in class org.unitConverter.math.ObjectProduct
-
 
-
getConversionFactor() - Method in class org.unitConverter.unit.LinearUnit
-
 
-
getDimension() - Method in class org.unitConverter.unit.Unit
-
 
-
getDimension(String) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Gets a unit dimension from the database using its name.
-
-
getDimensionFromExpression(String) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Uses the database's data to parse an expression into a unit dimension
-
-
getExponent(T) - Method in class org.unitConverter.math.ObjectProduct
-
-
Gets the exponent for a specific dimension.
-
-
getMultiplier() - Method in class org.unitConverter.unit.UnitPrefix
-
 
-
getName() - Method in class org.unitConverter.unit.BaseDimension
-
 
-
getOtherNames() - Method in class org.unitConverter.unit.NameSymbol
-
 
-
getOtherNames() - Method in class org.unitConverter.unit.Unit
-
 
-
getOtherNames() - Method in class org.unitConverter.unit.UnitPrefix
-
 
-
getPrefix(String) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Gets a unit prefix from the database from its name
-
-
getPrefixFromExpression(String) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Gets a unit prefix from a prefix expression
-
-
getPrimaryName() - Method in class org.unitConverter.unit.NameSymbol
-
 
-
getPrimaryName() - Method in class org.unitConverter.unit.Unit
-
 
-
getPrimaryName() - Method in class org.unitConverter.unit.UnitPrefix
-
 
-
getSymbol() - Method in class org.unitConverter.unit.BaseDimension
-
 
-
getSymbol() - Method in class org.unitConverter.unit.NameSymbol
-
 
-
getSymbol() - Method in class org.unitConverter.unit.Unit
-
 
-
getSymbol() - Method in class org.unitConverter.unit.UnitPrefix
-
 
-
getUnit(String) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Gets a unit from the database from its name, looking for prefixes.
-
-
getUnitFromExpression(String) - Method in class org.unitConverter.unit.UnitDatabase
-
-
Uses the database's unit data to parse an expression into a unit
-
-
GIBI - Static variable in class org.unitConverter.unit.SI
-
 
-
GIGA - Static variable in class org.unitConverter.unit.SI
-
 
-
GILL - Static variable in class org.unitConverter.unit.BritishImperial.Volume
-
 
-
GILL - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
GRAIN - Static variable in class org.unitConverter.unit.BritishImperial.Mass
-
 
-
GRAIN - Static variable in class org.unitConverter.unit.USCustomary.Mass
-
 
-
GRAM - Static variable in class org.unitConverter.unit.SI
-
 
-
GRAY - Static variable in class org.unitConverter.unit.SI
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-8.html b/doc/index-files/index-8.html deleted file mode 100644 index 94afc86..0000000 --- a/doc/index-files/index-8.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - -H-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

H

-
-
HAND - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
hash(double) - Static method in class org.unitConverter.math.DecimalComparison
-
-
Takes the hash code of doubles.
-
-
hashCode() - Method in class org.unitConverter.math.ObjectProduct
-
 
-
hashCode() - Method in class org.unitConverter.unit.LinearUnit
-
-
- - Uses the base and conversion factor to compute a hash code.
-
-
hashCode() - Method in class org.unitConverter.unit.UnitPrefix
-
-
- - Uses the prefix's multiplier to determine a hash code.
-
-
HECTARE - Static variable in class org.unitConverter.unit.SI
-
 
-
HECTO - Static variable in class org.unitConverter.unit.SI
-
 
-
HENRY - Static variable in class org.unitConverter.unit.SI
-
 
-
HERTZ - Static variable in class org.unitConverter.unit.SI
-
 
-
HOGSHEAD - Static variable in class org.unitConverter.unit.USCustomary.Volume
-
 
-
HORSEPOWER - Static variable in class org.unitConverter.unit.USCustomary
-
 
-
HOUR - Static variable in class org.unitConverter.unit.SI
-
 
-
HUNDREDWEIGHT - Static variable in class org.unitConverter.unit.BritishImperial.Mass
-
 
-
HUNDREDWEIGHT - Static variable in class org.unitConverter.unit.USCustomary.Mass
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index-files/index-9.html b/doc/index-files/index-9.html deleted file mode 100644 index bd68fcb..0000000 --- a/doc/index-files/index-9.html +++ /dev/null @@ -1,145 +0,0 @@ - - - - - -I-Index - - - - - - - - -
- - - - - - - -
- - -
A B C D E F G H I J K L M N O P Q R S T U V W Y Z  - - -

I

-
-
ILLUMINANCE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
INCH - Static variable in class org.unitConverter.unit.BritishImperial.Length
-
 
-
INCH - Static variable in class org.unitConverter.unit.USCustomary.Length
-
 
-
INDUCTANCE - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
INFORMATION - Static variable in class org.unitConverter.unit.SI.BaseDimensions
-
 
-
INFORMATION - Static variable in class org.unitConverter.unit.SI.Dimensions
-
 
-
isBase() - Method in class org.unitConverter.unit.LinearUnit
-
 
-
isCoherent() - Method in class org.unitConverter.unit.LinearUnit
-
 
-
isSingleObject() - Method in class org.unitConverter.math.ObjectProduct
-
 
-
-A B C D E F G H I J K L M N O P Q R S T U V W Y Z 
- -
- - - - - - - -
- - - - diff --git a/doc/index.html b/doc/index.html deleted file mode 100644 index 863863b..0000000 --- a/doc/index.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - -Generated Documentation (Untitled) - - - - - - - - - -<noscript> -<div>JavaScript is disabled on your browser.</div> -</noscript> -<h2>Frame Alert</h2> -<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p> - - - diff --git a/doc/jquery/external/jquery/jquery.js b/doc/jquery/external/jquery/jquery.js deleted file mode 100644 index 9b5206b..0000000 --- a/doc/jquery/external/jquery/jquery.js +++ /dev/null @@ -1,10364 +0,0 @@ -/*! - * jQuery JavaScript Library v3.3.1 - * https://jquery.com/ - * - * Includes Sizzle.js - * https://sizzlejs.com/ - * - * Copyright JS Foundation and other contributors - * Released under the MIT license - * https://jquery.org/license - * - * Date: 2018-01-20T17:24Z - */ -( function( global, factory ) { - - "use strict"; - - if ( typeof module === "object" && typeof module.exports === "object" ) { - - // For CommonJS and CommonJS-like environments where a proper `window` - // is present, execute the factory and get jQuery. - // For environments that do not have a `window` with a `document` - // (such as Node.js), expose a factory as module.exports. - // This accentuates the need for the creation of a real `window`. - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - -// Pass this if window is not defined yet -} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - -// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 -// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode -// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common -// enough that all such attempts are guarded in a try block. -"use strict"; - -var arr = []; - -var document = window.document; - -var getProto = Object.getPrototypeOf; - -var slice = arr.slice; - -var concat = arr.concat; - -var push = arr.push; - -var indexOf = arr.indexOf; - -var class2type = {}; - -var toString = class2type.toString; - -var hasOwn = class2type.hasOwnProperty; - -var fnToString = hasOwn.toString; - -var ObjectFunctionString = fnToString.call( Object ); - -var support = {}; - -var isFunction = function isFunction( obj ) { - - // Support: Chrome <=57, Firefox <=52 - // In some browsers, typeof returns "function" for HTML elements - // (i.e., `typeof document.createElement( "object" ) === "function"`). - // We don't want to classify *any* DOM node as a function. - return typeof obj === "function" && typeof obj.nodeType !== "number"; - }; - - -var isWindow = function isWindow( obj ) { - return obj != null && obj === obj.window; - }; - - - - - var preservedScriptAttributes = { - type: true, - src: true, - noModule: true - }; - - function DOMEval( code, doc, node ) { - doc = doc || document; - - var i, - script = doc.createElement( "script" ); - - script.text = code; - if ( node ) { - for ( i in preservedScriptAttributes ) { - if ( node[ i ] ) { - script[ i ] = node[ i ]; - } - } - } - doc.head.appendChild( script ).parentNode.removeChild( script ); - } - - -function toType( obj ) { - if ( obj == null ) { - return obj + ""; - } - - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; -} -/* global Symbol */ -// Defining this global in .eslintrc.json would create a danger of using the global -// unguarded in another place, it seems safer to define global only for this module - - - -var - version = "3.3.1", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, - - // Support: Android <=4.0 only - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; - -jQuery.fn = jQuery.prototype = { - - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - - // Return all the elements in a clean array - if ( num == null ) { - return slice.call( this ); - } - - // Return just the one element from the set - return num < 0 ? this[ num + this.length ] : this[ num ]; - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !isFunction( target ) ) { - target = {}; - } - - // Extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - - // Only deal with non-null/undefined values - if ( ( options = arguments[ i ] ) != null ) { - - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = Array.isArray( copy ) ) ) ) { - - if ( copyIsArray ) { - copyIsArray = false; - clone = src && Array.isArray( src ) ? src : []; - - } else { - clone = src && jQuery.isPlainObject( src ) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend( { - - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - isPlainObject: function( obj ) { - var proto, Ctor; - - // Detect obvious negatives - // Use toString instead of jQuery.type to catch host objects - if ( !obj || toString.call( obj ) !== "[object Object]" ) { - return false; - } - - proto = getProto( obj ); - - // Objects with no prototype (e.g., `Object.create( null )`) are plain - if ( !proto ) { - return true; - } - - // Objects with prototype are plain iff they were constructed by a global Object function - Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; - return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; - }, - - isEmptyObject: function( obj ) { - - /* eslint-disable no-unused-vars */ - // See https://github.com/eslint/eslint/issues/6125 - var name; - - for ( name in obj ) { - return false; - } - return true; - }, - - // Evaluates a script in a global context - globalEval: function( code ) { - DOMEval( code ); - }, - - each: function( obj, callback ) { - var length, i = 0; - - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } - - return obj; - }, - - // Support: Android <=4.0 only - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -} ); - -if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; -} - -// Populate the class2type map -jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -} ); - -function isArrayLike( obj ) { - - // Support: real iOS 8.2 only (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = toType( obj ); - - if ( isFunction( obj ) || isWindow( obj ) ) { - return false; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.3.3 - * https://sizzlejs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2016-08-08 - */ -(function( window ) { - -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - - // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }, - - disabledAncestor = addCombinator( - function( elem ) { - return elem.disabled === true && ("form" in elem || "label" in elem); - }, - { dir: "parentNode", next: "legend" } - ); - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { - - // ID selector - if ( (m = match[1]) ) { - - // Document context - if ( nodeType === 9 ) { - if ( (elem = context.getElementById( m )) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && (elem = newContext.getElementById( m )) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( (m = match[3]) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !compilerCache[ selector + " " ] && - (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - - if ( nodeType !== 1 ) { - newContext = context; - newSelector = selector; - - // qSA looks outside Element context, which is not what we want - // Thanks to Andrew Dupont for this workaround technique - // Support: IE <=8 - // Exclude object elements - } else if ( context.nodeName.toLowerCase() !== "object" ) { - - // Capture the context ID, setting it first if necessary - if ( (nid = context.getAttribute( "id" )) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", (nid = expando) ); - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - while ( i-- ) { - groups[i] = "#" + nid + " " + toSelector( groups[i] ); - } - newSelector = groups.join( "," ); - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created element and returns a boolean result - */ -function assert( fn ) { - var el = document.createElement("fieldset"); - - try { - return !!fn( el ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( el.parentNode ) { - el.parentNode.removeChild( el ); - } - // release memory in IE - el = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for :enabled/:disabled - * @param {Boolean} disabled true for :disabled; false for :enabled - */ -function createDisabledPseudo( disabled ) { - - // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable - return function( elem ) { - - // Only certain elements can match :enabled or :disabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled - if ( "form" in elem ) { - - // Check for inherited disabledness on relevant non-disabled elements: - // * listed form-associated elements in a disabled fieldset - // https://html.spec.whatwg.org/multipage/forms.html#category-listed - // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled - // * option elements in a disabled optgroup - // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled - // All such elements have a "form" property. - if ( elem.parentNode && elem.disabled === false ) { - - // Option elements defer to a parent optgroup if present - if ( "label" in elem ) { - if ( "label" in elem.parentNode ) { - return elem.parentNode.disabled === disabled; - } else { - return elem.disabled === disabled; - } - } - - // Support: IE 6 - 11 - // Use the isDisabled shortcut property to check for disabled fieldset ancestors - return elem.isDisabled === disabled || - - // Where there is no isDisabled, check manually - /* jshint -W018 */ - elem.isDisabled !== !disabled && - disabledAncestor( elem ) === disabled; - } - - return elem.disabled === disabled; - - // Try to winnow out elements that can't be disabled before trusting the disabled property. - // Some victims get caught in our net (label, legend, menu, track), but it shouldn't - // even exist on them, let alone have a boolean value. - } else if ( "label" in elem ) { - return elem.disabled === disabled; - } - - // Remaining elements are neither :enabled nor :disabled - return false; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, subWindow, - doc = node ? node.ownerDocument || node : preferredDoc; - - // Return early if doc is invalid or already selected - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Update global variables - document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); - - // Support: IE 9-11, Edge - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - if ( preferredDoc !== document && - (subWindow = document.defaultView) && subWindow.top !== subWindow ) { - - // Support: IE 11, Edge - if ( subWindow.addEventListener ) { - subWindow.addEventListener( "unload", unloadHandler, false ); - - // Support: IE 9 - 10 only - } else if ( subWindow.attachEvent ) { - subWindow.attachEvent( "onunload", unloadHandler ); - } - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert(function( el ) { - el.className = "i"; - return !el.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( el ) { - el.appendChild( document.createComment("") ); - return !el.getElementsByTagName("*").length; - }); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programmatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( el ) { - docElem.appendChild( el ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; - }); - - // ID filter and find - if ( support.getById ) { - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var elem = context.getElementById( id ); - return elem ? [ elem ] : []; - } - }; - } else { - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - - // Support: IE 6 - 7 only - // getElementById is not reliable as a find shortcut - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var node, i, elems, - elem = context.getElementById( id ); - - if ( elem ) { - - // Verify the id attribute - node = elem.getAttributeNode("id"); - if ( node && node.value === id ) { - return [ elem ]; - } - - // Fall back on getElementsByName - elems = context.getElementsByName( id ); - i = 0; - while ( (elem = elems[i++]) ) { - node = elem.getAttributeNode("id"); - if ( node && node.value === id ) { - return [ elem ]; - } - } - } - - return []; - } - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See https://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( el ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // https://bugs.jquery.com/ticket/12359 - docElem.appendChild( el ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( el.querySelectorAll("[msallowcapture^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push("~="); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !el.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibling-combinator selector` fails - if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push(".#.+[+~]"); - } - }); - - assert(function( el ) { - el.innerHTML = "" + - ""; - - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement("input"); - input.setAttribute( "type", "hidden" ); - el.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( el.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( el.querySelectorAll(":enabled").length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: IE9-11+ - // IE's :disabled selector does not pick up the children of disabled fieldsets - docElem.appendChild( el ).disabled = true; - if ( el.querySelectorAll(":disabled").length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - el.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( el ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( el, "*" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( el, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === document ? -1 : - b === document ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return document; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - if ( support.matchesSelector && documentIsHTML && - !compilerCache[ expr + " " ] && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch (e) {} - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; -}; - -Sizzle.escape = function( sel ) { - return (sel + "").replace( rcssescape, fcssescape ); -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); - - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, context, xml ) { - var cache, uniqueCache, outerCache, node, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType, - diff = false; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) { - - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - - // Seek `elem` from a previously-cached index - - // ...in a gzip-friendly way - node = parent; - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex && cache[ 2 ]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( (node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - } else { - // Use previously-cached element index if available - if ( useCache ) { - // ...in a gzip-friendly way - node = elem; - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex; - } - - // xml :nth-child(...) - // or :nth-last-child(...) or :nth(-last)?-of-type(...) - if ( diff === false ) { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) && - ++diff ) { - - // Cache the index of each encountered element - if ( useCache ) { - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - uniqueCache[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - // Don't keep the element (issue #299) - input[0] = null; - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": createDisabledPseudo( false ), - "disabled": createDisabledPseudo( true ), - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} - -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); - -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - skip = combinator.next, - key = skip || dir, - checkNonElements = base && key === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - return false; - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, uniqueCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); - - if ( skip && skip === elem.nodeName.toLowerCase() ) { - elem = elem[ dir ] || elem; - } else if ( (oldCache = uniqueCache[ key ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - uniqueCache[ key ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } - } - } - } - return false; - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if ( outermost ) { - outermostContext = context === document || context || outermost; - } - - // Add elements passing elementMatchers directly to results - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - if ( !context && elem.ownerDocument !== document ) { - setDocument( elem ); - xml = !documentIsHTML; - } - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context || document, xml) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // `i` is now the count of elements visited above, and adding it to `matchedCount` - // makes the latter nonnegative. - matchedCount += i; - - // Apply set filters to unmatched elements - // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` - // equals `i`), unless we didn't visit _any_ elements in the above loop because we have - // no element matchers and no seed. - // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that - // case, which will result in a "00" `matchedCount` that differs from `i` but is also - // numerically zero. - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); - - results = results || []; - - // Try to minimize operations if there is only one selector in the list and no seed - // (the latter of which guarantees us context) - if ( match.length === 1 ) { - - // Reduce context if the leading compound selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { - - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - !context || rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; - -// Support: Chrome 14-35+ -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( el ) { - // Should return 1, but returns 4 (following) - return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; -}); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( el ) { - el.innerHTML = ""; - return el.firstChild.getAttribute("href") === "#" ; -}) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( el ) { - el.innerHTML = ""; - el.firstChild.setAttribute( "value", "" ); - return el.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( el ) { - return el.getAttribute("disabled") == null; -}) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; - } - }); -} - -return Sizzle; - -})( window ); - - - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; - -// Deprecated -jQuery.expr[ ":" ] = jQuery.expr.pseudos; -jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; -jQuery.escapeSelector = Sizzle.escape; - - - - -var dir = function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; -}; - - -var siblings = function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; -}; - - -var rneedsContext = jQuery.expr.match.needsContext; - - - -function nodeName( elem, name ) { - - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - -}; -var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); - - - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - return !!qualifier.call( elem, i, elem ) !== not; - } ); - } - - // Single element - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - } ); - } - - // Arraylike of elements (jQuery, arguments, Array) - if ( typeof qualifier !== "string" ) { - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) > -1 ) !== not; - } ); - } - - // Filtered directly for both simple and complex selectors - return jQuery.filter( qualifier, elements, not ); -} - -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - if ( elems.length === 1 && elem.nodeType === 1 ) { - return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; - } - - return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - } ) ); -}; - -jQuery.fn.extend( { - find: function( selector ) { - var i, ret, - len = this.length, - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter( function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - } ) ); - } - - ret = this.pushStack( [] ); - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - return len > 1 ? jQuery.uniqueSort( ret ) : ret; - }, - filter: function( selector ) { - return this.pushStack( winnow( this, selector || [], false ) ); - }, - not: function( selector ) { - return this.pushStack( winnow( this, selector || [], true ) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -} ); - - -// Initialize a jQuery object - - -// A central reference to the root jQuery(document) -var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - // Shortcut simple #id case for speed - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, - - init = jQuery.fn.init = function( selector, context, root ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Method init() accepts an alternate rootjQuery - // so migrate can support jQuery.sub (gh-2101) - root = root || rootjQuery; - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[ 0 ] === "<" && - selector[ selector.length - 1 ] === ">" && - selector.length >= 3 ) { - - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && ( match[ 1 ] || !context ) ) { - - // HANDLE: $(html) -> $(array) - if ( match[ 1 ] ) { - context = context instanceof jQuery ? context[ 0 ] : context; - - // Option to run scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[ 1 ], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - - // Properties of context are called as methods if possible - if ( isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[ 2 ] ); - - if ( elem ) { - - // Inject the element directly into the jQuery object - this[ 0 ] = elem; - this.length = 1; - } - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || root ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this[ 0 ] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( isFunction( selector ) ) { - return root.ready !== undefined ? - root.ready( selector ) : - - // Execute immediately if ready is not present - selector( jQuery ); - } - - return jQuery.makeArray( selector, this ); - }; - -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; - -// Initialize central reference -rootjQuery = jQuery( document ); - - -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - - // Methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend( { - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter( function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[ i ] ) ) { - return true; - } - } - } ); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - targets = typeof selectors !== "string" && jQuery( selectors ); - - // Positional selectors never match, since there's no _selection_ context - if ( !rneedsContext.test( selectors ) ) { - for ( ; i < l; i++ ) { - for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { - - // Always skip document fragments - if ( cur.nodeType < 11 && ( targets ? - targets.index( cur ) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector( cur, selectors ) ) ) { - - matched.push( cur ); - break; - } - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); - }, - - // Determine the position of an element within the set - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // Index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.uniqueSort( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - } -} ); - -function sibling( cur, dir ) { - while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} - return cur; -} - -jQuery.each( { - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return siblings( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return siblings( elem.firstChild ); - }, - contents: function( elem ) { - if ( nodeName( elem, "iframe" ) ) { - return elem.contentDocument; - } - - // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only - // Treat the template element as a regular one in browsers that - // don't support it. - if ( nodeName( elem, "template" ) ) { - elem = elem.content || elem; - } - - return jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.uniqueSort( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; -} ); -var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); - - - -// Convert String-formatted options into Object-formatted ones -function createOptions( options ) { - var object = {}; - jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { - object[ flag ] = true; - } ); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - createOptions( options ) : - jQuery.extend( {}, options ); - - var // Flag to know if list is currently firing - firing, - - // Last fire value for non-forgettable lists - memory, - - // Flag to know if list was already fired - fired, - - // Flag to prevent firing - locked, - - // Actual callback list - list = [], - - // Queue of execution data for repeatable lists - queue = [], - - // Index of currently firing callback (modified by add/remove as needed) - firingIndex = -1, - - // Fire callbacks - fire = function() { - - // Enforce single-firing - locked = locked || options.once; - - // Execute callbacks for all pending executions, - // respecting firingIndex overrides and runtime changes - fired = firing = true; - for ( ; queue.length; firingIndex = -1 ) { - memory = queue.shift(); - while ( ++firingIndex < list.length ) { - - // Run callback and check for early termination - if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && - options.stopOnFalse ) { - - // Jump to end and forget the data so .add doesn't re-fire - firingIndex = list.length; - memory = false; - } - } - } - - // Forget the data if we're done with it - if ( !options.memory ) { - memory = false; - } - - firing = false; - - // Clean up if we're done firing for good - if ( locked ) { - - // Keep an empty list if we have data for future add calls - if ( memory ) { - list = []; - - // Otherwise, this object is spent - } else { - list = ""; - } - } - }, - - // Actual Callbacks object - self = { - - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - - // If we have memory from a past run, we should fire after adding - if ( memory && !firing ) { - firingIndex = list.length - 1; - queue.push( memory ); - } - - ( function add( args ) { - jQuery.each( args, function( _, arg ) { - if ( isFunction( arg ) ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && toType( arg ) !== "string" ) { - - // Inspect recursively - add( arg ); - } - } ); - } )( arguments ); - - if ( memory && !firing ) { - fire(); - } - } - return this; - }, - - // Remove a callback from the list - remove: function() { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - - // Handle firing indexes - if ( index <= firingIndex ) { - firingIndex--; - } - } - } ); - return this; - }, - - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? - jQuery.inArray( fn, list ) > -1 : - list.length > 0; - }, - - // Remove all callbacks from the list - empty: function() { - if ( list ) { - list = []; - } - return this; - }, - - // Disable .fire and .add - // Abort any current/pending executions - // Clear all callbacks and values - disable: function() { - locked = queue = []; - list = memory = ""; - return this; - }, - disabled: function() { - return !list; - }, - - // Disable .fire - // Also disable .add unless we have memory (since it would have no effect) - // Abort any pending executions - lock: function() { - locked = queue = []; - if ( !memory && !firing ) { - list = memory = ""; - } - return this; - }, - locked: function() { - return !!locked; - }, - - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( !locked ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - queue.push( args ); - if ( !firing ) { - fire(); - } - } - return this; - }, - - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - -function Identity( v ) { - return v; -} -function Thrower( ex ) { - throw ex; -} - -function adoptValue( value, resolve, reject, noValue ) { - var method; - - try { - - // Check for promise aspect first to privilege synchronous behavior - if ( value && isFunction( ( method = value.promise ) ) ) { - method.call( value ).done( resolve ).fail( reject ); - - // Other thenables - } else if ( value && isFunction( ( method = value.then ) ) ) { - method.call( value, resolve, reject ); - - // Other non-thenables - } else { - - // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: - // * false: [ value ].slice( 0 ) => resolve( value ) - // * true: [ value ].slice( 1 ) => resolve() - resolve.apply( undefined, [ value ].slice( noValue ) ); - } - - // For Promises/A+, convert exceptions into rejections - // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in - // Deferred#then to conditionally suppress rejection. - } catch ( value ) { - - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - reject.apply( undefined, [ value ] ); - } -} - -jQuery.extend( { - - Deferred: function( func ) { - var tuples = [ - - // action, add listener, callbacks, - // ... .then handlers, argument index, [final state] - [ "notify", "progress", jQuery.Callbacks( "memory" ), - jQuery.Callbacks( "memory" ), 2 ], - [ "resolve", "done", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 0, "resolved" ], - [ "reject", "fail", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 1, "rejected" ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - "catch": function( fn ) { - return promise.then( null, fn ); - }, - - // Keep pipe for back-compat - pipe: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - - return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - - // Map tuples (progress, done, fail) to arguments (done, fail, progress) - var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; - - // deferred.progress(function() { bind to newDefer or newDefer.notify }) - // deferred.done(function() { bind to newDefer or newDefer.resolve }) - // deferred.fail(function() { bind to newDefer or newDefer.reject }) - deferred[ tuple[ 1 ] ]( function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && isFunction( returned.promise ) ) { - returned.promise() - .progress( newDefer.notify ) - .done( newDefer.resolve ) - .fail( newDefer.reject ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( - this, - fn ? [ returned ] : arguments - ); - } - } ); - } ); - fns = null; - } ).promise(); - }, - then: function( onFulfilled, onRejected, onProgress ) { - var maxDepth = 0; - function resolve( depth, deferred, handler, special ) { - return function() { - var that = this, - args = arguments, - mightThrow = function() { - var returned, then; - - // Support: Promises/A+ section 2.3.3.3.3 - // https://promisesaplus.com/#point-59 - // Ignore double-resolution attempts - if ( depth < maxDepth ) { - return; - } - - returned = handler.apply( that, args ); - - // Support: Promises/A+ section 2.3.1 - // https://promisesaplus.com/#point-48 - if ( returned === deferred.promise() ) { - throw new TypeError( "Thenable self-resolution" ); - } - - // Support: Promises/A+ sections 2.3.3.1, 3.5 - // https://promisesaplus.com/#point-54 - // https://promisesaplus.com/#point-75 - // Retrieve `then` only once - then = returned && - - // Support: Promises/A+ section 2.3.4 - // https://promisesaplus.com/#point-64 - // Only check objects and functions for thenability - ( typeof returned === "object" || - typeof returned === "function" ) && - returned.then; - - // Handle a returned thenable - if ( isFunction( then ) ) { - - // Special processors (notify) just wait for resolution - if ( special ) { - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ) - ); - - // Normal processors (resolve) also hook into progress - } else { - - // ...and disregard older resolution values - maxDepth++; - - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ), - resolve( maxDepth, deferred, Identity, - deferred.notifyWith ) - ); - } - - // Handle all other returned values - } else { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Identity ) { - that = undefined; - args = [ returned ]; - } - - // Process the value(s) - // Default process is resolve - ( special || deferred.resolveWith )( that, args ); - } - }, - - // Only normal processors (resolve) catch and reject exceptions - process = special ? - mightThrow : - function() { - try { - mightThrow(); - } catch ( e ) { - - if ( jQuery.Deferred.exceptionHook ) { - jQuery.Deferred.exceptionHook( e, - process.stackTrace ); - } - - // Support: Promises/A+ section 2.3.3.3.4.1 - // https://promisesaplus.com/#point-61 - // Ignore post-resolution exceptions - if ( depth + 1 >= maxDepth ) { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Thrower ) { - that = undefined; - args = [ e ]; - } - - deferred.rejectWith( that, args ); - } - } - }; - - // Support: Promises/A+ section 2.3.3.3.1 - // https://promisesaplus.com/#point-57 - // Re-resolve promises immediately to dodge false rejection from - // subsequent errors - if ( depth ) { - process(); - } else { - - // Call an optional hook to record the stack, in case of exception - // since it's otherwise lost when execution goes async - if ( jQuery.Deferred.getStackHook ) { - process.stackTrace = jQuery.Deferred.getStackHook(); - } - window.setTimeout( process ); - } - }; - } - - return jQuery.Deferred( function( newDefer ) { - - // progress_handlers.add( ... ) - tuples[ 0 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onProgress ) ? - onProgress : - Identity, - newDefer.notifyWith - ) - ); - - // fulfilled_handlers.add( ... ) - tuples[ 1 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onFulfilled ) ? - onFulfilled : - Identity - ) - ); - - // rejected_handlers.add( ... ) - tuples[ 2 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onRejected ) ? - onRejected : - Thrower - ) - ); - } ).promise(); - }, - - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 5 ]; - - // promise.progress = list.add - // promise.done = list.add - // promise.fail = list.add - promise[ tuple[ 1 ] ] = list.add; - - // Handle state - if ( stateString ) { - list.add( - function() { - - // state = "resolved" (i.e., fulfilled) - // state = "rejected" - state = stateString; - }, - - // rejected_callbacks.disable - // fulfilled_callbacks.disable - tuples[ 3 - i ][ 2 ].disable, - - // rejected_handlers.disable - // fulfilled_handlers.disable - tuples[ 3 - i ][ 3 ].disable, - - // progress_callbacks.lock - tuples[ 0 ][ 2 ].lock, - - // progress_handlers.lock - tuples[ 0 ][ 3 ].lock - ); - } - - // progress_handlers.fire - // fulfilled_handlers.fire - // rejected_handlers.fire - list.add( tuple[ 3 ].fire ); - - // deferred.notify = function() { deferred.notifyWith(...) } - // deferred.resolve = function() { deferred.resolveWith(...) } - // deferred.reject = function() { deferred.rejectWith(...) } - deferred[ tuple[ 0 ] ] = function() { - deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); - return this; - }; - - // deferred.notifyWith = list.fireWith - // deferred.resolveWith = list.fireWith - // deferred.rejectWith = list.fireWith - deferred[ tuple[ 0 ] + "With" ] = list.fireWith; - } ); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( singleValue ) { - var - - // count of uncompleted subordinates - remaining = arguments.length, - - // count of unprocessed arguments - i = remaining, - - // subordinate fulfillment data - resolveContexts = Array( i ), - resolveValues = slice.call( arguments ), - - // the master Deferred - master = jQuery.Deferred(), - - // subordinate callback factory - updateFunc = function( i ) { - return function( value ) { - resolveContexts[ i ] = this; - resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( !( --remaining ) ) { - master.resolveWith( resolveContexts, resolveValues ); - } - }; - }; - - // Single- and empty arguments are adopted like Promise.resolve - if ( remaining <= 1 ) { - adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, - !remaining ); - - // Use .then() to unwrap secondary thenables (cf. gh-3000) - if ( master.state() === "pending" || - isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { - - return master.then(); - } - } - - // Multiple arguments are aggregated like Promise.all array elements - while ( i-- ) { - adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); - } - - return master.promise(); - } -} ); - - -// These usually indicate a programmer mistake during development, -// warn about them ASAP rather than swallowing them by default. -var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; - -jQuery.Deferred.exceptionHook = function( error, stack ) { - - // Support: IE 8 - 9 only - // Console exists when dev tools are open, which can happen at any time - if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { - window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); - } -}; - - - - -jQuery.readyException = function( error ) { - window.setTimeout( function() { - throw error; - } ); -}; - - - - -// The deferred used on DOM ready -var readyList = jQuery.Deferred(); - -jQuery.fn.ready = function( fn ) { - - readyList - .then( fn ) - - // Wrap jQuery.readyException in a function so that the lookup - // happens at the time of error handling instead of callback - // registration. - .catch( function( error ) { - jQuery.readyException( error ); - } ); - - return this; -}; - -jQuery.extend( { - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - } -} ); - -jQuery.ready.then = readyList.then; - -// The ready event handler and self cleanup method -function completed() { - document.removeEventListener( "DOMContentLoaded", completed ); - window.removeEventListener( "load", completed ); - jQuery.ready(); -} - -// Catch cases where $(document).ready() is called -// after the browser event has already occurred. -// Support: IE <=9 - 10 only -// Older IE sometimes signals "interactive" too soon -if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { - - // Handle it asynchronously to allow scripts the opportunity to delay ready - window.setTimeout( jQuery.ready ); - -} else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed ); -} - - - - -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( toType( key ) === "object" ) { - chainable = true; - for ( i in key ) { - access( elems, fn, i, key[ i ], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( - elems[ i ], key, raw ? - value : - value.call( elems[ i ], i, fn( elems[ i ], key ) ) - ); - } - } - } - - if ( chainable ) { - return elems; - } - - // Gets - if ( bulk ) { - return fn.call( elems ); - } - - return len ? fn( elems[ 0 ], key ) : emptyGet; -}; - - -// Matches dashed string for camelizing -var rmsPrefix = /^-ms-/, - rdashAlpha = /-([a-z])/g; - -// Used by camelCase as callback to replace() -function fcamelCase( all, letter ) { - return letter.toUpperCase(); -} - -// Convert dashed to camelCase; used by the css and data modules -// Support: IE <=9 - 11, Edge 12 - 15 -// Microsoft forgot to hump their vendor prefix (#9572) -function camelCase( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); -} -var acceptData = function( owner ) { - - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; - - - - -function Data() { - this.expando = jQuery.expando + Data.uid++; -} - -Data.uid = 1; - -Data.prototype = { - - cache: function( owner ) { - - // Check if the owner object already has a cache - var value = owner[ this.expando ]; - - // If not, create one - if ( !value ) { - value = {}; - - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return an empty object. - if ( acceptData( owner ) ) { - - // If it is a node unlikely to be stringify-ed or looped over - // use plain assignment - if ( owner.nodeType ) { - owner[ this.expando ] = value; - - // Otherwise secure it in a non-enumerable property - // configurable must be true to allow the property to be - // deleted when data is removed - } else { - Object.defineProperty( owner, this.expando, { - value: value, - configurable: true - } ); - } - } - } - - return value; - }, - set: function( owner, data, value ) { - var prop, - cache = this.cache( owner ); - - // Handle: [ owner, key, value ] args - // Always use camelCase key (gh-2257) - if ( typeof data === "string" ) { - cache[ camelCase( data ) ] = value; - - // Handle: [ owner, { properties } ] args - } else { - - // Copy the properties one-by-one to the cache object - for ( prop in data ) { - cache[ camelCase( prop ) ] = data[ prop ]; - } - } - return cache; - }, - get: function( owner, key ) { - return key === undefined ? - this.cache( owner ) : - - // Always use camelCase key (gh-2257) - owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; - }, - access: function( owner, key, value ) { - - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ( ( key && typeof key === "string" ) && value === undefined ) ) { - - return this.get( owner, key ); - } - - // When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, - cache = owner[ this.expando ]; - - if ( cache === undefined ) { - return; - } - - if ( key !== undefined ) { - - // Support array or space separated string of keys - if ( Array.isArray( key ) ) { - - // If key is an array of keys... - // We always set camelCase keys, so remove that. - key = key.map( camelCase ); - } else { - key = camelCase( key ); - - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - key = key in cache ? - [ key ] : - ( key.match( rnothtmlwhite ) || [] ); - } - - i = key.length; - - while ( i-- ) { - delete cache[ key[ i ] ]; - } - } - - // Remove the expando if there's no more data - if ( key === undefined || jQuery.isEmptyObject( cache ) ) { - - // Support: Chrome <=35 - 45 - // Webkit & Blink performance suffers when deleting properties - // from DOM nodes, so set to undefined instead - // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) - if ( owner.nodeType ) { - owner[ this.expando ] = undefined; - } else { - delete owner[ this.expando ]; - } - } - }, - hasData: function( owner ) { - var cache = owner[ this.expando ]; - return cache !== undefined && !jQuery.isEmptyObject( cache ); - } -}; -var dataPriv = new Data(); - -var dataUser = new Data(); - - - -// Implementation Summary -// -// 1. Enforce API surface and semantic compatibility with 1.9.x branch -// 2. Improve the module's maintainability by reducing the storage -// paths to a single mechanism. -// 3. Use the same single mechanism to support "private" and "user" data. -// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) -// 5. Avoid exposing implementation details on user objects (eg. expando properties) -// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 - -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /[A-Z]/g; - -function getData( data ) { - if ( data === "true" ) { - return true; - } - - if ( data === "false" ) { - return false; - } - - if ( data === "null" ) { - return null; - } - - // Only convert to a number if it doesn't change the string - if ( data === +data + "" ) { - return +data; - } - - if ( rbrace.test( data ) ) { - return JSON.parse( data ); - } - - return data; -} - -function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = getData( data ); - } catch ( e ) {} - - // Make sure we set the data so it isn't changed later - dataUser.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; -} - -jQuery.extend( { - hasData: function( elem ) { - return dataUser.hasData( elem ) || dataPriv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return dataUser.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - dataUser.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to dataPriv methods, these can be deprecated. - _data: function( elem, name, data ) { - return dataPriv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - dataPriv.remove( elem, name ); - } -} ); - -jQuery.fn.extend( { - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = dataUser.get( elem ); - - if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE 11 only - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = camelCase( name.slice( 5 ) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - dataPriv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each( function() { - dataUser.set( this, key ); - } ); - } - - return access( this, function( value ) { - var data; - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - - // Attempt to get data from the cache - // The key will always be camelCased in Data - data = dataUser.get( elem, key ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, key ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - this.each( function() { - - // We always store the camelCased key - dataUser.set( this, key, value ); - } ); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each( function() { - dataUser.remove( this, key ); - } ); - } -} ); - - -jQuery.extend( { - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = dataPriv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || Array.isArray( data ) ) { - queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // Clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // Not public - generate a queueHooks object, or return the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { - empty: jQuery.Callbacks( "once memory" ).add( function() { - dataPriv.remove( elem, [ type + "queue", key ] ); - } ) - } ); - } -} ); - -jQuery.fn.extend( { - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[ 0 ], type ); - } - - return data === undefined ? - this : - this.each( function() { - var queue = jQuery.queue( this, type, data ); - - // Ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - } ); - }, - dequeue: function( type ) { - return this.each( function() { - jQuery.dequeue( this, type ); - } ); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -} ); -var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; - -var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); - - -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var isHiddenWithinTree = function( elem, el ) { - - // isHiddenWithinTree might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - - // Inline style trumps all - return elem.style.display === "none" || - elem.style.display === "" && - - // Otherwise, check computed style - // Support: Firefox <=43 - 45 - // Disconnected elements can have computed display: none, so first confirm that elem is - // in the document. - jQuery.contains( elem.ownerDocument, elem ) && - - jQuery.css( elem, "display" ) === "none"; - }; - -var swap = function( elem, options, callback, args ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.apply( elem, args || [] ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - - - -function adjustCSS( elem, prop, valueParts, tween ) { - var adjusted, scale, - maxIterations = 20, - currentValue = tween ? - function() { - return tween.cur(); - } : - function() { - return jQuery.css( elem, prop, "" ); - }, - initial = currentValue(), - unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && - rcssNum.exec( jQuery.css( elem, prop ) ); - - if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { - - // Support: Firefox <=54 - // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) - initial = initial / 2; - - // Trust units reported by jQuery.css - unit = unit || initialInUnit[ 3 ]; - - // Iteratively approximate from a nonzero starting point - initialInUnit = +initial || 1; - - while ( maxIterations-- ) { - - // Evaluate and update our best guess (doubling guesses that zero out). - // Finish if the scale equals or crosses 1 (making the old*new product non-positive). - jQuery.style( elem, prop, initialInUnit + unit ); - if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { - maxIterations = 0; - } - initialInUnit = initialInUnit / scale; - - } - - initialInUnit = initialInUnit * 2; - jQuery.style( elem, prop, initialInUnit + unit ); - - // Make sure we update the tween properties later on - valueParts = valueParts || []; - } - - if ( valueParts ) { - initialInUnit = +initialInUnit || +initial || 0; - - // Apply relative offset (+=/-=) if specified - adjusted = valueParts[ 1 ] ? - initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : - +valueParts[ 2 ]; - if ( tween ) { - tween.unit = unit; - tween.start = initialInUnit; - tween.end = adjusted; - } - } - return adjusted; -} - - -var defaultDisplayMap = {}; - -function getDefaultDisplay( elem ) { - var temp, - doc = elem.ownerDocument, - nodeName = elem.nodeName, - display = defaultDisplayMap[ nodeName ]; - - if ( display ) { - return display; - } - - temp = doc.body.appendChild( doc.createElement( nodeName ) ); - display = jQuery.css( temp, "display" ); - - temp.parentNode.removeChild( temp ); - - if ( display === "none" ) { - display = "block"; - } - defaultDisplayMap[ nodeName ] = display; - - return display; -} - -function showHide( elements, show ) { - var display, elem, - values = [], - index = 0, - length = elements.length; - - // Determine new display value for elements that need to change - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - - display = elem.style.display; - if ( show ) { - - // Since we force visibility upon cascade-hidden elements, an immediate (and slow) - // check is required in this first loop unless we have a nonempty display value (either - // inline or about-to-be-restored) - if ( display === "none" ) { - values[ index ] = dataPriv.get( elem, "display" ) || null; - if ( !values[ index ] ) { - elem.style.display = ""; - } - } - if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { - values[ index ] = getDefaultDisplay( elem ); - } - } else { - if ( display !== "none" ) { - values[ index ] = "none"; - - // Remember what we're overwriting - dataPriv.set( elem, "display", display ); - } - } - } - - // Set the display of the elements in a second loop to avoid constant reflow - for ( index = 0; index < length; index++ ) { - if ( values[ index ] != null ) { - elements[ index ].style.display = values[ index ]; - } - } - - return elements; -} - -jQuery.fn.extend( { - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state ) { - if ( typeof state === "boolean" ) { - return state ? this.show() : this.hide(); - } - - return this.each( function() { - if ( isHiddenWithinTree( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - } ); - } -} ); -var rcheckableType = ( /^(?:checkbox|radio)$/i ); - -var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); - -var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); - - - -// We have to close these tags to support XHTML (#13200) -var wrapMap = { - - // Support: IE <=9 only - option: [ 1, "" ], - - // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten - // this by omitting or other required elements. - thead: [ 1, "", "
" ], - col: [ 2, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - - _default: [ 0, "", "" ] -}; - -// Support: IE <=9 only -wrapMap.optgroup = wrapMap.option; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - - -function getAll( context, tag ) { - - // Support: IE <=9 - 11 only - // Use typeof to avoid zero-argument method invocation on host objects (#15151) - var ret; - - if ( typeof context.getElementsByTagName !== "undefined" ) { - ret = context.getElementsByTagName( tag || "*" ); - - } else if ( typeof context.querySelectorAll !== "undefined" ) { - ret = context.querySelectorAll( tag || "*" ); - - } else { - ret = []; - } - - if ( tag === undefined || tag && nodeName( context, tag ) ) { - return jQuery.merge( [ context ], ret ); - } - - return ret; -} - - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - dataPriv.set( - elems[ i ], - "globalEval", - !refElements || dataPriv.get( refElements[ i ], "globalEval" ) - ); - } -} - - -var rhtml = /<|&#?\w+;/; - -function buildFragment( elems, context, scripts, selection, ignored ) { - var elem, tmp, tag, wrap, contains, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( toType( elem ) === "object" ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Ensure the created nodes are orphaned (#12392) - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( ( elem = nodes[ i++ ] ) ) { - - // Skip elements already in the context collection (trac-4087) - if ( selection && jQuery.inArray( elem, selection ) > -1 ) { - if ( ignored ) { - ignored.push( elem ); - } - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( ( elem = tmp[ j++ ] ) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; -} - - -( function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Android <=4.1 only - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE <=11 only - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -} )(); -var documentElement = document.documentElement; - - - -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -// Support: IE <=9 only -// See #13393 for more info -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -function on( elem, types, selector, data, fn, one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - on( elem, type, selector, data, types[ type ], one ); - } - return elem; - } - - if ( data == null && fn == null ) { - - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return elem; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return elem.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - } ); -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.get( elem ); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Ensure that invalid selectors throw exceptions at attach time - // Evaluate against documentElement in case elem is a non-element node (e.g., document) - if ( selector ) { - jQuery.find.matchesSelector( documentElement, selector ); - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !( events = elemData.events ) ) { - events = elemData.events = {}; - } - if ( !( eventHandle = elemData.handle ) ) { - eventHandle = elemData.handle = function( e ) { - - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend( { - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join( "." ) - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !( handlers = events[ type ] ) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || - special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); - - if ( !elemData || !( events = elemData.events ) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[ 2 ] && - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || - selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || - special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove data and the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - dataPriv.remove( elem, "handle events" ); - } - }, - - dispatch: function( nativeEvent ) { - - // Make a writable jQuery.Event from the native event object - var event = jQuery.event.fix( nativeEvent ); - - var i, j, ret, matched, handleObj, handlerQueue, - args = new Array( arguments.length ), - handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[ 0 ] = event; - - for ( i = 1; i < arguments.length; i++ ) { - args[ i ] = arguments[ i ]; - } - - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( ( handleObj = matched.handlers[ j++ ] ) && - !event.isImmediatePropagationStopped() ) { - - // Triggered event must either 1) have no namespace, or 2) have namespace(s) - // a subset or equal to those in the bound event (both can have no namespace). - if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || - handleObj.handler ).apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( ( event.result = ret ) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, handleObj, sel, matchedHandlers, matchedSelectors, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - if ( delegateCount && - - // Support: IE <=9 - // Black-hole SVG instance trees (trac-13180) - cur.nodeType && - - // Support: Firefox <=42 - // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) - // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click - // Support: IE 11 only - // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) - !( event.type === "click" && event.button >= 1 ) ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { - matchedHandlers = []; - matchedSelectors = {}; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matchedSelectors[ sel ] === undefined ) { - matchedSelectors[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) > -1 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matchedSelectors[ sel ] ) { - matchedHandlers.push( handleObj ); - } - } - if ( matchedHandlers.length ) { - handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); - } - } - } - } - - // Add the remaining (directly-bound) handlers - cur = this; - if ( delegateCount < handlers.length ) { - handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); - } - - return handlerQueue; - }, - - addProp: function( name, hook ) { - Object.defineProperty( jQuery.Event.prototype, name, { - enumerable: true, - configurable: true, - - get: isFunction( hook ) ? - function() { - if ( this.originalEvent ) { - return hook( this.originalEvent ); - } - } : - function() { - if ( this.originalEvent ) { - return this.originalEvent[ name ]; - } - }, - - set: function( value ) { - Object.defineProperty( this, name, { - enumerable: true, - configurable: true, - writable: true, - value: value - } ); - } - } ); - }, - - fix: function( originalEvent ) { - return originalEvent[ jQuery.expando ] ? - originalEvent : - new jQuery.Event( originalEvent ); - }, - - special: { - load: { - - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - this.focus(); - return false; - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - } -}; - -jQuery.removeEvent = function( elem, type, handle ) { - - // This "if" is needed for plain objects - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle ); - } -}; - -jQuery.Event = function( src, props ) { - - // Allow instantiation without the 'new' keyword - if ( !( this instanceof jQuery.Event ) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - - // Support: Android <=2.3 only - src.returnValue === false ? - returnTrue : - returnFalse; - - // Create target properties - // Support: Safari <=6 - 7 only - // Target should not be a text node (#504, #13143) - this.target = ( src.target && src.target.nodeType === 3 ) ? - src.target.parentNode : - src.target; - - this.currentTarget = src.currentTarget; - this.relatedTarget = src.relatedTarget; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || Date.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - constructor: jQuery.Event, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - isSimulated: false, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && !this.isSimulated ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } -}; - -// Includes all common event props including KeyEvent and MouseEvent specific props -jQuery.each( { - altKey: true, - bubbles: true, - cancelable: true, - changedTouches: true, - ctrlKey: true, - detail: true, - eventPhase: true, - metaKey: true, - pageX: true, - pageY: true, - shiftKey: true, - view: true, - "char": true, - charCode: true, - key: true, - keyCode: true, - button: true, - buttons: true, - clientX: true, - clientY: true, - offsetX: true, - offsetY: true, - pointerId: true, - pointerType: true, - screenX: true, - screenY: true, - targetTouches: true, - toElement: true, - touches: true, - - which: function( event ) { - var button = event.button; - - // Add which for key events - if ( event.which == null && rkeyEvent.test( event.type ) ) { - return event.charCode != null ? event.charCode : event.keyCode; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { - if ( button & 1 ) { - return 1; - } - - if ( button & 2 ) { - return 3; - } - - if ( button & 4 ) { - return 2; - } - - return 0; - } - - return event.which; - } -}, jQuery.event.addProp ); - -// Create mouseenter/leave events using mouseover/out and event-time checks -// so that event delegation works in jQuery. -// Do the same for pointerenter/pointerleave and pointerover/pointerout -// -// Support: Safari 7 only -// Safari sends mouseenter too often; see: -// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 -// for the description of the bug (it existed in older Chrome versions as well). -jQuery.each( { - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mouseenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -} ); - -jQuery.fn.extend( { - - on: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn ); - }, - one: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? - handleObj.origType + "." + handleObj.namespace : - handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each( function() { - jQuery.event.remove( this, types, fn, selector ); - } ); - } -} ); - - -var - - /* eslint-disable max-len */ - - // See https://github.com/eslint/eslint/issues/3229 - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, - - /* eslint-enable */ - - // Support: IE <=10 - 11, Edge 12 - 13 only - // In IE/Edge using regex groups here causes severe slowdowns. - // See https://connect.microsoft.com/IE/feedback/details/1736512/ - rnoInnerhtml = /\s*$/g; - -// Prefer a tbody over its parent table for containing new rows -function manipulationTarget( elem, content ) { - if ( nodeName( elem, "table" ) && - nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { - - return jQuery( elem ).children( "tbody" )[ 0 ] || elem; - } - - return elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { - elem.type = elem.type.slice( 5 ); - } else { - elem.removeAttribute( "type" ); - } - - return elem; -} - -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.access( src ); - pdataCur = dataPriv.set( dest, pdataOld ); - events = pdataOld.events; - - if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( dataUser.hasData( src ) ) { - udataOld = dataUser.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - dataUser.set( dest, udataCur ); - } -} - -// Fix IE bugs, see support tests -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -function domManip( collection, args, callback, ignored ) { - - // Flatten any nested arrays - args = concat.apply( [], args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = collection.length, - iNoClone = l - 1, - value = args[ 0 ], - valueIsFunction = isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( valueIsFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return collection.each( function( index ) { - var self = collection.eq( index ); - if ( valueIsFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - domManip( self, args, callback, ignored ); - } ); - } - - if ( l ) { - fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - // Require either new content or an interest in ignored elements to invoke the callback - if ( first || ignored ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item - // instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( collection[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !dataPriv.access( node, "globalEval" ) && - jQuery.contains( doc, node ) ) { - - if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { - - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); - } - } - } - } - } - } - - return collection; -} - -function remove( elem, selector, keepData ) { - var node, - nodes = selector ? jQuery.filter( selector, elem ) : elem, - i = 0; - - for ( ; ( node = nodes[ i ] ) != null; i++ ) { - if ( !keepData && node.nodeType === 1 ) { - jQuery.cleanData( getAll( node ) ); - } - - if ( node.parentNode ) { - if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { - setGlobalEval( getAll( node, "script" ) ); - } - node.parentNode.removeChild( node ); - } - } - - return elem; -} - -jQuery.extend( { - htmlPrefilter: function( html ) { - return html.replace( rxhtmlTag, "<$1>" ); - }, - - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); - - // Fix IE cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - cleanData: function( elems ) { - var data, elem, type, - special = jQuery.event.special, - i = 0; - - for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { - if ( acceptData( elem ) ) { - if ( ( data = elem[ dataPriv.expando ] ) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataPriv.expando ] = undefined; - } - if ( elem[ dataUser.expando ] ) { - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataUser.expando ] = undefined; - } - } - } - } -} ); - -jQuery.fn.extend( { - detach: function( selector ) { - return remove( this, selector, true ); - }, - - remove: function( selector ) { - return remove( this, selector ); - }, - - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each( function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - } ); - }, null, value, arguments.length ); - }, - - append: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - } ); - }, - - prepend: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - } ); - }, - - before: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - } ); - }, - - after: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - } ); - }, - - empty: function() { - var elem, - i = 0; - - for ( ; ( elem = this[ i ] ) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - } ); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = jQuery.htmlPrefilter( value ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch ( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var ignored = []; - - // Make the changes, replacing each non-ignored context element with the new content - return domManip( this, arguments, function( elem ) { - var parent = this.parentNode; - - if ( jQuery.inArray( this, ignored ) < 0 ) { - jQuery.cleanData( getAll( this ) ); - if ( parent ) { - parent.replaceChild( elem, this ); - } - } - - // Force callback invocation - }, ignored ); - } -} ); - -jQuery.each( { - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: Android <=4.0 only, PhantomJS 1 only - // .get() because push.apply(_, arraylike) throws on ancient WebKit - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -} ); -var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); - -var getStyles = function( elem ) { - - // Support: IE <=11 only, Firefox <=30 (#15098, #14150) - // IE throws on elements created in popups - // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" - var view = elem.ownerDocument.defaultView; - - if ( !view || !view.opener ) { - view = window; - } - - return view.getComputedStyle( elem ); - }; - -var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); - - - -( function() { - - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computeStyleTests() { - - // This is a singleton, we need to execute it only once - if ( !div ) { - return; - } - - container.style.cssText = "position:absolute;left:-11111px;width:60px;" + - "margin-top:1px;padding:0;border:0"; - div.style.cssText = - "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + - "margin:auto;border:1px;padding:1px;" + - "width:60%;top:1%"; - documentElement.appendChild( container ).appendChild( div ); - - var divStyle = window.getComputedStyle( div ); - pixelPositionVal = divStyle.top !== "1%"; - - // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 - reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; - - // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 - // Some styles come back with percentage values, even though they shouldn't - div.style.right = "60%"; - pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; - - // Support: IE 9 - 11 only - // Detect misreporting of content dimensions for box-sizing:border-box elements - boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; - - // Support: IE 9 only - // Detect overflow:scroll screwiness (gh-3699) - div.style.position = "absolute"; - scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; - - documentElement.removeChild( container ); - - // Nullify the div so it wouldn't be stored in the memory and - // it will also be a sign that checks already performed - div = null; - } - - function roundPixelMeasures( measure ) { - return Math.round( parseFloat( measure ) ); - } - - var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, - reliableMarginLeftVal, - container = document.createElement( "div" ), - div = document.createElement( "div" ); - - // Finish early in limited (non-browser) environments - if ( !div.style ) { - return; - } - - // Support: IE <=9 - 11 only - // Style of cloned element affects source element cloned (#8908) - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - jQuery.extend( support, { - boxSizingReliable: function() { - computeStyleTests(); - return boxSizingReliableVal; - }, - pixelBoxStyles: function() { - computeStyleTests(); - return pixelBoxStylesVal; - }, - pixelPosition: function() { - computeStyleTests(); - return pixelPositionVal; - }, - reliableMarginLeft: function() { - computeStyleTests(); - return reliableMarginLeftVal; - }, - scrollboxSize: function() { - computeStyleTests(); - return scrollboxSizeVal; - } - } ); -} )(); - - -function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - - // Support: Firefox 51+ - // Retrieving style before computed somehow - // fixes an issue with getting wrong values - // on detached elements - style = elem.style; - - computed = computed || getStyles( elem ); - - // getPropertyValue is needed for: - // .css('filter') (IE 9 only, #12537) - // .css('--customProperty) (#3144) - if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; - - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { - ret = jQuery.style( elem, name ); - } - - // A tribute to the "awesome hack by Dean Edwards" - // Android Browser returns percentage for some values, - // but width seems to be reliably pixels. - // This is against the CSSOM draft spec: - // https://drafts.csswg.org/cssom/#resolved-values - if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret !== undefined ? - - // Support: IE <=9 - 11 only - // IE returns zIndex value as an integer. - ret + "" : - ret; -} - - -function addGetHookIf( conditionFn, hookFn ) { - - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { - - // Hook not needed (or it's not possible to use it due - // to missing dependency), remove it. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - return ( this.get = hookFn ).apply( this, arguments ); - } - }; -} - - -var - - // Swappable if display is none or starts with table - // except "table", "table-cell", or "table-caption" - // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rcustomProp = /^--/, - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }, - - cssPrefixes = [ "Webkit", "Moz", "ms" ], - emptyStyle = document.createElement( "div" ).style; - -// Return a css property mapped to a potentially vendor prefixed property -function vendorPropName( name ) { - - // Shortcut for names that are not vendor prefixed - if ( name in emptyStyle ) { - return name; - } - - // Check for vendor prefixed names - var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in emptyStyle ) { - return name; - } - } -} - -// Return a property mapped along what jQuery.cssProps suggests or to -// a vendor prefixed property. -function finalPropName( name ) { - var ret = jQuery.cssProps[ name ]; - if ( !ret ) { - ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; - } - return ret; -} - -function setPositiveNumber( elem, value, subtract ) { - - // Any relative (+/-) values have already been - // normalized at this point - var matches = rcssNum.exec( value ); - return matches ? - - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : - value; -} - -function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { - var i = dimension === "width" ? 1 : 0, - extra = 0, - delta = 0; - - // Adjustment may not be necessary - if ( box === ( isBorderBox ? "border" : "content" ) ) { - return 0; - } - - for ( ; i < 4; i += 2 ) { - - // Both box models exclude margin - if ( box === "margin" ) { - delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); - } - - // If we get here with a content-box, we're seeking "padding" or "border" or "margin" - if ( !isBorderBox ) { - - // Add padding - delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - - // For "border" or "margin", add border - if ( box !== "padding" ) { - delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - - // But still keep track of it otherwise - } else { - extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - - // If we get here with a border-box (content + padding + border), we're seeking "content" or - // "padding" or "margin" - } else { - - // For "content", subtract padding - if ( box === "content" ) { - delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } - - // For "content" or "padding", subtract border - if ( box !== "margin" ) { - delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } - - // Account for positive content-box scroll gutter when requested by providing computedVal - if ( !isBorderBox && computedVal >= 0 ) { - - // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border - // Assuming integer scroll gutter, subtract the rest and round down - delta += Math.max( 0, Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - computedVal - - delta - - extra - - 0.5 - ) ); - } - - return delta; -} - -function getWidthOrHeight( elem, dimension, extra ) { - - // Start with computed style - var styles = getStyles( elem ), - val = curCSS( elem, dimension, styles ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - valueIsBorderBox = isBorderBox; - - // Support: Firefox <=54 - // Return a confounding non-pixel value or feign ignorance, as appropriate. - if ( rnumnonpx.test( val ) ) { - if ( !extra ) { - return val; - } - val = "auto"; - } - - // Check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = valueIsBorderBox && - ( support.boxSizingReliable() || val === elem.style[ dimension ] ); - - // Fall back to offsetWidth/offsetHeight when value is "auto" - // This happens for inline elements with no explicit setting (gh-3571) - // Support: Android <=4.1 - 4.3 only - // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) - if ( val === "auto" || - !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { - - val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; - - // offsetWidth/offsetHeight provide border-box values - valueIsBorderBox = true; - } - - // Normalize "" and auto - val = parseFloat( val ) || 0; - - // Adjust for the element's box model - return ( val + - boxModelAdjustment( - elem, - dimension, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles, - - // Provide the current computed size to request scroll gutter calculation (gh-3589) - val - ) - ) + "px"; -} - -jQuery.extend( { - - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - } - } - } - }, - - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "animationIterationCount": true, - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: {}, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ), - style = elem.style; - - // Make sure that we're working with the right name. We don't - // want to query the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Gets hook for the prefixed version, then unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // Convert "+=" or "-=" to relative numbers (#7345) - if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { - value = adjustCSS( elem, name, ret ); - - // Fixes bug #9237 - type = "number"; - } - - // Make sure that null and NaN values aren't set (#7116) - if ( value == null || value !== value ) { - return; - } - - // If a number was passed in, add the unit (except for certain CSS properties) - if ( type === "number" ) { - value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); - } - - // background-* props affect original clone's values - if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { - style[ name ] = "inherit"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !( "set" in hooks ) || - ( value = hooks.set( elem, value, extra ) ) !== undefined ) { - - if ( isCustomProp ) { - style.setProperty( name, value ); - } else { - style[ name ] = value; - } - } - - } else { - - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && - ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { - - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, extra, styles ) { - var val, num, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ); - - // Make sure that we're working with the right name. We don't - // want to modify the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Try prefixed name followed by the unprefixed name - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name, styles ); - } - - // Convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Make numeric if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || isFinite( num ) ? num || 0 : val; - } - - return val; - } -} ); - -jQuery.each( [ "height", "width" ], function( i, dimension ) { - jQuery.cssHooks[ dimension ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - - // Certain elements can have dimension info if we invisibly show them - // but it must have a current display style that would benefit - return rdisplayswap.test( jQuery.css( elem, "display" ) ) && - - // Support: Safari 8+ - // Table columns in Safari have non-zero offsetWidth & zero - // getBoundingClientRect().width unless display is changed. - // Support: IE <=11 only - // Running getBoundingClientRect on a disconnected node - // in IE throws an error. - ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? - swap( elem, cssShow, function() { - return getWidthOrHeight( elem, dimension, extra ); - } ) : - getWidthOrHeight( elem, dimension, extra ); - } - }, - - set: function( elem, value, extra ) { - var matches, - styles = getStyles( elem ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - subtract = extra && boxModelAdjustment( - elem, - dimension, - extra, - isBorderBox, - styles - ); - - // Account for unreliable border-box dimensions by comparing offset* to computed and - // faking a content-box to get border and padding (gh-3699) - if ( isBorderBox && support.scrollboxSize() === styles.position ) { - subtract -= Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - parseFloat( styles[ dimension ] ) - - boxModelAdjustment( elem, dimension, "border", false, styles ) - - 0.5 - ); - } - - // Convert to pixels if value adjustment is needed - if ( subtract && ( matches = rcssNum.exec( value ) ) && - ( matches[ 3 ] || "px" ) !== "px" ) { - - elem.style[ dimension ] = value; - value = jQuery.css( elem, dimension ); - } - - return setPositiveNumber( elem, value, subtract ); - } - }; -} ); - -jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, - function( elem, computed ) { - if ( computed ) { - return ( parseFloat( curCSS( elem, "marginLeft" ) ) || - elem.getBoundingClientRect().left - - swap( elem, { marginLeft: 0 }, function() { - return elem.getBoundingClientRect().left; - } ) - ) + "px"; - } - } -); - -// These hooks are used by animate to expand properties -jQuery.each( { - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i = 0, - expanded = {}, - - // Assumes a single number if not a string - parts = typeof value === "string" ? value.split( " " ) : [ value ]; - - for ( ; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } - - return expanded; - } - }; - - if ( prefix !== "margin" ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -} ); - -jQuery.fn.extend( { - css: function( name, value ) { - return access( this, function( elem, name, value ) { - var styles, len, - map = {}, - i = 0; - - if ( Array.isArray( name ) ) { - styles = getStyles( elem ); - len = name.length; - - for ( ; i < len; i++ ) { - map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); - } - - return map; - } - - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - } -} ); - - -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; - -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || jQuery.easing._default; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; - - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; - - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; - - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; - -Tween.prototype.init.prototype = Tween.prototype; - -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; - - // Use a property on the element directly when it is not a DOM element, - // or when there is no matching style property that exists. - if ( tween.elem.nodeType !== 1 || - tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { - return tween.elem[ tween.prop ]; - } - - // Passing an empty string as a 3rd parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails. - // Simple values such as "10px" are parsed to Float; - // complex values such as "rotate(1rad)" are returned as-is. - result = jQuery.css( tween.elem, tween.prop, "" ); - - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - - // Use step hook for back compat. - // Use cssHook if its there. - // Use .style if available and use plain properties where available. - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.nodeType === 1 && - ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || - jQuery.cssHooks[ tween.prop ] ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Support: IE <=9 only -// Panic based approach to setting things on disconnected nodes -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p * Math.PI ) / 2; - }, - _default: "swing" -}; - -jQuery.fx = Tween.prototype.init; - -// Back compat <1.8 extension point -jQuery.fx.step = {}; - - - - -var - fxNow, inProgress, - rfxtypes = /^(?:toggle|show|hide)$/, - rrun = /queueHooks$/; - -function schedule() { - if ( inProgress ) { - if ( document.hidden === false && window.requestAnimationFrame ) { - window.requestAnimationFrame( schedule ); - } else { - window.setTimeout( schedule, jQuery.fx.interval ); - } - - jQuery.fx.tick(); - } -} - -// Animations created synchronously will run synchronously -function createFxNow() { - window.setTimeout( function() { - fxNow = undefined; - } ); - return ( fxNow = Date.now() ); -} - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - i = 0, - attrs = { height: type }; - - // If we include width, step value is 1 to do all cssExpand values, - // otherwise step value is 2 to skip over Left and Right - includeWidth = includeWidth ? 1 : 0; - for ( ; i < 4; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } - - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } - - return attrs; -} - -function createTween( value, prop, animation ) { - var tween, - collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { - - // We're done with this property - return tween; - } - } -} - -function defaultPrefilter( elem, props, opts ) { - var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, - isBox = "width" in props || "height" in props, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHiddenWithinTree( elem ), - dataShow = dataPriv.get( elem, "fxshow" ); - - // Queue-skipping animations hijack the fx hooks - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always( function() { - - // Ensure the complete handler is called before this completes - anim.always( function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - } ); - } ); - } - - // Detect show/hide animations - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.test( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { - - // Pretend to be hidden if this is a "show" and - // there is still data from a stopped show/hide - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; - - // Ignore all other no-op show/hide data - } else { - continue; - } - } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - } - } - - // Bail out if this is a no-op like .hide().hide() - propTween = !jQuery.isEmptyObject( props ); - if ( !propTween && jQuery.isEmptyObject( orig ) ) { - return; - } - - // Restrict "overflow" and "display" styles during box animations - if ( isBox && elem.nodeType === 1 ) { - - // Support: IE <=9 - 11, Edge 12 - 15 - // Record all 3 overflow attributes because IE does not infer the shorthand - // from identically-valued overflowX and overflowY and Edge just mirrors - // the overflowX value there. - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Identify a display type, preferring old show/hide data over the CSS cascade - restoreDisplay = dataShow && dataShow.display; - if ( restoreDisplay == null ) { - restoreDisplay = dataPriv.get( elem, "display" ); - } - display = jQuery.css( elem, "display" ); - if ( display === "none" ) { - if ( restoreDisplay ) { - display = restoreDisplay; - } else { - - // Get nonempty value(s) by temporarily forcing visibility - showHide( [ elem ], true ); - restoreDisplay = elem.style.display || restoreDisplay; - display = jQuery.css( elem, "display" ); - showHide( [ elem ] ); - } - } - - // Animate inline elements as inline-block - if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { - if ( jQuery.css( elem, "float" ) === "none" ) { - - // Restore the original display value at the end of pure show/hide animations - if ( !propTween ) { - anim.done( function() { - style.display = restoreDisplay; - } ); - if ( restoreDisplay == null ) { - display = style.display; - restoreDisplay = display === "none" ? "" : display; - } - } - style.display = "inline-block"; - } - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - anim.always( function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - } ); - } - - // Implement show/hide animations - propTween = false; - for ( prop in orig ) { - - // General show/hide setup for this element animation - if ( !propTween ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; - } - } else { - dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); - } - - // Store hidden/visible for toggle so `.stop().toggle()` "reverses" - if ( toggle ) { - dataShow.hidden = !hidden; - } - - // Show elements before animating them - if ( hidden ) { - showHide( [ elem ], true ); - } - - /* eslint-disable no-loop-func */ - - anim.done( function() { - - /* eslint-enable no-loop-func */ - - // The final step of a "hide" animation is actually hiding the element - if ( !hidden ) { - showHide( [ elem ] ); - } - dataPriv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - } ); - } - - // Per-property setup - propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = propTween.start; - if ( hidden ) { - propTween.end = propTween.start; - propTween.start = 0; - } - } - } -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( Array.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } - - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; - } - - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; - - // Not quite $.extend, this won't overwrite existing keys. - // Reusing 'index' because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; - } - } -} - -function Animation( elem, properties, options ) { - var result, - stopped, - index = 0, - length = Animation.prefilters.length, - deferred = jQuery.Deferred().always( function() { - - // Don't match elem in the :animated selector - delete tick.elem; - } ), - tick = function() { - if ( stopped ) { - return false; - } - var currentTime = fxNow || createFxNow(), - remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - - // Support: Android 2.3 only - // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) - temp = remaining / animation.duration || 0, - percent = 1 - temp, - index = 0, - length = animation.tweens.length; - - for ( ; index < length; index++ ) { - animation.tweens[ index ].run( percent ); - } - - deferred.notifyWith( elem, [ animation, percent, remaining ] ); - - // If there's more to do, yield - if ( percent < 1 && length ) { - return remaining; - } - - // If this was an empty animation, synthesize a final progress notification - if ( !length ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - } - - // Resolve the animation and report its conclusion - deferred.resolveWith( elem, [ animation ] ); - return false; - }, - animation = deferred.promise( { - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { - specialEasing: {}, - easing: jQuery.easing._default - }, options ), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function( prop, end ) { - var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); - animation.tweens.push( tween ); - return tween; - }, - stop: function( gotoEnd ) { - var index = 0, - - // If we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - if ( stopped ) { - return this; - } - stopped = true; - for ( ; index < length; index++ ) { - animation.tweens[ index ].run( 1 ); - } - - // Resolve when we played the last frame; otherwise, reject - if ( gotoEnd ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - deferred.resolveWith( elem, [ animation, gotoEnd ] ); - } else { - deferred.rejectWith( elem, [ animation, gotoEnd ] ); - } - return this; - } - } ), - props = animation.props; - - propFilter( props, animation.opts.specialEasing ); - - for ( ; index < length; index++ ) { - result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - if ( isFunction( result.stop ) ) { - jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = - result.stop.bind( result ); - } - return result; - } - } - - jQuery.map( props, createTween, animation ); - - if ( isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - // Attach callbacks from options - animation - .progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); - - jQuery.fx.timer( - jQuery.extend( tick, { - elem: elem, - anim: animation, - queue: animation.opts.queue - } ) - ); - - return animation; -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweeners: { - "*": [ function( prop, value ) { - var tween = this.createTween( prop, value ); - adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); - return tween; - } ] - }, - - tweener: function( props, callback ) { - if ( isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.match( rnothtmlwhite ); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length; index++ ) { - prop = props[ index ]; - Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; - Animation.tweeners[ prop ].unshift( callback ); - } - }, - - prefilters: [ defaultPrefilter ], - - prefilter: function( callback, prepend ) { - if ( prepend ) { - Animation.prefilters.unshift( callback ); - } else { - Animation.prefilters.push( callback ); - } - } -} ); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !isFunction( easing ) && easing - }; - - // Go to the end state if fx are off - if ( jQuery.fx.off ) { - opt.duration = 0; - - } else { - if ( typeof opt.duration !== "number" ) { - if ( opt.duration in jQuery.fx.speeds ) { - opt.duration = jQuery.fx.speeds[ opt.duration ]; - - } else { - opt.duration = jQuery.fx.speeds._default; - } - } - } - - // Normalize opt.queue - true/undefined/null -> "fx" - if ( opt.queue == null || opt.queue === true ) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function() { - if ( isFunction( opt.old ) ) { - opt.old.call( this ); - } - - if ( opt.queue ) { - jQuery.dequeue( this, opt.queue ); - } - }; - - return opt; -}; - -jQuery.fn.extend( { - fadeTo: function( speed, to, easing, callback ) { - - // Show any hidden elements after setting opacity to 0 - return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() - - // Animate to the value specified - .end().animate( { opacity: to }, speed, easing, callback ); - }, - animate: function( prop, speed, easing, callback ) { - var empty = jQuery.isEmptyObject( prop ), - optall = jQuery.speed( speed, easing, callback ), - doAnimation = function() { - - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - - // Empty animations, or finishing resolves immediately - if ( empty || dataPriv.get( this, "finish" ) ) { - anim.stop( true ); - } - }; - doAnimation.finish = doAnimation; - - return empty || optall.queue === false ? - this.each( doAnimation ) : - this.queue( optall.queue, doAnimation ); - }, - stop: function( type, clearQueue, gotoEnd ) { - var stopQueue = function( hooks ) { - var stop = hooks.stop; - delete hooks.stop; - stop( gotoEnd ); - }; - - if ( typeof type !== "string" ) { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if ( clearQueue && type !== false ) { - this.queue( type || "fx", [] ); - } - - return this.each( function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = dataPriv.get( this ); - - if ( index ) { - if ( data[ index ] && data[ index ].stop ) { - stopQueue( data[ index ] ); - } - } else { - for ( index in data ) { - if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { - stopQueue( data[ index ] ); - } - } - } - - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && - ( type == null || timers[ index ].queue === type ) ) { - - timers[ index ].anim.stop( gotoEnd ); - dequeue = false; - timers.splice( index, 1 ); - } - } - - // Start the next in the queue if the last step wasn't forced. - // Timers currently will call their complete callbacks, which - // will dequeue but only if they were gotoEnd. - if ( dequeue || !gotoEnd ) { - jQuery.dequeue( this, type ); - } - } ); - }, - finish: function( type ) { - if ( type !== false ) { - type = type || "fx"; - } - return this.each( function() { - var index, - data = dataPriv.get( this ), - queue = data[ type + "queue" ], - hooks = data[ type + "queueHooks" ], - timers = jQuery.timers, - length = queue ? queue.length : 0; - - // Enable finishing flag on private data - data.finish = true; - - // Empty the queue first - jQuery.queue( this, type, [] ); - - if ( hooks && hooks.stop ) { - hooks.stop.call( this, true ); - } - - // Look for any active animations, and finish them - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && timers[ index ].queue === type ) { - timers[ index ].anim.stop( true ); - timers.splice( index, 1 ); - } - } - - // Look for any animations in the old queue and finish them - for ( index = 0; index < length; index++ ) { - if ( queue[ index ] && queue[ index ].finish ) { - queue[ index ].finish.call( this ); - } - } - - // Turn off finishing flag - delete data.finish; - } ); - } -} ); - -jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { - var cssFn = jQuery.fn[ name ]; - jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" ? - cssFn.apply( this, arguments ) : - this.animate( genFx( name, true ), speed, easing, callback ); - }; -} ); - -// Generate shortcuts for custom animations -jQuery.each( { - slideDown: genFx( "show" ), - slideUp: genFx( "hide" ), - slideToggle: genFx( "toggle" ), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } -}, function( name, props ) { - jQuery.fn[ name ] = function( speed, easing, callback ) { - return this.animate( props, speed, easing, callback ); - }; -} ); - -jQuery.timers = []; -jQuery.fx.tick = function() { - var timer, - i = 0, - timers = jQuery.timers; - - fxNow = Date.now(); - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - - // Run the timer and safely remove it when done (allowing for external removal) - if ( !timer() && timers[ i ] === timer ) { - timers.splice( i--, 1 ); - } - } - - if ( !timers.length ) { - jQuery.fx.stop(); - } - fxNow = undefined; -}; - -jQuery.fx.timer = function( timer ) { - jQuery.timers.push( timer ); - jQuery.fx.start(); -}; - -jQuery.fx.interval = 13; -jQuery.fx.start = function() { - if ( inProgress ) { - return; - } - - inProgress = true; - schedule(); -}; - -jQuery.fx.stop = function() { - inProgress = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - - // Default speed - _default: 400 -}; - - -// Based off of the plugin by Clint Helfers, with permission. -// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ -jQuery.fn.delay = function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = window.setTimeout( next, time ); - hooks.stop = function() { - window.clearTimeout( timeout ); - }; - } ); -}; - - -( function() { - var input = document.createElement( "input" ), - select = document.createElement( "select" ), - opt = select.appendChild( document.createElement( "option" ) ); - - input.type = "checkbox"; - - // Support: Android <=4.3 only - // Default value for a checkbox should be "on" - support.checkOn = input.value !== ""; - - // Support: IE <=11 only - // Must access selectedIndex to make default options select - support.optSelected = opt.selected; - - // Support: IE <=11 only - // An input loses its value after becoming a radio - input = document.createElement( "input" ); - input.value = "t"; - input.type = "radio"; - support.radioValue = input.value === "t"; -} )(); - - -var boolHook, - attrHandle = jQuery.expr.attrHandle; - -jQuery.fn.extend( { - attr: function( name, value ) { - return access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each( function() { - jQuery.removeAttr( this, name ); - } ); - } -} ); - -jQuery.extend( { - attr: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set attributes on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return jQuery.prop( elem, name, value ); - } - - // Attribute hooks are determined by the lowercase version - // Grab necessary hook if one is defined - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - hooks = jQuery.attrHooks[ name.toLowerCase() ] || - ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); - } - - if ( value !== undefined ) { - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return; - } - - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - elem.setAttribute( name, value + "" ); - return value; - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - ret = jQuery.find.attr( elem, name ); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? undefined : ret; - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !support.radioValue && value === "radio" && - nodeName( elem, "input" ) ) { - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } - }, - - removeAttr: function( elem, value ) { - var name, - i = 0, - - // Attribute names can contain non-HTML whitespace characters - // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 - attrNames = value && value.match( rnothtmlwhite ); - - if ( attrNames && elem.nodeType === 1 ) { - while ( ( name = attrNames[ i++ ] ) ) { - elem.removeAttribute( name ); - } - } - } -} ); - -// Hooks for boolean attributes -boolHook = { - set: function( elem, value, name ) { - if ( value === false ) { - - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - elem.setAttribute( name, name ); - } - return name; - } -}; - -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { - var getter = attrHandle[ name ] || jQuery.find.attr; - - attrHandle[ name ] = function( elem, name, isXML ) { - var ret, handle, - lowercaseName = name.toLowerCase(); - - if ( !isXML ) { - - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[ lowercaseName ]; - attrHandle[ lowercaseName ] = ret; - ret = getter( elem, name, isXML ) != null ? - lowercaseName : - null; - attrHandle[ lowercaseName ] = handle; - } - return ret; - }; -} ); - - - - -var rfocusable = /^(?:input|select|textarea|button)$/i, - rclickable = /^(?:a|area)$/i; - -jQuery.fn.extend( { - prop: function( name, value ) { - return access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - return this.each( function() { - delete this[ jQuery.propFix[ name ] || name ]; - } ); - } -} ); - -jQuery.extend( { - prop: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set properties on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - return ( elem[ name ] = value ); - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - return elem[ name ]; - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - - // Support: IE <=9 - 11 only - // elem.tabIndex doesn't always return the - // correct value when it hasn't been explicitly set - // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - // Use proper attribute retrieval(#12072) - var tabindex = jQuery.find.attr( elem, "tabindex" ); - - if ( tabindex ) { - return parseInt( tabindex, 10 ); - } - - if ( - rfocusable.test( elem.nodeName ) || - rclickable.test( elem.nodeName ) && - elem.href - ) { - return 0; - } - - return -1; - } - } - }, - - propFix: { - "for": "htmlFor", - "class": "className" - } -} ); - -// Support: IE <=11 only -// Accessing the selectedIndex property -// forces the browser to respect setting selected -// on the option -// The getter ensures a default option is selected -// when in an optgroup -// eslint rule "no-unused-expressions" is disabled for this code -// since it considers such accessions noop -if ( !support.optSelected ) { - jQuery.propHooks.selected = { - get: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent && parent.parentNode ) { - parent.parentNode.selectedIndex; - } - return null; - }, - set: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent ) { - parent.selectedIndex; - - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - } - }; -} - -jQuery.each( [ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" -], function() { - jQuery.propFix[ this.toLowerCase() ] = this; -} ); - - - - - // Strip and collapse whitespace according to HTML spec - // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace - function stripAndCollapse( value ) { - var tokens = value.match( rnothtmlwhite ) || []; - return tokens.join( " " ); - } - - -function getClass( elem ) { - return elem.getAttribute && elem.getAttribute( "class" ) || ""; -} - -function classesToArray( value ) { - if ( Array.isArray( value ) ) { - return value; - } - if ( typeof value === "string" ) { - return value.match( rnothtmlwhite ) || []; - } - return []; -} - -jQuery.fn.extend( { - addClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - if ( !arguments.length ) { - return this.attr( "class", "" ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - - // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) > -1 ) { - cur = cur.replace( " " + clazz + " ", " " ); - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isValidValue = type === "string" || Array.isArray( value ); - - if ( typeof stateVal === "boolean" && isValidValue ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - - if ( isFunction( value ) ) { - return this.each( function( i ) { - jQuery( this ).toggleClass( - value.call( this, i, getClass( this ), stateVal ), - stateVal - ); - } ); - } - - return this.each( function() { - var className, i, self, classNames; - - if ( isValidValue ) { - - // Toggle individual class names - i = 0; - self = jQuery( this ); - classNames = classesToArray( value ); - - while ( ( className = classNames[ i++ ] ) ) { - - // Check each className given, space separated list - if ( self.hasClass( className ) ) { - self.removeClass( className ); - } else { - self.addClass( className ); - } - } - - // Toggle whole class name - } else if ( value === undefined || type === "boolean" ) { - className = getClass( this ); - if ( className ) { - - // Store className if set - dataPriv.set( this, "__className__", className ); - } - - // If the element has a class name or if we're passed `false`, - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - if ( this.setAttribute ) { - this.setAttribute( "class", - className || value === false ? - "" : - dataPriv.get( this, "__className__" ) || "" - ); - } - } - } ); - }, - - hasClass: function( selector ) { - var className, elem, - i = 0; - - className = " " + selector + " "; - while ( ( elem = this[ i++ ] ) ) { - if ( elem.nodeType === 1 && - ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { - return true; - } - } - - return false; - } -} ); - - - - -var rreturn = /\r/g; - -jQuery.fn.extend( { - val: function( value ) { - var hooks, ret, valueIsFunction, - elem = this[ 0 ]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || - jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && - "get" in hooks && - ( ret = hooks.get( elem, "value" ) ) !== undefined - ) { - return ret; - } - - ret = elem.value; - - // Handle most common string cases - if ( typeof ret === "string" ) { - return ret.replace( rreturn, "" ); - } - - // Handle cases where value is null/undef or number - return ret == null ? "" : ret; - } - - return; - } - - valueIsFunction = isFunction( value ); - - return this.each( function( i ) { - var val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( valueIsFunction ) { - val = value.call( this, i, jQuery( this ).val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - - } else if ( typeof val === "number" ) { - val += ""; - - } else if ( Array.isArray( val ) ) { - val = jQuery.map( val, function( value ) { - return value == null ? "" : value + ""; - } ); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - } ); - } -} ); - -jQuery.extend( { - valHooks: { - option: { - get: function( elem ) { - - var val = jQuery.find.attr( elem, "value" ); - return val != null ? - val : - - // Support: IE <=10 - 11 only - // option.text throws exceptions (#14686, #14858) - // Strip and collapse whitespace - // https://html.spec.whatwg.org/#strip-and-collapse-whitespace - stripAndCollapse( jQuery.text( elem ) ); - } - }, - select: { - get: function( elem ) { - var value, option, i, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one", - values = one ? null : [], - max = one ? index + 1 : options.length; - - if ( index < 0 ) { - i = max; - - } else { - i = one ? index : 0; - } - - // Loop through all the selected options - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Support: IE <=9 only - // IE8-9 doesn't update selected after form reset (#2551) - if ( ( option.selected || i === index ) && - - // Don't return options that are disabled or in a disabled optgroup - !option.disabled && - ( !option.parentNode.disabled || - !nodeName( option.parentNode, "optgroup" ) ) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - }, - - set: function( elem, value ) { - var optionSet, option, - options = elem.options, - values = jQuery.makeArray( value ), - i = options.length; - - while ( i-- ) { - option = options[ i ]; - - /* eslint-disable no-cond-assign */ - - if ( option.selected = - jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 - ) { - optionSet = true; - } - - /* eslint-enable no-cond-assign */ - } - - // Force browsers to behave consistently when non-matching value is set - if ( !optionSet ) { - elem.selectedIndex = -1; - } - return values; - } - } - } -} ); - -// Radios and checkboxes getter/setter -jQuery.each( [ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - set: function( elem, value ) { - if ( Array.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); - } - } - }; - if ( !support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - return elem.getAttribute( "value" ) === null ? "on" : elem.value; - }; - } -} ); - - - - -// Return jQuery for attributes-only inclusion - - -support.focusin = "onfocusin" in window; - - -var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - stopPropagationCallback = function( e ) { - e.stopPropagation(); - }; - -jQuery.extend( jQuery.event, { - - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; - - cur = lastElement = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "." ) > -1 ) { - - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split( "." ); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf( ":" ) < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join( "." ); - event.rnamespace = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === ( elem.ownerDocument || document ) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { - lastElement = cur; - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && - dataPriv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( ( !special._default || - special._default.apply( eventPath.pop(), data ) === false ) && - acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - - if ( event.isPropagationStopped() ) { - lastElement.addEventListener( type, stopPropagationCallback ); - } - - elem[ type ](); - - if ( event.isPropagationStopped() ) { - lastElement.removeEventListener( type, stopPropagationCallback ); - } - - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - // Piggyback on a donor event to simulate a different one - // Used only for `focus(in | out)` events - simulate: function( type, elem, event ) { - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true - } - ); - - jQuery.event.trigger( e, null, elem ); - } - -} ); - -jQuery.fn.extend( { - - trigger: function( type, data ) { - return this.each( function() { - jQuery.event.trigger( type, data, this ); - } ); - }, - triggerHandler: function( type, data ) { - var elem = this[ 0 ]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } -} ); - - -// Support: Firefox <=44 -// Firefox doesn't have focus(in | out) events -// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 -// -// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 -// focus(in | out) events fire after focus & blur events, -// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order -// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 -if ( !support.focusin ) { - jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - var doc = this.ownerDocument || this, - attaches = dataPriv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this, - attaches = dataPriv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - dataPriv.remove( doc, fix ); - - } else { - dataPriv.access( doc, fix, attaches ); - } - } - }; - } ); -} -var location = window.location; - -var nonce = Date.now(); - -var rquery = ( /\?/ ); - - - -// Cross-browser xml parsing -jQuery.parseXML = function( data ) { - var xml; - if ( !data || typeof data !== "string" ) { - return null; - } - - // Support: IE 9 - 11 only - // IE throws on parseFromString with invalid input. - try { - xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); - } catch ( e ) { - xml = undefined; - } - - if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; -}; - - -var - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, - rsubmittable = /^(?:input|select|textarea|keygen)/i; - -function buildParams( prefix, obj, traditional, add ) { - var name; - - if ( Array.isArray( obj ) ) { - - // Serialize array item. - jQuery.each( obj, function( i, v ) { - if ( traditional || rbracket.test( prefix ) ) { - - // Treat each array item as a scalar. - add( prefix, v ); - - } else { - - // Item is non-scalar (array or object), encode its numeric index. - buildParams( - prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", - v, - traditional, - add - ); - } - } ); - - } else if ( !traditional && toType( obj ) === "object" ) { - - // Serialize object item. - for ( name in obj ) { - buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); - } - - } else { - - // Serialize scalar item. - add( prefix, obj ); - } -} - -// Serialize an array of form elements or a set of -// key/values into a query string -jQuery.param = function( a, traditional ) { - var prefix, - s = [], - add = function( key, valueOrFunction ) { - - // If value is a function, invoke it and use its return value - var value = isFunction( valueOrFunction ) ? - valueOrFunction() : - valueOrFunction; - - s[ s.length ] = encodeURIComponent( key ) + "=" + - encodeURIComponent( value == null ? "" : value ); - }; - - // If an array was passed in, assume that it is an array of form elements. - if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { - - // Serialize the form elements - jQuery.each( a, function() { - add( this.name, this.value ); - } ); - - } else { - - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for ( prefix in a ) { - buildParams( prefix, a[ prefix ], traditional, add ); - } - } - - // Return the resulting serialization - return s.join( "&" ); -}; - -jQuery.fn.extend( { - serialize: function() { - return jQuery.param( this.serializeArray() ); - }, - serializeArray: function() { - return this.map( function() { - - // Can add propHook for "elements" to filter or add form elements - var elements = jQuery.prop( this, "elements" ); - return elements ? jQuery.makeArray( elements ) : this; - } ) - .filter( function() { - var type = this.type; - - // Use .is( ":disabled" ) so that fieldset[disabled] works - return this.name && !jQuery( this ).is( ":disabled" ) && - rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && - ( this.checked || !rcheckableType.test( type ) ); - } ) - .map( function( i, elem ) { - var val = jQuery( this ).val(); - - if ( val == null ) { - return null; - } - - if ( Array.isArray( val ) ) { - return jQuery.map( val, function( val ) { - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ); - } - - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ).get(); - } -} ); - - -var - r20 = /%20/g, - rhash = /#.*$/, - rantiCache = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, - - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = "*/".concat( "*" ), - - // Anchor tag for parsing the document origin - originAnchor = document.createElement( "a" ); - originAnchor.href = location.href; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport -function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, - i = 0, - dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; - - if ( isFunction( func ) ) { - - // For each dataType in the dataTypeExpression - while ( ( dataType = dataTypes[ i++ ] ) ) { - - // Prepend if requested - if ( dataType[ 0 ] === "+" ) { - dataType = dataType.slice( 1 ) || "*"; - ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); - - // Otherwise append - } else { - ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); - } - } - } - }; -} - -// Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { - - var inspected = {}, - seekingTransport = ( structure === transports ); - - function inspect( dataType ) { - var selected; - inspected[ dataType ] = true; - jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { - var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); - if ( typeof dataTypeOrTransport === "string" && - !seekingTransport && !inspected[ dataTypeOrTransport ] ) { - - options.dataTypes.unshift( dataTypeOrTransport ); - inspect( dataTypeOrTransport ); - return false; - } else if ( seekingTransport ) { - return !( selected = dataTypeOrTransport ); - } - } ); - return selected; - } - - return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); -} - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 -function ajaxExtend( target, src ) { - var key, deep, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } - - return target; -} - -/* Handles responses to an ajax request: - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ -function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, - contents = s.contents, - dataTypes = s.dataTypes; - - // Remove auto dataType and get content-type in the process - while ( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } -} - -/* Chain conversions given the request and the original response - * Also sets the responseXXX fields on the jqXHR instance - */ -function ajaxConvert( s, response, jqXHR, isSuccess ) { - var conv2, current, conv, tmp, prev, - converters = {}, - - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(); - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - current = dataTypes.shift(); - - // Convert to each sequential dataType - while ( current ) { - - if ( s.responseFields[ current ] ) { - jqXHR[ s.responseFields[ current ] ] = response; - } - - // Apply the dataFilter if provided - if ( !prev && isSuccess && s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - prev = current; - current = dataTypes.shift(); - - if ( current ) { - - // There's only work to do if current dataType is non-auto - if ( current === "*" ) { - - current = prev; - - // Convert response if prev dataType is non-auto and differs from current - } else if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split( " " ); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.unshift( tmp[ 1 ] ); - } - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s.throws ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { - state: "parsererror", - error: conv ? e : "No conversion from " + prev + " to " + current - }; - } - } - } - } - } - } - - return { state: "success", data: response }; -} - -jQuery.extend( { - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {}, - - ajaxSettings: { - url: location.href, - type: "GET", - isLocal: rlocalProtocol.test( location.protocol ), - global: true, - processData: true, - async: true, - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - "*": allTypes, - text: "text/plain", - html: "text/html", - xml: "application/xml, text/xml", - json: "application/json, text/javascript" - }, - - contents: { - xml: /\bxml\b/, - html: /\bhtml/, - json: /\bjson\b/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText", - json: "responseJSON" - }, - - // Data converters - // Keys separate source (or catchall "*") and destination types with a single space - converters: { - - // Convert anything to text - "* text": String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": JSON.parse, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - url: true, - context: true - } - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - return settings ? - - // Building a settings object - ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : - - // Extending ajaxSettings - ajaxExtend( jQuery.ajaxSettings, target ); - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var transport, - - // URL without anti-cache param - cacheURL, - - // Response headers - responseHeadersString, - responseHeaders, - - // timeout handle - timeoutTimer, - - // Url cleanup var - urlAnchor, - - // Request state (becomes false upon send and true upon completion) - completed, - - // To know if global events are to be dispatched - fireGlobals, - - // Loop variable - i, - - // uncached part of the url - uncached, - - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - - // Callbacks context - callbackContext = s.context || s, - - // Context for global events is callbackContext if it is a DOM node or jQuery collection - globalEventContext = s.context && - ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, - - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks( "once memory" ), - - // Status-dependent callbacks - statusCode = s.statusCode || {}, - - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - - // Default abort message - strAbort = "canceled", - - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( completed ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while ( ( match = rheaders.exec( responseHeadersString ) ) ) { - responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; - } - } - match = responseHeaders[ key.toLowerCase() ]; - } - return match == null ? null : match; - }, - - // Raw string - getAllResponseHeaders: function() { - return completed ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function( name, value ) { - if ( completed == null ) { - name = requestHeadersNames[ name.toLowerCase() ] = - requestHeadersNames[ name.toLowerCase() ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( completed == null ) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function( map ) { - var code; - if ( map ) { - if ( completed ) { - - // Execute the appropriate callbacks - jqXHR.always( map[ jqXHR.status ] ); - } else { - - // Lazy-add the new callbacks in a way that preserves old ones - for ( code in map ) { - statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; - } - } - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - var finalText = statusText || strAbort; - if ( transport ) { - transport.abort( finalText ); - } - done( 0, finalText ); - return this; - } - }; - - // Attach deferreds - deferred.promise( jqXHR ); - - // Add protocol if not provided (prefilters might expect it) - // Handle falsy url in the settings object (#10093: consistency with old signature) - // We also use the url parameter if available - s.url = ( ( url || s.url || location.href ) + "" ) - .replace( rprotocol, location.protocol + "//" ); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; - - // A cross-domain request is in order when the origin doesn't match the current origin. - if ( s.crossDomain == null ) { - urlAnchor = document.createElement( "a" ); - - // Support: IE <=8 - 11, Edge 12 - 15 - // IE throws exception on accessing the href property if url is malformed, - // e.g. http://example.com:80x/ - try { - urlAnchor.href = s.url; - - // Support: IE <=8 - 11 only - // Anchor's host property isn't correctly set when s.url is relative - urlAnchor.href = urlAnchor.href; - s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== - urlAnchor.protocol + "//" + urlAnchor.host; - } catch ( e ) { - - // If there is an error parsing the URL, assume it is crossDomain, - // it can be rejected by the transport if it is invalid - s.crossDomain = true; - } - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( completed ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) - fireGlobals = jQuery.event && s.global; - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger( "ajaxStart" ); - } - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Save the URL in case we're toying with the If-Modified-Since - // and/or If-None-Match header later on - // Remove hash to simplify url manipulation - cacheURL = s.url.replace( rhash, "" ); - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // Remember the hash so we can put it back - uncached = s.url.slice( cacheURL.length ); - - // If data is available and should be processed, append data to url - if ( s.data && ( s.processData || typeof s.data === "string" ) ) { - cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; - - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add or update anti-cache param if needed - if ( s.cache === false ) { - cacheURL = cacheURL.replace( rantiCache, "$1" ); - uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; - } - - // Put hash and anti-cache on the URL that will be requested (gh-1732) - s.url = cacheURL + uncached; - - // Change '%20' to '+' if this is encoded form body content (gh-2658) - } else if ( s.data && s.processData && - ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { - s.data = s.data.replace( r20, "+" ); - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - if ( jQuery.lastModified[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); - } - if ( jQuery.etag[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? - s.accepts[ s.dataTypes[ 0 ] ] + - ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && - ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { - - // Abort if not done already and return - return jqXHR.abort(); - } - - // Aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - completeDeferred.add( s.complete ); - jqXHR.done( s.success ); - jqXHR.fail( s.error ); - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - - // If request was aborted inside ajaxSend, stop there - if ( completed ) { - return jqXHR; - } - - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = window.setTimeout( function() { - jqXHR.abort( "timeout" ); - }, s.timeout ); - } - - try { - completed = false; - transport.send( requestHeaders, done ); - } catch ( e ) { - - // Rethrow post-completion exceptions - if ( completed ) { - throw e; - } - - // Propagate others as results - done( -1, e ); - } - } - - // Callback for when everything is done - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Ignore repeat invocations - if ( completed ) { - return; - } - - completed = true; - - // Clear timeout if it exists - if ( timeoutTimer ) { - window.clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Determine if successful - isSuccess = status >= 200 && status < 300 || status === 304; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // Convert no matter what (that way responseXXX fields are always set) - response = ajaxConvert( s, response, jqXHR, isSuccess ); - - // If successful, handle type chaining - if ( isSuccess ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - modified = jqXHR.getResponseHeader( "Last-Modified" ); - if ( modified ) { - jQuery.lastModified[ cacheURL ] = modified; - } - modified = jqXHR.getResponseHeader( "etag" ); - if ( modified ) { - jQuery.etag[ cacheURL ] = modified; - } - } - - // if no content - if ( status === 204 || s.type === "HEAD" ) { - statusText = "nocontent"; - - // if not modified - } else if ( status === 304 ) { - statusText = "notmodified"; - - // If we have data, let's convert it - } else { - statusText = response.state; - success = response.data; - error = response.error; - isSuccess = !error; - } - } else { - - // Extract error from statusText and normalize for non-aborts - error = statusText; - if ( status || !statusText ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger( "ajaxStop" ); - } - } - } - - return jqXHR; - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - } -} ); - -jQuery.each( [ "get", "post" ], function( i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - - // Shift arguments if data argument was omitted - if ( isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - // The url can be an options object (which then must have .url) - return jQuery.ajax( jQuery.extend( { - url: url, - type: method, - dataType: type, - data: data, - success: callback - }, jQuery.isPlainObject( url ) && url ) ); - }; -} ); - - -jQuery._evalUrl = function( url ) { - return jQuery.ajax( { - url: url, - - // Make this explicit, since user can override this through ajaxSetup (#11264) - type: "GET", - dataType: "script", - cache: true, - async: false, - global: false, - "throws": true - } ); -}; - - -jQuery.fn.extend( { - wrapAll: function( html ) { - var wrap; - - if ( this[ 0 ] ) { - if ( isFunction( html ) ) { - html = html.call( this[ 0 ] ); - } - - // The elements to wrap the target around - wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); - - if ( this[ 0 ].parentNode ) { - wrap.insertBefore( this[ 0 ] ); - } - - wrap.map( function() { - var elem = this; - - while ( elem.firstElementChild ) { - elem = elem.firstElementChild; - } - - return elem; - } ).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( isFunction( html ) ) { - return this.each( function( i ) { - jQuery( this ).wrapInner( html.call( this, i ) ); - } ); - } - - return this.each( function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - } ); - }, - - wrap: function( html ) { - var htmlIsFunction = isFunction( html ); - - return this.each( function( i ) { - jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); - } ); - }, - - unwrap: function( selector ) { - this.parent( selector ).not( "body" ).each( function() { - jQuery( this ).replaceWith( this.childNodes ); - } ); - return this; - } -} ); - - -jQuery.expr.pseudos.hidden = function( elem ) { - return !jQuery.expr.pseudos.visible( elem ); -}; -jQuery.expr.pseudos.visible = function( elem ) { - return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); -}; - - - - -jQuery.ajaxSettings.xhr = function() { - try { - return new window.XMLHttpRequest(); - } catch ( e ) {} -}; - -var xhrSuccessStatus = { - - // File protocol always yields status code 0, assume 200 - 0: 200, - - // Support: IE <=9 only - // #1450: sometimes IE returns 1223 when it should be 204 - 1223: 204 - }, - xhrSupported = jQuery.ajaxSettings.xhr(); - -support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); -support.ajax = xhrSupported = !!xhrSupported; - -jQuery.ajaxTransport( function( options ) { - var callback, errorCallback; - - // Cross domain only allowed if supported through XMLHttpRequest - if ( support.cors || xhrSupported && !options.crossDomain ) { - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(); - - xhr.open( - options.type, - options.url, - options.async, - options.username, - options.password - ); - - // Apply custom fields if provided - if ( options.xhrFields ) { - for ( i in options.xhrFields ) { - xhr[ i ] = options.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( options.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( options.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { - headers[ "X-Requested-With" ] = "XMLHttpRequest"; - } - - // Set headers - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - - // Callback - callback = function( type ) { - return function() { - if ( callback ) { - callback = errorCallback = xhr.onload = - xhr.onerror = xhr.onabort = xhr.ontimeout = - xhr.onreadystatechange = null; - - if ( type === "abort" ) { - xhr.abort(); - } else if ( type === "error" ) { - - // Support: IE <=9 only - // On a manual native abort, IE9 throws - // errors on any property access that is not readyState - if ( typeof xhr.status !== "number" ) { - complete( 0, "error" ); - } else { - complete( - - // File: protocol always yields status 0; see #8605, #14207 - xhr.status, - xhr.statusText - ); - } - } else { - complete( - xhrSuccessStatus[ xhr.status ] || xhr.status, - xhr.statusText, - - // Support: IE <=9 only - // IE9 has no XHR2 but throws on binary (trac-11426) - // For XHR2 non-text, let the caller handle it (gh-2498) - ( xhr.responseType || "text" ) !== "text" || - typeof xhr.responseText !== "string" ? - { binary: xhr.response } : - { text: xhr.responseText }, - xhr.getAllResponseHeaders() - ); - } - } - }; - }; - - // Listen to events - xhr.onload = callback(); - errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); - - // Support: IE 9 only - // Use onreadystatechange to replace onabort - // to handle uncaught aborts - if ( xhr.onabort !== undefined ) { - xhr.onabort = errorCallback; - } else { - xhr.onreadystatechange = function() { - - // Check readyState before timeout as it changes - if ( xhr.readyState === 4 ) { - - // Allow onerror to be called first, - // but that will not handle a native abort - // Also, save errorCallback to a variable - // as xhr.onerror cannot be accessed - window.setTimeout( function() { - if ( callback ) { - errorCallback(); - } - } ); - } - }; - } - - // Create the abort callback - callback = callback( "abort" ); - - try { - - // Do send the request (this may raise an exception) - xhr.send( options.hasContent && options.data || null ); - } catch ( e ) { - - // #14683: Only rethrow if this hasn't been notified as an error yet - if ( callback ) { - throw e; - } - } - }, - - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -} ); - - - - -// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) -jQuery.ajaxPrefilter( function( s ) { - if ( s.crossDomain ) { - s.contents.script = false; - } -} ); - -// Install script dataType -jQuery.ajaxSetup( { - accepts: { - script: "text/javascript, application/javascript, " + - "application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /\b(?:java|ecma)script\b/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -} ); - -// Handle cache's special case and crossDomain -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - } -} ); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function( s ) { - - // This transport only deals with cross domain requests - if ( s.crossDomain ) { - var script, callback; - return { - send: function( _, complete ) { - script = jQuery( "\r\n"; - -// inject VBScript -document.write(IEBinaryToArray_ByteStr_Script); - -global.JSZipUtils._getBinaryFromXHR = function (xhr) { - var binary = xhr.responseBody; - var byteMapping = {}; - for ( var i = 0; i < 256; i++ ) { - for ( var j = 0; j < 256; j++ ) { - byteMapping[ String.fromCharCode( i + (j << 8) ) ] = - String.fromCharCode(i) + String.fromCharCode(j); - } - } - var rawBytes = IEBinaryToArray_ByteStr(binary); - var lastChr = IEBinaryToArray_ByteStr_Last(binary); - return rawBytes.replace(/[\s\S]/g, function( match ) { - return byteMapping[match]; - }) + lastChr; -}; - -// enforcing Stuk's coding style -// vim: set shiftwidth=4 softtabstop=4: - -},{}]},{},[1]) -; diff --git a/doc/jquery/jszip-utils/dist/jszip-utils-ie.min.js b/doc/jquery/jszip-utils/dist/jszip-utils-ie.min.js deleted file mode 100644 index 93d8bc8..0000000 --- a/doc/jquery/jszip-utils/dist/jszip-utils-ie.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/*! - -JSZipUtils - A collection of cross-browser utilities to go along with JSZip. - - -(c) 2014 Stuart Knightley, David Duponchel -Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. - -*/ -!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g\r\n";document.write(b),a.JSZipUtils._getBinaryFromXHR=function(a){for(var b=a.responseBody,c={},d=0;256>d;d++)for(var e=0;256>e;e++)c[String.fromCharCode(d+(e<<8))]=String.fromCharCode(d)+String.fromCharCode(e);var f=IEBinaryToArray_ByteStr(b),g=IEBinaryToArray_ByteStr_Last(b);return f.replace(/[\s\S]/g,function(a){return c[a]})+g}},{}]},{},[1]); diff --git a/doc/jquery/jszip-utils/dist/jszip-utils.js b/doc/jquery/jszip-utils/dist/jszip-utils.js deleted file mode 100644 index 775895e..0000000 --- a/doc/jquery/jszip-utils/dist/jszip-utils.js +++ /dev/null @@ -1,118 +0,0 @@ -/*! - -JSZipUtils - A collection of cross-browser utilities to go along with JSZip. - - -(c) 2014 Stuart Knightley, David Duponchel -Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. - -*/ -!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSZipUtils=e():"undefined"!=typeof global?global.JSZipUtils=e():"undefined"!=typeof self&&(self.JSZipUtils=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o - -(c) 2014 Stuart Knightley, David Duponchel -Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip-utils/master/LICENSE.markdown. - -*/ -!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.JSZipUtils=a():"undefined"!=typeof global?global.JSZipUtils=a():"undefined"!=typeof self&&(self.JSZipUtils=a())}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g - -(c) 2009-2016 Stuart Knightley -Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. - -JSZip uses the library pako released under the MIT license : -https://github.com/nodeca/pako/blob/master/LICENSE -*/ - -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.JSZip = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; - enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); - enc3 = remainingBytes > 1 ? (((chr2 & 15) << 2) | (chr3 >> 6)) : 64; - enc4 = remainingBytes > 2 ? (chr3 & 63) : 64; - - output.push(_keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4)); - - } - - return output.join(""); -}; - -// public method for decoding -exports.decode = function(input) { - var chr1, chr2, chr3; - var enc1, enc2, enc3, enc4; - var i = 0, resultIndex = 0; - - var dataUrlPrefix = "data:"; - - if (input.substr(0, dataUrlPrefix.length) === dataUrlPrefix) { - // This is a common error: people give a data url - // (data:image/png;base64,iVBOR...) with a {base64: true} and - // wonders why things don't work. - // We can detect that the string input looks like a data url but we - // *can't* be sure it is one: removing everything up to the comma would - // be too dangerous. - throw new Error("Invalid base64 input, it looks like a data url."); - } - - input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); - - var totalLength = input.length * 3 / 4; - if(input.charAt(input.length - 1) === _keyStr.charAt(64)) { - totalLength--; - } - if(input.charAt(input.length - 2) === _keyStr.charAt(64)) { - totalLength--; - } - if (totalLength % 1 !== 0) { - // totalLength is not an integer, the length does not match a valid - // base64 content. That can happen if: - // - the input is not a base64 content - // - the input is *almost* a base64 content, with a extra chars at the - // beginning or at the end - // - the input uses a base64 variant (base64url for example) - throw new Error("Invalid base64 input, bad content length."); - } - var output; - if (support.uint8array) { - output = new Uint8Array(totalLength|0); - } else { - output = new Array(totalLength|0); - } - - while (i < input.length) { - - enc1 = _keyStr.indexOf(input.charAt(i++)); - enc2 = _keyStr.indexOf(input.charAt(i++)); - enc3 = _keyStr.indexOf(input.charAt(i++)); - enc4 = _keyStr.indexOf(input.charAt(i++)); - - chr1 = (enc1 << 2) | (enc2 >> 4); - chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); - chr3 = ((enc3 & 3) << 6) | enc4; - - output[resultIndex++] = chr1; - - if (enc3 !== 64) { - output[resultIndex++] = chr2; - } - if (enc4 !== 64) { - output[resultIndex++] = chr3; - } - - } - - return output; -}; - -},{"./support":30,"./utils":32}],2:[function(require,module,exports){ -'use strict'; - -var external = require("./external"); -var DataWorker = require('./stream/DataWorker'); -var DataLengthProbe = require('./stream/DataLengthProbe'); -var Crc32Probe = require('./stream/Crc32Probe'); -var DataLengthProbe = require('./stream/DataLengthProbe'); - -/** - * Represent a compressed object, with everything needed to decompress it. - * @constructor - * @param {number} compressedSize the size of the data compressed. - * @param {number} uncompressedSize the size of the data after decompression. - * @param {number} crc32 the crc32 of the decompressed file. - * @param {object} compression the type of compression, see lib/compressions.js. - * @param {String|ArrayBuffer|Uint8Array|Buffer} data the compressed data. - */ -function CompressedObject(compressedSize, uncompressedSize, crc32, compression, data) { - this.compressedSize = compressedSize; - this.uncompressedSize = uncompressedSize; - this.crc32 = crc32; - this.compression = compression; - this.compressedContent = data; -} - -CompressedObject.prototype = { - /** - * Create a worker to get the uncompressed content. - * @return {GenericWorker} the worker. - */ - getContentWorker : function () { - var worker = new DataWorker(external.Promise.resolve(this.compressedContent)) - .pipe(this.compression.uncompressWorker()) - .pipe(new DataLengthProbe("data_length")); - - var that = this; - worker.on("end", function () { - if(this.streamInfo['data_length'] !== that.uncompressedSize) { - throw new Error("Bug : uncompressed data size mismatch"); - } - }); - return worker; - }, - /** - * Create a worker to get the compressed content. - * @return {GenericWorker} the worker. - */ - getCompressedWorker : function () { - return new DataWorker(external.Promise.resolve(this.compressedContent)) - .withStreamInfo("compressedSize", this.compressedSize) - .withStreamInfo("uncompressedSize", this.uncompressedSize) - .withStreamInfo("crc32", this.crc32) - .withStreamInfo("compression", this.compression) - ; - } -}; - -/** - * Chain the given worker with other workers to compress the content with the - * given compresion. - * @param {GenericWorker} uncompressedWorker the worker to pipe. - * @param {Object} compression the compression object. - * @param {Object} compressionOptions the options to use when compressing. - * @return {GenericWorker} the new worker compressing the content. - */ -CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions) { - return uncompressedWorker - .pipe(new Crc32Probe()) - .pipe(new DataLengthProbe("uncompressedSize")) - .pipe(compression.compressWorker(compressionOptions)) - .pipe(new DataLengthProbe("compressedSize")) - .withStreamInfo("compression", compression); -}; - -module.exports = CompressedObject; - -},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(require,module,exports){ -'use strict'; - -var GenericWorker = require("./stream/GenericWorker"); - -exports.STORE = { - magic: "\x00\x00", - compressWorker : function (compressionOptions) { - return new GenericWorker("STORE compression"); - }, - uncompressWorker : function () { - return new GenericWorker("STORE decompression"); - } -}; -exports.DEFLATE = require('./flate'); - -},{"./flate":7,"./stream/GenericWorker":28}],4:[function(require,module,exports){ -'use strict'; - -var utils = require('./utils'); - -/** - * The following functions come from pako, from pako/lib/zlib/crc32.js - * released under the MIT license, see pako https://github.com/nodeca/pako/ - */ - -// Use ordinary array, since untyped makes no boost here -function makeTable() { - var c, table = []; - - for(var n =0; n < 256; n++){ - c = n; - for(var k =0; k < 8; k++){ - c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); - } - table[n] = c; - } - - return table; -} - -// Create table on load. Just 255 signed longs. Not a problem. -var crcTable = makeTable(); - - -function crc32(crc, buf, len, pos) { - var t = crcTable, end = pos + len; - - crc = crc ^ (-1); - - for (var i = pos; i < end; i++ ) { - crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; - } - - return (crc ^ (-1)); // >>> 0; -} - -// That's all for the pako functions. - -/** - * Compute the crc32 of a string. - * This is almost the same as the function crc32, but for strings. Using the - * same function for the two use cases leads to horrible performances. - * @param {Number} crc the starting value of the crc. - * @param {String} str the string to use. - * @param {Number} len the length of the string. - * @param {Number} pos the starting position for the crc32 computation. - * @return {Number} the computed crc32. - */ -function crc32str(crc, str, len, pos) { - var t = crcTable, end = pos + len; - - crc = crc ^ (-1); - - for (var i = pos; i < end; i++ ) { - crc = (crc >>> 8) ^ t[(crc ^ str.charCodeAt(i)) & 0xFF]; - } - - return (crc ^ (-1)); // >>> 0; -} - -module.exports = function crc32wrapper(input, crc) { - if (typeof input === "undefined" || !input.length) { - return 0; - } - - var isArray = utils.getTypeOf(input) !== "string"; - - if(isArray) { - return crc32(crc|0, input, input.length, 0); - } else { - return crc32str(crc|0, input, input.length, 0); - } -}; - -},{"./utils":32}],5:[function(require,module,exports){ -'use strict'; -exports.base64 = false; -exports.binary = false; -exports.dir = false; -exports.createFolders = true; -exports.date = null; -exports.compression = null; -exports.compressionOptions = null; -exports.comment = null; -exports.unixPermissions = null; -exports.dosPermissions = null; - -},{}],6:[function(require,module,exports){ -/* global Promise */ -'use strict'; - -// load the global object first: -// - it should be better integrated in the system (unhandledRejection in node) -// - the environment may have a custom Promise implementation (see zone.js) -var ES6Promise = null; -if (typeof Promise !== "undefined") { - ES6Promise = Promise; -} else { - ES6Promise = require("lie"); -} - -/** - * Let the user use/change some implementations. - */ -module.exports = { - Promise: ES6Promise -}; - -},{"lie":58}],7:[function(require,module,exports){ -'use strict'; -var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); - -var pako = require("pako"); -var utils = require("./utils"); -var GenericWorker = require("./stream/GenericWorker"); - -var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array"; - -exports.magic = "\x08\x00"; - -/** - * Create a worker that uses pako to inflate/deflate. - * @constructor - * @param {String} action the name of the pako function to call : either "Deflate" or "Inflate". - * @param {Object} options the options to use when (de)compressing. - */ -function FlateWorker(action, options) { - GenericWorker.call(this, "FlateWorker/" + action); - - this._pako = null; - this._pakoAction = action; - this._pakoOptions = options; - // the `meta` object from the last chunk received - // this allow this worker to pass around metadata - this.meta = {}; -} - -utils.inherits(FlateWorker, GenericWorker); - -/** - * @see GenericWorker.processChunk - */ -FlateWorker.prototype.processChunk = function (chunk) { - this.meta = chunk.meta; - if (this._pako === null) { - this._createPako(); - } - this._pako.push(utils.transformTo(ARRAY_TYPE, chunk.data), false); -}; - -/** - * @see GenericWorker.flush - */ -FlateWorker.prototype.flush = function () { - GenericWorker.prototype.flush.call(this); - if (this._pako === null) { - this._createPako(); - } - this._pako.push([], true); -}; -/** - * @see GenericWorker.cleanUp - */ -FlateWorker.prototype.cleanUp = function () { - GenericWorker.prototype.cleanUp.call(this); - this._pako = null; -}; - -/** - * Create the _pako object. - * TODO: lazy-loading this object isn't the best solution but it's the - * quickest. The best solution is to lazy-load the worker list. See also the - * issue #446. - */ -FlateWorker.prototype._createPako = function () { - this._pako = new pako[this._pakoAction]({ - raw: true, - level: this._pakoOptions.level || -1 // default compression - }); - var self = this; - this._pako.onData = function(data) { - self.push({ - data : data, - meta : self.meta - }); - }; -}; - -exports.compressWorker = function (compressionOptions) { - return new FlateWorker("Deflate", compressionOptions); -}; -exports.uncompressWorker = function () { - return new FlateWorker("Inflate", {}); -}; - -},{"./stream/GenericWorker":28,"./utils":32,"pako":59}],8:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var GenericWorker = require('../stream/GenericWorker'); -var utf8 = require('../utf8'); -var crc32 = require('../crc32'); -var signature = require('../signature'); - -/** - * Transform an integer into a string in hexadecimal. - * @private - * @param {number} dec the number to convert. - * @param {number} bytes the number of bytes to generate. - * @returns {string} the result. - */ -var decToHex = function(dec, bytes) { - var hex = "", i; - for (i = 0; i < bytes; i++) { - hex += String.fromCharCode(dec & 0xff); - dec = dec >>> 8; - } - return hex; -}; - -/** - * Generate the UNIX part of the external file attributes. - * @param {Object} unixPermissions the unix permissions or null. - * @param {Boolean} isDir true if the entry is a directory, false otherwise. - * @return {Number} a 32 bit integer. - * - * adapted from http://unix.stackexchange.com/questions/14705/the-zip-formats-external-file-attribute : - * - * TTTTsstrwxrwxrwx0000000000ADVSHR - * ^^^^____________________________ file type, see zipinfo.c (UNX_*) - * ^^^_________________________ setuid, setgid, sticky - * ^^^^^^^^^________________ permissions - * ^^^^^^^^^^______ not used ? - * ^^^^^^ DOS attribute bits : Archive, Directory, Volume label, System file, Hidden, Read only - */ -var generateUnixExternalFileAttr = function (unixPermissions, isDir) { - - var result = unixPermissions; - if (!unixPermissions) { - // I can't use octal values in strict mode, hence the hexa. - // 040775 => 0x41fd - // 0100664 => 0x81b4 - result = isDir ? 0x41fd : 0x81b4; - } - return (result & 0xFFFF) << 16; -}; - -/** - * Generate the DOS part of the external file attributes. - * @param {Object} dosPermissions the dos permissions or null. - * @param {Boolean} isDir true if the entry is a directory, false otherwise. - * @return {Number} a 32 bit integer. - * - * Bit 0 Read-Only - * Bit 1 Hidden - * Bit 2 System - * Bit 3 Volume Label - * Bit 4 Directory - * Bit 5 Archive - */ -var generateDosExternalFileAttr = function (dosPermissions, isDir) { - - // the dir flag is already set for compatibility - return (dosPermissions || 0) & 0x3F; -}; - -/** - * Generate the various parts used in the construction of the final zip file. - * @param {Object} streamInfo the hash with informations about the compressed file. - * @param {Boolean} streamedContent is the content streamed ? - * @param {Boolean} streamingEnded is the stream finished ? - * @param {number} offset the current offset from the start of the zip file. - * @param {String} platform let's pretend we are this platform (change platform dependents fields) - * @param {Function} encodeFileName the function to encode the file name / comment. - * @return {Object} the zip parts. - */ -var generateZipParts = function(streamInfo, streamedContent, streamingEnded, offset, platform, encodeFileName) { - var file = streamInfo['file'], - compression = streamInfo['compression'], - useCustomEncoding = encodeFileName !== utf8.utf8encode, - encodedFileName = utils.transformTo("string", encodeFileName(file.name)), - utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), - comment = file.comment, - encodedComment = utils.transformTo("string", encodeFileName(comment)), - utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), - useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, - useUTF8ForComment = utfEncodedComment.length !== comment.length, - dosTime, - dosDate, - extraFields = "", - unicodePathExtraField = "", - unicodeCommentExtraField = "", - dir = file.dir, - date = file.date; - - - var dataInfo = { - crc32 : 0, - compressedSize : 0, - uncompressedSize : 0 - }; - - // if the content is streamed, the sizes/crc32 are only available AFTER - // the end of the stream. - if (!streamedContent || streamingEnded) { - dataInfo.crc32 = streamInfo['crc32']; - dataInfo.compressedSize = streamInfo['compressedSize']; - dataInfo.uncompressedSize = streamInfo['uncompressedSize']; - } - - var bitflag = 0; - if (streamedContent) { - // Bit 3: the sizes/crc32 are set to zero in the local header. - // The correct values are put in the data descriptor immediately - // following the compressed data. - bitflag |= 0x0008; - } - if (!useCustomEncoding && (useUTF8ForFileName || useUTF8ForComment)) { - // Bit 11: Language encoding flag (EFS). - bitflag |= 0x0800; - } - - - var extFileAttr = 0; - var versionMadeBy = 0; - if (dir) { - // dos or unix, we set the dos dir flag - extFileAttr |= 0x00010; - } - if(platform === "UNIX") { - versionMadeBy = 0x031E; // UNIX, version 3.0 - extFileAttr |= generateUnixExternalFileAttr(file.unixPermissions, dir); - } else { // DOS or other, fallback to DOS - versionMadeBy = 0x0014; // DOS, version 2.0 - extFileAttr |= generateDosExternalFileAttr(file.dosPermissions, dir); - } - - // date - // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html - // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html - // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html - - dosTime = date.getUTCHours(); - dosTime = dosTime << 6; - dosTime = dosTime | date.getUTCMinutes(); - dosTime = dosTime << 5; - dosTime = dosTime | date.getUTCSeconds() / 2; - - dosDate = date.getUTCFullYear() - 1980; - dosDate = dosDate << 4; - dosDate = dosDate | (date.getUTCMonth() + 1); - dosDate = dosDate << 5; - dosDate = dosDate | date.getUTCDate(); - - if (useUTF8ForFileName) { - // set the unicode path extra field. unzip needs at least one extra - // field to correctly handle unicode path, so using the path is as good - // as any other information. This could improve the situation with - // other archive managers too. - // This field is usually used without the utf8 flag, with a non - // unicode path in the header (winrar, winzip). This helps (a bit) - // with the messy Windows' default compressed folders feature but - // breaks on p7zip which doesn't seek the unicode path extra field. - // So for now, UTF-8 everywhere ! - unicodePathExtraField = - // Version - decToHex(1, 1) + - // NameCRC32 - decToHex(crc32(encodedFileName), 4) + - // UnicodeName - utfEncodedFileName; - - extraFields += - // Info-ZIP Unicode Path Extra Field - "\x75\x70" + - // size - decToHex(unicodePathExtraField.length, 2) + - // content - unicodePathExtraField; - } - - if(useUTF8ForComment) { - - unicodeCommentExtraField = - // Version - decToHex(1, 1) + - // CommentCRC32 - decToHex(crc32(encodedComment), 4) + - // UnicodeName - utfEncodedComment; - - extraFields += - // Info-ZIP Unicode Path Extra Field - "\x75\x63" + - // size - decToHex(unicodeCommentExtraField.length, 2) + - // content - unicodeCommentExtraField; - } - - var header = ""; - - // version needed to extract - header += "\x0A\x00"; - // general purpose bit flag - header += decToHex(bitflag, 2); - // compression method - header += compression.magic; - // last mod file time - header += decToHex(dosTime, 2); - // last mod file date - header += decToHex(dosDate, 2); - // crc-32 - header += decToHex(dataInfo.crc32, 4); - // compressed size - header += decToHex(dataInfo.compressedSize, 4); - // uncompressed size - header += decToHex(dataInfo.uncompressedSize, 4); - // file name length - header += decToHex(encodedFileName.length, 2); - // extra field length - header += decToHex(extraFields.length, 2); - - - var fileRecord = signature.LOCAL_FILE_HEADER + header + encodedFileName + extraFields; - - var dirRecord = signature.CENTRAL_FILE_HEADER + - // version made by (00: DOS) - decToHex(versionMadeBy, 2) + - // file header (common to file and central directory) - header + - // file comment length - decToHex(encodedComment.length, 2) + - // disk number start - "\x00\x00" + - // internal file attributes TODO - "\x00\x00" + - // external file attributes - decToHex(extFileAttr, 4) + - // relative offset of local header - decToHex(offset, 4) + - // file name - encodedFileName + - // extra field - extraFields + - // file comment - encodedComment; - - return { - fileRecord: fileRecord, - dirRecord: dirRecord - }; -}; - -/** - * Generate the EOCD record. - * @param {Number} entriesCount the number of entries in the zip file. - * @param {Number} centralDirLength the length (in bytes) of the central dir. - * @param {Number} localDirLength the length (in bytes) of the local dir. - * @param {String} comment the zip file comment as a binary string. - * @param {Function} encodeFileName the function to encode the comment. - * @return {String} the EOCD record. - */ -var generateCentralDirectoryEnd = function (entriesCount, centralDirLength, localDirLength, comment, encodeFileName) { - var dirEnd = ""; - var encodedComment = utils.transformTo("string", encodeFileName(comment)); - - // end of central dir signature - dirEnd = signature.CENTRAL_DIRECTORY_END + - // number of this disk - "\x00\x00" + - // number of the disk with the start of the central directory - "\x00\x00" + - // total number of entries in the central directory on this disk - decToHex(entriesCount, 2) + - // total number of entries in the central directory - decToHex(entriesCount, 2) + - // size of the central directory 4 bytes - decToHex(centralDirLength, 4) + - // offset of start of central directory with respect to the starting disk number - decToHex(localDirLength, 4) + - // .ZIP file comment length - decToHex(encodedComment.length, 2) + - // .ZIP file comment - encodedComment; - - return dirEnd; -}; - -/** - * Generate data descriptors for a file entry. - * @param {Object} streamInfo the hash generated by a worker, containing informations - * on the file entry. - * @return {String} the data descriptors. - */ -var generateDataDescriptors = function (streamInfo) { - var descriptor = ""; - descriptor = signature.DATA_DESCRIPTOR + - // crc-32 4 bytes - decToHex(streamInfo['crc32'], 4) + - // compressed size 4 bytes - decToHex(streamInfo['compressedSize'], 4) + - // uncompressed size 4 bytes - decToHex(streamInfo['uncompressedSize'], 4); - - return descriptor; -}; - - -/** - * A worker to concatenate other workers to create a zip file. - * @param {Boolean} streamFiles `true` to stream the content of the files, - * `false` to accumulate it. - * @param {String} comment the comment to use. - * @param {String} platform the platform to use, "UNIX" or "DOS". - * @param {Function} encodeFileName the function to encode file names and comments. - */ -function ZipFileWorker(streamFiles, comment, platform, encodeFileName) { - GenericWorker.call(this, "ZipFileWorker"); - // The number of bytes written so far. This doesn't count accumulated chunks. - this.bytesWritten = 0; - // The comment of the zip file - this.zipComment = comment; - // The platform "generating" the zip file. - this.zipPlatform = platform; - // the function to encode file names and comments. - this.encodeFileName = encodeFileName; - // Should we stream the content of the files ? - this.streamFiles = streamFiles; - // If `streamFiles` is false, we will need to accumulate the content of the - // files to calculate sizes / crc32 (and write them *before* the content). - // This boolean indicates if we are accumulating chunks (it will change a lot - // during the lifetime of this worker). - this.accumulate = false; - // The buffer receiving chunks when accumulating content. - this.contentBuffer = []; - // The list of generated directory records. - this.dirRecords = []; - // The offset (in bytes) from the beginning of the zip file for the current source. - this.currentSourceOffset = 0; - // The total number of entries in this zip file. - this.entriesCount = 0; - // the name of the file currently being added, null when handling the end of the zip file. - // Used for the emited metadata. - this.currentFile = null; - - - - this._sources = []; -} -utils.inherits(ZipFileWorker, GenericWorker); - -/** - * @see GenericWorker.push - */ -ZipFileWorker.prototype.push = function (chunk) { - - var currentFilePercent = chunk.meta.percent || 0; - var entriesCount = this.entriesCount; - var remainingFiles = this._sources.length; - - if(this.accumulate) { - this.contentBuffer.push(chunk); - } else { - this.bytesWritten += chunk.data.length; - - GenericWorker.prototype.push.call(this, { - data : chunk.data, - meta : { - currentFile : this.currentFile, - percent : entriesCount ? (currentFilePercent + 100 * (entriesCount - remainingFiles - 1)) / entriesCount : 100 - } - }); - } -}; - -/** - * The worker started a new source (an other worker). - * @param {Object} streamInfo the streamInfo object from the new source. - */ -ZipFileWorker.prototype.openedSource = function (streamInfo) { - this.currentSourceOffset = this.bytesWritten; - this.currentFile = streamInfo['file'].name; - - var streamedContent = this.streamFiles && !streamInfo['file'].dir; - - // don't stream folders (because they don't have any content) - if(streamedContent) { - var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); - this.push({ - data : record.fileRecord, - meta : {percent:0} - }); - } else { - // we need to wait for the whole file before pushing anything - this.accumulate = true; - } -}; - -/** - * The worker finished a source (an other worker). - * @param {Object} streamInfo the streamInfo object from the finished source. - */ -ZipFileWorker.prototype.closedSource = function (streamInfo) { - this.accumulate = false; - var streamedContent = this.streamFiles && !streamInfo['file'].dir; - var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName); - - this.dirRecords.push(record.dirRecord); - if(streamedContent) { - // after the streamed file, we put data descriptors - this.push({ - data : generateDataDescriptors(streamInfo), - meta : {percent:100} - }); - } else { - // the content wasn't streamed, we need to push everything now - // first the file record, then the content - this.push({ - data : record.fileRecord, - meta : {percent:0} - }); - while(this.contentBuffer.length) { - this.push(this.contentBuffer.shift()); - } - } - this.currentFile = null; -}; - -/** - * @see GenericWorker.flush - */ -ZipFileWorker.prototype.flush = function () { - - var localDirLength = this.bytesWritten; - for(var i = 0; i < this.dirRecords.length; i++) { - this.push({ - data : this.dirRecords[i], - meta : {percent:100} - }); - } - var centralDirLength = this.bytesWritten - localDirLength; - - var dirEnd = generateCentralDirectoryEnd(this.dirRecords.length, centralDirLength, localDirLength, this.zipComment, this.encodeFileName); - - this.push({ - data : dirEnd, - meta : {percent:100} - }); -}; - -/** - * Prepare the next source to be read. - */ -ZipFileWorker.prototype.prepareNextSource = function () { - this.previous = this._sources.shift(); - this.openedSource(this.previous.streamInfo); - if (this.isPaused) { - this.previous.pause(); - } else { - this.previous.resume(); - } -}; - -/** - * @see GenericWorker.registerPrevious - */ -ZipFileWorker.prototype.registerPrevious = function (previous) { - this._sources.push(previous); - var self = this; - - previous.on('data', function (chunk) { - self.processChunk(chunk); - }); - previous.on('end', function () { - self.closedSource(self.previous.streamInfo); - if(self._sources.length) { - self.prepareNextSource(); - } else { - self.end(); - } - }); - previous.on('error', function (e) { - self.error(e); - }); - return this; -}; - -/** - * @see GenericWorker.resume - */ -ZipFileWorker.prototype.resume = function () { - if(!GenericWorker.prototype.resume.call(this)) { - return false; - } - - if (!this.previous && this._sources.length) { - this.prepareNextSource(); - return true; - } - if (!this.previous && !this._sources.length && !this.generatedError) { - this.end(); - return true; - } -}; - -/** - * @see GenericWorker.error - */ -ZipFileWorker.prototype.error = function (e) { - var sources = this._sources; - if(!GenericWorker.prototype.error.call(this, e)) { - return false; - } - for(var i = 0; i < sources.length; i++) { - try { - sources[i].error(e); - } catch(e) { - // the `error` exploded, nothing to do - } - } - return true; -}; - -/** - * @see GenericWorker.lock - */ -ZipFileWorker.prototype.lock = function () { - GenericWorker.prototype.lock.call(this); - var sources = this._sources; - for(var i = 0; i < sources.length; i++) { - sources[i].lock(); - } -}; - -module.exports = ZipFileWorker; - -},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(require,module,exports){ -'use strict'; - -var compressions = require('../compressions'); -var ZipFileWorker = require('./ZipFileWorker'); - -/** - * Find the compression to use. - * @param {String} fileCompression the compression defined at the file level, if any. - * @param {String} zipCompression the compression defined at the load() level. - * @return {Object} the compression object to use. - */ -var getCompression = function (fileCompression, zipCompression) { - - var compressionName = fileCompression || zipCompression; - var compression = compressions[compressionName]; - if (!compression) { - throw new Error(compressionName + " is not a valid compression method !"); - } - return compression; -}; - -/** - * Create a worker to generate a zip file. - * @param {JSZip} zip the JSZip instance at the right root level. - * @param {Object} options to generate the zip file. - * @param {String} comment the comment to use. - */ -exports.generateWorker = function (zip, options, comment) { - - var zipFileWorker = new ZipFileWorker(options.streamFiles, comment, options.platform, options.encodeFileName); - var entriesCount = 0; - try { - - zip.forEach(function (relativePath, file) { - entriesCount++; - var compression = getCompression(file.options.compression, options.compression); - var compressionOptions = file.options.compressionOptions || options.compressionOptions || {}; - var dir = file.dir, date = file.date; - - file._compressWorker(compression, compressionOptions) - .withStreamInfo("file", { - name : relativePath, - dir : dir, - date : date, - comment : file.comment || "", - unixPermissions : file.unixPermissions, - dosPermissions : file.dosPermissions - }) - .pipe(zipFileWorker); - }); - zipFileWorker.entriesCount = entriesCount; - } catch (e) { - zipFileWorker.error(e); - } - - return zipFileWorker; -}; - -},{"../compressions":3,"./ZipFileWorker":8}],10:[function(require,module,exports){ -'use strict'; - -/** - * Representation a of zip file in js - * @constructor - */ -function JSZip() { - // if this constructor is used without `new`, it adds `new` before itself: - if(!(this instanceof JSZip)) { - return new JSZip(); - } - - if(arguments.length) { - throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide."); - } - - // object containing the files : - // { - // "folder/" : {...}, - // "folder/data.txt" : {...} - // } - this.files = {}; - - this.comment = null; - - // Where we are in the hierarchy - this.root = ""; - this.clone = function() { - var newObj = new JSZip(); - for (var i in this) { - if (typeof this[i] !== "function") { - newObj[i] = this[i]; - } - } - return newObj; - }; -} -JSZip.prototype = require('./object'); -JSZip.prototype.loadAsync = require('./load'); -JSZip.support = require('./support'); -JSZip.defaults = require('./defaults'); - -// TODO find a better way to handle this version, -// a require('package.json').version doesn't work with webpack, see #327 -JSZip.version = "3.1.5"; - -JSZip.loadAsync = function (content, options) { - return new JSZip().loadAsync(content, options); -}; - -JSZip.external = require("./external"); -module.exports = JSZip; - -},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(require,module,exports){ -'use strict'; -var utils = require('./utils'); -var external = require("./external"); -var utf8 = require('./utf8'); -var utils = require('./utils'); -var ZipEntries = require('./zipEntries'); -var Crc32Probe = require('./stream/Crc32Probe'); -var nodejsUtils = require("./nodejsUtils"); - -/** - * Check the CRC32 of an entry. - * @param {ZipEntry} zipEntry the zip entry to check. - * @return {Promise} the result. - */ -function checkEntryCRC32(zipEntry) { - return new external.Promise(function (resolve, reject) { - var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe()); - worker.on("error", function (e) { - reject(e); - }) - .on("end", function () { - if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) { - reject(new Error("Corrupted zip : CRC32 mismatch")); - } else { - resolve(); - } - }) - .resume(); - }); -} - -module.exports = function(data, options) { - var zip = this; - options = utils.extend(options || {}, { - base64: false, - checkCRC32: false, - optimizedBinaryString: false, - createFolders: false, - decodeFileName: utf8.utf8decode - }); - - if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { - return external.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")); - } - - return utils.prepareContent("the loaded zip file", data, true, options.optimizedBinaryString, options.base64) - .then(function(data) { - var zipEntries = new ZipEntries(options); - zipEntries.load(data); - return zipEntries; - }).then(function checkCRC32(zipEntries) { - var promises = [external.Promise.resolve(zipEntries)]; - var files = zipEntries.files; - if (options.checkCRC32) { - for (var i = 0; i < files.length; i++) { - promises.push(checkEntryCRC32(files[i])); - } - } - return external.Promise.all(promises); - }).then(function addFiles(results) { - var zipEntries = results.shift(); - var files = zipEntries.files; - for (var i = 0; i < files.length; i++) { - var input = files[i]; - zip.file(input.fileNameStr, input.decompressed, { - binary: true, - optimizedBinaryString: true, - date: input.date, - dir: input.dir, - comment : input.fileCommentStr.length ? input.fileCommentStr : null, - unixPermissions : input.unixPermissions, - dosPermissions : input.dosPermissions, - createFolders: options.createFolders - }); - } - if (zipEntries.zipComment.length) { - zip.comment = zipEntries.zipComment; - } - - return zip; - }); -}; - -},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(require,module,exports){ -"use strict"; - -var utils = require('../utils'); -var GenericWorker = require('../stream/GenericWorker'); - -/** - * A worker that use a nodejs stream as source. - * @constructor - * @param {String} filename the name of the file entry for this stream. - * @param {Readable} stream the nodejs stream. - */ -function NodejsStreamInputAdapter(filename, stream) { - GenericWorker.call(this, "Nodejs stream input adapter for " + filename); - this._upstreamEnded = false; - this._bindStream(stream); -} - -utils.inherits(NodejsStreamInputAdapter, GenericWorker); - -/** - * Prepare the stream and bind the callbacks on it. - * Do this ASAP on node 0.10 ! A lazy binding doesn't always work. - * @param {Stream} stream the nodejs stream to use. - */ -NodejsStreamInputAdapter.prototype._bindStream = function (stream) { - var self = this; - this._stream = stream; - stream.pause(); - stream - .on("data", function (chunk) { - self.push({ - data: chunk, - meta : { - percent : 0 - } - }); - }) - .on("error", function (e) { - if(self.isPaused) { - this.generatedError = e; - } else { - self.error(e); - } - }) - .on("end", function () { - if(self.isPaused) { - self._upstreamEnded = true; - } else { - self.end(); - } - }); -}; -NodejsStreamInputAdapter.prototype.pause = function () { - if(!GenericWorker.prototype.pause.call(this)) { - return false; - } - this._stream.pause(); - return true; -}; -NodejsStreamInputAdapter.prototype.resume = function () { - if(!GenericWorker.prototype.resume.call(this)) { - return false; - } - - if(this._upstreamEnded) { - this.end(); - } else { - this._stream.resume(); - } - - return true; -}; - -module.exports = NodejsStreamInputAdapter; - -},{"../stream/GenericWorker":28,"../utils":32}],13:[function(require,module,exports){ -'use strict'; - -var Readable = require('readable-stream').Readable; - -var utils = require('../utils'); -utils.inherits(NodejsStreamOutputAdapter, Readable); - -/** -* A nodejs stream using a worker as source. -* @see the SourceWrapper in http://nodejs.org/api/stream.html -* @constructor -* @param {StreamHelper} helper the helper wrapping the worker -* @param {Object} options the nodejs stream options -* @param {Function} updateCb the update callback. -*/ -function NodejsStreamOutputAdapter(helper, options, updateCb) { - Readable.call(this, options); - this._helper = helper; - - var self = this; - helper.on("data", function (data, meta) { - if (!self.push(data)) { - self._helper.pause(); - } - if(updateCb) { - updateCb(meta); - } - }) - .on("error", function(e) { - self.emit('error', e); - }) - .on("end", function () { - self.push(null); - }); -} - - -NodejsStreamOutputAdapter.prototype._read = function() { - this._helper.resume(); -}; - -module.exports = NodejsStreamOutputAdapter; - -},{"../utils":32,"readable-stream":16}],14:[function(require,module,exports){ -'use strict'; - -module.exports = { - /** - * True if this is running in Nodejs, will be undefined in a browser. - * In a browser, browserify won't include this file and the whole module - * will be resolved an empty object. - */ - isNode : typeof Buffer !== "undefined", - /** - * Create a new nodejs Buffer from an existing content. - * @param {Object} data the data to pass to the constructor. - * @param {String} encoding the encoding to use. - * @return {Buffer} a new Buffer. - */ - newBufferFrom: function(data, encoding) { - // XXX We can't use `Buffer.from` which comes from `Uint8Array.from` - // in nodejs v4 (< v.4.5). It's not the expected implementation (and - // has a different signature). - // see https://github.com/nodejs/node/issues/8053 - // A condition on nodejs' version won't solve the issue as we don't - // control the Buffer polyfills that may or may not be used. - return new Buffer(data, encoding); - }, - /** - * Create a new nodejs Buffer with the specified size. - * @param {Integer} size the size of the buffer. - * @return {Buffer} a new Buffer. - */ - allocBuffer: function (size) { - if (Buffer.alloc) { - return Buffer.alloc(size); - } else { - return new Buffer(size); - } - }, - /** - * Find out if an object is a Buffer. - * @param {Object} b the object to test. - * @return {Boolean} true if the object is a Buffer, false otherwise. - */ - isBuffer : function(b){ - return Buffer.isBuffer(b); - }, - - isStream : function (obj) { - return obj && - typeof obj.on === "function" && - typeof obj.pause === "function" && - typeof obj.resume === "function"; - } -}; - -},{}],15:[function(require,module,exports){ -'use strict'; -var utf8 = require('./utf8'); -var utils = require('./utils'); -var GenericWorker = require('./stream/GenericWorker'); -var StreamHelper = require('./stream/StreamHelper'); -var defaults = require('./defaults'); -var CompressedObject = require('./compressedObject'); -var ZipObject = require('./zipObject'); -var generate = require("./generate"); -var nodejsUtils = require("./nodejsUtils"); -var NodejsStreamInputAdapter = require("./nodejs/NodejsStreamInputAdapter"); - - -/** - * Add a file in the current folder. - * @private - * @param {string} name the name of the file - * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file - * @param {Object} originalOptions the options of the file - * @return {Object} the new file. - */ -var fileAdd = function(name, data, originalOptions) { - // be sure sub folders exist - var dataType = utils.getTypeOf(data), - parent; - - - /* - * Correct options. - */ - - var o = utils.extend(originalOptions || {}, defaults); - o.date = o.date || new Date(); - if (o.compression !== null) { - o.compression = o.compression.toUpperCase(); - } - - if (typeof o.unixPermissions === "string") { - o.unixPermissions = parseInt(o.unixPermissions, 8); - } - - // UNX_IFDIR 0040000 see zipinfo.c - if (o.unixPermissions && (o.unixPermissions & 0x4000)) { - o.dir = true; - } - // Bit 4 Directory - if (o.dosPermissions && (o.dosPermissions & 0x0010)) { - o.dir = true; - } - - if (o.dir) { - name = forceTrailingSlash(name); - } - if (o.createFolders && (parent = parentFolder(name))) { - folderAdd.call(this, parent, true); - } - - var isUnicodeString = dataType === "string" && o.binary === false && o.base64 === false; - if (!originalOptions || typeof originalOptions.binary === "undefined") { - o.binary = !isUnicodeString; - } - - - var isCompressedEmpty = (data instanceof CompressedObject) && data.uncompressedSize === 0; - - if (isCompressedEmpty || o.dir || !data || data.length === 0) { - o.base64 = false; - o.binary = true; - data = ""; - o.compression = "STORE"; - dataType = "string"; - } - - /* - * Convert content to fit. - */ - - var zipObjectContent = null; - if (data instanceof CompressedObject || data instanceof GenericWorker) { - zipObjectContent = data; - } else if (nodejsUtils.isNode && nodejsUtils.isStream(data)) { - zipObjectContent = new NodejsStreamInputAdapter(name, data); - } else { - zipObjectContent = utils.prepareContent(name, data, o.binary, o.optimizedBinaryString, o.base64); - } - - var object = new ZipObject(name, zipObjectContent, o); - this.files[name] = object; - /* - TODO: we can't throw an exception because we have async promises - (we can have a promise of a Date() for example) but returning a - promise is useless because file(name, data) returns the JSZip - object for chaining. Should we break that to allow the user - to catch the error ? - - return external.Promise.resolve(zipObjectContent) - .then(function () { - return object; - }); - */ -}; - -/** - * Find the parent folder of the path. - * @private - * @param {string} path the path to use - * @return {string} the parent folder, or "" - */ -var parentFolder = function (path) { - if (path.slice(-1) === '/') { - path = path.substring(0, path.length - 1); - } - var lastSlash = path.lastIndexOf('/'); - return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; -}; - -/** - * Returns the path with a slash at the end. - * @private - * @param {String} path the path to check. - * @return {String} the path with a trailing slash. - */ -var forceTrailingSlash = function(path) { - // Check the name ends with a / - if (path.slice(-1) !== "/") { - path += "/"; // IE doesn't like substr(-1) - } - return path; -}; - -/** - * Add a (sub) folder in the current folder. - * @private - * @param {string} name the folder's name - * @param {boolean=} [createFolders] If true, automatically create sub - * folders. Defaults to false. - * @return {Object} the new folder. - */ -var folderAdd = function(name, createFolders) { - createFolders = (typeof createFolders !== 'undefined') ? createFolders : defaults.createFolders; - - name = forceTrailingSlash(name); - - // Does this folder already exist? - if (!this.files[name]) { - fileAdd.call(this, name, null, { - dir: true, - createFolders: createFolders - }); - } - return this.files[name]; -}; - -/** -* Cross-window, cross-Node-context regular expression detection -* @param {Object} object Anything -* @return {Boolean} true if the object is a regular expression, -* false otherwise -*/ -function isRegExp(object) { - return Object.prototype.toString.call(object) === "[object RegExp]"; -} - -// return the actual prototype of JSZip -var out = { - /** - * @see loadAsync - */ - load: function() { - throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); - }, - - - /** - * Call a callback function for each entry at this folder level. - * @param {Function} cb the callback function: - * function (relativePath, file) {...} - * It takes 2 arguments : the relative path and the file. - */ - forEach: function(cb) { - var filename, relativePath, file; - for (filename in this.files) { - if (!this.files.hasOwnProperty(filename)) { - continue; - } - file = this.files[filename]; - relativePath = filename.slice(this.root.length, filename.length); - if (relativePath && filename.slice(0, this.root.length) === this.root) { // the file is in the current root - cb(relativePath, file); // TODO reverse the parameters ? need to be clean AND consistent with the filter search fn... - } - } - }, - - /** - * Filter nested files/folders with the specified function. - * @param {Function} search the predicate to use : - * function (relativePath, file) {...} - * It takes 2 arguments : the relative path and the file. - * @return {Array} An array of matching elements. - */ - filter: function(search) { - var result = []; - this.forEach(function (relativePath, entry) { - if (search(relativePath, entry)) { // the file matches the function - result.push(entry); - } - - }); - return result; - }, - - /** - * Add a file to the zip file, or search a file. - * @param {string|RegExp} name The name of the file to add (if data is defined), - * the name of the file to find (if no data) or a regex to match files. - * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded - * @param {Object} o File options - * @return {JSZip|Object|Array} this JSZip object (when adding a file), - * a file (when searching by string) or an array of files (when searching by regex). - */ - file: function(name, data, o) { - if (arguments.length === 1) { - if (isRegExp(name)) { - var regexp = name; - return this.filter(function(relativePath, file) { - return !file.dir && regexp.test(relativePath); - }); - } - else { // text - var obj = this.files[this.root + name]; - if (obj && !obj.dir) { - return obj; - } else { - return null; - } - } - } - else { // more than one argument : we have data ! - name = this.root + name; - fileAdd.call(this, name, data, o); - } - return this; - }, - - /** - * Add a directory to the zip file, or search. - * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. - * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. - */ - folder: function(arg) { - if (!arg) { - return this; - } - - if (isRegExp(arg)) { - return this.filter(function(relativePath, file) { - return file.dir && arg.test(relativePath); - }); - } - - // else, name is a new folder - var name = this.root + arg; - var newFolder = folderAdd.call(this, name); - - // Allow chaining by returning a new object with this folder as the root - var ret = this.clone(); - ret.root = newFolder.name; - return ret; - }, - - /** - * Delete a file, or a directory and all sub-files, from the zip - * @param {string} name the name of the file to delete - * @return {JSZip} this JSZip object - */ - remove: function(name) { - name = this.root + name; - var file = this.files[name]; - if (!file) { - // Look for any folders - if (name.slice(-1) !== "/") { - name += "/"; - } - file = this.files[name]; - } - - if (file && !file.dir) { - // file - delete this.files[name]; - } else { - // maybe a folder, delete recursively - var kids = this.filter(function(relativePath, file) { - return file.name.slice(0, name.length) === name; - }); - for (var i = 0; i < kids.length; i++) { - delete this.files[kids[i].name]; - } - } - - return this; - }, - - /** - * Generate the complete zip file - * @param {Object} options the options to generate the zip file : - * - compression, "STORE" by default. - * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. - * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file - */ - generate: function(options) { - throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); - }, - - /** - * Generate the complete zip file as an internal stream. - * @param {Object} options the options to generate the zip file : - * - compression, "STORE" by default. - * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. - * @return {StreamHelper} the streamed zip file. - */ - generateInternalStream: function(options) { - var worker, opts = {}; - try { - opts = utils.extend(options || {}, { - streamFiles: false, - compression: "STORE", - compressionOptions : null, - type: "", - platform: "DOS", - comment: null, - mimeType: 'application/zip', - encodeFileName: utf8.utf8encode - }); - - opts.type = opts.type.toLowerCase(); - opts.compression = opts.compression.toUpperCase(); - - // "binarystring" is prefered but the internals use "string". - if(opts.type === "binarystring") { - opts.type = "string"; - } - - if (!opts.type) { - throw new Error("No output type specified."); - } - - utils.checkSupport(opts.type); - - // accept nodejs `process.platform` - if( - opts.platform === 'darwin' || - opts.platform === 'freebsd' || - opts.platform === 'linux' || - opts.platform === 'sunos' - ) { - opts.platform = "UNIX"; - } - if (opts.platform === 'win32') { - opts.platform = "DOS"; - } - - var comment = opts.comment || this.comment || ""; - worker = generate.generateWorker(this, opts, comment); - } catch (e) { - worker = new GenericWorker("error"); - worker.error(e); - } - return new StreamHelper(worker, opts.type || "string", opts.mimeType); - }, - /** - * Generate the complete zip file asynchronously. - * @see generateInternalStream - */ - generateAsync: function(options, onUpdate) { - return this.generateInternalStream(options).accumulate(onUpdate); - }, - /** - * Generate the complete zip file asynchronously. - * @see generateInternalStream - */ - generateNodeStream: function(options, onUpdate) { - options = options || {}; - if (!options.type) { - options.type = "nodebuffer"; - } - return this.generateInternalStream(options).toNodejsStream(onUpdate); - } -}; -module.exports = out; - -},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(require,module,exports){ -/* - * This file is used by module bundlers (browserify/webpack/etc) when - * including a stream implementation. We use "readable-stream" to get a - * consistent behavior between nodejs versions but bundlers often have a shim - * for "stream". Using this shim greatly improve the compatibility and greatly - * reduce the final size of the bundle (only one stream implementation, not - * two). - */ -module.exports = require("stream"); - -},{"stream":undefined}],17:[function(require,module,exports){ -'use strict'; -var DataReader = require('./DataReader'); -var utils = require('../utils'); - -function ArrayReader(data) { - DataReader.call(this, data); - for(var i = 0; i < this.data.length; i++) { - data[i] = data[i] & 0xFF; - } -} -utils.inherits(ArrayReader, DataReader); -/** - * @see DataReader.byteAt - */ -ArrayReader.prototype.byteAt = function(i) { - return this.data[this.zero + i]; -}; -/** - * @see DataReader.lastIndexOfSignature - */ -ArrayReader.prototype.lastIndexOfSignature = function(sig) { - var sig0 = sig.charCodeAt(0), - sig1 = sig.charCodeAt(1), - sig2 = sig.charCodeAt(2), - sig3 = sig.charCodeAt(3); - for (var i = this.length - 4; i >= 0; --i) { - if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { - return i - this.zero; - } - } - - return -1; -}; -/** - * @see DataReader.readAndCheckSignature - */ -ArrayReader.prototype.readAndCheckSignature = function (sig) { - var sig0 = sig.charCodeAt(0), - sig1 = sig.charCodeAt(1), - sig2 = sig.charCodeAt(2), - sig3 = sig.charCodeAt(3), - data = this.readData(4); - return sig0 === data[0] && sig1 === data[1] && sig2 === data[2] && sig3 === data[3]; -}; -/** - * @see DataReader.readData - */ -ArrayReader.prototype.readData = function(size) { - this.checkOffset(size); - if(size === 0) { - return []; - } - var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); - this.index += size; - return result; -}; -module.exports = ArrayReader; - -},{"../utils":32,"./DataReader":18}],18:[function(require,module,exports){ -'use strict'; -var utils = require('../utils'); - -function DataReader(data) { - this.data = data; // type : see implementation - this.length = data.length; - this.index = 0; - this.zero = 0; -} -DataReader.prototype = { - /** - * Check that the offset will not go too far. - * @param {string} offset the additional offset to check. - * @throws {Error} an Error if the offset is out of bounds. - */ - checkOffset: function(offset) { - this.checkIndex(this.index + offset); - }, - /** - * Check that the specified index will not be too far. - * @param {string} newIndex the index to check. - * @throws {Error} an Error if the index is out of bounds. - */ - checkIndex: function(newIndex) { - if (this.length < this.zero + newIndex || newIndex < 0) { - throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); - } - }, - /** - * Change the index. - * @param {number} newIndex The new index. - * @throws {Error} if the new index is out of the data. - */ - setIndex: function(newIndex) { - this.checkIndex(newIndex); - this.index = newIndex; - }, - /** - * Skip the next n bytes. - * @param {number} n the number of bytes to skip. - * @throws {Error} if the new index is out of the data. - */ - skip: function(n) { - this.setIndex(this.index + n); - }, - /** - * Get the byte at the specified index. - * @param {number} i the index to use. - * @return {number} a byte. - */ - byteAt: function(i) { - // see implementations - }, - /** - * Get the next number with a given byte size. - * @param {number} size the number of bytes to read. - * @return {number} the corresponding number. - */ - readInt: function(size) { - var result = 0, - i; - this.checkOffset(size); - for (i = this.index + size - 1; i >= this.index; i--) { - result = (result << 8) + this.byteAt(i); - } - this.index += size; - return result; - }, - /** - * Get the next string with a given byte size. - * @param {number} size the number of bytes to read. - * @return {string} the corresponding string. - */ - readString: function(size) { - return utils.transformTo("string", this.readData(size)); - }, - /** - * Get raw data without conversion, bytes. - * @param {number} size the number of bytes to read. - * @return {Object} the raw data, implementation specific. - */ - readData: function(size) { - // see implementations - }, - /** - * Find the last occurence of a zip signature (4 bytes). - * @param {string} sig the signature to find. - * @return {number} the index of the last occurence, -1 if not found. - */ - lastIndexOfSignature: function(sig) { - // see implementations - }, - /** - * Read the signature (4 bytes) at the current position and compare it with sig. - * @param {string} sig the expected signature - * @return {boolean} true if the signature matches, false otherwise. - */ - readAndCheckSignature: function(sig) { - // see implementations - }, - /** - * Get the next date. - * @return {Date} the date. - */ - readDate: function() { - var dostime = this.readInt(4); - return new Date(Date.UTC( - ((dostime >> 25) & 0x7f) + 1980, // year - ((dostime >> 21) & 0x0f) - 1, // month - (dostime >> 16) & 0x1f, // day - (dostime >> 11) & 0x1f, // hour - (dostime >> 5) & 0x3f, // minute - (dostime & 0x1f) << 1)); // second - } -}; -module.exports = DataReader; - -},{"../utils":32}],19:[function(require,module,exports){ -'use strict'; -var Uint8ArrayReader = require('./Uint8ArrayReader'); -var utils = require('../utils'); - -function NodeBufferReader(data) { - Uint8ArrayReader.call(this, data); -} -utils.inherits(NodeBufferReader, Uint8ArrayReader); - -/** - * @see DataReader.readData - */ -NodeBufferReader.prototype.readData = function(size) { - this.checkOffset(size); - var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); - this.index += size; - return result; -}; -module.exports = NodeBufferReader; - -},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(require,module,exports){ -'use strict'; -var DataReader = require('./DataReader'); -var utils = require('../utils'); - -function StringReader(data) { - DataReader.call(this, data); -} -utils.inherits(StringReader, DataReader); -/** - * @see DataReader.byteAt - */ -StringReader.prototype.byteAt = function(i) { - return this.data.charCodeAt(this.zero + i); -}; -/** - * @see DataReader.lastIndexOfSignature - */ -StringReader.prototype.lastIndexOfSignature = function(sig) { - return this.data.lastIndexOf(sig) - this.zero; -}; -/** - * @see DataReader.readAndCheckSignature - */ -StringReader.prototype.readAndCheckSignature = function (sig) { - var data = this.readData(4); - return sig === data; -}; -/** - * @see DataReader.readData - */ -StringReader.prototype.readData = function(size) { - this.checkOffset(size); - // this will work because the constructor applied the "& 0xff" mask. - var result = this.data.slice(this.zero + this.index, this.zero + this.index + size); - this.index += size; - return result; -}; -module.exports = StringReader; - -},{"../utils":32,"./DataReader":18}],21:[function(require,module,exports){ -'use strict'; -var ArrayReader = require('./ArrayReader'); -var utils = require('../utils'); - -function Uint8ArrayReader(data) { - ArrayReader.call(this, data); -} -utils.inherits(Uint8ArrayReader, ArrayReader); -/** - * @see DataReader.readData - */ -Uint8ArrayReader.prototype.readData = function(size) { - this.checkOffset(size); - if(size === 0) { - // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. - return new Uint8Array(0); - } - var result = this.data.subarray(this.zero + this.index, this.zero + this.index + size); - this.index += size; - return result; -}; -module.exports = Uint8ArrayReader; - -},{"../utils":32,"./ArrayReader":17}],22:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var support = require('../support'); -var ArrayReader = require('./ArrayReader'); -var StringReader = require('./StringReader'); -var NodeBufferReader = require('./NodeBufferReader'); -var Uint8ArrayReader = require('./Uint8ArrayReader'); - -/** - * Create a reader adapted to the data. - * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data to read. - * @return {DataReader} the data reader. - */ -module.exports = function (data) { - var type = utils.getTypeOf(data); - utils.checkSupport(type); - if (type === "string" && !support.uint8array) { - return new StringReader(data); - } - if (type === "nodebuffer") { - return new NodeBufferReader(data); - } - if (support.uint8array) { - return new Uint8ArrayReader(utils.transformTo("uint8array", data)); - } - return new ArrayReader(utils.transformTo("array", data)); -}; - -},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(require,module,exports){ -'use strict'; -exports.LOCAL_FILE_HEADER = "PK\x03\x04"; -exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; -exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; -exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; -exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; -exports.DATA_DESCRIPTOR = "PK\x07\x08"; - -},{}],24:[function(require,module,exports){ -'use strict'; - -var GenericWorker = require('./GenericWorker'); -var utils = require('../utils'); - -/** - * A worker which convert chunks to a specified type. - * @constructor - * @param {String} destType the destination type. - */ -function ConvertWorker(destType) { - GenericWorker.call(this, "ConvertWorker to " + destType); - this.destType = destType; -} -utils.inherits(ConvertWorker, GenericWorker); - -/** - * @see GenericWorker.processChunk - */ -ConvertWorker.prototype.processChunk = function (chunk) { - this.push({ - data : utils.transformTo(this.destType, chunk.data), - meta : chunk.meta - }); -}; -module.exports = ConvertWorker; - -},{"../utils":32,"./GenericWorker":28}],25:[function(require,module,exports){ -'use strict'; - -var GenericWorker = require('./GenericWorker'); -var crc32 = require('../crc32'); -var utils = require('../utils'); - -/** - * A worker which calculate the crc32 of the data flowing through. - * @constructor - */ -function Crc32Probe() { - GenericWorker.call(this, "Crc32Probe"); - this.withStreamInfo("crc32", 0); -} -utils.inherits(Crc32Probe, GenericWorker); - -/** - * @see GenericWorker.processChunk - */ -Crc32Probe.prototype.processChunk = function (chunk) { - this.streamInfo.crc32 = crc32(chunk.data, this.streamInfo.crc32 || 0); - this.push(chunk); -}; -module.exports = Crc32Probe; - -},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var GenericWorker = require('./GenericWorker'); - -/** - * A worker which calculate the total length of the data flowing through. - * @constructor - * @param {String} propName the name used to expose the length - */ -function DataLengthProbe(propName) { - GenericWorker.call(this, "DataLengthProbe for " + propName); - this.propName = propName; - this.withStreamInfo(propName, 0); -} -utils.inherits(DataLengthProbe, GenericWorker); - -/** - * @see GenericWorker.processChunk - */ -DataLengthProbe.prototype.processChunk = function (chunk) { - if(chunk) { - var length = this.streamInfo[this.propName] || 0; - this.streamInfo[this.propName] = length + chunk.data.length; - } - GenericWorker.prototype.processChunk.call(this, chunk); -}; -module.exports = DataLengthProbe; - - -},{"../utils":32,"./GenericWorker":28}],27:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var GenericWorker = require('./GenericWorker'); - -// the size of the generated chunks -// TODO expose this as a public variable -var DEFAULT_BLOCK_SIZE = 16 * 1024; - -/** - * A worker that reads a content and emits chunks. - * @constructor - * @param {Promise} dataP the promise of the data to split - */ -function DataWorker(dataP) { - GenericWorker.call(this, "DataWorker"); - var self = this; - this.dataIsReady = false; - this.index = 0; - this.max = 0; - this.data = null; - this.type = ""; - - this._tickScheduled = false; - - dataP.then(function (data) { - self.dataIsReady = true; - self.data = data; - self.max = data && data.length || 0; - self.type = utils.getTypeOf(data); - if(!self.isPaused) { - self._tickAndRepeat(); - } - }, function (e) { - self.error(e); - }); -} - -utils.inherits(DataWorker, GenericWorker); - -/** - * @see GenericWorker.cleanUp - */ -DataWorker.prototype.cleanUp = function () { - GenericWorker.prototype.cleanUp.call(this); - this.data = null; -}; - -/** - * @see GenericWorker.resume - */ -DataWorker.prototype.resume = function () { - if(!GenericWorker.prototype.resume.call(this)) { - return false; - } - - if (!this._tickScheduled && this.dataIsReady) { - this._tickScheduled = true; - utils.delay(this._tickAndRepeat, [], this); - } - return true; -}; - -/** - * Trigger a tick a schedule an other call to this function. - */ -DataWorker.prototype._tickAndRepeat = function() { - this._tickScheduled = false; - if(this.isPaused || this.isFinished) { - return; - } - this._tick(); - if(!this.isFinished) { - utils.delay(this._tickAndRepeat, [], this); - this._tickScheduled = true; - } -}; - -/** - * Read and push a chunk. - */ -DataWorker.prototype._tick = function() { - - if(this.isPaused || this.isFinished) { - return false; - } - - var size = DEFAULT_BLOCK_SIZE; - var data = null, nextIndex = Math.min(this.max, this.index + size); - if (this.index >= this.max) { - // EOF - return this.end(); - } else { - switch(this.type) { - case "string": - data = this.data.substring(this.index, nextIndex); - break; - case "uint8array": - data = this.data.subarray(this.index, nextIndex); - break; - case "array": - case "nodebuffer": - data = this.data.slice(this.index, nextIndex); - break; - } - this.index = nextIndex; - return this.push({ - data : data, - meta : { - percent : this.max ? this.index / this.max * 100 : 0 - } - }); - } -}; - -module.exports = DataWorker; - -},{"../utils":32,"./GenericWorker":28}],28:[function(require,module,exports){ -'use strict'; - -/** - * A worker that does nothing but passing chunks to the next one. This is like - * a nodejs stream but with some differences. On the good side : - * - it works on IE 6-9 without any issue / polyfill - * - it weights less than the full dependencies bundled with browserify - * - it forwards errors (no need to declare an error handler EVERYWHERE) - * - * A chunk is an object with 2 attributes : `meta` and `data`. The former is an - * object containing anything (`percent` for example), see each worker for more - * details. The latter is the real data (String, Uint8Array, etc). - * - * @constructor - * @param {String} name the name of the stream (mainly used for debugging purposes) - */ -function GenericWorker(name) { - // the name of the worker - this.name = name || "default"; - // an object containing metadata about the workers chain - this.streamInfo = {}; - // an error which happened when the worker was paused - this.generatedError = null; - // an object containing metadata to be merged by this worker into the general metadata - this.extraStreamInfo = {}; - // true if the stream is paused (and should not do anything), false otherwise - this.isPaused = true; - // true if the stream is finished (and should not do anything), false otherwise - this.isFinished = false; - // true if the stream is locked to prevent further structure updates (pipe), false otherwise - this.isLocked = false; - // the event listeners - this._listeners = { - 'data':[], - 'end':[], - 'error':[] - }; - // the previous worker, if any - this.previous = null; -} - -GenericWorker.prototype = { - /** - * Push a chunk to the next workers. - * @param {Object} chunk the chunk to push - */ - push : function (chunk) { - this.emit("data", chunk); - }, - /** - * End the stream. - * @return {Boolean} true if this call ended the worker, false otherwise. - */ - end : function () { - if (this.isFinished) { - return false; - } - - this.flush(); - try { - this.emit("end"); - this.cleanUp(); - this.isFinished = true; - } catch (e) { - this.emit("error", e); - } - return true; - }, - /** - * End the stream with an error. - * @param {Error} e the error which caused the premature end. - * @return {Boolean} true if this call ended the worker with an error, false otherwise. - */ - error : function (e) { - if (this.isFinished) { - return false; - } - - if(this.isPaused) { - this.generatedError = e; - } else { - this.isFinished = true; - - this.emit("error", e); - - // in the workers chain exploded in the middle of the chain, - // the error event will go downward but we also need to notify - // workers upward that there has been an error. - if(this.previous) { - this.previous.error(e); - } - - this.cleanUp(); - } - return true; - }, - /** - * Add a callback on an event. - * @param {String} name the name of the event (data, end, error) - * @param {Function} listener the function to call when the event is triggered - * @return {GenericWorker} the current object for chainability - */ - on : function (name, listener) { - this._listeners[name].push(listener); - return this; - }, - /** - * Clean any references when a worker is ending. - */ - cleanUp : function () { - this.streamInfo = this.generatedError = this.extraStreamInfo = null; - this._listeners = []; - }, - /** - * Trigger an event. This will call registered callback with the provided arg. - * @param {String} name the name of the event (data, end, error) - * @param {Object} arg the argument to call the callback with. - */ - emit : function (name, arg) { - if (this._listeners[name]) { - for(var i = 0; i < this._listeners[name].length; i++) { - this._listeners[name][i].call(this, arg); - } - } - }, - /** - * Chain a worker with an other. - * @param {Worker} next the worker receiving events from the current one. - * @return {worker} the next worker for chainability - */ - pipe : function (next) { - return next.registerPrevious(this); - }, - /** - * Same as `pipe` in the other direction. - * Using an API with `pipe(next)` is very easy. - * Implementing the API with the point of view of the next one registering - * a source is easier, see the ZipFileWorker. - * @param {Worker} previous the previous worker, sending events to this one - * @return {Worker} the current worker for chainability - */ - registerPrevious : function (previous) { - if (this.isLocked) { - throw new Error("The stream '" + this + "' has already been used."); - } - - // sharing the streamInfo... - this.streamInfo = previous.streamInfo; - // ... and adding our own bits - this.mergeStreamInfo(); - this.previous = previous; - var self = this; - previous.on('data', function (chunk) { - self.processChunk(chunk); - }); - previous.on('end', function () { - self.end(); - }); - previous.on('error', function (e) { - self.error(e); - }); - return this; - }, - /** - * Pause the stream so it doesn't send events anymore. - * @return {Boolean} true if this call paused the worker, false otherwise. - */ - pause : function () { - if(this.isPaused || this.isFinished) { - return false; - } - this.isPaused = true; - - if(this.previous) { - this.previous.pause(); - } - return true; - }, - /** - * Resume a paused stream. - * @return {Boolean} true if this call resumed the worker, false otherwise. - */ - resume : function () { - if(!this.isPaused || this.isFinished) { - return false; - } - this.isPaused = false; - - // if true, the worker tried to resume but failed - var withError = false; - if(this.generatedError) { - this.error(this.generatedError); - withError = true; - } - if(this.previous) { - this.previous.resume(); - } - - return !withError; - }, - /** - * Flush any remaining bytes as the stream is ending. - */ - flush : function () {}, - /** - * Process a chunk. This is usually the method overridden. - * @param {Object} chunk the chunk to process. - */ - processChunk : function(chunk) { - this.push(chunk); - }, - /** - * Add a key/value to be added in the workers chain streamInfo once activated. - * @param {String} key the key to use - * @param {Object} value the associated value - * @return {Worker} the current worker for chainability - */ - withStreamInfo : function (key, value) { - this.extraStreamInfo[key] = value; - this.mergeStreamInfo(); - return this; - }, - /** - * Merge this worker's streamInfo into the chain's streamInfo. - */ - mergeStreamInfo : function () { - for(var key in this.extraStreamInfo) { - if (!this.extraStreamInfo.hasOwnProperty(key)) { - continue; - } - this.streamInfo[key] = this.extraStreamInfo[key]; - } - }, - - /** - * Lock the stream to prevent further updates on the workers chain. - * After calling this method, all calls to pipe will fail. - */ - lock: function () { - if (this.isLocked) { - throw new Error("The stream '" + this + "' has already been used."); - } - this.isLocked = true; - if (this.previous) { - this.previous.lock(); - } - }, - - /** - * - * Pretty print the workers chain. - */ - toString : function () { - var me = "Worker " + this.name; - if (this.previous) { - return this.previous + " -> " + me; - } else { - return me; - } - } -}; - -module.exports = GenericWorker; - -},{}],29:[function(require,module,exports){ -'use strict'; - -var utils = require('../utils'); -var ConvertWorker = require('./ConvertWorker'); -var GenericWorker = require('./GenericWorker'); -var base64 = require('../base64'); -var support = require("../support"); -var external = require("../external"); - -var NodejsStreamOutputAdapter = null; -if (support.nodestream) { - try { - NodejsStreamOutputAdapter = require('../nodejs/NodejsStreamOutputAdapter'); - } catch(e) {} -} - -/** - * Apply the final transformation of the data. If the user wants a Blob for - * example, it's easier to work with an U8intArray and finally do the - * ArrayBuffer/Blob conversion. - * @param {String} type the name of the final type - * @param {String|Uint8Array|Buffer} content the content to transform - * @param {String} mimeType the mime type of the content, if applicable. - * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the content in the right format. - */ -function transformZipOutput(type, content, mimeType) { - switch(type) { - case "blob" : - return utils.newBlob(utils.transformTo("arraybuffer", content), mimeType); - case "base64" : - return base64.encode(content); - default : - return utils.transformTo(type, content); - } -} - -/** - * Concatenate an array of data of the given type. - * @param {String} type the type of the data in the given array. - * @param {Array} dataArray the array containing the data chunks to concatenate - * @return {String|Uint8Array|Buffer} the concatenated data - * @throws Error if the asked type is unsupported - */ -function concat (type, dataArray) { - var i, index = 0, res = null, totalLength = 0; - for(i = 0; i < dataArray.length; i++) { - totalLength += dataArray[i].length; - } - switch(type) { - case "string": - return dataArray.join(""); - case "array": - return Array.prototype.concat.apply([], dataArray); - case "uint8array": - res = new Uint8Array(totalLength); - for(i = 0; i < dataArray.length; i++) { - res.set(dataArray[i], index); - index += dataArray[i].length; - } - return res; - case "nodebuffer": - return Buffer.concat(dataArray); - default: - throw new Error("concat : unsupported type '" + type + "'"); - } -} - -/** - * Listen a StreamHelper, accumulate its content and concatenate it into a - * complete block. - * @param {StreamHelper} helper the helper to use. - * @param {Function} updateCallback a callback called on each update. Called - * with one arg : - * - the metadata linked to the update received. - * @return Promise the promise for the accumulation. - */ -function accumulate(helper, updateCallback) { - return new external.Promise(function (resolve, reject){ - var dataArray = []; - var chunkType = helper._internalType, - resultType = helper._outputType, - mimeType = helper._mimeType; - helper - .on('data', function (data, meta) { - dataArray.push(data); - if(updateCallback) { - updateCallback(meta); - } - }) - .on('error', function(err) { - dataArray = []; - reject(err); - }) - .on('end', function (){ - try { - var result = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType); - resolve(result); - } catch (e) { - reject(e); - } - dataArray = []; - }) - .resume(); - }); -} - -/** - * An helper to easily use workers outside of JSZip. - * @constructor - * @param {Worker} worker the worker to wrap - * @param {String} outputType the type of data expected by the use - * @param {String} mimeType the mime type of the content, if applicable. - */ -function StreamHelper(worker, outputType, mimeType) { - var internalType = outputType; - switch(outputType) { - case "blob": - case "arraybuffer": - internalType = "uint8array"; - break; - case "base64": - internalType = "string"; - break; - } - - try { - // the type used internally - this._internalType = internalType; - // the type used to output results - this._outputType = outputType; - // the mime type - this._mimeType = mimeType; - utils.checkSupport(internalType); - this._worker = worker.pipe(new ConvertWorker(internalType)); - // the last workers can be rewired without issues but we need to - // prevent any updates on previous workers. - worker.lock(); - } catch(e) { - this._worker = new GenericWorker("error"); - this._worker.error(e); - } -} - -StreamHelper.prototype = { - /** - * Listen a StreamHelper, accumulate its content and concatenate it into a - * complete block. - * @param {Function} updateCb the update callback. - * @return Promise the promise for the accumulation. - */ - accumulate : function (updateCb) { - return accumulate(this, updateCb); - }, - /** - * Add a listener on an event triggered on a stream. - * @param {String} evt the name of the event - * @param {Function} fn the listener - * @return {StreamHelper} the current helper. - */ - on : function (evt, fn) { - var self = this; - - if(evt === "data") { - this._worker.on(evt, function (chunk) { - fn.call(self, chunk.data, chunk.meta); - }); - } else { - this._worker.on(evt, function () { - utils.delay(fn, arguments, self); - }); - } - return this; - }, - /** - * Resume the flow of chunks. - * @return {StreamHelper} the current helper. - */ - resume : function () { - utils.delay(this._worker.resume, [], this._worker); - return this; - }, - /** - * Pause the flow of chunks. - * @return {StreamHelper} the current helper. - */ - pause : function () { - this._worker.pause(); - return this; - }, - /** - * Return a nodejs stream for this helper. - * @param {Function} updateCb the update callback. - * @return {NodejsStreamOutputAdapter} the nodejs stream. - */ - toNodejsStream : function (updateCb) { - utils.checkSupport("nodestream"); - if (this._outputType !== "nodebuffer") { - // an object stream containing blob/arraybuffer/uint8array/string - // is strange and I don't know if it would be useful. - // I you find this comment and have a good usecase, please open a - // bug report ! - throw new Error(this._outputType + " is not supported by this method"); - } - - return new NodejsStreamOutputAdapter(this, { - objectMode : this._outputType !== "nodebuffer" - }, updateCb); - } -}; - - -module.exports = StreamHelper; - -},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(require,module,exports){ -'use strict'; - -exports.base64 = true; -exports.array = true; -exports.string = true; -exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; -exports.nodebuffer = typeof Buffer !== "undefined"; -// contains true if JSZip can read/generate Uint8Array, false otherwise. -exports.uint8array = typeof Uint8Array !== "undefined"; - -if (typeof ArrayBuffer === "undefined") { - exports.blob = false; -} -else { - var buffer = new ArrayBuffer(0); - try { - exports.blob = new Blob([buffer], { - type: "application/zip" - }).size === 0; - } - catch (e) { - try { - var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; - var builder = new Builder(); - builder.append(buffer); - exports.blob = builder.getBlob('application/zip').size === 0; - } - catch (e) { - exports.blob = false; - } - } -} - -try { - exports.nodestream = !!require('readable-stream').Readable; -} catch(e) { - exports.nodestream = false; -} - -},{"readable-stream":16}],31:[function(require,module,exports){ -'use strict'; - -var utils = require('./utils'); -var support = require('./support'); -var nodejsUtils = require('./nodejsUtils'); -var GenericWorker = require('./stream/GenericWorker'); - -/** - * The following functions come from pako, from pako/lib/utils/strings - * released under the MIT license, see pako https://github.com/nodeca/pako/ - */ - -// Table with utf8 lengths (calculated by first byte of sequence) -// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, -// because max possible codepoint is 0x10ffff -var _utf8len = new Array(256); -for (var i=0; i<256; i++) { - _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); -} -_utf8len[254]=_utf8len[254]=1; // Invalid sequence start - -// convert string to array (typed, when possible) -var string2buf = function (str) { - var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; - - // count binary size - for (m_pos = 0; m_pos < str_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { - c2 = str.charCodeAt(m_pos+1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; - } - - // allocate buffer - if (support.uint8array) { - buf = new Uint8Array(buf_len); - } else { - buf = new Array(buf_len); - } - - // convert - for (i=0, m_pos = 0; i < buf_len; m_pos++) { - c = str.charCodeAt(m_pos); - if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { - c2 = str.charCodeAt(m_pos+1); - if ((c2 & 0xfc00) === 0xdc00) { - c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); - m_pos++; - } - } - if (c < 0x80) { - /* one byte */ - buf[i++] = c; - } else if (c < 0x800) { - /* two bytes */ - buf[i++] = 0xC0 | (c >>> 6); - buf[i++] = 0x80 | (c & 0x3f); - } else if (c < 0x10000) { - /* three bytes */ - buf[i++] = 0xE0 | (c >>> 12); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } else { - /* four bytes */ - buf[i++] = 0xf0 | (c >>> 18); - buf[i++] = 0x80 | (c >>> 12 & 0x3f); - buf[i++] = 0x80 | (c >>> 6 & 0x3f); - buf[i++] = 0x80 | (c & 0x3f); - } - } - - return buf; -}; - -// Calculate max possible position in utf8 buffer, -// that will not break sequence. If that's not possible -// - (very small limits) return max size as is. -// -// buf[] - utf8 bytes array -// max - length limit (mandatory); -var utf8border = function(buf, max) { - var pos; - - max = max || buf.length; - if (max > buf.length) { max = buf.length; } - - // go back from last position, until start of sequence found - pos = max-1; - while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } - - // Fuckup - very small and broken sequence, - // return max, because we should return something anyway. - if (pos < 0) { return max; } - - // If we came to start of buffer - that means vuffer is too small, - // return max too. - if (pos === 0) { return max; } - - return (pos + _utf8len[buf[pos]] > max) ? pos : max; -}; - -// convert array to string -var buf2string = function (buf) { - var str, i, out, c, c_len; - var len = buf.length; - - // Reserve max possible length (2 words per char) - // NB: by unknown reasons, Array is significantly faster for - // String.fromCharCode.apply than Uint16Array. - var utf16buf = new Array(len*2); - - for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } - - // apply mask on first byte - c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; - // join the rest - while (c_len > 1 && i < len) { - c = (c << 6) | (buf[i++] & 0x3f); - c_len--; - } - - // terminated by end of string? - if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } - - if (c < 0x10000) { - utf16buf[out++] = c; - } else { - c -= 0x10000; - utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); - utf16buf[out++] = 0xdc00 | (c & 0x3ff); - } - } - - // shrinkBuf(utf16buf, out) - if (utf16buf.length !== out) { - if(utf16buf.subarray) { - utf16buf = utf16buf.subarray(0, out); - } else { - utf16buf.length = out; - } - } - - // return String.fromCharCode.apply(null, utf16buf); - return utils.applyFromCharCode(utf16buf); -}; - - -// That's all for the pako functions. - - -/** - * Transform a javascript string into an array (typed if possible) of bytes, - * UTF-8 encoded. - * @param {String} str the string to encode - * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. - */ -exports.utf8encode = function utf8encode(str) { - if (support.nodebuffer) { - return nodejsUtils.newBufferFrom(str, "utf-8"); - } - - return string2buf(str); -}; - - -/** - * Transform a bytes array (or a representation) representing an UTF-8 encoded - * string into a javascript string. - * @param {Array|Uint8Array|Buffer} buf the data de decode - * @return {String} the decoded string. - */ -exports.utf8decode = function utf8decode(buf) { - if (support.nodebuffer) { - return utils.transformTo("nodebuffer", buf).toString("utf-8"); - } - - buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); - - return buf2string(buf); -}; - -/** - * A worker to decode utf8 encoded binary chunks into string chunks. - * @constructor - */ -function Utf8DecodeWorker() { - GenericWorker.call(this, "utf-8 decode"); - // the last bytes if a chunk didn't end with a complete codepoint. - this.leftOver = null; -} -utils.inherits(Utf8DecodeWorker, GenericWorker); - -/** - * @see GenericWorker.processChunk - */ -Utf8DecodeWorker.prototype.processChunk = function (chunk) { - - var data = utils.transformTo(support.uint8array ? "uint8array" : "array", chunk.data); - - // 1st step, re-use what's left of the previous chunk - if (this.leftOver && this.leftOver.length) { - if(support.uint8array) { - var previousData = data; - data = new Uint8Array(previousData.length + this.leftOver.length); - data.set(this.leftOver, 0); - data.set(previousData, this.leftOver.length); - } else { - data = this.leftOver.concat(data); - } - this.leftOver = null; - } - - var nextBoundary = utf8border(data); - var usableData = data; - if (nextBoundary !== data.length) { - if (support.uint8array) { - usableData = data.subarray(0, nextBoundary); - this.leftOver = data.subarray(nextBoundary, data.length); - } else { - usableData = data.slice(0, nextBoundary); - this.leftOver = data.slice(nextBoundary, data.length); - } - } - - this.push({ - data : exports.utf8decode(usableData), - meta : chunk.meta - }); -}; - -/** - * @see GenericWorker.flush - */ -Utf8DecodeWorker.prototype.flush = function () { - if(this.leftOver && this.leftOver.length) { - this.push({ - data : exports.utf8decode(this.leftOver), - meta : {} - }); - this.leftOver = null; - } -}; -exports.Utf8DecodeWorker = Utf8DecodeWorker; - -/** - * A worker to endcode string chunks into utf8 encoded binary chunks. - * @constructor - */ -function Utf8EncodeWorker() { - GenericWorker.call(this, "utf-8 encode"); -} -utils.inherits(Utf8EncodeWorker, GenericWorker); - -/** - * @see GenericWorker.processChunk - */ -Utf8EncodeWorker.prototype.processChunk = function (chunk) { - this.push({ - data : exports.utf8encode(chunk.data), - meta : chunk.meta - }); -}; -exports.Utf8EncodeWorker = Utf8EncodeWorker; - -},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(require,module,exports){ -'use strict'; - -var support = require('./support'); -var base64 = require('./base64'); -var nodejsUtils = require('./nodejsUtils'); -var setImmediate = require('core-js/library/fn/set-immediate'); -var external = require("./external"); - - -/** - * Convert a string that pass as a "binary string": it should represent a byte - * array but may have > 255 char codes. Be sure to take only the first byte - * and returns the byte array. - * @param {String} str the string to transform. - * @return {Array|Uint8Array} the string in a binary format. - */ -function string2binary(str) { - var result = null; - if (support.uint8array) { - result = new Uint8Array(str.length); - } else { - result = new Array(str.length); - } - return stringToArrayLike(str, result); -} - -/** - * Create a new blob with the given content and the given type. - * @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use - * an Uint8Array because the stock browser of android 4 won't accept it (it - * will be silently converted to a string, "[object Uint8Array]"). - * - * Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: - * when a large amount of Array is used to create the Blob, the amount of - * memory consumed is nearly 100 times the original data amount. - * - * @param {String} type the mime type of the blob. - * @return {Blob} the created blob. - */ -exports.newBlob = function(part, type) { - exports.checkSupport("blob"); - - try { - // Blob constructor - return new Blob([part], { - type: type - }); - } - catch (e) { - - try { - // deprecated, browser only, old way - var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; - var builder = new Builder(); - builder.append(part); - return builder.getBlob(type); - } - catch (e) { - - // well, fuck ?! - throw new Error("Bug : can't construct the Blob."); - } - } - - -}; -/** - * The identity function. - * @param {Object} input the input. - * @return {Object} the same input. - */ -function identity(input) { - return input; -} - -/** - * Fill in an array with a string. - * @param {String} str the string to use. - * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). - * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. - */ -function stringToArrayLike(str, array) { - for (var i = 0; i < str.length; ++i) { - array[i] = str.charCodeAt(i) & 0xFF; - } - return array; -} - -/** - * An helper for the function arrayLikeToString. - * This contains static informations and functions that - * can be optimized by the browser JIT compiler. - */ -var arrayToStringHelper = { - /** - * Transform an array of int into a string, chunk by chunk. - * See the performances notes on arrayLikeToString. - * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. - * @param {String} type the type of the array. - * @param {Integer} chunk the chunk size. - * @return {String} the resulting string. - * @throws Error if the chunk is too big for the stack. - */ - stringifyByChunk: function(array, type, chunk) { - var result = [], k = 0, len = array.length; - // shortcut - if (len <= chunk) { - return String.fromCharCode.apply(null, array); - } - while (k < len) { - if (type === "array" || type === "nodebuffer") { - result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); - } - else { - result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); - } - k += chunk; - } - return result.join(""); - }, - /** - * Call String.fromCharCode on every item in the array. - * This is the naive implementation, which generate A LOT of intermediate string. - * This should be used when everything else fail. - * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. - * @return {String} the result. - */ - stringifyByChar: function(array){ - var resultStr = ""; - for(var i = 0; i < array.length; i++) { - resultStr += String.fromCharCode(array[i]); - } - return resultStr; - }, - applyCanBeUsed : { - /** - * true if the browser accepts to use String.fromCharCode on Uint8Array - */ - uint8array : (function () { - try { - return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; - } catch (e) { - return false; - } - })(), - /** - * true if the browser accepts to use String.fromCharCode on nodejs Buffer. - */ - nodebuffer : (function () { - try { - return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; - } catch (e) { - return false; - } - })() - } -}; - -/** - * Transform an array-like object to a string. - * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. - * @return {String} the result. - */ -function arrayLikeToString(array) { - // Performances notes : - // -------------------- - // String.fromCharCode.apply(null, array) is the fastest, see - // see http://jsperf.com/converting-a-uint8array-to-a-string/2 - // but the stack is limited (and we can get huge arrays !). - // - // result += String.fromCharCode(array[i]); generate too many strings ! - // - // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 - // TODO : we now have workers that split the work. Do we still need that ? - var chunk = 65536, - type = exports.getTypeOf(array), - canUseApply = true; - if (type === "uint8array") { - canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; - } else if (type === "nodebuffer") { - canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; - } - - if (canUseApply) { - while (chunk > 1) { - try { - return arrayToStringHelper.stringifyByChunk(array, type, chunk); - } catch (e) { - chunk = Math.floor(chunk / 2); - } - } - } - - // no apply or chunk error : slow and painful algorithm - // default browser on android 4.* - return arrayToStringHelper.stringifyByChar(array); -} - -exports.applyFromCharCode = arrayLikeToString; - - -/** - * Copy the data from an array-like to an other array-like. - * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. - * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. - * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. - */ -function arrayLikeToArrayLike(arrayFrom, arrayTo) { - for (var i = 0; i < arrayFrom.length; i++) { - arrayTo[i] = arrayFrom[i]; - } - return arrayTo; -} - -// a matrix containing functions to transform everything into everything. -var transform = {}; - -// string to ? -transform["string"] = { - "string": identity, - "array": function(input) { - return stringToArrayLike(input, new Array(input.length)); - }, - "arraybuffer": function(input) { - return transform["string"]["uint8array"](input).buffer; - }, - "uint8array": function(input) { - return stringToArrayLike(input, new Uint8Array(input.length)); - }, - "nodebuffer": function(input) { - return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); - } -}; - -// array to ? -transform["array"] = { - "string": arrayLikeToString, - "array": identity, - "arraybuffer": function(input) { - return (new Uint8Array(input)).buffer; - }, - "uint8array": function(input) { - return new Uint8Array(input); - }, - "nodebuffer": function(input) { - return nodejsUtils.newBufferFrom(input); - } -}; - -// arraybuffer to ? -transform["arraybuffer"] = { - "string": function(input) { - return arrayLikeToString(new Uint8Array(input)); - }, - "array": function(input) { - return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); - }, - "arraybuffer": identity, - "uint8array": function(input) { - return new Uint8Array(input); - }, - "nodebuffer": function(input) { - return nodejsUtils.newBufferFrom(new Uint8Array(input)); - } -}; - -// uint8array to ? -transform["uint8array"] = { - "string": arrayLikeToString, - "array": function(input) { - return arrayLikeToArrayLike(input, new Array(input.length)); - }, - "arraybuffer": function(input) { - return input.buffer; - }, - "uint8array": identity, - "nodebuffer": function(input) { - return nodejsUtils.newBufferFrom(input); - } -}; - -// nodebuffer to ? -transform["nodebuffer"] = { - "string": arrayLikeToString, - "array": function(input) { - return arrayLikeToArrayLike(input, new Array(input.length)); - }, - "arraybuffer": function(input) { - return transform["nodebuffer"]["uint8array"](input).buffer; - }, - "uint8array": function(input) { - return arrayLikeToArrayLike(input, new Uint8Array(input.length)); - }, - "nodebuffer": identity -}; - -/** - * Transform an input into any type. - * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. - * If no output type is specified, the unmodified input will be returned. - * @param {String} outputType the output type. - * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. - * @throws {Error} an Error if the browser doesn't support the requested output type. - */ -exports.transformTo = function(outputType, input) { - if (!input) { - // undefined, null, etc - // an empty string won't harm. - input = ""; - } - if (!outputType) { - return input; - } - exports.checkSupport(outputType); - var inputType = exports.getTypeOf(input); - var result = transform[inputType][outputType](input); - return result; -}; - -/** - * Return the type of the input. - * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. - * @param {Object} input the input to identify. - * @return {String} the (lowercase) type of the input. - */ -exports.getTypeOf = function(input) { - if (typeof input === "string") { - return "string"; - } - if (Object.prototype.toString.call(input) === "[object Array]") { - return "array"; - } - if (support.nodebuffer && nodejsUtils.isBuffer(input)) { - return "nodebuffer"; - } - if (support.uint8array && input instanceof Uint8Array) { - return "uint8array"; - } - if (support.arraybuffer && input instanceof ArrayBuffer) { - return "arraybuffer"; - } -}; - -/** - * Throw an exception if the type is not supported. - * @param {String} type the type to check. - * @throws {Error} an Error if the browser doesn't support the requested type. - */ -exports.checkSupport = function(type) { - var supported = support[type.toLowerCase()]; - if (!supported) { - throw new Error(type + " is not supported by this platform"); - } -}; - -exports.MAX_VALUE_16BITS = 65535; -exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 - -/** - * Prettify a string read as binary. - * @param {string} str the string to prettify. - * @return {string} a pretty string. - */ -exports.pretty = function(str) { - var res = '', - code, i; - for (i = 0; i < (str || "").length; i++) { - code = str.charCodeAt(i); - res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); - } - return res; -}; - -/** - * Defer the call of a function. - * @param {Function} callback the function to call asynchronously. - * @param {Array} args the arguments to give to the callback. - */ -exports.delay = function(callback, args, self) { - setImmediate(function () { - callback.apply(self || null, args || []); - }); -}; - -/** - * Extends a prototype with an other, without calling a constructor with - * side effects. Inspired by nodejs' `utils.inherits` - * @param {Function} ctor the constructor to augment - * @param {Function} superCtor the parent constructor to use - */ -exports.inherits = function (ctor, superCtor) { - var Obj = function() {}; - Obj.prototype = superCtor.prototype; - ctor.prototype = new Obj(); -}; - -/** - * Merge the objects passed as parameters into a new one. - * @private - * @param {...Object} var_args All objects to merge. - * @return {Object} a new object with the data of the others. - */ -exports.extend = function() { - var result = {}, i, attr; - for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers - for (attr in arguments[i]) { - if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { - result[attr] = arguments[i][attr]; - } - } - } - return result; -}; - -/** - * Transform arbitrary content into a Promise. - * @param {String} name a name for the content being processed. - * @param {Object} inputData the content to process. - * @param {Boolean} isBinary true if the content is not an unicode string - * @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. - * @param {Boolean} isBase64 true if the string content is encoded with base64. - * @return {Promise} a promise in a format usable by JSZip. - */ -exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { - - // if inputData is already a promise, this flatten it. - var promise = external.Promise.resolve(inputData).then(function(data) { - - - var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); - - if (isBlob && typeof FileReader !== "undefined") { - return new external.Promise(function (resolve, reject) { - var reader = new FileReader(); - - reader.onload = function(e) { - resolve(e.target.result); - }; - reader.onerror = function(e) { - reject(e.target.error); - }; - reader.readAsArrayBuffer(data); - }); - } else { - return data; - } - }); - - return promise.then(function(data) { - var dataType = exports.getTypeOf(data); - - if (!dataType) { - return external.Promise.reject( - new Error("Can't read the data of '" + name + "'. Is it " + - "in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") - ); - } - // special case : it's way easier to work with Uint8Array than with ArrayBuffer - if (dataType === "arraybuffer") { - data = exports.transformTo("uint8array", data); - } else if (dataType === "string") { - if (isBase64) { - data = base64.decode(data); - } - else if (isBinary) { - // optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask - if (isOptimizedBinaryString !== true) { - // this is a string, not in a base64 format. - // Be sure that this is a correct "binary string" - data = string2binary(data); - } - } - } - return data; - }); -}; - -},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"core-js/library/fn/set-immediate":36}],33:[function(require,module,exports){ -'use strict'; -var readerFor = require('./reader/readerFor'); -var utils = require('./utils'); -var sig = require('./signature'); -var ZipEntry = require('./zipEntry'); -var utf8 = require('./utf8'); -var support = require('./support'); -// class ZipEntries {{{ -/** - * All the entries in the zip file. - * @constructor - * @param {Object} loadOptions Options for loading the stream. - */ -function ZipEntries(loadOptions) { - this.files = []; - this.loadOptions = loadOptions; -} -ZipEntries.prototype = { - /** - * Check that the reader is on the specified signature. - * @param {string} expectedSignature the expected signature. - * @throws {Error} if it is an other signature. - */ - checkSignature: function(expectedSignature) { - if (!this.reader.readAndCheckSignature(expectedSignature)) { - this.reader.index -= 4; - var signature = this.reader.readString(4); - throw new Error("Corrupted zip or bug: unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); - } - }, - /** - * Check if the given signature is at the given index. - * @param {number} askedIndex the index to check. - * @param {string} expectedSignature the signature to expect. - * @return {boolean} true if the signature is here, false otherwise. - */ - isSignature: function(askedIndex, expectedSignature) { - var currentIndex = this.reader.index; - this.reader.setIndex(askedIndex); - var signature = this.reader.readString(4); - var result = signature === expectedSignature; - this.reader.setIndex(currentIndex); - return result; - }, - /** - * Read the end of the central directory. - */ - readBlockEndOfCentral: function() { - this.diskNumber = this.reader.readInt(2); - this.diskWithCentralDirStart = this.reader.readInt(2); - this.centralDirRecordsOnThisDisk = this.reader.readInt(2); - this.centralDirRecords = this.reader.readInt(2); - this.centralDirSize = this.reader.readInt(4); - this.centralDirOffset = this.reader.readInt(4); - - this.zipCommentLength = this.reader.readInt(2); - // warning : the encoding depends of the system locale - // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. - // On a windows machine, this field is encoded with the localized windows code page. - var zipComment = this.reader.readData(this.zipCommentLength); - var decodeParamType = support.uint8array ? "uint8array" : "array"; - // To get consistent behavior with the generation part, we will assume that - // this is utf8 encoded unless specified otherwise. - var decodeContent = utils.transformTo(decodeParamType, zipComment); - this.zipComment = this.loadOptions.decodeFileName(decodeContent); - }, - /** - * Read the end of the Zip 64 central directory. - * Not merged with the method readEndOfCentral : - * The end of central can coexist with its Zip64 brother, - * I don't want to read the wrong number of bytes ! - */ - readBlockZip64EndOfCentral: function() { - this.zip64EndOfCentralSize = this.reader.readInt(8); - this.reader.skip(4); - // this.versionMadeBy = this.reader.readString(2); - // this.versionNeeded = this.reader.readInt(2); - this.diskNumber = this.reader.readInt(4); - this.diskWithCentralDirStart = this.reader.readInt(4); - this.centralDirRecordsOnThisDisk = this.reader.readInt(8); - this.centralDirRecords = this.reader.readInt(8); - this.centralDirSize = this.reader.readInt(8); - this.centralDirOffset = this.reader.readInt(8); - - this.zip64ExtensibleData = {}; - var extraDataSize = this.zip64EndOfCentralSize - 44, - index = 0, - extraFieldId, - extraFieldLength, - extraFieldValue; - while (index < extraDataSize) { - extraFieldId = this.reader.readInt(2); - extraFieldLength = this.reader.readInt(4); - extraFieldValue = this.reader.readData(extraFieldLength); - this.zip64ExtensibleData[extraFieldId] = { - id: extraFieldId, - length: extraFieldLength, - value: extraFieldValue - }; - } - }, - /** - * Read the end of the Zip 64 central directory locator. - */ - readBlockZip64EndOfCentralLocator: function() { - this.diskWithZip64CentralDirStart = this.reader.readInt(4); - this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); - this.disksCount = this.reader.readInt(4); - if (this.disksCount > 1) { - throw new Error("Multi-volumes zip are not supported"); - } - }, - /** - * Read the local files, based on the offset read in the central part. - */ - readLocalFiles: function() { - var i, file; - for (i = 0; i < this.files.length; i++) { - file = this.files[i]; - this.reader.setIndex(file.localHeaderOffset); - this.checkSignature(sig.LOCAL_FILE_HEADER); - file.readLocalPart(this.reader); - file.handleUTF8(); - file.processAttributes(); - } - }, - /** - * Read the central directory. - */ - readCentralDir: function() { - var file; - - this.reader.setIndex(this.centralDirOffset); - while (this.reader.readAndCheckSignature(sig.CENTRAL_FILE_HEADER)) { - file = new ZipEntry({ - zip64: this.zip64 - }, this.loadOptions); - file.readCentralPart(this.reader); - this.files.push(file); - } - - if (this.centralDirRecords !== this.files.length) { - if (this.centralDirRecords !== 0 && this.files.length === 0) { - // We expected some records but couldn't find ANY. - // This is really suspicious, as if something went wrong. - throw new Error("Corrupted zip or bug: expected " + this.centralDirRecords + " records in central dir, got " + this.files.length); - } else { - // We found some records but not all. - // Something is wrong but we got something for the user: no error here. - // console.warn("expected", this.centralDirRecords, "records in central dir, got", this.files.length); - } - } - }, - /** - * Read the end of central directory. - */ - readEndOfCentral: function() { - var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); - if (offset < 0) { - // Check if the content is a truncated zip or complete garbage. - // A "LOCAL_FILE_HEADER" is not required at the beginning (auto - // extractible zip for example) but it can give a good hint. - // If an ajax request was used without responseType, we will also - // get unreadable data. - var isGarbage = !this.isSignature(0, sig.LOCAL_FILE_HEADER); - - if (isGarbage) { - throw new Error("Can't find end of central directory : is this a zip file ? " + - "If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"); - } else { - throw new Error("Corrupted zip: can't find end of central directory"); - } - - } - this.reader.setIndex(offset); - var endOfCentralDirOffset = offset; - this.checkSignature(sig.CENTRAL_DIRECTORY_END); - this.readBlockEndOfCentral(); - - - /* extract from the zip spec : - 4) If one of the fields in the end of central directory - record is too small to hold required data, the field - should be set to -1 (0xFFFF or 0xFFFFFFFF) and the - ZIP64 format record should be created. - 5) The end of central directory record and the - Zip64 end of central directory locator record must - reside on the same disk when splitting or spanning - an archive. - */ - if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { - this.zip64 = true; - - /* - Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from - the zip file can fit into a 32bits integer. This cannot be solved : JavaScript represents - all numbers as 64-bit double precision IEEE 754 floating point numbers. - So, we have 53bits for integers and bitwise operations treat everything as 32bits. - see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators - and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 - */ - - // should look for a zip64 EOCD locator - offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); - if (offset < 0) { - throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator"); - } - this.reader.setIndex(offset); - this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); - this.readBlockZip64EndOfCentralLocator(); - - // now the zip64 EOCD record - if (!this.isSignature(this.relativeOffsetEndOfZip64CentralDir, sig.ZIP64_CENTRAL_DIRECTORY_END)) { - // console.warn("ZIP64 end of central directory not where expected."); - this.relativeOffsetEndOfZip64CentralDir = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); - if (this.relativeOffsetEndOfZip64CentralDir < 0) { - throw new Error("Corrupted zip: can't find the ZIP64 end of central directory"); - } - } - this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); - this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); - this.readBlockZip64EndOfCentral(); - } - - var expectedEndOfCentralDirOffset = this.centralDirOffset + this.centralDirSize; - if (this.zip64) { - expectedEndOfCentralDirOffset += 20; // end of central dir 64 locator - expectedEndOfCentralDirOffset += 12 /* should not include the leading 12 bytes */ + this.zip64EndOfCentralSize; - } - - var extraBytes = endOfCentralDirOffset - expectedEndOfCentralDirOffset; - - if (extraBytes > 0) { - // console.warn(extraBytes, "extra bytes at beginning or within zipfile"); - if (this.isSignature(endOfCentralDirOffset, sig.CENTRAL_FILE_HEADER)) { - // The offsets seem wrong, but we have something at the specified offset. - // So… we keep it. - } else { - // the offset is wrong, update the "zero" of the reader - // this happens if data has been prepended (crx files for example) - this.reader.zero = extraBytes; - } - } else if (extraBytes < 0) { - throw new Error("Corrupted zip: missing " + Math.abs(extraBytes) + " bytes."); - } - }, - prepareReader: function(data) { - this.reader = readerFor(data); - }, - /** - * Read a zip file and create ZipEntries. - * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. - */ - load: function(data) { - this.prepareReader(data); - this.readEndOfCentral(); - this.readCentralDir(); - this.readLocalFiles(); - } -}; -// }}} end of ZipEntries -module.exports = ZipEntries; - -},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(require,module,exports){ -'use strict'; -var readerFor = require('./reader/readerFor'); -var utils = require('./utils'); -var CompressedObject = require('./compressedObject'); -var crc32fn = require('./crc32'); -var utf8 = require('./utf8'); -var compressions = require('./compressions'); -var support = require('./support'); - -var MADE_BY_DOS = 0x00; -var MADE_BY_UNIX = 0x03; - -/** - * Find a compression registered in JSZip. - * @param {string} compressionMethod the method magic to find. - * @return {Object|null} the JSZip compression object, null if none found. - */ -var findCompression = function(compressionMethod) { - for (var method in compressions) { - if (!compressions.hasOwnProperty(method)) { - continue; - } - if (compressions[method].magic === compressionMethod) { - return compressions[method]; - } - } - return null; -}; - -// class ZipEntry {{{ -/** - * An entry in the zip file. - * @constructor - * @param {Object} options Options of the current file. - * @param {Object} loadOptions Options for loading the stream. - */ -function ZipEntry(options, loadOptions) { - this.options = options; - this.loadOptions = loadOptions; -} -ZipEntry.prototype = { - /** - * say if the file is encrypted. - * @return {boolean} true if the file is encrypted, false otherwise. - */ - isEncrypted: function() { - // bit 1 is set - return (this.bitFlag & 0x0001) === 0x0001; - }, - /** - * say if the file has utf-8 filename/comment. - * @return {boolean} true if the filename/comment is in utf-8, false otherwise. - */ - useUTF8: function() { - // bit 11 is set - return (this.bitFlag & 0x0800) === 0x0800; - }, - /** - * Read the local part of a zip file and add the info in this object. - * @param {DataReader} reader the reader to use. - */ - readLocalPart: function(reader) { - var compression, localExtraFieldsLength; - - // we already know everything from the central dir ! - // If the central dir data are false, we are doomed. - // On the bright side, the local part is scary : zip64, data descriptors, both, etc. - // The less data we get here, the more reliable this should be. - // Let's skip the whole header and dash to the data ! - reader.skip(22); - // in some zip created on windows, the filename stored in the central dir contains \ instead of /. - // Strangely, the filename here is OK. - // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes - // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... - // Search "unzip mismatching "local" filename continuing with "central" filename version" on - // the internet. - // - // I think I see the logic here : the central directory is used to display - // content and the local directory is used to extract the files. Mixing / and \ - // may be used to display \ to windows users and use / when extracting the files. - // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 - this.fileNameLength = reader.readInt(2); - localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir - // the fileName is stored as binary data, the handleUTF8 method will take care of the encoding. - this.fileName = reader.readData(this.fileNameLength); - reader.skip(localExtraFieldsLength); - - if (this.compressedSize === -1 || this.uncompressedSize === -1) { - throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize === -1 || uncompressedSize === -1)"); - } - - compression = findCompression(this.compressionMethod); - if (compression === null) { // no compression found - throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + utils.transformTo("string", this.fileName) + ")"); - } - this.decompressed = new CompressedObject(this.compressedSize, this.uncompressedSize, this.crc32, compression, reader.readData(this.compressedSize)); - }, - - /** - * Read the central part of a zip file and add the info in this object. - * @param {DataReader} reader the reader to use. - */ - readCentralPart: function(reader) { - this.versionMadeBy = reader.readInt(2); - reader.skip(2); - // this.versionNeeded = reader.readInt(2); - this.bitFlag = reader.readInt(2); - this.compressionMethod = reader.readString(2); - this.date = reader.readDate(); - this.crc32 = reader.readInt(4); - this.compressedSize = reader.readInt(4); - this.uncompressedSize = reader.readInt(4); - var fileNameLength = reader.readInt(2); - this.extraFieldsLength = reader.readInt(2); - this.fileCommentLength = reader.readInt(2); - this.diskNumberStart = reader.readInt(2); - this.internalFileAttributes = reader.readInt(2); - this.externalFileAttributes = reader.readInt(4); - this.localHeaderOffset = reader.readInt(4); - - if (this.isEncrypted()) { - throw new Error("Encrypted zip are not supported"); - } - - // will be read in the local part, see the comments there - reader.skip(fileNameLength); - this.readExtraFields(reader); - this.parseZIP64ExtraField(reader); - this.fileComment = reader.readData(this.fileCommentLength); - }, - - /** - * Parse the external file attributes and get the unix/dos permissions. - */ - processAttributes: function () { - this.unixPermissions = null; - this.dosPermissions = null; - var madeBy = this.versionMadeBy >> 8; - - // Check if we have the DOS directory flag set. - // We look for it in the DOS and UNIX permissions - // but some unknown platform could set it as a compatibility flag. - this.dir = this.externalFileAttributes & 0x0010 ? true : false; - - if(madeBy === MADE_BY_DOS) { - // first 6 bits (0 to 5) - this.dosPermissions = this.externalFileAttributes & 0x3F; - } - - if(madeBy === MADE_BY_UNIX) { - this.unixPermissions = (this.externalFileAttributes >> 16) & 0xFFFF; - // the octal permissions are in (this.unixPermissions & 0x01FF).toString(8); - } - - // fail safe : if the name ends with a / it probably means a folder - if (!this.dir && this.fileNameStr.slice(-1) === '/') { - this.dir = true; - } - }, - - /** - * Parse the ZIP64 extra field and merge the info in the current ZipEntry. - * @param {DataReader} reader the reader to use. - */ - parseZIP64ExtraField: function(reader) { - - if (!this.extraFields[0x0001]) { - return; - } - - // should be something, preparing the extra reader - var extraReader = readerFor(this.extraFields[0x0001].value); - - // I really hope that these 64bits integer can fit in 32 bits integer, because js - // won't let us have more. - if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { - this.uncompressedSize = extraReader.readInt(8); - } - if (this.compressedSize === utils.MAX_VALUE_32BITS) { - this.compressedSize = extraReader.readInt(8); - } - if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { - this.localHeaderOffset = extraReader.readInt(8); - } - if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { - this.diskNumberStart = extraReader.readInt(4); - } - }, - /** - * Read the central part of a zip file and add the info in this object. - * @param {DataReader} reader the reader to use. - */ - readExtraFields: function(reader) { - var end = reader.index + this.extraFieldsLength, - extraFieldId, - extraFieldLength, - extraFieldValue; - - if (!this.extraFields) { - this.extraFields = {}; - } - - while (reader.index < end) { - extraFieldId = reader.readInt(2); - extraFieldLength = reader.readInt(2); - extraFieldValue = reader.readData(extraFieldLength); - - this.extraFields[extraFieldId] = { - id: extraFieldId, - length: extraFieldLength, - value: extraFieldValue - }; - } - }, - /** - * Apply an UTF8 transformation if needed. - */ - handleUTF8: function() { - var decodeParamType = support.uint8array ? "uint8array" : "array"; - if (this.useUTF8()) { - this.fileNameStr = utf8.utf8decode(this.fileName); - this.fileCommentStr = utf8.utf8decode(this.fileComment); - } else { - var upath = this.findExtraFieldUnicodePath(); - if (upath !== null) { - this.fileNameStr = upath; - } else { - // ASCII text or unsupported code page - var fileNameByteArray = utils.transformTo(decodeParamType, this.fileName); - this.fileNameStr = this.loadOptions.decodeFileName(fileNameByteArray); - } - - var ucomment = this.findExtraFieldUnicodeComment(); - if (ucomment !== null) { - this.fileCommentStr = ucomment; - } else { - // ASCII text or unsupported code page - var commentByteArray = utils.transformTo(decodeParamType, this.fileComment); - this.fileCommentStr = this.loadOptions.decodeFileName(commentByteArray); - } - } - }, - - /** - * Find the unicode path declared in the extra field, if any. - * @return {String} the unicode path, null otherwise. - */ - findExtraFieldUnicodePath: function() { - var upathField = this.extraFields[0x7075]; - if (upathField) { - var extraReader = readerFor(upathField.value); - - // wrong version - if (extraReader.readInt(1) !== 1) { - return null; - } - - // the crc of the filename changed, this field is out of date. - if (crc32fn(this.fileName) !== extraReader.readInt(4)) { - return null; - } - - return utf8.utf8decode(extraReader.readData(upathField.length - 5)); - } - return null; - }, - - /** - * Find the unicode comment declared in the extra field, if any. - * @return {String} the unicode comment, null otherwise. - */ - findExtraFieldUnicodeComment: function() { - var ucommentField = this.extraFields[0x6375]; - if (ucommentField) { - var extraReader = readerFor(ucommentField.value); - - // wrong version - if (extraReader.readInt(1) !== 1) { - return null; - } - - // the crc of the comment changed, this field is out of date. - if (crc32fn(this.fileComment) !== extraReader.readInt(4)) { - return null; - } - - return utf8.utf8decode(extraReader.readData(ucommentField.length - 5)); - } - return null; - } -}; -module.exports = ZipEntry; - -},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(require,module,exports){ -'use strict'; - -var StreamHelper = require('./stream/StreamHelper'); -var DataWorker = require('./stream/DataWorker'); -var utf8 = require('./utf8'); -var CompressedObject = require('./compressedObject'); -var GenericWorker = require('./stream/GenericWorker'); - -/** - * A simple object representing a file in the zip file. - * @constructor - * @param {string} name the name of the file - * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data - * @param {Object} options the options of the file - */ -var ZipObject = function(name, data, options) { - this.name = name; - this.dir = options.dir; - this.date = options.date; - this.comment = options.comment; - this.unixPermissions = options.unixPermissions; - this.dosPermissions = options.dosPermissions; - - this._data = data; - this._dataBinary = options.binary; - // keep only the compression - this.options = { - compression : options.compression, - compressionOptions : options.compressionOptions - }; -}; - -ZipObject.prototype = { - /** - * Create an internal stream for the content of this object. - * @param {String} type the type of each chunk. - * @return StreamHelper the stream. - */ - internalStream: function (type) { - var result = null, outputType = "string"; - try { - if (!type) { - throw new Error("No output type specified."); - } - outputType = type.toLowerCase(); - var askUnicodeString = outputType === "string" || outputType === "text"; - if (outputType === "binarystring" || outputType === "text") { - outputType = "string"; - } - result = this._decompressWorker(); - - var isUnicodeString = !this._dataBinary; - - if (isUnicodeString && !askUnicodeString) { - result = result.pipe(new utf8.Utf8EncodeWorker()); - } - if (!isUnicodeString && askUnicodeString) { - result = result.pipe(new utf8.Utf8DecodeWorker()); - } - } catch (e) { - result = new GenericWorker("error"); - result.error(e); - } - - return new StreamHelper(result, outputType, ""); - }, - - /** - * Prepare the content in the asked type. - * @param {String} type the type of the result. - * @param {Function} onUpdate a function to call on each internal update. - * @return Promise the promise of the result. - */ - async: function (type, onUpdate) { - return this.internalStream(type).accumulate(onUpdate); - }, - - /** - * Prepare the content as a nodejs stream. - * @param {String} type the type of each chunk. - * @param {Function} onUpdate a function to call on each internal update. - * @return Stream the stream. - */ - nodeStream: function (type, onUpdate) { - return this.internalStream(type || "nodebuffer").toNodejsStream(onUpdate); - }, - - /** - * Return a worker for the compressed content. - * @private - * @param {Object} compression the compression object to use. - * @param {Object} compressionOptions the options to use when compressing. - * @return Worker the worker. - */ - _compressWorker: function (compression, compressionOptions) { - if ( - this._data instanceof CompressedObject && - this._data.compression.magic === compression.magic - ) { - return this._data.getCompressedWorker(); - } else { - var result = this._decompressWorker(); - if(!this._dataBinary) { - result = result.pipe(new utf8.Utf8EncodeWorker()); - } - return CompressedObject.createWorkerFrom(result, compression, compressionOptions); - } - }, - /** - * Return a worker for the decompressed content. - * @private - * @return Worker the worker. - */ - _decompressWorker : function () { - if (this._data instanceof CompressedObject) { - return this._data.getContentWorker(); - } else if (this._data instanceof GenericWorker) { - return this._data; - } else { - return new DataWorker(this._data); - } - } -}; - -var removedMethods = ["asText", "asBinary", "asNodeBuffer", "asUint8Array", "asArrayBuffer"]; -var removedFn = function () { - throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide."); -}; - -for(var i = 0; i < removedMethods.length; i++) { - ZipObject.prototype[removedMethods[i]] = removedFn; -} -module.exports = ZipObject; - -},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(require,module,exports){ -require('../modules/web.immediate'); -module.exports = require('../modules/_core').setImmediate; -},{"../modules/_core":40,"../modules/web.immediate":56}],37:[function(require,module,exports){ -module.exports = function(it){ - if(typeof it != 'function')throw TypeError(it + ' is not a function!'); - return it; -}; -},{}],38:[function(require,module,exports){ -var isObject = require('./_is-object'); -module.exports = function(it){ - if(!isObject(it))throw TypeError(it + ' is not an object!'); - return it; -}; -},{"./_is-object":51}],39:[function(require,module,exports){ -var toString = {}.toString; - -module.exports = function(it){ - return toString.call(it).slice(8, -1); -}; -},{}],40:[function(require,module,exports){ -var core = module.exports = {version: '2.3.0'}; -if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef -},{}],41:[function(require,module,exports){ -// optional / simple context binding -var aFunction = require('./_a-function'); -module.exports = function(fn, that, length){ - aFunction(fn); - if(that === undefined)return fn; - switch(length){ - case 1: return function(a){ - return fn.call(that, a); - }; - case 2: return function(a, b){ - return fn.call(that, a, b); - }; - case 3: return function(a, b, c){ - return fn.call(that, a, b, c); - }; - } - return function(/* ...args */){ - return fn.apply(that, arguments); - }; -}; -},{"./_a-function":37}],42:[function(require,module,exports){ -// Thank's IE8 for his funny defineProperty -module.exports = !require('./_fails')(function(){ - return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; -}); -},{"./_fails":45}],43:[function(require,module,exports){ -var isObject = require('./_is-object') - , document = require('./_global').document - // in old IE typeof document.createElement is 'object' - , is = isObject(document) && isObject(document.createElement); -module.exports = function(it){ - return is ? document.createElement(it) : {}; -}; -},{"./_global":46,"./_is-object":51}],44:[function(require,module,exports){ -var global = require('./_global') - , core = require('./_core') - , ctx = require('./_ctx') - , hide = require('./_hide') - , PROTOTYPE = 'prototype'; - -var $export = function(type, name, source){ - var IS_FORCED = type & $export.F - , IS_GLOBAL = type & $export.G - , IS_STATIC = type & $export.S - , IS_PROTO = type & $export.P - , IS_BIND = type & $export.B - , IS_WRAP = type & $export.W - , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) - , expProto = exports[PROTOTYPE] - , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] - , key, own, out; - if(IS_GLOBAL)source = name; - for(key in source){ - // contains in native - own = !IS_FORCED && target && target[key] !== undefined; - if(own && key in exports)continue; - // export native or passed - out = own ? target[key] : source[key]; - // prevent global pollution for namespaces - exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] - // bind timers to global for call from export context - : IS_BIND && own ? ctx(out, global) - // wrap global constructors for prevent change them in library - : IS_WRAP && target[key] == out ? (function(C){ - var F = function(a, b, c){ - if(this instanceof C){ - switch(arguments.length){ - case 0: return new C; - case 1: return new C(a); - case 2: return new C(a, b); - } return new C(a, b, c); - } return C.apply(this, arguments); - }; - F[PROTOTYPE] = C[PROTOTYPE]; - return F; - // make static versions for prototype methods - })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; - // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% - if(IS_PROTO){ - (exports.virtual || (exports.virtual = {}))[key] = out; - // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% - if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); - } - } -}; -// type bitmap -$export.F = 1; // forced -$export.G = 2; // global -$export.S = 4; // static -$export.P = 8; // proto -$export.B = 16; // bind -$export.W = 32; // wrap -$export.U = 64; // safe -$export.R = 128; // real proto method for `library` -module.exports = $export; -},{"./_core":40,"./_ctx":41,"./_global":46,"./_hide":47}],45:[function(require,module,exports){ -module.exports = function(exec){ - try { - return !!exec(); - } catch(e){ - return true; - } -}; -},{}],46:[function(require,module,exports){ -// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 -var global = module.exports = typeof window != 'undefined' && window.Math == Math - ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); -if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef -},{}],47:[function(require,module,exports){ -var dP = require('./_object-dp') - , createDesc = require('./_property-desc'); -module.exports = require('./_descriptors') ? function(object, key, value){ - return dP.f(object, key, createDesc(1, value)); -} : function(object, key, value){ - object[key] = value; - return object; -}; -},{"./_descriptors":42,"./_object-dp":52,"./_property-desc":53}],48:[function(require,module,exports){ -module.exports = require('./_global').document && document.documentElement; -},{"./_global":46}],49:[function(require,module,exports){ -module.exports = !require('./_descriptors') && !require('./_fails')(function(){ - return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7; -}); -},{"./_descriptors":42,"./_dom-create":43,"./_fails":45}],50:[function(require,module,exports){ -// fast apply, http://jsperf.lnkit.com/fast-apply/5 -module.exports = function(fn, args, that){ - var un = that === undefined; - switch(args.length){ - case 0: return un ? fn() - : fn.call(that); - case 1: return un ? fn(args[0]) - : fn.call(that, args[0]); - case 2: return un ? fn(args[0], args[1]) - : fn.call(that, args[0], args[1]); - case 3: return un ? fn(args[0], args[1], args[2]) - : fn.call(that, args[0], args[1], args[2]); - case 4: return un ? fn(args[0], args[1], args[2], args[3]) - : fn.call(that, args[0], args[1], args[2], args[3]); - } return fn.apply(that, args); -}; -},{}],51:[function(require,module,exports){ -module.exports = function(it){ - return typeof it === 'object' ? it !== null : typeof it === 'function'; -}; -},{}],52:[function(require,module,exports){ -var anObject = require('./_an-object') - , IE8_DOM_DEFINE = require('./_ie8-dom-define') - , toPrimitive = require('./_to-primitive') - , dP = Object.defineProperty; - -exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes){ - anObject(O); - P = toPrimitive(P, true); - anObject(Attributes); - if(IE8_DOM_DEFINE)try { - return dP(O, P, Attributes); - } catch(e){ /* empty */ } - if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); - if('value' in Attributes)O[P] = Attributes.value; - return O; -}; -},{"./_an-object":38,"./_descriptors":42,"./_ie8-dom-define":49,"./_to-primitive":55}],53:[function(require,module,exports){ -module.exports = function(bitmap, value){ - return { - enumerable : !(bitmap & 1), - configurable: !(bitmap & 2), - writable : !(bitmap & 4), - value : value - }; -}; -},{}],54:[function(require,module,exports){ -var ctx = require('./_ctx') - , invoke = require('./_invoke') - , html = require('./_html') - , cel = require('./_dom-create') - , global = require('./_global') - , process = global.process - , setTask = global.setImmediate - , clearTask = global.clearImmediate - , MessageChannel = global.MessageChannel - , counter = 0 - , queue = {} - , ONREADYSTATECHANGE = 'onreadystatechange' - , defer, channel, port; -var run = function(){ - var id = +this; - if(queue.hasOwnProperty(id)){ - var fn = queue[id]; - delete queue[id]; - fn(); - } -}; -var listener = function(event){ - run.call(event.data); -}; -// Node.js 0.9+ & IE10+ has setImmediate, otherwise: -if(!setTask || !clearTask){ - setTask = function setImmediate(fn){ - var args = [], i = 1; - while(arguments.length > i)args.push(arguments[i++]); - queue[++counter] = function(){ - invoke(typeof fn == 'function' ? fn : Function(fn), args); - }; - defer(counter); - return counter; - }; - clearTask = function clearImmediate(id){ - delete queue[id]; - }; - // Node.js 0.8- - if(require('./_cof')(process) == 'process'){ - defer = function(id){ - process.nextTick(ctx(run, id, 1)); - }; - // Browsers with MessageChannel, includes WebWorkers - } else if(MessageChannel){ - channel = new MessageChannel; - port = channel.port2; - channel.port1.onmessage = listener; - defer = ctx(port.postMessage, port, 1); - // Browsers with postMessage, skip WebWorkers - // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' - } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ - defer = function(id){ - global.postMessage(id + '', '*'); - }; - global.addEventListener('message', listener, false); - // IE8- - } else if(ONREADYSTATECHANGE in cel('script')){ - defer = function(id){ - html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ - html.removeChild(this); - run.call(id); - }; - }; - // Rest old browsers - } else { - defer = function(id){ - setTimeout(ctx(run, id, 1), 0); - }; - } -} -module.exports = { - set: setTask, - clear: clearTask -}; -},{"./_cof":39,"./_ctx":41,"./_dom-create":43,"./_global":46,"./_html":48,"./_invoke":50}],55:[function(require,module,exports){ -// 7.1.1 ToPrimitive(input [, PreferredType]) -var isObject = require('./_is-object'); -// instead of the ES6 spec version, we didn't implement @@toPrimitive case -// and the second argument - flag - preferred type is a string -module.exports = function(it, S){ - if(!isObject(it))return it; - var fn, val; - if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; - if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; - if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; - throw TypeError("Can't convert object to primitive value"); -}; -},{"./_is-object":51}],56:[function(require,module,exports){ -var $export = require('./_export') - , $task = require('./_task'); -$export($export.G + $export.B, { - setImmediate: $task.set, - clearImmediate: $task.clear -}); -},{"./_export":44,"./_task":54}],57:[function(require,module,exports){ -(function (global){ -'use strict'; -var Mutation = global.MutationObserver || global.WebKitMutationObserver; - -var scheduleDrain; - -{ - if (Mutation) { - var called = 0; - var observer = new Mutation(nextTick); - var element = global.document.createTextNode(''); - observer.observe(element, { - characterData: true - }); - scheduleDrain = function () { - element.data = (called = ++called % 2); - }; - } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { - var channel = new global.MessageChannel(); - channel.port1.onmessage = nextTick; - scheduleDrain = function () { - channel.port2.postMessage(0); - }; - } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { - scheduleDrain = function () { - - // Create a - - - - - - - - - - -
- -
- -
-
- -

Class DelegateListModel<E>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • javax.swing.AbstractListModel<E>
    • -
    • -
        -
      • org.unitConverter.converterGUI.DelegateListModel<E>
      • -
      -
    • -
    -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.io.Serializable, java.lang.Iterable<E>, java.util.Collection<E>, java.util.List<E>, javax.swing.ListModel<E>
    -
    -
    -
    final class DelegateListModel<E>
    -extends javax.swing.AbstractListModel<E>
    -implements java.util.List<E>
    -
    A list model that delegates to a list. -

    - It is recommended to use the delegate methods in DelegateListModel instead of the delegated list's methods because - the delegate methods handle updating the list. -

    -
    -
    Since:
    -
    2019-01-14, v0.1.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private java.util.List<E>delegate -
      The list that this model is a delegate to.
      -
      private static longserialVersionUID 
      -
        -
      • - - -

        Fields inherited from class javax.swing.AbstractListModel

        -listenerList
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      DelegateListModel() -
      Creates an empty DelegateListModel.
      -
      DelegateListModel​(java.util.List<E> delegate) -
      Creates the DelegateListModel.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      voidadd​(int index, - E element) 
      booleanadd​(E element) 
      booleanaddAll​(int index, - java.util.Collection<? extends E> c) 
      booleanaddAll​(java.util.Collection<? extends E> c) 
      voidclear() 
      booleancontains​(java.lang.Object elem) 
      booleancontainsAll​(java.util.Collection<?> c) 
      Eget​(int index) 
      EgetElementAt​(int index) 
      intgetSize() 
      intindexOf​(java.lang.Object elem) 
      booleanisEmpty() 
      java.util.Iterator<E>iterator() 
      intlastIndexOf​(java.lang.Object elem) 
      java.util.ListIterator<E>listIterator() 
      java.util.ListIterator<E>listIterator​(int index) 
      Eremove​(int index) 
      booleanremove​(java.lang.Object o) 
      booleanremoveAll​(java.util.Collection<?> c) 
      booleanretainAll​(java.util.Collection<?> c) 
      Eset​(int index, - E element) 
      intsize() 
      java.util.List<E>subList​(int fromIndex, - int toIndex) 
      java.lang.Object[]toArray() 
      <T> T[]toArray​(T[] a) 
      java.lang.StringtoString() 
      -
        -
      • - - -

        Methods inherited from class javax.swing.AbstractListModel

        -addListDataListener, fireContentsChanged, fireIntervalAdded, fireIntervalRemoved, getListDataListeners, getListeners, removeListDataListener
      • -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Collection

        -parallelStream, removeIf, stream, toArray
      • -
      -
        -
      • - - -

        Methods inherited from interface java.lang.Iterable

        -forEach
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.List

        -equals, hashCode, replaceAll, sort, spliterator
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        serialVersionUID

        -
        private static final long serialVersionUID
        -
        -
        Since:
        -
        2019-01-14, v0.1.0
        -
        See Also:
        -
        Constant Field Values
        -
        -
      • -
      - - - -
        -
      • -

        delegate

        -
        private final java.util.List<E> delegate
        -
        The list that this model is a delegate to.
        -
        -
        Since:
        -
        2019-01-14, v0.1.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        DelegateListModel

        -
        public DelegateListModel()
        -
        Creates an empty DelegateListModel.
        -
        -
        Since:
        -
        2019-04-13
        -
        -
      • -
      - - - -
        -
      • -

        DelegateListModel

        -
        public DelegateListModel​(java.util.List<E> delegate)
        -
        Creates the DelegateListModel.
        -
        -
        Parameters:
        -
        delegate - list to delegate
        -
        Since:
        -
        2019-01-14, v0.1.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - - - -
        -
      • -

        add

        -
        public boolean add​(E element)
        -
        -
        Specified by:
        -
        add in interface java.util.Collection<E>
        -
        Specified by:
        -
        add in interface java.util.List<E>
        -
        -
      • -
      - - - - - -
        -
      • -

        add

        -
        public void add​(int index,
        -                E element)
        -
        -
        Specified by:
        -
        add in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        addAll

        -
        public boolean addAll​(java.util.Collection<? extends E> c)
        -
        -
        Specified by:
        -
        addAll in interface java.util.Collection<E>
        -
        Specified by:
        -
        addAll in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        addAll

        -
        public boolean addAll​(int index,
        -                      java.util.Collection<? extends E> c)
        -
        -
        Specified by:
        -
        addAll in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        clear

        -
        public void clear()
        -
        -
        Specified by:
        -
        clear in interface java.util.Collection<E>
        -
        Specified by:
        -
        clear in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        contains

        -
        public boolean contains​(java.lang.Object elem)
        -
        -
        Specified by:
        -
        contains in interface java.util.Collection<E>
        -
        Specified by:
        -
        contains in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        containsAll

        -
        public boolean containsAll​(java.util.Collection<?> c)
        -
        -
        Specified by:
        -
        containsAll in interface java.util.Collection<E>
        -
        Specified by:
        -
        containsAll in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        get

        -
        public E get​(int index)
        -
        -
        Specified by:
        -
        get in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        getElementAt

        -
        public E getElementAt​(int index)
        -
        -
        Specified by:
        -
        getElementAt in interface javax.swing.ListModel<E>
        -
        -
      • -
      - - - -
        -
      • -

        getSize

        -
        public int getSize()
        -
        -
        Specified by:
        -
        getSize in interface javax.swing.ListModel<E>
        -
        -
      • -
      - - - -
        -
      • -

        indexOf

        -
        public int indexOf​(java.lang.Object elem)
        -
        -
        Specified by:
        -
        indexOf in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        isEmpty

        -
        public boolean isEmpty()
        -
        -
        Specified by:
        -
        isEmpty in interface java.util.Collection<E>
        -
        Specified by:
        -
        isEmpty in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        iterator

        -
        public java.util.Iterator<E> iterator()
        -
        -
        Specified by:
        -
        iterator in interface java.util.Collection<E>
        -
        Specified by:
        -
        iterator in interface java.lang.Iterable<E>
        -
        Specified by:
        -
        iterator in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        lastIndexOf

        -
        public int lastIndexOf​(java.lang.Object elem)
        -
        -
        Specified by:
        -
        lastIndexOf in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        listIterator

        -
        public java.util.ListIterator<E> listIterator()
        -
        -
        Specified by:
        -
        listIterator in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        listIterator

        -
        public java.util.ListIterator<E> listIterator​(int index)
        -
        -
        Specified by:
        -
        listIterator in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        remove

        -
        public E remove​(int index)
        -
        -
        Specified by:
        -
        remove in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        remove

        -
        public boolean remove​(java.lang.Object o)
        -
        -
        Specified by:
        -
        remove in interface java.util.Collection<E>
        -
        Specified by:
        -
        remove in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        removeAll

        -
        public boolean removeAll​(java.util.Collection<?> c)
        -
        -
        Specified by:
        -
        removeAll in interface java.util.Collection<E>
        -
        Specified by:
        -
        removeAll in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        retainAll

        -
        public boolean retainAll​(java.util.Collection<?> c)
        -
        -
        Specified by:
        -
        retainAll in interface java.util.Collection<E>
        -
        Specified by:
        -
        retainAll in interface java.util.List<E>
        -
        -
      • -
      - - - - - -
        -
      • -

        set

        -
        public E set​(int index,
        -             E element)
        -
        -
        Specified by:
        -
        set in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        size

        -
        public int size()
        -
        -
        Specified by:
        -
        size in interface java.util.Collection<E>
        -
        Specified by:
        -
        size in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        subList

        -
        public java.util.List<E> subList​(int fromIndex,
        -                                 int toIndex)
        -
        -
        Specified by:
        -
        subList in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        toArray

        -
        public java.lang.Object[] toArray()
        -
        -
        Specified by:
        -
        toArray in interface java.util.Collection<E>
        -
        Specified by:
        -
        toArray in interface java.util.List<E>
        -
        -
      • -
      - - - - - -
        -
      • -

        toArray

        -
        public <T> T[] toArray​(T[] a)
        -
        -
        Specified by:
        -
        toArray in interface java.util.Collection<E>
        -
        Specified by:
        -
        toArray in interface java.util.List<E>
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        -
        Overrides:
        -
        toString in class java.lang.Object
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/converterGUI/FilterComparator.html b/doc/org/unitConverter/converterGUI/FilterComparator.html deleted file mode 100644 index af91555..0000000 --- a/doc/org/unitConverter/converterGUI/FilterComparator.html +++ /dev/null @@ -1,489 +0,0 @@ - - - - - -FilterComparator - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class FilterComparator

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.converterGUI.FilterComparator
    • -
    -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.util.Comparator<java.lang.String>
    -
    -
    -
    final class FilterComparator
    -extends java.lang.Object
    -implements java.util.Comparator<java.lang.String>
    -
    A comparator that compares strings using a filter.
    -
    -
    Since:
    -
    2019-01-15, v0.1.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private booleancaseSensitive -
      Whether or not the comparison is case-sensitive.
      -
      private java.util.Comparator<java.lang.String>comparator -
      The comparator to use if the arguments are otherwise equal.
      -
      private java.lang.Stringfilter -
      The filter that the comparator is filtered by.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      FilterComparator​(java.lang.String filter) -
      Creates the FilterComparator.
      -
      FilterComparator​(java.lang.String filter, - java.util.Comparator<java.lang.String> comparator) -
      Creates the FilterComparator.
      -
      FilterComparator​(java.lang.String filter, - java.util.Comparator<java.lang.String> comparator, - boolean caseSensitive) -
      Creates the FilterComparator.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      intcompare​(java.lang.String arg0, - java.lang.String arg1) 
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Comparator

        -equals, reversed, thenComparing, thenComparing, thenComparing, thenComparingDouble, thenComparingInt, thenComparingLong
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        filter

        -
        private final java.lang.String filter
        -
        The filter that the comparator is filtered by.
        -
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        comparator

        -
        private final java.util.Comparator<java.lang.String> comparator
        -
        The comparator to use if the arguments are otherwise equal.
        -
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        caseSensitive

        -
        private final boolean caseSensitive
        -
        Whether or not the comparison is case-sensitive.
        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        FilterComparator

        -
        public FilterComparator​(java.lang.String filter)
        -
        Creates the FilterComparator.
        -
        -
        Parameters:
        -
        filter -
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        FilterComparator

        -
        public FilterComparator​(java.lang.String filter,
        -                        java.util.Comparator<java.lang.String> comparator)
        -
        Creates the FilterComparator.
        -
        -
        Parameters:
        -
        filter - string to filter by
        -
        comparator - comparator to fall back to if all else fails, null is compareTo.
        -
        Throws:
        -
        java.lang.NullPointerException - if filter is null
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        FilterComparator

        -
        public FilterComparator​(java.lang.String filter,
        -                        java.util.Comparator<java.lang.String> comparator,
        -                        boolean caseSensitive)
        -
        Creates the FilterComparator.
        -
        -
        Parameters:
        -
        filter - string to filter by
        -
        comparator - comparator to fall back to if all else fails, null is compareTo.
        -
        caseSensitive - whether or not the comparator is case-sensitive
        -
        Throws:
        -
        java.lang.NullPointerException - if filter is null
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        compare

        -
        public int compare​(java.lang.String arg0,
        -                   java.lang.String arg1)
        -
        -
        Specified by:
        -
        compare in interface java.util.Comparator<java.lang.String>
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/converterGUI/GridBagBuilder.html b/doc/org/unitConverter/converterGUI/GridBagBuilder.html deleted file mode 100644 index c8e80d2..0000000 --- a/doc/org/unitConverter/converterGUI/GridBagBuilder.html +++ /dev/null @@ -1,1140 +0,0 @@ - - - - - -GridBagBuilder - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class GridBagBuilder

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.converterGUI.GridBagBuilder
    • -
    -
  • -
-
-
    -
  • -
    -
    final class GridBagBuilder
    -extends java.lang.Object
    -
    A builder for Java's GridBagConstraints class.
    -
    -
    Since:
    -
    2018-11-30, v0.1.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private intanchor -
      The built GridBagConstraints's anchor property.
      -
      private intfill -
      The built GridBagConstraints's fill property.
      -
      private intgridheight -
      The built GridBagConstraints's gridheight property.
      -
      private intgridwidth -
      The built GridBagConstraints's gridwidth property.
      -
      private intgridx -
      The built GridBagConstraints's gridx property.
      -
      private intgridy -
      The built GridBagConstraints's gridy property.
      -
      private java.awt.Insetsinsets -
      The built GridBagConstraints's insets property.
      -
      private intipadx -
      The built GridBagConstraints's ipadx property.
      -
      private intipady -
      The built GridBagConstraints's ipady property.
      -
      private doubleweightx -
      The built GridBagConstraints's weightx property.
      -
      private doubleweighty -
      The built GridBagConstraints's weighty property.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - - - - - - - - - - - - - -
      Constructors 
      ModifierConstructorDescription
       GridBagBuilder​(int gridx, - int gridy) 
       GridBagBuilder​(int gridx, - int gridy, - int gridwidth, - int gridheight) 
      private GridBagBuilder​(int gridx, - int gridy, - int gridwidth, - int gridheight, - double weightx, - double weighty, - int anchor, - int fill, - java.awt.Insets insets, - int ipadx, - int ipady) 
      -
    • -
    -
    - -
    - -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        gridx

        -
        private final int gridx
        -
        The built GridBagConstraints's gridx property. -

        - Specifies the cell containing the leading edge of the component's display area, where the first cell in a row has - gridx=0. The leading edge of a component's display area is its left edge for a horizontal, - left-to-right container and its right edge for a horizontal, right-to-left container. The value - RELATIVE specifies that the component be placed immediately following the component that was added - to the container just before this component was added. -

        - The default value is RELATIVE. gridx should be a non-negative value.

        -
        -
        See Also:
        -
        Object.clone(), -GridBagConstraints.gridy, -ComponentOrientation
        -
        -
      • -
      - - - -
        -
      • -

        gridy

        -
        private final int gridy
        -
        The built GridBagConstraints's gridy property. -

        - Specifies the cell at the top of the component's display area, where the topmost cell has gridy=0. - The value RELATIVE specifies that the component be placed just below the component that was added to - the container just before this component was added. -

        - The default value is RELATIVE. gridy should be a non-negative value.

        -
        -
        See Also:
        -
        Object.clone(), -GridBagConstraints.gridx
        -
        -
      • -
      - - - -
        -
      • -

        gridwidth

        -
        private final int gridwidth
        -
        The built GridBagConstraints's gridwidth property. -

        - Specifies the number of cells in a row for the component's display area. -

        - Use REMAINDER to specify that the component's display area will be from gridx to the - last cell in the row. Use RELATIVE to specify that the component's display area will be from - gridx to the next to the last one in its row. -

        - gridwidth should be non-negative and the default value is 1.

        -
        -
        See Also:
        -
        Object.clone(), -GridBagConstraints.gridheight
        -
        -
      • -
      - - - -
        -
      • -

        gridheight

        -
        private final int gridheight
        -
        The built GridBagConstraints's gridheight property. -

        - Specifies the number of cells in a column for the component's display area. -

        - Use REMAINDER to specify that the component's display area will be from gridy to the - last cell in the column. Use RELATIVE to specify that the component's display area will be from - gridy to the next to the last one in its column. -

        - gridheight should be a non-negative value and the default value is 1.

        -
        -
        See Also:
        -
        Object.clone(), -GridBagConstraints.gridwidth
        -
        -
      • -
      - - - -
        -
      • -

        weightx

        -
        private double weightx
        -
        The built GridBagConstraints's weightx property. -

        - Specifies how to distribute extra horizontal space. -

        - The grid bag layout manager calculates the weight of a column to be the maximum weightx of all the - components in a column. If the resulting layout is smaller horizontally than the area it needs to fill, the extra - space is distributed to each column in proportion to its weight. A column that has a weight of zero receives no - extra space. -

        - If all the weights are zero, all the extra space appears between the grids of the cell and the left and right - edges. -

        - The default value of this field is 0. weightx should be a non-negative value.

        -
        -
        See Also:
        -
        Object.clone(), -GridBagConstraints.weighty
        -
        -
      • -
      - - - -
        -
      • -

        weighty

        -
        private double weighty
        -
        The built GridBagConstraints's weighty property. -

        - Specifies how to distribute extra vertical space. -

        - The grid bag layout manager calculates the weight of a row to be the maximum weighty of all the - components in a row. If the resulting layout is smaller vertically than the area it needs to fill, the extra - space is distributed to each row in proportion to its weight. A row that has a weight of zero receives no extra - space. -

        - If all the weights are zero, all the extra space appears between the grids of the cell and the top and bottom - edges. -

        - The default value of this field is 0. weighty should be a non-negative value.

        -
        -
        See Also:
        -
        Object.clone(), -GridBagConstraints.weightx
        -
        -
      • -
      - - - -
        -
      • -

        anchor

        -
        private int anchor
        -
        The built GridBagConstraints's anchor property. -

        - This field is used when the component is smaller than its display area. It determines where, within the display - area, to place the component. -

        - There are three kinds of possible values: orientation relative, baseline relative and absolute. Orientation - relative values are interpreted relative to the container's component orientation property, baseline relative - values are interpreted relative to the baseline and absolute values are not. The absolute values are: - CENTER, NORTH, NORTHEAST, EAST, SOUTHEAST, - SOUTH, SOUTHWEST, WEST, and NORTHWEST. The orientation - relative values are: PAGE_START, PAGE_END, LINE_START, - LINE_END, FIRST_LINE_START, FIRST_LINE_END, LAST_LINE_START - and LAST_LINE_END. The baseline relative values are: BASELINE, - BASELINE_LEADING, BASELINE_TRAILING, ABOVE_BASELINE, - ABOVE_BASELINE_LEADING, ABOVE_BASELINE_TRAILING, BELOW_BASELINE, - BELOW_BASELINE_LEADING, and BELOW_BASELINE_TRAILING. The default value is - CENTER.

        -
        -
        See Also:
        -
        Object.clone(), -ComponentOrientation
        -
        -
      • -
      - - - -
        -
      • -

        fill

        -
        private int fill
        -
        The built GridBagConstraints's fill property. -

        - This field is used when the component's display area is larger than the component's requested size. It determines - whether to resize the component, and if so, how. -

        - The following values are valid for fill: - -

          -
        • NONE: Do not resize the component. -
        • HORIZONTAL: Make the component wide enough to fill its display area horizontally, but do not - change its height. -
        • VERTICAL: Make the component tall enough to fill its display area vertically, but do not change - its width. -
        • BOTH: Make the component fill its display area entirely. -
        -

        - The default value is NONE.

        -
        -
        See Also:
        -
        Object.clone()
        -
        -
      • -
      - - - -
        -
      • -

        insets

        -
        private java.awt.Insets insets
        -
        The built GridBagConstraints's insets property. -

        - This field specifies the external padding of the component, the minimum amount of space between the component and - the edges of its display area. -

        - The default value is new Insets(0, 0, 0, 0).

        -
        -
        See Also:
        -
        Object.clone()
        -
        -
      • -
      - - - -
        -
      • -

        ipadx

        -
        private int ipadx
        -
        The built GridBagConstraints's ipadx property. -

        - This field specifies the internal padding of the component, how much space to add to the minimum width of the - component. The width of the component is at least its minimum width plus ipadx pixels. -

        - The default value is 0.

        -
        -
        See Also:
        -
        Object.clone(), -GridBagConstraints.ipady
        -
        -
      • -
      - - - -
        -
      • -

        ipady

        -
        private int ipady
        -
        The built GridBagConstraints's ipady property. -

        - This field specifies the internal padding, that is, how much space to add to the minimum height of the component. - The height of the component is at least its minimum height plus ipady pixels. -

        - The default value is 0.

        -
        -
        See Also:
        -
        Object.clone(), -GridBagConstraints.ipadx
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        GridBagBuilder

        -
        public GridBagBuilder​(int gridx,
        -                      int gridy)
        -
        -
        Parameters:
        -
        gridx - x position
        -
        gridy - y position
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        GridBagBuilder

        -
        public GridBagBuilder​(int gridx,
        -                      int gridy,
        -                      int gridwidth,
        -                      int gridheight)
        -
        -
        Parameters:
        -
        gridx - x position
        -
        gridy - y position
        -
        gridwidth - number of cells occupied horizontally
        -
        gridheight - number of cells occupied vertically
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        GridBagBuilder

        -
        private GridBagBuilder​(int gridx,
        -                       int gridy,
        -                       int gridwidth,
        -                       int gridheight,
        -                       double weightx,
        -                       double weighty,
        -                       int anchor,
        -                       int fill,
        -                       java.awt.Insets insets,
        -                       int ipadx,
        -                       int ipady)
        -
        -
        Parameters:
        -
        gridx - x position
        -
        gridy - y position
        -
        gridwidth - number of cells occupied horizontally
        -
        gridheight - number of cells occupied vertically
        -
        weightx -
        -
        weighty -
        -
        anchor -
        -
        fill -
        -
        insets -
        -
        ipadx -
        -
        ipady -
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        build

        -
        public java.awt.GridBagConstraints build()
        -
        -
        Returns:
        -
        GridBagConstraints created by this builder
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getAnchor

        -
        public int getAnchor()
        -
        -
        Returns:
        -
        anchor
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getFill

        -
        public int getFill()
        -
        -
        Returns:
        -
        fill
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getGridheight

        -
        public int getGridheight()
        -
        -
        Returns:
        -
        gridheight
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getGridwidth

        -
        public int getGridwidth()
        -
        -
        Returns:
        -
        gridwidth
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getGridx

        -
        public int getGridx()
        -
        -
        Returns:
        -
        gridx
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getGridy

        -
        public int getGridy()
        -
        -
        Returns:
        -
        gridy
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getInsets

        -
        public java.awt.Insets getInsets()
        -
        -
        Returns:
        -
        insets
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getIpadx

        -
        public int getIpadx()
        -
        -
        Returns:
        -
        ipadx
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getIpady

        -
        public int getIpady()
        -
        -
        Returns:
        -
        ipady
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getWeightx

        -
        public double getWeightx()
        -
        -
        Returns:
        -
        weightx
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getWeighty

        -
        public double getWeighty()
        -
        -
        Returns:
        -
        weighty
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setAnchor

        -
        public GridBagBuilder setAnchor​(int anchor)
        -
        -
        Parameters:
        -
        anchor - anchor to set
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setFill

        -
        public GridBagBuilder setFill​(int fill)
        -
        -
        Parameters:
        -
        fill - fill to set
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setInsets

        -
        public GridBagBuilder setInsets​(java.awt.Insets insets)
        -
        -
        Parameters:
        -
        insets - insets to set
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setIpadx

        -
        public GridBagBuilder setIpadx​(int ipadx)
        -
        -
        Parameters:
        -
        ipadx - ipadx to set
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setIpady

        -
        public GridBagBuilder setIpady​(int ipady)
        -
        -
        Parameters:
        -
        ipady - ipady to set
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setWeightx

        -
        public GridBagBuilder setWeightx​(double weightx)
        -
        -
        Parameters:
        -
        weightx - weightx to set
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setWeighty

        -
        public GridBagBuilder setWeighty​(double weighty)
        -
        -
        Parameters:
        -
        weighty - weighty to set
        -
        Since:
        -
        2018-11-30, v0.1.0
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/converterGUI/MutablePredicate.html b/doc/org/unitConverter/converterGUI/MutablePredicate.html deleted file mode 100644 index d7af17c..0000000 --- a/doc/org/unitConverter/converterGUI/MutablePredicate.html +++ /dev/null @@ -1,428 +0,0 @@ - - - - - -MutablePredicate - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class MutablePredicate<T>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.converterGUI.MutablePredicate<T>
    • -
    -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.util.function.Predicate<T>
    -
    -
    -
    final class MutablePredicate<T>
    -extends java.lang.Object
    -implements java.util.function.Predicate<T>
    -
    A container for a predicate, which can be changed later.
    -
    -
    Since:
    -
    2019-04-13, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private java.util.function.Predicate<T>predicate -
      The predicate stored in this MutablePredicate
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      MutablePredicate​(java.util.function.Predicate<T> predicate) -
      Creates the MutablePredicate.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      java.util.function.Predicate<T>getPredicate() 
      voidsetPredicate​(java.util.function.Predicate<T> predicate) 
      booleantest​(T t) 
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.function.Predicate

        -and, negate, or
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        predicate

        -
        private java.util.function.Predicate<T> predicate
        -
        The predicate stored in this MutablePredicate
        -
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        MutablePredicate

        -
        public MutablePredicate​(java.util.function.Predicate<T> predicate)
        -
        Creates the MutablePredicate.
        -
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        getPredicate

        -
        public final java.util.function.Predicate<T> getPredicate()
        -
        -
        Returns:
        -
        predicate
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        setPredicate

        -
        public final void setPredicate​(java.util.function.Predicate<T> predicate)
        -
        -
        Parameters:
        -
        predicate - new value of predicate
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - - - -
        -
      • -

        test

        -
        public boolean test​(T t)
        -
        -
        Specified by:
        -
        test in interface java.util.function.Predicate<T>
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/converterGUI/SearchBoxList.html b/doc/org/unitConverter/converterGUI/SearchBoxList.html deleted file mode 100644 index 1831fbd..0000000 --- a/doc/org/unitConverter/converterGUI/SearchBoxList.html +++ /dev/null @@ -1,902 +0,0 @@ - - - - - -SearchBoxList - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class SearchBoxList

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • java.awt.Component
    • -
    • -
        -
      • java.awt.Container
      • -
      • -
          -
        • javax.swing.JComponent
        • -
        • -
            -
          • javax.swing.JPanel
          • -
          • -
              -
            • org.unitConverter.converterGUI.SearchBoxList
            • -
            -
          • -
          -
        • -
        -
      • -
      -
    • -
    -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.awt.image.ImageObserver, java.awt.MenuContainer, java.io.Serializable, javax.accessibility.Accessible
    -
    -
    -
    final class SearchBoxList
    -extends javax.swing.JPanel
    -
    -
    Since:
    -
    2019-04-13, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Nested Class Summary

      -
        -
      • - - -

        Nested classes/interfaces inherited from class javax.swing.JPanel

        -javax.swing.JPanel.AccessibleJPanel
      • -
      -
        -
      • - - -

        Nested classes/interfaces inherited from class javax.swing.JComponent

        -javax.swing.JComponent.AccessibleJComponent
      • -
      -
        -
      • - - -

        Nested classes/interfaces inherited from class java.awt.Container

        -java.awt.Container.AccessibleAWTContainer
      • -
      -
        -
      • - - -

        Nested classes/interfaces inherited from class java.awt.Component

        -java.awt.Component.AccessibleAWTComponent, java.awt.Component.BaselineResizeBehavior, java.awt.Component.BltBufferStrategy, java.awt.Component.FlipBufferStrategy
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private booleancaseSensitive 
      private java.util.function.Predicate<java.lang.String>customSearchFilter 
      private java.util.Comparator<java.lang.String>defaultOrdering 
      private static java.awt.ColorEMPTY_FOREGROUND -
      The color to use for an empty foreground.
      -
      private static java.lang.StringEMPTY_TEXT -
      The text to place in an empty search box.
      -
      private java.util.Collection<java.lang.String>itemsToFilter 
      private DelegateListModel<java.lang.String>listModel 
      private javax.swing.JTextFieldsearchBox 
      private booleansearchBoxEmpty 
      private booleansearchBoxFocused 
      private javax.swing.JList<java.lang.String>searchItems 
      private static longserialVersionUID 
      -
        -
      • - - -

        Fields inherited from class javax.swing.JComponent

        -listenerList, TOOL_TIP_TEXT_KEY, ui, UNDEFINED_CONDITION, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, WHEN_FOCUSED, WHEN_IN_FOCUSED_WINDOW
      • -
      -
        -
      • - - -

        Fields inherited from class java.awt.Component

        -accessibleContext, BOTTOM_ALIGNMENT, CENTER_ALIGNMENT, LEFT_ALIGNMENT, RIGHT_ALIGNMENT, TOP_ALIGNMENT
      • -
      -
        -
      • - - -

        Fields inherited from interface java.awt.image.ImageObserver

        -ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, WIDTH
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      SearchBoxList​(java.util.Collection<java.lang.String> itemsToFilter) -
      Creates the SearchBoxList.
      -
      SearchBoxList​(java.util.Collection<java.lang.String> itemsToFilter, - java.util.Comparator<java.lang.String> defaultOrdering, - boolean caseSensitive) -
      Creates the SearchBoxList.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      voidaddSearchFilter​(java.util.function.Predicate<java.lang.String> filter) -
      Adds an additional filter for searching.
      -
      voidclearSearchFilters() -
      Resets the search filter.
      -
      javax.swing.JTextFieldgetSearchBox() 
      private java.util.function.Predicate<java.lang.String>getSearchFilter​(java.lang.String searchText) 
      javax.swing.JList<java.lang.String>getSearchList() 
      intgetSelectedIndex() 
      java.lang.StringgetSelectedValue() 
      voidreapplyFilter() -
      Re-applies the filters.
      -
      private voidsearchBoxFocusGained​(java.awt.event.FocusEvent e) -
      Runs whenever the search box gains focus.
      -
      private voidsearchBoxFocusLost​(java.awt.event.FocusEvent e) -
      Runs whenever the search box loses focus.
      -
      private voidsearchBoxTextChanged() -
      Runs whenever the text in the search box is changed.
      -
      -
        -
      • - - -

        Methods inherited from class javax.swing.JPanel

        -getAccessibleContext, getUI, getUIClassID, paramString, setUI, updateUI
      • -
      -
        -
      • - - -

        Methods inherited from class javax.swing.JComponent

        -addAncestorListener, addNotify, addVetoableChangeListener, computeVisibleRect, contains, createToolTip, disable, enable, firePropertyChange, firePropertyChange, firePropertyChange, fireVetoableChange, getActionForKeyStroke, getActionMap, getAlignmentX, getAlignmentY, getAncestorListeners, getAutoscrolls, getBaseline, getBaselineResizeBehavior, getBorder, getBounds, getClientProperty, getComponentGraphics, getComponentPopupMenu, getConditionForKeyStroke, getDebugGraphicsOptions, getDefaultLocale, getFontMetrics, getGraphics, getHeight, getInheritsPopupMenu, getInputMap, getInputMap, getInputVerifier, getInsets, getInsets, getListeners, getLocation, getMaximumSize, getMinimumSize, getNextFocusableComponent, getPopupLocation, getPreferredSize, getRegisteredKeyStrokes, getRootPane, getSize, getToolTipLocation, getToolTipText, getToolTipText, getTopLevelAncestor, getTransferHandler, getVerifyInputWhenFocusTarget, getVetoableChangeListeners, getVisibleRect, getWidth, getX, getY, grabFocus, hide, isDoubleBuffered, isLightweightComponent, isManagingFocus, isOpaque, isOptimizedDrawingEnabled, isPaintingForPrint, isPaintingOrigin, isPaintingTile, isRequestFocusEnabled, isValidateRoot, paint, paintBorder, paintChildren, paintComponent, paintImmediately, paintImmediately, print, printAll, printBorder, printChildren, printComponent, processComponentKeyEvent, processKeyBinding, processKeyEvent, processMouseEvent, processMouseMotionEvent, putClientProperty, registerKeyboardAction, registerKeyboardAction, removeAncestorListener, removeNotify, removeVetoableChangeListener, repaint, repaint, requestDefaultFocus, requestFocus, requestFocus, requestFocusInWindow, requestFocusInWindow, resetKeyboardActions, reshape, revalidate, scrollRectToVisible, setActionMap, setAlignmentX, setAlignmentY, setAutoscrolls, setBackground, setBorder, setComponentPopupMenu, setDebugGraphicsOptions, setDefaultLocale, setDoubleBuffered, setEnabled, setFocusTraversalKeys, setFont, setForeground, setInheritsPopupMenu, setInputMap, setInputVerifier, setMaximumSize, setMinimumSize, setNextFocusableComponent, setOpaque, setPreferredSize, setRequestFocusEnabled, setToolTipText, setTransferHandler, setUI, setVerifyInputWhenFocusTarget, setVisible, unregisterKeyboardAction, update
      • -
      -
        -
      • - - -

        Methods inherited from class java.awt.Container

        -add, add, add, add, add, addContainerListener, addImpl, addPropertyChangeListener, addPropertyChangeListener, applyComponentOrientation, areFocusTraversalKeysSet, countComponents, deliverEvent, doLayout, findComponentAt, findComponentAt, getComponent, getComponentAt, getComponentAt, getComponentCount, getComponents, getComponentZOrder, getContainerListeners, getFocusTraversalKeys, getFocusTraversalPolicy, getLayout, getMousePosition, insets, invalidate, isAncestorOf, isFocusCycleRoot, isFocusCycleRoot, isFocusTraversalPolicyProvider, isFocusTraversalPolicySet, layout, list, list, locate, minimumSize, paintComponents, preferredSize, printComponents, processContainerEvent, processEvent, remove, remove, removeAll, removeContainerListener, setComponentZOrder, setFocusCycleRoot, setFocusTraversalPolicy, setFocusTraversalPolicyProvider, setLayout, transferFocusDownCycle, validate, validateTree
      • -
      -
        -
      • - - -

        Methods inherited from class java.awt.Component

        -action, add, addComponentListener, addFocusListener, addHierarchyBoundsListener, addHierarchyListener, addInputMethodListener, addKeyListener, addMouseListener, addMouseMotionListener, addMouseWheelListener, bounds, checkImage, checkImage, coalesceEvents, contains, createImage, createImage, createVolatileImage, createVolatileImage, disableEvents, dispatchEvent, enable, enableEvents, enableInputMethods, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, getBackground, getBounds, getColorModel, getComponentListeners, getComponentOrientation, getCursor, getDropTarget, getFocusCycleRootAncestor, getFocusListeners, getFocusTraversalKeysEnabled, getFont, getForeground, getGraphicsConfiguration, getHierarchyBoundsListeners, getHierarchyListeners, getIgnoreRepaint, getInputContext, getInputMethodListeners, getInputMethodRequests, getKeyListeners, getLocale, getLocation, getLocationOnScreen, getMouseListeners, getMouseMotionListeners, getMousePosition, getMouseWheelListeners, getName, getParent, getPropertyChangeListeners, getPropertyChangeListeners, getSize, getToolkit, getTreeLock, gotFocus, handleEvent, hasFocus, imageUpdate, inside, isBackgroundSet, isCursorSet, isDisplayable, isEnabled, isFocusable, isFocusOwner, isFocusTraversable, isFontSet, isForegroundSet, isLightweight, isMaximumSizeSet, isMinimumSizeSet, isPreferredSizeSet, isShowing, isValid, isVisible, keyDown, keyUp, list, list, list, location, lostFocus, mouseDown, mouseDrag, mouseEnter, mouseExit, mouseMove, mouseUp, move, nextFocus, paintAll, postEvent, prepareImage, prepareImage, processComponentEvent, processFocusEvent, processHierarchyBoundsEvent, processHierarchyEvent, processInputMethodEvent, processMouseWheelEvent, remove, removeComponentListener, removeFocusListener, removeHierarchyBoundsListener, removeHierarchyListener, removeInputMethodListener, removeKeyListener, removeMouseListener, removeMouseMotionListener, removeMouseWheelListener, removePropertyChangeListener, removePropertyChangeListener, repaint, repaint, repaint, requestFocus, requestFocus, requestFocusInWindow, resize, resize, setBounds, setBounds, setComponentOrientation, setCursor, setDropTarget, setFocusable, setFocusTraversalKeysEnabled, setIgnoreRepaint, setLocale, setLocation, setLocation, setMixingCutoutShape, setName, setSize, setSize, show, show, size, toString, transferFocus, transferFocusBackward, transferFocusUpCycle
      • -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        serialVersionUID

        -
        private static final long serialVersionUID
        -
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        See Also:
        -
        Constant Field Values
        -
        -
      • -
      - - - -
        -
      • -

        EMPTY_TEXT

        -
        private static final java.lang.String EMPTY_TEXT
        -
        The text to place in an empty search box.
        -
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        See Also:
        -
        Constant Field Values
        -
        -
      • -
      - - - -
        -
      • -

        EMPTY_FOREGROUND

        -
        private static final java.awt.Color EMPTY_FOREGROUND
        -
        The color to use for an empty foreground.
        -
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        itemsToFilter

        -
        private final java.util.Collection<java.lang.String> itemsToFilter
        -
      • -
      - - - - - - - -
        -
      • -

        searchBox

        -
        private final javax.swing.JTextField searchBox
        -
      • -
      - - - -
        -
      • -

        searchItems

        -
        private final javax.swing.JList<java.lang.String> searchItems
        -
      • -
      - - - -
        -
      • -

        searchBoxEmpty

        -
        private boolean searchBoxEmpty
        -
      • -
      - - - -
        -
      • -

        searchBoxFocused

        -
        private boolean searchBoxFocused
        -
      • -
      - - - -
        -
      • -

        customSearchFilter

        -
        private java.util.function.Predicate<java.lang.String> customSearchFilter
        -
      • -
      - - - -
        -
      • -

        defaultOrdering

        -
        private final java.util.Comparator<java.lang.String> defaultOrdering
        -
      • -
      - - - -
        -
      • -

        caseSensitive

        -
        private final boolean caseSensitive
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        SearchBoxList

        -
        public SearchBoxList​(java.util.Collection<java.lang.String> itemsToFilter)
        -
        Creates the SearchBoxList.
        -
        -
        Parameters:
        -
        itemsToFilter - items to put in the list
        -
        Since:
        -
        2019-04-14
        -
        -
      • -
      - - - -
        -
      • -

        SearchBoxList

        -
        public SearchBoxList​(java.util.Collection<java.lang.String> itemsToFilter,
        -                     java.util.Comparator<java.lang.String> defaultOrdering,
        -                     boolean caseSensitive)
        -
        Creates the SearchBoxList.
        -
        -
        Parameters:
        -
        itemsToFilter - items to put in the list
        -
        defaultOrdering - default ordering of items after filtration (null=Comparable)
        -
        caseSensitive - whether or not the filtration is case-sensitive
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        addSearchFilter

        -
        public void addSearchFilter​(java.util.function.Predicate<java.lang.String> filter)
        -
        Adds an additional filter for searching.
        -
        -
        Parameters:
        -
        filter - filter to add.
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        clearSearchFilters

        -
        public void clearSearchFilters()
        -
        Resets the search filter.
        -
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getSearchBox

        -
        public final javax.swing.JTextField getSearchBox()
        -
        -
        Returns:
        -
        this component's search box component
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getSearchFilter

        -
        private java.util.function.Predicate<java.lang.String> getSearchFilter​(java.lang.String searchText)
        -
        -
        Parameters:
        -
        searchText - text to search for
        -
        Returns:
        -
        a filter that filters out that text, based on this list's case sensitive setting
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getSearchList

        -
        public final javax.swing.JList<java.lang.String> getSearchList()
        -
        -
        Returns:
        -
        this component's list component
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getSelectedIndex

        -
        public int getSelectedIndex()
        -
        -
        Returns:
        -
        index selected in item list
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getSelectedValue

        -
        public java.lang.String getSelectedValue()
        -
        -
        Returns:
        -
        value selected in item list
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        reapplyFilter

        -
        public void reapplyFilter()
        -
        Re-applies the filters.
        -
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        searchBoxFocusGained

        -
        private void searchBoxFocusGained​(java.awt.event.FocusEvent e)
        -
        Runs whenever the search box gains focus.
        -
        -
        Parameters:
        -
        e - focus event
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        searchBoxFocusLost

        -
        private void searchBoxFocusLost​(java.awt.event.FocusEvent e)
        -
        Runs whenever the search box loses focus.
        -
        -
        Parameters:
        -
        e - focus event
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        searchBoxTextChanged

        -
        private void searchBoxTextChanged()
        -
        Runs whenever the text in the search box is changed. -

        - Reapplies the search filter, and custom filters. -

        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/converterGUI/UnitConverterGUI.Presenter.html b/doc/org/unitConverter/converterGUI/UnitConverterGUI.Presenter.html deleted file mode 100644 index a33e4d8..0000000 --- a/doc/org/unitConverter/converterGUI/UnitConverterGUI.Presenter.html +++ /dev/null @@ -1,717 +0,0 @@ - - - - - -UnitConverterGUI.Presenter - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitConverterGUI.Presenter

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.converterGUI.UnitConverterGUI.Presenter
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    UnitConverterGUI
    -
    -
    -
    private static class UnitConverterGUI.Presenter
    -extends java.lang.Object
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private UnitDatabasedatabase -
      The units known by the program.
      -
      private java.util.List<java.lang.String>dimensionNames -
      The names of all of the dimensions
      -
      private java.util.Comparator<java.lang.String>prefixNameComparator 
      private java.util.List<java.lang.String>prefixNames -
      The names of all of the prefixes
      -
      private intsignificantFigures 
      private java.util.List<java.lang.String>unitNames -
      The names of all of the units
      -
      private UnitConverterGUI.Viewview -
      The presenter's associated view.
      -
      -
    • -
    -
    - -
    - -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      private static voidaddDefaults​(UnitDatabase database) -
      Adds default units and dimensions to a database.
      -
      voidconvertDimensionBased() -
      Converts in the dimension-based converter
      -
      voidconvertExpressions() -
      Runs whenever the convert button is pressed.
      -
      java.util.List<java.lang.String>dimensionNameList() 
      java.util.Comparator<java.lang.String>getPrefixNameComparator() 
      private java.lang.StringgetRoundedString​(double value) 
      java.util.Set<java.lang.String>prefixNameSet() 
      voidprefixSelected() -
      Runs whenever a prefix is selected in the viewer.
      -
      voidsetSignificantFigures​(int significantFigures) 
      booleanunitMatchesDimension​(java.lang.String unitName, - java.lang.String dimensionName) -
      Returns true if and only if the unit represented by unitName has the dimension represented by - dimensionName.
      -
      voidunitNameSelected() -
      Runs whenever a unit is selected in the viewer.
      -
      java.util.Set<java.lang.String>unitNameSet() 
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - - - - - -
        -
      • -

        database

        -
        private final UnitDatabase database
        -
        The units known by the program.
        -
      • -
      - - - -
        -
      • -

        unitNames

        -
        private final java.util.List<java.lang.String> unitNames
        -
        The names of all of the units
        -
      • -
      - - - -
        -
      • -

        prefixNames

        -
        private final java.util.List<java.lang.String> prefixNames
        -
        The names of all of the prefixes
        -
      • -
      - - - -
        -
      • -

        dimensionNames

        -
        private final java.util.List<java.lang.String> dimensionNames
        -
        The names of all of the dimensions
        -
      • -
      - - - -
        -
      • -

        prefixNameComparator

        -
        private final java.util.Comparator<java.lang.String> prefixNameComparator
        -
      • -
      - - - -
        -
      • -

        significantFigures

        -
        private int significantFigures
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        Presenter

        -
        Presenter​(UnitConverterGUI.View view)
        -
        Creates the presenter.
        -
        -
        Parameters:
        -
        view - presenter's associated view
        -
        Since:
        -
        2018-12-27, v0.1.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        addDefaults

        -
        private static void addDefaults​(UnitDatabase database)
        -
        Adds default units and dimensions to a database.
        -
        -
        Parameters:
        -
        database - database to add to
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        convertDimensionBased

        -
        public final void convertDimensionBased()
        -
        Converts in the dimension-based converter
        -
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        convertExpressions

        -
        public final void convertExpressions()
        -
        Runs whenever the convert button is pressed. - -

        - Reads and parses a unit expression from the from and to boxes, then converts from to to. Any - errors are shown in JOptionPanes. -

        -
        -
        Since:
        -
        2019-01-26, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        dimensionNameList

        -
        public final java.util.List<java.lang.String> dimensionNameList()
        -
        -
        Returns:
        -
        a list of all of the unit dimensions
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getPrefixNameComparator

        -
        public final java.util.Comparator<java.lang.String> getPrefixNameComparator()
        -
        -
        Returns:
        -
        a comparator to compare prefix names
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getRoundedString

        -
        private final java.lang.String getRoundedString​(double value)
        -
        -
        Parameters:
        -
        value - value to round
        -
        Returns:
        -
        string of that value rounded to significantDigits significant digits.
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        prefixNameSet

        -
        public final java.util.Set<java.lang.String> prefixNameSet()
        -
        -
        Returns:
        -
        a set of all prefix names in the database
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        prefixSelected

        -
        public final void prefixSelected()
        -
        Runs whenever a prefix is selected in the viewer. -

        - Shows its information in the text box to the right. -

        -
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setSignificantFigures

        -
        public final void setSignificantFigures​(int significantFigures)
        -
        -
        Parameters:
        -
        significantFigures - new value of significantFigures
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        unitMatchesDimension

        -
        public final boolean unitMatchesDimension​(java.lang.String unitName,
        -                                          java.lang.String dimensionName)
        -
        Returns true if and only if the unit represented by unitName has the dimension represented by - dimensionName.
        -
        -
        Parameters:
        -
        unitName - name of unit to test
        -
        dimensionName - name of dimension to test
        -
        Returns:
        -
        whether unit has dimenision
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        unitNameSelected

        -
        public final void unitNameSelected()
        -
        Runs whenever a unit is selected in the viewer. -

        - Shows its information in the text box to the right. -

        -
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        unitNameSet

        -
        public final java.util.Set<java.lang.String> unitNameSet()
        -
        -
        Returns:
        -
        a set of all of the unit names
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/converterGUI/UnitConverterGUI.View.html b/doc/org/unitConverter/converterGUI/UnitConverterGUI.View.html deleted file mode 100644 index 708050f..0000000 --- a/doc/org/unitConverter/converterGUI/UnitConverterGUI.View.html +++ /dev/null @@ -1,853 +0,0 @@ - - - - - -UnitConverterGUI.View - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitConverterGUI.View

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.converterGUI.UnitConverterGUI.View
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    UnitConverterGUI
    -
    -
    -
    private static class UnitConverterGUI.View
    -extends java.lang.Object
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private javax.swing.JTextAreadimensionBasedOutput -
      The output area in the dimension-based converter
      -
      private javax.swing.JFrameframe -
      The view's frame.
      -
      private javax.swing.JTextFieldfromEntry -
      The "From" entry in the conversion panel
      -
      private SearchBoxListfromSearch -
      The panel for "From" in the dimension-based converter
      -
      private javax.swing.JTextAreaoutput -
      The output area in the conversion panel
      -
      private SearchBoxListprefixNameList -
      The searchable list of prefix names in the prefix viewer
      -
      private javax.swing.JTextAreaprefixTextBox -
      The text box for prefix data in the prefix viewer
      -
      private UnitConverterGUI.Presenterpresenter -
      The view's associated presenter.
      -
      private javax.swing.JTextFieldtoEntry -
      The "To" entry in the conversion panel
      -
      private SearchBoxListtoSearch -
      The panel for "To" in the dimension-based converter
      -
      private SearchBoxListunitNameList -
      The searchable list of unit names in the unit viewer
      -
      private javax.swing.JTextAreaunitTextBox -
      The text box for unit data in the unit viewer
      -
      private javax.swing.JTextFieldvalueInput -
      The panel for inputting values in the dimension-based converter
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      View() -
      Creates the View.
      -
      -
    • -
    -
    - -
    - -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        frame

        -
        private final javax.swing.JFrame frame
        -
        The view's frame.
        -
      • -
      - - - - - - - -
        -
      • -

        valueInput

        -
        private final javax.swing.JTextField valueInput
        -
        The panel for inputting values in the dimension-based converter
        -
      • -
      - - - -
        -
      • -

        fromSearch

        -
        private final SearchBoxList fromSearch
        -
        The panel for "From" in the dimension-based converter
        -
      • -
      - - - -
        -
      • -

        toSearch

        -
        private final SearchBoxList toSearch
        -
        The panel for "To" in the dimension-based converter
        -
      • -
      - - - -
        -
      • -

        dimensionBasedOutput

        -
        private final javax.swing.JTextArea dimensionBasedOutput
        -
        The output area in the dimension-based converter
        -
      • -
      - - - -
        -
      • -

        fromEntry

        -
        private final javax.swing.JTextField fromEntry
        -
        The "From" entry in the conversion panel
        -
      • -
      - - - -
        -
      • -

        toEntry

        -
        private final javax.swing.JTextField toEntry
        -
        The "To" entry in the conversion panel
        -
      • -
      - - - -
        -
      • -

        output

        -
        private final javax.swing.JTextArea output
        -
        The output area in the conversion panel
        -
      • -
      - - - -
        -
      • -

        unitNameList

        -
        private final SearchBoxList unitNameList
        -
        The searchable list of unit names in the unit viewer
        -
      • -
      - - - -
        -
      • -

        prefixNameList

        -
        private final SearchBoxList prefixNameList
        -
        The searchable list of prefix names in the prefix viewer
        -
      • -
      - - - -
        -
      • -

        unitTextBox

        -
        private final javax.swing.JTextArea unitTextBox
        -
        The text box for unit data in the unit viewer
        -
      • -
      - - - -
        -
      • -

        prefixTextBox

        -
        private final javax.swing.JTextArea prefixTextBox
        -
        The text box for prefix data in the prefix viewer
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        View

        -
        public View()
        -
        Creates the View.
        -
        -
        Since:
        -
        2019-01-14, v0.1.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        getDimensionConverterInput

        -
        public java.lang.String getDimensionConverterInput()
        -
        -
        Returns:
        -
        value in dimension-based converter
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getFromSelection

        -
        public java.lang.String getFromSelection()
        -
        -
        Returns:
        -
        selection in "From" selector in dimension-based converter
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getFromText

        -
        public java.lang.String getFromText()
        -
        -
        Returns:
        -
        text in "From" box in converter panel
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getPrefixViewerSelection

        -
        public java.lang.String getPrefixViewerSelection()
        -
        -
        Returns:
        -
        index of selected prefix in prefix viewer
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getToSelection

        -
        public java.lang.String getToSelection()
        -
        -
        Returns:
        -
        selection in "To" selector in dimension-based converter
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getToText

        -
        public java.lang.String getToText()
        -
        -
        Returns:
        -
        text in "To" box in converter panel
        -
        Since:
        -
        2019-01-26, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getUnitViewerSelection

        -
        public java.lang.String getUnitViewerSelection()
        -
        -
        Returns:
        -
        index of selected unit in unit viewer
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        init

        -
        public final void init()
        -
        Starts up the application.
        -
        -
        Since:
        -
        2018-12-27, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        initComponents

        -
        private final void initComponents()
        -
        Initializes the view's components.
        -
        -
        Since:
        -
        2018-12-27, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setDimensionConverterOutputText

        -
        public void setDimensionConverterOutputText​(java.lang.String text)
        -
        Sets the text in the output of the dimension-based converter.
        -
        -
        Parameters:
        -
        text - text to set
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        setExpressionConverterOutputText

        -
        public void setExpressionConverterOutputText​(java.lang.String text)
        -
        Sets the text in the output of the conversion panel.
        -
        -
        Parameters:
        -
        text - text to set
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setPrefixTextBoxText

        -
        public void setPrefixTextBoxText​(java.lang.String text)
        -
        Sets the text of the prefix text box in the prefix viewer.
        -
        -
        Parameters:
        -
        text - text to set
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        setUnitTextBoxText

        -
        public void setUnitTextBoxText​(java.lang.String text)
        -
        Sets the text of the unit text box in the unit viewer.
        -
        -
        Parameters:
        -
        text - text to set
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        showErrorDialog

        -
        public void showErrorDialog​(java.lang.String title,
        -                            java.lang.String message)
        -
        Shows an error dialog.
        -
        -
        Parameters:
        -
        title - title of dialog
        -
        message - message in dialog
        -
        Since:
        -
        2019-01-14, v0.1.0
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/converterGUI/UnitConverterGUI.html b/doc/org/unitConverter/converterGUI/UnitConverterGUI.html deleted file mode 100644 index a61d917..0000000 --- a/doc/org/unitConverter/converterGUI/UnitConverterGUI.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - - -UnitConverterGUI - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitConverterGUI

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.converterGUI.UnitConverterGUI
    • -
    -
  • -
-
-
    -
  • -
    -
    final class UnitConverterGUI
    -extends java.lang.Object
    -
    -
    Since:
    -
    2018-12-27, v0.1.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      UnitConverterGUI() 
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - -
      All Methods Static Methods Concrete Methods 
      Modifier and TypeMethodDescription
      static voidmain​(java.lang.String[] args) 
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        UnitConverterGUI

        -
        UnitConverterGUI()
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        main

        -
        public static void main​(java.lang.String[] args)
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/converterGUI/class-use/DelegateListModel.html b/doc/org/unitConverter/converterGUI/class-use/DelegateListModel.html deleted file mode 100644 index 11be7c6..0000000 --- a/doc/org/unitConverter/converterGUI/class-use/DelegateListModel.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - - -Uses of Class org.unitConverter.converterGUI.DelegateListModel - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.converterGUI.DelegateListModel

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/converterGUI/class-use/FilterComparator.html b/doc/org/unitConverter/converterGUI/class-use/FilterComparator.html deleted file mode 100644 index 45696dc..0000000 --- a/doc/org/unitConverter/converterGUI/class-use/FilterComparator.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.converterGUI.FilterComparator - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.converterGUI.FilterComparator

-
-
No usage of org.unitConverter.converterGUI.FilterComparator
-
- - - diff --git a/doc/org/unitConverter/converterGUI/class-use/GridBagBuilder.html b/doc/org/unitConverter/converterGUI/class-use/GridBagBuilder.html deleted file mode 100644 index 6dbde14..0000000 --- a/doc/org/unitConverter/converterGUI/class-use/GridBagBuilder.html +++ /dev/null @@ -1,225 +0,0 @@ - - - - - -Uses of Class org.unitConverter.converterGUI.GridBagBuilder - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.converterGUI.GridBagBuilder

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/converterGUI/class-use/MutablePredicate.html b/doc/org/unitConverter/converterGUI/class-use/MutablePredicate.html deleted file mode 100644 index 91113cd..0000000 --- a/doc/org/unitConverter/converterGUI/class-use/MutablePredicate.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.converterGUI.MutablePredicate - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.converterGUI.MutablePredicate

-
-
No usage of org.unitConverter.converterGUI.MutablePredicate
-
- - - diff --git a/doc/org/unitConverter/converterGUI/class-use/SearchBoxList.html b/doc/org/unitConverter/converterGUI/class-use/SearchBoxList.html deleted file mode 100644 index ef2d34c..0000000 --- a/doc/org/unitConverter/converterGUI/class-use/SearchBoxList.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - - -Uses of Class org.unitConverter.converterGUI.SearchBoxList - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.converterGUI.SearchBoxList

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.Presenter.html b/doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.Presenter.html deleted file mode 100644 index e2116c8..0000000 --- a/doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.Presenter.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - -Uses of Class org.unitConverter.converterGUI.UnitConverterGUI.Presenter - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.converterGUI.UnitConverterGUI.Presenter

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.View.html b/doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.View.html deleted file mode 100644 index 0660499..0000000 --- a/doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.View.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - -Uses of Class org.unitConverter.converterGUI.UnitConverterGUI.View - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.converterGUI.UnitConverterGUI.View

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.html b/doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.html deleted file mode 100644 index 4cfc3f6..0000000 --- a/doc/org/unitConverter/converterGUI/class-use/UnitConverterGUI.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.converterGUI.UnitConverterGUI - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.converterGUI.UnitConverterGUI

-
-
No usage of org.unitConverter.converterGUI.UnitConverterGUI
-
- - - diff --git a/doc/org/unitConverter/converterGUI/package-frame.html b/doc/org/unitConverter/converterGUI/package-frame.html deleted file mode 100644 index 33d1aeb..0000000 --- a/doc/org/unitConverter/converterGUI/package-frame.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - -org.unitConverter.converterGUI - - - - - -

org.unitConverter.converterGUI

- - diff --git a/doc/org/unitConverter/converterGUI/package-summary.html b/doc/org/unitConverter/converterGUI/package-summary.html deleted file mode 100644 index fd85478..0000000 --- a/doc/org/unitConverter/converterGUI/package-summary.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - -org.unitConverter.converterGUI - - - - - - - - - - - -
-

Package org.unitConverter.converterGUI

-
-
The GUI interface of the Unit Converter.
-
-

See: Description

-
-
- - -

Package org.unitConverter.converterGUI Description

-
The GUI interface of the Unit Converter.
-
-
Since:
-
2019-01-25, v0.2.0
-
Author:
-
Adrien Hopkins
-
-
- - - - - - diff --git a/doc/org/unitConverter/converterGUI/package-tree.html b/doc/org/unitConverter/converterGUI/package-tree.html deleted file mode 100644 index 007991a..0000000 --- a/doc/org/unitConverter/converterGUI/package-tree.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - -org.unitConverter.converterGUI Class Hierarchy - - - - - - - - - - - -
-

Hierarchy For Package org.unitConverter.converterGUI

-Package Hierarchies: - -
- - - - - - diff --git a/doc/org/unitConverter/converterGUI/package-use.html b/doc/org/unitConverter/converterGUI/package-use.html deleted file mode 100644 index 83a9bc5..0000000 --- a/doc/org/unitConverter/converterGUI/package-use.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Package org.unitConverter.converterGUI - - - - - - - - - - - -
-

Uses of Package
org.unitConverter.converterGUI

-
-
No usage of org.unitConverter.converterGUI
- - - - - - diff --git a/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceCollection.html b/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceCollection.html deleted file mode 100644 index 3607ffa..0000000 --- a/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceCollection.html +++ /dev/null @@ -1,532 +0,0 @@ - - - - - -ConditionalExistenceCollections.ConditionalExistenceCollection - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class ConditionalExistenceCollections.ConditionalExistenceCollection<E>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • java.util.AbstractCollection<E>
    • -
    • -
        -
      • org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceCollection<E>
      • -
      -
    • -
    -
  • -
-
-
    -
  • -
    -
    Type Parameters:
    -
    E - type of element in collection
    -
    -
    -
    All Implemented Interfaces:
    -
    java.lang.Iterable<E>, java.util.Collection<E>
    -
    -
    -
    Enclosing class:
    -
    ConditionalExistenceCollections
    -
    -
    -
    static final class ConditionalExistenceCollections.ConditionalExistenceCollection<E>
    -extends java.util.AbstractCollection<E>
    -
    Elements in this collection only exist if they meet a condition.
    -
    -
    Since:
    -
    2019-10-17
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      (package private) java.util.Collection<E>collection 
      (package private) java.util.function.Predicate<E>existenceCondition 
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - - - -
      Constructors 
      ModifierConstructorDescription
      private ConditionalExistenceCollection​(java.util.Collection<E> collection, - java.util.function.Predicate<E> existenceCondition) -
      Creates the ConditionalExistenceCollection.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      booleanadd​(E e) 
      voidclear() 
      booleancontains​(java.lang.Object o) 
      java.util.Iterator<E>iterator() 
      booleanremove​(java.lang.Object o) 
      intsize() 
      -
        -
      • - - -

        Methods inherited from class java.util.AbstractCollection

        -addAll, containsAll, isEmpty, removeAll, retainAll, toArray, toArray, toString
      • -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Collection

        -equals, hashCode, parallelStream, removeIf, spliterator, stream, toArray
      • -
      -
        -
      • - - -

        Methods inherited from interface java.lang.Iterable

        -forEach
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        collection

        -
        final java.util.Collection<E> collection
        -
      • -
      - - - -
        -
      • -

        existenceCondition

        -
        final java.util.function.Predicate<E> existenceCondition
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        ConditionalExistenceCollection

        -
        private ConditionalExistenceCollection​(java.util.Collection<E> collection,
        -                                       java.util.function.Predicate<E> existenceCondition)
        -
        Creates the ConditionalExistenceCollection.
        -
        -
        Parameters:
        -
        collection -
        -
        existenceCondition -
        -
        Since:
        -
        2019-10-17
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - - - -
        -
      • -

        add

        -
        public boolean add​(E e)
        -
        -
        Specified by:
        -
        add in interface java.util.Collection<E>
        -
        Overrides:
        -
        add in class java.util.AbstractCollection<E>
        -
        -
      • -
      - - - -
        -
      • -

        clear

        -
        public void clear()
        -
        -
        Specified by:
        -
        clear in interface java.util.Collection<E>
        -
        Overrides:
        -
        clear in class java.util.AbstractCollection<E>
        -
        -
      • -
      - - - -
        -
      • -

        contains

        -
        public boolean contains​(java.lang.Object o)
        -
        -
        Specified by:
        -
        contains in interface java.util.Collection<E>
        -
        Overrides:
        -
        contains in class java.util.AbstractCollection<E>
        -
        -
      • -
      - - - -
        -
      • -

        iterator

        -
        public java.util.Iterator<E> iterator()
        -
        -
        Specified by:
        -
        iterator in interface java.util.Collection<E>
        -
        Specified by:
        -
        iterator in interface java.lang.Iterable<E>
        -
        Specified by:
        -
        iterator in class java.util.AbstractCollection<E>
        -
        -
      • -
      - - - -
        -
      • -

        remove

        -
        public boolean remove​(java.lang.Object o)
        -
        -
        Specified by:
        -
        remove in interface java.util.Collection<E>
        -
        Overrides:
        -
        remove in class java.util.AbstractCollection<E>
        -
        -
      • -
      - - - -
        -
      • -

        size

        -
        public int size()
        -
        -
        Specified by:
        -
        size in interface java.util.Collection<E>
        -
        Specified by:
        -
        size in class java.util.AbstractCollection<E>
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceIterator.html b/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceIterator.html deleted file mode 100644 index 0a3a963..0000000 --- a/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceIterator.html +++ /dev/null @@ -1,493 +0,0 @@ - - - - - -ConditionalExistenceCollections.ConditionalExistenceIterator - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class ConditionalExistenceCollections.ConditionalExistenceIterator<E>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceIterator<E>
    • -
    -
  • -
-
-
    -
  • -
    -
    Type Parameters:
    -
    E - type of elements in iterator
    -
    -
    -
    All Implemented Interfaces:
    -
    java.util.Iterator<E>
    -
    -
    -
    Enclosing class:
    -
    ConditionalExistenceCollections
    -
    -
    -
    static final class ConditionalExistenceCollections.ConditionalExistenceIterator<E>
    -extends java.lang.Object
    -implements java.util.Iterator<E>
    -
    Elements in this wrapper iterator only exist if they pass a condition.
    -
    -
    Since:
    -
    2019-10-17
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      (package private) java.util.function.Predicate<E>existenceCondition 
      (package private) booleanhasNext 
      (package private) java.util.Iterator<E>iterator 
      (package private) EnextElement 
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - - - -
      Constructors 
      ModifierConstructorDescription
      private ConditionalExistenceIterator​(java.util.Iterator<E> iterator, - java.util.function.Predicate<E> condition) -
      Creates the ConditionalExistenceIterator.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      private voidgetAndSetNextElement() -
      Gets the next element, and sets nextElement and hasNext accordingly.
      -
      booleanhasNext() 
      Enext() 
      voidremove() 
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Iterator

        -forEachRemaining
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        iterator

        -
        final java.util.Iterator<E> iterator
        -
      • -
      - - - -
        -
      • -

        existenceCondition

        -
        final java.util.function.Predicate<E> existenceCondition
        -
      • -
      - - - -
        -
      • -

        nextElement

        -
        E nextElement
        -
      • -
      - - - -
        -
      • -

        hasNext

        -
        boolean hasNext
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        ConditionalExistenceIterator

        -
        private ConditionalExistenceIterator​(java.util.Iterator<E> iterator,
        -                                     java.util.function.Predicate<E> condition)
        -
        Creates the ConditionalExistenceIterator.
        -
        -
        Parameters:
        -
        iterator -
        -
        condition -
        -
        Since:
        -
        2019-10-17
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        getAndSetNextElement

        -
        private void getAndSetNextElement()
        -
        Gets the next element, and sets nextElement and hasNext accordingly.
        -
        -
        Since:
        -
        2019-10-17
        -
        -
      • -
      - - - -
        -
      • -

        hasNext

        -
        public boolean hasNext()
        -
        -
        Specified by:
        -
        hasNext in interface java.util.Iterator<E>
        -
        -
      • -
      - - - -
        -
      • -

        next

        -
        public E next()
        -
        -
        Specified by:
        -
        next in interface java.util.Iterator<E>
        -
        -
      • -
      - - - -
        -
      • -

        remove

        -
        public void remove()
        -
        -
        Specified by:
        -
        remove in interface java.util.Iterator<E>
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceMap.html b/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceMap.html deleted file mode 100644 index 1b7b1a7..0000000 --- a/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceMap.html +++ /dev/null @@ -1,570 +0,0 @@ - - - - - -ConditionalExistenceCollections.ConditionalExistenceMap - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class ConditionalExistenceCollections.ConditionalExistenceMap<K,​V>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • java.util.AbstractMap<K,​V>
    • -
    • -
        -
      • org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceMap<K,​V>
      • -
      -
    • -
    -
  • -
-
-
    -
  • -
    -
    Type Parameters:
    -
    K - key type
    -
    V - value type
    -
    -
    -
    All Implemented Interfaces:
    -
    java.util.Map<K,​V>
    -
    -
    -
    Enclosing class:
    -
    ConditionalExistenceCollections
    -
    -
    -
    static final class ConditionalExistenceCollections.ConditionalExistenceMap<K,​V>
    -extends java.util.AbstractMap<K,​V>
    -
    Mappings in this map only exist if the entry passes some condition.
    -
    -
    Since:
    -
    2019-10-17
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Nested Class Summary

      -
        -
      • - - -

        Nested classes/interfaces inherited from class java.util.AbstractMap

        -java.util.AbstractMap.SimpleEntry<K extends java.lang.Object,​V extends java.lang.Object>, java.util.AbstractMap.SimpleImmutableEntry<K extends java.lang.Object,​V extends java.lang.Object>
      • -
      -
        -
      • - - -

        Nested classes/interfaces inherited from interface java.util.Map

        -java.util.Map.Entry<K extends java.lang.Object,​V extends java.lang.Object>
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      (package private) java.util.function.Predicate<java.util.Map.Entry<K,​V>>entryExistenceCondition 
      (package private) java.util.Map<K,​V>map 
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - - - -
      Constructors 
      ModifierConstructorDescription
      private ConditionalExistenceMap​(java.util.Map<K,​V> map, - java.util.function.Predicate<java.util.Map.Entry<K,​V>> entryExistenceCondition) -
      Creates the ConditionalExistenceMap.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      booleancontainsKey​(java.lang.Object key) 
      java.util.Set<java.util.Map.Entry<K,​V>>entrySet() 
      Vget​(java.lang.Object key) 
      java.util.Set<K>keySet() 
      Vput​(K key, - V value) 
      Vremove​(java.lang.Object key) 
      java.util.Collection<V>values() 
      -
        -
      • - - -

        Methods inherited from class java.util.AbstractMap

        -clear, clone, containsValue, equals, hashCode, isEmpty, putAll, size, toString
      • -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -finalize, getClass, notify, notifyAll, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Map

        -compute, computeIfAbsent, computeIfPresent, forEach, getOrDefault, merge, putIfAbsent, remove, replace, replace, replaceAll
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        map

        -
        java.util.Map<K,​V> map
        -
      • -
      - - - -
        -
      • -

        entryExistenceCondition

        -
        java.util.function.Predicate<java.util.Map.Entry<K,​V>> entryExistenceCondition
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        ConditionalExistenceMap

        -
        private ConditionalExistenceMap​(java.util.Map<K,​V> map,
        -                                java.util.function.Predicate<java.util.Map.Entry<K,​V>> entryExistenceCondition)
        -
        Creates the ConditionalExistenceMap.
        -
        -
        Parameters:
        -
        map -
        -
        entryExistenceCondition -
        -
        Since:
        -
        2019-10-17
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        containsKey

        -
        public boolean containsKey​(java.lang.Object key)
        -
        -
        Specified by:
        -
        containsKey in interface java.util.Map<K,​V>
        -
        Overrides:
        -
        containsKey in class java.util.AbstractMap<K,​V>
        -
        -
      • -
      - - - -
        -
      • -

        entrySet

        -
        public java.util.Set<java.util.Map.Entry<K,​V>> entrySet()
        -
        -
        Specified by:
        -
        entrySet in interface java.util.Map<K,​V>
        -
        Specified by:
        -
        entrySet in class java.util.AbstractMap<K,​V>
        -
        -
      • -
      - - - -
        -
      • -

        get

        -
        public V get​(java.lang.Object key)
        -
        -
        Specified by:
        -
        get in interface java.util.Map<K,​V>
        -
        Overrides:
        -
        get in class java.util.AbstractMap<K,​V>
        -
        -
      • -
      - - - -
        -
      • -

        keySet

        -
        public java.util.Set<K> keySet()
        -
        -
        Specified by:
        -
        keySet in interface java.util.Map<K,​V>
        -
        Overrides:
        -
        keySet in class java.util.AbstractMap<K,​V>
        -
        -
      • -
      - - - - - -
        -
      • -

        put

        -
        public V put​(K key,
        -             V value)
        -
        -
        Specified by:
        -
        put in interface java.util.Map<K,​V>
        -
        Overrides:
        -
        put in class java.util.AbstractMap<K,​V>
        -
        -
      • -
      - - - -
        -
      • -

        remove

        -
        public V remove​(java.lang.Object key)
        -
        -
        Specified by:
        -
        remove in interface java.util.Map<K,​V>
        -
        Overrides:
        -
        remove in class java.util.AbstractMap<K,​V>
        -
        -
      • -
      - - - -
        -
      • -

        values

        -
        public java.util.Collection<V> values()
        -
        -
        Specified by:
        -
        values in interface java.util.Map<K,​V>
        -
        Overrides:
        -
        values in class java.util.AbstractMap<K,​V>
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceSet.html b/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceSet.html deleted file mode 100644 index 060e2a3..0000000 --- a/doc/org/unitConverter/math/ConditionalExistenceCollections.ConditionalExistenceSet.html +++ /dev/null @@ -1,565 +0,0 @@ - - - - - -ConditionalExistenceCollections.ConditionalExistenceSet - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class ConditionalExistenceCollections.ConditionalExistenceSet<E>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • java.util.AbstractCollection<E>
    • -
    • -
        -
      • java.util.AbstractSet<E>
      • -
      • -
          -
        • org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceSet<E>
        • -
        -
      • -
      -
    • -
    -
  • -
-
-
    -
  • -
    -
    Type Parameters:
    -
    E - type of element in set
    -
    -
    -
    All Implemented Interfaces:
    -
    java.lang.Iterable<E>, java.util.Collection<E>, java.util.Set<E>
    -
    -
    -
    Enclosing class:
    -
    ConditionalExistenceCollections
    -
    -
    -
    static final class ConditionalExistenceCollections.ConditionalExistenceSet<E>
    -extends java.util.AbstractSet<E>
    -
    Elements in this set only exist if a certain condition is true.
    -
    -
    Since:
    -
    2019-10-17
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private java.util.function.Predicate<E>existenceCondition 
      private java.util.Set<E>set 
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - - - -
      Constructors 
      ModifierConstructorDescription
      private ConditionalExistenceSet​(java.util.Set<E> set, - java.util.function.Predicate<E> existenceCondition) -
      Creates the ConditionalNonexistenceSet.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      booleanadd​(E e)
      voidclear() 
      booleancontains​(java.lang.Object o) 
      java.util.Iterator<E>iterator() 
      booleanremove​(java.lang.Object o) 
      intsize() 
      -
        -
      • - - -

        Methods inherited from class java.util.AbstractSet

        -equals, hashCode, removeAll
      • -
      -
        -
      • - - -

        Methods inherited from class java.util.AbstractCollection

        -addAll, containsAll, isEmpty, retainAll, toArray, toArray, toString
      • -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, finalize, getClass, notify, notifyAll, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Collection

        -parallelStream, removeIf, stream, toArray
      • -
      -
        -
      • - - -

        Methods inherited from interface java.lang.Iterable

        -forEach
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Set

        -addAll, containsAll, isEmpty, retainAll, spliterator, toArray, toArray
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        set

        -
        private final java.util.Set<E> set
        -
      • -
      - - - -
        -
      • -

        existenceCondition

        -
        private final java.util.function.Predicate<E> existenceCondition
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        ConditionalExistenceSet

        -
        private ConditionalExistenceSet​(java.util.Set<E> set,
        -                                java.util.function.Predicate<E> existenceCondition)
        -
        Creates the ConditionalNonexistenceSet.
        -
        -
        Parameters:
        -
        set - set to use
        -
        existenceCondition - condition where element exists
        -
        Since:
        -
        2019-10-17
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - - - -
        -
      • -

        add

        -
        public boolean add​(E e)
        -
        -

        - Note that this method returns false if e does not pass the existence condition.

        -
        -
        Specified by:
        -
        add in interface java.util.Collection<E>
        -
        Specified by:
        -
        add in interface java.util.Set<E>
        -
        Overrides:
        -
        add in class java.util.AbstractCollection<E>
        -
        -
      • -
      - - - -
        -
      • -

        clear

        -
        public void clear()
        -
        -
        Specified by:
        -
        clear in interface java.util.Collection<E>
        -
        Specified by:
        -
        clear in interface java.util.Set<E>
        -
        Overrides:
        -
        clear in class java.util.AbstractCollection<E>
        -
        -
      • -
      - - - -
        -
      • -

        contains

        -
        public boolean contains​(java.lang.Object o)
        -
        -
        Specified by:
        -
        contains in interface java.util.Collection<E>
        -
        Specified by:
        -
        contains in interface java.util.Set<E>
        -
        Overrides:
        -
        contains in class java.util.AbstractCollection<E>
        -
        -
      • -
      - - - -
        -
      • -

        iterator

        -
        public java.util.Iterator<E> iterator()
        -
        -
        Specified by:
        -
        iterator in interface java.util.Collection<E>
        -
        Specified by:
        -
        iterator in interface java.lang.Iterable<E>
        -
        Specified by:
        -
        iterator in interface java.util.Set<E>
        -
        Specified by:
        -
        iterator in class java.util.AbstractCollection<E>
        -
        -
      • -
      - - - -
        -
      • -

        remove

        -
        public boolean remove​(java.lang.Object o)
        -
        -
        Specified by:
        -
        remove in interface java.util.Collection<E>
        -
        Specified by:
        -
        remove in interface java.util.Set<E>
        -
        Overrides:
        -
        remove in class java.util.AbstractCollection<E>
        -
        -
      • -
      - - - -
        -
      • -

        size

        -
        public int size()
        -
        -
        Specified by:
        -
        size in interface java.util.Collection<E>
        -
        Specified by:
        -
        size in interface java.util.Set<E>
        -
        Specified by:
        -
        size in class java.util.AbstractCollection<E>
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/math/ConditionalExistenceCollections.html b/doc/org/unitConverter/math/ConditionalExistenceCollections.html deleted file mode 100644 index 2764146..0000000 --- a/doc/org/unitConverter/math/ConditionalExistenceCollections.html +++ /dev/null @@ -1,397 +0,0 @@ - - - - - -ConditionalExistenceCollections - - - - - - - - - - - - -
-
org.unitConverter.math
-

Class ConditionalExistenceCollections

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.ConditionalExistenceCollections
    • -
    -
  • -
-
-
    -
  • -
    -
    -
    public final class ConditionalExistenceCollections
    -extends java.lang.Object
    -
    Elements in these wrapper collections only exist if they pass a condition. -

    - All of the collections in this class are "views" of the provided collections. They are mutable if the provided - collections are mutable, they allow null if the provided collections allow null, they will reflect changes in the - provided collection, etc. -

    - The modification operations will always run the corresponding operations, even if the conditional existence - collection doesn't change. For example, if you have a set that ignores even numbers, add(2) will still add a 2 to the - backing set (but the conditional existence set will say it doesn't exist). -

    - The returned collections do not pass the hashCode and equals operations through to the backing collections, - but rely on Object's equals and hashCode methods. This is necessary to preserve the contracts - of these operations in the case that the backing collections are sets or lists. -

    - Other than that, the only difference between the provided collections and the returned collections are that - elements don't exist if they don't pass the provided condition.

    -
    -
    Since:
    -
    2019-10-17
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - - - -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Static Methods Concrete Methods 
      Modifier and TypeMethod and Description
      static <E> java.util.Collection<E>conditionalExistenceCollection(java.util.Collection<E> collection, - java.util.function.Predicate<E> existenceCondition) -
      Elements in the returned wrapper collection are ignored if they don't pass a condition.
      -
      static <E> java.util.Iterator<E>conditionalExistenceIterator(java.util.Iterator<E> iterator, - java.util.function.Predicate<E> existenceCondition) -
      Elements in the returned wrapper iterator are ignored if they don't pass a condition.
      -
      static <K,V> java.util.Map<K,V>conditionalExistenceMap(java.util.Map<K,V> map, - java.util.function.Predicate<java.util.Map.Entry<K,V>> entryExistenceCondition) -
      Mappings in the returned wrapper map are ignored if the corresponding entry doesn't pass a condition
      -
      static <E> java.util.Set<E>conditionalExistenceSet(java.util.Set<E> set, - java.util.function.Predicate<E> existenceCondition) -
      Elements in the returned wrapper set are ignored if they don't pass a condition.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
    • -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        ConditionalExistenceCollections

        -
        public ConditionalExistenceCollections()
        -
      • -
      -
    • -
    - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        conditionalExistenceCollection

        -
        public static final <E> java.util.Collection<E> conditionalExistenceCollection(java.util.Collection<E> collection,
        -                                                                               java.util.function.Predicate<E> existenceCondition)
        -
        Elements in the returned wrapper collection are ignored if they don't pass a condition.
        -
        -
        Type Parameters:
        -
        E - type of elements in collection
        -
        Parameters:
        -
        collection - collection to wrap
        -
        existenceCondition - elements only exist if this returns true
        -
        Returns:
        -
        wrapper collection
        -
        Since:
        -
        2019-10-17
        -
        -
      • -
      - - - -
        -
      • -

        conditionalExistenceIterator

        -
        public static final <E> java.util.Iterator<E> conditionalExistenceIterator(java.util.Iterator<E> iterator,
        -                                                                           java.util.function.Predicate<E> existenceCondition)
        -
        Elements in the returned wrapper iterator are ignored if they don't pass a condition.
        -
        -
        Type Parameters:
        -
        E - type of elements in iterator
        -
        Parameters:
        -
        iterator - iterator to wrap
        -
        existenceCondition - elements only exist if this returns true
        -
        Returns:
        -
        wrapper iterator
        -
        Since:
        -
        2019-10-17
        -
        -
      • -
      - - - -
        -
      • -

        conditionalExistenceMap

        -
        public static final <K,V> java.util.Map<K,V> conditionalExistenceMap(java.util.Map<K,V> map,
        -                                                                     java.util.function.Predicate<java.util.Map.Entry<K,V>> entryExistenceCondition)
        -
        Mappings in the returned wrapper map are ignored if the corresponding entry doesn't pass a condition
        -
        -
        Type Parameters:
        -
        K - type of key in map
        -
        V - type of value in map
        -
        Parameters:
        -
        map - map to wrap
        -
        entryExistenceCondition - mappings only exist if this returns true
        -
        Returns:
        -
        wrapper map
        -
        Since:
        -
        2019-10-17
        -
        -
      • -
      - - - -
        -
      • -

        conditionalExistenceSet

        -
        public static final <E> java.util.Set<E> conditionalExistenceSet(java.util.Set<E> set,
        -                                                                 java.util.function.Predicate<E> existenceCondition)
        -
        Elements in the returned wrapper set are ignored if they don't pass a condition.
        -
        -
        Type Parameters:
        -
        E - type of elements in set
        -
        Parameters:
        -
        set - set to wrap
        -
        existenceCondition - elements only exist if this returns true
        -
        Returns:
        -
        wrapper set
        -
        Since:
        -
        2019-10-17
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/math/ConditionalExistenceCollectionsTest.html b/doc/org/unitConverter/math/ConditionalExistenceCollectionsTest.html deleted file mode 100644 index e08b3f5..0000000 --- a/doc/org/unitConverter/math/ConditionalExistenceCollectionsTest.html +++ /dev/null @@ -1,469 +0,0 @@ - - - - - -ConditionalExistenceCollectionsTest - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class ConditionalExistenceCollectionsTest

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.ConditionalExistenceCollectionsTest
    • -
    -
  • -
-
-
    -
  • -
    -
    class ConditionalExistenceCollectionsTest
    -extends java.lang.Object
    -
    Tests the #ConditionalExistenceCollections.
    -
    -
    Since:
    -
    2019-10-16
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      (package private) ConditionalExistenceCollections.ConditionalExistenceIterator<java.lang.String>getTestIterator() -
      The returned iterator ignores elements that don't start with "a".
      -
      (package private) java.util.Map<java.lang.String,​java.lang.Integer>getTestMap() -
      The returned map ignores mappings where the value is zero.
      -
      (package private) voidtestContainsKeyObject() -
      Test method for org.unitConverter.math.ZeroIsNullMap#containsKey(java.lang.Object).
      -
      (package private) voidtestContainsValueObject() -
      Test method for org.unitConverter.math.ZeroIsNullMap#containsValue(java.lang.Object).
      -
      (package private) voidtestEntrySet() -
      Test method for org.unitConverter.math.ZeroIsNullMap#entrySet().
      -
      (package private) voidtestGetObject() -
      Test method for org.unitConverter.math.ZeroIsNullMap#get(java.lang.Object).
      -
      (package private) voidtestIterator() 
      (package private) voidtestKeySet() -
      Test method for org.unitConverter.math.ZeroIsNullMap#keySet().
      -
      (package private) voidtestValues() -
      Test method for org.unitConverter.math.ZeroIsNullMap#values().
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        ConditionalExistenceCollectionsTest

        -
        ConditionalExistenceCollectionsTest()
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - - - - - -
        -
      • -

        getTestMap

        -
        java.util.Map<java.lang.String,​java.lang.Integer> getTestMap()
        -
        The returned map ignores mappings where the value is zero.
        -
        -
        Returns:
        -
        map to be used for test data
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        testContainsKeyObject

        -
        @Test
        -void testContainsKeyObject()
        -
        Test method for org.unitConverter.math.ZeroIsNullMap#containsKey(java.lang.Object).
        -
      • -
      - - - -
        -
      • -

        testContainsValueObject

        -
        @Test
        -void testContainsValueObject()
        -
        Test method for org.unitConverter.math.ZeroIsNullMap#containsValue(java.lang.Object).
        -
      • -
      - - - -
        -
      • -

        testEntrySet

        -
        @Test
        -void testEntrySet()
        -
        Test method for org.unitConverter.math.ZeroIsNullMap#entrySet().
        -
      • -
      - - - -
        -
      • -

        testGetObject

        -
        @Test
        -void testGetObject()
        -
        Test method for org.unitConverter.math.ZeroIsNullMap#get(java.lang.Object).
        -
      • -
      - - - -
        -
      • -

        testIterator

        -
        @Test
        -void testIterator()
        -
      • -
      - - - -
        -
      • -

        testKeySet

        -
        @Test
        -void testKeySet()
        -
        Test method for org.unitConverter.math.ZeroIsNullMap#keySet().
        -
      • -
      - - - -
        -
      • -

        testValues

        -
        @Test
        -void testValues()
        -
        Test method for org.unitConverter.math.ZeroIsNullMap#values().
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/math/DecimalComparison.html b/doc/org/unitConverter/math/DecimalComparison.html deleted file mode 100644 index 6b013fc..0000000 --- a/doc/org/unitConverter/math/DecimalComparison.html +++ /dev/null @@ -1,492 +0,0 @@ - - - - - -DecimalComparison - - - - - - - - - - - - -
-
org.unitConverter.math
-

Class DecimalComparison

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.DecimalComparison
    • -
    -
  • -
-
-
    -
  • -
    -
    -
    public final class DecimalComparison
    -extends java.lang.Object
    -
    A class that contains methods to compare float and double values.
    -
    -
    Since:
    -
    2019-03-18, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeField and Description
      static doubleDOUBLE_EPSILON -
      The value used for double comparison.
      -
      static floatFLOAT_EPSILON -
      The value used for float comparison.
      -
      -
    • -
    - -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Static Methods Concrete Methods 
      Modifier and TypeMethod and Description
      static booleanequals(double a, - double b) -
      Tests for equality of double values using DOUBLE_EPSILON.
      -
      static booleanequals(double a, - double b, - double epsilon) -
      Tests for double equality using a custom epsilon value.
      -
      static booleanequals(float a, - float b) -
      Tests for equality of float values using FLOAT_EPSILON.
      -
      static booleanequals(float a, - float b, - float epsilon) -
      Tests for float equality using a custom epsilon value.
      -
      static inthash(double d) -
      Takes the hash code of doubles.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
    • -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        DOUBLE_EPSILON

        -
        public static final double DOUBLE_EPSILON
        -
        The value used for double comparison. If two double values are within this value multiplied by the larger value, - they are considered equal.
        -
        -
        Since:
        -
        2019-03-18, v0.2.0
        -
        See Also:
        -
        Constant Field Values
        -
        -
      • -
      - - - -
        -
      • -

        FLOAT_EPSILON

        -
        public static final float FLOAT_EPSILON
        -
        The value used for float comparison. If two float values are within this value multiplied by the larger value, - they are considered equal.
        -
        -
        Since:
        -
        2019-03-18, v0.2.0
        -
        See Also:
        -
        Constant Field Values
        -
        -
      • -
      -
    • -
    - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        equals

        -
        public static final boolean equals(double a,
        -                                   double b)
        -
        Tests for equality of double values using DOUBLE_EPSILON. -

        - WARNING: this method is not technically transitive. If a and b are off by slightly less than - epsilon * max(abs(a), abs(b)), and b and c are off by slightly less than - epsilon * max(abs(b), abs(c)), then equals(a, b) and equals(b, c) will both return true, but equals(a, c) - will return false. However, this situation is very unlikely to ever happen in a real programming situation. -

        - If this does become a concern, some ways to solve this problem: -

          -
        1. Raise the value of epsilon using equals(double, double, double) (this does not make a violation of - transitivity impossible, it just significantly reduces the chances of it happening) -
        2. Use BigDecimal instead of double (this will make a violation of transitivity 100% impossible) -
        -
        -
        Parameters:
        -
        a - first value to test
        -
        b - second value to test
        -
        Returns:
        -
        whether they are equal
        -
        Since:
        -
        2019-03-18, v0.2.0
        -
        See Also:
        -
        #hashCode(double)
        -
        -
      • -
      - - - -
        -
      • -

        equals

        -
        public static final boolean equals(double a,
        -                                   double b,
        -                                   double epsilon)
        -
        Tests for double equality using a custom epsilon value. - -

        - WARNING: this method is not technically transitive. If a and b are off by slightly less than - epsilon * max(abs(a), abs(b)), and b and c are off by slightly less than - epsilon * max(abs(b), abs(c)), then equals(a, b) and equals(b, c) will both return true, but equals(a, c) - will return false. However, this situation is very unlikely to ever happen in a real programming situation. -

        - If this does become a concern, some ways to solve this problem: -

          -
        1. Raise the value of epsilon (this does not make a violation of transitivity impossible, it just significantly - reduces the chances of it happening) -
        2. Use BigDecimal instead of double (this will make a violation of transitivity 100% impossible) -
        -
        -
        Parameters:
        -
        a - first value to test
        -
        b - second value to test
        -
        epsilon - allowed difference
        -
        Returns:
        -
        whether they are equal
        -
        Since:
        -
        2019-03-18, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        equals

        -
        public static final boolean equals(float a,
        -                                   float b)
        -
        Tests for equality of float values using FLOAT_EPSILON. - -

        - WARNING: this method is not technically transitive. If a and b are off by slightly less than - epsilon * max(abs(a), abs(b)), and b and c are off by slightly less than - epsilon * max(abs(b), abs(c)), then equals(a, b) and equals(b, c) will both return true, but equals(a, c) - will return false. However, this situation is very unlikely to ever happen in a real programming situation. -

        - If this does become a concern, some ways to solve this problem: -

          -
        1. Raise the value of epsilon using equals(float, float, float) (this does not make a violation of - transitivity impossible, it just significantly reduces the chances of it happening) -
        2. Use BigDecimal instead of float (this will make a violation of transitivity 100% impossible) -
        -
        -
        Parameters:
        -
        a - first value to test
        -
        b - second value to test
        -
        Returns:
        -
        whether they are equal
        -
        Since:
        -
        2019-03-18, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        equals

        -
        public static final boolean equals(float a,
        -                                   float b,
        -                                   float epsilon)
        -
        Tests for float equality using a custom epsilon value. - -

        - WARNING: this method is not technically transitive. If a and b are off by slightly less than - epsilon * max(abs(a), abs(b)), and b and c are off by slightly less than - epsilon * max(abs(b), abs(c)), then equals(a, b) and equals(b, c) will both return true, but equals(a, c) - will return false. However, this situation is very unlikely to ever happen in a real programming situation. -

        - If this does become a concern, some ways to solve this problem: -

          -
        1. Raise the value of epsilon (this does not make a violation of transitivity impossible, it just significantly - reduces the chances of it happening) -
        2. Use BigDecimal instead of float (this will make a violation of transitivity 100% impossible) -
        -
        -
        Parameters:
        -
        a - first value to test
        -
        b - second value to test
        -
        epsilon - allowed difference
        -
        Returns:
        -
        whether they are equal
        -
        Since:
        -
        2019-03-18, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        hash

        -
        public static final int hash(double d)
        -
        Takes the hash code of doubles. Values that are equal according to equals(double, double) will have the - same hash code.
        -
        -
        Parameters:
        -
        d - double to hash
        -
        Returns:
        -
        hash code of double
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/math/ExpressionParser.Builder.html b/doc/org/unitConverter/math/ExpressionParser.Builder.html deleted file mode 100644 index 563f6eb..0000000 --- a/doc/org/unitConverter/math/ExpressionParser.Builder.html +++ /dev/null @@ -1,391 +0,0 @@ - - - - - -ExpressionParser.Builder - - - - - - - - - - - - -
-
org.unitConverter.math
-

Class ExpressionParser.Builder<T>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.ExpressionParser.Builder<T>
    • -
    -
  • -
-
-
    -
  • -
    -
    Type Parameters:
    -
    T - type of object that exists in parsed expressions
    -
    -
    -
    Enclosing class:
    -
    ExpressionParser<T>
    -
    -
    -
    -
    public static final class ExpressionParser.Builder<T>
    -extends java.lang.Object
    -
    A builder that can create ExpressionParser<T> instances.
    -
    -
    Since:
    -
    2019-03-17, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Constructor Summary

      - - - - - - - - -
      Constructors 
      Constructor and Description
      Builder(java.util.function.Function<java.lang.String,? extends T> objectObtainer) -
      Creates the Builder.
      -
      -
    • -
    - - -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        Builder

        -
        public Builder(java.util.function.Function<java.lang.String,? extends T> objectObtainer)
        -
        Creates the Builder.
        -
        -
        Parameters:
        -
        objectObtainer - a function that can turn strings into objects of the type handled by the parser.
        -
        Throws:
        -
        java.lang.NullPointerException - if objectObtainer is null
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      -
    • -
    - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        addBinaryOperator

        -
        public ExpressionParser.Builder<T> addBinaryOperator(java.lang.String text,
        -                                                     java.util.function.BinaryOperator<T> operator,
        -                                                     int priority)
        -
        Adds a binary operator to the builder.
        -
        -
        Parameters:
        -
        text - text used to reference the operator, like '+'
        -
        operator - operator to add
        -
        priority - operator's priority, which determines which operators are applied first
        -
        Returns:
        -
        this builder
        -
        Throws:
        -
        java.lang.NullPointerException - if text or operator is null
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        addSpaceFunction

        -
        public ExpressionParser.Builder<T> addSpaceFunction(java.lang.String operator)
        -
        Adds a function for spaces. You must use the text of an existing binary operator.
        -
        -
        Parameters:
        -
        operator - text of operator to use
        -
        Returns:
        -
        this builder
        -
        Since:
        -
        2019-03-22, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        addUnaryOperator

        -
        public ExpressionParser.Builder<T> addUnaryOperator(java.lang.String text,
        -                                                    java.util.function.UnaryOperator<T> operator,
        -                                                    int priority)
        -
        Adds a unary operator to the builder.
        -
        -
        Parameters:
        -
        text - text used to reference the operator, like '-'
        -
        operator - operator to add
        -
        priority - operator's priority, which determines which operators are applied first
        -
        Returns:
        -
        this builder
        -
        Throws:
        -
        java.lang.NullPointerException - if text or operator is null
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        build

        -
        public ExpressionParser<T> build()
        -
        -
        Returns:
        -
        an ExpressionParser<T> instance with the properties given to this builder
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/math/ExpressionParser.PriorityBinaryOperator.html b/doc/org/unitConverter/math/ExpressionParser.PriorityBinaryOperator.html deleted file mode 100644 index ad8f42a..0000000 --- a/doc/org/unitConverter/math/ExpressionParser.PriorityBinaryOperator.html +++ /dev/null @@ -1,425 +0,0 @@ - - - - - -ExpressionParser.PriorityBinaryOperator - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class ExpressionParser.PriorityBinaryOperator<T>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.ExpressionParser.PriorityBinaryOperator<T>
    • -
    -
  • -
-
-
    -
  • -
    -
    Type Parameters:
    -
    T - type of operand and result
    -
    -
    -
    All Implemented Interfaces:
    -
    java.lang.Comparable<ExpressionParser.PriorityBinaryOperator<T>>, java.util.function.BiFunction<T,​T,​T>, java.util.function.BinaryOperator<T>
    -
    -
    -
    Enclosing class:
    -
    ExpressionParser<T>
    -
    -
    -
    private abstract static class ExpressionParser.PriorityBinaryOperator<T>
    -extends java.lang.Object
    -implements java.util.function.BinaryOperator<T>, java.lang.Comparable<ExpressionParser.PriorityBinaryOperator<T>>
    -
    A binary operator with a priority field that determines which operators apply first.
    -
    -
    Since:
    -
    2019-03-17, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private intpriority -
      The operator's priority.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      PriorityBinaryOperator​(int priority) -
      Creates the PriorityBinaryOperator.
      -
      -
    • -
    -
    - -
    - -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        priority

        -
        private final int priority
        -
        The operator's priority. Higher-priority operators are applied before lower-priority operators
        -
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        PriorityBinaryOperator

        -
        public PriorityBinaryOperator​(int priority)
        -
        Creates the PriorityBinaryOperator.
        -
        -
        Parameters:
        -
        priority - operator's priority
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        compareTo

        -
        public int compareTo​(ExpressionParser.PriorityBinaryOperator<T> o)
        -
        Compares this object to another by priority. - -

        - -

        -
        -
        Specified by:
        -
        compareTo in interface java.lang.Comparable<T>
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getPriority

        -
        public final int getPriority()
        -
        -
        Returns:
        -
        priority
        -
        Since:
        -
        2019-03-22, v0.2.0
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/math/ExpressionParser.PriorityUnaryOperator.html b/doc/org/unitConverter/math/ExpressionParser.PriorityUnaryOperator.html deleted file mode 100644 index cddfb62..0000000 --- a/doc/org/unitConverter/math/ExpressionParser.PriorityUnaryOperator.html +++ /dev/null @@ -1,425 +0,0 @@ - - - - - -ExpressionParser.PriorityUnaryOperator - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class ExpressionParser.PriorityUnaryOperator<T>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.ExpressionParser.PriorityUnaryOperator<T>
    • -
    -
  • -
-
-
    -
  • -
    -
    Type Parameters:
    -
    T - type of operand and result
    -
    -
    -
    All Implemented Interfaces:
    -
    java.lang.Comparable<ExpressionParser.PriorityUnaryOperator<T>>, java.util.function.Function<T,​T>, java.util.function.UnaryOperator<T>
    -
    -
    -
    Enclosing class:
    -
    ExpressionParser<T>
    -
    -
    -
    private abstract static class ExpressionParser.PriorityUnaryOperator<T>
    -extends java.lang.Object
    -implements java.util.function.UnaryOperator<T>, java.lang.Comparable<ExpressionParser.PriorityUnaryOperator<T>>
    -
    A unary operator with a priority field that determines which operators apply first.
    -
    -
    Since:
    -
    2019-03-17, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private intpriority -
      The operator's priority.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      PriorityUnaryOperator​(int priority) -
      Creates the PriorityUnaryOperator.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      intcompareTo​(ExpressionParser.PriorityUnaryOperator<T> o) -
      Compares this object to another by priority.
      -
      intgetPriority() 
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.function.Function

        -andThen, apply, compose
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        priority

        -
        private final int priority
        -
        The operator's priority. Higher-priority operators are applied before lower-priority operators
        -
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        PriorityUnaryOperator

        -
        public PriorityUnaryOperator​(int priority)
        -
        Creates the PriorityUnaryOperator.
        -
        -
        Parameters:
        -
        priority - operator's priority
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        compareTo

        -
        public int compareTo​(ExpressionParser.PriorityUnaryOperator<T> o)
        -
        Compares this object to another by priority. - -

        - -

        -
        -
        Specified by:
        -
        compareTo in interface java.lang.Comparable<T>
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getPriority

        -
        public final int getPriority()
        -
        -
        Returns:
        -
        priority
        -
        Since:
        -
        2019-03-22, v0.2.0
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/math/ExpressionParser.TokenType.html b/doc/org/unitConverter/math/ExpressionParser.TokenType.html deleted file mode 100644 index 40c9d05..0000000 --- a/doc/org/unitConverter/math/ExpressionParser.TokenType.html +++ /dev/null @@ -1,445 +0,0 @@ - - - - - -ExpressionParser.TokenType - - - - - - - - - - - - - - - -
- -
- -
-
- -

Enum ExpressionParser.TokenType

-
-
-
    -
  • java.lang.Object
  • -
  • - -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.io.Serializable, java.lang.Comparable<ExpressionParser.TokenType>
    -
    -
    -
    Enclosing class:
    -
    ExpressionParser<T>
    -
    -
    -
    private static enum ExpressionParser.TokenType
    -extends java.lang.Enum<ExpressionParser.TokenType>
    -
    The types of tokens that are available.
    -
    -
    Since:
    -
    2019-03-14, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - - - -
      Constructors 
      ModifierConstructorDescription
      private TokenType() 
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - -
      All Methods Static Methods Concrete Methods 
      Modifier and TypeMethodDescription
      static ExpressionParser.TokenTypevalueOf​(java.lang.String name) -
      Returns the enum constant of this type with the specified name.
      -
      static ExpressionParser.TokenType[]values() -
      Returns an array containing the constants of this enum type, in -the order they are declared.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Enum

        -clone, compareTo, equals, finalize, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
      • -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -getClass, notify, notifyAll, wait, wait, wait
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        TokenType

        -
        private TokenType()
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        values

        -
        public static ExpressionParser.TokenType[] values()
        -
        Returns an array containing the constants of this enum type, in -the order they are declared. This method may be used to iterate -over the constants as follows: -
        -for (ExpressionParser.TokenType c : ExpressionParser.TokenType.values())
        -    System.out.println(c);
        -
        -
        -
        Returns:
        -
        an array containing the constants of this enum type, in the order they are declared
        -
        -
      • -
      - - - -
        -
      • -

        valueOf

        -
        public static ExpressionParser.TokenType valueOf​(java.lang.String name)
        -
        Returns the enum constant of this type with the specified name. -The string must match exactly an identifier used to declare an -enum constant in this type. (Extraneous whitespace characters are -not permitted.)
        -
        -
        Parameters:
        -
        name - the name of the enum constant to be returned.
        -
        Returns:
        -
        the enum constant with the specified name
        -
        Throws:
        -
        java.lang.IllegalArgumentException - if this enum type has no constant with the specified name
        -
        java.lang.NullPointerException - if the argument is null
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/math/ExpressionParser.html b/doc/org/unitConverter/math/ExpressionParser.html deleted file mode 100644 index 601bf35..0000000 --- a/doc/org/unitConverter/math/ExpressionParser.html +++ /dev/null @@ -1,349 +0,0 @@ - - - - - -ExpressionParser - - - - - - - - - - - - -
-
org.unitConverter.math
-

Class ExpressionParser<T>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.ExpressionParser<T>
    • -
    -
  • -
-
-
    -
  • -
    -
    Type Parameters:
    -
    T - type of object that exists in parsed expressions
    -
    -
    -
    -
    public final class ExpressionParser<T>
    -extends java.lang.Object
    -
    An object that can parse expressions with unary or binary operators.
    -
    -
    Since:
    -
    2019-03-14, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Nested Class Summary

      - - - - - - - - - - -
      Nested Classes 
      Modifier and TypeClass and Description
      static class ExpressionParser.Builder<T> -
      A builder that can create ExpressionParser<T> instances.
      -
      -
    • -
    - -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeField and Description
      static charCLOSING_BRACKET -
      The closing bracket.
      -
      static charOPENING_BRACKET -
      The opening bracket.
      -
      -
    • -
    - -
      -
    • - - -

      Method Summary

      - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      TparseExpression(java.lang.String expression) -
      Parses an expression.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
    • -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        OPENING_BRACKET

        -
        public static final char OPENING_BRACKET
        -
        The opening bracket.
        -
        -
        Since:
        -
        2019-03-22, v0.2.0
        -
        See Also:
        -
        Constant Field Values
        -
        -
      • -
      - - - -
        -
      • -

        CLOSING_BRACKET

        -
        public static final char CLOSING_BRACKET
        -
        The closing bracket.
        -
        -
        Since:
        -
        2019-03-22, v0.2.0
        -
        See Also:
        -
        Constant Field Values
        -
        -
      • -
      -
    • -
    - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        parseExpression

        -
        public T parseExpression(java.lang.String expression)
        -
        Parses an expression.
        -
        -
        Parameters:
        -
        expression - expression to parse
        -
        Returns:
        -
        result
        -
        Throws:
        -
        java.lang.NullPointerException - if expression is null
        -
        Since:
        -
        2019-03-14, v0.2.0
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/math/ExpressionParserTest.html b/doc/org/unitConverter/math/ExpressionParserTest.html deleted file mode 100644 index e39075d..0000000 --- a/doc/org/unitConverter/math/ExpressionParserTest.html +++ /dev/null @@ -1,360 +0,0 @@ - - - - - -ExpressionParserTest - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class ExpressionParserTest

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.ExpressionParserTest
    • -
    -
  • -
-
-
    -
  • -
    -
    class ExpressionParserTest
    -extends java.lang.Object
    -
    A test for the ExpressionParser class. This is NOT part of this program's public API.
    -
    -
    Since:
    -
    2019-03-22, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
- -
-
-
- - - - diff --git a/doc/org/unitConverter/math/ObjectProduct.html b/doc/org/unitConverter/math/ObjectProduct.html deleted file mode 100644 index 08f8e8f..0000000 --- a/doc/org/unitConverter/math/ObjectProduct.html +++ /dev/null @@ -1,553 +0,0 @@ - - - - - -ObjectProduct - - - - - - - - - - - - -
-
org.unitConverter.math
-

Class ObjectProduct<T>

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.ObjectProduct<T>
    • -
    -
  • -
-
-
    -
  • -
    -
    -
    public final class ObjectProduct<T>
    -extends java.lang.Object
    -
    An immutable product of multiple objects of a type, such as base units. The objects can be multiplied and - exponentiated.
    -
    -
    Since:
    -
    2019-10-16
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        empty

        -
        public static final <T> ObjectProduct<T> empty()
        -
        Returns an empty ObjectProduct of a certain type
        -
        -
        Type Parameters:
        -
        T - type of objects that can be multiplied
        -
        Returns:
        -
        empty product
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        fromExponentMapping

        -
        public static final <T> ObjectProduct<T> fromExponentMapping(java.util.Map<T,java.lang.Integer> map)
        -
        Gets an ObjectProduct from an object-to-integer mapping
        -
        -
        Type Parameters:
        -
        T - type of object in product
        -
        Parameters:
        -
        map - map mapping objects to exponents
        -
        Returns:
        -
        object product
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - - - -
        -
      • -

        oneOf

        -
        public static final <T> ObjectProduct<T> oneOf(T object)
        -
        Gets an ObjectProduct that has one of the inputted argument, and nothing else.
        -
        -
        Parameters:
        -
        object - object that will be in the product
        -
        Returns:
        -
        product
        -
        Throws:
        -
        java.lang.NullPointerException - if object is null
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        dividedBy

        -
        public ObjectProduct<T> dividedBy(ObjectProduct<T> other)
        -
        Calculates the quotient of two products
        -
        -
        Parameters:
        -
        other - other product
        -
        Returns:
        -
        quotient of two products
        -
        Throws:
        -
        java.lang.NullPointerException - if other is null
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        equals

        -
        public boolean equals(java.lang.Object obj)
        -
        -
        Overrides:
        -
        equals in class java.lang.Object
        -
        -
      • -
      - - - -
        -
      • -

        exponentMap

        -
        public java.util.Map<T,java.lang.Integer> exponentMap()
        -
        -
        Returns:
        -
        immutable map mapping objects to exponents
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        getBaseSet

        -
        public final java.util.Set<T> getBaseSet()
        -
        -
        Returns:
        -
        a set of all of the base objects with non-zero exponents that make up this dimension.
        -
        Since:
        -
        2018-12-12, v0.1.0
        -
        -
      • -
      - - - - - -
        -
      • -

        getExponent

        -
        public int getExponent(T dimension)
        -
        Gets the exponent for a specific dimension.
        -
        -
        Parameters:
        -
        dimension - dimension to check
        -
        Returns:
        -
        exponent for that dimension
        -
        Since:
        -
        2018-12-12, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        hashCode

        -
        public int hashCode()
        -
        -
        Overrides:
        -
        hashCode in class java.lang.Object
        -
        -
      • -
      - - - -
        -
      • -

        isSingleObject

        -
        public boolean isSingleObject()
        -
        -
        Returns:
        -
        true if this product is a single object, i.e. it has one exponent of one and no other nonzero exponents
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        times

        -
        public ObjectProduct<T> times(ObjectProduct<T> other)
        -
        Multiplies this product by another
        -
        -
        Parameters:
        -
        other - other product
        -
        Returns:
        -
        product of two products
        -
        Throws:
        -
        java.lang.NullPointerException - if other is null
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        toExponent

        -
        public ObjectProduct<T> toExponent(int exponent)
        -
        Returns this product, but to an exponent
        -
        -
        Parameters:
        -
        exponent - exponent
        -
        Returns:
        -
        result of exponentiation
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        Converts this product to a string using the objects' Object.toString() method. If objects have a long - toString representation, it is recommended to use toString(Function) instead to shorten the returned - string. - -

        -

        -
        -
        Overrides:
        -
        toString in class java.lang.Object
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString(java.util.function.Function<T,java.lang.String> objectToString)
        -
        Converts this product to a string. The objects that make up this product are represented by - objectToString
        -
        -
        Parameters:
        -
        objectToString - function to convert objects to strings
        -
        Returns:
        -
        string representation of product
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/math/ObjectProductTest.html b/doc/org/unitConverter/math/ObjectProductTest.html deleted file mode 100644 index 2fb1aa4..0000000 --- a/doc/org/unitConverter/math/ObjectProductTest.html +++ /dev/null @@ -1,366 +0,0 @@ - - - - - -ObjectProductTest - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class ObjectProductTest

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.math.ObjectProductTest
    • -
    -
  • -
-
-
    -
  • -
    -
    class ObjectProductTest
    -extends java.lang.Object
    -
    Tests for ObjectProduct using BaseDimension as a test object. This is NOT part of this program's public API.
    -
    -
    Since:
    -
    2018-12-12, v0.1.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      ObjectProductTest() 
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      voidtestEquals() -
      Tests UnitDimension#equals
      -
      voidtestExponents() -
      Tests UnitDimension's exponentiation
      -
      voidtestMultiplicationAndDivision() -
      Tests UnitDimension's multiplication and division.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        ObjectProductTest

        -
        ObjectProductTest()
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        testEquals

        -
        @Test
        -public void testEquals()
        -
        Tests UnitDimension#equals
        -
        -
        Since:
        -
        2018-12-12, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        testExponents

        -
        @Test
        -public void testExponents()
        -
        Tests UnitDimension's exponentiation
        -
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        testMultiplicationAndDivision

        -
        @Test
        -public void testMultiplicationAndDivision()
        -
        Tests UnitDimension's multiplication and division.
        -
        -
        Since:
        -
        2018-12-12, v0.1.0
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceCollection.html b/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceCollection.html deleted file mode 100644 index b8b2122..0000000 --- a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceCollection.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceCollection - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceCollection

-
-
No usage of org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceCollection
-
- - - diff --git a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceIterator.html b/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceIterator.html deleted file mode 100644 index c521457..0000000 --- a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceIterator.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceIterator - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceIterator

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceMap.html b/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceMap.html deleted file mode 100644 index fe3a0ec..0000000 --- a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceMap.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceMap - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceMap

-
-
No usage of org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceMap
-
- - - diff --git a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceSet.html b/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceSet.html deleted file mode 100644 index e35104b..0000000 --- a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.ConditionalExistenceSet.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceSet - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceSet

-
-
No usage of org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceSet
-
- - - diff --git a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.html b/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.html deleted file mode 100644 index d56f5bf..0000000 --- a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollections.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ConditionalExistenceCollections - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.math.ConditionalExistenceCollections

-
-
No usage of org.unitConverter.math.ConditionalExistenceCollections
- - - - - - diff --git a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollectionsTest.html b/doc/org/unitConverter/math/class-use/ConditionalExistenceCollectionsTest.html deleted file mode 100644 index 4fa2386..0000000 --- a/doc/org/unitConverter/math/class-use/ConditionalExistenceCollectionsTest.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ConditionalExistenceCollectionsTest - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.math.ConditionalExistenceCollectionsTest

-
-
No usage of org.unitConverter.math.ConditionalExistenceCollectionsTest
-
- - - diff --git a/doc/org/unitConverter/math/class-use/DecimalComparison.html b/doc/org/unitConverter/math/class-use/DecimalComparison.html deleted file mode 100644 index 0090edb..0000000 --- a/doc/org/unitConverter/math/class-use/DecimalComparison.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.DecimalComparison - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.math.DecimalComparison

-
-
No usage of org.unitConverter.math.DecimalComparison
- - - - - - diff --git a/doc/org/unitConverter/math/class-use/ExpressionParser.Builder.html b/doc/org/unitConverter/math/class-use/ExpressionParser.Builder.html deleted file mode 100644 index fdedeca..0000000 --- a/doc/org/unitConverter/math/class-use/ExpressionParser.Builder.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ExpressionParser.Builder - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.math.ExpressionParser.Builder

-
-
- -
- - - - - - diff --git a/doc/org/unitConverter/math/class-use/ExpressionParser.PriorityBinaryOperator.html b/doc/org/unitConverter/math/class-use/ExpressionParser.PriorityBinaryOperator.html deleted file mode 100644 index 86c2daf..0000000 --- a/doc/org/unitConverter/math/class-use/ExpressionParser.PriorityBinaryOperator.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ExpressionParser.PriorityBinaryOperator - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.math.ExpressionParser.PriorityBinaryOperator

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/math/class-use/ExpressionParser.PriorityUnaryOperator.html b/doc/org/unitConverter/math/class-use/ExpressionParser.PriorityUnaryOperator.html deleted file mode 100644 index 1d8f896..0000000 --- a/doc/org/unitConverter/math/class-use/ExpressionParser.PriorityUnaryOperator.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ExpressionParser.PriorityUnaryOperator - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.math.ExpressionParser.PriorityUnaryOperator

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/math/class-use/ExpressionParser.TokenType.html b/doc/org/unitConverter/math/class-use/ExpressionParser.TokenType.html deleted file mode 100644 index 7932193..0000000 --- a/doc/org/unitConverter/math/class-use/ExpressionParser.TokenType.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ExpressionParser.TokenType - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.math.ExpressionParser.TokenType

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/math/class-use/ExpressionParser.html b/doc/org/unitConverter/math/class-use/ExpressionParser.html deleted file mode 100644 index 2e75c83..0000000 --- a/doc/org/unitConverter/math/class-use/ExpressionParser.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ExpressionParser - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.math.ExpressionParser

-
-
- -
- - - - - - diff --git a/doc/org/unitConverter/math/class-use/ExpressionParserTest.html b/doc/org/unitConverter/math/class-use/ExpressionParserTest.html deleted file mode 100644 index cdee52e..0000000 --- a/doc/org/unitConverter/math/class-use/ExpressionParserTest.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ExpressionParserTest - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.math.ExpressionParserTest

-
-
No usage of org.unitConverter.math.ExpressionParserTest
-
- - - diff --git a/doc/org/unitConverter/math/class-use/ObjectProduct.html b/doc/org/unitConverter/math/class-use/ObjectProduct.html deleted file mode 100644 index 1f326fa..0000000 --- a/doc/org/unitConverter/math/class-use/ObjectProduct.html +++ /dev/null @@ -1,515 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ObjectProduct - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.math.ObjectProduct

-
-
- -
- - - - - - diff --git a/doc/org/unitConverter/math/class-use/ObjectProductTest.html b/doc/org/unitConverter/math/class-use/ObjectProductTest.html deleted file mode 100644 index bb7eca6..0000000 --- a/doc/org/unitConverter/math/class-use/ObjectProductTest.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.math.ObjectProductTest - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.math.ObjectProductTest

-
-
No usage of org.unitConverter.math.ObjectProductTest
-
- - - diff --git a/doc/org/unitConverter/math/package-frame.html b/doc/org/unitConverter/math/package-frame.html deleted file mode 100644 index 46d3edd..0000000 --- a/doc/org/unitConverter/math/package-frame.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - -org.unitConverter.math - - - - - -

org.unitConverter.math

- - - diff --git a/doc/org/unitConverter/math/package-summary.html b/doc/org/unitConverter/math/package-summary.html deleted file mode 100644 index ea8dec5..0000000 --- a/doc/org/unitConverter/math/package-summary.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - -org.unitConverter.math - - - - - - - - - - - -
-

Package org.unitConverter.math

-
-
Supplementary classes that are not related to units, but are necessary for their function.
-
-

See: Description

-
-
-
    -
  • - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Class Summary 
    ClassDescription
    ConditionalExistenceCollections -
    Elements in these wrapper collections only exist if they pass a condition.
    -
    DecimalComparison -
    A class that contains methods to compare float and double values.
    -
    ExpressionParser<T> -
    An object that can parse expressions with unary or binary operators.
    -
    ExpressionParser.Builder<T> -
    A builder that can create ExpressionParser<T> instances.
    -
    ObjectProduct<T> -
    An immutable product of multiple objects of a type, such as base units.
    -
    -
  • -
- - - -

Package org.unitConverter.math Description

-
Supplementary classes that are not related to units, but are necessary for their function.
-
-
Since:
-
2019-03-14, v0.2.0
-
Author:
-
Adrien Hopkins
-
-
- - - - - - diff --git a/doc/org/unitConverter/math/package-tree.html b/doc/org/unitConverter/math/package-tree.html deleted file mode 100644 index 116fe4e..0000000 --- a/doc/org/unitConverter/math/package-tree.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - -org.unitConverter.math Class Hierarchy - - - - - - - - - - - -
-

Hierarchy For Package org.unitConverter.math

-Package Hierarchies: - -
-
-

Class Hierarchy

- -
- - - - - - diff --git a/doc/org/unitConverter/math/package-use.html b/doc/org/unitConverter/math/package-use.html deleted file mode 100644 index 35075d2..0000000 --- a/doc/org/unitConverter/math/package-use.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - -Uses of Package org.unitConverter.math - - - - - - - - - - - -
-

Uses of Package
org.unitConverter.math

-
-
- -
- - - - - - diff --git a/doc/org/unitConverter/package-frame.html b/doc/org/unitConverter/package-frame.html deleted file mode 100644 index 845bd90..0000000 --- a/doc/org/unitConverter/package-frame.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - -org.unitConverter - - - - - -

org.unitConverter

- - diff --git a/doc/org/unitConverter/package-summary.html b/doc/org/unitConverter/package-summary.html deleted file mode 100644 index 3c32a6e..0000000 --- a/doc/org/unitConverter/package-summary.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - -org.unitConverter - - - - - - - - - - - -
-

Package org.unitConverter

-
-
A program that converts units.
-
-

See: Description

-
-
- - -

Package org.unitConverter Description

-
A program that converts units.
-
-
Since:
-
2019-01-25
-
Version:
-
v0.2.0
-
Author:
-
Adrien Hopkins
-
-
- - - - - - diff --git a/doc/org/unitConverter/package-tree.html b/doc/org/unitConverter/package-tree.html deleted file mode 100644 index 1f5a0a0..0000000 --- a/doc/org/unitConverter/package-tree.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - -org.unitConverter Class Hierarchy - - - - - - - - - - - -
-

Hierarchy For Package org.unitConverter

-Package Hierarchies: - -
- - - - - - diff --git a/doc/org/unitConverter/package-use.html b/doc/org/unitConverter/package-use.html deleted file mode 100644 index b6dcd18..0000000 --- a/doc/org/unitConverter/package-use.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Package org.unitConverter - - - - - - - - - - - -
-

Uses of Package
org.unitConverter

-
-
No usage of org.unitConverter
- - - - - - diff --git a/doc/org/unitConverter/unit/BaseDimension.html b/doc/org/unitConverter/unit/BaseDimension.html deleted file mode 100644 index c5c27c7..0000000 --- a/doc/org/unitConverter/unit/BaseDimension.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - - -BaseDimension - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class BaseDimension

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.BaseDimension
    • -
    -
  • -
-
-
    -
  • -
    -
    -
    public final class BaseDimension
    -extends java.lang.Object
    -
    A dimension that defines a BaseUnit
    -
    -
    Since:
    -
    2019-10-16
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      java.lang.StringgetName() 
      java.lang.StringgetSymbol() 
      java.lang.StringtoString() 
      static BaseDimensionvalueOf(java.lang.String name, - java.lang.String symbol) -
      Gets a BaseDimension with the provided name and symbol.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • -
      -
    • -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        valueOf

        -
        public static BaseDimension valueOf(java.lang.String name,
        -                                    java.lang.String symbol)
        -
        Gets a BaseDimension with the provided name and symbol.
        -
        -
        Parameters:
        -
        name - name of dimension
        -
        symbol - symbol used for dimension
        -
        Returns:
        -
        dimension
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        getName

        -
        public final java.lang.String getName()
        -
        -
        Returns:
        -
        name
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        getSymbol

        -
        public final java.lang.String getSymbol()
        -
        -
        Returns:
        -
        symbol
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        -
        Overrides:
        -
        toString in class java.lang.Object
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/BaseUnit.html b/doc/org/unitConverter/unit/BaseUnit.html deleted file mode 100644 index 56fb19c..0000000 --- a/doc/org/unitConverter/unit/BaseUnit.html +++ /dev/null @@ -1,452 +0,0 @@ - - - - - -BaseUnit - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class BaseUnit

-
-
- -
-
    -
  • -
    -
    -
    public final class BaseUnit
    -extends Unit
    -
    A unit that other units are defined by. -

    - Note that BaseUnits must have names and symbols. This is because they are used for toString code. Therefore, - the Optionals provided by Unit.getPrimaryName() and Unit.getSymbol() will always contain a value.

    -
    -
    Since:
    -
    2019-10-16
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        valueOf

        -
        public static BaseUnit valueOf(BaseDimension dimension,
        -                               java.lang.String name,
        -                               java.lang.String symbol)
        -
        Gets a base unit from the dimension it measures, its name and its symbol.
        -
        -
        Parameters:
        -
        dimension - dimension measured by this unit
        -
        name - name of unit
        -
        symbol - symbol of unit
        -
        Returns:
        -
        base unit
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        valueOf

        -
        public static BaseUnit valueOf(BaseDimension dimension,
        -                               java.lang.String name,
        -                               java.lang.String symbol,
        -                               java.util.Set<java.lang.String> otherNames)
        -
        Gets a base unit from the dimension it measures, its name and its symbol.
        -
        -
        Parameters:
        -
        dimension - dimension measured by this unit
        -
        name - name of unit
        -
        symbol - symbol of unit
        -
        Returns:
        -
        base unit
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        asLinearUnit

        -
        public LinearUnit asLinearUnit()
        -
        Returns a LinearUnit with this unit as a base and a conversion factor of 1. This operation must be done - in order to allow units to be created with operations.
        -
        -
        Returns:
        -
        this unit as a LinearUnit
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        convertFromBase

        -
        public double convertFromBase(double value)
        -
        Description copied from class: Unit
        -
        Converts from a value expressed in this unit's base unit to a value expressed in this unit. -

        - This must be the inverse of convertToBase, so convertFromBase(convertToBase(value)) must be equal - to value for any value, ignoring precision loss by roundoff error. -

        -

        - If this unit is a base unit, this method should return value. -

        -
        -
        Specified by:
        -
        convertFromBase in class Unit
        -
        Parameters:
        -
        value - value expressed in base unit
        -
        Returns:
        -
        value expressed in this unit
        -
        -
      • -
      - - - -
        -
      • -

        convertToBase

        -
        public double convertToBase(double value)
        -
        Description copied from class: Unit
        -
        Converts from a value expressed in this unit to a value expressed in this unit's base unit. -

        - This must be the inverse of convertFromBase, so convertToBase(convertFromBase(value)) must be - equal to value for any value, ignoring precision loss by roundoff error. -

        -

        - If this unit is a base unit, this method should return value. -

        -
        -
        Specified by:
        -
        convertToBase in class Unit
        -
        Parameters:
        -
        value - value expressed in this unit
        -
        Returns:
        -
        value expressed in base unit
        -
        -
      • -
      - - - -
        -
      • -

        getBaseDimension

        -
        public final BaseDimension getBaseDimension()
        -
        -
        Returns:
        -
        dimension
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        -
        Overrides:
        -
        toString in class Unit
        -
        -
      • -
      - - - -
        -
      • -

        withName

        -
        public BaseUnit withName(NameSymbol ns)
        -
        -
        Overrides:
        -
        withName in class Unit
        -
        Parameters:
        -
        ns - name(s) and symbol to use
        -
        Returns:
        -
        a copy of this unit with provided name(s) and symbol
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/BritishImperial.Area.html b/doc/org/unitConverter/unit/BritishImperial.Area.html deleted file mode 100644 index 28b404b..0000000 --- a/doc/org/unitConverter/unit/BritishImperial.Area.html +++ /dev/null @@ -1,349 +0,0 @@ - - - - - -BritishImperial.Area - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class BritishImperial.Area

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.BritishImperial.Area
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    BritishImperial
    -
    -
    -
    -
    public static final class BritishImperial.Area
    -extends java.lang.Object
    -
    Imperial units that measure area
    -
    -
    Since:
    -
    2019-11-08
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - - - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        Area

        -
        public Area()
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/BritishImperial.Length.html b/doc/org/unitConverter/unit/BritishImperial.Length.html deleted file mode 100644 index f1235a8..0000000 --- a/doc/org/unitConverter/unit/BritishImperial.Length.html +++ /dev/null @@ -1,443 +0,0 @@ - - - - - -BritishImperial.Length - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class BritishImperial.Length

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.BritishImperial.Length
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    BritishImperial
    -
    -
    -
    -
    public static final class BritishImperial.Length
    -extends java.lang.Object
    -
    Imperial units that measure length
    -
    -
    Since:
    -
    2019-10-28
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - - - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        Length

        -
        public Length()
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/BritishImperial.Mass.html b/doc/org/unitConverter/unit/BritishImperial.Mass.html deleted file mode 100644 index ba6d965..0000000 --- a/doc/org/unitConverter/unit/BritishImperial.Mass.html +++ /dev/null @@ -1,388 +0,0 @@ - - - - - -BritishImperial.Mass - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class BritishImperial.Mass

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.BritishImperial.Mass
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    BritishImperial
    -
    -
    -
    -
    public static final class BritishImperial.Mass
    -extends java.lang.Object
    -
    British Imperial units that measure mass.
    -
    -
    Since:
    -
    2019-11-08
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
- -
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/BritishImperial.Volume.html b/doc/org/unitConverter/unit/BritishImperial.Volume.html deleted file mode 100644 index dc8d76a..0000000 --- a/doc/org/unitConverter/unit/BritishImperial.Volume.html +++ /dev/null @@ -1,414 +0,0 @@ - - - - - -BritishImperial.Volume - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class BritishImperial.Volume

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.BritishImperial.Volume
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    BritishImperial
    -
    -
    -
    -
    public static final class BritishImperial.Volume
    -extends java.lang.Object
    -
    British Imperial units that measure volume
    -
    -
    Since:
    -
    2019-11-08
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
- -
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/BritishImperial.html b/doc/org/unitConverter/unit/BritishImperial.html deleted file mode 100644 index 2f63c1f..0000000 --- a/doc/org/unitConverter/unit/BritishImperial.html +++ /dev/null @@ -1,384 +0,0 @@ - - - - - -BritishImperial - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class BritishImperial

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.BritishImperial
    • -
    -
  • -
-
-
    -
  • -
    -
    -
    public final class BritishImperial
    -extends java.lang.Object
    -
    A static utility class that contains units in the British Imperial system.
    -
    -
    Since:
    -
    2019-10-21
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        OUNCE_FORCE

        -
        public static final LinearUnit OUNCE_FORCE
        -
      • -
      - - - -
        -
      • -

        POUND_FORCE

        -
        public static final LinearUnit POUND_FORCE
        -
      • -
      - - - -
        -
      • -

        BRITISH_THERMAL_UNIT

        -
        public static final LinearUnit BRITISH_THERMAL_UNIT
        -
      • -
      - - - -
        -
      • -

        CALORIE

        -
        public static final LinearUnit CALORIE
        -
      • -
      - - - -
        -
      • -

        KILOCALORIE

        -
        public static final LinearUnit KILOCALORIE
        -
      • -
      - - - -
        -
      • -

        FAHRENHEIT

        -
        public static final Unit FAHRENHEIT
        -
      • -
      -
    • -
    - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        BritishImperial

        -
        public BritishImperial()
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/FunctionalUnit.html b/doc/org/unitConverter/unit/FunctionalUnit.html deleted file mode 100644 index fc0d446..0000000 --- a/doc/org/unitConverter/unit/FunctionalUnit.html +++ /dev/null @@ -1,504 +0,0 @@ - - - - - -FunctionalUnit - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class FunctionalUnit

-
-
- -
-
    -
  • -
    -
    final class FunctionalUnit
    -extends Unit
    -
    A unit that uses functional objects to convert to and from its base.
    -
    -
    Since:
    -
    2019-05-22
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private java.util.function.DoubleUnaryOperatorconverterFrom -
      A function that accepts a value expressed in the unit's base and returns that value expressed in this unit.
      -
      private java.util.function.DoubleUnaryOperatorconverterTo -
      A function that accepts a value expressed in the unit and returns that value expressed in the unit's base.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - - - -
      Constructors 
      ModifierConstructorDescription
      private FunctionalUnit​(ObjectProduct<BaseUnit> base, - java.util.function.DoubleUnaryOperator converterFrom, - java.util.function.DoubleUnaryOperator converterTo) -
      Creates the FunctionalUnit.
      -
      -
    • -
    -
    - -
    - -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        converterFrom

        -
        private final java.util.function.DoubleUnaryOperator converterFrom
        -
        A function that accepts a value expressed in the unit's base and returns that value expressed in this unit.
        -
        -
        Since:
        -
        2019-05-22
        -
        -
      • -
      - - - -
        -
      • -

        converterTo

        -
        private final java.util.function.DoubleUnaryOperator converterTo
        -
        A function that accepts a value expressed in the unit and returns that value expressed in the unit's base.
        -
        -
        Since:
        -
        2019-05-22
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        FunctionalUnit

        -
        private FunctionalUnit​(ObjectProduct<BaseUnit> base,
        -                       java.util.function.DoubleUnaryOperator converterFrom,
        -                       java.util.function.DoubleUnaryOperator converterTo)
        -
        Creates the FunctionalUnit.
        -
        -
        Parameters:
        -
        base - unit's base
        -
        converterFrom - function that accepts a value expressed in the unit's base and returns that value expressed in this - unit.
        -
        converterTo - function that accepts a value expressed in the unit and returns that value expressed in the unit's - base.
        -
        Throws:
        -
        java.lang.NullPointerException - if any argument is null
        -
        Since:
        -
        2019-05-22
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        valueOf

        -
        public static FunctionalUnit valueOf​(ObjectProduct<BaseUnit> base,
        -                                     java.util.function.DoubleUnaryOperator converterFrom,
        -                                     java.util.function.DoubleUnaryOperator converterTo)
        -
        Returns a unit from its base and the functions it uses to convert to and from its base.
        -
        -
        Parameters:
        -
        base - unit's base
        -
        converterFrom - function that accepts a value expressed in the unit's base and returns that value expressed in this - unit.
        -
        converterTo - function that accepts a value expressed in the unit and returns that value expressed in the unit's - base.
        -
        Returns:
        -
        a unit that uses the provided functions to convert.
        -
        Throws:
        -
        java.lang.NullPointerException - if any argument is null
        -
        Since:
        -
        2019-05-22
        -
        -
      • -
      - - - -
        -
      • -

        convertFromBase

        -
        public double convertFromBase​(double value)
        -
        Description copied from class: Unit
        -
        Converts from a value expressed in this unit's base unit to a value expressed in this unit. -

        - This must be the inverse of convertToBase, so convertFromBase(convertToBase(value)) must be equal - to value for any value, ignoring precision loss by roundoff error. -

        -

        - If this unit is a base unit, this method should return value. -

        -
        -
        Specified by:
        -
        convertFromBase in class Unit
        -
        Parameters:
        -
        value - value expressed in base unit
        -
        Returns:
        -
        value expressed in this unit
        -
        -
      • -
      - - - -
        -
      • -

        convertToBase

        -
        public double convertToBase​(double value)
        -
        Description copied from class: Unit
        -
        Converts from a value expressed in this unit to a value expressed in this unit's base unit. -

        - This must be the inverse of convertFromBase, so convertToBase(convertFromBase(value)) must be - equal to value for any value, ignoring precision loss by roundoff error. -

        -

        - If this unit is a base unit, this method should return value. -

        -
        -
        Specified by:
        -
        convertToBase in class Unit
        -
        Parameters:
        -
        value - value expressed in this unit
        -
        Returns:
        -
        value expressed in base unit
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/unit/LinearUnit.html b/doc/org/unitConverter/unit/LinearUnit.html deleted file mode 100644 index 1e1fce2..0000000 --- a/doc/org/unitConverter/unit/LinearUnit.html +++ /dev/null @@ -1,800 +0,0 @@ - - - - - -LinearUnit - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class LinearUnit

-
-
- -
-
    -
  • -
    -
    -
    public final class LinearUnit
    -extends Unit
    -
    A unit that can be expressed as a product of its base and a number. For example, kilometres, inches and pounds.
    -
    -
    Since:
    -
    2019-10-16
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        fromUnitValue

        -
        public static LinearUnit fromUnitValue(Unit unit,
        -                                       double value)
        -
        Gets a LinearUnit from a unit and a value. For example, converts '59 °F' to a linear unit with the value - of '288.15 K'
        -
        -
        Parameters:
        -
        unit - unit to convert
        -
        value - value to convert
        -
        Returns:
        -
        value expressed as a LinearUnit
        -
        Throws:
        -
        java.lang.NullPointerException - if unit is null
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        fromUnitValue

        -
        public static LinearUnit fromUnitValue(Unit unit,
        -                                       double value,
        -                                       NameSymbol ns)
        -
        Gets a LinearUnit from a unit and a value. For example, converts '59 °F' to a linear unit with the value - of '288.15 K'
        -
        -
        Parameters:
        -
        unit - unit to convert
        -
        value - value to convert
        -
        ns - name(s) and symbol of unit
        -
        Returns:
        -
        value expressed as a LinearUnit
        -
        Throws:
        -
        java.lang.NullPointerException - if unit or ns is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        valueOf

        -
        public static LinearUnit valueOf(ObjectProduct<BaseUnit> unitBase,
        -                                 double conversionFactor)
        -
        Gets a LinearUnit from a unit base and a conversion factor. In other words, gets the product of - unitBase and conversionFactor, expressed as a LinearUnit.
        -
        -
        Parameters:
        -
        unitBase - unit base to multiply by
        -
        conversionFactor - number to multiply base by
        -
        Returns:
        -
        product of base and conversion factor
        -
        Throws:
        -
        java.lang.NullPointerException - if unitBase is null
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        valueOf

        -
        public static LinearUnit valueOf(ObjectProduct<BaseUnit> unitBase,
        -                                 double conversionFactor,
        -                                 NameSymbol ns)
        -
        Gets a LinearUnit from a unit base and a conversion factor. In other words, gets the product of - unitBase and conversionFactor, expressed as a LinearUnit.
        -
        -
        Parameters:
        -
        unitBase - unit base to multiply by
        -
        conversionFactor - number to multiply base by
        -
        ns - name(s) and symbol of unit
        -
        Returns:
        -
        product of base and conversion factor
        -
        Throws:
        -
        java.lang.NullPointerException - if unitBase is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        convertFromBase

        -
        protected double convertFromBase(double value)
        -
        Converts from a value expressed in this unit's base unit to a value expressed in this unit. -

        - This must be the inverse of convertToBase, so convertFromBase(convertToBase(value)) must be equal - to value for any value, ignoring precision loss by roundoff error. -

        -

        - If this unit is a base unit, this method should return value. -

        - - Converts by dividing by conversionFactor
        -
        -
        Specified by:
        -
        convertFromBase in class Unit
        -
        Parameters:
        -
        value - value expressed in base unit
        -
        Returns:
        -
        value expressed in this unit
        -
        -
      • -
      - - - -
        -
      • -

        convertToBase

        -
        protected double convertToBase(double value)
        -
        Converts from a value expressed in this unit to a value expressed in this unit's base unit. -

        - This must be the inverse of convertFromBase, so convertToBase(convertFromBase(value)) must be - equal to value for any value, ignoring precision loss by roundoff error. -

        -

        - If this unit is a base unit, this method should return value. -

        - - Converts by multiplying by conversionFactor
        -
        -
        Specified by:
        -
        convertToBase in class Unit
        -
        Parameters:
        -
        value - value expressed in this unit
        -
        Returns:
        -
        value expressed in base unit
        -
        -
      • -
      - - - -
        -
      • -

        dividedBy

        -
        public LinearUnit dividedBy(double divisor)
        -
        Divides this unit by a scalar.
        -
        -
        Parameters:
        -
        divisor - scalar to divide by
        -
        Returns:
        -
        quotient
        -
        Since:
        -
        2018-12-23, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        dividedBy

        -
        public LinearUnit dividedBy(LinearUnit divisor)
        -
        Returns the quotient of this unit and another.
        -
        -
        Parameters:
        -
        divisor - unit to divide by
        -
        Returns:
        -
        quotient of two units
        -
        Throws:
        -
        java.lang.NullPointerException - if divisor is null
        -
        Since:
        -
        2018-12-22, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        equals

        -
        public boolean equals(java.lang.Object obj)
        -
        - - Uses the base and conversion factor of units to test for equality.
        -
        -
        Overrides:
        -
        equals in class java.lang.Object
        -
        -
      • -
      - - - -
        -
      • -

        getConversionFactor

        -
        public double getConversionFactor()
        -
        -
        Returns:
        -
        conversion factor
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        hashCode

        -
        public int hashCode()
        -
        - - Uses the base and conversion factor to compute a hash code.
        -
        -
        Overrides:
        -
        hashCode in class java.lang.Object
        -
        -
      • -
      - - - -
        -
      • -

        isBase

        -
        public boolean isBase()
        -
        -
        Returns:
        -
        whether this unit is equivalent to a BaseUnit (i.e. there is a BaseUnit b where - b.asLinearUnit().equals(this) returns true.)
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        isCoherent

        -
        public boolean isCoherent()
        -
        -
        Returns:
        -
        whether this unit is coherent (i.e. has conversion factor 1)
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        minus

        -
        public LinearUnit minus(LinearUnit subtrahendend)
        -
        Returns the difference of this unit and another. -

        - Two units can be subtracted if they have the same base. Note that Unit.canConvertTo(org.unitConverter.unit.Unit) can be used to determine - this. If subtrahend does not meet this condition, an IllegalArgumentException will be thrown. -

        -
        -
        Parameters:
        -
        subtrahend - unit to subtract
        -
        Returns:
        -
        difference of units
        -
        Throws:
        -
        java.lang.IllegalArgumentException - if subtrahend is not compatible for subtraction as described above
        -
        java.lang.NullPointerException - if subtrahend is null
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        plus

        -
        public LinearUnit plus(LinearUnit addend)
        -
        Returns the sum of this unit and another. -

        - Two units can be added if they have the same base. Note that Unit.canConvertTo(org.unitConverter.unit.Unit) can be used to determine this. - If addend does not meet this condition, an IllegalArgumentException will be thrown. -

        -
        -
        Parameters:
        -
        addend - unit to add
        -
        Returns:
        -
        sum of units
        -
        Throws:
        -
        java.lang.IllegalArgumentException - if addend is not compatible for addition as described above
        -
        java.lang.NullPointerException - if addend is null
        -
        Since:
        -
        2019-03-17, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        times

        -
        public LinearUnit times(double multiplier)
        -
        Multiplies this unit by a scalar.
        -
        -
        Parameters:
        -
        multiplier - scalar to multiply by
        -
        Returns:
        -
        product
        -
        Since:
        -
        2018-12-23, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        times

        -
        public LinearUnit times(LinearUnit multiplier)
        -
        Returns the product of this unit and another.
        -
        -
        Parameters:
        -
        multiplier - unit to multiply by
        -
        Returns:
        -
        product of two units
        -
        Throws:
        -
        java.lang.NullPointerException - if multiplier is null
        -
        Since:
        -
        2018-12-22, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        toExponent

        -
        public LinearUnit toExponent(int exponent)
        -
        Returns this unit but to an exponent.
        -
        -
        Parameters:
        -
        exponent - exponent to exponentiate unit to
        -
        Returns:
        -
        exponentiated unit
        -
        Since:
        -
        2019-01-15, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        -
        Overrides:
        -
        toString in class Unit
        -
        Returns:
        -
        a string providing a definition of this unit
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        withName

        -
        public LinearUnit withName(NameSymbol ns)
        -
        -
        Overrides:
        -
        withName in class Unit
        -
        Parameters:
        -
        ns - name(s) and symbol to use
        -
        Returns:
        -
        a copy of this unit with provided name(s) and symbol
        -
        -
      • -
      - - - -
        -
      • -

        withPrefix

        -
        public LinearUnit withPrefix(UnitPrefix prefix)
        -
        Returns the result of applying prefix to this unit. -

        - If this unit and the provided prefix have a primary name, the returned unit will have a primary name (prefix's - name + unit's name).
        - If this unit and the provided prefix have a symbol, the returned unit will have a symbol.
        - This method ignores alternate names of both this unit and the provided prefix.

        -
        -
        Parameters:
        -
        prefix - prefix to apply
        -
        Returns:
        -
        unit with prefix
        -
        Throws:
        -
        java.lang.NullPointerException - if prefix is null
        -
        Since:
        -
        2019-03-18, v0.2.0
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/NameSymbol.html b/doc/org/unitConverter/unit/NameSymbol.html deleted file mode 100644 index 17b5d4e..0000000 --- a/doc/org/unitConverter/unit/NameSymbol.html +++ /dev/null @@ -1,641 +0,0 @@ - - - - - -NameSymbol - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class NameSymbol

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.NameSymbol
    • -
    -
  • -
-
-
    -
  • -
    -
    -
    public final class NameSymbol
    -extends java.lang.Object
    -
    A class that can be used to specify names and a symbol for a unit.
    -
    -
    Since:
    -
    2019-10-21
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Field Summary

      - - - - - - - - - - -
      Fields 
      Modifier and TypeField and Description
      static NameSymbolEMPTY 
      -
    • -
    - -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      java.util.Set<java.lang.String>getOtherNames() 
      java.util.Optional<java.lang.String>getPrimaryName() 
      java.util.Optional<java.lang.String>getSymbol() 
      static NameSymbolof(java.lang.String name, - java.lang.String symbol) -
      Gets a NameSymbol with a primary name, a symbol and no other names.
      -
      static NameSymbolof(java.lang.String name, - java.lang.String symbol, - java.util.Set<java.lang.String> otherNames) -
      Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolof(java.lang.String name, - java.lang.String symbol, - java.lang.String... otherNames) -
      h * Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolof(java.lang.String name, - java.lang.String symbol, - java.lang.String name2) -
      Gets a NameSymbol with a primary name, a symbol and an additional name.
      -
      static NameSymbolof(java.lang.String name, - java.lang.String symbol, - java.lang.String name2, - java.lang.String name3) -
      Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolof(java.lang.String name, - java.lang.String symbol, - java.lang.String name2, - java.lang.String name3, - java.lang.String name4) -
      Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolofName(java.lang.String name) -
      Gets a NameSymbol with a primary name, no symbol, and no other names.
      -
      static NameSymbolofNullable(java.lang.String name, - java.lang.String symbol, - java.util.Set<java.lang.String> otherNames) -
      Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolofNullable(java.lang.String name, - java.lang.String symbol, - java.lang.String... otherNames) -
      h * Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolofSymbol(java.lang.String symbol) -
      Gets a NameSymbol with a symbol and no names.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
    • -
    -
  • -
-
-
-
    -
  • - - - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        of

        -
        public static final NameSymbol of(java.lang.String name,
        -                                  java.lang.String symbol)
        -
        Gets a NameSymbol with a primary name, a symbol and no other names.
        -
        -
        Parameters:
        -
        name - name to use
        -
        symbol - symbol to use
        -
        Returns:
        -
        NameSymbol instance
        -
        Throws:
        -
        java.lang.NullPointerException - if name or symbol is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        of

        -
        public static final NameSymbol of(java.lang.String name,
        -                                  java.lang.String symbol,
        -                                  java.util.Set<java.lang.String> otherNames)
        -
        Gets a NameSymbol with a primary name, a symbol and additional names.
        -
        -
        Parameters:
        -
        name - name to use
        -
        symbol - symbol to use
        -
        otherNames - other names to use
        -
        Returns:
        -
        NameSymbol instance
        -
        Throws:
        -
        java.lang.NullPointerException - if any argument is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        of

        -
        public static final NameSymbol of(java.lang.String name,
        -                                  java.lang.String symbol,
        -                                  java.lang.String... otherNames)
        -
        h * Gets a NameSymbol with a primary name, a symbol and additional names.
        -
        -
        Parameters:
        -
        name - name to use
        -
        symbol - symbol to use
        -
        otherNames - other names to use
        -
        Returns:
        -
        NameSymbol instance
        -
        Throws:
        -
        java.lang.NullPointerException - if any argument is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        of

        -
        public static final NameSymbol of(java.lang.String name,
        -                                  java.lang.String symbol,
        -                                  java.lang.String name2)
        -
        Gets a NameSymbol with a primary name, a symbol and an additional name.
        -
        -
        Parameters:
        -
        name - name to use
        -
        symbol - symbol to use
        -
        otherNames - other names to use
        -
        name2 - alternate name
        -
        Returns:
        -
        NameSymbol instance
        -
        Throws:
        -
        java.lang.NullPointerException - if any argument is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        of

        -
        public static final NameSymbol of(java.lang.String name,
        -                                  java.lang.String symbol,
        -                                  java.lang.String name2,
        -                                  java.lang.String name3)
        -
        Gets a NameSymbol with a primary name, a symbol and additional names.
        -
        -
        Parameters:
        -
        name - name to use
        -
        symbol - symbol to use
        -
        otherNames - other names to use
        -
        name2 - alternate name
        -
        name3 - alternate name
        -
        Returns:
        -
        NameSymbol instance
        -
        Throws:
        -
        java.lang.NullPointerException - if any argument is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        of

        -
        public static final NameSymbol of(java.lang.String name,
        -                                  java.lang.String symbol,
        -                                  java.lang.String name2,
        -                                  java.lang.String name3,
        -                                  java.lang.String name4)
        -
        Gets a NameSymbol with a primary name, a symbol and additional names.
        -
        -
        Parameters:
        -
        name - name to use
        -
        symbol - symbol to use
        -
        otherNames - other names to use
        -
        name2 - alternate name
        -
        name3 - alternate name
        -
        name4 - alternate name
        -
        Returns:
        -
        NameSymbol instance
        -
        Throws:
        -
        java.lang.NullPointerException - if any argument is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        ofName

        -
        public static final NameSymbol ofName(java.lang.String name)
        -
        Gets a NameSymbol with a primary name, no symbol, and no other names.
        -
        -
        Parameters:
        -
        name - name to use
        -
        Returns:
        -
        NameSymbol instance
        -
        Throws:
        -
        java.lang.NullPointerException - if name is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        ofNullable

        -
        public static final NameSymbol ofNullable(java.lang.String name,
        -                                          java.lang.String symbol,
        -                                          java.util.Set<java.lang.String> otherNames)
        -
        Gets a NameSymbol with a primary name, a symbol and additional names. -

        - If any argument is null, this static factory replaces it with an empty Optional or empty Set.

        -
        -
        Parameters:
        -
        name - name to use
        -
        symbol - symbol to use
        -
        otherNames - other names to use
        -
        Returns:
        -
        NameSymbol instance
        -
        Since:
        -
        2019-11-26
        -
        -
      • -
      - - - -
        -
      • -

        ofNullable

        -
        public static final NameSymbol ofNullable(java.lang.String name,
        -                                          java.lang.String symbol,
        -                                          java.lang.String... otherNames)
        -
        h * Gets a NameSymbol with a primary name, a symbol and additional names. -

        - If any argument is null, this static factory replaces it with an empty Optional or empty Set.

        -
        -
        Parameters:
        -
        name - name to use
        -
        symbol - symbol to use
        -
        otherNames - other names to use
        -
        Returns:
        -
        NameSymbol instance
        -
        Since:
        -
        2019-11-26
        -
        -
      • -
      - - - -
        -
      • -

        ofSymbol

        -
        public static final NameSymbol ofSymbol(java.lang.String symbol)
        -
        Gets a NameSymbol with a symbol and no names.
        -
        -
        Parameters:
        -
        symbol - symbol to use
        -
        Returns:
        -
        NameSymbol instance
        -
        Throws:
        -
        java.lang.NullPointerException - if symbol is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        getOtherNames

        -
        public final java.util.Set<java.lang.String> getOtherNames()
        -
        -
        Returns:
        -
        otherNames
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        getPrimaryName

        -
        public final java.util.Optional<java.lang.String> getPrimaryName()
        -
        -
        Returns:
        -
        primaryName
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        getSymbol

        -
        public final java.util.Optional<java.lang.String> getSymbol()
        -
        -
        Returns:
        -
        symbol
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/SI.BaseDimensions.html b/doc/org/unitConverter/unit/SI.BaseDimensions.html deleted file mode 100644 index 9b0383a..0000000 --- a/doc/org/unitConverter/unit/SI.BaseDimensions.html +++ /dev/null @@ -1,347 +0,0 @@ - - - - - -SI.BaseDimensions - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class SI.BaseDimensions

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.SI.BaseDimensions
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    SI
    -
    -
    -
    -
    public static final class SI.BaseDimensions
    -extends java.lang.Object
    -
  • -
-
-
- -
-
- -
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/SI.BaseUnits.html b/doc/org/unitConverter/unit/SI.BaseUnits.html deleted file mode 100644 index af96cd3..0000000 --- a/doc/org/unitConverter/unit/SI.BaseUnits.html +++ /dev/null @@ -1,347 +0,0 @@ - - - - - -SI.BaseUnits - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class SI.BaseUnits

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.SI.BaseUnits
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    SI
    -
    -
    -
    -
    public static final class SI.BaseUnits
    -extends java.lang.Object
    -
  • -
-
-
- -
-
-
    -
  • - - -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/SI.Constants.html b/doc/org/unitConverter/unit/SI.Constants.html deleted file mode 100644 index f846f4a..0000000 --- a/doc/org/unitConverter/unit/SI.Constants.html +++ /dev/null @@ -1,284 +0,0 @@ - - - - - -SI.Constants - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class SI.Constants

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.SI.Constants
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    SI
    -
    -
    -
    -
    public static final class SI.Constants
    -extends java.lang.Object
    -
    Constants that relate to the SI or other systems.
    -
    -
    Since:
    -
    2019-11-08
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - - - -
      -
    • - - -

      Constructor Summary

      - - - - - - - - -
      Constructors 
      Constructor and Description
      Constants() 
      -
    • -
    - -
      -
    • - - -

      Method Summary

      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
    • -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        EARTH_GRAVITY

        -
        public static final LinearUnit EARTH_GRAVITY
        -
      • -
      -
    • -
    - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        Constants

        -
        public Constants()
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/SI.Dimensions.html b/doc/org/unitConverter/unit/SI.Dimensions.html deleted file mode 100644 index f626044..0000000 --- a/doc/org/unitConverter/unit/SI.Dimensions.html +++ /dev/null @@ -1,789 +0,0 @@ - - - - - -SI.Dimensions - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class SI.Dimensions

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.SI.Dimensions
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    SI
    -
    -
    -
    -
    public static final class SI.Dimensions
    -extends java.lang.Object
    -
  • -
-
-
- -
-
- -
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/SI.html b/doc/org/unitConverter/unit/SI.html deleted file mode 100644 index 7e50983..0000000 --- a/doc/org/unitConverter/unit/SI.html +++ /dev/null @@ -1,1313 +0,0 @@ - - - - - -SI - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class SI

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.SI
    • -
    -
  • -
-
-
    -
  • -
    -
    -
    public final class SI
    -extends java.lang.Object
    -
    All of the units, prefixes and dimensions that are used by the SI, as well as some outside the SI. - -

    - This class does not include prefixed units. To obtain prefixed units, use LinearUnit.withPrefix(org.unitConverter.unit.UnitPrefix): - -

    - LinearUnit KILOMETRE = SI.METRE.withPrefix(SI.KILO);
    - 
    -
    -
    Since:
    -
    2019-10-16
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
- -
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/USCustomary.Area.html b/doc/org/unitConverter/unit/USCustomary.Area.html deleted file mode 100644 index f811e72..0000000 --- a/doc/org/unitConverter/unit/USCustomary.Area.html +++ /dev/null @@ -1,336 +0,0 @@ - - - - - -USCustomary.Area - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class USCustomary.Area

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.USCustomary.Area
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    USCustomary
    -
    -
    -
    -
    public static final class USCustomary.Area
    -extends java.lang.Object
    -
    US Customary units that measure area
    -
    -
    Since:
    -
    2019-11-08
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        SQUARE_SURVEY_FOOT

        -
        public static final LinearUnit SQUARE_SURVEY_FOOT
        -
      • -
      - - - -
        -
      • -

        SQUARE_CHAIN

        -
        public static final LinearUnit SQUARE_CHAIN
        -
      • -
      - - - -
        -
      • -

        ACRE

        -
        public static final LinearUnit ACRE
        -
      • -
      - - - -
        -
      • -

        SECTION

        -
        public static final LinearUnit SECTION
        -
      • -
      - - - -
        -
      • -

        SURVEY_TOWNSHIP

        -
        public static final LinearUnit SURVEY_TOWNSHIP
        -
      • -
      -
    • -
    - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        Area

        -
        public Area()
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/USCustomary.Length.html b/doc/org/unitConverter/unit/USCustomary.Length.html deleted file mode 100644 index 19c9c9b..0000000 --- a/doc/org/unitConverter/unit/USCustomary.Length.html +++ /dev/null @@ -1,492 +0,0 @@ - - - - - -USCustomary.Length - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class USCustomary.Length

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.USCustomary.Length
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    USCustomary
    -
    -
    -
    -
    public static final class USCustomary.Length
    -extends java.lang.Object
    -
    US Customary units that measure length
    -
    -
    Since:
    -
    2019-10-28
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
- -
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/USCustomary.Mass.html b/doc/org/unitConverter/unit/USCustomary.Mass.html deleted file mode 100644 index 65c463b..0000000 --- a/doc/org/unitConverter/unit/USCustomary.Mass.html +++ /dev/null @@ -1,388 +0,0 @@ - - - - - -USCustomary.Mass - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class USCustomary.Mass

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.USCustomary.Mass
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    USCustomary
    -
    -
    -
    -
    public static final class USCustomary.Mass
    -extends java.lang.Object
    -
    mass units
    -
    -
    Since:
    -
    2019-11-08
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - - - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        Mass

        -
        public Mass()
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/USCustomary.Volume.html b/doc/org/unitConverter/unit/USCustomary.Volume.html deleted file mode 100644 index 0a1cbf9..0000000 --- a/doc/org/unitConverter/unit/USCustomary.Volume.html +++ /dev/null @@ -1,583 +0,0 @@ - - - - - -USCustomary.Volume - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class USCustomary.Volume

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.USCustomary.Volume
    • -
    -
  • -
-
-
    -
  • -
    -
    Enclosing class:
    -
    USCustomary
    -
    -
    -
    -
    public static final class USCustomary.Volume
    -extends java.lang.Object
    -
    Volume units
    -
    -
    Since:
    -
    2019-11-08
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
- -
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/USCustomary.html b/doc/org/unitConverter/unit/USCustomary.html deleted file mode 100644 index 38777d1..0000000 --- a/doc/org/unitConverter/unit/USCustomary.html +++ /dev/null @@ -1,423 +0,0 @@ - - - - - -USCustomary - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class USCustomary

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.USCustomary
    • -
    -
  • -
-
-
    -
  • -
    -
    -
    public final class USCustomary
    -extends java.lang.Object
    -
    A static utility class that contains units in the US Customary system.
    -
    -
    Since:
    -
    2019-10-21
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        OUNCE_FORCE

        -
        public static final LinearUnit OUNCE_FORCE
        -
      • -
      - - - -
        -
      • -

        POUND_FORCE

        -
        public static final LinearUnit POUND_FORCE
        -
      • -
      - - - -
        -
      • -

        BRITISH_THERMAL_UNIT

        -
        public static final LinearUnit BRITISH_THERMAL_UNIT
        -
      • -
      - - - -
        -
      • -

        CALORIE

        -
        public static final LinearUnit CALORIE
        -
      • -
      - - - -
        -
      • -

        KILOCALORIE

        -
        public static final LinearUnit KILOCALORIE
        -
      • -
      - - - -
        -
      • -

        FOOT_POUND

        -
        public static final LinearUnit FOOT_POUND
        -
      • -
      - - - -
        -
      • -

        HORSEPOWER

        -
        public static final LinearUnit HORSEPOWER
        -
      • -
      - - - -
        -
      • -

        POUND_PER_SQUARE_INCH

        -
        public static final LinearUnit POUND_PER_SQUARE_INCH
        -
      • -
      - - - -
        -
      • -

        FAHRENHEIT

        -
        public static final Unit FAHRENHEIT
        -
      • -
      -
    • -
    - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        USCustomary

        -
        public USCustomary()
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/Unit.html b/doc/org/unitConverter/unit/Unit.html deleted file mode 100644 index 2a84bfa..0000000 --- a/doc/org/unitConverter/unit/Unit.html +++ /dev/null @@ -1,632 +0,0 @@ - - - - - -Unit - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class Unit

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.Unit
    • -
    -
  • -
-
-
    -
  • -
    -
    Direct Known Subclasses:
    -
    BaseUnit, LinearUnit
    -
    -
    -
    -
    public abstract class Unit
    -extends java.lang.Object
    -
    A unit that is composed of base units.
    -
    -
    Since:
    -
    2019-10-16
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        Unit

        -
        protected Unit(ObjectProduct<BaseUnit> unitBase,
        -               NameSymbol ns)
        -
        Creates the AbstractUnit.
        -
        -
        Parameters:
        -
        unitBase - base of unit
        -
        ns - names and symbol of unit
        -
        Throws:
        -
        java.lang.NullPointerException - if unitBase or ns is null
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      -
    • -
    - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        fromConversionFunctions

        -
        public static final Unit fromConversionFunctions(ObjectProduct<BaseUnit> base,
        -                                                 java.util.function.DoubleUnaryOperator converterFrom,
        -                                                 java.util.function.DoubleUnaryOperator converterTo)
        -
        Returns a unit from its base and the functions it uses to convert to and from its base. - -

        - For example, to get a unit representing the degree Celsius, the following code can be used: - - Unit.fromConversionFunctions(SI.KELVIN, tempK -> tempK - 273.15, tempC -> tempC + 273.15); -

        -
        -
        Parameters:
        -
        base - unit's base
        -
        converterFrom - function that accepts a value expressed in the unit's base and returns that value expressed in this - unit.
        -
        converterTo - function that accepts a value expressed in the unit and returns that value expressed in the unit's - base.
        -
        Returns:
        -
        a unit that uses the provided functions to convert.
        -
        Throws:
        -
        java.lang.NullPointerException - if any argument is null
        -
        Since:
        -
        2019-05-22
        -
        -
      • -
      - - - -
        -
      • -

        fromConversionFunctions

        -
        public static final Unit fromConversionFunctions(ObjectProduct<BaseUnit> base,
        -                                                 java.util.function.DoubleUnaryOperator converterFrom,
        -                                                 java.util.function.DoubleUnaryOperator converterTo,
        -                                                 NameSymbol ns)
        -
        Returns a unit from its base and the functions it uses to convert to and from its base. - -

        - For example, to get a unit representing the degree Celsius, the following code can be used: - - Unit.fromConversionFunctions(SI.KELVIN, tempK -> tempK - 273.15, tempC -> tempC + 273.15); -

        -
        -
        Parameters:
        -
        base - unit's base
        -
        converterFrom - function that accepts a value expressed in the unit's base and returns that value expressed in this - unit.
        -
        converterTo - function that accepts a value expressed in the unit and returns that value expressed in the unit's - base.
        -
        ns - names and symbol of unit
        -
        Returns:
        -
        a unit that uses the provided functions to convert.
        -
        Throws:
        -
        java.lang.NullPointerException - if any argument is null
        -
        Since:
        -
        2019-05-22
        -
        -
      • -
      - - - -
        -
      • -

        canConvertTo

        -
        public final boolean canConvertTo(Unit other)
        -
        Checks if a value expressed in this unit can be converted to a value expressed in other
        -
        -
        Parameters:
        -
        other - unit to test with
        -
        Returns:
        -
        true if the units are compatible
        -
        Throws:
        -
        java.lang.NullPointerException - if other is null
        -
        Since:
        -
        2019-01-13, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        convertFromBase

        -
        protected abstract double convertFromBase(double value)
        -
        Converts from a value expressed in this unit's base unit to a value expressed in this unit. -

        - This must be the inverse of convertToBase, so convertFromBase(convertToBase(value)) must be equal - to value for any value, ignoring precision loss by roundoff error. -

        -

        - If this unit is a base unit, this method should return value. -

        -
        -
        Parameters:
        -
        value - value expressed in base unit
        -
        Returns:
        -
        value expressed in this unit
        -
        Since:
        -
        2018-12-22, v0.1.0
        -
        Implementation Requirements:
        -
        This method is used by convertTo(org.unitConverter.unit.Unit, double), and its behaviour affects the behaviour of - convertTo.
        -
        -
      • -
      - - - -
        -
      • -

        convertTo

        -
        public final double convertTo(Unit other,
        -                              double value)
        -
        Converts a value expressed in this unit to a value expressed in other.
        -
        -
        Parameters:
        -
        other - unit to convert to
        -
        value - value to convert
        -
        Returns:
        -
        converted value
        -
        Throws:
        -
        java.lang.IllegalArgumentException - if other is incompatible for conversion with this unit (as tested by - canConvertTo(org.unitConverter.unit.Unit)).
        -
        java.lang.NullPointerException - if other is null
        -
        Since:
        -
        2019-05-22
        -
        Implementation Requirements:
        -
        If unit conversion is possible, this implementation returns - other.convertFromBase(this.convertToBase(value)). Therefore, overriding either of those methods - will change the output of this method.
        -
        -
      • -
      - - - -
        -
      • -

        convertToBase

        -
        protected abstract double convertToBase(double value)
        -
        Converts from a value expressed in this unit to a value expressed in this unit's base unit. -

        - This must be the inverse of convertFromBase, so convertToBase(convertFromBase(value)) must be - equal to value for any value, ignoring precision loss by roundoff error. -

        -

        - If this unit is a base unit, this method should return value. -

        -
        -
        Parameters:
        -
        value - value expressed in this unit
        -
        Returns:
        -
        value expressed in base unit
        -
        Since:
        -
        2018-12-22, v0.1.0
        -
        Implementation Requirements:
        -
        This method is used by convertTo(org.unitConverter.unit.Unit, double), and its behaviour affects the behaviour of - convertTo.
        -
        -
      • -
      - - - -
        -
      • -

        getBase

        -
        public final ObjectProduct<BaseUnit> getBase()
        -
        -
        Returns:
        -
        combination of units that this unit is based on
        -
        Since:
        -
        2018-12-22, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getDimension

        -
        public final ObjectProduct<BaseDimension> getDimension()
        -
        -
        Returns:
        -
        dimension measured by this unit
        -
        Since:
        -
        2018-12-22, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getOtherNames

        -
        public final java.util.Set<java.lang.String> getOtherNames()
        -
        -
        Returns:
        -
        additionalNames
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        getPrimaryName

        -
        public final java.util.Optional<java.lang.String> getPrimaryName()
        -
        -
        Returns:
        -
        primaryName
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        getSymbol

        -
        public final java.util.Optional<java.lang.String> getSymbol()
        -
        -
        Returns:
        -
        symbol
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        -
        Overrides:
        -
        toString in class java.lang.Object
        -
        -
      • -
      - - - -
        -
      • -

        withName

        -
        public Unit withName(NameSymbol ns)
        -
        -
        Parameters:
        -
        ns - name(s) and symbol to use
        -
        Returns:
        -
        a copy of this unit with provided name(s) and symbol
        -
        Throws:
        -
        java.lang.NullPointerException - if ns is null
        -
        Since:
        -
        2019-10-21
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry.html b/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry.html deleted file mode 100644 index 65b640c..0000000 --- a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry.html +++ /dev/null @@ -1,499 +0,0 @@ - - - - - -UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry
    • -
    -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.util.Map.Entry<java.lang.String,​Unit>
    -
    -
    -
    Enclosing class:
    -
    UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet
    -
    -
    -
    private static final class UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry
    -extends java.lang.Object
    -implements java.util.Map.Entry<java.lang.String,​Unit>
    -
    The entry for this set.
    -
    -
    Since:
    -
    2019-04-14, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private java.lang.Stringkey 
      private Unitvalue 
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      PrefixedUnitEntry​(java.lang.String key, - Unit value) -
      Creates the PrefixedUnitEntry.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      booleanequals​(java.lang.Object o) 
      java.lang.StringgetKey() 
      UnitgetValue() 
      inthashCode() 
      UnitsetValue​(Unit value) 
      java.lang.StringtoString() -
      Returns a string representation of the entry.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, finalize, getClass, notify, notifyAll, wait, wait, wait
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        key

        -
        private final java.lang.String key
        -
      • -
      - - - -
        -
      • -

        value

        -
        private final Unit value
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        PrefixedUnitEntry

        -
        public PrefixedUnitEntry​(java.lang.String key,
        -                         Unit value)
        -
        Creates the PrefixedUnitEntry.
        -
        -
        Parameters:
        -
        key - key
        -
        value - value
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        equals

        -
        public boolean equals​(java.lang.Object o)
        -
        -
        Specified by:
        -
        equals in interface java.util.Map.Entry<java.lang.String,​Unit>
        -
        Overrides:
        -
        equals in class java.lang.Object
        -
        Since:
        -
        2019-05-03
        -
        -
      • -
      - - - -
        -
      • -

        getKey

        -
        public java.lang.String getKey()
        -
        -
        Specified by:
        -
        getKey in interface java.util.Map.Entry<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        getValue

        -
        public Unit getValue()
        -
        -
        Specified by:
        -
        getValue in interface java.util.Map.Entry<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        hashCode

        -
        public int hashCode()
        -
        -
        Specified by:
        -
        hashCode in interface java.util.Map.Entry<java.lang.String,​Unit>
        -
        Overrides:
        -
        hashCode in class java.lang.Object
        -
        Since:
        -
        2019-05-03
        -
        -
      • -
      - - - -
        -
      • -

        setValue

        -
        public Unit setValue​(Unit value)
        -
        -
        Specified by:
        -
        setValue in interface java.util.Map.Entry<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        Returns a string representation of the entry. The format of the string is the string representation - of the key, then the equals (=) character, then the string representation of the value.
        -
        -
        Overrides:
        -
        toString in class java.lang.Object
        -
        Since:
        -
        2019-05-03
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator.html b/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator.html deleted file mode 100644 index 465ee75..0000000 --- a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator.html +++ /dev/null @@ -1,542 +0,0 @@ - - - - - -UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator
    • -
    -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.util.Iterator<java.util.Map.Entry<java.lang.String,​Unit>>
    -
    -
    -
    Enclosing class:
    -
    UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet
    -
    -
    -
    private static final class UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator
    -extends java.lang.Object
    -implements java.util.Iterator<java.util.Map.Entry<java.lang.String,​Unit>>
    -
    An iterator that iterates over the units of a PrefixedUnitNameSet.
    -
    -
    Since:
    -
    2019-04-14, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private java.util.Map<java.lang.String,​Unit>map 
      private java.util.List<java.lang.Integer>prefixCoordinates 
      private java.util.List<java.lang.String>prefixNames 
      private intunitNamePosition 
      private java.util.List<java.lang.String>unitNames 
      -
    • -
    -
    - -
    - -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      private java.lang.StringgetCurrentUnitName() 
      booleanhasNext() 
      private voidincrementPosition() -
      Changes this iterator's position to the next available one.
      -
      java.util.Map.Entry<java.lang.String,​Unit>next() 
      private java.util.Map.Entry<java.lang.String,​Unit>peek() 
      java.lang.StringtoString() -
      Returns a string representation of the object.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Iterator

        -forEachRemaining, remove
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        unitNamePosition

        -
        private int unitNamePosition
        -
      • -
      - - - -
        -
      • -

        prefixCoordinates

        -
        private final java.util.List<java.lang.Integer> prefixCoordinates
        -
      • -
      - - - -
        -
      • -

        map

        -
        private final java.util.Map<java.lang.String,​Unit> map
        -
      • -
      - - - -
        -
      • -

        unitNames

        -
        private final transient java.util.List<java.lang.String> unitNames
        -
      • -
      - - - -
        -
      • -

        prefixNames

        -
        private final transient java.util.List<java.lang.String> prefixNames
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        PrefixedUnitEntryIterator

        -
        public PrefixedUnitEntryIterator​(UnitDatabase.PrefixedUnitMap map)
        -
        Creates the UnitsDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.
        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        getCurrentUnitName

        -
        private java.lang.String getCurrentUnitName()
        -
        -
        Returns:
        -
        current unit name
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        hasNext

        -
        public boolean hasNext()
        -
        -
        Specified by:
        -
        hasNext in interface java.util.Iterator<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        incrementPosition

        -
        private void incrementPosition()
        -
        Changes this iterator's position to the next available one.
        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        next

        -
        public java.util.Map.Entry<java.lang.String,​Unit> next()
        -
        -
        Specified by:
        -
        next in interface java.util.Iterator<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        peek

        -
        private java.util.Map.Entry<java.lang.String,​Unit> peek()
        -
        -
        Returns:
        -
        the next element in the iterator, without iterating over it
        -
        Since:
        -
        2019-05-03
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        Returns a string representation of the object. The exact details of the representation are - unspecified and subject to change.
        -
        -
        Overrides:
        -
        toString in class java.lang.Object
        -
        Since:
        -
        2019-05-03
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.html b/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.html deleted file mode 100644 index 66e7804..0000000 --- a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.html +++ /dev/null @@ -1,761 +0,0 @@ - - - - - -UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • java.util.AbstractCollection<E>
    • -
    • -
        -
      • java.util.AbstractSet<java.util.Map.Entry<java.lang.String,​Unit>>
      • -
      • -
          -
        • org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet
        • -
        -
      • -
      -
    • -
    -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.lang.Iterable<java.util.Map.Entry<java.lang.String,​Unit>>, java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>, java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
    -
    -
    -
    Enclosing class:
    -
    UnitDatabase.PrefixedUnitMap
    -
    -
    -
    private static final class UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet
    -extends java.util.AbstractSet<java.util.Map.Entry<java.lang.String,​Unit>>
    -
    The class used for entry sets. - -

    - If the map that created this set is infinite in size (has at least one unit and at least one prefix), this - set is infinite as well. If this set is infinite in size, toArray() will fail with a - IllegalStateException instead of creating an infinite-sized array. -

    -
    -
    Since:
    -
    2019-04-13, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    - -
    - -
    - -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      booleanadd​(java.util.Map.Entry<java.lang.String,​Unit> e) 
      booleanaddAll​(java.util.Collection<? extends java.util.Map.Entry<java.lang.String,​Unit>> c) 
      voidclear() 
      booleancontains​(java.lang.Object o) 
      booleancontainsAll​(java.util.Collection<?> c) 
      booleanisEmpty() 
      java.util.Iterator<java.util.Map.Entry<java.lang.String,​Unit>>iterator() 
      booleanremove​(java.lang.Object o) 
      booleanremoveAll​(java.util.Collection<?> c) 
      booleanremoveIf​(java.util.function.Predicate<? super java.util.Map.Entry<java.lang.String,​Unit>> filter) 
      booleanretainAll​(java.util.Collection<?> c) 
      intsize() 
      java.lang.Object[]toArray() 
      <T> T[]toArray​(T[] a) 
      java.lang.StringtoString() 
      -
        -
      • - - -

        Methods inherited from class java.util.AbstractSet

        -equals, hashCode
      • -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, finalize, getClass, notify, notifyAll, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Collection

        -parallelStream, stream, toArray
      • -
      -
        -
      • - - -

        Methods inherited from interface java.lang.Iterable

        -forEach
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Set

        -spliterator
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        PrefixedUnitEntrySet

        -
        public PrefixedUnitEntrySet​(UnitDatabase.PrefixedUnitMap map)
        -
        Creates the PrefixedUnitNameSet.
        -
        -
        Parameters:
        -
        map - map that created this set
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        add

        -
        public boolean add​(java.util.Map.Entry<java.lang.String,​Unit> e)
        -
        -
        Specified by:
        -
        add in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        add in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        add in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        addAll

        -
        public boolean addAll​(java.util.Collection<? extends java.util.Map.Entry<java.lang.String,​Unit>> c)
        -
        -
        Specified by:
        -
        addAll in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        addAll in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        addAll in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        clear

        -
        public void clear()
        -
        -
        Specified by:
        -
        clear in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        clear in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        clear in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        contains

        -
        public boolean contains​(java.lang.Object o)
        -
        -
        Specified by:
        -
        contains in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        contains in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        contains in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        containsAll

        -
        public boolean containsAll​(java.util.Collection<?> c)
        -
        -
        Specified by:
        -
        containsAll in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        containsAll in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        containsAll in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        isEmpty

        -
        public boolean isEmpty()
        -
        -
        Specified by:
        -
        isEmpty in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        isEmpty in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        isEmpty in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        iterator

        -
        public java.util.Iterator<java.util.Map.Entry<java.lang.String,​Unit>> iterator()
        -
        -
        Specified by:
        -
        iterator in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        iterator in interface java.lang.Iterable<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        iterator in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        iterator in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        remove

        -
        public boolean remove​(java.lang.Object o)
        -
        -
        Specified by:
        -
        remove in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        remove in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        remove in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        removeAll

        -
        public boolean removeAll​(java.util.Collection<?> c)
        -
        -
        Specified by:
        -
        removeAll in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        removeAll in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        removeAll in class java.util.AbstractSet<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        removeIf

        -
        public boolean removeIf​(java.util.function.Predicate<? super java.util.Map.Entry<java.lang.String,​Unit>> filter)
        -
      • -
      - - - -
        -
      • -

        retainAll

        -
        public boolean retainAll​(java.util.Collection<?> c)
        -
        -
        Specified by:
        -
        retainAll in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        retainAll in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        retainAll in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        size

        -
        public int size()
        -
        -
        Specified by:
        -
        size in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        size in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        size in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      - - - -
        -
      • -

        toArray

        -
        public java.lang.Object[] toArray()
        -
        -
        Specified by:
        -
        toArray in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        toArray in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        toArray in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Throws:
        -
        java.lang.IllegalStateException - if the set is infinite in size
        -
        -
      • -
      - - - - - -
        -
      • -

        toArray

        -
        public <T> T[] toArray​(T[] a)
        -
        -
        Specified by:
        -
        toArray in interface java.util.Collection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Specified by:
        -
        toArray in interface java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Overrides:
        -
        toArray in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        Throws:
        -
        java.lang.IllegalStateException - if the set is infinite in size
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        -
        Overrides:
        -
        toString in class java.util.AbstractCollection<java.util.Map.Entry<java.lang.String,​Unit>>
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.html b/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.html deleted file mode 100644 index 0e4a161..0000000 --- a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.html +++ /dev/null @@ -1,542 +0,0 @@ - - - - - -UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator
    • -
    -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.util.Iterator<java.lang.String>
    -
    -
    -
    Enclosing class:
    -
    UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet
    -
    -
    -
    private static final class UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator
    -extends java.lang.Object
    -implements java.util.Iterator<java.lang.String>
    -
    An iterator that iterates over the units of a PrefixedUnitNameSet.
    -
    -
    Since:
    -
    2019-04-14, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private java.util.Map<java.lang.String,​Unit>map 
      private java.util.List<java.lang.Integer>prefixCoordinates 
      private java.util.List<java.lang.String>prefixNames 
      private intunitNamePosition 
      private java.util.List<java.lang.String>unitNames 
      -
    • -
    -
    - -
    - -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      private java.lang.StringgetCurrentUnitName() 
      booleanhasNext() 
      private voidincrementPosition() -
      Changes this iterator's position to the next available one.
      -
      java.lang.Stringnext() 
      private java.lang.Stringpeek() 
      java.lang.StringtoString() -
      Returns a string representation of the object.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Iterator

        -forEachRemaining, remove
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        unitNamePosition

        -
        private int unitNamePosition
        -
      • -
      - - - -
        -
      • -

        prefixCoordinates

        -
        private final java.util.List<java.lang.Integer> prefixCoordinates
        -
      • -
      - - - -
        -
      • -

        map

        -
        private final java.util.Map<java.lang.String,​Unit> map
        -
      • -
      - - - -
        -
      • -

        unitNames

        -
        private final transient java.util.List<java.lang.String> unitNames
        -
      • -
      - - - -
        -
      • -

        prefixNames

        -
        private final transient java.util.List<java.lang.String> prefixNames
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        PrefixedUnitNameIterator

        -
        public PrefixedUnitNameIterator​(UnitDatabase.PrefixedUnitMap map)
        -
        Creates the UnitsDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.
        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        getCurrentUnitName

        -
        private java.lang.String getCurrentUnitName()
        -
        -
        Returns:
        -
        current unit name
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        hasNext

        -
        public boolean hasNext()
        -
        -
        Specified by:
        -
        hasNext in interface java.util.Iterator<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        incrementPosition

        -
        private void incrementPosition()
        -
        Changes this iterator's position to the next available one.
        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        next

        -
        public java.lang.String next()
        -
        -
        Specified by:
        -
        next in interface java.util.Iterator<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        peek

        -
        private java.lang.String peek()
        -
        -
        Returns:
        -
        the next element in the iterator, without iterating over it
        -
        Since:
        -
        2019-05-03
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        Returns a string representation of the object. The exact details of the representation are - unspecified and subject to change.
        -
        -
        Overrides:
        -
        toString in class java.lang.Object
        -
        Since:
        -
        2019-05-03
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.html b/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.html deleted file mode 100644 index 8794e15..0000000 --- a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.html +++ /dev/null @@ -1,754 +0,0 @@ - - - - - -UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • java.util.AbstractCollection<E>
    • -
    • -
        -
      • java.util.AbstractSet<java.lang.String>
      • -
      • -
          -
        • org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet
        • -
        -
      • -
      -
    • -
    -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.lang.Iterable<java.lang.String>, java.util.Collection<java.lang.String>, java.util.Set<java.lang.String>
    -
    -
    -
    Enclosing class:
    -
    UnitDatabase.PrefixedUnitMap
    -
    -
    -
    private static final class UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet
    -extends java.util.AbstractSet<java.lang.String>
    -
    The class used for unit name sets. - -

    - If the map that created this set is infinite in size (has at least one unit and at least one prefix), this - set is infinite as well. If this set is infinite in size, toArray() will fail with a - IllegalStateException instead of creating an infinite-sized array. -

    -
    -
    Since:
    -
    2019-04-13, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    - -
    - -
    - -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      booleanadd​(java.lang.String e) 
      booleanaddAll​(java.util.Collection<? extends java.lang.String> c) 
      voidclear() 
      booleancontains​(java.lang.Object o) 
      booleancontainsAll​(java.util.Collection<?> c) 
      booleanisEmpty() 
      java.util.Iterator<java.lang.String>iterator() 
      booleanremove​(java.lang.Object o) 
      booleanremoveAll​(java.util.Collection<?> c) 
      booleanremoveIf​(java.util.function.Predicate<? super java.lang.String> filter) 
      booleanretainAll​(java.util.Collection<?> c) 
      intsize() 
      java.lang.Object[]toArray() 
      <T> T[]toArray​(T[] a) 
      java.lang.StringtoString() 
      -
        -
      • - - -

        Methods inherited from class java.util.AbstractSet

        -equals, hashCode
      • -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, finalize, getClass, notify, notifyAll, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Collection

        -parallelStream, stream, toArray
      • -
      -
        -
      • - - -

        Methods inherited from interface java.lang.Iterable

        -forEach
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Set

        -spliterator
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        PrefixedUnitNameSet

        -
        public PrefixedUnitNameSet​(UnitDatabase.PrefixedUnitMap map)
        -
        Creates the PrefixedUnitNameSet.
        -
        -
        Parameters:
        -
        map - map that created this set
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        add

        -
        public boolean add​(java.lang.String e)
        -
        -
        Specified by:
        -
        add in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        add in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        add in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        addAll

        -
        public boolean addAll​(java.util.Collection<? extends java.lang.String> c)
        -
        -
        Specified by:
        -
        addAll in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        addAll in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        addAll in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        clear

        -
        public void clear()
        -
        -
        Specified by:
        -
        clear in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        clear in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        clear in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        contains

        -
        public boolean contains​(java.lang.Object o)
        -
        -
        Specified by:
        -
        contains in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        contains in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        contains in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        containsAll

        -
        public boolean containsAll​(java.util.Collection<?> c)
        -
        -
        Specified by:
        -
        containsAll in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        containsAll in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        containsAll in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        isEmpty

        -
        public boolean isEmpty()
        -
        -
        Specified by:
        -
        isEmpty in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        isEmpty in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        isEmpty in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        iterator

        -
        public java.util.Iterator<java.lang.String> iterator()
        -
        -
        Specified by:
        -
        iterator in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        iterator in interface java.lang.Iterable<java.lang.String>
        -
        Specified by:
        -
        iterator in interface java.util.Set<java.lang.String>
        -
        Specified by:
        -
        iterator in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        remove

        -
        public boolean remove​(java.lang.Object o)
        -
        -
        Specified by:
        -
        remove in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        remove in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        remove in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        removeAll

        -
        public boolean removeAll​(java.util.Collection<?> c)
        -
        -
        Specified by:
        -
        removeAll in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        removeAll in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        removeAll in class java.util.AbstractSet<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        removeIf

        -
        public boolean removeIf​(java.util.function.Predicate<? super java.lang.String> filter)
        -
      • -
      - - - -
        -
      • -

        retainAll

        -
        public boolean retainAll​(java.util.Collection<?> c)
        -
        -
        Specified by:
        -
        retainAll in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        retainAll in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        retainAll in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        size

        -
        public int size()
        -
        -
        Specified by:
        -
        size in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        size in interface java.util.Set<java.lang.String>
        -
        Specified by:
        -
        size in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      - - - -
        -
      • -

        toArray

        -
        public java.lang.Object[] toArray()
        -
        -
        Specified by:
        -
        toArray in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        toArray in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        toArray in class java.util.AbstractCollection<java.lang.String>
        -
        Throws:
        -
        java.lang.IllegalStateException - if the set is infinite in size
        -
        -
      • -
      - - - - - -
        -
      • -

        toArray

        -
        public <T> T[] toArray​(T[] a)
        -
        -
        Specified by:
        -
        toArray in interface java.util.Collection<java.lang.String>
        -
        Specified by:
        -
        toArray in interface java.util.Set<java.lang.String>
        -
        Overrides:
        -
        toArray in class java.util.AbstractCollection<java.lang.String>
        -
        Throws:
        -
        java.lang.IllegalStateException - if the set is infinite in size
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        -
        Overrides:
        -
        toString in class java.util.AbstractCollection<java.lang.String>
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.html b/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.html deleted file mode 100644 index 5ed1f84..0000000 --- a/doc/org/unitConverter/unit/UnitDatabase.PrefixedUnitMap.html +++ /dev/null @@ -1,930 +0,0 @@ - - - - - -UnitDatabase.PrefixedUnitMap - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitDatabase.PrefixedUnitMap

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.UnitDatabase.PrefixedUnitMap
    • -
    -
  • -
-
-
    -
  • -
    -
    All Implemented Interfaces:
    -
    java.util.Map<java.lang.String,​Unit>
    -
    -
    -
    Enclosing class:
    -
    UnitDatabase
    -
    -
    -
    private static final class UnitDatabase.PrefixedUnitMap
    -extends java.lang.Object
    -implements java.util.Map<java.lang.String,​Unit>
    -
    A map for units that allows the use of prefixes. -

    - As this map implementation is intended to be used as a sort of "augmented view" of a unit and prefix map, it is - unmodifiable but instead reflects the changes to the maps passed into it. Do not edit this map, instead edit the - maps that were passed in during construction. -

    -

    - The rules for applying prefixes onto units are the following: -

      -
    • Prefixes can only be applied to linear units.
    • -
    • Before attempting to search for prefixes in a unit name, this map will first search for a unit name. So, if - there are two units, "B" and "AB", and a prefix "A", this map will favour the unit "AB" over the unit "B" with - the prefix "A", even though they have the same string.
    • -
    • Longer prefixes are preferred to shorter prefixes. So, if you have units "BC" and "C", and prefixes "AB" and - "A", inputting "ABC" will return the unit "C" with the prefix "AB", not "BC" with the prefix "A".
    • -
    -

    -

    - This map is infinite in size if there is at least one unit and at least one prefix. If it is infinite, some - operations that only work with finite collections, like converting name/entry sets to arrays, will throw an - IllegalStateException. -

    -

    - Because of ambiguities between prefixes (i.e. kilokilo = mega), containsValue(java.lang.Object) and values() - currently ignore prefixes. -

    -
    -
    Since:
    -
    2019-04-13, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    -
      -
    • - - -

      Field Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Fields 
      Modifier and TypeFieldDescription
      private java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>entrySet 
      private java.util.Set<java.lang.String>keySet 
      private java.util.Map<java.lang.String,​UnitPrefix>prefixes -
      The available prefixes for use.
      -
      private java.util.Map<java.lang.String,​Unit>units -
      The units stored in this collection, without prefixes.
      -
      private java.util.Collection<Unit>values 
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      PrefixedUnitMap​(java.util.Map<java.lang.String,​Unit> units, - java.util.Map<java.lang.String,​UnitPrefix> prefixes) -
      Creates the PrefixedUnitMap.
      -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      voidclear() 
      Unitcompute​(java.lang.String key, - java.util.function.BiFunction<? super java.lang.String,​? super Unit,​? extends Unit> remappingFunction) 
      UnitcomputeIfAbsent​(java.lang.String key, - java.util.function.Function<? super java.lang.String,​? extends Unit> mappingFunction) 
      UnitcomputeIfPresent​(java.lang.String key, - java.util.function.BiFunction<? super java.lang.String,​? super Unit,​? extends Unit> remappingFunction) 
      booleancontainsKey​(java.lang.Object key) 
      booleancontainsValue​(java.lang.Object value)
      java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>>entrySet() 
      Unitget​(java.lang.Object key) 
      booleanisEmpty() 
      java.util.Set<java.lang.String>keySet() 
      Unitmerge​(java.lang.String key, - Unit value, - java.util.function.BiFunction<? super Unit,​? super Unit,​? extends Unit> remappingFunction) 
      Unitput​(java.lang.String key, - Unit value) 
      voidputAll​(java.util.Map<? extends java.lang.String,​? extends Unit> m) 
      UnitputIfAbsent​(java.lang.String key, - Unit value) 
      Unitremove​(java.lang.Object key) 
      booleanremove​(java.lang.Object key, - java.lang.Object value) 
      Unitreplace​(java.lang.String key, - Unit value) 
      booleanreplace​(java.lang.String key, - Unit oldValue, - Unit newValue) 
      voidreplaceAll​(java.util.function.BiFunction<? super java.lang.String,​? super Unit,​? extends Unit> function) 
      intsize() 
      java.lang.StringtoString() 
      java.util.Collection<Unit>values()
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • -
      -
        -
      • - - -

        Methods inherited from interface java.util.Map

        -equals, forEach, getOrDefault, hashCode
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        units

        -
        private final java.util.Map<java.lang.String,​Unit> units
        -
        The units stored in this collection, without prefixes.
        -
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        prefixes

        -
        private final java.util.Map<java.lang.String,​UnitPrefix> prefixes
        -
        The available prefixes for use.
        -
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        values

        -
        private transient java.util.Collection<Unit> values
        -
      • -
      - - - -
        -
      • -

        keySet

        -
        private transient java.util.Set<java.lang.String> keySet
        -
      • -
      - - - -
        -
      • -

        entrySet

        -
        private transient java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>> entrySet
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        PrefixedUnitMap

        -
        public PrefixedUnitMap​(java.util.Map<java.lang.String,​Unit> units,
        -                       java.util.Map<java.lang.String,​UnitPrefix> prefixes)
        -
        Creates the PrefixedUnitMap.
        -
        -
        Parameters:
        -
        units - map mapping unit names to units
        -
        prefixes - map mapping prefix names to prefixes
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        clear

        -
        public void clear()
        -
        -
        Specified by:
        -
        clear in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        compute

        -
        public Unit compute​(java.lang.String key,
        -                    java.util.function.BiFunction<? super java.lang.String,​? super Unit,​? extends Unit> remappingFunction)
        -
        -
        Specified by:
        -
        compute in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        computeIfAbsent

        -
        public Unit computeIfAbsent​(java.lang.String key,
        -                            java.util.function.Function<? super java.lang.String,​? extends Unit> mappingFunction)
        -
        -
        Specified by:
        -
        computeIfAbsent in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        computeIfPresent

        -
        public Unit computeIfPresent​(java.lang.String key,
        -                             java.util.function.BiFunction<? super java.lang.String,​? super Unit,​? extends Unit> remappingFunction)
        -
        -
        Specified by:
        -
        computeIfPresent in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        containsKey

        -
        public boolean containsKey​(java.lang.Object key)
        -
        -
        Specified by:
        -
        containsKey in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        containsValue

        -
        public boolean containsValue​(java.lang.Object value)
        -
        - -

        - Because of ambiguities between prefixes (i.e. kilokilo = mega), this method only tests for prefixless units. -

        -
        -
        Specified by:
        -
        containsValue in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        entrySet

        -
        public java.util.Set<java.util.Map.Entry<java.lang.String,​Unit>> entrySet()
        -
        -
        Specified by:
        -
        entrySet in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        get

        -
        public Unit get​(java.lang.Object key)
        -
        -
        Specified by:
        -
        get in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        isEmpty

        -
        public boolean isEmpty()
        -
        -
        Specified by:
        -
        isEmpty in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        keySet

        -
        public java.util.Set<java.lang.String> keySet()
        -
        -
        Specified by:
        -
        keySet in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        merge

        -
        public Unit merge​(java.lang.String key,
        -                  Unit value,
        -                  java.util.function.BiFunction<? super Unit,​? super Unit,​? extends Unit> remappingFunction)
        -
        -
        Specified by:
        -
        merge in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        put

        -
        public Unit put​(java.lang.String key,
        -                Unit value)
        -
        -
        Specified by:
        -
        put in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        putAll

        -
        public void putAll​(java.util.Map<? extends java.lang.String,​? extends Unit> m)
        -
        -
        Specified by:
        -
        putAll in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        putIfAbsent

        -
        public Unit putIfAbsent​(java.lang.String key,
        -                        Unit value)
        -
        -
        Specified by:
        -
        putIfAbsent in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        remove

        -
        public Unit remove​(java.lang.Object key)
        -
        -
        Specified by:
        -
        remove in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        remove

        -
        public boolean remove​(java.lang.Object key,
        -                      java.lang.Object value)
        -
        -
        Specified by:
        -
        remove in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        replace

        -
        public Unit replace​(java.lang.String key,
        -                    Unit value)
        -
        -
        Specified by:
        -
        replace in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        replace

        -
        public boolean replace​(java.lang.String key,
        -                       Unit oldValue,
        -                       Unit newValue)
        -
        -
        Specified by:
        -
        replace in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        replaceAll

        -
        public void replaceAll​(java.util.function.BiFunction<? super java.lang.String,​? super Unit,​? extends Unit> function)
        -
        -
        Specified by:
        -
        replaceAll in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        size

        -
        public int size()
        -
        -
        Specified by:
        -
        size in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        -
        Overrides:
        -
        toString in class java.lang.Object
        -
        -
      • -
      - - - -
        -
      • -

        values

        -
        public java.util.Collection<Unit> values()
        -
        - -

        - Because of ambiguities between prefixes (i.e. kilokilo = mega), this method ignores prefixes. -

        -
        -
        Specified by:
        -
        values in interface java.util.Map<java.lang.String,​Unit>
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/unit/UnitDatabase.html b/doc/org/unitConverter/unit/UnitDatabase.html deleted file mode 100644 index d62f73a..0000000 --- a/doc/org/unitConverter/unit/UnitDatabase.html +++ /dev/null @@ -1,789 +0,0 @@ - - - - - -UnitDatabase - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class UnitDatabase

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.UnitDatabase
    • -
    -
  • -
-
-
    -
  • -
    -
    -
    public final class UnitDatabase
    -extends java.lang.Object
    -
    A database of units, prefixes and dimensions, and their names.
    -
    -
    Since:
    -
    2019-01-07, v0.1.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Constructor Summary

      - - - - - - - - -
      Constructors 
      Constructor and Description
      UnitDatabase() -
      Creates the UnitsDatabase.
      -
      -
    • -
    - -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethod and Description
      voidaddDimension(java.lang.String name, - ObjectProduct<BaseDimension> dimension) -
      Adds a unit dimension to the database.
      -
      voidaddPrefix(java.lang.String name, - UnitPrefix prefix) -
      Adds a unit prefix to the database.
      -
      voidaddUnit(java.lang.String name, - Unit unit) -
      Adds a unit to the database.
      -
      booleancontainsDimensionName(java.lang.String name) -
      Tests if the database has a unit dimension with this name.
      -
      booleancontainsPrefixName(java.lang.String name) -
      Tests if the database has a unit prefix with this name.
      -
      booleancontainsUnitName(java.lang.String name) -
      Tests if the database has a unit with this name, taking prefixes into consideration
      -
      java.util.Map<java.lang.String,ObjectProduct<BaseDimension>>dimensionMap() 
      ObjectProduct<BaseDimension>getDimension(java.lang.String name) -
      Gets a unit dimension from the database using its name.
      -
      ObjectProduct<BaseDimension>getDimensionFromExpression(java.lang.String expression) -
      Uses the database's data to parse an expression into a unit dimension
      -
      UnitPrefixgetPrefix(java.lang.String name) -
      Gets a unit prefix from the database from its name
      -
      UnitPrefixgetPrefixFromExpression(java.lang.String expression) -
      Gets a unit prefix from a prefix expression
      -
      UnitgetUnit(java.lang.String name) -
      Gets a unit from the database from its name, looking for prefixes.
      -
      UnitgetUnitFromExpression(java.lang.String expression) -
      Uses the database's unit data to parse an expression into a unit
      -
      voidloadDimensionFile(java.io.File file) -
      Adds all dimensions from a file, using data from the database to parse them.
      -
      voidloadUnitsFile(java.io.File file) -
      Adds all units from a file, using data from the database to parse them.
      -
      java.util.Map<java.lang.String,UnitPrefix>prefixMap() 
      java.lang.StringtoString() 
      java.util.Map<java.lang.String,Unit>unitMap() -
      Returns a map mapping unit names to units, including units with prefixes.
      -
      java.util.Map<java.lang.String,Unit>unitMapPrefixless() 
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • -
      -
    • -
    -
  • -
-
-
-
    -
  • - -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        UnitDatabase

        -
        public UnitDatabase()
        -
        Creates the UnitsDatabase.
        -
        -
        Since:
        -
        2019-01-10, v0.1.0
        -
        -
      • -
      -
    • -
    - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        addDimension

        -
        public void addDimension(java.lang.String name,
        -                         ObjectProduct<BaseDimension> dimension)
        -
        Adds a unit dimension to the database.
        -
        -
        Parameters:
        -
        name - dimension's name
        -
        dimension - dimension to add
        -
        Throws:
        -
        java.lang.NullPointerException - if name or dimension is null
        -
        Since:
        -
        2019-03-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        addPrefix

        -
        public void addPrefix(java.lang.String name,
        -                      UnitPrefix prefix)
        -
        Adds a unit prefix to the database.
        -
        -
        Parameters:
        -
        name - prefix's name
        -
        prefix - prefix to add
        -
        Throws:
        -
        java.lang.NullPointerException - if name or prefix is null
        -
        Since:
        -
        2019-01-14, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        addUnit

        -
        public void addUnit(java.lang.String name,
        -                    Unit unit)
        -
        Adds a unit to the database.
        -
        -
        Parameters:
        -
        name - unit's name
        -
        unit - unit to add
        -
        Throws:
        -
        java.lang.NullPointerException - if unit is null
        -
        Since:
        -
        2019-01-10, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        containsDimensionName

        -
        public boolean containsDimensionName(java.lang.String name)
        -
        Tests if the database has a unit dimension with this name.
        -
        -
        Parameters:
        -
        name - name to test
        -
        Returns:
        -
        if database contains name
        -
        Since:
        -
        2019-03-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        containsPrefixName

        -
        public boolean containsPrefixName(java.lang.String name)
        -
        Tests if the database has a unit prefix with this name.
        -
        -
        Parameters:
        -
        name - name to test
        -
        Returns:
        -
        if database contains name
        -
        Since:
        -
        2019-01-13, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        containsUnitName

        -
        public boolean containsUnitName(java.lang.String name)
        -
        Tests if the database has a unit with this name, taking prefixes into consideration
        -
        -
        Parameters:
        -
        name - name to test
        -
        Returns:
        -
        if database contains name
        -
        Since:
        -
        2019-01-13, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        dimensionMap

        -
        public java.util.Map<java.lang.String,ObjectProduct<BaseDimension>> dimensionMap()
        -
        -
        Returns:
        -
        a map mapping dimension names to dimensions
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getDimension

        -
        public ObjectProduct<BaseDimension> getDimension(java.lang.String name)
        -
        Gets a unit dimension from the database using its name. - -

        - This method accepts exponents, like "L^3" -

        -
        -
        Parameters:
        -
        name - dimension's name
        -
        Returns:
        -
        dimension
        -
        Since:
        -
        2019-03-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getDimensionFromExpression

        -
        public ObjectProduct<BaseDimension> getDimensionFromExpression(java.lang.String expression)
        -
        Uses the database's data to parse an expression into a unit dimension -

        - The expression is a series of any of the following: -

          -
        • The name of a unit dimension, which multiplies or divides the result based on preceding operators
        • -
        • The operators '*' and '/', which multiply and divide (note that just putting two unit dimensions next to each - other is equivalent to multiplication)
        • -
        • The operator '^' which exponentiates. Exponents must be integers.
        • -
        -
        -
        Parameters:
        -
        expression - expression to parse
        -
        Throws:
        -
        java.lang.IllegalArgumentException - if the expression cannot be parsed
        -
        java.lang.NullPointerException - if expression is null
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        getPrefix

        -
        public UnitPrefix getPrefix(java.lang.String name)
        -
        Gets a unit prefix from the database from its name
        -
        -
        Parameters:
        -
        name - prefix's name
        -
        Returns:
        -
        prefix
        -
        Since:
        -
        2019-01-10, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getPrefixFromExpression

        -
        public UnitPrefix getPrefixFromExpression(java.lang.String expression)
        -
        Gets a unit prefix from a prefix expression -

        - Currently, prefix expressions are much simpler than unit expressions: They are either a number or the name of - another prefix -

        -
        -
        Parameters:
        -
        expression - expression to input
        -
        Returns:
        -
        prefix
        -
        Throws:
        -
        java.lang.IllegalArgumentException - if expression cannot be parsed
        -
        java.lang.NullPointerException - if any argument is null
        -
        Since:
        -
        2019-01-14, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getUnit

        -
        public Unit getUnit(java.lang.String name)
        -
        Gets a unit from the database from its name, looking for prefixes.
        -
        -
        Parameters:
        -
        name - unit's name
        -
        Returns:
        -
        unit
        -
        Since:
        -
        2019-01-10, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        getUnitFromExpression

        -
        public Unit getUnitFromExpression(java.lang.String expression)
        -
        Uses the database's unit data to parse an expression into a unit -

        - The expression is a series of any of the following: -

          -
        • The name of a unit, which multiplies or divides the result based on preceding operators
        • -
        • The operators '*' and '/', which multiply and divide (note that just putting two units or values next to each - other is equivalent to multiplication)
        • -
        • The operator '^' which exponentiates. Exponents must be integers.
        • -
        • A number which is multiplied or divided
        • -
        - This method only works with linear units.
        -
        -
        Parameters:
        -
        expression - expression to parse
        -
        Throws:
        -
        java.lang.IllegalArgumentException - if the expression cannot be parsed
        -
        java.lang.NullPointerException - if expression is null
        -
        Since:
        -
        2019-01-07, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        loadDimensionFile

        -
        public void loadDimensionFile(java.io.File file)
        -
        Adds all dimensions from a file, using data from the database to parse them. -

        - Each line in the file should consist of a name and an expression (parsed by getDimensionFromExpression) separated - by any number of tab characters. -

        -

        - Allowed exceptions: -

          -
        • Anything after a '#' character is considered a comment and ignored.
        • -
        • Blank lines are also ignored
        • -
        • If an expression consists of a single exclamation point, instead of parsing it, this method will search the - database for an existing unit. If no unit is found, an IllegalArgumentException is thrown. This is used to define - initial units and ensure that the database contains them.
        • -
        -
        -
        Parameters:
        -
        file - file to read
        -
        Throws:
        -
        java.lang.IllegalArgumentException - if the file cannot be parsed, found or read
        -
        java.lang.NullPointerException - if file is null
        -
        Since:
        -
        2019-01-13, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        loadUnitsFile

        -
        public void loadUnitsFile(java.io.File file)
        -
        Adds all units from a file, using data from the database to parse them. -

        - Each line in the file should consist of a name and an expression (parsed by getUnitFromExpression) separated by - any number of tab characters. -

        -

        - Allowed exceptions: -

          -
        • Anything after a '#' character is considered a comment and ignored.
        • -
        • Blank lines are also ignored
        • -
        • If an expression consists of a single exclamation point, instead of parsing it, this method will search the - database for an existing unit. If no unit is found, an IllegalArgumentException is thrown. This is used to define - initial units and ensure that the database contains them.
        • -
        -
        -
        Parameters:
        -
        file - file to read
        -
        Throws:
        -
        java.lang.IllegalArgumentException - if the file cannot be parsed, found or read
        -
        java.lang.NullPointerException - if file is null
        -
        Since:
        -
        2019-01-13, v0.1.0
        -
        -
      • -
      - - - -
        -
      • -

        prefixMap

        -
        public java.util.Map<java.lang.String,UnitPrefix> prefixMap()
        -
        -
        Returns:
        -
        a map mapping prefix names to prefixes
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        -
        Overrides:
        -
        toString in class java.lang.Object
        -
        Returns:
        -
        a string stating the number of units, prefixes and dimensions in the database
        -
        -
      • -
      - - - -
        -
      • -

        unitMap

        -
        public java.util.Map<java.lang.String,Unit> unitMap()
        -
        Returns a map mapping unit names to units, including units with prefixes. -

        - The returned map is infinite in size if there is at least one unit and at least one prefix. If it is infinite, - some operations that only work with finite collections, like converting name/entry sets to arrays, will throw an - IllegalStateException. -

        -

        - Specifically, the operations that will throw an IllegalStateException if the map is infinite in size are: -

          -
        • unitMap.entrySet().toArray() (either overloading)
        • -
        • unitMap.keySet().toArray() (either overloading)
        • -
        -

        -

        - Because of ambiguities between prefixes (i.e. kilokilo = mega), the map's containsValue and values() methods currently ignore prefixes. -

        -
        -
        Returns:
        -
        a map mapping unit names to units, including prefixed names
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        unitMapPrefixless

        -
        public java.util.Map<java.lang.String,Unit> unitMapPrefixless()
        -
        -
        Returns:
        -
        a map mapping unit names to units, ignoring prefixes
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/UnitDatabaseTest.html b/doc/org/unitConverter/unit/UnitDatabaseTest.html deleted file mode 100644 index 1b88314..0000000 --- a/doc/org/unitConverter/unit/UnitDatabaseTest.html +++ /dev/null @@ -1,643 +0,0 @@ - - - - - -UnitDatabaseTest - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitDatabaseTest

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.UnitDatabaseTest
    • -
    -
  • -
-
-
    -
  • -
    -
    class UnitDatabaseTest
    -extends java.lang.Object
    -
    A test for the UnitDatabase class. This is NOT part of this program's public API.
    -
    -
    Since:
    -
    2019-04-14, v0.2.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    -
      -
    • - - -

      Constructor Summary

      - - - - - - - - - - -
      Constructors 
      ConstructorDescription
      UnitDatabaseTest() 
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Summary

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      All Methods Instance Methods Concrete Methods 
      Modifier and TypeMethodDescription
      voidtestInfiniteSetExceptions() -
      Confirms that operations that shouldn't function for infinite databases throw an IllegalStateException.
      -
      voidtestPrefixes() -
      Test that prefixes correctly apply to units.
      -
      voidtestPrefixlessUnitMap() -
      Tests the functionnalites of the prefixless unit map.
      -
      voidtestPrefixlessUnits() -
      Tests that the database correctly stores and retrieves units, ignoring prefixes.
      -
      voidtestUnitExpressions() -
      Test that unit expressions return the correct value.
      -
      voidtestUnitIterator() -
      Tests both the unit name iterator and the name-unit entry iterator
      -
      voidtestUnitPrefixCombinations() -
      Determine, given a unit name that could mean multiple things, which meaning is chosen.
      -
      -
        -
      • - - -

        Methods inherited from class java.lang.Object

        -clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
      • -
      -
    • -
    -
    -
  • -
-
-
-
    -
  • - -
    - -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        UnitDatabaseTest

        -
        UnitDatabaseTest()
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        testInfiniteSetExceptions

        -
        @Test
        -public void testInfiniteSetExceptions()
        -
        Confirms that operations that shouldn't function for infinite databases throw an IllegalStateException.
        -
        -
        Since:
        -
        2019-05-03
        -
        -
      • -
      - - - -
        -
      • -

        testPrefixes

        -
        @Test
        -public void testPrefixes()
        -
        Test that prefixes correctly apply to units.
        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        testPrefixlessUnitMap

        -
        @Test
        -public void testPrefixlessUnitMap()
        -
        Tests the functionnalites of the prefixless unit map. - -

        - The map should be an auto-updating view of the units in the database. -

        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        testPrefixlessUnits

        -
        @Test
        -public void testPrefixlessUnits()
        -
        Tests that the database correctly stores and retrieves units, ignoring prefixes.
        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        testUnitExpressions

        -
        @Test
        -public void testUnitExpressions()
        -
        Test that unit expressions return the correct value.
        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        testUnitIterator

        -
        @Test
        -public void testUnitIterator()
        -
        Tests both the unit name iterator and the name-unit entry iterator
        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        testUnitPrefixCombinations

        -
        @Test
        -public void testUnitPrefixCombinations()
        -
        Determine, given a unit name that could mean multiple things, which meaning is chosen. -

        - For example, "ABCU" could mean "A-B-C-U", "AB-C-U", or "A-BC-U". In this case, "AB-C-U" is the correct choice. -

        -
        -
        Since:
        -
        2019-04-14, v0.2.0
        -
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/unit/UnitPrefix.html b/doc/org/unitConverter/unit/UnitPrefix.html deleted file mode 100644 index 04e6256..0000000 --- a/doc/org/unitConverter/unit/UnitPrefix.html +++ /dev/null @@ -1,570 +0,0 @@ - - - - - -UnitPrefix - - - - - - - - - - - - -
-
org.unitConverter.unit
-

Class UnitPrefix

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.UnitPrefix
    • -
    -
  • -
-
-
    -
  • -
    -
    -
    public final class UnitPrefix
    -extends java.lang.Object
    -
    A prefix that can be applied to a LinearUnit to multiply it by some value
    -
    -
    Since:
    -
    2019-10-16
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        valueOf

        -
        public static UnitPrefix valueOf(double multiplier)
        -
        Gets a UnitPrefix from a multiplier
        -
        -
        Parameters:
        -
        multiplier - multiplier of prefix
        -
        Returns:
        -
        prefix
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        valueOf

        -
        public static UnitPrefix valueOf(double multiplier,
        -                                 NameSymbol ns)
        -
        Gets a UnitPrefix from a multiplier and a name
        -
        -
        Parameters:
        -
        multiplier - multiplier of prefix
        -
        ns - name(s) and symbol of prefix
        -
        Returns:
        -
        prefix
        -
        Throws:
        -
        java.lang.NullPointerException - if ns is null
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        dividedBy

        -
        public UnitPrefix dividedBy(double divisor)
        -
        Divides this prefix by a scalar
        -
        -
        Parameters:
        -
        divisor - number to divide by
        -
        Returns:
        -
        quotient of prefix and scalar
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        dividedBy

        -
        public UnitPrefix dividedBy(UnitPrefix other)
        -
        Divides this prefix by other.
        -
        -
        Parameters:
        -
        other - prefix to divide by
        -
        Returns:
        -
        quotient of prefixes
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        equals

        -
        public boolean equals(java.lang.Object obj)
        -
        - - Uses the prefix's multiplier to determine equality.
        -
        -
        Overrides:
        -
        equals in class java.lang.Object
        -
        -
      • -
      - - - -
        -
      • -

        getMultiplier

        -
        public double getMultiplier()
        -
        -
        Returns:
        -
        prefix's multiplier
        -
        Since:
        -
        2019-11-26
        -
        -
      • -
      - - - -
        -
      • -

        getOtherNames

        -
        public final java.util.Set<java.lang.String> getOtherNames()
        -
        -
        Returns:
        -
        other names
        -
        Since:
        -
        2019-11-26
        -
        -
      • -
      - - - -
        -
      • -

        getPrimaryName

        -
        public final java.util.Optional<java.lang.String> getPrimaryName()
        -
        -
        Returns:
        -
        primary name
        -
        Since:
        -
        2019-11-26
        -
        -
      • -
      - - - -
        -
      • -

        getSymbol

        -
        public final java.util.Optional<java.lang.String> getSymbol()
        -
        -
        Returns:
        -
        symbol
        -
        Since:
        -
        2019-11-26
        -
        -
      • -
      - - - -
        -
      • -

        hashCode

        -
        public int hashCode()
        -
        - - Uses the prefix's multiplier to determine a hash code.
        -
        -
        Overrides:
        -
        hashCode in class java.lang.Object
        -
        -
      • -
      - - - -
        -
      • -

        times

        -
        public UnitPrefix times(double multiplicand)
        -
        Multiplies this prefix by a scalar
        -
        -
        Parameters:
        -
        multiplicand - number to multiply by
        -
        Returns:
        -
        product of prefix and scalar
        -
        Since:
        -
        2019-10-16
        -
        -
      • -
      - - - -
        -
      • -

        times

        -
        public UnitPrefix times(UnitPrefix other)
        -
        Multiplies this prefix by other.
        -
        -
        Parameters:
        -
        other - prefix to multiply by
        -
        Returns:
        -
        product of prefixes
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        toExponent

        -
        public UnitPrefix toExponent(double exponent)
        -
        Raises this prefix to an exponent.
        -
        -
        Parameters:
        -
        exponent - exponent to raise to
        -
        Returns:
        -
        result of exponentiation.
        -
        Since:
        -
        2019-04-13, v0.2.0
        -
        -
      • -
      - - - -
        -
      • -

        toString

        -
        public java.lang.String toString()
        -
        -
        Overrides:
        -
        toString in class java.lang.Object
        -
        Returns:
        -
        a string describing the prefix and its multiplier
        -
        -
      • -
      - - - -
        -
      • -

        withName

        -
        public UnitPrefix withName(NameSymbol ns)
        -
        -
        Parameters:
        -
        ns - name(s) and symbol to use
        -
        Returns:
        -
        copy of this prefix with provided name(s) and symbol
        -
        Throws:
        -
        java.lang.NullPointerException - if ns is null
        -
        Since:
        -
        2019-11-26
        -
        -
      • -
      -
    • -
    -
  • -
-
-
- - - - - - - diff --git a/doc/org/unitConverter/unit/UnitTest.html b/doc/org/unitConverter/unit/UnitTest.html deleted file mode 100644 index ea13777..0000000 --- a/doc/org/unitConverter/unit/UnitTest.html +++ /dev/null @@ -1,420 +0,0 @@ - - - - - -UnitTest - - - - - - - - - - - - - - - -
- -
- -
-
- -

Class UnitTest

-
-
-
    -
  • java.lang.Object
  • -
  • -
      -
    • org.unitConverter.unit.UnitTest
    • -
    -
  • -
-
-
    -
  • -
    -
    class UnitTest
    -extends java.lang.Object
    -
    Testing the various Unit classes. This is NOT part of this program's public API.
    -
    -
    Since:
    -
    2018-12-22, v0.1.0
    -
    Author:
    -
    Adrien Hopkins
    -
    -
  • -
-
-
- -
-
-
    -
  • - -
    -
      -
    • - - -

      Field Detail

      - - - -
        -
      • -

        rng

        -
        private static final java.util.Random rng
        -
        A random number generator
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Constructor Detail

      - - - -
        -
      • -

        UnitTest

        -
        UnitTest()
        -
      • -
      -
    • -
    -
    - -
    -
      -
    • - - -

      Method Detail

      - - - -
        -
      • -

        testAdditionAndSubtraction

        -
        @Test
        -public void testAdditionAndSubtraction()
        -
      • -
      - - - -
        -
      • -

        testConversion

        -
        @Test
        -public void testConversion()
        -
      • -
      - - - -
        -
      • -

        testEquals

        -
        @Test
        -public void testEquals()
        -
      • -
      - - - -
        -
      • -

        testMultiplicationAndDivision

        -
        @Test
        -public void testMultiplicationAndDivision()
        -
      • -
      - - - -
        -
      • -

        testPrefixes

        -
        @Test
        -public void testPrefixes()
        -
      • -
      -
    • -
    -
    -
  • -
-
-
-
- - - - diff --git a/doc/org/unitConverter/unit/class-use/BaseDimension.html b/doc/org/unitConverter/unit/class-use/BaseDimension.html deleted file mode 100644 index 7ff411e..0000000 --- a/doc/org/unitConverter/unit/class-use/BaseDimension.html +++ /dev/null @@ -1,470 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.BaseDimension - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.BaseDimension

-
-
- -
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/BaseUnit.html b/doc/org/unitConverter/unit/class-use/BaseUnit.html deleted file mode 100644 index 48598fc..0000000 --- a/doc/org/unitConverter/unit/class-use/BaseUnit.html +++ /dev/null @@ -1,296 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.BaseUnit - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.BaseUnit

-
-
- -
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/BritishImperial.Area.html b/doc/org/unitConverter/unit/class-use/BritishImperial.Area.html deleted file mode 100644 index 5e10bda..0000000 --- a/doc/org/unitConverter/unit/class-use/BritishImperial.Area.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.BritishImperial.Area - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.BritishImperial.Area

-
-
No usage of org.unitConverter.unit.BritishImperial.Area
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/BritishImperial.Length.html b/doc/org/unitConverter/unit/class-use/BritishImperial.Length.html deleted file mode 100644 index 5b5e9dc..0000000 --- a/doc/org/unitConverter/unit/class-use/BritishImperial.Length.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.BritishImperial.Length - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.BritishImperial.Length

-
-
No usage of org.unitConverter.unit.BritishImperial.Length
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/BritishImperial.Mass.html b/doc/org/unitConverter/unit/class-use/BritishImperial.Mass.html deleted file mode 100644 index 4af05d9..0000000 --- a/doc/org/unitConverter/unit/class-use/BritishImperial.Mass.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.BritishImperial.Mass - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.BritishImperial.Mass

-
-
No usage of org.unitConverter.unit.BritishImperial.Mass
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/BritishImperial.Volume.html b/doc/org/unitConverter/unit/class-use/BritishImperial.Volume.html deleted file mode 100644 index 715c7ce..0000000 --- a/doc/org/unitConverter/unit/class-use/BritishImperial.Volume.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.BritishImperial.Volume - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.BritishImperial.Volume

-
-
No usage of org.unitConverter.unit.BritishImperial.Volume
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/BritishImperial.html b/doc/org/unitConverter/unit/class-use/BritishImperial.html deleted file mode 100644 index c2a34ed..0000000 --- a/doc/org/unitConverter/unit/class-use/BritishImperial.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.BritishImperial - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.BritishImperial

-
-
No usage of org.unitConverter.unit.BritishImperial
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/FunctionalUnit.html b/doc/org/unitConverter/unit/class-use/FunctionalUnit.html deleted file mode 100644 index e63c6ab..0000000 --- a/doc/org/unitConverter/unit/class-use/FunctionalUnit.html +++ /dev/null @@ -1,199 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.FunctionalUnit - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.unit.FunctionalUnit

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/unit/class-use/LinearUnit.html b/doc/org/unitConverter/unit/class-use/LinearUnit.html deleted file mode 100644 index 353978e..0000000 --- a/doc/org/unitConverter/unit/class-use/LinearUnit.html +++ /dev/null @@ -1,926 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.LinearUnit - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.LinearUnit

-
-
- -
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/NameSymbol.html b/doc/org/unitConverter/unit/class-use/NameSymbol.html deleted file mode 100644 index eece8b2..0000000 --- a/doc/org/unitConverter/unit/class-use/NameSymbol.html +++ /dev/null @@ -1,324 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.NameSymbol - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.NameSymbol

-
-
-
    -
  • - - - - - - - - - - - - -
    Packages that use NameSymbol 
    PackageDescription
    org.unitConverter.unit -
    Everything to do with the units that make up Unit Converter.
    -
    -
  • -
  • -
      -
    • - - -

      Uses of NameSymbol in org.unitConverter.unit

      - - - - - - - - - - - - -
      Fields in org.unitConverter.unit declared as NameSymbol 
      Modifier and TypeField and Description
      static NameSymbolNameSymbol.EMPTY 
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Methods in org.unitConverter.unit that return NameSymbol 
      Modifier and TypeMethod and Description
      static NameSymbolNameSymbol.of(java.lang.String name, - java.lang.String symbol) -
      Gets a NameSymbol with a primary name, a symbol and no other names.
      -
      static NameSymbolNameSymbol.of(java.lang.String name, - java.lang.String symbol, - java.util.Set<java.lang.String> otherNames) -
      Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolNameSymbol.of(java.lang.String name, - java.lang.String symbol, - java.lang.String... otherNames) -
      h * Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolNameSymbol.of(java.lang.String name, - java.lang.String symbol, - java.lang.String name2) -
      Gets a NameSymbol with a primary name, a symbol and an additional name.
      -
      static NameSymbolNameSymbol.of(java.lang.String name, - java.lang.String symbol, - java.lang.String name2, - java.lang.String name3) -
      Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolNameSymbol.of(java.lang.String name, - java.lang.String symbol, - java.lang.String name2, - java.lang.String name3, - java.lang.String name4) -
      Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolNameSymbol.ofName(java.lang.String name) -
      Gets a NameSymbol with a primary name, no symbol, and no other names.
      -
      static NameSymbolNameSymbol.ofNullable(java.lang.String name, - java.lang.String symbol, - java.util.Set<java.lang.String> otherNames) -
      Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolNameSymbol.ofNullable(java.lang.String name, - java.lang.String symbol, - java.lang.String... otherNames) -
      h * Gets a NameSymbol with a primary name, a symbol and additional names.
      -
      static NameSymbolNameSymbol.ofSymbol(java.lang.String symbol) -
      Gets a NameSymbol with a symbol and no names.
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Methods in org.unitConverter.unit with parameters of type NameSymbol 
      Modifier and TypeMethod and Description
      static UnitUnit.fromConversionFunctions(ObjectProduct<BaseUnit> base, - java.util.function.DoubleUnaryOperator converterFrom, - java.util.function.DoubleUnaryOperator converterTo, - NameSymbol ns) -
      Returns a unit from its base and the functions it uses to convert to and from its base.
      -
      static LinearUnitLinearUnit.fromUnitValue(Unit unit, - double value, - NameSymbol ns) -
      Gets a LinearUnit from a unit and a value.
      -
      static UnitPrefixUnitPrefix.valueOf(double multiplier, - NameSymbol ns) -
      Gets a UnitPrefix from a multiplier and a name
      -
      static LinearUnitLinearUnit.valueOf(ObjectProduct<BaseUnit> unitBase, - double conversionFactor, - NameSymbol ns) -
      Gets a LinearUnit from a unit base and a conversion factor.
      -
      UnitUnit.withName(NameSymbol ns) 
      LinearUnitLinearUnit.withName(NameSymbol ns) 
      UnitPrefixUnitPrefix.withName(NameSymbol ns) 
      BaseUnitBaseUnit.withName(NameSymbol ns) 
      - - - - - - - - - - -
      Constructors in org.unitConverter.unit with parameters of type NameSymbol 
      Constructor and Description
      Unit(ObjectProduct<BaseUnit> unitBase, - NameSymbol ns) -
      Creates the AbstractUnit.
      -
      -
    • -
    -
  • -
-
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/SI.BaseDimensions.html b/doc/org/unitConverter/unit/class-use/SI.BaseDimensions.html deleted file mode 100644 index 4d79069..0000000 --- a/doc/org/unitConverter/unit/class-use/SI.BaseDimensions.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.SI.BaseDimensions - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.SI.BaseDimensions

-
-
No usage of org.unitConverter.unit.SI.BaseDimensions
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/SI.BaseUnits.html b/doc/org/unitConverter/unit/class-use/SI.BaseUnits.html deleted file mode 100644 index ff04c69..0000000 --- a/doc/org/unitConverter/unit/class-use/SI.BaseUnits.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.SI.BaseUnits - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.SI.BaseUnits

-
-
No usage of org.unitConverter.unit.SI.BaseUnits
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/SI.Constants.html b/doc/org/unitConverter/unit/class-use/SI.Constants.html deleted file mode 100644 index cc27e64..0000000 --- a/doc/org/unitConverter/unit/class-use/SI.Constants.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.SI.Constants - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.SI.Constants

-
-
No usage of org.unitConverter.unit.SI.Constants
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/SI.Dimensions.html b/doc/org/unitConverter/unit/class-use/SI.Dimensions.html deleted file mode 100644 index 8dd5ed0..0000000 --- a/doc/org/unitConverter/unit/class-use/SI.Dimensions.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.SI.Dimensions - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.SI.Dimensions

-
-
No usage of org.unitConverter.unit.SI.Dimensions
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/SI.html b/doc/org/unitConverter/unit/class-use/SI.html deleted file mode 100644 index ed8577b..0000000 --- a/doc/org/unitConverter/unit/class-use/SI.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.SI - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.SI

-
-
No usage of org.unitConverter.unit.SI
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/USCustomary.Area.html b/doc/org/unitConverter/unit/class-use/USCustomary.Area.html deleted file mode 100644 index b29fcd1..0000000 --- a/doc/org/unitConverter/unit/class-use/USCustomary.Area.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.USCustomary.Area - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.USCustomary.Area

-
-
No usage of org.unitConverter.unit.USCustomary.Area
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/USCustomary.Length.html b/doc/org/unitConverter/unit/class-use/USCustomary.Length.html deleted file mode 100644 index b7e0c10..0000000 --- a/doc/org/unitConverter/unit/class-use/USCustomary.Length.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.USCustomary.Length - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.USCustomary.Length

-
-
No usage of org.unitConverter.unit.USCustomary.Length
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/USCustomary.Mass.html b/doc/org/unitConverter/unit/class-use/USCustomary.Mass.html deleted file mode 100644 index 310581a..0000000 --- a/doc/org/unitConverter/unit/class-use/USCustomary.Mass.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.USCustomary.Mass - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.USCustomary.Mass

-
-
No usage of org.unitConverter.unit.USCustomary.Mass
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/USCustomary.Volume.html b/doc/org/unitConverter/unit/class-use/USCustomary.Volume.html deleted file mode 100644 index a21595b..0000000 --- a/doc/org/unitConverter/unit/class-use/USCustomary.Volume.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.USCustomary.Volume - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.USCustomary.Volume

-
-
No usage of org.unitConverter.unit.USCustomary.Volume
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/USCustomary.html b/doc/org/unitConverter/unit/class-use/USCustomary.html deleted file mode 100644 index 8625d92..0000000 --- a/doc/org/unitConverter/unit/class-use/USCustomary.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.USCustomary - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.USCustomary

-
-
No usage of org.unitConverter.unit.USCustomary
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/Unit.html b/doc/org/unitConverter/unit/class-use/Unit.html deleted file mode 100644 index 33cd17f..0000000 --- a/doc/org/unitConverter/unit/class-use/Unit.html +++ /dev/null @@ -1,312 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.Unit - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.Unit

-
-
-
    -
  • - - - - - - - - - - - - -
    Packages that use Unit 
    PackageDescription
    org.unitConverter.unit -
    Everything to do with the units that make up Unit Converter.
    -
    -
  • -
  • -
      -
    • - - -

      Uses of Unit in org.unitConverter.unit

      - - - - - - - - - - - - - - - - -
      Subclasses of Unit in org.unitConverter.unit 
      Modifier and TypeClass and Description
      class BaseUnit -
      A unit that other units are defined by.
      -
      class LinearUnit -
      A unit that can be expressed as a product of its base and a number.
      -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Fields in org.unitConverter.unit declared as Unit 
      Modifier and TypeField and Description
      static UnitSI.BEL 
      static UnitSI.CELSIUS 
      static UnitSI.DECIBEL 
      static UnitUSCustomary.FAHRENHEIT 
      static UnitBritishImperial.FAHRENHEIT 
      static UnitSI.NEPER 
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Methods in org.unitConverter.unit that return Unit 
      Modifier and TypeMethod and Description
      static UnitUnit.fromConversionFunctions(ObjectProduct<BaseUnit> base, - java.util.function.DoubleUnaryOperator converterFrom, - java.util.function.DoubleUnaryOperator converterTo) -
      Returns a unit from its base and the functions it uses to convert to and from its base.
      -
      static UnitUnit.fromConversionFunctions(ObjectProduct<BaseUnit> base, - java.util.function.DoubleUnaryOperator converterFrom, - java.util.function.DoubleUnaryOperator converterTo, - NameSymbol ns) -
      Returns a unit from its base and the functions it uses to convert to and from its base.
      -
      UnitUnitDatabase.getUnit(java.lang.String name) -
      Gets a unit from the database from its name, looking for prefixes.
      -
      UnitUnitDatabase.getUnitFromExpression(java.lang.String expression) -
      Uses the database's unit data to parse an expression into a unit
      -
      UnitUnit.withName(NameSymbol ns) 
      - - - - - - - - - - - - - - - - -
      Methods in org.unitConverter.unit that return types with arguments of type Unit 
      Modifier and TypeMethod and Description
      java.util.Map<java.lang.String,Unit>UnitDatabase.unitMap() -
      Returns a map mapping unit names to units, including units with prefixes.
      -
      java.util.Map<java.lang.String,Unit>UnitDatabase.unitMapPrefixless() 
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Methods in org.unitConverter.unit with parameters of type Unit 
      Modifier and TypeMethod and Description
      voidUnitDatabase.addUnit(java.lang.String name, - Unit unit) -
      Adds a unit to the database.
      -
      booleanUnit.canConvertTo(Unit other) -
      Checks if a value expressed in this unit can be converted to a value expressed in other
      -
      doubleUnit.convertTo(Unit other, - double value) -
      Converts a value expressed in this unit to a value expressed in other.
      -
      static LinearUnitLinearUnit.fromUnitValue(Unit unit, - double value) -
      Gets a LinearUnit from a unit and a value.
      -
      static LinearUnitLinearUnit.fromUnitValue(Unit unit, - double value, - NameSymbol ns) -
      Gets a LinearUnit from a unit and a value.
      -
      -
    • -
    -
  • -
-
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry.html b/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry.html deleted file mode 100644 index 46984bb..0000000 --- a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry

-
-
No usage of org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntry
-
- - - diff --git a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator.html b/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator.html deleted file mode 100644 index 2e397dc..0000000 --- a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator

-
-
No usage of org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.PrefixedUnitEntryIterator
-
- - - diff --git a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.html b/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.html deleted file mode 100644 index 7ede112..0000000 --- a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet

-
-
No usage of org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitEntrySet
-
- - - diff --git a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.html b/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.html deleted file mode 100644 index bc25e67..0000000 --- a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator

-
-
No usage of org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator
-
- - - diff --git a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.html b/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.html deleted file mode 100644 index 71e73db..0000000 --- a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet

-
-
No usage of org.unitConverter.unit.UnitDatabase.PrefixedUnitMap.PrefixedUnitNameSet
-
- - - diff --git a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.html b/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.html deleted file mode 100644 index 4565b71..0000000 --- a/doc/org/unitConverter/unit/class-use/UnitDatabase.PrefixedUnitMap.html +++ /dev/null @@ -1,233 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.UnitDatabase.PrefixedUnitMap - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.unit.UnitDatabase.PrefixedUnitMap

-
-
- -
-
- - - diff --git a/doc/org/unitConverter/unit/class-use/UnitDatabase.html b/doc/org/unitConverter/unit/class-use/UnitDatabase.html deleted file mode 100644 index 498974d..0000000 --- a/doc/org/unitConverter/unit/class-use/UnitDatabase.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.UnitDatabase - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.UnitDatabase

-
-
No usage of org.unitConverter.unit.UnitDatabase
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/UnitDatabaseTest.html b/doc/org/unitConverter/unit/class-use/UnitDatabaseTest.html deleted file mode 100644 index 2dc04eb..0000000 --- a/doc/org/unitConverter/unit/class-use/UnitDatabaseTest.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.UnitDatabaseTest - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.unit.UnitDatabaseTest

-
-
No usage of org.unitConverter.unit.UnitDatabaseTest
-
- - - diff --git a/doc/org/unitConverter/unit/class-use/UnitPrefix.html b/doc/org/unitConverter/unit/class-use/UnitPrefix.html deleted file mode 100644 index a4beeb6..0000000 --- a/doc/org/unitConverter/unit/class-use/UnitPrefix.html +++ /dev/null @@ -1,381 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.UnitPrefix - - - - - - - - - - - -
-

Uses of Class
org.unitConverter.unit.UnitPrefix

-
-
- -
- - - - - - diff --git a/doc/org/unitConverter/unit/class-use/UnitTest.html b/doc/org/unitConverter/unit/class-use/UnitTest.html deleted file mode 100644 index 4039629..0000000 --- a/doc/org/unitConverter/unit/class-use/UnitTest.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - -Uses of Class org.unitConverter.unit.UnitTest - - - - - - - - - - - - - - - -
- -
-
-
-

Uses of Class
org.unitConverter.unit.UnitTest

-
-
No usage of org.unitConverter.unit.UnitTest
-
- - - diff --git a/doc/org/unitConverter/unit/package-frame.html b/doc/org/unitConverter/unit/package-frame.html deleted file mode 100644 index 6b5cb13..0000000 --- a/doc/org/unitConverter/unit/package-frame.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - -org.unitConverter.unit - - - - - -

org.unitConverter.unit

- - - diff --git a/doc/org/unitConverter/unit/package-summary.html b/doc/org/unitConverter/unit/package-summary.html deleted file mode 100644 index 82e16b6..0000000 --- a/doc/org/unitConverter/unit/package-summary.html +++ /dev/null @@ -1,279 +0,0 @@ - - - - - -org.unitConverter.unit - - - - - - - - - - - -
-

Package org.unitConverter.unit

-
-
Everything to do with the units that make up Unit Converter.
-
-

See: Description

-
-
-
    -
  • - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Class Summary 
    ClassDescription
    BaseDimension -
    A dimension that defines a BaseUnit
    -
    BaseUnit -
    A unit that other units are defined by.
    -
    BritishImperial -
    A static utility class that contains units in the British Imperial system.
    -
    BritishImperial.Area -
    Imperial units that measure area
    -
    BritishImperial.Length -
    Imperial units that measure length
    -
    BritishImperial.Mass -
    British Imperial units that measure mass.
    -
    BritishImperial.Volume -
    British Imperial units that measure volume
    -
    LinearUnit -
    A unit that can be expressed as a product of its base and a number.
    -
    NameSymbol -
    A class that can be used to specify names and a symbol for a unit.
    -
    SI -
    All of the units, prefixes and dimensions that are used by the SI, as well as some outside the SI.
    -
    SI.BaseDimensions 
    SI.BaseUnits 
    SI.Constants -
    Constants that relate to the SI or other systems.
    -
    SI.Dimensions 
    Unit -
    A unit that is composed of base units.
    -
    UnitDatabase -
    A database of units, prefixes and dimensions, and their names.
    -
    UnitPrefix -
    A prefix that can be applied to a LinearUnit to multiply it by some value
    -
    USCustomary -
    A static utility class that contains units in the US Customary system.
    -
    USCustomary.Area -
    US Customary units that measure area
    -
    USCustomary.Length -
    US Customary units that measure length
    -
    USCustomary.Mass -
    mass units
    -
    USCustomary.Volume -
    Volume units
    -
    -
  • -
- - - -

Package org.unitConverter.unit Description

-
Everything to do with the units that make up Unit Converter.
-
-
Since:
-
2019-10-16, v0.1.0
-
Author:
-
Adrien Hopkins
-
-
- - - - - - diff --git a/doc/org/unitConverter/unit/package-tree.html b/doc/org/unitConverter/unit/package-tree.html deleted file mode 100644 index 9ebd21b..0000000 --- a/doc/org/unitConverter/unit/package-tree.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - -org.unitConverter.unit Class Hierarchy - - - - - - - - - - - -
-

Hierarchy For Package org.unitConverter.unit

-Package Hierarchies: - -
-
-

Class Hierarchy

- -
- - - - - - diff --git a/doc/org/unitConverter/unit/package-use.html b/doc/org/unitConverter/unit/package-use.html deleted file mode 100644 index e4719cc..0000000 --- a/doc/org/unitConverter/unit/package-use.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - -Uses of Package org.unitConverter.unit - - - - - - - - - - - -
-

Uses of Package
org.unitConverter.unit

-
-
- -
- - - - - - diff --git a/doc/overview-frame.html b/doc/overview-frame.html deleted file mode 100644 index 999ded8..0000000 --- a/doc/overview-frame.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - -Overview List - - - - - - - -

 

- - diff --git a/doc/overview-summary.html b/doc/overview-summary.html deleted file mode 100644 index abd6efb..0000000 --- a/doc/overview-summary.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - -Overview - - - - - - - - -
- - - - - - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - -
Packages 
PackageDescription
org.unitConverter -
A program that converts units.
-
org.unitConverter.converterGUI -
The GUI interface of the Unit Converter.
-
org.unitConverter.math -
Supplementary classes that are not related to units, but are necessary for their function.
-
org.unitConverter.unit -
Everything to do with the units that make up Unit Converter.
-
-
- -
- - - - - - - -
- - - - diff --git a/doc/overview-tree.html b/doc/overview-tree.html deleted file mode 100644 index eef28af..0000000 --- a/doc/overview-tree.html +++ /dev/null @@ -1,169 +0,0 @@ - - - - - -Class Hierarchy - - - - - - - - -
- - - - - - - -
- - -
-

Hierarchy For All Packages

-Package Hierarchies: - -
-
-

Class Hierarchy

- -
- -
- - - - - - - -
- - - - diff --git a/doc/package-list b/doc/package-list deleted file mode 100644 index 82e9a56..0000000 --- a/doc/package-list +++ /dev/null @@ -1,4 +0,0 @@ -org.unitConverter -org.unitConverter.converterGUI -org.unitConverter.math -org.unitConverter.unit diff --git a/doc/package-search-index.js b/doc/package-search-index.js deleted file mode 100644 index 9aa13e0..0000000 --- a/doc/package-search-index.js +++ /dev/null @@ -1 +0,0 @@ -packageSearchIndex = [{"l":"All Packages","url":"allpackages-index.html"},{"l":"org.unitConverter"},{"l":"org.unitConverter.converterGUI"},{"l":"org.unitConverter.math"},{"l":"org.unitConverter.unit"}] \ No newline at end of file diff --git a/doc/package-search-index.zip b/doc/package-search-index.zip deleted file mode 100644 index f1a1477..0000000 Binary files a/doc/package-search-index.zip and /dev/null differ diff --git a/doc/resources/glass.png b/doc/resources/glass.png deleted file mode 100644 index a7f591f..0000000 Binary files a/doc/resources/glass.png and /dev/null differ diff --git a/doc/resources/x.png b/doc/resources/x.png deleted file mode 100644 index 30548a7..0000000 Binary files a/doc/resources/x.png and /dev/null differ diff --git a/doc/script.js b/doc/script.js deleted file mode 100644 index b346356..0000000 --- a/doc/script.js +++ /dev/null @@ -1,30 +0,0 @@ -function show(type) -{ - count = 0; - for (var key in methods) { - var row = document.getElementById(key); - if ((methods[key] & type) != 0) { - row.style.display = ''; - row.className = (count++ % 2) ? rowColor : altColor; - } - else - row.style.display = 'none'; - } - updateTabs(type); -} - -function updateTabs(type) -{ - for (var value in tabs) { - var sNode = document.getElementById(tabs[value][0]); - var spanNode = sNode.firstChild; - if (value == type) { - sNode.className = activeTableTab; - spanNode.innerHTML = tabs[value][1]; - } - else { - sNode.className = tableTab; - spanNode.innerHTML = "" + tabs[value][1] + ""; - } - } -} diff --git a/doc/search.js b/doc/search.js deleted file mode 100644 index b773531..0000000 --- a/doc/search.js +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -var noResult = {l: "No results found"}; -var catModules = "Modules"; -var catPackages = "Packages"; -var catTypes = "Types"; -var catMembers = "Members"; -var catSearchTags = "SearchTags"; -var highlight = "$&"; -var camelCaseRegexp = ""; -var secondaryMatcher = ""; -function getHighlightedText(item) { - var ccMatcher = new RegExp(camelCaseRegexp); - var label = item.replace(ccMatcher, highlight); - if (label === item) { - label = item.replace(secondaryMatcher, highlight); - } - return label; -} -function getURLPrefix(ui) { - var urlPrefix=""; - if (useModuleDirectories) { - var slash = "/"; - if (ui.item.category === catModules) { - return ui.item.l + slash; - } else if (ui.item.category === catPackages && ui.item.m) { - return ui.item.m + slash; - } else if ((ui.item.category === catTypes && ui.item.p) || ui.item.category === catMembers) { - $.each(packageSearchIndex, function(index, item) { - if (ui.item.p == item.l) { - urlPrefix = item.m + slash; - } - }); - return urlPrefix; - } else { - return urlPrefix; - } - } - return urlPrefix; -} -var watermark = 'Search'; -$(function() { - $("#search").val(''); - $("#search").prop("disabled", false); - $("#reset").prop("disabled", false); - $("#search").val(watermark).addClass('watermark'); - $("#search").blur(function() { - if ($(this).val().length == 0) { - $(this).val(watermark).addClass('watermark'); - } - }); - $("#search").on('click keydown', function() { - if ($(this).val() == watermark) { - $(this).val('').removeClass('watermark'); - } - }); - $("#reset").click(function() { - $("#search").val(''); - $("#search").focus(); - }); - $("#search").focus(); - $("#search")[0].setSelectionRange(0, 0); -}); -$.widget("custom.catcomplete", $.ui.autocomplete, { - _create: function() { - this._super(); - this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)"); - }, - _renderMenu: function(ul, items) { - var rMenu = this, - currentCategory = ""; - rMenu.menu.bindings = $(); - $.each(items, function(index, item) { - var li; - if (item.l !== noResult.l && item.category !== currentCategory) { - ul.append("
  • " + item.category + "
  • "); - currentCategory = item.category; - } - li = rMenu._renderItemData(ul, item); - if (item.category) { - li.attr("aria-label", item.category + " : " + item.l); - li.attr("class", "resultItem"); - } else { - li.attr("aria-label", item.l); - li.attr("class", "resultItem"); - } - }); - }, - _renderItem: function(ul, item) { - var label = ""; - if (item.category === catModules) { - label = getHighlightedText(item.l); - } else if (item.category === catPackages) { - label = (item.m) - ? getHighlightedText(item.m + "/" + item.l) - : getHighlightedText(item.l); - } else if (item.category === catTypes) { - label = (item.p) - ? getHighlightedText(item.p + "." + item.l) - : getHighlightedText(item.l); - } else if (item.category === catMembers) { - label = getHighlightedText(item.p + "." + (item.c + "." + item.l)); - } else if (item.category === catSearchTags) { - label = getHighlightedText(item.l); - } else { - label = item.l; - } - var li = $("
  • ").appendTo(ul); - var div = $("
    ").appendTo(li); - if (item.category === catSearchTags) { - if (item.d) { - div.html(label + " (" + item.h + ")
    " - + item.d + "
    "); - } else { - div.html(label + " (" + item.h + ")"); - } - } else { - div.html(label); - } - return li; - } -}); -$(function() { - $("#search").catcomplete({ - minLength: 1, - delay: 100, - source: function(request, response) { - var result = new Array(); - var presult = new Array(); - var tresult = new Array(); - var mresult = new Array(); - var tgresult = new Array(); - var secondaryresult = new Array(); - var displayCount = 0; - var exactMatcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(request.term) + "$", "i"); - camelCaseRegexp = ($.ui.autocomplete.escapeRegex(request.term)).split(/(?=[A-Z])/).join("([a-z0-9_$]*?)"); - var camelCaseMatcher = new RegExp("^" + camelCaseRegexp); - secondaryMatcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i"); - - // Return the nested innermost name from the specified object - function nestedName(e) { - return e.l.substring(e.l.lastIndexOf(".") + 1); - } - - function concatResults(a1, a2) { - a1 = a1.concat(a2); - a2.length = 0; - return a1; - } - - if (moduleSearchIndex) { - var mdleCount = 0; - $.each(moduleSearchIndex, function(index, item) { - item.category = catModules; - if (exactMatcher.test(item.l)) { - result.push(item); - mdleCount++; - } else if (camelCaseMatcher.test(item.l)) { - result.push(item); - } else if (secondaryMatcher.test(item.l)) { - secondaryresult.push(item); - } - }); - displayCount = mdleCount; - result = concatResults(result, secondaryresult); - } - if (packageSearchIndex) { - var pCount = 0; - var pkg = ""; - $.each(packageSearchIndex, function(index, item) { - item.category = catPackages; - pkg = (item.m) - ? (item.m + "/" + item.l) - : item.l; - if (exactMatcher.test(item.l)) { - presult.push(item); - pCount++; - } else if (camelCaseMatcher.test(pkg)) { - presult.push(item); - } else if (secondaryMatcher.test(pkg)) { - secondaryresult.push(item); - } - }); - result = result.concat(concatResults(presult, secondaryresult)); - displayCount = (pCount > displayCount) ? pCount : displayCount; - } - if (typeSearchIndex) { - var tCount = 0; - $.each(typeSearchIndex, function(index, item) { - item.category = catTypes; - var s = nestedName(item); - if (exactMatcher.test(s)) { - tresult.push(item); - tCount++; - } else if (camelCaseMatcher.test(s)) { - tresult.push(item); - } else if (secondaryMatcher.test(item.p + "." + item.l)) { - secondaryresult.push(item); - } - }); - result = result.concat(concatResults(tresult, secondaryresult)); - displayCount = (tCount > displayCount) ? tCount : displayCount; - } - if (memberSearchIndex) { - var mCount = 0; - $.each(memberSearchIndex, function(index, item) { - item.category = catMembers; - var s = nestedName(item); - if (exactMatcher.test(s)) { - mresult.push(item); - mCount++; - } else if (camelCaseMatcher.test(s)) { - mresult.push(item); - } else if (secondaryMatcher.test(item.c + "." + item.l)) { - secondaryresult.push(item); - } - }); - result = result.concat(concatResults(mresult, secondaryresult)); - displayCount = (mCount > displayCount) ? mCount : displayCount; - } - if (tagSearchIndex) { - var tgCount = 0; - $.each(tagSearchIndex, function(index, item) { - item.category = catSearchTags; - if (exactMatcher.test(item.l)) { - tgresult.push(item); - tgCount++; - } else if (secondaryMatcher.test(item.l)) { - secondaryresult.push(item); - } - }); - result = result.concat(concatResults(tgresult, secondaryresult)); - displayCount = (tgCount > displayCount) ? tgCount : displayCount; - } - displayCount = (displayCount > 500) ? displayCount : 500; - var counter = function() { - var count = {Modules: 0, Packages: 0, Types: 0, Members: 0, SearchTags: 0}; - var f = function(item) { - count[item.category] += 1; - return (count[item.category] <= displayCount); - }; - return f; - }(); - response(result.filter(counter)); - }, - response: function(event, ui) { - if (!ui.content.length) { - ui.content.push(noResult); - } else { - $("#search").empty(); - } - }, - autoFocus: true, - position: { - collision: "flip" - }, - select: function(event, ui) { - if (ui.item.l !== noResult.l) { - var url = getURLPrefix(ui); - if (ui.item.category === catModules) { - if (useModuleDirectories) { - url += "module-summary.html"; - } else { - url = ui.item.l + "-summary.html"; - } - } else if (ui.item.category === catPackages) { - if (ui.item.url) { - url = ui.item.url; - } else { - url += ui.item.l.replace(/\./g, '/') + "/package-summary.html"; - } - } else if (ui.item.category === catTypes) { - if (ui.item.url) { - url = ui.item.url; - } else if (ui.item.p === "") { - url += ui.item.l + ".html"; - } else { - url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.l + ".html"; - } - } else if (ui.item.category === catMembers) { - if (ui.item.p === "") { - url += ui.item.c + ".html" + "#"; - } else { - url += ui.item.p.replace(/\./g, '/') + "/" + ui.item.c + ".html" + "#"; - } - if (ui.item.url) { - url += ui.item.url; - } else { - url += ui.item.l; - } - } else if (ui.item.category === catSearchTags) { - url += ui.item.u; - } - if (top !== window) { - parent.classFrame.location = pathtoroot + url; - } else { - window.location.href = pathtoroot + url; - } - $("#search").focus(); - } - } - }); -}); diff --git a/doc/stylesheet.css b/doc/stylesheet.css deleted file mode 100644 index fa24676..0000000 --- a/doc/stylesheet.css +++ /dev/null @@ -1,906 +0,0 @@ -/* - * Javadoc style sheet - */ - -@import url('resources/fonts/dejavu.css'); - -/* - * Styles for individual HTML elements. - * - * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular - * HTML element throughout the page. - */ - -body { - background-color:#ffffff; - color:#353833; - font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; - font-size:14px; - margin:0; - padding:0; - height:100%; - width:100%; -} -iframe { - margin:0; - padding:0; - height:100%; - width:100%; - overflow-y:scroll; - border:none; -} -a:link, a:visited { - text-decoration:none; - color:#4A6782; -} -a[href]:hover, a[href]:focus { - text-decoration:none; - color:#bb7a2a; -} -a[name] { - color:#353833; -} -a[name]:before, a[name]:target, a[id]:before, a[id]:target { - content:""; - display:inline-block; - position:relative; - padding-top:129px; - margin-top:-129px; -} -pre { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; -} -h1 { - font-size:20px; -} -h2 { - font-size:18px; -} -h3 { - font-size:16px; - font-style:italic; -} -h4 { - font-size:13px; -} -h5 { - font-size:12px; -} -h6 { - font-size:11px; -} -ul { - list-style-type:disc; -} -code, tt { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; - padding-top:4px; - margin-top:8px; - line-height:1.4em; -} -dt code { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; - padding-top:4px; -} -table tr td dt code { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; - vertical-align:top; - padding-top:4px; -} -sup { - font-size:8px; -} - -/* - * Styles for HTML generated by javadoc. - * - * These are style classes that are used by the standard doclet to generate HTML documentation. - */ - -/* - * Styles for document title and copyright. - */ -.clear { - clear:both; - height:0px; - overflow:hidden; -} -.aboutLanguage { - float:right; - padding:0px 21px; - font-size:11px; - z-index:200; - margin-top:-9px; -} -.legalCopy { - margin-left:.5em; -} -.bar a, .bar a:link, .bar a:visited, .bar a:active { - color:#FFFFFF; - text-decoration:none; -} -.bar a:hover, .bar a:focus { - color:#bb7a2a; -} -.tab { - background-color:#0066FF; - color:#ffffff; - padding:8px; - width:5em; - font-weight:bold; -} -/* - * Styles for navigation bar. - */ -.bar { - background-color:#4D7A97; - color:#FFFFFF; - padding:.8em .5em .4em .8em; - height:auto;/*height:1.8em;*/ - font-size:11px; - margin:0; -} -.navPadding { - padding-top: 107px; -} -.fixedNav { - position:fixed; - width:100%; - z-index:999; - background-color:#ffffff; -} -.topNav { - background-color:#4D7A97; - color:#FFFFFF; - float:left; - padding:0; - width:100%; - clear:right; - height:2.8em; - padding-top:10px; - overflow:hidden; - font-size:12px; -} -.bottomNav { - margin-top:10px; - background-color:#4D7A97; - color:#FFFFFF; - float:left; - padding:0; - width:100%; - clear:right; - height:2.8em; - padding-top:10px; - overflow:hidden; - font-size:12px; -} -.subNav { - background-color:#dee3e9; - float:left; - width:100%; - overflow:hidden; - font-size:12px; -} -.subNav div { - clear:left; - float:left; - padding:0 0 5px 6px; - text-transform:uppercase; -} -ul.navList, ul.subNavList { - float:left; - margin:0 25px 0 0; - padding:0; -} -ul.navList li{ - list-style:none; - float:left; - padding: 5px 6px; - text-transform:uppercase; -} -ul.navListSearch { - float:right; - margin:0 0 0 0; - padding:0; -} -ul.navListSearch li { - list-style:none; - float:right; - padding: 5px 6px; - text-transform:uppercase; -} -ul.navListSearch li label { - position:relative; - right:-16px; -} -ul.subNavList li { - list-style:none; - float:left; -} -.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { - color:#FFFFFF; - text-decoration:none; - text-transform:uppercase; -} -.topNav a:hover, .bottomNav a:hover { - text-decoration:none; - color:#bb7a2a; - text-transform:uppercase; -} -.navBarCell1Rev { - background-color:#F8981D; - color:#253441; - margin: auto 5px; -} -.skipNav { - position:absolute; - top:auto; - left:-9999px; - overflow:hidden; -} -/* - * Styles for page header and footer. - */ -.header, .footer { - clear:both; - margin:0 20px; - padding:5px 0 0 0; -} -.indexNav { - position:relative; - font-size:12px; - background-color:#dee3e9; -} -.indexNav ul { - margin-top:0; - padding:5px; -} -.indexNav ul li { - display:inline; - list-style-type:none; - padding-right:10px; - text-transform:uppercase; -} -.indexNav h1 { - font-size:13px; -} -.title { - color:#2c4557; - margin:10px 0; -} -.subTitle { - margin:5px 0 0 0; -} -.header ul { - margin:0 0 15px 0; - padding:0; -} -.footer ul { - margin:20px 0 5px 0; -} -.header ul li, .footer ul li { - list-style:none; - font-size:13px; -} -/* - * Styles for headings. - */ -div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { - background-color:#dee3e9; - border:1px solid #d0d9e0; - margin:0 0 6px -8px; - padding:7px 5px; -} -ul.blockList ul.blockList ul.blockList li.blockList h3 { - background-color:#dee3e9; - border:1px solid #d0d9e0; - margin:0 0 6px -8px; - padding:7px 5px; -} -ul.blockList ul.blockList li.blockList h3 { - padding:0; - margin:15px 0; -} -ul.blockList li.blockList h2 { - padding:0px 0 20px 0; -} -/* - * Styles for page layout containers. - */ -.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer, -.allClassesContainer, .allPackagesContainer { - clear:both; - padding:10px 20px; - position:relative; -} -.indexContainer { - margin:10px; - position:relative; - font-size:12px; -} -.indexContainer h2 { - font-size:13px; - padding:0 0 3px 0; -} -.indexContainer ul { - margin:0; - padding:0; -} -.indexContainer ul li { - list-style:none; - padding-top:2px; -} -.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { - font-size:12px; - font-weight:bold; - margin:10px 0 0 0; - color:#4E4E4E; -} -.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { - margin:5px 0 10px 0px; - font-size:14px; - font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; -} -.serializedFormContainer dl.nameValue dt { - margin-left:1px; - font-size:1.1em; - display:inline; - font-weight:bold; -} -.serializedFormContainer dl.nameValue dd { - margin:0 0 0 1px; - font-size:1.1em; - display:inline; -} -/* - * Styles for lists. - */ -li.circle { - list-style:circle; -} -ul.horizontal li { - display:inline; - font-size:0.9em; -} -ul.inheritance { - margin:0; - padding:0; -} -ul.inheritance li { - display:inline; - list-style:none; -} -ul.inheritance li ul.inheritance { - margin-left:15px; - padding-left:15px; - padding-top:1px; -} -ul.blockList, ul.blockListLast { - margin:10px 0 10px 0; - padding:0; -} -ul.blockList li.blockList, ul.blockListLast li.blockList { - list-style:none; - margin-bottom:15px; - line-height:1.4; -} -ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { - padding:0px 20px 5px 10px; - border:1px solid #ededed; - background-color:#f8f8f8; -} -ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { - padding:0 0 5px 8px; - background-color:#ffffff; - border:none; -} -ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { - margin-left:0; - padding-left:0; - padding-bottom:15px; - border:none; -} -ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { - list-style:none; - border-bottom:none; - padding-bottom:0; -} -table tr td dl, table tr td dl dt, table tr td dl dd { - margin-top:0; - margin-bottom:1px; -} -/* - * Styles for tables. - */ -.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary, -.requiresSummary, .packagesSummary, .providesSummary, .usesSummary { - width:100%; - border-spacing:0; - border-left:1px solid #EEE; - border-right:1px solid #EEE; - border-bottom:1px solid #EEE; -} -.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary { - padding:0px; -} -.overviewSummary caption, .memberSummary caption, .typeSummary caption, -.useSummary caption, .constantsSummary caption, .deprecatedSummary caption, -.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption { - position:relative; - text-align:left; - background-repeat:no-repeat; - color:#253441; - font-weight:bold; - clear:none; - overflow:hidden; - padding:0px; - padding-top:10px; - padding-left:1px; - margin:0px; - white-space:pre; -} -.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, -.constantsSummary caption a:link, .deprecatedSummary caption a:link, -.requiresSummary caption a:link, .packagesSummary caption a:link, .providesSummary caption a:link, -.usesSummary caption a:link, -.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, -.constantsSummary caption a:hover, .deprecatedSummary caption a:hover, -.requiresSummary caption a:hover, .packagesSummary caption a:hover, .providesSummary caption a:hover, -.usesSummary caption a:hover, -.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, -.constantsSummary caption a:active, .deprecatedSummary caption a:active, -.requiresSummary caption a:active, .packagesSummary caption a:active, .providesSummary caption a:active, -.usesSummary caption a:active, -.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, -.constantsSummary caption a:visited, .deprecatedSummary caption a:visited, -.requiresSummary caption a:visited, .packagesSummary caption a:visited, .providesSummary caption a:visited, -.usesSummary caption a:visited { - color:#FFFFFF; -} -.useSummary caption a:link, .useSummary caption a:hover, .useSummary caption a:active, -.useSummary caption a:visited { - color:#1f389c; -} -.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, -.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span, -.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span, -.usesSummary caption span { - white-space:nowrap; - padding-top:5px; - padding-left:12px; - padding-right:12px; - padding-bottom:7px; - display:inline-block; - float:left; - background-color:#F8981D; - border: none; - height:16px; -} -.memberSummary caption span.activeTableTab span, .packagesSummary caption span.activeTableTab span, -.overviewSummary caption span.activeTableTab span, .typeSummary caption span.activeTableTab span { - white-space:nowrap; - padding-top:5px; - padding-left:12px; - padding-right:12px; - margin-right:3px; - display:inline-block; - float:left; - background-color:#F8981D; - height:16px; -} -.memberSummary caption span.tableTab span, .packagesSummary caption span.tableTab span, -.overviewSummary caption span.tableTab span, .typeSummary caption span.tableTab span { - white-space:nowrap; - padding-top:5px; - padding-left:12px; - padding-right:12px; - margin-right:3px; - display:inline-block; - float:left; - background-color:#4D7A97; - height:16px; -} -.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab, -.packagesSummary caption span.tableTab, .packagesSummary caption span.activeTableTab, -.overviewSummary caption span.tableTab, .overviewSummary caption span.activeTableTab, -.typeSummary caption span.tableTab, .typeSummary caption span.activeTableTab { - padding-top:0px; - padding-left:0px; - padding-right:0px; - background-image:none; - float:none; - display:inline; -} -.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, -.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd, -.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd { - display:none; - width:5px; - position:relative; - float:left; - background-color:#F8981D; -} -.memberSummary .activeTableTab .tabEnd, .packagesSummary .activeTableTab .tabEnd, -.overviewSummary .activeTableTab .tabEnd, .typeSummary .activeTableTab .tabEnd { - display:none; - width:5px; - margin-right:3px; - position:relative; - float:left; - background-color:#F8981D; -} -.memberSummary .tableTab .tabEnd, .packagesSummary .tableTab .tabEnd, -.overviewSummary .tableTab .tabEnd, .typeSummary .tableTab .tabEnd { - display:none; - width:5px; - margin-right:3px; - position:relative; - background-color:#4D7A97; - float:left; -} -.rowColor th, .altColor th { - font-weight:normal; -} -.overviewSummary td, .memberSummary td, .typeSummary td, -.useSummary td, .constantsSummary td, .deprecatedSummary td, -.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td { - text-align:left; - padding:0px 0px 12px 10px; -} -th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .useSummary th, -.constantsSummary th, .packagesSummary th, td.colFirst, td.colSecond, td.colLast, .useSummary td, -.constantsSummary td { - vertical-align:top; - padding-right:0px; - padding-top:8px; - padding-bottom:3px; -} -th.colFirst, th.colSecond, th.colLast, th.colConstructorName, th.colDeprecatedItemName, .constantsSummary th, -.packagesSummary th { - background:#dee3e9; - text-align:left; - padding:8px 3px 3px 7px; -} -td.colFirst, th.colFirst { - font-size:13px; -} -td.colSecond, th.colSecond, td.colLast, th.colConstructorName, th.colDeprecatedItemName, th.colLast { - font-size:13px; -} -.constantsSummary th, .packagesSummary th { - font-size:13px; -} -.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst, -.providesSummary td.colLast { - white-space:normal; - font-size:13px; -} -.overviewSummary td.colFirst, .overviewSummary th.colFirst, -.requiresSummary td.colFirst, .requiresSummary th.colFirst, -.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th, -.usesSummary td.colFirst, .usesSummary th.colFirst, -.providesSummary td.colFirst, .providesSummary th.colFirst, -.memberSummary td.colFirst, .memberSummary th.colFirst, -.memberSummary td.colSecond, .memberSummary th.colSecond, .memberSummary th.colConstructorName, -.typeSummary td.colFirst, .typeSummary th.colFirst { - vertical-align:top; -} -.packagesSummary th.colLast, .packagesSummary td.colLast { - white-space:normal; -} -td.colFirst a:link, td.colFirst a:visited, -td.colSecond a:link, td.colSecond a:visited, -th.colFirst a:link, th.colFirst a:visited, -th.colSecond a:link, th.colSecond a:visited, -th.colConstructorName a:link, th.colConstructorName a:visited, -th.colDeprecatedItemName a:link, th.colDeprecatedItemName a:visited, -.constantValuesContainer td a:link, .constantValuesContainer td a:visited, -.allClassesContainer td a:link, .allClassesContainer td a:visited, -.allPackagesContainer td a:link, .allPackagesContainer td a:visited { - font-weight:bold; -} -.tableSubHeadingColor { - background-color:#EEEEFF; -} -.altColor, .altColor th { - background-color:#FFFFFF; -} -.rowColor, .rowColor th { - background-color:#EEEEEF; -} -/* - * Styles for contents. - */ -.description pre { - margin-top:0; -} -.deprecatedContent { - margin:0; - padding:10px 0; -} -.docSummary { - padding:0; -} -ul.blockList ul.blockList ul.blockList li.blockList h3 { - font-style:normal; -} -div.block { - font-size:14px; - font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; -} -td.colLast div { - padding-top:0px; -} -td.colLast a { - padding-bottom:3px; -} -/* - * Styles for formatting effect. - */ -.sourceLineNo { - color:green; - padding:0 30px 0 0; -} -h1.hidden { - visibility:hidden; - overflow:hidden; - font-size:10px; -} -.block { - display:block; - margin:3px 10px 2px 0px; - color:#474747; -} -.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink, -.moduleLabelInPackage, .moduleLabelInType, .overrideSpecifyLabel, .packageLabelInType, -.packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, -.throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { - font-weight:bold; -} -.deprecationComment, .emphasizedPhrase, .interfaceName { - font-style:italic; -} -.deprecationBlock { - font-size:14px; - font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; - border-style:solid; - border-width:thin; - border-radius:10px; - padding:10px; - margin-bottom:10px; - margin-right:10px; - display:inline-block; -} -div.block div.deprecationComment, div.block div.block span.emphasizedPhrase, -div.block div.block span.interfaceName { - font-style:normal; -} -div.contentContainer ul.blockList li.blockList h2 { - padding-bottom:0px; -} -/* - * Styles for IFRAME. - */ -.mainContainer { - margin:0 auto; - padding:0; - height:100%; - width:100%; - position:fixed; - top:0; - left:0; -} -.leftContainer { - height:100%; - position:fixed; - width:320px; -} -.leftTop { - position:relative; - float:left; - width:315px; - top:0; - left:0; - height:30%; - border-right:6px solid #ccc; - border-bottom:6px solid #ccc; -} -.leftBottom { - position:relative; - float:left; - width:315px; - bottom:0; - left:0; - height:70%; - border-right:6px solid #ccc; - border-top:1px solid #000; -} -.rightContainer { - position:absolute; - left:320px; - top:0; - bottom:0; - height:100%; - right:0; - border-left:1px solid #000; -} -.rightIframe { - margin:0; - padding:0; - height:100%; - right:30px; - width:100%; - overflow:visible; - margin-bottom:30px; -} -/* - * Styles specific to HTML5 elements. - */ -main, nav, header, footer, section { - display:block; -} -/* - * Styles for javadoc search. - */ -.ui-autocomplete-category { - font-weight:bold; - font-size:15px; - padding:7px 0 7px 3px; - background-color:#4D7A97; - color:#FFFFFF; -} -.resultItem { - font-size:13px; -} -.ui-autocomplete { - max-height:85%; - max-width:65%; - overflow-y:scroll; - overflow-x:scroll; - white-space:nowrap; - box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); -} -ul.ui-autocomplete { - position:fixed; - z-index:999999; -} -ul.ui-autocomplete li { - float:left; - clear:both; - width:100%; -} -.resultHighlight { - font-weight:bold; -} -#search { - background-image:url('resources/glass.png'); - background-size:13px; - background-repeat:no-repeat; - background-position:2px 3px; - padding-left:20px; - position:relative; - right:-18px; -} -#reset { - background-color: rgb(255,255,255); - background-image:url('resources/x.png'); - background-position:center; - background-repeat:no-repeat; - background-size:12px; - border:0 none; - width:16px; - height:17px; - position:relative; - left:-4px; - top:-4px; - font-size:0px; -} -.watermark { - color:#545454; -} -.searchTagDescResult { - font-style:italic; - font-size:11px; -} -.searchTagHolderResult { - font-style:italic; - font-size:12px; -} -.searchTagResult:before, .searchTagResult:target { - color:red; -} -.moduleGraph span { - display:none; - position:absolute; -} -.moduleGraph:hover span { - display:block; - margin: -100px 0 0 100px; - z-index: 1; -} -.methodSignature { - white-space:normal; -} - -/* - * Styles for user-provided tables. - * - * borderless: - * No borders, vertical margins, styled caption. - * This style is provided for use with existing doc comments. - * In general, borderless tables should not be used for layout purposes. - * - * plain: - * Plain borders around table and cells, vertical margins, styled caption. - * Best for small tables or for complex tables for tables with cells that span - * rows and columns, when the "striped" style does not work well. - * - * striped: - * Borders around the table and vertical borders between cells, striped rows, - * vertical margins, styled caption. - * Best for tables that have a header row, and a body containing a series of simple rows. - */ - -table.borderless, -table.plain, -table.striped { - margin-top: 10px; - margin-bottom: 10px; -} -table.borderless > caption, -table.plain > caption, -table.striped > caption { - font-weight: bold; - font-size: smaller; -} -table.borderless th, table.borderless td, -table.plain th, table.plain td, -table.striped th, table.striped td { - padding: 2px 5px; -} -table.borderless, -table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th, -table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td { - border: none; -} -table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr { - background-color: transparent; -} -table.plain { - border-collapse: collapse; - border: 1px solid black; -} -table.plain > thead > tr, table.plain > tbody tr, table.plain > tr { - background-color: transparent; -} -table.plain > thead > tr > th, table.plain > tbody > tr > th, table.plain > tr > th, -table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td { - border: 1px solid black; -} -table.striped { - border-collapse: collapse; - border: 1px solid black; -} -table.striped > thead { - background-color: #E3E3E3; -} -table.striped > thead > tr > th, table.striped > thead > tr > td { - border: 1px solid black; -} -table.striped > tbody > tr:nth-child(even) { - background-color: #EEE -} -table.striped > tbody > tr:nth-child(odd) { - background-color: #FFF -} -table.striped > tbody > tr > th, table.striped > tbody > tr > td { - border-left: 1px solid black; - border-right: 1px solid black; -} -table.striped > tbody > tr > th { - font-weight: normal; -} diff --git a/doc/type-search-index.js b/doc/type-search-index.js deleted file mode 100644 index ad28999..0000000 --- a/doc/type-search-index.js +++ /dev/null @@ -1 +0,0 @@ -typeSearchIndex = [{"l":"All Classes","url":"allclasses-index.html"},{"p":"org.unitConverter.unit","l":"BaseDimension"},{"p":"org.unitConverter.unit","l":"SI.BaseDimensions"},{"p":"org.unitConverter.unit","l":"BaseUnit"},{"p":"org.unitConverter.unit","l":"SI.BaseUnits"},{"p":"org.unitConverter.unit","l":"BritishImperial"},{"p":"org.unitConverter.math","l":"ExpressionParser.Builder"},{"p":"org.unitConverter.math","l":"ConditionalExistenceCollections"},{"p":"org.unitConverter.math","l":"DecimalComparison"},{"p":"org.unitConverter.unit","l":"SI.Dimensions"},{"p":"org.unitConverter.math","l":"ExpressionParser"},{"p":"org.unitConverter.unit","l":"LinearUnit"},{"p":"org.unitConverter.math","l":"ObjectProduct"},{"p":"org.unitConverter.unit","l":"SI"},{"p":"org.unitConverter.unit","l":"Unit"},{"p":"org.unitConverter.unit","l":"UnitDatabase"},{"p":"org.unitConverter.unit","l":"UnitPrefix"},{"p":"org.unitConverter.unit","l":"USCustomary"}] \ No newline at end of file diff --git a/doc/type-search-index.zip b/doc/type-search-index.zip deleted file mode 100644 index 9954304..0000000 Binary files a/doc/type-search-index.zip and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..490fda8 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..a4b4429 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..2fe81a7 --- /dev/null +++ b/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..62bd9b9 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,103 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 5b3e468..0000000 --- a/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - 4.0.0 - org.unitConverter - unitConverter - 0.1.0 - Unit Converter - A Java unit converter inspired by GNU Units - - src - - - maven-compiler-plugin - 3.8.0 - - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-surefire-plugin - - false - - - - org.codehaus.mojo - exec-maven-plugin - - org.unitConverter.converterGUI.UnitConverterGUI - - - - org.apache.maven.plugins - maven-jar-plugin - - - - org.unitConverter.converterGUI.UnitConverterGUI - - - - - - - - - junit - junit - 4.11 - - - diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..34ea90c --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/6.3/userguide/multi_project_builds.html + */ + +rootProject.name = 'UnitConverter' diff --git a/settings.txt b/settings.txt new file mode 100644 index 0000000..6a9d120 --- /dev/null +++ b/settings.txt @@ -0,0 +1,4 @@ +precision=6 +rounding_type=SCIENTIFIC +prefix_rule=COMPLEX_REPETITION +one_way=true diff --git a/src/about.txt b/src/about.txt deleted file mode 100644 index 1bad9e8..0000000 --- a/src/about.txt +++ /dev/null @@ -1,12 +0,0 @@ -About Unit Converter v0.2.0 - -Copyright Notice: - -Unit Converter Copyright (C) 2018-2021 Adrien Hopkins -This program comes with ABSOLUTELY NO WARRANTY; -for details read the LICENSE file, section 15 - -This is free software, and you are welcome to redistribute -it under certain conditions; for details go to - -or read the LICENSE file. \ No newline at end of file diff --git a/src/main/java/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java b/src/main/java/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java new file mode 100644 index 0000000..bdc3a2e --- /dev/null +++ b/src/main/java/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java @@ -0,0 +1,95 @@ +/** + * @since 2020-08-26 + */ +package org.unitConverter.converterGUI; + +import java.util.List; +import java.util.function.Predicate; + +import org.unitConverter.unit.SI; +import org.unitConverter.unit.UnitPrefix; + +/** + * A rule that specifies whether prefix repetition is allowed + * + * @since 2020-08-26 + */ +enum DefaultPrefixRepetitionRule implements Predicate> { + NO_REPETITION { + @Override + public boolean test(List prefixes) { + return prefixes.size() <= 1; + } + }, + NO_RESTRICTION { + @Override + public boolean test(List prefixes) { + return true; + } + }, + /** + * You are allowed to have any number of Yotta/Yocto followed by possibly one + * Kilo-Zetta/Milli-Zepto followed by possibly one Deca/Hecto. Same for + * reducing prefixes, don't mix magnifying and reducing. Non-metric + * (including binary) prefixes can't be repeated. + */ + COMPLEX_REPETITION { + @Override + public boolean test(List prefixes) { + // determine whether we are magnifying or reducing + final boolean magnifying; + if (prefixes.isEmpty()) + return true; + else if (prefixes.get(0).getMultiplier() > 1) { + magnifying = true; + } else { + magnifying = false; + } + + // if the first prefix is non-metric (including binary prefixes), + // assume we are using non-metric prefixes + // non-metric prefixes are allowed, but can't be repeated. + if (!SI.DECIMAL_PREFIXES.contains(prefixes.get(0))) + return NO_REPETITION.test(prefixes); + + int part = 0; // 0=yotta/yoctos, 1=kilo-zetta/milli-zepto, + // 2=deka,hecto,deci,centi + + for (final UnitPrefix prefix : prefixes) { + // check that the current prefix is metric and appropriately + // magnifying/reducing + if (!SI.DECIMAL_PREFIXES.contains(prefix)) + return false; + if (magnifying != prefix.getMultiplier() > 1) + return false; + + // check if the current prefix is correct + // since part is set *after* this check, part designates the state + // of the *previous* prefix + switch (part) { + case 0: + // do nothing, any prefix is valid after a yotta + break; + case 1: + // after a kilo-zetta, only deka/hecto are valid + if (SI.THOUSAND_PREFIXES.contains(prefix)) + return false; + break; + case 2: + // deka/hecto must be the last prefix, so this is always invalid + return false; + } + + // set part + if (SI.YOTTA.equals(prefix) || SI.YOCTO.equals(prefix)) { + part = 0; + } else if (SI.THOUSAND_PREFIXES.contains(prefix)) { + part = 1; + } else { + part = 2; + } + } + return true; + } + }; +} diff --git a/src/main/java/org/unitConverter/converterGUI/DelegateListModel.java b/src/main/java/org/unitConverter/converterGUI/DelegateListModel.java new file mode 100644 index 0000000..b80f63d --- /dev/null +++ b/src/main/java/org/unitConverter/converterGUI/DelegateListModel.java @@ -0,0 +1,242 @@ +/** + * Copyright (C) 2018 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.converterGUI; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +import javax.swing.AbstractListModel; + +/** + * A list model that delegates to a list. + *

    + * It is recommended to use the delegate methods in DelegateListModel instead of the delegated list's methods because + * the delegate methods handle updating the list. + *

    + * + * @author Adrien Hopkins + * @since 2019-01-14 + * @since v0.1.0 + */ +final class DelegateListModel extends AbstractListModel implements List { + /** + * @since 2019-01-14 + * @since v0.1.0 + */ + private static final long serialVersionUID = 8985494428224810045L; + + /** + * The list that this model is a delegate to. + * + * @since 2019-01-14 + * @since v0.1.0 + */ + private final List delegate; + + /** + * Creates an empty {@code DelegateListModel}. + * + * @since 2019-04-13 + */ + public DelegateListModel() { + this(new ArrayList<>()); + } + + /** + * Creates the {@code DelegateListModel}. + * + * @param delegate + * list to delegate + * @since 2019-01-14 + * @since v0.1.0 + */ + public DelegateListModel(final List delegate) { + this.delegate = delegate; + } + + @Override + public boolean add(final E element) { + final int index = this.delegate.size(); + final boolean success = this.delegate.add(element); + this.fireIntervalAdded(this, index, index); + return success; + } + + @Override + public void add(final int index, final E element) { + this.delegate.add(index, element); + this.fireIntervalAdded(this, index, index); + } + + @Override + public boolean addAll(final Collection c) { + boolean changed = false; + for (final E e : c) { + if (this.add(e)) { + changed = true; + } + } + return changed; + } + + @Override + public boolean addAll(final int index, final Collection c) { + for (final E e : c) { + this.add(index, e); + } + return !c.isEmpty(); // Since this is a list, it will always change if c has elements. + } + + @Override + public void clear() { + final int oldSize = this.delegate.size(); + this.delegate.clear(); + if (oldSize >= 1) { + this.fireIntervalRemoved(this, 0, oldSize - 1); + } + } + + @Override + public boolean contains(final Object elem) { + return this.delegate.contains(elem); + } + + @Override + public boolean containsAll(final Collection c) { + for (final Object e : c) { + if (!c.contains(e)) + return false; + } + return true; + } + + @Override + public E get(final int index) { + return this.delegate.get(index); + } + + @Override + public E getElementAt(final int index) { + return this.delegate.get(index); + } + + @Override + public int getSize() { + return this.delegate.size(); + } + + @Override + public int indexOf(final Object elem) { + return this.delegate.indexOf(elem); + } + + @Override + public boolean isEmpty() { + return this.delegate.isEmpty(); + } + + @Override + public Iterator iterator() { + return this.delegate.iterator(); + } + + @Override + public int lastIndexOf(final Object elem) { + return this.delegate.lastIndexOf(elem); + } + + @Override + public ListIterator listIterator() { + return this.delegate.listIterator(); + } + + @Override + public ListIterator listIterator(final int index) { + return this.delegate.listIterator(index); + } + + @Override + public E remove(final int index) { + final E returnValue = this.delegate.get(index); + this.delegate.remove(index); + this.fireIntervalRemoved(this, index, index); + return returnValue; + } + + @Override + public boolean remove(final Object o) { + final int index = this.delegate.indexOf(o); + final boolean returnValue = this.delegate.remove(o); + this.fireIntervalRemoved(this, index, index); + return returnValue; + } + + @Override + public boolean removeAll(final Collection c) { + boolean changed = false; + for (final Object e : c) { + if (this.remove(e)) { + changed = true; + } + } + return changed; + } + + @Override + public boolean retainAll(final Collection c) { + final int oldSize = this.size(); + final boolean returnValue = this.delegate.retainAll(c); + this.fireIntervalRemoved(this, this.size(), oldSize - 1); + return returnValue; + } + + @Override + public E set(final int index, final E element) { + final E returnValue = this.delegate.get(index); + this.delegate.set(index, element); + this.fireContentsChanged(this, index, index); + return returnValue; + } + + @Override + public int size() { + return this.delegate.size(); + } + + @Override + public List subList(final int fromIndex, final int toIndex) { + return this.delegate.subList(fromIndex, toIndex); + } + + @Override + public Object[] toArray() { + return this.delegate.toArray(); + } + + @Override + public T[] toArray(final T[] a) { + return this.delegate.toArray(a); + } + + @Override + public String toString() { + return this.delegate.toString(); + } +} diff --git a/src/main/java/org/unitConverter/converterGUI/FilterComparator.java b/src/main/java/org/unitConverter/converterGUI/FilterComparator.java new file mode 100644 index 0000000..9b77f21 --- /dev/null +++ b/src/main/java/org/unitConverter/converterGUI/FilterComparator.java @@ -0,0 +1,129 @@ +/** + * Copyright (C) 2018 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.converterGUI; + +import java.util.Comparator; +import java.util.Objects; + +/** + * A comparator that compares strings using a filter. + * + * @author Adrien Hopkins + * @since 2019-01-15 + * @since v0.1.0 + */ +final class FilterComparator implements Comparator { + /** + * The filter that the comparator is filtered by. + * + * @since 2019-01-15 + * @since v0.1.0 + */ + private final String filter; + /** + * The comparator to use if the arguments are otherwise equal. + * + * @since 2019-01-15 + * @since v0.1.0 + */ + private final Comparator comparator; + /** + * Whether or not the comparison is case-sensitive. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + private final boolean caseSensitive; + + /** + * Creates the {@code FilterComparator}. + * + * @param filter + * @since 2019-01-15 + * @since v0.1.0 + */ + public FilterComparator(final String filter) { + this(filter, null); + } + + /** + * Creates the {@code FilterComparator}. + * + * @param filter + * string to filter by + * @param comparator + * comparator to fall back to if all else fails, null is compareTo. + * @throws NullPointerException + * if filter is null + * @since 2019-01-15 + * @since v0.1.0 + */ + public FilterComparator(final String filter, final Comparator comparator) { + this(filter, comparator, false); + } + + /** + * Creates the {@code FilterComparator}. + * + * @param filter + * string to filter by + * @param comparator + * comparator to fall back to if all else fails, null is compareTo. + * @param caseSensitive + * whether or not the comparator is case-sensitive + * @throws NullPointerException + * if filter is null + * @since 2019-04-14 + * @since v0.2.0 + */ + public FilterComparator(final String filter, final Comparator comparator, final boolean caseSensitive) { + this.filter = Objects.requireNonNull(filter, "filter must not be null."); + this.comparator = comparator; + this.caseSensitive = caseSensitive; + } + + @Override + public int compare(final String arg0, final String arg1) { + // if this is case insensitive, make them lowercase + final String str0, str1; + if (this.caseSensitive) { + str0 = arg0; + str1 = arg1; + } else { + str0 = arg0.toLowerCase(); + str1 = arg1.toLowerCase(); + } + + // elements that start with the filter always go first + if (str0.startsWith(this.filter) && !str1.startsWith(this.filter)) + return -1; + else if (!str0.startsWith(this.filter) && str1.startsWith(this.filter)) + return 1; + + // elements that contain the filter but don't start with them go next + if (str0.contains(this.filter) && !str1.contains(this.filter)) + return -1; + else if (!str0.contains(this.filter) && !str1.contains(this.filter)) + return 1; + + // other elements go last + if (this.comparator == null) + return str0.compareTo(str1); + else + return this.comparator.compare(str0, str1); + } +} diff --git a/src/main/java/org/unitConverter/converterGUI/GridBagBuilder.java b/src/main/java/org/unitConverter/converterGUI/GridBagBuilder.java new file mode 100644 index 0000000..f1229b2 --- /dev/null +++ b/src/main/java/org/unitConverter/converterGUI/GridBagBuilder.java @@ -0,0 +1,479 @@ +/** + * Copyright (C) 2018 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.converterGUI; + +import java.awt.GridBagConstraints; +import java.awt.Insets; + +/** + * A builder for Java's {@link java.awt.GridBagConstraints} class. + * + * @author Adrien Hopkins + * @since 2018-11-30 + * @since v0.1.0 + */ +final class GridBagBuilder { + /** + * The built {@code GridBagConstraints}'s {@code gridx} property. + *

    + * Specifies the cell containing the leading edge of the component's display area, where the first cell in a row has + * gridx=0. The leading edge of a component's display area is its left edge for a horizontal, + * left-to-right container and its right edge for a horizontal, right-to-left container. The value + * RELATIVE specifies that the component be placed immediately following the component that was added + * to the container just before this component was added. + *

    + * The default value is RELATIVE. gridx should be a non-negative value. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#gridy + * @see java.awt.ComponentOrientation + */ + private final int gridx; + + /** + * The built {@code GridBagConstraints}'s {@code gridy} property. + *

    + * Specifies the cell at the top of the component's display area, where the topmost cell has gridy=0. + * The value RELATIVE specifies that the component be placed just below the component that was added to + * the container just before this component was added. + *

    + * The default value is RELATIVE. gridy should be a non-negative value. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#gridx + */ + private final int gridy; + + /** + * The built {@code GridBagConstraints}'s {@code gridwidth} property. + *

    + * Specifies the number of cells in a row for the component's display area. + *

    + * Use REMAINDER to specify that the component's display area will be from gridx to the + * last cell in the row. Use RELATIVE to specify that the component's display area will be from + * gridx to the next to the last one in its row. + *

    + * gridwidth should be non-negative and the default value is 1. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#gridheight + */ + private final int gridwidth; + + /** + * The built {@code GridBagConstraints}'s {@code gridheight} property. + *

    + * Specifies the number of cells in a column for the component's display area. + *

    + * Use REMAINDER to specify that the component's display area will be from gridy to the + * last cell in the column. Use RELATIVE to specify that the component's display area will be from + * gridy to the next to the last one in its column. + *

    + * gridheight should be a non-negative value and the default value is 1. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#gridwidth + */ + private final int gridheight; + + /** + * The built {@code GridBagConstraints}'s {@code weightx} property. + *

    + * Specifies how to distribute extra horizontal space. + *

    + * The grid bag layout manager calculates the weight of a column to be the maximum weightx of all the + * components in a column. If the resulting layout is smaller horizontally than the area it needs to fill, the extra + * space is distributed to each column in proportion to its weight. A column that has a weight of zero receives no + * extra space. + *

    + * If all the weights are zero, all the extra space appears between the grids of the cell and the left and right + * edges. + *

    + * The default value of this field is 0. weightx should be a non-negative value. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#weighty + */ + private double weightx; + + /** + * The built {@code GridBagConstraints}'s {@code weighty} property. + *

    + * Specifies how to distribute extra vertical space. + *

    + * The grid bag layout manager calculates the weight of a row to be the maximum weighty of all the + * components in a row. If the resulting layout is smaller vertically than the area it needs to fill, the extra + * space is distributed to each row in proportion to its weight. A row that has a weight of zero receives no extra + * space. + *

    + * If all the weights are zero, all the extra space appears between the grids of the cell and the top and bottom + * edges. + *

    + * The default value of this field is 0. weighty should be a non-negative value. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#weightx + */ + private double weighty; + + /** + * The built {@code GridBagConstraints}'s {@code anchor} property. + *

    + * This field is used when the component is smaller than its display area. It determines where, within the display + * area, to place the component. + *

    + * There are three kinds of possible values: orientation relative, baseline relative and absolute. Orientation + * relative values are interpreted relative to the container's component orientation property, baseline relative + * values are interpreted relative to the baseline and absolute values are not. The absolute values are: + * CENTER, NORTH, NORTHEAST, EAST, SOUTHEAST, + * SOUTH, SOUTHWEST, WEST, and NORTHWEST. The orientation + * relative values are: PAGE_START, PAGE_END, LINE_START, + * LINE_END, FIRST_LINE_START, FIRST_LINE_END, LAST_LINE_START + * and LAST_LINE_END. The baseline relative values are: BASELINE, + * BASELINE_LEADING, BASELINE_TRAILING, ABOVE_BASELINE, + * ABOVE_BASELINE_LEADING, ABOVE_BASELINE_TRAILING, BELOW_BASELINE, + * BELOW_BASELINE_LEADING, and BELOW_BASELINE_TRAILING. The default value is + * CENTER. + * + * @serial + * @see #clone() + * @see java.awt.ComponentOrientation + */ + private int anchor; + + /** + * The built {@code GridBagConstraints}'s {@code fill} property. + *

    + * This field is used when the component's display area is larger than the component's requested size. It determines + * whether to resize the component, and if so, how. + *

    + * The following values are valid for fill: + * + *

      + *
    • NONE: Do not resize the component. + *
    • HORIZONTAL: Make the component wide enough to fill its display area horizontally, but do not + * change its height. + *
    • VERTICAL: Make the component tall enough to fill its display area vertically, but do not change + * its width. + *
    • BOTH: Make the component fill its display area entirely. + *
    + *

    + * The default value is NONE. + * + * @serial + * @see #clone() + */ + private int fill; + + /** + * The built {@code GridBagConstraints}'s {@code insets} property. + *

    + * This field specifies the external padding of the component, the minimum amount of space between the component and + * the edges of its display area. + *

    + * The default value is new Insets(0, 0, 0, 0). + * + * @serial + * @see #clone() + */ + private Insets insets; + + /** + * The built {@code GridBagConstraints}'s {@code ipadx} property. + *

    + * This field specifies the internal padding of the component, how much space to add to the minimum width of the + * component. The width of the component is at least its minimum width plus ipadx pixels. + *

    + * The default value is 0. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#ipady + */ + private int ipadx; + + /** + * The built {@code GridBagConstraints}'s {@code ipady} property. + *

    + * This field specifies the internal padding, that is, how much space to add to the minimum height of the component. + * The height of the component is at least its minimum height plus ipady pixels. + *

    + * The default value is 0. + * + * @serial + * @see #clone() + * @see java.awt.GridBagConstraints#ipadx + */ + private int ipady; + + /** + * @param gridx + * x position + * @param gridy + * y position + * @since 2018-11-30 + * @since v0.1.0 + */ + public GridBagBuilder(final int gridx, final int gridy) { + this(gridx, gridy, 1, 1); + } + + /** + * @param gridx + * x position + * @param gridy + * y position + * @param gridwidth + * number of cells occupied horizontally + * @param gridheight + * number of cells occupied vertically + * @since 2018-11-30 + * @since v0.1.0 + */ + public GridBagBuilder(final int gridx, final int gridy, final int gridwidth, final int gridheight) { + this(gridx, gridy, gridwidth, gridheight, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, + new Insets(0, 0, 0, 0), 0, 0); + } + + /** + * @param gridx + * x position + * @param gridy + * y position + * @param gridwidth + * number of cells occupied horizontally + * @param gridheight + * number of cells occupied vertically + * @param weightx + * @param weighty + * @param anchor + * @param fill + * @param insets + * @param ipadx + * @param ipady + * @since 2018-11-30 + * @since v0.1.0 + */ + private GridBagBuilder(final int gridx, final int gridy, final int gridwidth, final int gridheight, + final double weightx, final double weighty, final int anchor, final int fill, final Insets insets, + final int ipadx, final int ipady) { + super(); + this.gridx = gridx; + this.gridy = gridy; + this.gridwidth = gridwidth; + this.gridheight = gridheight; + this.weightx = weightx; + this.weighty = weighty; + this.anchor = anchor; + this.fill = fill; + this.insets = (Insets) insets.clone(); + this.ipadx = ipadx; + this.ipady = ipady; + } + + /** + * @return {@code GridBagConstraints} created by this builder + * @since 2018-11-30 + * @since v0.1.0 + */ + public GridBagConstraints build() { + return new GridBagConstraints(this.gridx, this.gridy, this.gridwidth, this.gridheight, this.weightx, + this.weighty, this.anchor, this.fill, this.insets, this.ipadx, this.ipady); + } + + /** + * @return anchor + * @since 2018-11-30 + * @since v0.1.0 + */ + public int getAnchor() { + return this.anchor; + } + + /** + * @return fill + * @since 2018-11-30 + * @since v0.1.0 + */ + public int getFill() { + return this.fill; + } + + /** + * @return gridheight + * @since 2018-11-30 + * @since v0.1.0 + */ + public int getGridheight() { + return this.gridheight; + } + + /** + * @return gridwidth + * @since 2018-11-30 + * @since v0.1.0 + */ + public int getGridwidth() { + return this.gridwidth; + } + + /** + * @return gridx + * @since 2018-11-30 + * @since v0.1.0 + */ + public int getGridx() { + return this.gridx; + } + + /** + * @return gridy + * @since 2018-11-30 + * @since v0.1.0 + */ + public int getGridy() { + return this.gridy; + } + + /** + * @return insets + * @since 2018-11-30 + * @since v0.1.0 + */ + public Insets getInsets() { + return this.insets; + } + + /** + * @return ipadx + * @since 2018-11-30 + * @since v0.1.0 + */ + public int getIpadx() { + return this.ipadx; + } + + /** + * @return ipady + * @since 2018-11-30 + * @since v0.1.0 + */ + public int getIpady() { + return this.ipady; + } + + /** + * @return weightx + * @since 2018-11-30 + * @since v0.1.0 + */ + public double getWeightx() { + return this.weightx; + } + + /** + * @return weighty + * @since 2018-11-30 + * @since v0.1.0 + */ + public double getWeighty() { + return this.weighty; + } + + /** + * @param anchor + * anchor to set + * @since 2018-11-30 + * @since v0.1.0 + */ + public GridBagBuilder setAnchor(final int anchor) { + this.anchor = anchor; + return this; + } + + /** + * @param fill + * fill to set + * @since 2018-11-30 + * @since v0.1.0 + */ + public GridBagBuilder setFill(final int fill) { + this.fill = fill; + return this; + } + + /** + * @param insets + * insets to set + * @since 2018-11-30 + * @since v0.1.0 + */ + public GridBagBuilder setInsets(final Insets insets) { + this.insets = insets; + return this; + } + + /** + * @param ipadx + * ipadx to set + * @since 2018-11-30 + * @since v0.1.0 + */ + public GridBagBuilder setIpadx(final int ipadx) { + this.ipadx = ipadx; + return this; + } + + /** + * @param ipady + * ipady to set + * @since 2018-11-30 + * @since v0.1.0 + */ + public GridBagBuilder setIpady(final int ipady) { + this.ipady = ipady; + return this; + } + + /** + * @param weightx + * weightx to set + * @since 2018-11-30 + * @since v0.1.0 + */ + public GridBagBuilder setWeightx(final double weightx) { + this.weightx = weightx; + return this; + } + + /** + * @param weighty + * weighty to set + * @since 2018-11-30 + * @since v0.1.0 + */ + public GridBagBuilder setWeighty(final double weighty) { + this.weighty = weighty; + return this; + } +} diff --git a/src/main/java/org/unitConverter/converterGUI/MutablePredicate.java b/src/main/java/org/unitConverter/converterGUI/MutablePredicate.java new file mode 100644 index 0000000..e15b3cd --- /dev/null +++ b/src/main/java/org/unitConverter/converterGUI/MutablePredicate.java @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.converterGUI; + +import java.util.function.Predicate; + +/** + * A container for a predicate, which can be changed later. + * + * @author Adrien Hopkins + * @since 2019-04-13 + * @since v0.2.0 + */ +final class MutablePredicate implements Predicate { + /** + * The predicate stored in this {@code MutablePredicate} + * + * @since 2019-04-13 + * @since v0.2.0 + */ + private Predicate predicate; + + /** + * Creates the {@code MutablePredicate}. + * + * @since 2019-04-13 + * @since v0.2.0 + */ + public MutablePredicate(final Predicate predicate) { + this.predicate = predicate; + } + + /** + * @return predicate + * @since 2019-04-13 + * @since v0.2.0 + */ + public final Predicate getPredicate() { + return this.predicate; + } + + /** + * @param predicate + * new value of predicate + * @since 2019-04-13 + * @since v0.2.0 + */ + public final void setPredicate(final Predicate predicate) { + this.predicate = predicate; + } + + @Override + public boolean test(final T t) { + return this.predicate.test(t); + } +} diff --git a/src/main/java/org/unitConverter/converterGUI/SearchBoxList.java b/src/main/java/org/unitConverter/converterGUI/SearchBoxList.java new file mode 100644 index 0000000..10ef589 --- /dev/null +++ b/src/main/java/org/unitConverter/converterGUI/SearchBoxList.java @@ -0,0 +1,307 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.converterGUI; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.function.Predicate; + +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; + +/** + * @author Adrien Hopkins + * @since 2019-04-13 + * @since v0.2.0 + */ +final class SearchBoxList extends JPanel { + + /** + * @since 2019-04-13 + * @since v0.2.0 + */ + private static final long serialVersionUID = 6226930279415983433L; + + /** + * The text to place in an empty search box. + * + * @since 2019-04-13 + * @since v0.2.0 + */ + private static final String EMPTY_TEXT = "Search..."; + + /** + * The color to use for an empty foreground. + * + * @since 2019-04-13 + * @since v0.2.0 + */ + private static final Color EMPTY_FOREGROUND = new Color(192, 192, 192); + + // the components + private final Collection itemsToFilter; + private final DelegateListModel listModel; + private final JTextField searchBox; + private final JList searchItems; + + private boolean searchBoxEmpty = true; + + // I need to do this because, for some reason, Swing is auto-focusing my + // search box without triggering a focus + // event. + private boolean searchBoxFocused = false; + + private Predicate customSearchFilter = o -> true; + private final Comparator defaultOrdering; + private final boolean caseSensitive; + + /** + * Creates the {@code SearchBoxList}. + * + * @param itemsToFilter items to put in the list + * @since 2019-04-14 + */ + public SearchBoxList(final Collection itemsToFilter) { + this(itemsToFilter, null, false); + } + + /** + * Creates the {@code SearchBoxList}. + * + * @param itemsToFilter items to put in the list + * @param defaultOrdering default ordering of items after filtration + * (null=Comparable) + * @param caseSensitive whether or not the filtration is case-sensitive + * + * @since 2019-04-13 + * @since v0.2.0 + */ + public SearchBoxList(final Collection itemsToFilter, + final Comparator defaultOrdering, + final boolean caseSensitive) { + super(new BorderLayout(), true); + this.itemsToFilter = itemsToFilter; + this.defaultOrdering = defaultOrdering; + this.caseSensitive = caseSensitive; + + // create the components + this.listModel = new DelegateListModel<>(new ArrayList<>(itemsToFilter)); + this.searchItems = new JList<>(this.listModel); + + this.searchBox = new JTextField(EMPTY_TEXT); + this.searchBox.setForeground(EMPTY_FOREGROUND); + + // add them to the panel + this.add(this.searchBox, BorderLayout.PAGE_START); + this.add(new JScrollPane(this.searchItems), BorderLayout.CENTER); + + // set up the search box + this.searchBox.addFocusListener(new FocusListener() { + @Override + public void focusGained(final FocusEvent e) { + SearchBoxList.this.searchBoxFocusGained(e); + } + + @Override + public void focusLost(final FocusEvent e) { + SearchBoxList.this.searchBoxFocusLost(e); + } + }); + + this.searchBox.addCaretListener(e -> this.searchBoxTextChanged()); + this.searchBoxEmpty = true; + } + + /** + * Adds an additional filter for searching. + * + * @param filter filter to add. + * @since 2019-04-13 + * @since v0.2.0 + */ + public void addSearchFilter(final Predicate filter) { + this.customSearchFilter = this.customSearchFilter.and(filter); + } + + /** + * Resets the search filter. + * + * @since 2019-04-13 + * @since v0.2.0 + */ + public void clearSearchFilters() { + this.customSearchFilter = o -> true; + } + + /** + * @return this component's search box component + * @since 2019-04-14 + * @since v0.2.0 + */ + public final JTextField getSearchBox() { + return this.searchBox; + } + + /** + * @param searchText text to search for + * @return a filter that filters out that text, based on this list's case + * sensitive setting + * @since 2019-04-14 + * @since v0.2.0 + */ + private Predicate getSearchFilter(final String searchText) { + if (this.caseSensitive) + return string -> string.contains(searchText); + else + return string -> string.toLowerCase() + .contains(searchText.toLowerCase()); + } + + /** + * @return this component's list component + * @since 2019-04-14 + * @since v0.2.0 + */ + public final JList getSearchList() { + return this.searchItems; + } + + /** + * @return index selected in item list + * @since 2019-04-14 + * @since v0.2.0 + */ + public int getSelectedIndex() { + return this.searchItems.getSelectedIndex(); + } + + /** + * @return value selected in item list + * @since 2019-04-13 + * @since v0.2.0 + */ + public String getSelectedValue() { + return this.searchItems.getSelectedValue(); + } + + /** + * Re-applies the filters. + * + * @since 2019-04-13 + * @since v0.2.0 + */ + public void reapplyFilter() { + final String searchText = this.searchBoxEmpty ? "" + : this.searchBox.getText(); + final FilterComparator comparator = new FilterComparator(searchText, + this.defaultOrdering, this.caseSensitive); + final Predicate searchFilter = this.getSearchFilter(searchText); + + this.listModel.clear(); + this.itemsToFilter.forEach(string -> { + if (searchFilter.test(string)) { + this.listModel.add(string); + } + }); + + // applies the custom filters + this.listModel.removeIf(this.customSearchFilter.negate()); + + // sorts the remaining items + this.listModel.sort(comparator); + } + + /** + * Runs whenever the search box gains focus. + * + * @param e focus event + * @since 2019-04-13 + * @since v0.2.0 + */ + private void searchBoxFocusGained(final FocusEvent e) { + this.searchBoxFocused = true; + if (this.searchBoxEmpty) { + this.searchBox.setText(""); + this.searchBox.setForeground(Color.BLACK); + } + } + + /** + * Runs whenever the search box loses focus. + * + * @param e focus event + * @since 2019-04-13 + * @since v0.2.0 + */ + private void searchBoxFocusLost(final FocusEvent e) { + this.searchBoxFocused = false; + if (this.searchBoxEmpty) { + this.searchBox.setText(EMPTY_TEXT); + this.searchBox.setForeground(EMPTY_FOREGROUND); + } + } + + /** + * Runs whenever the text in the search box is changed. + *

    + * Reapplies the search filter, and custom filters. + *

    + * + * @since 2019-04-14 + * @since v0.2.0 + */ + private void searchBoxTextChanged() { + if (this.searchBoxFocused) { + this.searchBoxEmpty = this.searchBox.getText().equals(""); + } + final String searchText = this.searchBoxEmpty ? "" + : this.searchBox.getText(); + final FilterComparator comparator = new FilterComparator(searchText, + this.defaultOrdering, this.caseSensitive); + final Predicate searchFilter = this.getSearchFilter(searchText); + + // initialize list with items that match the filter then sort + this.listModel.clear(); + this.itemsToFilter.forEach(string -> { + if (searchFilter.test(string)) { + this.listModel.add(string); + } + }); + + // applies the custom filters + this.listModel.removeIf(this.customSearchFilter.negate()); + + // sorts the remaining items + this.listModel.sort(comparator); + } + + /** + * Manually updates the search box's item list. + * + * @since 2020-08-27 + */ + public void updateList() { + this.searchBoxTextChanged(); + } +} diff --git a/src/main/java/org/unitConverter/converterGUI/UnitConverterGUI.java b/src/main/java/org/unitConverter/converterGUI/UnitConverterGUI.java new file mode 100644 index 0000000..c046846 --- /dev/null +++ b/src/main/java/org/unitConverter/converterGUI/UnitConverterGUI.java @@ -0,0 +1,1426 @@ +/** + * Copyright (C) 2018-2021 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.converterGUI; + +import java.awt.BorderLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.event.KeyEvent; +import java.io.BufferedWriter; +import java.io.IOException; +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JSlider; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.WindowConstants; +import javax.swing.border.TitledBorder; + +import org.unitConverter.math.ConditionalExistenceCollections; +import org.unitConverter.math.ObjectProduct; +import org.unitConverter.unit.BaseDimension; +import org.unitConverter.unit.BritishImperial; +import org.unitConverter.unit.LinearUnit; +import org.unitConverter.unit.LinearUnitValue; +import org.unitConverter.unit.NameSymbol; +import org.unitConverter.unit.SI; +import org.unitConverter.unit.Unit; +import org.unitConverter.unit.UnitDatabase; +import org.unitConverter.unit.UnitPrefix; +import org.unitConverter.unit.UnitValue; + +/** + * @author Adrien Hopkins + * @since 2018-12-27 + * @since v0.1.0 + */ +final class UnitConverterGUI { + /** + * A tab in the View. + */ + private enum Pane { + UNIT_CONVERTER, EXPRESSION_CONVERTER, UNIT_VIEWER, PREFIX_VIEWER, ABOUT, + SETTINGS; + } + + private static class Presenter { + /** The default place where settings are stored. */ + private static final String DEFAULT_SETTINGS_FILEPATH = "settings.txt"; + /** The default place where units are stored. */ + private static final Path DEFAULT_UNITS_FILE = Path.of("unitsfile.txt"); + /** The default place where dimensions are stored. */ + private static final Path DEFAULT_DIMENSION_FILE = Path + .of("dimensionfile.txt"); + /** The default place where exceptions are stored. */ + private static final Path DEFAULT_EXCEPTIONS_FILE = Path + .of("metric_exceptions.txt"); + + /** + * Adds default units and dimensions to a database. + * + * @param database database to add to + * @since 2019-04-14 + * @since v0.2.0 + */ + private static void addDefaults(final UnitDatabase database) { + database.addUnit("metre", SI.METRE); + database.addUnit("kilogram", SI.KILOGRAM); + database.addUnit("gram", SI.KILOGRAM.dividedBy(1000)); + database.addUnit("second", SI.SECOND); + database.addUnit("ampere", SI.AMPERE); + database.addUnit("kelvin", SI.KELVIN); + database.addUnit("mole", SI.MOLE); + database.addUnit("candela", SI.CANDELA); + database.addUnit("bit", SI.BIT); + database.addUnit("unit", SI.ONE); + // nonlinear units - must be loaded manually + database.addUnit("tempCelsius", SI.CELSIUS); + database.addUnit("tempFahrenheit", BritishImperial.FAHRENHEIT); + + // load initial dimensions + database.addDimension("LENGTH", SI.Dimensions.LENGTH); + database.addDimension("MASS", SI.Dimensions.MASS); + database.addDimension("TIME", SI.Dimensions.TIME); + database.addDimension("TEMPERATURE", SI.Dimensions.TEMPERATURE); + } + + /** + * @return {@code line} with any comments removed. + * @since 2021-03-13 + */ + private static final String withoutComments(String line) { + final int index = line.indexOf('#'); + return index == -1 ? line : line.substring(index); + } + + /** The presenter's associated view. */ + private final View view; + + /** The units known by the program. */ + private final UnitDatabase database; + + /** The names of all of the units */ + private final List unitNames; + + /** The names of all of the prefixes */ + private final List prefixNames; + + /** The names of all of the dimensions */ + private final List dimensionNames; + + /** Unit names that are ignored by the metric-only/imperial-only filter */ + private final Set metricExceptions; + + private final Comparator prefixNameComparator; + + /** A boolean remembering whether or not one-way conversion is on */ + private boolean oneWay = true; + + /** The prefix rule */ + private DefaultPrefixRepetitionRule prefixRule = null; + // conditions for existence of From and To entries + // used for one-way conversion + private final MutablePredicate fromExistenceCondition = new MutablePredicate<>( + s -> true); + + private final MutablePredicate toExistenceCondition = new MutablePredicate<>( + s -> true); + + /* + * Rounding-related settings. I am using my own system, and not + * MathContext, because MathContext does not support decimal place based + * or scientific rounding, only significant digit based rounding. + */ + private int precision = 6; + + private RoundingType roundingType = RoundingType.SIGNIFICANT_DIGITS; + + /** + * Creates the presenter. + * + * @param view presenter's associated view + * @since 2018-12-27 + * @since v0.1.0 + */ + Presenter(final View view) { + this.view = view; + + // load initial units + this.database = new UnitDatabase( + DefaultPrefixRepetitionRule.NO_RESTRICTION); + Presenter.addDefaults(this.database); + + this.database.loadUnitsFile(DEFAULT_UNITS_FILE); + this.database.loadDimensionFile(DEFAULT_DIMENSION_FILE); + + // load metric exceptions + try { + this.metricExceptions = Files.readAllLines(DEFAULT_EXCEPTIONS_FILE) + .stream().map(Presenter::withoutComments) + .filter(s -> !s.isBlank()).collect(Collectors.toSet()); + } catch (final IOException e) { + throw new AssertionError("Loading of metric_exceptions.txt failed.", + e); + } + + // load settings - requires database to exist + this.loadSettings(); + + // a comparator that can be used to compare prefix names + // any name that does not exist is less than a name that does. + // otherwise, they are compared by value + this.prefixNameComparator = (o1, o2) -> { + if (!Presenter.this.database.containsPrefixName(o1)) + return -1; + else if (!Presenter.this.database.containsPrefixName(o2)) + return 1; + + final UnitPrefix p1 = Presenter.this.database.getPrefix(o1); + final UnitPrefix p2 = Presenter.this.database.getPrefix(o2); + + if (p1.getMultiplier() < p2.getMultiplier()) + return -1; + else if (p1.getMultiplier() > p2.getMultiplier()) + return 1; + + return o1.compareTo(o2); + }; + + this.unitNames = new ArrayList<>( + this.database.unitMapPrefixless().keySet()); + this.unitNames.sort(null); // sorts it using Comparable + + this.prefixNames = new ArrayList<>(this.database.prefixMap().keySet()); + this.prefixNames.sort(this.prefixNameComparator); // sorts it using my + // comparator + + this.dimensionNames = new DelegateListModel<>( + new ArrayList<>(this.database.dimensionMap().keySet())); + this.dimensionNames.sort(null); // sorts it using Comparable + + // a Predicate that returns true iff the argument is a full base unit + final Predicate isFullBase = unit -> unit instanceof LinearUnit + && ((LinearUnit) unit).isBase(); + + // print out unit counts + System.out.printf( + "Successfully loaded %d units with %d unit names (%d base units).%n", + new HashSet<>(this.database.unitMapPrefixless().values()).size(), + this.database.unitMapPrefixless().size(), + new HashSet<>(this.database.unitMapPrefixless().values()) + .stream().filter(isFullBase).count()); + } + + /** + * Converts in the dimension-based converter + * + * @since 2019-04-13 + * @since v0.2.0 + */ + public final void convertDimensionBased() { + final String fromSelection = this.view.getFromSelection(); + if (fromSelection == null) { + this.view.showErrorDialog("Error", + "No unit selected in From field"); + return; + } + final String toSelection = this.view.getToSelection(); + if (toSelection == null) { + this.view.showErrorDialog("Error", "No unit selected in To field"); + return; + } + + final Unit from = this.database.getUnit(fromSelection); + final Unit to = this.database.getUnit(toSelection) + .withName(NameSymbol.ofName(toSelection)); + + final UnitValue beforeValue; + try { + beforeValue = UnitValue.of(from, + this.view.getDimensionConverterInput()); + } catch (final ParseException e) { + this.view.showErrorDialog("Error", + "Error in parsing: " + e.getMessage()); + return; + } + final UnitValue value = beforeValue.convertTo(to); + + final String output = this.getRoundedString(value); + + this.view.setDimensionConverterOutputText( + String.format("%s = %s", beforeValue, output)); + } + + /** + * Runs whenever the convert button is pressed. + * + *

    + * Reads and parses a unit expression from the from and to boxes, then + * converts {@code from} to {@code to}. Any errors are shown in + * JOptionPanes. + *

    + * + * @since 2019-01-26 + * @since v0.1.0 + */ + public final void convertExpressions() { + final String fromUnitString = this.view.getFromText(); + final String toUnitString = this.view.getToText(); + + if (fromUnitString.isEmpty()) { + this.view.showErrorDialog("Parse Error", + "Please enter a unit expression in the From: box."); + return; + } + if (toUnitString.isEmpty()) { + this.view.showErrorDialog("Parse Error", + "Please enter a unit expression in the To: box."); + return; + } + + final LinearUnitValue from; + final Unit to; + try { + from = this.database.evaluateUnitExpression(fromUnitString); + } catch (final IllegalArgumentException | NoSuchElementException e) { + this.view.showErrorDialog("Parse Error", + "Could not recognize text in From entry: " + e.getMessage()); + return; + } + try { + to = this.database.getUnitFromExpression(toUnitString); + } catch (final IllegalArgumentException | NoSuchElementException e) { + this.view.showErrorDialog("Parse Error", + "Could not recognize text in To entry: " + e.getMessage()); + return; + } + + if (to instanceof LinearUnit) { + // convert to LinearUnitValue + final LinearUnitValue from2; + final LinearUnit to2 = ((LinearUnit) to) + .withName(NameSymbol.ofName(toUnitString)); + final boolean useSlash; + + if (from.canConvertTo(to2)) { + from2 = from; + useSlash = false; + } else if (LinearUnitValue.ONE.dividedBy(from).canConvertTo(to2)) { + from2 = LinearUnitValue.ONE.dividedBy(from); + useSlash = true; + } else { + // if I can't convert, leave + this.view.showErrorDialog("Conversion Error", + String.format("Cannot convert between %s and %s", + fromUnitString, toUnitString)); + return; + } + + final LinearUnitValue converted = from2.convertTo(to2); + this.view.setExpressionConverterOutputText((useSlash ? "1 / " : "") + + String.format("%s = %s", fromUnitString, + this.getRoundedString(converted, false))); + return; + } else { + // convert to UnitValue + final UnitValue from2 = from.asUnitValue(); + if (from2.canConvertTo(to)) { + final UnitValue converted = from2.convertTo(to); + + this.view + .setExpressionConverterOutputText(String.format("%s = %s", + fromUnitString, this.getRoundedString(converted))); + } else { + // if I can't convert, leave + this.view.showErrorDialog("Conversion Error", + String.format("Cannot convert between %s and %s", + fromUnitString, toUnitString)); + } + } + } + + /** + * @return a list of all of the unit dimensions + * @since 2019-04-13 + * @since v0.2.0 + */ + public final List dimensionNameList() { + return this.dimensionNames; + } + + /** + * @return a list of all the entries in the dimension-based converter's + * From box + * @since 2020-08-27 + */ + public final Set fromEntries() { + return ConditionalExistenceCollections.conditionalExistenceSet( + this.unitNameSet(), this.fromExistenceCondition); + } + + /** + * @return a comparator to compare prefix names + * @since 2019-04-14 + * @since v0.2.0 + */ + public final Comparator getPrefixNameComparator() { + return this.prefixNameComparator; + } + + /** + * Like {@link LinearUnitValue#toString(boolean)}, but obeys this unit + * converter's rounding settings. + * + * @since 2020-08-04 + */ + private final String getRoundedString(final LinearUnitValue value, + boolean showUncertainty) { + switch (this.roundingType) { + case DECIMAL_PLACES: + case SIGNIFICANT_DIGITS: + return this.getRoundedString(value.asUnitValue()); + case SCIENTIFIC: + return value.toString(showUncertainty); + default: + throw new AssertionError("Invalid switch condition."); + } + } + + /** + * Like {@link UnitValue#toString()}, but obeys this unit converter's + * rounding settings. + * + * @since 2020-08-04 + */ + private final String getRoundedString(final UnitValue value) { + final BigDecimal unrounded = new BigDecimal(value.getValue()); + final BigDecimal rounded; + int precision = this.precision; + + switch (this.roundingType) { + case DECIMAL_PLACES: + rounded = unrounded.setScale(precision, RoundingMode.HALF_EVEN); + break; + case SCIENTIFIC: + precision = 12; + //$FALL-THROUGH$ + case SIGNIFICANT_DIGITS: + rounded = unrounded + .round(new MathContext(precision, RoundingMode.HALF_EVEN)); + break; + default: + throw new AssertionError("Invalid switch condition."); + } + + String output = rounded.toString(); + + // remove trailing zeroes + if (output.contains(".")) { + while (output.endsWith("0")) { + output = output.substring(0, output.length() - 1); + } + if (output.endsWith(".")) { + output = output.substring(0, output.length() - 1); + } + } + + return output + " " + value.getUnit().getPrimaryName().get(); + } + + /** + * @return The file where settings are stored; + * @since 2020-12-11 + */ + private final Path getSettingsFile() { + return Path.of(DEFAULT_SETTINGS_FILEPATH); + } + + /** + * Loads settings from the settings file. + * + * @since 2021-02-17 + */ + public final void loadSettings() { + try { + // read file line by line + final int lineNum = 0; + for (final String line : Files + .readAllLines(this.getSettingsFile())) { + final int equalsIndex = line.indexOf('='); + if (equalsIndex == -1) + throw new IllegalStateException( + "Settings file is malformed at line " + lineNum); + + final String param = line.substring(0, equalsIndex); + final String value = line.substring(equalsIndex + 1); + + switch (param) { + // set manually to avoid the unnecessary saving of the non-manual + // methods + case "precision": + this.precision = Integer.valueOf(value); + break; + case "rounding_type": + this.roundingType = RoundingType.valueOf(value); + break; + case "prefix_rule": + this.prefixRule = DefaultPrefixRepetitionRule.valueOf(value); + this.database.setPrefixRepetitionRule(this.prefixRule); + break; + case "one_way": + this.oneWay = Boolean.valueOf(value); + if (this.oneWay) { + this.fromExistenceCondition.setPredicate( + unitName -> this.metricExceptions.contains(unitName) + || !this.database.getUnit(unitName) + .isMetric()); + this.toExistenceCondition.setPredicate( + unitName -> this.metricExceptions.contains(unitName) + || this.database.getUnit(unitName).isMetric()); + } else { + this.fromExistenceCondition.setPredicate(unitName -> true); + this.toExistenceCondition.setPredicate(unitName -> true); + } + break; + default: + System.err.printf("Warning: unrecognized setting \"%s\".", + param); + break; + } + } + } catch (final IOException e) {} + } + + /** + * @return a set of all prefix names in the database + * @since 2019-04-14 + * @since v0.2.0 + */ + public final Set prefixNameSet() { + return this.database.prefixMap().keySet(); + } + + /** + * Runs whenever a prefix is selected in the viewer. + *

    + * Shows its information in the text box to the right. + *

    + * + * @since 2019-01-15 + * @since v0.1.0 + */ + public final void prefixSelected() { + final String prefixName = this.view.getPrefixViewerSelection(); + if (prefixName == null) + return; + else { + final UnitPrefix prefix = this.database.getPrefix(prefixName); + + this.view.setPrefixTextBoxText(String.format("%s%nMultiplier: %s", + prefixName, prefix.getMultiplier())); + } + } + + /** + * Saves the settings to the settings file. + * + * @since 2021-02-17 + */ + public final void saveSettings() { + try (BufferedWriter writer = Files + .newBufferedWriter(this.getSettingsFile())) { + writer.write(String.format("precision=%d\n", this.precision)); + writer.write( + String.format("rounding_type=%s\n", this.roundingType)); + writer.write(String.format("prefix_rule=%s\n", this.prefixRule)); + writer.write(String.format("one_way=%s\n", this.oneWay)); + } catch (final IOException e) { + e.printStackTrace(); + this.view.showErrorDialog("I/O Error", + "Error occurred while saving settings: " + + e.getLocalizedMessage()); + } + } + + /** + * Enables or disables one-way conversion. + * + * @param oneWay whether one-way conversion should be on (true) or off + * (false) + * @since 2020-08-27 + */ + public final void setOneWay(boolean oneWay) { + this.oneWay = oneWay; + if (oneWay) { + this.fromExistenceCondition.setPredicate( + unitName -> this.metricExceptions.contains(unitName) + || !this.database.getUnit(unitName).isMetric()); + this.toExistenceCondition.setPredicate( + unitName -> this.metricExceptions.contains(unitName) + || this.database.getUnit(unitName).isMetric()); + } else { + this.fromExistenceCondition.setPredicate(unitName -> true); + this.toExistenceCondition.setPredicate(unitName -> true); + } + + this.saveSettings(); + } + + /** + * @param precision new value of precision + * @since 2019-01-15 + * @since v0.1.0 + */ + public final void setPrecision(final int precision) { + this.precision = precision; + + this.saveSettings(); + } + + /** + * @param prefixRepetitionRule the prefixRepetitionRule to set + * @since 2020-08-26 + */ + public void setPrefixRepetitionRule( + Predicate> prefixRepetitionRule) { + if (prefixRepetitionRule instanceof DefaultPrefixRepetitionRule) { + this.prefixRule = (DefaultPrefixRepetitionRule) prefixRepetitionRule; + } else { + this.prefixRule = null; + } + this.database.setPrefixRepetitionRule(prefixRepetitionRule); + + this.saveSettings(); + } + + /** + * @param roundingType the roundingType to set + * @since 2020-07-16 + */ + public final void setRoundingType(RoundingType roundingType) { + this.roundingType = roundingType; + + this.saveSettings(); + } + + /** + * @return a list of all the entries in the dimension-based converter's To + * box + * @since 2020-08-27 + */ + public final Set toEntries() { + return ConditionalExistenceCollections.conditionalExistenceSet( + this.unitNameSet(), this.toExistenceCondition); + } + + /** + * Returns true if and only if the unit represented by {@code unitName} + * has the dimension represented by {@code dimensionName}. + * + * @param unitName name of unit to test + * @param dimensionName name of dimension to test + * @return whether unit has dimenision + * @since 2019-04-13 + * @since v0.2.0 + */ + public final boolean unitMatchesDimension(final String unitName, + final String dimensionName) { + final Unit unit = this.database.getUnit(unitName); + final ObjectProduct dimension = this.database + .getDimension(dimensionName); + return unit.getDimension().equals(dimension); + } + + /** + * Runs whenever a unit is selected in the viewer. + *

    + * Shows its information in the text box to the right. + *

    + * + * @since 2019-01-15 + * @since v0.1.0 + */ + public final void unitNameSelected() { + final String unitName = this.view.getUnitViewerSelection(); + if (unitName == null) + return; + else { + final Unit unit = this.database.getUnit(unitName); + + this.view.setUnitTextBoxText(unit.toString()); + } + } + + /** + * @return a set of all of the unit names + * @since 2019-04-14 + * @since v0.2.0 + */ + private final Set unitNameSet() { + return this.database.unitMapPrefixless().keySet(); + } + } + + /** + * Different types of rounding. + * + * Significant digits: Rounds to a number of digits. i.e. with precision 5, + * 12345.6789 rounds to 12346. Decimal places: Rounds to a number of digits + * after the decimal point, i.e. with precision 5, 12345.6789 rounds to + * 12345.67890. Scientific: Rounds based on the number of digits and + * operations, following standard scientific rounding. + */ + private static enum RoundingType { + SIGNIFICANT_DIGITS, DECIMAL_PLACES, SCIENTIFIC; + } + + private static class View { + private static final NumberFormat NUMBER_FORMATTER = new DecimalFormat(); + + /** The view's frame. */ + private final JFrame frame; + /** The view's associated presenter. */ + private final Presenter presenter; + /** The master pane containing all of the tabs. */ + private final JTabbedPane masterPane; + + // DIMENSION-BASED CONVERTER + /** The panel for inputting values in the dimension-based converter */ + private final JTextField valueInput; + /** The panel for "From" in the dimension-based converter */ + private final SearchBoxList fromSearch; + /** The panel for "To" in the dimension-based converter */ + private final SearchBoxList toSearch; + /** The output area in the dimension-based converter */ + private final JTextArea dimensionBasedOutput; + + // EXPRESSION-BASED CONVERTER + /** The "From" entry in the conversion panel */ + private final JTextField fromEntry; + /** The "To" entry in the conversion panel */ + private final JTextField toEntry; + /** The output area in the conversion panel */ + private final JTextArea output; + + // UNIT AND PREFIX VIEWERS + /** The searchable list of unit names in the unit viewer */ + private final SearchBoxList unitNameList; + /** The searchable list of prefix names in the prefix viewer */ + private final SearchBoxList prefixNameList; + /** The text box for unit data in the unit viewer */ + private final JTextArea unitTextBox; + /** The text box for prefix data in the prefix viewer */ + private final JTextArea prefixTextBox; + + /** + * Creates the {@code View}. + * + * @since 2019-01-14 + * @since v0.1.0 + */ + public View() { + this.presenter = new Presenter(this); + this.frame = new JFrame("Unit Converter"); + this.frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + + // enable system look and feel + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException | UnsupportedLookAndFeelException e) { + // oh well, just use default theme + System.err.println("Failed to enable system look-and-feel."); + e.printStackTrace(); + } + + // create the components + this.masterPane = new JTabbedPane(); + this.unitNameList = new SearchBoxList(this.presenter.unitNameSet()); + this.prefixNameList = new SearchBoxList(this.presenter.prefixNameSet(), + this.presenter.getPrefixNameComparator(), true); + this.unitTextBox = new JTextArea(); + this.prefixTextBox = new JTextArea(); + this.fromSearch = new SearchBoxList(this.presenter.fromEntries()); + this.toSearch = new SearchBoxList(this.presenter.toEntries()); + this.valueInput = new JFormattedTextField(NUMBER_FORMATTER); + this.dimensionBasedOutput = new JTextArea(2, 32); + this.fromEntry = new JTextField(); + this.toEntry = new JTextField(); + this.output = new JTextArea(2, 32); + + // create more components + this.initComponents(); + + this.frame.pack(); + } + + /** + * @return the currently selected pane. + * @throws AssertionError if no pane (or an invalid pane) is selected + */ + public Pane getActivePane() { + switch (this.masterPane.getSelectedIndex()) { + case 0: + return Pane.UNIT_CONVERTER; + case 1: + return Pane.EXPRESSION_CONVERTER; + case 2: + return Pane.UNIT_VIEWER; + case 3: + return Pane.PREFIX_VIEWER; + case 4: + return Pane.ABOUT; + case 5: + return Pane.SETTINGS; + default: + throw new AssertionError("No selected pane, or invalid pane."); + } + } + + /** + * @return value in dimension-based converter + * @throws ParseException + * @since 2020-07-07 + */ + public double getDimensionConverterInput() throws ParseException { + final Number value = NUMBER_FORMATTER.parse(this.valueInput.getText()); + if (value instanceof Double) + return (double) value; + else if (value instanceof Long) + return ((Long) value).longValue(); + else + throw new AssertionError(); + } + + /** + * @return selection in "From" selector in dimension-based converter + * @since 2019-04-13 + * @since v0.2.0 + */ + public String getFromSelection() { + return this.fromSearch.getSelectedValue(); + } + + /** + * @return text in "From" box in converter panel + * @since 2019-01-15 + * @since v0.1.0 + */ + public String getFromText() { + return this.fromEntry.getText(); + } + + /** + * @return index of selected prefix in prefix viewer + * @since 2019-01-15 + * @since v0.1.0 + */ + public String getPrefixViewerSelection() { + return this.prefixNameList.getSelectedValue(); + } + + /** + * @return selection in "To" selector in dimension-based converter + * @since 2019-04-13 + * @since v0.2.0 + */ + public String getToSelection() { + return this.toSearch.getSelectedValue(); + } + + /** + * @return text in "To" box in converter panel + * @since 2019-01-26 + * @since v0.1.0 + */ + public String getToText() { + return this.toEntry.getText(); + } + + /** + * @return index of selected unit in unit viewer + * @since 2019-01-15 + * @since v0.1.0 + */ + public String getUnitViewerSelection() { + return this.unitNameList.getSelectedValue(); + } + + /** + * Starts up the application. + * + * @since 2018-12-27 + * @since v0.1.0 + */ + public final void init() { + this.frame.setVisible(true); + } + + /** + * Initializes the view's components. + * + * @since 2018-12-27 + * @since v0.1.0 + */ + private final void initComponents() { + final JPanel masterPanel = new JPanel(); + this.frame.add(masterPanel); + + masterPanel.setLayout(new BorderLayout()); + + { // pane with all of the tabs + masterPanel.add(this.masterPane, BorderLayout.CENTER); + + // update stuff + this.masterPane.addChangeListener(e -> this.update()); + + { // a panel for unit conversion using a selector + final JPanel convertUnitPanel = new JPanel(); + this.masterPane.addTab("Convert Units", convertUnitPanel); + this.masterPane.setMnemonicAt(0, KeyEvent.VK_U); + + convertUnitPanel.setLayout(new BorderLayout()); + + { // panel for input part + final JPanel inputPanel = new JPanel(); + convertUnitPanel.add(inputPanel, BorderLayout.CENTER); + + inputPanel.setLayout(new GridLayout(1, 3)); + + final JComboBox dimensionSelector = new JComboBox<>( + this.presenter.dimensionNameList() + .toArray(new String[0])); + dimensionSelector.setSelectedItem("LENGTH"); + + // handle dimension filter + final MutablePredicate dimensionFilter = new MutablePredicate<>( + s -> true); + + // panel for From things + inputPanel.add(this.fromSearch); + + this.fromSearch.addSearchFilter(dimensionFilter); + + { // for dimension selector and arrow that represents + // conversion + final JPanel inBetweenPanel = new JPanel(); + inputPanel.add(inBetweenPanel); + + inBetweenPanel.setLayout(new BorderLayout()); + + { // dimension selector + inBetweenPanel.add(dimensionSelector, + BorderLayout.PAGE_START); + } + + { // the arrow in the middle + final JLabel arrowLabel = new JLabel("->"); + inBetweenPanel.add(arrowLabel, BorderLayout.CENTER); + } + } + + // panel for To things + + inputPanel.add(this.toSearch); + + this.toSearch.addSearchFilter(dimensionFilter); + + // code for dimension filter + dimensionSelector.addItemListener(e -> { + dimensionFilter.setPredicate(string -> View.this.presenter + .unitMatchesDimension(string, + (String) dimensionSelector.getSelectedItem())); + this.fromSearch.reapplyFilter(); + this.toSearch.reapplyFilter(); + }); + + // apply the item listener once because I have a default + // selection + dimensionFilter.setPredicate(string -> View.this.presenter + .unitMatchesDimension(string, + (String) dimensionSelector.getSelectedItem())); + this.fromSearch.reapplyFilter(); + this.toSearch.reapplyFilter(); + } + + { // panel for submit and output, and also value entry + final JPanel outputPanel = new JPanel(); + convertUnitPanel.add(outputPanel, BorderLayout.PAGE_END); + + outputPanel.setLayout(new GridLayout(3, 1)); + + { // unit input + final JPanel valueInputPanel = new JPanel(); + outputPanel.add(valueInputPanel); + + valueInputPanel.setLayout(new BorderLayout()); + + { // prompt + final JLabel valuePrompt = new JLabel( + "Value to convert: "); + valueInputPanel.add(valuePrompt, + BorderLayout.LINE_START); + } + + { // value to convert + valueInputPanel.add(this.valueInput, + BorderLayout.CENTER); + } + } + + { // button to convert + final JButton convertButton = new JButton("Convert"); + outputPanel.add(convertButton); + + convertButton.addActionListener( + e -> this.presenter.convertDimensionBased()); + convertButton.setMnemonic(KeyEvent.VK_ENTER); + } + + { // output of conversion + outputPanel.add(this.dimensionBasedOutput); + this.dimensionBasedOutput.setEditable(false); + } + } + } + + { // panel for unit conversion using expressions + final JPanel convertExpressionPanel = new JPanel(); + this.masterPane.addTab("Convert Unit Expressions", + convertExpressionPanel); + this.masterPane.setMnemonicAt(1, KeyEvent.VK_E); + + convertExpressionPanel.setLayout(new GridLayout(4, 1)); + + { // panel for units to convert from + final JPanel fromPanel = new JPanel(); + convertExpressionPanel.add(fromPanel); + + fromPanel.setBorder(BorderFactory.createTitledBorder("From")); + fromPanel.setLayout(new GridLayout(1, 1)); + + { // entry for units + fromPanel.add(this.fromEntry); + } + } + + { // panel for units to convert to + final JPanel toPanel = new JPanel(); + convertExpressionPanel.add(toPanel); + + toPanel.setBorder(BorderFactory.createTitledBorder("To")); + toPanel.setLayout(new GridLayout(1, 1)); + + { // entry for units + toPanel.add(this.toEntry); + } + } + + { // button to convert + final JButton convertButton = new JButton("Convert"); + convertExpressionPanel.add(convertButton); + + convertButton.addActionListener( + e -> this.presenter.convertExpressions()); + convertButton.setMnemonic(KeyEvent.VK_ENTER); + } + + { // output of conversion + final JPanel outputPanel = new JPanel(); + convertExpressionPanel.add(outputPanel); + + outputPanel + .setBorder(BorderFactory.createTitledBorder("Output")); + outputPanel.setLayout(new GridLayout(1, 1)); + + { // output + outputPanel.add(this.output); + this.output.setEditable(false); + } + } + } + + { // panel to look up units + final JPanel unitLookupPanel = new JPanel(); + this.masterPane.addTab("Unit Viewer", unitLookupPanel); + this.masterPane.setMnemonicAt(2, KeyEvent.VK_V); + + unitLookupPanel.setLayout(new GridLayout()); + + { // search panel + unitLookupPanel.add(this.unitNameList); + + this.unitNameList.getSearchList().addListSelectionListener( + e -> this.presenter.unitNameSelected()); + } + + { // the text box for unit's toString + unitLookupPanel.add(this.unitTextBox); + this.unitTextBox.setEditable(false); + this.unitTextBox.setLineWrap(true); + } + } + + { // panel to look up prefixes + final JPanel prefixLookupPanel = new JPanel(); + this.masterPane.addTab("Prefix Viewer", prefixLookupPanel); + this.masterPane.setMnemonicAt(3, KeyEvent.VK_P); + + prefixLookupPanel.setLayout(new GridLayout(1, 2)); + + { // panel for listing and seaching + prefixLookupPanel.add(this.prefixNameList); + + this.prefixNameList.getSearchList().addListSelectionListener( + e -> this.presenter.prefixSelected()); + } + + { // the text box for prefix's toString + prefixLookupPanel.add(this.prefixTextBox); + this.prefixTextBox.setEditable(false); + this.prefixTextBox.setLineWrap(true); + } + } + + { // Info panel + final JPanel infoPanel = new JPanel(); + this.masterPane.addTab("\uD83D\uDEC8", // info (i) character + new JScrollPane(infoPanel)); + + final JTextArea infoTextArea = new JTextArea(); + infoTextArea.setEditable(false); + infoTextArea.setOpaque(false); + infoPanel.add(infoTextArea); + + // get info text + final String infoText; + try { + final Path aboutFile = Path.of("src", "main", "resources", + "about.txt"); + infoText = Files.readAllLines(aboutFile).stream() + .map(Presenter::withoutComments) + .collect(Collectors.joining("\n")); + } catch (final IOException e) { + throw new AssertionError("I/O exception loading about.txt", + e); + } + infoTextArea.setText(infoText); + } + + { // Settings panel + final JPanel settingsPanel = new JPanel(); + this.masterPane.addTab("\u2699", new JScrollPane(settingsPanel)); + this.masterPane.setMnemonicAt(5, KeyEvent.VK_S); + + settingsPanel.setLayout( + new BoxLayout(settingsPanel, BoxLayout.PAGE_AXIS)); + + { // rounding settings + final JPanel roundingPanel = new JPanel(); + settingsPanel.add(roundingPanel); + roundingPanel + .setBorder(new TitledBorder("Rounding Settings")); + roundingPanel.setLayout(new GridBagLayout()); + + // rounding rule selection + final ButtonGroup roundingRuleButtons = new ButtonGroup(); + + final JLabel roundingRuleLabel = new JLabel("Rounding Rule:"); + roundingPanel.add(roundingRuleLabel, new GridBagBuilder(0, 0) + .setAnchor(GridBagConstraints.LINE_START).build()); + + final JRadioButton fixedPrecision = new JRadioButton( + "Fixed Precision"); + if (this.presenter.roundingType == RoundingType.SIGNIFICANT_DIGITS) { + fixedPrecision.setSelected(true); + } + fixedPrecision.addActionListener(e -> this.presenter + .setRoundingType(RoundingType.SIGNIFICANT_DIGITS)); + roundingRuleButtons.add(fixedPrecision); + roundingPanel.add(fixedPrecision, new GridBagBuilder(0, 1) + .setAnchor(GridBagConstraints.LINE_START).build()); + + final JRadioButton fixedDecimals = new JRadioButton( + "Fixed Decimal Places"); + if (this.presenter.roundingType == RoundingType.DECIMAL_PLACES) { + fixedDecimals.setSelected(true); + } + fixedDecimals.addActionListener(e -> this.presenter + .setRoundingType(RoundingType.DECIMAL_PLACES)); + roundingRuleButtons.add(fixedDecimals); + roundingPanel.add(fixedDecimals, new GridBagBuilder(0, 2) + .setAnchor(GridBagConstraints.LINE_START).build()); + + final JRadioButton relativePrecision = new JRadioButton( + "Scientific Precision"); + if (this.presenter.roundingType == RoundingType.SCIENTIFIC) { + relativePrecision.setSelected(true); + } + relativePrecision.addActionListener(e -> this.presenter + .setRoundingType(RoundingType.SCIENTIFIC)); + roundingRuleButtons.add(relativePrecision); + roundingPanel.add(relativePrecision, new GridBagBuilder(0, 3) + .setAnchor(GridBagConstraints.LINE_START).build()); + + final JLabel sliderLabel = new JLabel("Precision:"); + roundingPanel.add(sliderLabel, new GridBagBuilder(0, 4) + .setAnchor(GridBagConstraints.LINE_START).build()); + + final JSlider sigDigSlider = new JSlider(0, 12); + roundingPanel.add(sigDigSlider, new GridBagBuilder(0, 5) + .setAnchor(GridBagConstraints.LINE_START).build()); + + sigDigSlider.setMajorTickSpacing(4); + sigDigSlider.setMinorTickSpacing(1); + sigDigSlider.setSnapToTicks(true); + sigDigSlider.setPaintTicks(true); + sigDigSlider.setPaintLabels(true); + sigDigSlider.setValue(this.presenter.precision); + + sigDigSlider.addChangeListener(e -> this.presenter + .setPrecision(sigDigSlider.getValue())); + } + + { // prefix repetition settings + final JPanel prefixRepetitionPanel = new JPanel(); + settingsPanel.add(prefixRepetitionPanel); + prefixRepetitionPanel.setBorder( + new TitledBorder("Prefix Repetition Settings")); + prefixRepetitionPanel.setLayout(new GridBagLayout()); + + // prefix rules + final ButtonGroup prefixRuleButtons = new ButtonGroup(); + + final JRadioButton noRepetition = new JRadioButton( + "No Repetition"); + if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.NO_REPETITION) { + noRepetition.setSelected(true); + } + noRepetition.addActionListener( + e -> this.presenter.setPrefixRepetitionRule( + DefaultPrefixRepetitionRule.NO_REPETITION)); + prefixRuleButtons.add(noRepetition); + prefixRepetitionPanel.add(noRepetition, + new GridBagBuilder(0, 0) + .setAnchor(GridBagConstraints.LINE_START) + .build()); + + final JRadioButton noRestriction = new JRadioButton( + "No Restriction"); + if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.NO_RESTRICTION) { + noRestriction.setSelected(true); + } + noRestriction.addActionListener( + e -> this.presenter.setPrefixRepetitionRule( + DefaultPrefixRepetitionRule.NO_RESTRICTION)); + prefixRuleButtons.add(noRestriction); + prefixRepetitionPanel.add(noRestriction, + new GridBagBuilder(0, 1) + .setAnchor(GridBagConstraints.LINE_START) + .build()); + + final JRadioButton customRepetition = new JRadioButton( + "Complex Repetition"); + if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.COMPLEX_REPETITION) { + customRepetition.setSelected(true); + } + customRepetition.addActionListener( + e -> this.presenter.setPrefixRepetitionRule( + DefaultPrefixRepetitionRule.COMPLEX_REPETITION)); + prefixRuleButtons.add(customRepetition); + prefixRepetitionPanel.add(customRepetition, + new GridBagBuilder(0, 2) + .setAnchor(GridBagConstraints.LINE_START) + .build()); + } + + { // search settings + final JPanel searchingPanel = new JPanel(); + settingsPanel.add(searchingPanel); + searchingPanel.setBorder(new TitledBorder("Search Settings")); + searchingPanel.setLayout(new GridBagLayout()); + + // searching rules + final ButtonGroup searchRuleButtons = new ButtonGroup(); + + final JRadioButton noPrefixes = new JRadioButton( + "Never Include Prefixed Units"); + noPrefixes.setEnabled(false); + searchRuleButtons.add(noPrefixes); + searchingPanel.add(noPrefixes, new GridBagBuilder(0, 0) + .setAnchor(GridBagConstraints.LINE_START).build()); + + final JRadioButton fixedPrefixes = new JRadioButton( + "Include Some Prefixes"); + fixedPrefixes.setEnabled(false); + searchRuleButtons.add(fixedPrefixes); + searchingPanel.add(fixedPrefixes, new GridBagBuilder(0, 1) + .setAnchor(GridBagConstraints.LINE_START).build()); + + final JRadioButton explicitPrefixes = new JRadioButton( + "Include Explicit Prefixes"); + explicitPrefixes.setEnabled(false); + searchRuleButtons.add(explicitPrefixes); + searchingPanel.add(explicitPrefixes, new GridBagBuilder(0, 2) + .setAnchor(GridBagConstraints.LINE_START).build()); + + final JRadioButton alwaysInclude = new JRadioButton( + "Include All Single Prefixes"); + alwaysInclude.setEnabled(false); + searchRuleButtons.add(alwaysInclude); + searchingPanel.add(alwaysInclude, new GridBagBuilder(0, 3) + .setAnchor(GridBagConstraints.LINE_START).build()); + } + + { // miscellaneous settings + final JPanel miscPanel = new JPanel(); + settingsPanel.add(miscPanel); + miscPanel + .setBorder(new TitledBorder("Miscellaneous Settings")); + miscPanel.setLayout(new GridBagLayout()); + + final JCheckBox oneWay = new JCheckBox( + "Convert One Way Only"); + oneWay.setSelected(this.presenter.oneWay); + oneWay.addItemListener( + e -> this.presenter.setOneWay(e.getStateChange() == 1)); + miscPanel.add(oneWay, new GridBagBuilder(0, 0) + .setAnchor(GridBagConstraints.LINE_START).build()); + + final JCheckBox showAllVariations = new JCheckBox( + "Show Symbols in \"Convert Units\""); + showAllVariations.setSelected(true); + showAllVariations.setEnabled(false); + miscPanel.add(showAllVariations, new GridBagBuilder(0, 1) + .setAnchor(GridBagConstraints.LINE_START).build()); + + final JButton unitFileButton = new JButton( + "Manage Unit Data Files"); + unitFileButton.setEnabled(false); + miscPanel.add(unitFileButton, new GridBagBuilder(0, 2) + .setAnchor(GridBagConstraints.LINE_START).build()); + } + } + } + } + + /** + * Sets the text in the output of the dimension-based converter. + * + * @param text text to set + * @since 2019-04-13 + * @since v0.2.0 + */ + public void setDimensionConverterOutputText(final String text) { + this.dimensionBasedOutput.setText(text); + } + + /** + * Sets the text in the output of the conversion panel. + * + * @param text text to set + * @since 2019-01-15 + * @since v0.1.0 + */ + public void setExpressionConverterOutputText(final String text) { + this.output.setText(text); + } + + /** + * Sets the text of the prefix text box in the prefix viewer. + * + * @param text text to set + * @since 2019-01-15 + * @since v0.1.0 + */ + public void setPrefixTextBoxText(final String text) { + this.prefixTextBox.setText(text); + } + + /** + * Sets the text of the unit text box in the unit viewer. + * + * @param text text to set + * @since 2019-01-15 + * @since v0.1.0 + */ + public void setUnitTextBoxText(final String text) { + this.unitTextBox.setText(text); + } + + /** + * Shows an error dialog. + * + * @param title title of dialog + * @param message message in dialog + * @since 2019-01-14 + * @since v0.1.0 + */ + public void showErrorDialog(final String title, final String message) { + JOptionPane.showMessageDialog(this.frame, message, title, + JOptionPane.ERROR_MESSAGE); + } + + public void update() { + switch (this.getActivePane()) { + case UNIT_CONVERTER: + this.fromSearch.updateList(); + this.toSearch.updateList(); + break; + default: + // do nothing, for now + break; + } + } + } + + public static void main(final String[] args) { + new View().init(); + } +} diff --git a/src/main/java/org/unitConverter/converterGUI/package-info.java b/src/main/java/org/unitConverter/converterGUI/package-info.java new file mode 100644 index 0000000..d85ecab --- /dev/null +++ b/src/main/java/org/unitConverter/converterGUI/package-info.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +/** + * The GUI interface of the Unit Converter. + * + * @author Adrien Hopkins + * @since 2019-01-25 + * @since v0.2.0 + */ +package org.unitConverter.converterGUI; \ No newline at end of file diff --git a/src/main/java/org/unitConverter/math/ConditionalExistenceCollections.java b/src/main/java/org/unitConverter/math/ConditionalExistenceCollections.java new file mode 100644 index 0000000..ac1c0cf --- /dev/null +++ b/src/main/java/org/unitConverter/math/ConditionalExistenceCollections.java @@ -0,0 +1,468 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.math; + +import java.util.AbstractCollection; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.function.Predicate; + +/** + * Elements in these wrapper collections only exist if they pass a condition. + *

    + * All of the collections in this class are "views" of the provided collections. + * They are mutable if the provided collections are mutable, they allow null if + * the provided collections allow null, they will reflect changes in the + * provided collection, etc. + *

    + * The modification operations will always run the corresponding operations, + * even if the conditional existence collection doesn't change. For example, if + * you have a set that ignores even numbers, add(2) will still add a 2 to the + * backing set (but the conditional existence set will say it doesn't exist). + *

    + * The returned collections do not pass the hashCode and equals + * operations through to the backing collections, but rely on {@code Object}'s + * {@code equals} and {@code hashCode} methods. This is necessary to preserve + * the contracts of these operations in the case that the backing collections + * are sets or lists. + *

    + * Other than that, the only difference between the provided collections and + * the returned collections are that elements don't exist if they don't pass the + * provided condition. + * + * + * @author Adrien Hopkins + * @since 2019-10-17 + */ +// TODO add conditional existence Lists and Sorted/Navigable Sets/Maps +public final class ConditionalExistenceCollections { + /** + * Elements in this collection only exist if they meet a condition. + * + * @author Adrien Hopkins + * @since 2019-10-17 + * @param type of element in collection + */ + static final class ConditionalExistenceCollection + extends AbstractCollection { + final Collection collection; + final Predicate existenceCondition; + + /** + * Creates the {@code ConditionalExistenceCollection}. + * + * @param collection + * @param existenceCondition + * @since 2019-10-17 + */ + private ConditionalExistenceCollection(final Collection collection, + final Predicate existenceCondition) { + this.collection = collection; + this.existenceCondition = existenceCondition; + } + + @Override + public boolean add(final E e) { + return this.collection.add(e) && this.existenceCondition.test(e); + } + + @Override + public void clear() { + this.collection.clear(); + } + + @Override + public boolean contains(final Object o) { + if (!this.collection.contains(o)) + return false; + + // this collection can only contain instances of E + // since the object is in the collection, we know that it must be an + // instance of E + // therefore this cast will always work + @SuppressWarnings("unchecked") + final E e = (E) o; + + return this.existenceCondition.test(e); + } + + @Override + public Iterator iterator() { + return conditionalExistenceIterator(this.collection.iterator(), + this.existenceCondition); + } + + @Override + public boolean remove(final Object o) { + // remove() must be first in the && statement, otherwise it may not + // execute + final boolean containedObject = this.contains(o); + return this.collection.remove(o) && containedObject; + } + + @Override + public int size() { + return (int) this.collection.stream().filter(this.existenceCondition) + .count(); + } + + @Override + public Object[] toArray() { + // ensure the toArray operation is supported + this.collection.toArray(); + + // if it works, do it for real + return super.toArray(); + } + + @Override + public T[] toArray(T[] a) { + // ensure the toArray operation is supported + this.collection.toArray(); + + // if it works, do it for real + return super.toArray(a); + } + } + + /** + * Elements in this wrapper iterator only exist if they pass a condition. + * + * @author Adrien Hopkins + * @since 2019-10-17 + * @param type of elements in iterator + */ + static final class ConditionalExistenceIterator implements Iterator { + final Iterator iterator; + final Predicate existenceCondition; + E nextElement; + boolean hasNext; + + /** + * Creates the {@code ConditionalExistenceIterator}. + * + * @param iterator + * @param condition + * @since 2019-10-17 + */ + private ConditionalExistenceIterator(final Iterator iterator, + final Predicate condition) { + this.iterator = iterator; + this.existenceCondition = condition; + this.getAndSetNextElement(); + } + + /** + * Gets the next element, and sets nextElement and hasNext accordingly. + * + * @since 2019-10-17 + */ + private void getAndSetNextElement() { + do { + if (!this.iterator.hasNext()) { + this.nextElement = null; + this.hasNext = false; + return; + } + this.nextElement = this.iterator.next(); + } while (!this.existenceCondition.test(this.nextElement)); + this.hasNext = true; + } + + @Override + public boolean hasNext() { + return this.hasNext; + } + + @Override + public E next() { + if (this.hasNext()) { + final E next = this.nextElement; + this.getAndSetNextElement(); + return next; + } else + throw new NoSuchElementException(); + } + + @Override + public void remove() { + this.iterator.remove(); + } + } + + /** + * Mappings in this map only exist if the entry passes some condition. + * + * @author Adrien Hopkins + * @since 2019-10-17 + * @param key type + * @param value type + */ + static final class ConditionalExistenceMap extends AbstractMap { + Map map; + Predicate> entryExistenceCondition; + + /** + * Creates the {@code ConditionalExistenceMap}. + * + * @param map + * @param entryExistenceCondition + * @since 2019-10-17 + */ + private ConditionalExistenceMap(final Map map, + final Predicate> entryExistenceCondition) { + this.map = map; + this.entryExistenceCondition = entryExistenceCondition; + } + + @Override + public boolean containsKey(final Object key) { + if (!this.map.containsKey(key)) + return false; + + // only instances of K have mappings in the backing map + // since we know that key is a valid key, it must be an instance of K + @SuppressWarnings("unchecked") + final K keyAsK = (K) key; + + // get and test entry + final V value = this.map.get(key); + final Entry entry = new SimpleEntry<>(keyAsK, value); + return this.entryExistenceCondition.test(entry); + } + + @Override + public Set> entrySet() { + return conditionalExistenceSet(this.map.entrySet(), + this.entryExistenceCondition); + } + + @Override + public V get(final Object key) { + return this.containsKey(key) ? this.map.get(key) : null; + } + + private final Entry getEntry(K key) { + return new Entry() { + @Override + public K getKey() { + return key; + } + + @Override + public V getValue() { + return ConditionalExistenceMap.this.map.get(key); + } + + @Override + public V setValue(V value) { + return ConditionalExistenceMap.this.map.put(key, value); + } + }; + } + + @Override + public Set keySet() { + return conditionalExistenceSet(super.keySet(), + k -> this.entryExistenceCondition.test(this.getEntry(k))); + } + + @Override + public V put(final K key, final V value) { + final V oldValue = this.map.put(key, value); + + // get and test entry + final Entry entry = new SimpleEntry<>(key, oldValue); + return this.entryExistenceCondition.test(entry) ? oldValue : null; + } + + @Override + public V remove(final Object key) { + final V oldValue = this.map.remove(key); + return this.containsKey(key) ? oldValue : null; + } + + @Override + public Collection values() { + // maybe change this to use ConditionalExistenceCollection + return super.values(); + } + } + + /** + * Elements in this set only exist if a certain condition is true. + * + * @author Adrien Hopkins + * @since 2019-10-17 + * @param type of element in set + */ + static final class ConditionalExistenceSet extends AbstractSet { + private final Set set; + private final Predicate existenceCondition; + + /** + * Creates the {@code ConditionalNonexistenceSet}. + * + * @param set set to use + * @param existenceCondition condition where element exists + * @since 2019-10-17 + */ + private ConditionalExistenceSet(final Set set, + final Predicate existenceCondition) { + this.set = set; + this.existenceCondition = existenceCondition; + } + + /** + * {@inheritDoc} + *

    + * Note that this method returns {@code false} if {@code e} does not pass + * the existence condition. + */ + @Override + public boolean add(final E e) { + return this.set.add(e) && this.existenceCondition.test(e); + } + + @Override + public void clear() { + this.set.clear(); + } + + @Override + public boolean contains(final Object o) { + if (!this.set.contains(o)) + return false; + + // this set can only contain instances of E + // since the object is in the set, we know that it must be an instance + // of E + // therefore this cast will always work + @SuppressWarnings("unchecked") + final E e = (E) o; + + return this.existenceCondition.test(e); + } + + @Override + public Iterator iterator() { + return conditionalExistenceIterator(this.set.iterator(), + this.existenceCondition); + } + + @Override + public boolean remove(final Object o) { + // remove() must be first in the && statement, otherwise it may not + // execute + final boolean containedObject = this.contains(o); + return this.set.remove(o) && containedObject; + } + + @Override + public int size() { + return (int) this.set.stream().filter(this.existenceCondition).count(); + } + + @Override + public Object[] toArray() { + // ensure the toArray operation is supported + this.set.toArray(); + + // if it works, do it for real + return super.toArray(); + } + + @Override + public T[] toArray(T[] a) { + // ensure the toArray operation is supported + this.set.toArray(); + + // if it works, do it for real + return super.toArray(a); + } + } + + /** + * Elements in the returned wrapper collection are ignored if they don't pass + * a condition. + * + * @param type of elements in collection + * @param collection collection to wrap + * @param existenceCondition elements only exist if this returns true + * @return wrapper collection + * @since 2019-10-17 + */ + public static final Collection conditionalExistenceCollection( + final Collection collection, + final Predicate existenceCondition) { + return new ConditionalExistenceCollection<>(collection, + existenceCondition); + } + + /** + * Elements in the returned wrapper iterator are ignored if they don't pass a + * condition. + * + * @param type of elements in iterator + * @param iterator iterator to wrap + * @param existenceCondition elements only exist if this returns true + * @return wrapper iterator + * @since 2019-10-17 + */ + public static final Iterator conditionalExistenceIterator( + final Iterator iterator, final Predicate existenceCondition) { + return new ConditionalExistenceIterator<>(iterator, existenceCondition); + } + + /** + * Mappings in the returned wrapper map are ignored if the corresponding + * entry doesn't pass a condition + * + * @param type of key in map + * @param type of value in map + * @param map map to wrap + * @param entryExistenceCondition mappings only exist if this returns true + * @return wrapper map + * @since 2019-10-17 + */ + public static final Map conditionalExistenceMap( + final Map map, + final Predicate> entryExistenceCondition) { + return new ConditionalExistenceMap<>(map, entryExistenceCondition); + } + + /** + * Elements in the returned wrapper set are ignored if they don't pass a + * condition. + * + * @param type of elements in set + * @param set set to wrap + * @param existenceCondition elements only exist if this returns true + * @return wrapper set + * @since 2019-10-17 + */ + public static final Set conditionalExistenceSet(final Set set, + final Predicate existenceCondition) { + return new ConditionalExistenceSet<>(set, existenceCondition); + } +} diff --git a/src/main/java/org/unitConverter/math/DecimalComparison.java b/src/main/java/org/unitConverter/math/DecimalComparison.java new file mode 100644 index 0000000..0f5b91e --- /dev/null +++ b/src/main/java/org/unitConverter/math/DecimalComparison.java @@ -0,0 +1,256 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.math; + +import java.math.BigDecimal; + +/** + * A class that contains methods to compare float and double values. + * + * @author Adrien Hopkins + * @since 2019-03-18 + * @since v0.2.0 + */ +public final class DecimalComparison { + /** + * The value used for double comparison. If two double values are within this + * value multiplied by the larger value, they are considered equal. + * + * @since 2019-03-18 + * @since v0.2.0 + */ + public static final double DOUBLE_EPSILON = 1.0e-15; + + /** + * The value used for float comparison. If two float values are within this + * value multiplied by the larger value, they are considered equal. + * + * @since 2019-03-18 + * @since v0.2.0 + */ + public static final float FLOAT_EPSILON = 1.0e-6f; + + /** + * Tests for equality of double values using {@link #DOUBLE_EPSILON}. + *

    + * WARNING: this method is not technically transitive. If a + * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, + * and b and c are off by slightly less than + * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) + * will both return true, but equals(a, c) will return false. However, this + * situation is very unlikely to ever happen in a real programming situation. + *

    + * If this does become a concern, some ways to solve this problem: + *

      + *
    1. Raise the value of epsilon using + * {@link #equals(double, double, double)} (this does not make a violation of + * transitivity impossible, it just significantly reduces the chances of it + * happening) + *
    2. Use {@link BigDecimal} instead of {@code double} (this will make a + * violation of transitivity 100% impossible) + *
    + * + * @param a first value to test + * @param b second value to test + * @return whether they are equal + * @since 2019-03-18 + * @since v0.2.0 + * @see #hashCode(double) + */ + public static final boolean equals(final double a, final double b) { + return DecimalComparison.equals(a, b, DOUBLE_EPSILON); + } + + /** + * Tests for double equality using a custom epsilon value. + * + *

    + * WARNING: this method is not technically transitive. If a + * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, + * and b and c are off by slightly less than + * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) + * will both return true, but equals(a, c) will return false. However, this + * situation is very unlikely to ever happen in a real programming situation. + *

    + * If this does become a concern, some ways to solve this problem: + *

      + *
    1. Raise the value of epsilon (this does not make a violation of + * transitivity impossible, it just significantly reduces the chances of it + * happening) + *
    2. Use {@link BigDecimal} instead of {@code double} (this will make a + * violation of transitivity 100% impossible) + *
    + * + * @param a first value to test + * @param b second value to test + * @param epsilon allowed difference + * @return whether they are equal + * @since 2019-03-18 + * @since v0.2.0 + */ + public static final boolean equals(final double a, final double b, + final double epsilon) { + return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b)); + } + + /** + * Tests for equality of float values using {@link #FLOAT_EPSILON}. + * + *

    + * WARNING: this method is not technically transitive. If a + * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, + * and b and c are off by slightly less than + * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) + * will both return true, but equals(a, c) will return false. However, this + * situation is very unlikely to ever happen in a real programming situation. + *

    + * If this does become a concern, some ways to solve this problem: + *

      + *
    1. Raise the value of epsilon using {@link #equals(float, float, float)} + * (this does not make a violation of transitivity impossible, it just + * significantly reduces the chances of it happening) + *
    2. Use {@link BigDecimal} instead of {@code float} (this will make a + * violation of transitivity 100% impossible) + *
    + * + * @param a first value to test + * @param b second value to test + * @return whether they are equal + * @since 2019-03-18 + * @since v0.2.0 + */ + public static final boolean equals(final float a, final float b) { + return DecimalComparison.equals(a, b, FLOAT_EPSILON); + } + + /** + * Tests for float equality using a custom epsilon value. + * + *

    + * WARNING: this method is not technically transitive. If a + * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, + * and b and c are off by slightly less than + * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) + * will both return true, but equals(a, c) will return false. However, this + * situation is very unlikely to ever happen in a real programming situation. + *

    + * If this does become a concern, some ways to solve this problem: + *

      + *
    1. Raise the value of epsilon (this does not make a violation of + * transitivity impossible, it just significantly reduces the chances of it + * happening) + *
    2. Use {@link BigDecimal} instead of {@code float} (this will make a + * violation of transitivity 100% impossible) + *
    + * + * @param a first value to test + * @param b second value to test + * @param epsilon allowed difference + * @return whether they are equal + * @since 2019-03-18 + * @since v0.2.0 + */ + public static final boolean equals(final float a, final float b, + final float epsilon) { + return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b)); + } + + /** + * Tests for equality of {@code UncertainDouble} values using + * {@link #DOUBLE_EPSILON}. + *

    + * WARNING: this method is not technically transitive. If a + * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, + * and b and c are off by slightly less than + * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) + * will both return true, but equals(a, c) will return false. However, this + * situation is very unlikely to ever happen in a real programming situation. + *

    + * If this does become a concern, some ways to solve this problem: + *

      + *
    1. Raise the value of epsilon using + * {@link #equals(UncertainDouble, UncertainDouble, double)} (this does not + * make a violation of transitivity impossible, it just significantly reduces + * the chances of it happening) + *
    2. Use {@link BigDecimal} instead of {@code double} (this will make a + * violation of transitivity 100% impossible) + *
    + * + * @param a first value to test + * @param b second value to test + * @return whether they are equal + * @since 2020-09-07 + * @see #hashCode(double) + */ + public static final boolean equals(final UncertainDouble a, + final UncertainDouble b) { + return DecimalComparison.equals(a.value(), b.value()) + && DecimalComparison.equals(a.uncertainty(), b.uncertainty()); + } + + /** + * Tests for {@code UncertainDouble} equality using a custom epsilon value. + * + *

    + * WARNING: this method is not technically transitive. If a + * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, + * and b and c are off by slightly less than + * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) + * will both return true, but equals(a, c) will return false. However, this + * situation is very unlikely to ever happen in a real programming situation. + *

    + * If this does become a concern, some ways to solve this problem: + *

      + *
    1. Raise the value of epsilon (this does not make a violation of + * transitivity impossible, it just significantly reduces the chances of it + * happening) + *
    2. Use {@link BigDecimal} instead of {@code double} (this will make a + * violation of transitivity 100% impossible) + *
    + * + * @param a first value to test + * @param b second value to test + * @param epsilon allowed difference + * @return whether they are equal + * @since 2019-03-18 + * @since v0.2.0 + */ + public static final boolean equals(final UncertainDouble a, + final UncertainDouble b, final double epsilon) { + return DecimalComparison.equals(a.value(), b.value(), epsilon) + && DecimalComparison.equals(a.uncertainty(), b.uncertainty(), + epsilon); + } + + /** + * Takes the hash code of doubles. Values that are equal according to + * {@link #equals(double, double)} will have the same hash code. + * + * @param d double to hash + * @return hash code of double + * @since 2019-10-16 + */ + public static final int hash(final double d) { + return Float.hashCode((float) d); + } + + // You may NOT get any DecimalComparison instances + private DecimalComparison() { + throw new AssertionError(); + } + +} diff --git a/src/main/java/org/unitConverter/math/ExpressionParser.java b/src/main/java/org/unitConverter/math/ExpressionParser.java new file mode 100644 index 0000000..8a0e97d --- /dev/null +++ b/src/main/java/org/unitConverter/math/ExpressionParser.java @@ -0,0 +1,708 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.math; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Deque; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.UnaryOperator; + +/** + * An object that can parse expressions with unary or binary operators. + * + * @author Adrien Hopkins + * @param + * type of object that exists in parsed expressions + * @since 2019-03-14 + * @since v0.2.0 + */ +public final class ExpressionParser { + /** + * A builder that can create {@code ExpressionParser} instances. + * + * @author Adrien Hopkins + * @param + * type of object that exists in parsed expressions + * @since 2019-03-17 + * @since v0.2.0 + */ + public static final class Builder { + /** + * A function that obtains a parseable object from a string. For example, an integer {@code ExpressionParser} + * would use {@code Integer::parseInt}. + * + * @since 2019-03-14 + * @since v0.2.0 + */ + private final Function objectObtainer; + + /** + * The function of the space as an operator (like 3 x y) + * + * @since 2019-03-22 + * @since v0.2.0 + */ + private String spaceFunction = null; + + /** + * A map mapping operator strings to operator functions, for unary operators. + * + * @since 2019-03-14 + * @since v0.2.0 + */ + private final Map> unaryOperators; + + /** + * A map mapping operator strings to operator functions, for binary operators. + * + * @since 2019-03-14 + * @since v0.2.0 + */ + private final Map> binaryOperators; + + /** + * Creates the {@code Builder}. + * + * @param objectObtainer + * a function that can turn strings into objects of the type handled by the parser. + * @throws NullPointerException + * if {@code objectObtainer} is null + * @since 2019-03-17 + * @since v0.2.0 + */ + public Builder(final Function objectObtainer) { + this.objectObtainer = Objects.requireNonNull(objectObtainer, "objectObtainer must not be null."); + this.unaryOperators = new HashMap<>(); + this.binaryOperators = new HashMap<>(); + } + + /** + * Adds a binary operator to the builder. + * + * @param text + * text used to reference the operator, like '+' + * @param operator + * operator to add + * @param priority + * operator's priority, which determines which operators are applied first + * @return this builder + * @throws NullPointerException + * if {@code text} or {@code operator} is null + * @since 2019-03-17 + * @since v0.2.0 + */ + public Builder addBinaryOperator(final String text, final BinaryOperator operator, final int priority) { + Objects.requireNonNull(text, "text must not be null."); + Objects.requireNonNull(operator, "operator must not be null."); + + // Unfortunately, I cannot use a lambda because the PriorityBinaryOperator requires arguments. + final PriorityBinaryOperator priorityOperator = new PriorityBinaryOperator(priority) { + @Override + public T apply(final T t, final T u) { + return operator.apply(t, u); + } + + }; + this.binaryOperators.put(text, priorityOperator); + return this; + } + + /** + * Adds a function for spaces. You must use the text of an existing binary operator. + * + * @param operator + * text of operator to use + * @return this builder + * @since 2019-03-22 + * @since v0.2.0 + */ + public Builder addSpaceFunction(final String operator) { + Objects.requireNonNull(operator, "operator must not be null."); + + if (!this.binaryOperators.containsKey(operator)) + throw new IllegalArgumentException(String.format("Could not find binary operator '%s'", operator)); + + this.spaceFunction = operator; + return this; + } + + /** + * Adds a unary operator to the builder. + * + * @param text + * text used to reference the operator, like '-' + * @param operator + * operator to add + * @param priority + * operator's priority, which determines which operators are applied first + * @return this builder + * @throws NullPointerException + * if {@code text} or {@code operator} is null + * @since 2019-03-17 + * @since v0.2.0 + */ + public Builder addUnaryOperator(final String text, final UnaryOperator operator, final int priority) { + Objects.requireNonNull(text, "text must not be null."); + Objects.requireNonNull(operator, "operator must not be null."); + + // Unfortunately, I cannot use a lambda because the PriorityUnaryOperator requires arguments. + final PriorityUnaryOperator priorityOperator = new PriorityUnaryOperator(priority) { + @Override + public T apply(final T t) { + return operator.apply(t); + } + }; + this.unaryOperators.put(text, priorityOperator); + return this; + } + + /** + * @return an {@code ExpressionParser} instance with the properties given to this builder + * @since 2019-03-17 + * @since v0.2.0 + */ + public ExpressionParser build() { + return new ExpressionParser<>(this.objectObtainer, this.unaryOperators, this.binaryOperators, + this.spaceFunction); + } + } + + /** + * A binary operator with a priority field that determines which operators apply first. + * + * @author Adrien Hopkins + * @param + * type of operand and result + * @since 2019-03-17 + * @since v0.2.0 + */ + private static abstract class PriorityBinaryOperator + implements BinaryOperator, Comparable> { + /** + * The operator's priority. Higher-priority operators are applied before lower-priority operators + * + * @since 2019-03-17 + * @since v0.2.0 + */ + private final int priority; + + /** + * Creates the {@code PriorityBinaryOperator}. + * + * @param priority + * operator's priority + * @since 2019-03-17 + * @since v0.2.0 + */ + public PriorityBinaryOperator(final int priority) { + this.priority = priority; + } + + /** + * Compares this object to another by priority. + * + *

    + * {@inheritDoc} + *

    + * + * @since 2019-03-17 + * @since v0.2.0 + */ + @Override + public int compareTo(final PriorityBinaryOperator o) { + if (this.priority < o.priority) + return -1; + else if (this.priority > o.priority) + return 1; + else + return 0; + } + + /** + * @return priority + * @since 2019-03-22 + * @since v0.2.0 + */ + public final int getPriority() { + return this.priority; + } + } + + /** + * A unary operator with a priority field that determines which operators apply first. + * + * @author Adrien Hopkins + * @param + * type of operand and result + * @since 2019-03-17 + * @since v0.2.0 + */ + private static abstract class PriorityUnaryOperator + implements UnaryOperator, Comparable> { + /** + * The operator's priority. Higher-priority operators are applied before lower-priority operators + * + * @since 2019-03-17 + * @since v0.2.0 + */ + private final int priority; + + /** + * Creates the {@code PriorityUnaryOperator}. + * + * @param priority + * operator's priority + * @since 2019-03-17 + * @since v0.2.0 + */ + public PriorityUnaryOperator(final int priority) { + this.priority = priority; + } + + /** + * Compares this object to another by priority. + * + *

    + * {@inheritDoc} + *

    + * + * @since 2019-03-17 + * @since v0.2.0 + */ + @Override + public int compareTo(final PriorityUnaryOperator o) { + if (this.priority < o.priority) + return -1; + else if (this.priority > o.priority) + return 1; + else + return 0; + } + + /** + * @return priority + * @since 2019-03-22 + * @since v0.2.0 + */ + public final int getPriority() { + return this.priority; + } + } + + /** + * The types of tokens that are available. + * + * @author Adrien Hopkins + * @since 2019-03-14 + * @since v0.2.0 + */ + private static enum TokenType { + OBJECT, UNARY_OPERATOR, BINARY_OPERATOR; + } + + /** + * The opening bracket. + * + * @since 2019-03-22 + * @since v0.2.0 + */ + public static final char OPENING_BRACKET = '('; + + /** + * The closing bracket. + * + * @since 2019-03-22 + * @since v0.2.0 + */ + public static final char CLOSING_BRACKET = ')'; + + /** + * Finds the other bracket in a pair of brackets, given the position of one. + * + * @param string + * string that contains brackets + * @param bracketPosition + * position of first bracket + * @return position of matching bracket + * @throws NullPointerException + * if string is null + * @since 2019-03-22 + * @since v0.2.0 + */ + private static int findBracketPair(final String string, final int bracketPosition) { + Objects.requireNonNull(string, "string must not be null."); + + final char openingBracket = string.charAt(bracketPosition); + + // figure out what closing bracket to look for + final char closingBracket; + switch (openingBracket) { + case '(': + closingBracket = ')'; + break; + case '[': + closingBracket = ']'; + break; + case '{': + closingBracket = '}'; + break; + default: + throw new IllegalArgumentException(String.format("Invalid bracket '%s'", openingBracket)); + } + + // level of brackets. every opening bracket increments this; every closing bracket decrements it + int bracketLevel = 0; + + // iterate over the string to find the closing bracket + for (int currentPosition = bracketPosition; currentPosition < string.length(); currentPosition++) { + final char currentCharacter = string.charAt(currentPosition); + + if (currentCharacter == openingBracket) { + bracketLevel++; + } else if (currentCharacter == closingBracket) { + bracketLevel--; + if (bracketLevel == 0) + return currentPosition; + } + } + + throw new IllegalArgumentException("No matching bracket found."); + } + + /** + * A function that obtains a parseable object from a string. For example, an integer {@code ExpressionParser} would + * use {@code Integer::parseInt}. + * + * @since 2019-03-14 + * @since v0.2.0 + */ + private final Function objectObtainer; + + /** + * A map mapping operator strings to operator functions, for unary operators. + * + * @since 2019-03-14 + * @since v0.2.0 + */ + private final Map> unaryOperators; + + /** + * A map mapping operator strings to operator functions, for binary operators. + * + * @since 2019-03-14 + * @since v0.2.0 + */ + private final Map> binaryOperators; + + /** + * The operator for space, or null if spaces have no function. + * + * @since 2019-03-22 + * @since v0.2.0 + */ + private final String spaceOperator; + + /** + * Creates the {@code ExpressionParser}. + * + * @param objectObtainer + * function to get objects from strings + * @param unaryOperators + * unary operators available to the parser + * @param binaryOperators + * binary operators available to the parser + * @param spaceOperator + * operator used by spaces + * @since 2019-03-14 + * @since v0.2.0 + */ + private ExpressionParser(final Function objectObtainer, + final Map> unaryOperators, + final Map> binaryOperators, final String spaceOperator) { + this.objectObtainer = objectObtainer; + this.unaryOperators = unaryOperators; + this.binaryOperators = binaryOperators; + this.spaceOperator = spaceOperator; + } + + /** + * Converts a given mathematical expression to reverse Polish notation (operators after operands). + *

    + * For example,
    + * {@code 2 * (3 + 4)}
    + * becomes
    + * {@code 2 3 4 + *}. + * + * @param expression + * expression + * @return expression in RPN + * @since 2019-03-17 + * @since v0.2.0 + */ + private String convertExpressionToReversePolish(final String expression) { + Objects.requireNonNull(expression, "expression must not be null."); + + final List components = new ArrayList<>(); + + // the part of the expression remaining to parse + String partialExpression = expression; + + // find and deal with brackets + while (partialExpression.indexOf(OPENING_BRACKET) != -1) { + final int openingBracketPosition = partialExpression.indexOf(OPENING_BRACKET); + final int closingBracketPosition = findBracketPair(partialExpression, openingBracketPosition); + + // check for function + if (openingBracketPosition > 0 && partialExpression.charAt(openingBracketPosition - 1) != ' ') { + // function like sin(2) or tempF(32) + // find the position of the last space + int spacePosition = openingBracketPosition; + while (spacePosition >= 0 && partialExpression.charAt(spacePosition) != ' ') { + spacePosition--; + } + // then split the function into pre-function and function, using the space position + components.addAll(Arrays.asList(partialExpression.substring(0, spacePosition + 1).split(" "))); + components.add(partialExpression.substring(spacePosition + 1, closingBracketPosition + 1)); + partialExpression = partialExpression.substring(closingBracketPosition + 1); + } else { + // normal brackets like (1 + 2) * (3 / 5) + components.addAll(Arrays.asList(partialExpression.substring(0, openingBracketPosition).split(" "))); + components.add(this.convertExpressionToReversePolish( + partialExpression.substring(openingBracketPosition + 1, closingBracketPosition))); + partialExpression = partialExpression.substring(closingBracketPosition + 1); + } + } + + // add everything else + components.addAll(Arrays.asList(partialExpression.split(" "))); + + // remove empty entries + while (components.contains("")) { + components.remove(""); + } + + // deal with space multiplication (x y) + if (this.spaceOperator != null) { + for (int i = 0; i < components.size() - 1; i++) { + if (this.getTokenType(components.get(i)) == TokenType.OBJECT + && this.getTokenType(components.get(i + 1)) == TokenType.OBJECT) { + components.add(++i, this.spaceOperator); + } + } + } + + // turn the expression into reverse Polish + while (true) { + final int highestPriorityOperatorPosition = this.findHighestPriorityOperatorPosition(components); + if (highestPriorityOperatorPosition == -1) { + break; + } + + // swap components based on what kind of operator there is + // 1 + 2 becomes 2 1 + + // - 1 becomes 1 - + switch (this.getTokenType(components.get(highestPriorityOperatorPosition))) { + case UNARY_OPERATOR: + final String unaryOperator = components.remove(highestPriorityOperatorPosition); + final String operand = components.remove(highestPriorityOperatorPosition); + components.add(highestPriorityOperatorPosition, operand + " " + unaryOperator); + break; + case BINARY_OPERATOR: + final String binaryOperator = components.remove(highestPriorityOperatorPosition); + final String operand1 = components.remove(highestPriorityOperatorPosition - 1); + final String operand2 = components.remove(highestPriorityOperatorPosition - 1); + components.add(highestPriorityOperatorPosition - 1, + operand2 + " " + operand1 + " " + binaryOperator); + break; + default: + throw new AssertionError("Expected operator, found non-operator."); + } + } + + // join all of the components together, then ensure there is only one space in a row + String expressionRPN = String.join(" ", components).replaceAll(" +", " "); + + while (expressionRPN.charAt(0) == ' ') { + expressionRPN = expressionRPN.substring(1); + } + while (expressionRPN.charAt(expressionRPN.length() - 1) == ' ') { + expressionRPN = expressionRPN.substring(0, expressionRPN.length() - 1); + } + return expressionRPN; + } + + /** + * Finds the position of the highest-priority operator in a list + * + * @param components + * components to test + * @param blacklist + * positions of operators that should be ignored + * @return position of highest priority, or -1 if the list contains no operators + * @throws NullPointerException + * if components is null + * @since 2019-03-22 + * @since v0.2.0 + */ + private int findHighestPriorityOperatorPosition(final List components) { + Objects.requireNonNull(components, "components must not be null."); + // find highest priority + int maxPriority = Integer.MIN_VALUE; + int maxPriorityPosition = -1; + + // go over components one by one + // if it is an operator, test its priority to see if it's max + // if it is, update maxPriority and maxPriorityPosition + for (int i = 0; i < components.size(); i++) { + + switch (this.getTokenType(components.get(i))) { + case UNARY_OPERATOR: + final PriorityUnaryOperator unaryOperator = this.unaryOperators.get(components.get(i)); + final int unaryPriority = unaryOperator.getPriority(); + + if (unaryPriority > maxPriority) { + maxPriority = unaryPriority; + maxPriorityPosition = i; + } + break; + case BINARY_OPERATOR: + final PriorityBinaryOperator binaryOperator = this.binaryOperators.get(components.get(i)); + final int binaryPriority = binaryOperator.getPriority(); + + if (binaryPriority > maxPriority) { + maxPriority = binaryPriority; + maxPriorityPosition = i; + } + break; + default: + break; + } + } + + // max priority position found + return maxPriorityPosition; + } + + /** + * Determines whether an inputted string is an object or an operator + * + * @param token + * string to input + * @return type of token it is + * @throws NullPointerException + * if {@code expression} is null + * @since 2019-03-14 + * @since v0.2.0 + */ + private TokenType getTokenType(final String token) { + Objects.requireNonNull(token, "token must not be null."); + + if (this.unaryOperators.containsKey(token)) + return TokenType.UNARY_OPERATOR; + else if (this.binaryOperators.containsKey(token)) + return TokenType.BINARY_OPERATOR; + else + return TokenType.OBJECT; + } + + /** + * Parses an expression. + * + * @param expression + * expression to parse + * @return result + * @throws NullPointerException + * if {@code expression} is null + * @since 2019-03-14 + * @since v0.2.0 + */ + public T parseExpression(final String expression) { + return this.parseReversePolishExpression(this.convertExpressionToReversePolish(expression)); + } + + /** + * Parses an expression expressed in reverse Polish notation. + * + * @param expression + * expression to parse + * @return result + * @throws NullPointerException + * if {@code expression} is null + * @since 2019-03-14 + * @since v0.2.0 + */ + private T parseReversePolishExpression(final String expression) { + Objects.requireNonNull(expression, "expression must not be null."); + + final Deque stack = new ArrayDeque<>(); + + // iterate over every item in the expression, then + for (final String item : expression.split(" ")) { + // choose a path based on what kind of thing was just read + switch (this.getTokenType(item)) { + + case BINARY_OPERATOR: + if (stack.size() < 2) + throw new IllegalStateException(String.format( + "Attempted to call binary operator %s with only %d arguments.", item, stack.size())); + + // get two arguments and operator, then apply! + final T o1 = stack.pop(); + final T o2 = stack.pop(); + final BinaryOperator binaryOperator = this.binaryOperators.get(item); + + stack.push(binaryOperator.apply(o1, o2)); + break; + + case OBJECT: + // just add it to the stack + stack.push(this.objectObtainer.apply(item)); + break; + + case UNARY_OPERATOR: + if (stack.size() < 1) + throw new IllegalStateException(String.format( + "Attempted to call unary operator %s with only %d arguments.", item, stack.size())); + + // get one argument and operator, then apply! + final T o = stack.pop(); + final UnaryOperator unaryOperator = this.unaryOperators.get(item); + + stack.push(unaryOperator.apply(o)); + break; + default: + throw new AssertionError( + String.format("Internal error: Invalid token type %s.", this.getTokenType(item))); + + } + } + + // return answer, or throw an exception if I can't + if (stack.size() > 1) + throw new IllegalStateException("Computation ended up with more than one answer."); + else if (stack.size() == 0) + throw new IllegalStateException("Computation ended up without an answer."); + return stack.pop(); + } +} diff --git a/src/main/java/org/unitConverter/math/ObjectProduct.java b/src/main/java/org/unitConverter/math/ObjectProduct.java new file mode 100644 index 0000000..5217d93 --- /dev/null +++ b/src/main/java/org/unitConverter/math/ObjectProduct.java @@ -0,0 +1,284 @@ +/** + * Copyright (C) 2018 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.math; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; + +/** + * An immutable product of multiple objects of a type, such as base units. The objects can be multiplied and + * exponentiated. + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +public final class ObjectProduct { + /** + * Returns an empty ObjectProduct of a certain type + * + * @param + * type of objects that can be multiplied + * @return empty product + * @since 2019-10-16 + */ + public static final ObjectProduct empty() { + return new ObjectProduct<>(new HashMap<>()); + } + + /** + * Gets an {@code ObjectProduct} from an object-to-integer mapping + * + * @param + * type of object in product + * @param map + * map mapping objects to exponents + * @return object product + * @since 2019-10-16 + */ + public static final ObjectProduct fromExponentMapping(final Map map) { + return new ObjectProduct<>(new HashMap<>(map)); + } + + /** + * Gets an ObjectProduct that has one of the inputted argument, and nothing else. + * + * @param object + * object that will be in the product + * @return product + * @since 2019-10-16 + * @throws NullPointerException + * if object is null + */ + public static final ObjectProduct oneOf(final T object) { + Objects.requireNonNull(object, "object must not be null."); + final Map map = new HashMap<>(); + map.put(object, 1); + return new ObjectProduct<>(map); + } + + /** + * The objects that make up the product, mapped to their exponents. This map treats zero as null, and is immutable. + * + * @since 2019-10-16 + */ + final Map exponents; + + /** + * Creates the {@code ObjectProduct}. + * + * @param exponents + * objects that make up this product + * @since 2019-10-16 + */ + private ObjectProduct(final Map exponents) { + this.exponents = Collections.unmodifiableMap(ConditionalExistenceCollections.conditionalExistenceMap(exponents, + e -> !Integer.valueOf(0).equals(e.getValue()))); + } + + /** + * Calculates the quotient of two products + * + * @param other + * other product + * @return quotient of two products + * @since 2019-10-16 + * @throws NullPointerException + * if other is null + */ + public ObjectProduct dividedBy(final ObjectProduct other) { + Objects.requireNonNull(other, "other must not be null."); + // get a list of all objects in both sets + final Set objects = new HashSet<>(); + objects.addAll(this.getBaseSet()); + objects.addAll(other.getBaseSet()); + + // get a list of all exponents + final Map map = new HashMap<>(objects.size()); + for (final T key : objects) { + map.put(key, this.getExponent(key) - other.getExponent(key)); + } + + // create the product + return new ObjectProduct<>(map); + } + + // this method relies on the use of ZeroIsNullMap + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (!(obj instanceof ObjectProduct)) + return false; + final ObjectProduct other = (ObjectProduct) obj; + return Objects.equals(this.exponents, other.exponents); + } + + /** + * @return immutable map mapping objects to exponents + * @since 2019-10-16 + */ + public Map exponentMap() { + return this.exponents; + } + + /** + * @return a set of all of the base objects with non-zero exponents that make up this dimension. + * @since 2018-12-12 + * @since v0.1.0 + */ + public final Set getBaseSet() { + final Set dimensions = new HashSet<>(); + + // add all dimensions with a nonzero exponent - zero exponents shouldn't be there in the first place + for (final T dimension : this.exponents.keySet()) { + if (!this.exponents.get(dimension).equals(0)) { + dimensions.add(dimension); + } + } + + return dimensions; + } + + /** + * Gets the exponent for a specific dimension. + * + * @param dimension + * dimension to check + * @return exponent for that dimension + * @since 2018-12-12 + * @since v0.1.0 + */ + public int getExponent(final T dimension) { + return this.exponents.getOrDefault(dimension, 0); + } + + @Override + public int hashCode() { + return Objects.hash(this.exponents); + } + + /** + * @return true if this product is a single object, i.e. it has one exponent of one and no other nonzero exponents + * @since 2019-10-16 + */ + public boolean isSingleObject() { + int oneCount = 0; + boolean twoOrMore = false; // has exponents of 2 or more + for (final T b : this.getBaseSet()) { + if (this.getExponent(b) == 1) { + oneCount++; + } else if (this.getExponent(b) != 0) { + twoOrMore = true; + } + } + return oneCount == 1 && !twoOrMore; + } + + /** + * Multiplies this product by another + * + * @param other + * other product + * @return product of two products + * @since 2019-10-16 + * @throws NullPointerException + * if other is null + */ + public ObjectProduct times(final ObjectProduct other) { + Objects.requireNonNull(other, "other must not be null."); + // get a list of all objects in both sets + final Set objects = new HashSet<>(); + objects.addAll(this.getBaseSet()); + objects.addAll(other.getBaseSet()); + + // get a list of all exponents + final Map map = new HashMap<>(objects.size()); + for (final T key : objects) { + map.put(key, this.getExponent(key) + other.getExponent(key)); + } + + // create the product + return new ObjectProduct<>(map); + } + + /** + * Returns this product, but to an exponent + * + * @param exponent + * exponent + * @return result of exponentiation + * @since 2019-10-16 + */ + public ObjectProduct toExponent(final int exponent) { + final Map map = new HashMap<>(this.exponents); + for (final T key : this.exponents.keySet()) { + map.put(key, this.getExponent(key) * exponent); + } + return new ObjectProduct<>(map); + } + + /** + * Converts this product to a string using the objects' {@link Object#toString()} method. If objects have a long + * toString representation, it is recommended to use {@link #toString(Function)} instead to shorten the returned + * string. + * + *

    + * {@inheritDoc} + */ + @Override + public String toString() { + return this.toString(Object::toString); + } + + /** + * Converts this product to a string. The objects that make up this product are represented by + * {@code objectToString} + * + * @param objectToString + * function to convert objects to strings + * @return string representation of product + * @since 2019-10-16 + */ + public String toString(final Function objectToString) { + final List positiveStringComponents = new ArrayList<>(); + final List negativeStringComponents = new ArrayList<>(); + + // for each base object that makes up this object, add it and its exponent + for (final T object : this.getBaseSet()) { + final int exponent = this.exponents.get(object); + if (exponent > 0) { + positiveStringComponents.add(String.format("%s^%d", objectToString.apply(object), exponent)); + } else if (exponent < 0) { + negativeStringComponents.add(String.format("%s^%d", objectToString.apply(object), -exponent)); + } + } + + final String positiveString = positiveStringComponents.isEmpty() ? "1" + : String.join(" * ", positiveStringComponents); + final String negativeString = negativeStringComponents.isEmpty() ? "" + : " / " + String.join(" * ", negativeStringComponents); + + return positiveString + negativeString; + } +} diff --git a/src/main/java/org/unitConverter/math/UncertainDouble.java b/src/main/java/org/unitConverter/math/UncertainDouble.java new file mode 100644 index 0000000..3651bd5 --- /dev/null +++ b/src/main/java/org/unitConverter/math/UncertainDouble.java @@ -0,0 +1,419 @@ +/** + * Copyright (C) 2020 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.math; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A double with an associated uncertainty value. For example, 3.2 ± 0.2. + *

    + * All methods in this class throw a NullPointerException if any of their + * arguments is null. + * + * @since 2020-09-07 + */ +public final class UncertainDouble implements Comparable { + /** + * The exact value 0 + */ + public static final UncertainDouble ZERO = UncertainDouble.of(0, 0); + + /** + * A regular expression that can recognize toString forms + */ + private static final Pattern TO_STRING = Pattern + .compile("([a-zA-Z_0-9\\.\\,]+)" // a number + // optional "± [number]" + + "(?:\\s*(?:±|\\+-)\\s*([a-zA-Z_0-9\\.\\,]+))?"); + + /** + * Parses a string in the form of {@link UncertainDouble#toString(boolean)} + * and returns the corresponding {@code UncertainDouble} instance. + *

    + * This method allows some alternative forms of the string representation, + * such as using "+-" instead of "±". + * + * @param s string to parse + * @return {@code UncertainDouble} instance + * @throws IllegalArgumentException if the string is invalid + * @since 2020-09-07 + */ + public static final UncertainDouble fromString(String s) { + Objects.requireNonNull(s, "s may not be null"); + final Matcher matcher = TO_STRING.matcher(s); + + double value, uncertainty; + try { + value = Double.parseDouble(matcher.group(1)); + } catch (IllegalStateException | NumberFormatException e) { + throw new IllegalArgumentException( + "String " + s + " not in correct format."); + } + + final String uncertaintyString = matcher.group(2); + if (uncertaintyString == null) { + uncertainty = 0; + } else { + try { + uncertainty = Double.parseDouble(uncertaintyString); + } catch (final NumberFormatException e) { + throw new IllegalArgumentException( + "String " + s + " not in correct format."); + } + } + + return UncertainDouble.of(value, uncertainty); + } + + /** + * Gets an {@code UncertainDouble} from its value and absolute + * uncertainty. + * + * @since 2020-09-07 + */ + public static final UncertainDouble of(double value, double uncertainty) { + return new UncertainDouble(value, uncertainty); + } + + /** + * Gets an {@code UncertainDouble} from its value and relative + * uncertainty. + * + * @since 2020-09-07 + */ + public static final UncertainDouble ofRelative(double value, + double relativeUncertainty) { + return new UncertainDouble(value, value * relativeUncertainty); + } + + private final double value; + + private final double uncertainty; + + /** + * @param value + * @param uncertainty + * @since 2020-09-07 + */ + private UncertainDouble(double value, double uncertainty) { + this.value = value; + // uncertainty should only ever be positive + this.uncertainty = Math.abs(uncertainty); + } + + /** + * Compares this {@code UncertainDouble} with another + * {@code UncertainDouble}. + *

    + * This method only compares the values, not the uncertainties. So 3.1 ± 0.5 + * is considered less than 3.2 ± 0.5, even though they are equivalent. + *

    + * Note: The natural ordering of this class is inconsistent with + * equals. Specifically, if two {@code UncertainDouble} instances {@code a} + * and {@code b} have the same value but different uncertainties, + * {@code a.compareTo(b)} will return 0 but {@code a.equals(b)} will return + * {@code false}. + */ + @Override + public final int compareTo(UncertainDouble o) { + return Double.compare(this.value, o.value); + } + + /** + * Returns the quotient of {@code this} and {@code other}. + * + * @since 2020-09-07 + */ + public final UncertainDouble dividedBy(UncertainDouble other) { + Objects.requireNonNull(other, "other may not be null"); + return UncertainDouble.ofRelative(this.value / other.value, Math + .hypot(this.relativeUncertainty(), other.relativeUncertainty())); + } + + /** + * Returns the quotient of {@code this} and the exact value {@code other}. + * + * @since 2020-09-07 + */ + public final UncertainDouble dividedByExact(double other) { + return UncertainDouble.of(this.value / other, this.uncertainty / other); + } + + @Override + public final boolean equals(Object obj) { + if (this == obj) + return true; + if (!(obj instanceof UncertainDouble)) + return false; + final UncertainDouble other = (UncertainDouble) obj; + if (Double.compare(this.value, other.value) != 0) + return false; + if (Double.compare(this.uncertainty, other.uncertainty) != 0) + return false; + return true; + } + + /** + * @param other another {@code UncertainDouble} + * @return true iff this and {@code other} are within each other's + * uncertainty range. + * @since 2020-09-07 + */ + public final boolean equivalent(UncertainDouble other) { + Objects.requireNonNull(other, "other may not be null"); + return Math.abs(this.value - other.value) <= Math.min(this.uncertainty, + other.uncertainty); + } + + /** + * Gets the preferred scale for rounding a value for toString. + * + * @since 2020-09-07 + */ + private final int getDisplayScale() { + // round based on uncertainty + // if uncertainty starts with 1 (ignoring zeroes and the decimal + // point), rounds + // so that uncertainty has 2 significant digits. + // otherwise, rounds so that uncertainty has 1 significant digits. + // the value is rounded to the same number of decimal places as the + // uncertainty. + final BigDecimal bigUncertainty = BigDecimal.valueOf(this.uncertainty); + + // the scale that will give the uncertainty two decimal places + final int twoDecimalPlacesScale = bigUncertainty.scale() + - bigUncertainty.precision() + 2; + final BigDecimal roundedUncertainty = bigUncertainty + .setScale(twoDecimalPlacesScale, RoundingMode.HALF_EVEN); + + if (roundedUncertainty.unscaledValue().intValue() >= 20) + return twoDecimalPlacesScale - 1; // one decimal place + else + return twoDecimalPlacesScale; + } + + @Override + public final int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Double.hashCode(this.value); + result = prime * result + Double.hashCode(this.uncertainty); + return result; + } + + /** + * @return true iff the value has no uncertainty + * + * @since 2020-09-07 + */ + public final boolean isExact() { + return this.uncertainty == 0; + } + + /** + * Returns the difference of {@code this} and {@code other}. + * + * @since 2020-09-07 + */ + public final UncertainDouble minus(UncertainDouble other) { + Objects.requireNonNull(other, "other may not be null"); + return UncertainDouble.of(this.value - other.value, + Math.hypot(this.uncertainty, other.uncertainty)); + } + + /** + * Returns the difference of {@code this} and the exact value {@code other}. + * + * @since 2020-09-07 + */ + public final UncertainDouble minusExact(double other) { + return UncertainDouble.of(this.value - other, this.uncertainty); + } + + /** + * Returns the sum of {@code this} and {@code other}. + * + * @since 2020-09-07 + */ + public final UncertainDouble plus(UncertainDouble other) { + Objects.requireNonNull(other, "other may not be null"); + return UncertainDouble.of(this.value + other.value, + Math.hypot(this.uncertainty, other.uncertainty)); + } + + /** + * Returns the sum of {@code this} and the exact value {@code other}. + * + * @since 2020-09-07 + */ + public final UncertainDouble plusExact(double other) { + return UncertainDouble.of(this.value + other, this.uncertainty); + } + + /** + * @return relative uncertainty + * @since 2020-09-07 + */ + public final double relativeUncertainty() { + return this.uncertainty / this.value; + } + + /** + * Returns the product of {@code this} and {@code other}. + * + * @since 2020-09-07 + */ + public final UncertainDouble times(UncertainDouble other) { + Objects.requireNonNull(other, "other may not be null"); + return UncertainDouble.ofRelative(this.value * other.value, Math + .hypot(this.relativeUncertainty(), other.relativeUncertainty())); + } + + /** + * Returns the product of {@code this} and the exact value {@code other}. + * + * @since 2020-09-07 + */ + public final UncertainDouble timesExact(double other) { + return UncertainDouble.of(this.value * other, this.uncertainty * other); + } + + /** + * Returns the result of {@code this} raised to the exponent {@code other}. + * + * @since 2020-09-07 + */ + public final UncertainDouble toExponent(UncertainDouble other) { + Objects.requireNonNull(other, "other may not be null"); + + final double result = Math.pow(this.value, other.value); + final double relativeUncertainty = Math.hypot( + other.value * this.relativeUncertainty(), + Math.log(this.value) * other.uncertainty); + + return UncertainDouble.ofRelative(result, relativeUncertainty); + } + + /** + * Returns the result of {@code this} raised the exact exponent + * {@code other}. + * + * @since 2020-09-07 + */ + public final UncertainDouble toExponentExact(double other) { + return UncertainDouble.ofRelative(Math.pow(this.value, other), + this.relativeUncertainty() * other); + } + + /** + * Returns a string representation of this {@code UncertainDouble}. + *

    + * This method returns the same value as {@link #toString(boolean)}, but + * {@code showUncertainty} is true if and only if the uncertainty is + * non-zero. + * + *

    + * Examples: + * + *

    +	 * UncertainDouble.of(3.27, 0.22).toString() = "3.3 ± 0.2"
    +	 * UncertainDouble.of(3.27, 0.13).toString() = "3.27 ± 0.13"
    +	 * UncertainDouble.of(-5.01, 0).toString() = "-5.01"
    +	 * 
    + * + * @since 2020-09-07 + */ + @Override + public final String toString() { + return this.toString(!this.isExact()); + } + + /** + * Returns a string representation of this {@code UncertainDouble}. + *

    + * If {@code showUncertainty} is true, the string will be of the form "VALUE + * ± UNCERTAINTY", and if it is false the string will be of the form "VALUE" + *

    + * VALUE represents a string representation of this {@code UncertainDouble}'s + * value. If the uncertainty is non-zero, the string will be rounded to the + * same precision as the uncertainty, otherwise it will not be rounded. The + * string is still rounded if {@code showUncertainty} is false.
    + * UNCERTAINTY represents a string representation of this + * {@code UncertainDouble}'s uncertainty. If the uncertainty ends in 1X + * (where X represents any digit) it will be rounded to two significant + * digits otherwise it will be rounded to one significant digit. + *

    + * Examples: + * + *

    +	 * UncertainDouble.of(3.27, 0.22).toString(false) = "3.3"
    +	 * UncertainDouble.of(3.27, 0.22).toString(true) = "3.3 ± 0.2"
    +	 * UncertainDouble.of(3.27, 0.13).toString(false) = "3.27"
    +	 * UncertainDouble.of(3.27, 0.13).toString(true) = "3.27 ± 0.13"
    +	 * UncertainDouble.of(-5.01, 0).toString(false) = "-5.01"
    +	 * UncertainDouble.of(-5.01, 0).toString(true) = "-5.01 ± 0.0"
    +	 * 
    + * + * @since 2020-09-07 + */ + public final String toString(boolean showUncertainty) { + String valueString, uncertaintyString; + + // generate the string representation of value and uncertainty + if (this.isExact()) { + uncertaintyString = "0.0"; + valueString = Double.toString(this.value); + + } else { + // round the value and uncertainty according to getDisplayScale() + final BigDecimal bigValue = BigDecimal.valueOf(this.value); + final BigDecimal bigUncertainty = BigDecimal.valueOf(this.uncertainty); + + final int displayScale = this.getDisplayScale(); + final BigDecimal roundedUncertainty = bigUncertainty + .setScale(displayScale, RoundingMode.HALF_EVEN); + final BigDecimal roundedValue = bigValue.setScale(displayScale, + RoundingMode.HALF_EVEN); + + valueString = roundedValue.toString(); + uncertaintyString = roundedUncertainty.toString(); + } + + // return "value" or "value ± uncertainty" depending on showUncertainty + return valueString + (showUncertainty ? " ± " + uncertaintyString : ""); + } + + /** + * @return absolute uncertainty + * @since 2020-09-07 + */ + public final double uncertainty() { + return this.uncertainty; + } + + /** + * @return value without uncertainty + * @since 2020-09-07 + */ + public final double value() { + return this.value; + } +} diff --git a/src/main/java/org/unitConverter/math/package-info.java b/src/main/java/org/unitConverter/math/package-info.java new file mode 100644 index 0000000..65727e4 --- /dev/null +++ b/src/main/java/org/unitConverter/math/package-info.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +/** + * Supplementary classes that are not related to units, but are necessary for their function. + * + * @author Adrien Hopkins + * @since 2019-03-14 + * @since v0.2.0 + */ +package org.unitConverter.math; \ No newline at end of file diff --git a/src/main/java/org/unitConverter/package-info.java b/src/main/java/org/unitConverter/package-info.java new file mode 100644 index 0000000..23dd165 --- /dev/null +++ b/src/main/java/org/unitConverter/package-info.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +/** + * A program that converts units. + * + * @author Adrien Hopkins + * @version v0.2.0 + * @since 2019-01-25 + */ +package org.unitConverter; \ No newline at end of file diff --git a/src/main/java/org/unitConverter/unit/BaseDimension.java b/src/main/java/org/unitConverter/unit/BaseDimension.java new file mode 100644 index 0000000..8e63a17 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/BaseDimension.java @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.Objects; + +/** + * A dimension that defines a {@code BaseUnit} + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +public final class BaseDimension { + /** + * Gets a {@code BaseDimension} with the provided name and symbol. + * + * @param name + * name of dimension + * @param symbol + * symbol used for dimension + * @return dimension + * @since 2019-10-16 + */ + public static BaseDimension valueOf(final String name, final String symbol) { + return new BaseDimension(name, symbol); + } + + /** + * The name of the dimension. + */ + private final String name; + /** + * The symbol used by the dimension. Symbols should be short, generally one or two characters. + */ + private final String symbol; + + /** + * Creates the {@code BaseDimension}. + * + * @param name + * name of unit + * @param symbol + * symbol of unit + * @throws NullPointerException + * if any argument is null + * @since 2019-10-16 + */ + private BaseDimension(final String name, final String symbol) { + this.name = Objects.requireNonNull(name, "name must not be null."); + this.symbol = Objects.requireNonNull(symbol, "symbol must not be null."); + } + + /** + * @return name + * @since 2019-10-16 + */ + public final String getName() { + return this.name; + } + + /** + * @return symbol + * @since 2019-10-16 + */ + public final String getSymbol() { + return this.symbol; + } + + @Override + public String toString() { + return String.format("%s (%s)", this.getName(), this.getSymbol()); + } +} diff --git a/src/main/java/org/unitConverter/unit/BaseUnit.java b/src/main/java/org/unitConverter/unit/BaseUnit.java new file mode 100644 index 0000000..6757bd0 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/BaseUnit.java @@ -0,0 +1,133 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** + * A unit that other units are defined by. + *

    + * Note that BaseUnits must have names and symbols. This is because they + * are used for toString code. Therefore, the Optionals provided by + * {@link #getPrimaryName} and {@link #getSymbol} will always contain a value. + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +public final class BaseUnit extends Unit { + /** + * Gets a base unit from the dimension it measures, its name and its symbol. + * + * @param dimension dimension measured by this unit + * @param name name of unit + * @param symbol symbol of unit + * @return base unit + * @since 2019-10-16 + */ + public static BaseUnit valueOf(final BaseDimension dimension, + final String name, final String symbol) { + return new BaseUnit(dimension, name, symbol, new HashSet<>()); + } + + /** + * Gets a base unit from the dimension it measures, its name and its symbol. + * + * @param dimension dimension measured by this unit + * @param name name of unit + * @param symbol symbol of unit + * @return base unit + * @since 2019-10-21 + */ + public static BaseUnit valueOf(final BaseDimension dimension, + final String name, final String symbol, final Set otherNames) { + return new BaseUnit(dimension, name, symbol, otherNames); + } + + /** + * The dimension measured by this base unit. + */ + private final BaseDimension dimension; + + /** + * Creates the {@code BaseUnit}. + * + * @param dimension dimension of unit + * @param primaryName name of unit + * @param symbol symbol of unit + * @throws NullPointerException if any argument is null + * @since 2019-10-16 + */ + private BaseUnit(final BaseDimension dimension, final String primaryName, + final String symbol, final Set otherNames) { + super(primaryName, symbol, otherNames); + this.dimension = Objects.requireNonNull(dimension, + "dimension must not be null."); + } + + /** + * Returns a {@code LinearUnit} with this unit as a base and a conversion + * factor of 1. This operation must be done in order to allow units to be + * created with operations. + * + * @return this unit as a {@code LinearUnit} + * @since 2019-10-16 + */ + public LinearUnit asLinearUnit() { + return LinearUnit.valueOf(this.getBase(), 1); + } + + @Override + protected double convertFromBase(final double value) { + return value; + } + + @Override + protected double convertToBase(final double value) { + return value; + } + + /** + * @return dimension + * @since 2019-10-16 + */ + public final BaseDimension getBaseDimension() { + return this.dimension; + } + + @Override + public String toString() { + return this.getPrimaryName().orElse("Unnamed unit") + + (this.getSymbol().isPresent() + ? String.format(" (%s)", this.getSymbol().get()) + : ""); + } + + @Override + public BaseUnit withName(final NameSymbol ns) { + Objects.requireNonNull(ns, "ns must not be null."); + if (!ns.getPrimaryName().isPresent()) + throw new IllegalArgumentException( + "BaseUnits must have primary names."); + if (!ns.getSymbol().isPresent()) + throw new IllegalArgumentException("BaseUnits must have symbols."); + return BaseUnit.valueOf(this.getBaseDimension(), + ns.getPrimaryName().get(), ns.getSymbol().get(), + ns.getOtherNames()); + } +} diff --git a/src/main/java/org/unitConverter/unit/BritishImperial.java b/src/main/java/org/unitConverter/unit/BritishImperial.java new file mode 100644 index 0000000..ea23cd1 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/BritishImperial.java @@ -0,0 +1,116 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +/** + * A static utility class that contains units in the British Imperial system. + * + * @author Adrien Hopkins + * @since 2019-10-21 + */ +public final class BritishImperial { + /** + * Imperial units that measure area + * + * @author Adrien Hopkins + * @since 2019-11-08 + */ + public static final class Area { + public static final LinearUnit SQUARE_FOOT = Length.FOOT.toExponent(2); + public static final LinearUnit SQUARE_YARD = Length.YARD.toExponent(2); + public static final LinearUnit SQUARE_MILE = Length.MILE.toExponent(2); + public static final LinearUnit PERCH = Length.ROD.times(Length.ROD); + public static final LinearUnit ROOD = Length.ROD.times(Length.FURLONG); + public static final LinearUnit ACRE = Length.FURLONG.times(Length.CHAIN); + } + + /** + * Imperial units that measure length + * + * @author Adrien Hopkins + * @since 2019-10-28 + */ + public static final class Length { + /** + * According to the International Yard and Pound of 1959, a yard is defined as exactly 0.9144 metres. + */ + public static final LinearUnit YARD = SI.METRE.times(0.9144); + public static final LinearUnit FOOT = YARD.dividedBy(3); + public static final LinearUnit INCH = FOOT.dividedBy(12); + public static final LinearUnit THOU = INCH.dividedBy(1000); + public static final LinearUnit CHAIN = YARD.times(22); + public static final LinearUnit FURLONG = CHAIN.times(10); + public static final LinearUnit MILE = FURLONG.times(8); + public static final LinearUnit LEAGUE = MILE.times(3); + + public static final LinearUnit NAUTICAL_MILE = SI.METRE.times(1852); + public static final LinearUnit CABLE = NAUTICAL_MILE.dividedBy(10); + public static final LinearUnit FATHOM = CABLE.dividedBy(100); + + public static final LinearUnit ROD = YARD.times(5.5); + public static final LinearUnit LINK = ROD.dividedBy(25); + } + + /** + * British Imperial units that measure mass. + * + * @author Adrien Hopkins + * @since 2019-11-08 + */ + public static final class Mass { + public static final LinearUnit POUND = SI.GRAM.times(453.59237); + public static final LinearUnit OUNCE = POUND.dividedBy(16); + public static final LinearUnit DRACHM = POUND.dividedBy(256); + public static final LinearUnit GRAIN = POUND.dividedBy(7000); + public static final LinearUnit STONE = POUND.times(14); + public static final LinearUnit QUARTER = STONE.times(2); + public static final LinearUnit HUNDREDWEIGHT = QUARTER.times(4); + public static final LinearUnit LONG_TON = HUNDREDWEIGHT.times(20); + public static final LinearUnit SLUG = SI.KILOGRAM.times(14.59390294); + } + + /** + * British Imperial units that measure volume + * + * @author Adrien Hopkins + * @since 2019-11-08 + */ + public static final class Volume { + public static final LinearUnit FLUID_OUNCE = SI.LITRE.withPrefix(SI.MILLI).times(28.4130625); + public static final LinearUnit GILL = FLUID_OUNCE.times(5); + public static final LinearUnit PINT = FLUID_OUNCE.times(20); + public static final LinearUnit QUART = PINT.times(2); + public static final LinearUnit GALLON = QUART.times(4); + public static final LinearUnit PECK = GALLON.times(2); + public static final LinearUnit BUSHEL = PECK.times(4); + + public static final LinearUnit CUBIC_INCH = Length.INCH.toExponent(3); + public static final LinearUnit CUBIC_FOOT = Length.FOOT.toExponent(3); + public static final LinearUnit CUBIC_YARD = Length.YARD.toExponent(3); + public static final LinearUnit ACRE_FOOT = Area.ACRE.times(Length.FOOT); + } + + public static final LinearUnit OUNCE_FORCE = Mass.OUNCE.times(SI.Constants.EARTH_GRAVITY); + public static final LinearUnit POUND_FORCE = Mass.POUND.times(SI.Constants.EARTH_GRAVITY); + + public static final LinearUnit BRITISH_THERMAL_UNIT = SI.JOULE.times(1055.06); + public static final LinearUnit CALORIE = SI.JOULE.times(4.184); + public static final LinearUnit KILOCALORIE = SI.JOULE.times(4184); + + public static final Unit FAHRENHEIT = Unit.fromConversionFunctions(SI.KELVIN.getBase(), + tempK -> tempK * 1.8 - 459.67, tempF -> (tempF + 459.67) / 1.8); +} diff --git a/src/main/java/org/unitConverter/unit/FunctionalUnit.java b/src/main/java/org/unitConverter/unit/FunctionalUnit.java new file mode 100644 index 0000000..586e0d7 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/FunctionalUnit.java @@ -0,0 +1,109 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.Objects; +import java.util.function.DoubleUnaryOperator; + +import org.unitConverter.math.ObjectProduct; + +/** + * A unit that uses functional objects to convert to and from its base. + * + * @author Adrien Hopkins + * @since 2019-05-22 + */ +final class FunctionalUnit extends Unit { + /** + * A function that accepts a value expressed in the unit's base and returns that value expressed in this unit. + * + * @since 2019-05-22 + */ + private final DoubleUnaryOperator converterFrom; + + /** + * A function that accepts a value expressed in the unit and returns that value expressed in the unit's base. + * + * @since 2019-05-22 + */ + private final DoubleUnaryOperator converterTo; + + /** + * Creates the {@code FunctionalUnit}. + * + * @param base + * unit's base + * @param converterFrom + * function that accepts a value expressed in the unit's base and returns that value expressed in this + * unit. + * @param converterTo + * function that accepts a value expressed in the unit and returns that value expressed in the unit's + * base. + * @throws NullPointerException + * if any argument is null + * @since 2019-05-22 + */ + public FunctionalUnit(final ObjectProduct base, final DoubleUnaryOperator converterFrom, + final DoubleUnaryOperator converterTo) { + super(base, NameSymbol.EMPTY); + this.converterFrom = Objects.requireNonNull(converterFrom, "converterFrom must not be null."); + this.converterTo = Objects.requireNonNull(converterTo, "converterTo must not be null."); + } + + /** + * Creates the {@code FunctionalUnit}. + * + * @param base + * unit's base + * @param converterFrom + * function that accepts a value expressed in the unit's base and returns that value expressed in this + * unit. + * @param converterTo + * function that accepts a value expressed in the unit and returns that value expressed in the unit's + * base. + * @throws NullPointerException + * if any argument is null + * @since 2019-05-22 + */ + public FunctionalUnit(final ObjectProduct base, final DoubleUnaryOperator converterFrom, + final DoubleUnaryOperator converterTo, final NameSymbol ns) { + super(base, ns); + this.converterFrom = Objects.requireNonNull(converterFrom, "converterFrom must not be null."); + this.converterTo = Objects.requireNonNull(converterTo, "converterTo must not be null."); + } + + /** + * {@inheritDoc} + * + * Uses {@code converterFrom} to convert. + */ + @Override + public double convertFromBase(final double value) { + return this.converterFrom.applyAsDouble(value); + } + + /** + * {@inheritDoc} + * + * Uses {@code converterTo} to convert. + */ + @Override + public double convertToBase(final double value) { + return this.converterTo.applyAsDouble(value); + } + +} diff --git a/src/main/java/org/unitConverter/unit/FunctionalUnitlike.java b/src/main/java/org/unitConverter/unit/FunctionalUnitlike.java new file mode 100644 index 0000000..21c1fca --- /dev/null +++ b/src/main/java/org/unitConverter/unit/FunctionalUnitlike.java @@ -0,0 +1,72 @@ +/** + * Copyright (C) 2020 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.function.DoubleFunction; +import java.util.function.ToDoubleFunction; + +import org.unitConverter.math.ObjectProduct; + +/** + * A unitlike form that converts using two conversion functions. + * + * @since 2020-09-07 + */ +final class FunctionalUnitlike extends Unitlike { + /** + * A function that accepts a value in the unitlike form's base and returns a + * value in the unitlike form. + * + * @since 2020-09-07 + */ + private final DoubleFunction converterFrom; + + /** + * A function that accepts a value in the unitlike form and returns a value + * in the unitlike form's base. + */ + private final ToDoubleFunction converterTo; + + /** + * Creates the {@code FunctionalUnitlike}. + * + * @param base unitlike form's base + * @param converterFrom function that accepts a value in the unitlike form's + * base and returns a value in the unitlike form. + * @param converterTo function that accepts a value in the unitlike form + * and returns a value in the unitlike form's base. + * @throws NullPointerException if any argument is null + * @since 2019-05-22 + */ + protected FunctionalUnitlike(ObjectProduct unitBase, NameSymbol ns, + DoubleFunction converterFrom, ToDoubleFunction converterTo) { + super(unitBase, ns); + this.converterFrom = converterFrom; + this.converterTo = converterTo; + } + + @Override + protected V convertFromBase(double value) { + return this.converterFrom.apply(value); + } + + @Override + protected double convertToBase(V value) { + return this.converterTo.applyAsDouble(value); + } + +} diff --git a/src/main/java/org/unitConverter/unit/LinearUnit.java b/src/main/java/org/unitConverter/unit/LinearUnit.java new file mode 100644 index 0000000..b7f33d5 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/LinearUnit.java @@ -0,0 +1,441 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.Objects; + +import org.unitConverter.math.DecimalComparison; +import org.unitConverter.math.ObjectProduct; +import org.unitConverter.math.UncertainDouble; + +/** + * A unit that can be expressed as a product of its base and a number. For + * example, kilometres, inches and pounds. + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +public final class LinearUnit extends Unit { + /** + * Gets a {@code LinearUnit} from a unit and a value. For example, converts + * '59 °F' to a linear unit with the value of '288.15 K' + * + * @param unit unit to convert + * @param value value to convert + * @return value expressed as a {@code LinearUnit} + * @since 2019-10-16 + * @throws NullPointerException if unit is null + */ + public static LinearUnit fromUnitValue(final Unit unit, final double value) { + return new LinearUnit( + Objects.requireNonNull(unit, "unit must not be null.").getBase(), + unit.convertToBase(value), NameSymbol.EMPTY); + } + + /** + * Gets a {@code LinearUnit} from a unit and a value. For example, converts + * '59 °F' to a linear unit with the value of '288.15 K' + * + * @param unit unit to convert + * @param value value to convert + * @param ns name(s) and symbol of unit + * @return value expressed as a {@code LinearUnit} + * @since 2019-10-21 + * @throws NullPointerException if unit or ns is null + */ + public static LinearUnit fromUnitValue(final Unit unit, final double value, + final NameSymbol ns) { + return new LinearUnit( + Objects.requireNonNull(unit, "unit must not be null.").getBase(), + unit.convertToBase(value), ns); + } + + /** + * @return the base unit associated with {@code unit}, as a + * {@code LinearUnit}. + * @since 2020-10-02 + */ + public static LinearUnit getBase(final Unit unit) { + return new LinearUnit(unit.getBase(), 1, NameSymbol.EMPTY); + } + + /** + * @return the base unit associated with {@code unitlike}, as a + * {@code LinearUnit}. + * @since 2020-10-02 + */ + public static LinearUnit getBase(final Unitlike unit) { + return new LinearUnit(unit.getBase(), 1, NameSymbol.EMPTY); + } + + /** + * Gets a {@code LinearUnit} from a unit base and a conversion factor. In + * other words, gets the product of {@code unitBase} and + * {@code conversionFactor}, expressed as a {@code LinearUnit}. + * + * @param unitBase unit base to multiply by + * @param conversionFactor number to multiply base by + * @return product of base and conversion factor + * @since 2019-10-16 + * @throws NullPointerException if unitBase is null + */ + public static LinearUnit valueOf(final ObjectProduct unitBase, + final double conversionFactor) { + return new LinearUnit(unitBase, conversionFactor, NameSymbol.EMPTY); + } + + /** + * Gets a {@code LinearUnit} from a unit base and a conversion factor. In + * other words, gets the product of {@code unitBase} and + * {@code conversionFactor}, expressed as a {@code LinearUnit}. + * + * @param unitBase unit base to multiply by + * @param conversionFactor number to multiply base by + * @param ns name(s) and symbol of unit + * @return product of base and conversion factor + * @since 2019-10-21 + * @throws NullPointerException if unitBase is null + */ + public static LinearUnit valueOf(final ObjectProduct unitBase, + final double conversionFactor, final NameSymbol ns) { + return new LinearUnit(unitBase, conversionFactor, ns); + } + + /** + * The value of this unit as represented in its base form. Mathematically, + * + *

    +	 * this = conversionFactor * getBase()
    +	 * 
    + * + * @since 2019-10-16 + */ + private final double conversionFactor; + + /** + * Creates the {@code LinearUnit}. + * + * @param unitBase base of linear unit + * @param conversionFactor conversion factor between base and unit + * @since 2019-10-16 + */ + private LinearUnit(final ObjectProduct unitBase, + final double conversionFactor, final NameSymbol ns) { + super(unitBase, ns); + this.conversionFactor = conversionFactor; + } + + /** + * {@inheritDoc} + * + * Converts by dividing by {@code conversionFactor} + */ + @Override + protected double convertFromBase(final double value) { + return value / this.getConversionFactor(); + } + + /** + * Converts an {@code UncertainDouble} value expressed in this unit to an + * {@code UncertainValue} value expressed in {@code other}. + * + * @param other unit to convert to + * @param value value to convert + * @return converted value + * @since 2019-09-07 + * @throws IllegalArgumentException if {@code other} is incompatible for + * conversion with this unit (as tested by + * {@link Unit#canConvertTo}). + * @throws NullPointerException if value or other is null + */ + public UncertainDouble convertTo(LinearUnit other, UncertainDouble value) { + Objects.requireNonNull(other, "other must not be null."); + Objects.requireNonNull(value, "value may not be null."); + if (this.canConvertTo(other)) + return value.timesExact( + this.getConversionFactor() / other.getConversionFactor()); + else + throw new IllegalArgumentException( + String.format("Cannot convert from %s to %s.", this, other)); + + } + + /** + * {@inheritDoc} + * + * Converts by multiplying by {@code conversionFactor} + */ + @Override + protected double convertToBase(final double value) { + return value * this.getConversionFactor(); + } + + /** + * Converts an {@code UncertainDouble} to the base unit. + * + * @since 2020-09-07 + */ + UncertainDouble convertToBase(final UncertainDouble value) { + return value.timesExact(this.getConversionFactor()); + } + + /** + * Divides this unit by a scalar. + * + * @param divisor scalar to divide by + * @return quotient + * @since 2018-12-23 + * @since v0.1.0 + */ + public LinearUnit dividedBy(final double divisor) { + return valueOf(this.getBase(), this.getConversionFactor() / divisor); + } + + /** + * Returns the quotient of this unit and another. + * + * @param divisor unit to divide by + * @return quotient of two units + * @throws NullPointerException if {@code divisor} is null + * @since 2018-12-22 + * @since v0.1.0 + */ + public LinearUnit dividedBy(final LinearUnit divisor) { + Objects.requireNonNull(divisor, "other must not be null"); + + // divide the units + final ObjectProduct base = this.getBase() + .dividedBy(divisor.getBase()); + return valueOf(base, + this.getConversionFactor() / divisor.getConversionFactor()); + } + + /** + * {@inheritDoc} + * + * Uses the base and conversion factor of units to test for equality. + */ + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof LinearUnit)) + return false; + final LinearUnit other = (LinearUnit) obj; + return Objects.equals(this.getBase(), other.getBase()) + && DecimalComparison.equals(this.getConversionFactor(), + other.getConversionFactor()); + } + + /** + * @return conversion factor + * @since 2019-10-16 + */ + public double getConversionFactor() { + return this.conversionFactor; + } + + /** + * {@inheritDoc} + * + * Uses the base and conversion factor to compute a hash code. + */ + @Override + public int hashCode() { + return 31 * this.getBase().hashCode() + + DecimalComparison.hash(this.getConversionFactor()); + } + + /** + * @return whether this unit is equivalent to a {@code BaseUnit} (i.e. there + * is a {@code BaseUnit b} where + * {@code b.asLinearUnit().equals(this)} returns {@code true}.) + * @since 2019-10-16 + */ + public boolean isBase() { + return this.isCoherent() && this.getBase().isSingleObject(); + } + + /** + * @return whether this unit is coherent (i.e. has conversion factor 1) + * @since 2019-10-16 + */ + public boolean isCoherent() { + return this.getConversionFactor() == 1; + } + + /** + * Returns the difference of this unit and another. + *

    + * Two units can be subtracted if they have the same base. Note that + * {@link #canConvertTo} can be used to determine this. If {@code subtrahend} + * does not meet this condition, an {@code IllegalArgumentException} will be + * thrown. + *

    + * + * @param subtrahend unit to subtract + * @return difference of units + * @throws IllegalArgumentException if {@code subtrahend} is not compatible + * for subtraction as described above + * @throws NullPointerException if {@code subtrahend} is null + * @since 2019-03-17 + * @since v0.2.0 + */ + public LinearUnit minus(final LinearUnit subtrahend) { + Objects.requireNonNull(subtrahend, "addend must not be null."); + + // reject subtrahends that cannot be added to this unit + if (!this.getBase().equals(subtrahend.getBase())) + throw new IllegalArgumentException(String.format( + "Incompatible units for subtraction \"%s\" and \"%s\".", this, + subtrahend)); + + // subtract the units + return valueOf(this.getBase(), + this.getConversionFactor() - subtrahend.getConversionFactor()); + } + + /** + * Returns the sum of this unit and another. + *

    + * Two units can be added if they have the same base. Note that + * {@link #canConvertTo} can be used to determine this. If {@code addend} + * does not meet this condition, an {@code IllegalArgumentException} will be + * thrown. + *

    + * + * @param addend unit to add + * @return sum of units + * @throws IllegalArgumentException if {@code addend} is not compatible for + * addition as described above + * @throws NullPointerException if {@code addend} is null + * @since 2019-03-17 + * @since v0.2.0 + */ + public LinearUnit plus(final LinearUnit addend) { + Objects.requireNonNull(addend, "addend must not be null."); + + // reject addends that cannot be added to this unit + if (!this.getBase().equals(addend.getBase())) + throw new IllegalArgumentException(String.format( + "Incompatible units for addition \"%s\" and \"%s\".", this, + addend)); + + // add the units + return valueOf(this.getBase(), + this.getConversionFactor() + addend.getConversionFactor()); + } + + /** + * Multiplies this unit by a scalar. + * + * @param multiplier scalar to multiply by + * @return product + * @since 2018-12-23 + * @since v0.1.0 + */ + public LinearUnit times(final double multiplier) { + return valueOf(this.getBase(), this.getConversionFactor() * multiplier); + } + + /** + * Returns the product of this unit and another. + * + * @param multiplier unit to multiply by + * @return product of two units + * @throws NullPointerException if {@code multiplier} is null + * @since 2018-12-22 + * @since v0.1.0 + */ + public LinearUnit times(final LinearUnit multiplier) { + Objects.requireNonNull(multiplier, "other must not be null"); + + // multiply the units + final ObjectProduct base = this.getBase() + .times(multiplier.getBase()); + return valueOf(base, + this.getConversionFactor() * multiplier.getConversionFactor()); + } + + /** + * Returns this unit but to an exponent. + * + * @param exponent exponent to exponentiate unit to + * @return exponentiated unit + * @since 2019-01-15 + * @since v0.1.0 + */ + public LinearUnit toExponent(final int exponent) { + return valueOf(this.getBase().toExponent(exponent), + Math.pow(this.conversionFactor, exponent)); + } + + /** + * @return a string providing a definition of this unit + * @since 2019-10-21 + */ + @Override + public String toString() { + return this.getPrimaryName().orElse("Unnamed unit") + + (this.getSymbol().isPresent() + ? String.format(" (%s)", this.getSymbol().get()) + : "") + + ", " + Double.toString(this.conversionFactor) + " * " + + this.getBase().toString(u -> u.getSymbol().get()); + } + + @Override + public LinearUnit withName(final NameSymbol ns) { + return valueOf(this.getBase(), this.getConversionFactor(), ns); + } + + /** + * Returns the result of applying {@code prefix} to this unit. + *

    + * If this unit and the provided prefix have a primary name, the returned + * unit will have a primary name (prefix's name + unit's name).
    + * If this unit and the provided prefix have a symbol, the returned unit will + * have a symbol.
    + * This method ignores alternate names of both this unit and the provided + * prefix. + * + * @param prefix prefix to apply + * @return unit with prefix + * @since 2019-03-18 + * @since v0.2.0 + * @throws NullPointerException if prefix is null + */ + public LinearUnit withPrefix(final UnitPrefix prefix) { + final LinearUnit unit = this.times(prefix.getMultiplier()); + + // create new name and symbol, if possible + final String name; + if (this.getPrimaryName().isPresent() + && prefix.getPrimaryName().isPresent()) { + name = prefix.getPrimaryName().get() + this.getPrimaryName().get(); + } else { + name = null; + } + + final String symbol; + if (this.getSymbol().isPresent() && prefix.getSymbol().isPresent()) { + symbol = prefix.getSymbol().get() + this.getSymbol().get(); + } else { + symbol = null; + } + + return unit.withName(NameSymbol.ofNullable(name, symbol)); + } +} diff --git a/src/main/java/org/unitConverter/unit/LinearUnitValue.java b/src/main/java/org/unitConverter/unit/LinearUnitValue.java new file mode 100644 index 0000000..8de734e --- /dev/null +++ b/src/main/java/org/unitConverter/unit/LinearUnitValue.java @@ -0,0 +1,341 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.Objects; +import java.util.Optional; + +import org.unitConverter.math.DecimalComparison; +import org.unitConverter.math.UncertainDouble; + +/** + * A possibly uncertain value expressed in a linear unit. + * + * Unless otherwise indicated, all methods in this class throw a + * {@code NullPointerException} when an argument is null. + * + * @author Adrien Hopkins + * @since 2020-07-26 + */ +public final class LinearUnitValue { + public static final LinearUnitValue ONE = getExact(SI.ONE, 1); + + /** + * Gets an exact {@code LinearUnitValue} + * + * @param unit unit to express with + * @param value value to express + * @return exact {@code LinearUnitValue} instance + * @since 2020-07-26 + */ + public static final LinearUnitValue getExact(final LinearUnit unit, + final double value) { + return new LinearUnitValue( + Objects.requireNonNull(unit, "unit must not be null"), + UncertainDouble.of(value, 0)); + } + + /** + * Gets an uncertain {@code LinearUnitValue} + * + * @param unit unit to express with + * @param value value to express + * @param uncertainty absolute uncertainty of value + * @return uncertain {@code LinearUnitValue} instance + * @since 2020-07-26 + */ + public static final LinearUnitValue of(final LinearUnit unit, + final UncertainDouble value) { + return new LinearUnitValue( + Objects.requireNonNull(unit, "unit must not be null"), + Objects.requireNonNull(value, "value may not be null")); + } + + private final LinearUnit unit; + + private final UncertainDouble value; + + /** + * @param unit unit to express as + * @param value value to express + * @since 2020-07-26 + */ + private LinearUnitValue(final LinearUnit unit, final UncertainDouble value) { + this.unit = unit; + this.value = value; + } + + /** + * @return this value as a {@code UnitValue}. All uncertainty information is + * removed from the returned value. + * @since 2020-08-04 + */ + public final UnitValue asUnitValue() { + return UnitValue.of(this.unit, this.value.value()); + } + + /** + * @param other a {@code LinearUnit} + * @return true iff this value can be represented with {@code other}. + * @since 2020-07-26 + */ + public final boolean canConvertTo(final LinearUnit other) { + return this.unit.canConvertTo(other); + } + + /** + * Returns a LinearUnitValue that represents the same value expressed in a + * different unit + * + * @param other new unit to express value in + * @return value expressed in {@code other} + * @since 2020-07-26 + */ + public final LinearUnitValue convertTo(final LinearUnit other) { + return LinearUnitValue.of(other, this.unit.convertTo(other, this.value)); + } + + /** + * Divides this value by a scalar + * + * @param divisor value to divide by + * @return multiplied value + * @since 2020-07-28 + */ + public LinearUnitValue dividedBy(final double divisor) { + return LinearUnitValue.of(this.unit, this.value.dividedByExact(divisor)); + } + + /** + * Divides this value by another value + * + * @param divisor value to multiply by + * @return quotient + * @since 2020-07-28 + */ + public LinearUnitValue dividedBy(final LinearUnitValue divisor) { + return LinearUnitValue.of(this.unit.dividedBy(divisor.unit), + this.value.dividedBy(divisor.value)); + } + + /** + * Returns true if this and obj represent the same value, regardless of + * whether or not they are expressed in the same unit. So (1000 m).equals(1 + * km) returns true. + * + * @since 2020-07-26 + * @see #equals(Object, boolean) + */ + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof LinearUnitValue)) + return false; + final LinearUnitValue other = (LinearUnitValue) obj; + return Objects.equals(this.unit.getBase(), other.unit.getBase()) + && this.unit.convertToBase(this.value) + .equals(other.unit.convertToBase(other.value)); + } + + /** + * Returns true if this and obj represent the same value, regardless of + * whether or not they are expressed in the same unit. So (1000 m).equals(1 + * km) returns true. + *

    + * If avoidFPErrors is true, this method will attempt to avoid floating-point + * errors, at the cost of not always being transitive. + * + * @since 2020-07-28 + */ + public boolean equals(final Object obj, final boolean avoidFPErrors) { + if (!avoidFPErrors) + return this.equals(obj); + if (!(obj instanceof LinearUnitValue)) + return false; + final LinearUnitValue other = (LinearUnitValue) obj; + return Objects.equals(this.unit.getBase(), other.unit.getBase()) + && DecimalComparison.equals(this.unit.convertToBase(this.value), + other.unit.convertToBase(other.value)); + } + + /** + * @param other another {@code LinearUnitValue} + * @return true iff this and other are within each other's uncertainty range + * + * @since 2020-07-26 + */ + public boolean equivalent(final LinearUnitValue other) { + if (other == null + || !Objects.equals(this.unit.getBase(), other.unit.getBase())) + return false; + final LinearUnit base = LinearUnit.valueOf(this.unit.getBase(), 1); + final LinearUnitValue thisBase = this.convertTo(base); + final LinearUnitValue otherBase = other.convertTo(base); + + return thisBase.value.equivalent(otherBase.value); + } + + /** + * @return the unit + * @since 2020-09-29 + */ + public final LinearUnit getUnit() { + return this.unit; + } + + /** + * @return the value + * @since 2020-09-29 + */ + public final UncertainDouble getValue() { + return this.value; + } + + /** + * @return the exact value + * @since 2020-09-07 + */ + public final double getValueExact() { + return this.value.value(); + } + + @Override + public int hashCode() { + return Objects.hash(this.unit.getBase(), + this.unit.convertToBase(this.getValue())); + } + + /** + * Returns the difference of this value and another, expressed in this + * value's unit + * + * @param subtrahend value to subtract + * @return difference of values + * @throws IllegalArgumentException if {@code subtrahend} has a unit that is + * not compatible for addition + * @since 2020-07-26 + */ + public LinearUnitValue minus(final LinearUnitValue subtrahend) { + Objects.requireNonNull(subtrahend, "subtrahend may not be null"); + + if (!this.canConvertTo(subtrahend.unit)) + throw new IllegalArgumentException(String.format( + "Incompatible units for subtraction \"%s\" and \"%s\".", + this.unit, subtrahend.unit)); + + final LinearUnitValue otherConverted = subtrahend.convertTo(this.unit); + return LinearUnitValue.of(this.unit, + this.value.minus(otherConverted.value)); + } + + /** + * Returns the sum of this value and another, expressed in this value's unit + * + * @param addend value to add + * @return sum of values + * @throws IllegalArgumentException if {@code addend} has a unit that is not + * compatible for addition + * @since 2020-07-26 + */ + public LinearUnitValue plus(final LinearUnitValue addend) { + Objects.requireNonNull(addend, "addend may not be null"); + + if (!this.canConvertTo(addend.unit)) + throw new IllegalArgumentException(String.format( + "Incompatible units for addition \"%s\" and \"%s\".", this.unit, + addend.unit)); + + final LinearUnitValue otherConverted = addend.convertTo(this.unit); + return LinearUnitValue.of(this.unit, + this.value.plus(otherConverted.value)); + } + + /** + * Multiplies this value by a scalar + * + * @param multiplier value to multiply by + * @return multiplied value + * @since 2020-07-28 + */ + public LinearUnitValue times(final double multiplier) { + return LinearUnitValue.of(this.unit, this.value.timesExact(multiplier)); + } + + /** + * Multiplies this value by another value + * + * @param multiplier value to multiply by + * @return product + * @since 2020-07-28 + */ + public LinearUnitValue times(final LinearUnitValue multiplier) { + return LinearUnitValue.of(this.unit.times(multiplier.unit), + this.value.times(multiplier.value)); + } + + /** + * Raises a value to an exponent + * + * @param exponent exponent to raise to + * @return result of exponentiation + * @since 2020-07-28 + */ + public LinearUnitValue toExponent(final int exponent) { + return LinearUnitValue.of(this.unit.toExponent(exponent), + this.value.toExponentExact(exponent)); + } + + @Override + public String toString() { + return this.toString(!this.value.isExact()); + } + + /** + * Returns a string representing the object.
    + * If the attached unit has a name or symbol, the string looks like "12 km". + * Otherwise, it looks like "13 unnamed unit (= 2 m/s)". + *

    + * If showUncertainty is true, strings like "35 ± 8" are shown instead of + * single numbers. + *

    + * Non-exact values are rounded intelligently based on their uncertainty. + * + * @since 2020-07-26 + */ + public String toString(final boolean showUncertainty) { + final Optional primaryName = this.unit.getPrimaryName(); + final Optional symbol = this.unit.getSymbol(); + final String chosenName = symbol.orElse(primaryName.orElse(null)); + + final UncertainDouble baseValue = this.unit.convertToBase(this.value); + + // get rounded strings + // if showUncertainty is true, add brackets around the string + final String valueString = showUncertainty ? "(" + : "" + this.value.toString(showUncertainty) + + (showUncertainty ? ")" : ""); + final String baseValueString = showUncertainty ? "(" + : "" + baseValue.toString(showUncertainty) + + (showUncertainty ? ")" : ""); + + // create string + if (primaryName.isEmpty() && symbol.isEmpty()) + return String.format("%s unnamed unit (= %s %s)", valueString, + baseValueString, this.unit.getBase()); + else + return String.format("%s %s", valueString, chosenName); + } +} diff --git a/src/main/java/org/unitConverter/unit/MultiUnit.java b/src/main/java/org/unitConverter/unit/MultiUnit.java new file mode 100644 index 0000000..a1623f8 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/MultiUnit.java @@ -0,0 +1,160 @@ +/** + * Copyright (C) 2020 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.unitConverter.math.ObjectProduct; + +/** + * A combination of units, like "5 foot + 7 inch". All but the last units should + * have a whole number value associated with them. + * + * @since 2020-10-02 + */ +public final class MultiUnit extends Unitlike> { + /** + * Creates a {@code MultiUnit} from its units. It will not have a name or + * symbol. + * + * @since 2020-10-03 + */ + public static final MultiUnit of(LinearUnit... units) { + return of(Arrays.asList(units)); + } + + /** + * Creates a {@code MultiUnit} from its units. It will not have a name or + * symbol. + * + * @since 2020-10-03 + */ + public static final MultiUnit of(List units) { + if (units.size() < 1) + throw new IllegalArgumentException("Must have at least one unit"); + final ObjectProduct unitBase = units.get(0).getBase(); + for (final LinearUnit unit : units) { + if (!unitBase.equals(unit.getBase())) + throw new IllegalArgumentException( + "All units must have the same base."); + } + return new MultiUnit(new ArrayList<>(units), unitBase, NameSymbol.EMPTY); + } + + /** + * The units that make up this value. + */ + private final List units; + + /** + * Creates a {@code MultiUnit}. + * + * @since 2020-10-03 + */ + private MultiUnit(List units, ObjectProduct unitBase, + NameSymbol ns) { + super(unitBase, ns); + this.units = units; + } + + @Override + protected List convertFromBase(double value) { + final List values = new ArrayList<>(this.units.size()); + double temp = value; + + for (final LinearUnit unit : this.units.subList(0, + this.units.size() - 1)) { + values.add(Math.floor(temp / unit.getConversionFactor())); + temp %= unit.getConversionFactor(); + } + + values.add(this.units.size() - 1, + this.units.get(this.units.size() - 1).convertFromBase(temp)); + + return values; + } + + /** + * Converts a value expressed in this unitlike form to a value expressed in + * {@code other}. + * + * @implSpec If conversion is possible, this implementation returns + * {@code other.convertFromBase(this.convertToBase(value))}. + * Therefore, overriding either of those methods will change the + * output of this method. + * + * @param other unit to convert to + * @param value value to convert + * @return converted value + * @since 2020-10-03 + * @throws IllegalArgumentException if {@code other} is incompatible for + * conversion with this unitlike form (as + * tested by {@link Unit#canConvertTo}). + * @throws NullPointerException if other is null + */ + public final , V> V convertTo(U other, + double... values) { + final List valueList = new ArrayList<>(values.length); + for (final double d : values) { + valueList.add(d); + } + + return this.convertTo(other, valueList); + } + + /** + * Converts a value expressed in this unitlike form to a value expressed in + * {@code other}. + * + * @implSpec If conversion is possible, this implementation returns + * {@code other.convertFromBase(this.convertToBase(value))}. + * Therefore, overriding either of those methods will change the + * output of this method. + * + * @param other unit to convert to + * @param value value to convert + * @return converted value + * @since 2020-10-03 + * @throws IllegalArgumentException if {@code other} is incompatible for + * conversion with this unitlike form (as + * tested by {@link Unit#canConvertTo}). + * @throws NullPointerException if other is null + */ + public final double convertTo(Unit other, double... values) { + final List valueList = new ArrayList<>(values.length); + for (final double d : values) { + valueList.add(d); + } + + return this.convertTo(other, valueList); + } + + @Override + protected double convertToBase(List value) { + if (value.size() != this.units.size()) + throw new IllegalArgumentException("Wrong number of values for " + + this.units.size() + "-unit MultiUnit."); + + double baseValue = 0; + for (int i = 0; i < this.units.size(); i++) { + baseValue += value.get(i) * this.units.get(i).getConversionFactor(); + } + return baseValue; + } +} diff --git a/src/main/java/org/unitConverter/unit/NameSymbol.java b/src/main/java/org/unitConverter/unit/NameSymbol.java new file mode 100644 index 0000000..8d8302a --- /dev/null +++ b/src/main/java/org/unitConverter/unit/NameSymbol.java @@ -0,0 +1,280 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +/** + * A class that can be used to specify names and a symbol for a unit. + * + * @author Adrien Hopkins + * @since 2019-10-21 + */ +public final class NameSymbol { + public static final NameSymbol EMPTY = new NameSymbol(Optional.empty(), + Optional.empty(), new HashSet<>()); + + /** + * Creates a {@code NameSymbol}, ensuring that if primaryName is null and + * otherNames is not empty, one name is moved from otherNames to primaryName + * + * Ensure that otherNames is a copy of the inputted argument. + */ + private static final NameSymbol create(final String name, + final String symbol, final Set otherNames) { + final Optional primaryName; + + if (name == null && !otherNames.isEmpty()) { + // get primary name and remove it from savedNames + final Iterator it = otherNames.iterator(); + assert it.hasNext(); + primaryName = Optional.of(it.next()); + otherNames.remove(primaryName.get()); + } else { + primaryName = Optional.ofNullable(name); + } + + return new NameSymbol(primaryName, Optional.ofNullable(symbol), + otherNames); + } + + /** + * Gets a {@code NameSymbol} with a primary name, a symbol and no other + * names. + * + * @param name name to use + * @param symbol symbol to use + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException if name or symbol is null + */ + public static final NameSymbol of(final String name, final String symbol) { + return new NameSymbol(Optional.of(name), Optional.of(symbol), + new HashSet<>()); + } + + /** + * Gets a {@code NameSymbol} with a primary name, a symbol and additional + * names. + * + * @param name name to use + * @param symbol symbol to use + * @param otherNames other names to use + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException if any argument is null + */ + public static final NameSymbol of(final String name, final String symbol, + final Set otherNames) { + return new NameSymbol(Optional.of(name), Optional.of(symbol), + new HashSet<>(Objects.requireNonNull(otherNames, + "otherNames must not be null."))); + } + + /** + * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional + * names. + * + * @param name name to use + * @param symbol symbol to use + * @param otherNames other names to use + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException if any argument is null + */ + public static final NameSymbol of(final String name, final String symbol, + final String... otherNames) { + return new NameSymbol(Optional.of(name), Optional.of(symbol), + new HashSet<>(Arrays.asList(Objects.requireNonNull(otherNames, + "otherNames must not be null.")))); + } + + /** + * Gets a {@code NameSymbol} with a primary name, no symbol, and no other + * names. + * + * @param name name to use + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException if name is null + */ + public static final NameSymbol ofName(final String name) { + return new NameSymbol(Optional.of(name), Optional.empty(), + new HashSet<>()); + } + + /** + * Gets a {@code NameSymbol} with a primary name, a symbol and additional + * names. + *

    + * If any argument is null, this static factory replaces it with an empty + * Optional or empty Set. + *

    + * If {@code name} is null and {@code otherNames} is not empty, a primary + * name will be picked from {@code otherNames}. This name will not appear in + * getOtherNames(). + * + * @param name name to use + * @param symbol symbol to use + * @param otherNames other names to use + * @return NameSymbol instance + * @since 2019-11-26 + */ + public static final NameSymbol ofNullable(final String name, + final String symbol, final Set otherNames) { + return NameSymbol.create(name, symbol, + otherNames == null ? new HashSet<>() : new HashSet<>(otherNames)); + } + + /** + * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional + * names. + *

    + * If any argument is null, this static factory replaces it with an empty + * Optional or empty Set. + *

    + * If {@code name} is null and {@code otherNames} is not empty, a primary + * name will be picked from {@code otherNames}. This name will not appear in + * getOtherNames(). + * + * @param name name to use + * @param symbol symbol to use + * @param otherNames other names to use + * @return NameSymbol instance + * @since 2019-11-26 + */ + public static final NameSymbol ofNullable(final String name, + final String symbol, final String... otherNames) { + return create(name, symbol, otherNames == null ? new HashSet<>() + : new HashSet<>(Arrays.asList(otherNames))); + } + + /** + * Gets a {@code NameSymbol} with a symbol and no names. + * + * @param symbol symbol to use + * @return NameSymbol instance + * @since 2019-10-21 + * @throws NullPointerException if symbol is null + */ + public static final NameSymbol ofSymbol(final String symbol) { + return new NameSymbol(Optional.empty(), Optional.of(symbol), + new HashSet<>()); + } + + private final Optional primaryName; + private final Optional symbol; + + private final Set otherNames; + + /** + * Creates the {@code NameSymbol}. + * + * @param primaryName primary name of unit + * @param symbol symbol used to represent unit + * @param otherNames other names and/or spellings, should be a mutable copy + * of the argument + * @since 2019-10-21 + */ + private NameSymbol(final Optional primaryName, + final Optional symbol, final Set otherNames) { + this.primaryName = primaryName; + this.symbol = symbol; + otherNames.remove(null); + this.otherNames = Collections.unmodifiableSet(otherNames); + + if (this.primaryName.isEmpty()) { + assert this.otherNames.isEmpty(); + } + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!(obj instanceof NameSymbol)) + return false; + final NameSymbol other = (NameSymbol) obj; + if (this.otherNames == null) { + if (other.otherNames != null) + return false; + } else if (!this.otherNames.equals(other.otherNames)) + return false; + if (this.primaryName == null) { + if (other.primaryName != null) + return false; + } else if (!this.primaryName.equals(other.primaryName)) + return false; + if (this.symbol == null) { + if (other.symbol != null) + return false; + } else if (!this.symbol.equals(other.symbol)) + return false; + return true; + } + + /** + * @return otherNames + * @since 2019-10-21 + */ + public final Set getOtherNames() { + return this.otherNames; + } + + /** + * @return primaryName + * @since 2019-10-21 + */ + public final Optional getPrimaryName() { + return this.primaryName; + } + + /** + * @return symbol + * @since 2019-10-21 + */ + public final Optional getSymbol() { + return this.symbol; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + (this.otherNames == null ? 0 : this.otherNames.hashCode()); + result = prime * result + + (this.primaryName == null ? 0 : this.primaryName.hashCode()); + result = prime * result + + (this.symbol == null ? 0 : this.symbol.hashCode()); + return result; + } + + /** + * @return true iff this {@code NameSymbol} contains no names or symbols. + */ + public final boolean isEmpty() { + // if primaryName is empty, otherNames must also be empty + return this.primaryName.isEmpty() && this.symbol.isEmpty(); + } +} \ No newline at end of file diff --git a/src/main/java/org/unitConverter/unit/Nameable.java b/src/main/java/org/unitConverter/unit/Nameable.java new file mode 100644 index 0000000..36740ab --- /dev/null +++ b/src/main/java/org/unitConverter/unit/Nameable.java @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2020 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.Optional; +import java.util.Set; + +/** + * An object that can hold one or more names, and possibly a symbol. The name + * and symbol data should be immutable. + * + * @since 2020-09-07 + */ +public interface Nameable { + /** + * @return a {@code NameSymbol} that contains this object's primary name, + * symbol and other names + * @since 2020-09-07 + */ + NameSymbol getNameSymbol(); + + /** + * @return set of alternate names + * @since 2020-09-07 + */ + default Set getOtherNames() { + return this.getNameSymbol().getOtherNames(); + } + + /** + * @return preferred name of object + * @since 2020-09-07 + */ + default Optional getPrimaryName() { + return this.getNameSymbol().getPrimaryName(); + } + + /** + * @return short symbol representing object + * @since 2020-09-07 + */ + default Optional getSymbol() { + return this.getNameSymbol().getSymbol(); + } +} diff --git a/src/main/java/org/unitConverter/unit/SI.java b/src/main/java/org/unitConverter/unit/SI.java new file mode 100644 index 0000000..81736f3 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/SI.java @@ -0,0 +1,479 @@ +/** + * Copyright (C) 2018 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.Set; + +import org.unitConverter.math.ObjectProduct; + +/** + * All of the units, prefixes and dimensions that are used by the SI, as well as + * some outside the SI. + * + *

    + * This class does not include prefixed units. To obtain prefixed units, use + * {@link LinearUnit#withPrefix}: + * + *

    + * LinearUnit KILOMETRE = SI.METRE.withPrefix(SI.KILO);
    + * 
    + * + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +public final class SI { + /// dimensions used by SI units + // base dimensions, as BaseDimensions + public static final class BaseDimensions { + public static final BaseDimension LENGTH = BaseDimension.valueOf("Length", + "L"); + public static final BaseDimension MASS = BaseDimension.valueOf("Mass", + "M"); + public static final BaseDimension TIME = BaseDimension.valueOf("Time", + "T"); + public static final BaseDimension ELECTRIC_CURRENT = BaseDimension + .valueOf("Electric Current", "I"); + public static final BaseDimension TEMPERATURE = BaseDimension + .valueOf("Temperature", "\u0398"); // theta symbol + public static final BaseDimension QUANTITY = BaseDimension + .valueOf("Quantity", "N"); + public static final BaseDimension LUMINOUS_INTENSITY = BaseDimension + .valueOf("Luminous Intensity", "J"); + public static final BaseDimension INFORMATION = BaseDimension + .valueOf("Information", "Info"); // non-SI + public static final BaseDimension CURRENCY = BaseDimension + .valueOf("Currency", "$$"); // non-SI + + // You may NOT get SI.BaseDimensions instances! + private BaseDimensions() { + throw new AssertionError(); + } + } + + /// base units of the SI + // suppressing warnings since these are the same object, but in a different + /// form (class) + @SuppressWarnings("hiding") + public static final class BaseUnits { + public static final BaseUnit METRE = BaseUnit + .valueOf(BaseDimensions.LENGTH, "metre", "m"); + public static final BaseUnit KILOGRAM = BaseUnit + .valueOf(BaseDimensions.MASS, "kilogram", "kg"); + public static final BaseUnit SECOND = BaseUnit + .valueOf(BaseDimensions.TIME, "second", "s"); + public static final BaseUnit AMPERE = BaseUnit + .valueOf(BaseDimensions.ELECTRIC_CURRENT, "ampere", "A"); + public static final BaseUnit KELVIN = BaseUnit + .valueOf(BaseDimensions.TEMPERATURE, "kelvin", "K"); + public static final BaseUnit MOLE = BaseUnit + .valueOf(BaseDimensions.QUANTITY, "mole", "mol"); + public static final BaseUnit CANDELA = BaseUnit + .valueOf(BaseDimensions.LUMINOUS_INTENSITY, "candela", "cd"); + public static final BaseUnit BIT = BaseUnit + .valueOf(BaseDimensions.INFORMATION, "bit", "b"); + public static final BaseUnit DOLLAR = BaseUnit + .valueOf(BaseDimensions.CURRENCY, "dollar", "$"); + + public static final Set BASE_UNITS = Set.of(METRE, KILOGRAM, + SECOND, AMPERE, KELVIN, MOLE, CANDELA, BIT); + + // You may NOT get SI.BaseUnits instances! + private BaseUnits() { + throw new AssertionError(); + } + } + + /** + * Constants that relate to the SI or other systems. + * + * @author Adrien Hopkins + * @since 2019-11-08 + */ + public static final class Constants { + public static final LinearUnit EARTH_GRAVITY = METRE.dividedBy(SECOND) + .dividedBy(SECOND).times(9.80665); + } + + // dimensions used in the SI, as ObjectProducts + public static final class Dimensions { + public static final ObjectProduct EMPTY = ObjectProduct + .empty(); + public static final ObjectProduct LENGTH = ObjectProduct + .oneOf(BaseDimensions.LENGTH); + public static final ObjectProduct MASS = ObjectProduct + .oneOf(BaseDimensions.MASS); + public static final ObjectProduct TIME = ObjectProduct + .oneOf(BaseDimensions.TIME); + public static final ObjectProduct ELECTRIC_CURRENT = ObjectProduct + .oneOf(BaseDimensions.ELECTRIC_CURRENT); + public static final ObjectProduct TEMPERATURE = ObjectProduct + .oneOf(BaseDimensions.TEMPERATURE); + public static final ObjectProduct QUANTITY = ObjectProduct + .oneOf(BaseDimensions.QUANTITY); + public static final ObjectProduct LUMINOUS_INTENSITY = ObjectProduct + .oneOf(BaseDimensions.LUMINOUS_INTENSITY); + public static final ObjectProduct INFORMATION = ObjectProduct + .oneOf(BaseDimensions.INFORMATION); + public static final ObjectProduct CURRENCY = ObjectProduct + .oneOf(BaseDimensions.CURRENCY); + + // derived dimensions without named SI units + public static final ObjectProduct AREA = LENGTH + .times(LENGTH); + public static final ObjectProduct VOLUME = AREA + .times(LENGTH); + public static final ObjectProduct VELOCITY = LENGTH + .dividedBy(TIME); + public static final ObjectProduct ACCELERATION = VELOCITY + .dividedBy(TIME); + public static final ObjectProduct WAVENUMBER = EMPTY + .dividedBy(LENGTH); + public static final ObjectProduct MASS_DENSITY = MASS + .dividedBy(VOLUME); + public static final ObjectProduct SURFACE_DENSITY = MASS + .dividedBy(AREA); + public static final ObjectProduct SPECIFIC_VOLUME = VOLUME + .dividedBy(MASS); + public static final ObjectProduct CURRENT_DENSITY = ELECTRIC_CURRENT + .dividedBy(AREA); + public static final ObjectProduct MAGNETIC_FIELD_STRENGTH = ELECTRIC_CURRENT + .dividedBy(LENGTH); + public static final ObjectProduct CONCENTRATION = QUANTITY + .dividedBy(VOLUME); + public static final ObjectProduct MASS_CONCENTRATION = CONCENTRATION + .times(MASS); + public static final ObjectProduct LUMINANCE = LUMINOUS_INTENSITY + .dividedBy(AREA); + public static final ObjectProduct REFRACTIVE_INDEX = VELOCITY + .dividedBy(VELOCITY); + public static final ObjectProduct REFRACTIVE_PERMEABILITY = EMPTY + .times(EMPTY); + public static final ObjectProduct ANGLE = LENGTH + .dividedBy(LENGTH); + public static final ObjectProduct SOLID_ANGLE = AREA + .dividedBy(AREA); + + // derived dimensions with named SI units + public static final ObjectProduct FREQUENCY = EMPTY + .dividedBy(TIME); + public static final ObjectProduct FORCE = MASS + .times(ACCELERATION); + public static final ObjectProduct ENERGY = FORCE + .times(LENGTH); + public static final ObjectProduct POWER = ENERGY + .dividedBy(TIME); + public static final ObjectProduct ELECTRIC_CHARGE = ELECTRIC_CURRENT + .times(TIME); + public static final ObjectProduct VOLTAGE = ENERGY + .dividedBy(ELECTRIC_CHARGE); + public static final ObjectProduct CAPACITANCE = ELECTRIC_CHARGE + .dividedBy(VOLTAGE); + public static final ObjectProduct ELECTRIC_RESISTANCE = VOLTAGE + .dividedBy(ELECTRIC_CURRENT); + public static final ObjectProduct ELECTRIC_CONDUCTANCE = ELECTRIC_CURRENT + .dividedBy(VOLTAGE); + public static final ObjectProduct MAGNETIC_FLUX = VOLTAGE + .times(TIME); + public static final ObjectProduct MAGNETIC_FLUX_DENSITY = MAGNETIC_FLUX + .dividedBy(AREA); + public static final ObjectProduct INDUCTANCE = MAGNETIC_FLUX + .dividedBy(ELECTRIC_CURRENT); + public static final ObjectProduct LUMINOUS_FLUX = LUMINOUS_INTENSITY + .times(SOLID_ANGLE); + public static final ObjectProduct ILLUMINANCE = LUMINOUS_FLUX + .dividedBy(AREA); + public static final ObjectProduct SPECIFIC_ENERGY = ENERGY + .dividedBy(MASS); + public static final ObjectProduct CATALYTIC_ACTIVITY = QUANTITY + .dividedBy(TIME); + + // You may NOT get SI.Dimension instances! + private Dimensions() { + throw new AssertionError(); + } + } + + /// The units of the SI + public static final LinearUnit ONE = LinearUnit + .valueOf(ObjectProduct.empty(), 1); + + public static final LinearUnit METRE = BaseUnits.METRE.asLinearUnit() + .withName(NameSymbol.of("metre", "m", "meter")); + public static final LinearUnit KILOGRAM = BaseUnits.KILOGRAM.asLinearUnit() + .withName(NameSymbol.of("kilogram", "kg")); + public static final LinearUnit SECOND = BaseUnits.SECOND.asLinearUnit() + .withName(NameSymbol.of("second", "s", "sec")); + public static final LinearUnit AMPERE = BaseUnits.AMPERE.asLinearUnit() + .withName(NameSymbol.of("ampere", "A")); + public static final LinearUnit KELVIN = BaseUnits.KELVIN.asLinearUnit() + .withName(NameSymbol.of("kelvin", "K")); + public static final LinearUnit MOLE = BaseUnits.MOLE.asLinearUnit() + .withName(NameSymbol.of("mole", "mol")); + public static final LinearUnit CANDELA = BaseUnits.CANDELA.asLinearUnit() + .withName(NameSymbol.of("candela", "cd")); + public static final LinearUnit BIT = BaseUnits.BIT.asLinearUnit() + .withName(NameSymbol.of("bit", "b")); + public static final LinearUnit DOLLAR = BaseUnits.DOLLAR.asLinearUnit() + .withName(NameSymbol.of("dollar", "$")); + // Non-base units + public static final LinearUnit RADIAN = METRE.dividedBy(METRE) + .withName(NameSymbol.of("radian", "rad")); + + public static final LinearUnit STERADIAN = RADIAN.times(RADIAN) + .withName(NameSymbol.of("steradian", "sr")); + public static final LinearUnit HERTZ = ONE.dividedBy(SECOND) + .withName(NameSymbol.of("hertz", "Hz")); + // for periodic phenomena + public static final LinearUnit NEWTON = KILOGRAM.times(METRE) + .dividedBy(SECOND.times(SECOND)) + .withName(NameSymbol.of("newton", "N")); + public static final LinearUnit PASCAL = NEWTON.dividedBy(METRE.times(METRE)) + .withName(NameSymbol.of("pascal", "Pa")); + public static final LinearUnit JOULE = NEWTON.times(METRE) + .withName(NameSymbol.of("joule", "J")); + public static final LinearUnit WATT = JOULE.dividedBy(SECOND) + .withName(NameSymbol.of("watt", "W")); + public static final LinearUnit COULOMB = AMPERE.times(SECOND) + .withName(NameSymbol.of("coulomb", "C")); + public static final LinearUnit VOLT = JOULE.dividedBy(COULOMB) + .withName(NameSymbol.of("volt", "V")); + public static final LinearUnit FARAD = COULOMB.dividedBy(VOLT) + .withName(NameSymbol.of("farad", "F")); + public static final LinearUnit OHM = VOLT.dividedBy(AMPERE) + .withName(NameSymbol.of("ohm", "\u03A9")); // omega + public static final LinearUnit SIEMENS = ONE.dividedBy(OHM) + .withName(NameSymbol.of("siemens", "S")); + public static final LinearUnit WEBER = VOLT.times(SECOND) + .withName(NameSymbol.of("weber", "Wb")); + public static final LinearUnit TESLA = WEBER.dividedBy(METRE.times(METRE)) + .withName(NameSymbol.of("tesla", "T")); + public static final LinearUnit HENRY = WEBER.dividedBy(AMPERE) + .withName(NameSymbol.of("henry", "H")); + public static final LinearUnit LUMEN = CANDELA.times(STERADIAN) + .withName(NameSymbol.of("lumen", "lm")); + public static final LinearUnit LUX = LUMEN.dividedBy(METRE.times(METRE)) + .withName(NameSymbol.of("lux", "lx")); + public static final LinearUnit BEQUEREL = ONE.dividedBy(SECOND) + .withName(NameSymbol.of("bequerel", "Bq")); + // for activity referred to a nucleotide + public static final LinearUnit GRAY = JOULE.dividedBy(KILOGRAM) + .withName(NameSymbol.of("grey", "Gy")); + // for absorbed dose + public static final LinearUnit SIEVERT = JOULE.dividedBy(KILOGRAM) + .withName(NameSymbol.of("sievert", "Sv")); + // for dose equivalent + public static final LinearUnit KATAL = MOLE.dividedBy(SECOND) + .withName(NameSymbol.of("katal", "kat")); + // common derived units included for convenience + public static final LinearUnit GRAM = KILOGRAM.dividedBy(1000) + .withName(NameSymbol.of("gram", "g")); + + public static final LinearUnit SQUARE_METRE = METRE.toExponent(2) + .withName(NameSymbol.of("square metre", "m^2", "square meter", + "metre squared", "meter squared")); + public static final LinearUnit CUBIC_METRE = METRE.toExponent(3) + .withName(NameSymbol.of("cubic metre", "m^3", "cubic meter", + "metre cubed", "meter cubed")); + public static final LinearUnit METRE_PER_SECOND = METRE.dividedBy(SECOND) + .withName( + NameSymbol.of("metre per second", "m/s", "meter per second")); + // Non-SI units included for convenience + public static final Unit CELSIUS = Unit + .fromConversionFunctions(KELVIN.getBase(), tempK -> tempK - 273.15, + tempC -> tempC + 273.15) + .withName(NameSymbol.of("degree Celsius", "\u00B0C")); + + public static final LinearUnit MINUTE = SECOND.times(60) + .withName(NameSymbol.of("minute", "min")); + public static final LinearUnit HOUR = MINUTE.times(60) + .withName(NameSymbol.of("hour", "h", "hr")); + public static final LinearUnit DAY = HOUR.times(60) + .withName(NameSymbol.of("day", "d")); + public static final LinearUnit KILOMETRE_PER_HOUR = METRE.times(1000) + .dividedBy(HOUR).withName(NameSymbol.of("kilometre per hour", "km/h", + "kilometer per hour")); + public static final LinearUnit DEGREE = RADIAN.times(360 / (2 * Math.PI)) + .withName(NameSymbol.of("degree", "\u00B0", "deg")); + public static final LinearUnit ARCMINUTE = DEGREE.dividedBy(60) + .withName(NameSymbol.of("arcminute", "arcmin")); + public static final LinearUnit ARCSECOND = ARCMINUTE.dividedBy(60) + .withName(NameSymbol.of("arcsecond", "arcsec")); + public static final LinearUnit ASTRONOMICAL_UNIT = METRE + .times(149597870700.0) + .withName(NameSymbol.of("astronomical unit", "au")); + public static final LinearUnit PARSEC = ASTRONOMICAL_UNIT + .dividedBy(ARCSECOND).withName(NameSymbol.of("parsec", "pc")); + public static final LinearUnit HECTARE = METRE.times(METRE).times(10000.0) + .withName(NameSymbol.of("hectare", "ha")); + public static final LinearUnit LITRE = METRE.times(METRE).times(METRE) + .dividedBy(1000.0).withName(NameSymbol.of("litre", "L", "l", "liter")); + public static final LinearUnit TONNE = KILOGRAM.times(1000.0) + .withName(NameSymbol.of("tonne", "t", "metric ton")); + public static final LinearUnit DALTON = KILOGRAM.times(1.660539040e-27) + .withName(NameSymbol.of("dalton", "Da", "atomic unit", "u")); // approximate + // value + public static final LinearUnit ELECTRONVOLT = JOULE.times(1.602176634e-19) + .withName(NameSymbol.of("electron volt", "eV")); + public static final LinearUnit BYTE = BIT.times(8) + .withName(NameSymbol.of("byte", "B")); + public static final Unit NEPER = Unit.fromConversionFunctions(ONE.getBase(), + pr -> 0.5 * Math.log(pr), Np -> Math.exp(2 * Np)) + .withName(NameSymbol.of("neper", "Np")); + public static final Unit BEL = Unit.fromConversionFunctions(ONE.getBase(), + pr -> Math.log10(pr), dB -> Math.pow(10, dB)) + .withName(NameSymbol.of("bel", "B")); + public static final Unit DECIBEL = Unit + .fromConversionFunctions(ONE.getBase(), pr -> 10 * Math.log10(pr), + dB -> Math.pow(10, dB / 10)) + .withName(NameSymbol.of("decibel", "dB")); + + /// The prefixes of the SI + // expanding decimal prefixes + public static final UnitPrefix KILO = UnitPrefix.valueOf(1e3) + .withName(NameSymbol.of("kilo", "k", "K")); + public static final UnitPrefix MEGA = UnitPrefix.valueOf(1e6) + .withName(NameSymbol.of("mega", "M")); + public static final UnitPrefix GIGA = UnitPrefix.valueOf(1e9) + .withName(NameSymbol.of("giga", "G")); + public static final UnitPrefix TERA = UnitPrefix.valueOf(1e12) + .withName(NameSymbol.of("tera", "T")); + public static final UnitPrefix PETA = UnitPrefix.valueOf(1e15) + .withName(NameSymbol.of("peta", "P")); + public static final UnitPrefix EXA = UnitPrefix.valueOf(1e18) + .withName(NameSymbol.of("exa", "E")); + public static final UnitPrefix ZETTA = UnitPrefix.valueOf(1e21) + .withName(NameSymbol.of("zetta", "Z")); + public static final UnitPrefix YOTTA = UnitPrefix.valueOf(1e24) + .withName(NameSymbol.of("yotta", "Y")); + + // contracting decimal prefixes + public static final UnitPrefix MILLI = UnitPrefix.valueOf(1e-3) + .withName(NameSymbol.of("milli", "m")); + public static final UnitPrefix MICRO = UnitPrefix.valueOf(1e-6) + .withName(NameSymbol.of("micro", "\u03BC", "u")); // mu + public static final UnitPrefix NANO = UnitPrefix.valueOf(1e-9) + .withName(NameSymbol.of("nano", "n")); + public static final UnitPrefix PICO = UnitPrefix.valueOf(1e-12) + .withName(NameSymbol.of("pico", "p")); + public static final UnitPrefix FEMTO = UnitPrefix.valueOf(1e-15) + .withName(NameSymbol.of("femto", "f")); + public static final UnitPrefix ATTO = UnitPrefix.valueOf(1e-18) + .withName(NameSymbol.of("atto", "a")); + public static final UnitPrefix ZEPTO = UnitPrefix.valueOf(1e-21) + .withName(NameSymbol.of("zepto", "z")); + public static final UnitPrefix YOCTO = UnitPrefix.valueOf(1e-24) + .withName(NameSymbol.of("yocto", "y")); + + // prefixes that don't match the pattern of thousands + public static final UnitPrefix DEKA = UnitPrefix.valueOf(1e1) + .withName(NameSymbol.of("deka", "da", "deca", "D")); + public static final UnitPrefix HECTO = UnitPrefix.valueOf(1e2) + .withName(NameSymbol.of("hecto", "h", "H", "hekto")); + public static final UnitPrefix DECI = UnitPrefix.valueOf(1e-1) + .withName(NameSymbol.of("deci", "d")); + public static final UnitPrefix CENTI = UnitPrefix.valueOf(1e-2) + .withName(NameSymbol.of("centi", "c")); + public static final UnitPrefix KIBI = UnitPrefix.valueOf(1024) + .withName(NameSymbol.of("kibi", "Ki")); + public static final UnitPrefix MEBI = KIBI.times(1024) + .withName(NameSymbol.of("mebi", "Mi")); + public static final UnitPrefix GIBI = MEBI.times(1024) + .withName(NameSymbol.of("gibi", "Gi")); + public static final UnitPrefix TEBI = GIBI.times(1024) + .withName(NameSymbol.of("tebi", "Ti")); + public static final UnitPrefix PEBI = TEBI.times(1024) + .withName(NameSymbol.of("pebi", "Pi")); + public static final UnitPrefix EXBI = PEBI.times(1024) + .withName(NameSymbol.of("exbi", "Ei")); + + // a few prefixed units + public static final LinearUnit MICROMETRE = SI.METRE.withPrefix(SI.MICRO); + public static final LinearUnit MILLIMETRE = SI.METRE.withPrefix(SI.MILLI); + public static final LinearUnit KILOMETRE = SI.METRE.withPrefix(SI.KILO); + public static final LinearUnit MEGAMETRE = SI.METRE.withPrefix(SI.MEGA); + + public static final LinearUnit MICROLITRE = SI.LITRE.withPrefix(SI.MICRO); + public static final LinearUnit MILLILITRE = SI.LITRE.withPrefix(SI.MILLI); + public static final LinearUnit KILOLITRE = SI.LITRE.withPrefix(SI.KILO); + public static final LinearUnit MEGALITRE = SI.LITRE.withPrefix(SI.MEGA); + + public static final LinearUnit MICROSECOND = SI.SECOND.withPrefix(SI.MICRO); + public static final LinearUnit MILLISECOND = SI.SECOND.withPrefix(SI.MILLI); + public static final LinearUnit KILOSECOND = SI.SECOND.withPrefix(SI.KILO); + public static final LinearUnit MEGASECOND = SI.SECOND.withPrefix(SI.MEGA); + + public static final LinearUnit MICROGRAM = SI.GRAM.withPrefix(SI.MICRO); + public static final LinearUnit MILLIGRAM = SI.GRAM.withPrefix(SI.MILLI); + public static final LinearUnit MEGAGRAM = SI.GRAM.withPrefix(SI.MEGA); + + public static final LinearUnit MICRONEWTON = SI.NEWTON.withPrefix(SI.MICRO); + public static final LinearUnit MILLINEWTON = SI.NEWTON.withPrefix(SI.MILLI); + public static final LinearUnit KILONEWTON = SI.NEWTON.withPrefix(SI.KILO); + public static final LinearUnit MEGANEWTON = SI.NEWTON.withPrefix(SI.MEGA); + + public static final LinearUnit MICROJOULE = SI.JOULE.withPrefix(SI.MICRO); + public static final LinearUnit MILLIJOULE = SI.JOULE.withPrefix(SI.MILLI); + public static final LinearUnit KILOJOULE = SI.JOULE.withPrefix(SI.KILO); + public static final LinearUnit MEGAJOULE = SI.JOULE.withPrefix(SI.MEGA); + + public static final LinearUnit MICROWATT = SI.WATT.withPrefix(SI.MICRO); + public static final LinearUnit MILLIWATT = SI.WATT.withPrefix(SI.MILLI); + public static final LinearUnit KILOWATT = SI.WATT.withPrefix(SI.KILO); + public static final LinearUnit MEGAWATT = SI.WATT.withPrefix(SI.MEGA); + + public static final LinearUnit MICROCOULOMB = SI.COULOMB + .withPrefix(SI.MICRO); + public static final LinearUnit MILLICOULOMB = SI.COULOMB + .withPrefix(SI.MILLI); + public static final LinearUnit KILOCOULOMB = SI.COULOMB.withPrefix(SI.KILO); + public static final LinearUnit MEGACOULOMB = SI.COULOMB.withPrefix(SI.MEGA); + + public static final LinearUnit MICROAMPERE = SI.AMPERE.withPrefix(SI.MICRO); + public static final LinearUnit MILLIAMPERE = SI.AMPERE.withPrefix(SI.MILLI); + + public static final LinearUnit MICROVOLT = SI.VOLT.withPrefix(SI.MICRO); + public static final LinearUnit MILLIVOLT = SI.VOLT.withPrefix(SI.MILLI); + public static final LinearUnit KILOVOLT = SI.VOLT.withPrefix(SI.KILO); + public static final LinearUnit MEGAVOLT = SI.VOLT.withPrefix(SI.MEGA); + + public static final LinearUnit KILOOHM = SI.OHM.withPrefix(SI.KILO); + public static final LinearUnit MEGAOHM = SI.OHM.withPrefix(SI.MEGA); + + // sets of prefixes + public static final Set ALL_PREFIXES = Set.of(DEKA, HECTO, KILO, + MEGA, GIGA, TERA, PETA, EXA, ZETTA, YOTTA, DECI, CENTI, MILLI, MICRO, + NANO, PICO, FEMTO, ATTO, ZEPTO, YOCTO, KIBI, MEBI, GIBI, TEBI, PEBI, + EXBI); + + public static final Set DECIMAL_PREFIXES = Set.of(DEKA, HECTO, + KILO, MEGA, GIGA, TERA, PETA, EXA, ZETTA, YOTTA, DECI, CENTI, MILLI, + MICRO, NANO, PICO, FEMTO, ATTO, ZEPTO, YOCTO); + public static final Set THOUSAND_PREFIXES = Set.of(KILO, MEGA, + GIGA, TERA, PETA, EXA, ZETTA, YOTTA, MILLI, MICRO, NANO, PICO, FEMTO, + ATTO, ZEPTO, YOCTO); + public static final Set MAGNIFYING_PREFIXES = Set.of(DEKA, HECTO, + KILO, MEGA, GIGA, TERA, PETA, EXA, ZETTA, YOTTA, KIBI, MEBI, GIBI, + TEBI, PEBI, EXBI); + public static final Set REDUCING_PREFIXES = Set.of(DECI, CENTI, + MILLI, MICRO, NANO, PICO, FEMTO, ATTO, ZEPTO, YOCTO); + + // You may NOT get SI instances! + private SI() { + throw new AssertionError(); + } +} diff --git a/src/main/java/org/unitConverter/unit/USCustomary.java b/src/main/java/org/unitConverter/unit/USCustomary.java new file mode 100644 index 0000000..1c4bcfe --- /dev/null +++ b/src/main/java/org/unitConverter/unit/USCustomary.java @@ -0,0 +1,135 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +/** + * A static utility class that contains units in the US Customary system. + * + * @author Adrien Hopkins + * @since 2019-10-21 + */ +public final class USCustomary { + /** + * US Customary units that measure area + * + * @author Adrien Hopkins + * @since 2019-11-08 + */ + public static final class Area { + public static final LinearUnit SQUARE_SURVEY_FOOT = Length.SURVEY_FOOT.times(Length.SURVEY_FOOT); + public static final LinearUnit SQUARE_CHAIN = Length.SURVEY_CHAIN.times(Length.SURVEY_CHAIN); + public static final LinearUnit ACRE = Length.SURVEY_CHAIN.times(Length.SURVEY_FURLONG); + public static final LinearUnit SECTION = Length.SURVEY_MILE.times(Length.SURVEY_MILE); + public static final LinearUnit SURVEY_TOWNSHIP = SECTION.times(36); + } + + /** + * US Customary units that measure length + * + * @author Adrien Hopkins + * @since 2019-10-28 + */ + public static final class Length { + public static final LinearUnit FOOT = BritishImperial.Length.FOOT; + public static final LinearUnit INCH = BritishImperial.Length.INCH; + public static final LinearUnit HAND = INCH.times(4); + public static final LinearUnit PICA = INCH.dividedBy(6); + public static final LinearUnit POINT = PICA.dividedBy(12); + public static final LinearUnit YARD = BritishImperial.Length.YARD; + public static final LinearUnit MILE = BritishImperial.Length.MILE; + + public static final LinearUnit SURVEY_FOOT = SI.METRE.times(1200.0 / 3937.0); + public static final LinearUnit SURVEY_LINK = SURVEY_FOOT.times(33.0 / 50.0); + public static final LinearUnit SURVEY_ROD = SURVEY_FOOT.times(16.5); + public static final LinearUnit SURVEY_CHAIN = SURVEY_ROD.times(4); + public static final LinearUnit SURVEY_FURLONG = SURVEY_CHAIN.times(10); + public static final LinearUnit SURVEY_MILE = SURVEY_FURLONG.times(8); + public static final LinearUnit SURVEY_LEAGUE = SURVEY_MILE.times(3); + + public static final LinearUnit NAUTICAL_MILE = BritishImperial.Length.NAUTICAL_MILE; + public static final LinearUnit FATHOM = YARD.times(2); + public static final LinearUnit CABLE = FATHOM.times(120); + } + + /** + * mass units + * + * @author Adrien Hopkins + * @since 2019-11-08 + */ + public static final class Mass { + public static final LinearUnit GRAIN = BritishImperial.Mass.GRAIN; + public static final LinearUnit DRAM = BritishImperial.Mass.DRACHM; + public static final LinearUnit OUNCE = BritishImperial.Mass.OUNCE; + public static final LinearUnit POUND = BritishImperial.Mass.POUND; + public static final LinearUnit HUNDREDWEIGHT = POUND.times(100); + public static final LinearUnit SHORT_TON = HUNDREDWEIGHT.times(20); + + // troy system for precious metals + public static final LinearUnit PENNYWEIGHT = GRAIN.times(24); + public static final LinearUnit TROY_OUNCE = PENNYWEIGHT.times(20); + public static final LinearUnit TROY_POUND = TROY_OUNCE.times(12); + } + + /** + * Volume units + * + * @author Adrien Hopkins + * @since 2019-11-08 + */ + public static final class Volume { + public static final LinearUnit CUBIC_INCH = Length.INCH.toExponent(3); + public static final LinearUnit CUBIC_FOOT = Length.FOOT.toExponent(3); + public static final LinearUnit CUBIC_YARD = Length.YARD.toExponent(3); + public static final LinearUnit ACRE_FOOT = Area.ACRE.times(Length.FOOT); + + public static final LinearUnit MINIM = SI.LITRE.withPrefix(SI.MICRO).times(61.611519921875); + public static final LinearUnit FLUID_DRAM = MINIM.times(60); + public static final LinearUnit TEASPOON = MINIM.times(80); + public static final LinearUnit TABLESPOON = TEASPOON.times(3); + public static final LinearUnit FLUID_OUNCE = TABLESPOON.times(2); + public static final LinearUnit SHOT = TABLESPOON.times(3); + public static final LinearUnit GILL = FLUID_OUNCE.times(4); + public static final LinearUnit CUP = GILL.times(2); + public static final LinearUnit PINT = CUP.times(2); + public static final LinearUnit QUART = PINT.times(2); + public static final LinearUnit GALLON = QUART.times(4); + public static final LinearUnit BARREL = GALLON.times(31.5); + public static final LinearUnit OIL_BARREL = GALLON.times(42); + public static final LinearUnit HOGSHEAD = GALLON.times(63); + + public static final LinearUnit DRY_PINT = SI.LITRE.times(0.5506104713575); + public static final LinearUnit DRY_QUART = DRY_PINT.times(2); + public static final LinearUnit DRY_GALLON = DRY_QUART.times(4); + public static final LinearUnit PECK = DRY_GALLON.times(2); + public static final LinearUnit BUSHEL = PECK.times(4); + public static final LinearUnit DRY_BARREL = CUBIC_INCH.times(7056); + } + + public static final LinearUnit OUNCE_FORCE = BritishImperial.OUNCE_FORCE; + public static final LinearUnit POUND_FORCE = BritishImperial.POUND_FORCE; + + public static final LinearUnit BRITISH_THERMAL_UNIT = BritishImperial.BRITISH_THERMAL_UNIT; + public static final LinearUnit CALORIE = BritishImperial.CALORIE; + public static final LinearUnit KILOCALORIE = BritishImperial.KILOCALORIE; + public static final LinearUnit FOOT_POUND = POUND_FORCE.times(Length.FOOT); + + public static final LinearUnit HORSEPOWER = Length.FOOT.times(POUND_FORCE).dividedBy(SI.MINUTE).times(33000); + public static final LinearUnit POUND_PER_SQUARE_INCH = POUND_FORCE.dividedBy(Length.INCH.toExponent(2)); + + public static final Unit FAHRENHEIT = BritishImperial.FAHRENHEIT; +} diff --git a/src/main/java/org/unitConverter/unit/Unit.java b/src/main/java/org/unitConverter/unit/Unit.java new file mode 100644 index 0000000..0a3298f --- /dev/null +++ b/src/main/java/org/unitConverter/unit/Unit.java @@ -0,0 +1,377 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.function.DoubleUnaryOperator; + +import org.unitConverter.math.DecimalComparison; +import org.unitConverter.math.ObjectProduct; + +/** + * A unit that is composed of base units. + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +public abstract class Unit implements Nameable { + /** + * Returns a unit from its base and the functions it uses to convert to and + * from its base. + * + *

    + * For example, to get a unit representing the degree Celsius, the following + * code can be used: + * + * {@code Unit.fromConversionFunctions(SI.KELVIN, tempK -> tempK - 273.15, tempC -> tempC + 273.15);} + *

    + * + * @param base unit's base + * @param converterFrom function that accepts a value expressed in the unit's + * base and returns that value expressed in this unit. + * @param converterTo function that accepts a value expressed in the unit + * and returns that value expressed in the unit's base. + * @return a unit that uses the provided functions to convert. + * @since 2019-05-22 + * @throws NullPointerException if any argument is null + */ + public static final Unit fromConversionFunctions( + final ObjectProduct base, + final DoubleUnaryOperator converterFrom, + final DoubleUnaryOperator converterTo) { + return new FunctionalUnit(base, converterFrom, converterTo); + } + + /** + * Returns a unit from its base and the functions it uses to convert to and + * from its base. + * + *

    + * For example, to get a unit representing the degree Celsius, the following + * code can be used: + * + * {@code Unit.fromConversionFunctions(SI.KELVIN, tempK -> tempK - 273.15, tempC -> tempC + 273.15);} + *

    + * + * @param base unit's base + * @param converterFrom function that accepts a value expressed in the unit's + * base and returns that value expressed in this unit. + * @param converterTo function that accepts a value expressed in the unit + * and returns that value expressed in the unit's base. + * @param ns names and symbol of unit + * @return a unit that uses the provided functions to convert. + * @since 2019-05-22 + * @throws NullPointerException if any argument is null + */ + public static final Unit fromConversionFunctions( + final ObjectProduct base, + final DoubleUnaryOperator converterFrom, + final DoubleUnaryOperator converterTo, final NameSymbol ns) { + return new FunctionalUnit(base, converterFrom, converterTo, ns); + } + + /** + * The combination of units that this unit is based on. + * + * @since 2019-10-16 + */ + private final ObjectProduct unitBase; + + /** + * This unit's name(s) and symbol + * + * @since 2020-09-07 + */ + private final NameSymbol nameSymbol; + + /** + * Cache storing the result of getDimension() + * + * @since 2019-10-16 + */ + private transient ObjectProduct dimension = null; + + /** + * Creates the {@code Unit}. + * + * @param unitBase base of unit + * @param ns names and symbol of unit + * @since 2019-10-16 + * @throws NullPointerException if unitBase or ns is null + */ + Unit(ObjectProduct unitBase, NameSymbol ns) { + this.unitBase = Objects.requireNonNull(unitBase, + "unitBase may not be null"); + this.nameSymbol = Objects.requireNonNull(ns, "ns may not be null"); + } + + /** + * A constructor that constructs {@code BaseUnit} instances. + * + * @since 2019-10-16 + */ + Unit(final String primaryName, final String symbol, + final Set otherNames) { + if (this instanceof BaseUnit) { + this.unitBase = ObjectProduct.oneOf((BaseUnit) this); + } else + throw new AssertionError(); + this.nameSymbol = NameSymbol.of(primaryName, symbol, + new HashSet<>(otherNames)); + } + + /** + * @return this unit as a {@link Unitlike} + * @since 2020-09-07 + */ + public final Unitlike asUnitlike() { + return Unitlike.fromConversionFunctions(this.getBase(), + this::convertFromBase, this::convertToBase, this.getNameSymbol()); + } + + /** + * Checks if a value expressed in this unit can be converted to a value + * expressed in {@code other} + * + * @param other unit or unitlike form to test with + * @return true if they are compatible + * @since 2019-01-13 + * @since v0.1.0 + * @throws NullPointerException if other is null + */ + public final boolean canConvertTo(final Unit other) { + Objects.requireNonNull(other, "other must not be null."); + return Objects.equals(this.getBase(), other.getBase()); + } + + /** + * Checks if a value expressed in this unit can be converted to a value + * expressed in {@code other} + * + * @param other unit or unitlike form to test with + * @return true if they are compatible + * @since 2019-01-13 + * @since v0.1.0 + * @throws NullPointerException if other is null + */ + public final boolean canConvertTo(final Unitlike other) { + Objects.requireNonNull(other, "other must not be null."); + return Objects.equals(this.getBase(), other.getBase()); + } + + /** + * Converts from a value expressed in this unit's base unit to a value + * expressed in this unit. + *

    + * This must be the inverse of {@code convertToBase}, so + * {@code convertFromBase(convertToBase(value))} must be equal to + * {@code value} for any value, ignoring precision loss by roundoff error. + *

    + *

    + * If this unit is a base unit, this method should return + * {@code value}. + *

    + * + * @implSpec This method is used by {@link #convertTo}, and its behaviour + * affects the behaviour of {@code convertTo}. + * + * @param value value expressed in base unit + * @return value expressed in this unit + * @since 2018-12-22 + * @since v0.1.0 + */ + protected abstract double convertFromBase(double value); + + /** + * Converts a value expressed in this unit to a value expressed in + * {@code other}. + * + * @implSpec If unit conversion is possible, this implementation returns + * {@code other.convertFromBase(this.convertToBase(value))}. + * Therefore, overriding either of those methods will change the + * output of this method. + * + * @param other unit to convert to + * @param value value to convert + * @return converted value + * @since 2019-05-22 + * @throws IllegalArgumentException if {@code other} is incompatible for + * conversion with this unit (as tested by + * {@link Unit#canConvertTo}). + * @throws NullPointerException if other is null + */ + public final double convertTo(final Unit other, final double value) { + Objects.requireNonNull(other, "other must not be null."); + if (this.canConvertTo(other)) + return other.convertFromBase(this.convertToBase(value)); + else + throw new IllegalArgumentException( + String.format("Cannot convert from %s to %s.", this, other)); + } + + /** + * Converts a value expressed in this unit to a value expressed in + * {@code other}. + * + * @implSpec If conversion is possible, this implementation returns + * {@code other.convertFromBase(this.convertToBase(value))}. + * Therefore, overriding either of those methods will change the + * output of this method. + * + * @param other unitlike form to convert to + * @param value value to convert + * @param type of value to convert to + * @return converted value + * @since 2020-09-07 + * @throws IllegalArgumentException if {@code other} is incompatible for + * conversion with this unit (as tested by + * {@link Unit#canConvertTo}). + * @throws NullPointerException if other is null + */ + public final W convertTo(final Unitlike other, final double value) { + Objects.requireNonNull(other, "other must not be null."); + if (this.canConvertTo(other)) + return other.convertFromBase(this.convertToBase(value)); + else + throw new IllegalArgumentException( + String.format("Cannot convert from %s to %s.", this, other)); + } + + /** + * Converts from a value expressed in this unit to a value expressed in this + * unit's base unit. + *

    + * This must be the inverse of {@code convertFromBase}, so + * {@code convertToBase(convertFromBase(value))} must be equal to + * {@code value} for any value, ignoring precision loss by roundoff error. + *

    + *

    + * If this unit is a base unit, this method should return + * {@code value}. + *

    + * + * @implSpec This method is used by {@link #convertTo}, and its behaviour + * affects the behaviour of {@code convertTo}. + * + * @param value value expressed in this unit + * @return value expressed in base unit + * @since 2018-12-22 + * @since v0.1.0 + */ + protected abstract double convertToBase(double value); + + /** + * @return combination of units that this unit is based on + * @since 2018-12-22 + * @since v0.1.0 + */ + public final ObjectProduct getBase() { + return this.unitBase; + } + + /** + * @return dimension measured by this unit + * @since 2018-12-22 + * @since v0.1.0 + */ + public final ObjectProduct getDimension() { + if (this.dimension == null) { + final Map mapping = this.unitBase.exponentMap(); + final Map dimensionMap = new HashMap<>(); + + for (final BaseUnit key : mapping.keySet()) { + dimensionMap.put(key.getBaseDimension(), mapping.get(key)); + } + + this.dimension = ObjectProduct.fromExponentMapping(dimensionMap); + } + return this.dimension; + } + + /** + * @return the nameSymbol + * @since 2020-09-07 + */ + @Override + public final NameSymbol getNameSymbol() { + return this.nameSymbol; + } + + /** + * Returns true iff this unit is metric. + *

    + * "Metric" is defined by three conditions: + *

      + *
    • Must be an instance of {@link LinearUnit}.
    • + *
    • Must be based on the SI base units (as determined by getBase())
    • + *
    • The conversion factor must be a power of 10.
    • + *
    + *

    + * Note that this definition excludes some units that many would consider + * "metric", such as the degree Celsius (fails the first condition), + * calories, minutes and hours (fail the third condition). + *

    + * All SI units (as designated by the BIPM) except the degree Celsius are + * considered "metric" by this definition. + * + * @since 2020-08-27 + */ + public final boolean isMetric() { + // first condition - check that it is a linear unit + if (!(this instanceof LinearUnit)) + return false; + final LinearUnit linear = (LinearUnit) this; + + // second condition - check that + for (final BaseUnit b : linear.getBase().getBaseSet()) { + if (!SI.BaseUnits.BASE_UNITS.contains(b)) + return false; + } + + // third condition - check that conversion factor is a power of 10 + return DecimalComparison + .equals(Math.log10(linear.getConversionFactor()) % 1.0, 0); + } + + @Override + public String toString() { + return this.getPrimaryName().orElse("Unnamed unit") + + (this.getSymbol().isPresent() + ? String.format(" (%s)", this.getSymbol().get()) + : "") + + ", derived from " + + this.getBase().toString(u -> u.getSymbol().get()) + + (this.getOtherNames().isEmpty() ? "" + : ", also called " + String.join(", ", this.getOtherNames())); + } + + /** + * @param ns name(s) and symbol to use + * @return a copy of this unit with provided name(s) and symbol + * @since 2019-10-21 + * @throws NullPointerException if ns is null + */ + public Unit withName(final NameSymbol ns) { + return fromConversionFunctions(this.getBase(), this::convertFromBase, + this::convertToBase, + Objects.requireNonNull(ns, "ns must not be null.")); + } +} diff --git a/src/main/java/org/unitConverter/unit/UnitDatabase.java b/src/main/java/org/unitConverter/unit/UnitDatabase.java new file mode 100644 index 0000000..000acf5 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/UnitDatabase.java @@ -0,0 +1,1991 @@ +/** + * Copyright (C) 2018 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.math.BigDecimal; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.unitConverter.math.ConditionalExistenceCollections; +import org.unitConverter.math.DecimalComparison; +import org.unitConverter.math.ExpressionParser; +import org.unitConverter.math.ObjectProduct; +import org.unitConverter.math.UncertainDouble; + +/** + * A database of units, prefixes and dimensions, and their names. + * + * @author Adrien Hopkins + * @since 2019-01-07 + * @since v0.1.0 + */ +public final class UnitDatabase { + /** + * A map for units that allows the use of prefixes. + *

    + * As this map implementation is intended to be used as a sort of "augmented + * view" of a unit and prefix map, it is unmodifiable but instead reflects + * the changes to the maps passed into it. Do not edit this map, instead edit + * the maps that were passed in during construction. + *

    + *

    + * The rules for applying prefixes onto units are the following: + *

      + *
    • Prefixes can only be applied to linear units.
    • + *
    • Before attempting to search for prefixes in a unit name, this map will + * first search for a unit name. So, if there are two units, "B" and "AB", + * and a prefix "A", this map will favour the unit "AB" over the unit "B" + * with the prefix "A", even though they have the same string.
    • + *
    • Longer prefixes are preferred to shorter prefixes. So, if you have + * units "BC" and "C", and prefixes "AB" and "A", inputting "ABC" will return + * the unit "C" with the prefix "AB", not "BC" with the prefix "A".
    • + *
    + *

    + *

    + * This map is infinite in size if there is at least one unit and at least + * one prefix. If it is infinite, some operations that only work with finite + * collections, like converting name/entry sets to arrays, will throw an + * {@code IllegalStateException}. + *

    + *

    + * Because of ambiguities between prefixes (i.e. kilokilo = mega), + * {@link #containsValue} and {@link #values()} currently ignore prefixes. + *

    + * + * @author Adrien Hopkins + * @since 2019-04-13 + * @since v0.2.0 + */ + private static final class PrefixedUnitMap implements Map { + /** + * The class used for entry sets. + * + *

    + * If the map that created this set is infinite in size (has at least one + * unit and at least one prefix), this set is infinite as well. If this + * set is infinite in size, {@link #toArray} will fail with a + * {@code IllegalStateException} instead of creating an infinite-sized + * array. + *

    + * + * @author Adrien Hopkins + * @since 2019-04-13 + * @since v0.2.0 + */ + private static final class PrefixedUnitEntrySet + extends AbstractSet> { + /** + * The entry for this set. + * + * @author Adrien Hopkins + * @since 2019-04-14 + * @since v0.2.0 + */ + private static final class PrefixedUnitEntry + implements Entry { + private final String key; + private final Unit value; + + /** + * Creates the {@code PrefixedUnitEntry}. + * + * @param key key + * @param value value + * @since 2019-04-14 + * @since v0.2.0 + */ + public PrefixedUnitEntry(final String key, final Unit value) { + this.key = key; + this.value = value; + } + + /** + * @since 2019-05-03 + */ + @Override + public boolean equals(final Object o) { + if (!(o instanceof Map.Entry)) + return false; + final Map.Entry other = (Map.Entry) o; + return Objects.equals(this.getKey(), other.getKey()) + && Objects.equals(this.getValue(), other.getValue()); + } + + @Override + public String getKey() { + return this.key; + } + + @Override + public Unit getValue() { + return this.value; + } + + /** + * @since 2019-05-03 + */ + @Override + public int hashCode() { + return (this.getKey() == null ? 0 : this.getKey().hashCode()) + ^ (this.getValue() == null ? 0 + : this.getValue().hashCode()); + } + + @Override + public Unit setValue(final Unit value) { + throw new UnsupportedOperationException( + "Cannot set value in an immutable entry"); + } + + /** + * Returns a string representation of the entry. The format of the + * string is the string representation of the key, then the equals + * ({@code =}) character, then the string representation of the + * value. + * + * @since 2019-05-03 + */ + @Override + public String toString() { + return this.getKey() + "=" + this.getValue(); + } + } + + /** + * An iterator that iterates over the units of a + * {@code PrefixedUnitNameSet}. + * + * @author Adrien Hopkins + * @since 2019-04-14 + * @since v0.2.0 + */ + private static final class PrefixedUnitEntryIterator + implements Iterator> { + // position in the unit list + private int unitNamePosition = 0; + // the indices of the prefixes attached to the current unit + private final List prefixCoordinates = new ArrayList<>(); + + // values from the unit entry set + private final Map map; + private transient final List unitNames; + private transient final List prefixNames; + + /** + * Creates the + * {@code UnitsDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator}. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + public PrefixedUnitEntryIterator(final PrefixedUnitMap map) { + this.map = map; + this.unitNames = new ArrayList<>(map.units.keySet()); + this.prefixNames = new ArrayList<>(map.prefixes.keySet()); + } + + /** + * @return current unit name + * @since 2019-04-14 + * @since v0.2.0 + */ + private String getCurrentUnitName() { + final StringBuilder unitName = new StringBuilder(); + for (final int i : this.prefixCoordinates) { + unitName.append(this.prefixNames.get(i)); + } + unitName.append(this.unitNames.get(this.unitNamePosition)); + + return unitName.toString(); + } + + @Override + public boolean hasNext() { + if (this.unitNames.isEmpty()) + return false; + else { + if (this.prefixNames.isEmpty()) + return this.unitNamePosition >= this.unitNames.size() - 1; + else + return true; + } + } + + /** + * Changes this iterator's position to the next available one. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + private void incrementPosition() { + this.unitNamePosition++; + + if (this.unitNamePosition >= this.unitNames.size()) { + // we have used all of our units, go to a different prefix + this.unitNamePosition = 0; + + // if the prefix coordinates are empty, then set it to [0] + if (this.prefixCoordinates.isEmpty()) { + this.prefixCoordinates.add(0, 0); + } else { + // get the prefix coordinate to increment, then increment + int i = this.prefixCoordinates.size() - 1; + this.prefixCoordinates.set(i, + this.prefixCoordinates.get(i) + 1); + + // fix any carrying errors + while (i >= 0 && this.prefixCoordinates + .get(i) >= this.prefixNames.size()) { + // carry over + this.prefixCoordinates.set(i--, 0); // null and + // decrement at the + // same time + + if (i < 0) { // we need to add a new coordinate + this.prefixCoordinates.add(0, 0); + } else { // increment an existing one + this.prefixCoordinates.set(i, + this.prefixCoordinates.get(i) + 1); + } + } + } + } + } + + @Override + public Entry next() { + // get next element + final Entry nextEntry = this.peek(); + + // iterate to next position + this.incrementPosition(); + + return nextEntry; + } + + /** + * @return the next element in the iterator, without iterating over + * it + * @since 2019-05-03 + */ + private Entry peek() { + if (!this.hasNext()) + throw new NoSuchElementException("No units left!"); + + // if I have prefixes, ensure I'm not using a nonlinear unit + // since all of the unprefixed stuff is done, just remove + // nonlinear units + if (!this.prefixCoordinates.isEmpty()) { + while (this.unitNamePosition < this.unitNames.size() + && !(this.map.get(this.unitNames.get( + this.unitNamePosition)) instanceof LinearUnit)) { + this.unitNames.remove(this.unitNamePosition); + } + } + + final String nextName = this.getCurrentUnitName(); + + return new PrefixedUnitEntry(nextName, this.map.get(nextName)); + } + + /** + * Returns a string representation of the object. The exact details + * of the representation are unspecified and subject to change. + * + * @since 2019-05-03 + */ + @Override + public String toString() { + return String.format( + "Iterator iterating over name-unit entries; next value is \"%s\"", + this.peek()); + } + } + + // the map that created this set + private final PrefixedUnitMap map; + + /** + * Creates the {@code PrefixedUnitNameSet}. + * + * @param map map that created this set + * @since 2019-04-13 + * @since v0.2.0 + */ + public PrefixedUnitEntrySet(final PrefixedUnitMap map) { + this.map = map; + } + + @Override + public boolean add(final Map.Entry e) { + throw new UnsupportedOperationException( + "Cannot add to an immutable set"); + } + + @Override + public boolean addAll( + final Collection> c) { + throw new UnsupportedOperationException( + "Cannot add to an immutable set"); + } + + @Override + public void clear() { + throw new UnsupportedOperationException( + "Cannot clear an immutable set"); + } + + @Override + public boolean contains(final Object o) { + // get the entry + final Entry entry; + + try { + // This is OK because I'm in a try-catch block, catching the + // exact exception that would be thrown. + @SuppressWarnings("unchecked") + final Entry tempEntry = (Entry) o; + entry = tempEntry; + } catch (final ClassCastException e) { + throw new IllegalArgumentException( + "Attempted to test for an entry using a non-entry."); + } + + return this.map.containsKey(entry.getKey()) + && this.map.get(entry.getKey()).equals(entry.getValue()); + } + + @Override + public boolean containsAll(final Collection c) { + for (final Object o : c) + if (!this.contains(o)) + return false; + return true; + } + + @Override + public boolean isEmpty() { + return this.map.isEmpty(); + } + + @Override + public Iterator> iterator() { + return new PrefixedUnitEntryIterator(this.map); + } + + @Override + public boolean remove(final Object o) { + throw new UnsupportedOperationException( + "Cannot remove from an immutable set"); + } + + @Override + public boolean removeAll(final Collection c) { + throw new UnsupportedOperationException( + "Cannot remove from an immutable set"); + } + + @Override + public boolean removeIf( + final Predicate> filter) { + throw new UnsupportedOperationException( + "Cannot remove from an immutable set"); + } + + @Override + public boolean retainAll(final Collection c) { + throw new UnsupportedOperationException( + "Cannot remove from an immutable set"); + } + + @Override + public int size() { + if (this.map.units.isEmpty()) + return 0; + else { + if (this.map.prefixes.isEmpty()) + return this.map.units.size(); + else + // infinite set + return Integer.MAX_VALUE; + } + } + + /** + * @throws IllegalStateException if the set is infinite in size + */ + @Override + public Object[] toArray() { + if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) + return super.toArray(); + else + // infinite set + throw new IllegalStateException( + "Cannot make an infinite set into an array."); + } + + /** + * @throws IllegalStateException if the set is infinite in size + */ + @Override + public T[] toArray(final T[] a) { + if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) + return super.toArray(a); + else + // infinite set + throw new IllegalStateException( + "Cannot make an infinite set into an array."); + } + + @Override + public String toString() { + if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) + return super.toString(); + else + return String.format( + "Infinite set of name-unit entries created from units %s and prefixes %s", + this.map.units, this.map.prefixes); + } + } + + /** + * The class used for unit name sets. + * + *

    + * If the map that created this set is infinite in size (has at least one + * unit and at least one prefix), this set is infinite as well. If this + * set is infinite in size, {@link #toArray} will fail with a + * {@code IllegalStateException} instead of creating an infinite-sized + * array. + *

    + * + * @author Adrien Hopkins + * @since 2019-04-13 + * @since v0.2.0 + */ + private static final class PrefixedUnitNameSet + extends AbstractSet { + /** + * An iterator that iterates over the units of a + * {@code PrefixedUnitNameSet}. + * + * @author Adrien Hopkins + * @since 2019-04-14 + * @since v0.2.0 + */ + private static final class PrefixedUnitNameIterator + implements Iterator { + // position in the unit list + private int unitNamePosition = 0; + // the indices of the prefixes attached to the current unit + private final List prefixCoordinates = new ArrayList<>(); + + // values from the unit name set + private final Map map; + private transient final List unitNames; + private transient final List prefixNames; + + /** + * Creates the + * {@code UnitsDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator}. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + public PrefixedUnitNameIterator(final PrefixedUnitMap map) { + this.map = map; + this.unitNames = new ArrayList<>(map.units.keySet()); + this.prefixNames = new ArrayList<>(map.prefixes.keySet()); + } + + /** + * @return current unit name + * @since 2019-04-14 + * @since v0.2.0 + */ + private String getCurrentUnitName() { + final StringBuilder unitName = new StringBuilder(); + for (final int i : this.prefixCoordinates) { + unitName.append(this.prefixNames.get(i)); + } + unitName.append(this.unitNames.get(this.unitNamePosition)); + + return unitName.toString(); + } + + @Override + public boolean hasNext() { + if (this.unitNames.isEmpty()) + return false; + else { + if (this.prefixNames.isEmpty()) + return this.unitNamePosition >= this.unitNames.size() - 1; + else + return true; + } + } + + /** + * Changes this iterator's position to the next available one. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + private void incrementPosition() { + this.unitNamePosition++; + + if (this.unitNamePosition >= this.unitNames.size()) { + // we have used all of our units, go to a different prefix + this.unitNamePosition = 0; + + // if the prefix coordinates are empty, then set it to [0] + if (this.prefixCoordinates.isEmpty()) { + this.prefixCoordinates.add(0, 0); + } else { + // get the prefix coordinate to increment, then increment + int i = this.prefixCoordinates.size() - 1; + this.prefixCoordinates.set(i, + this.prefixCoordinates.get(i) + 1); + + // fix any carrying errors + while (i >= 0 && this.prefixCoordinates + .get(i) >= this.prefixNames.size()) { + // carry over + this.prefixCoordinates.set(i--, 0); // null and + // decrement at the + // same time + + if (i < 0) { // we need to add a new coordinate + this.prefixCoordinates.add(0, 0); + } else { // increment an existing one + this.prefixCoordinates.set(i, + this.prefixCoordinates.get(i) + 1); + } + } + } + } + } + + @Override + public String next() { + final String nextName = this.peek(); + + this.incrementPosition(); + + return nextName; + } + + /** + * @return the next element in the iterator, without iterating over + * it + * @since 2019-05-03 + */ + private String peek() { + if (!this.hasNext()) + throw new NoSuchElementException("No units left!"); + // if I have prefixes, ensure I'm not using a nonlinear unit + // since all of the unprefixed stuff is done, just remove + // nonlinear units + if (!this.prefixCoordinates.isEmpty()) { + while (this.unitNamePosition < this.unitNames.size() + && !(this.map.get(this.unitNames.get( + this.unitNamePosition)) instanceof LinearUnit)) { + this.unitNames.remove(this.unitNamePosition); + } + } + + return this.getCurrentUnitName(); + } + + /** + * Returns a string representation of the object. The exact details + * of the representation are unspecified and subject to change. + * + * @since 2019-05-03 + */ + @Override + public String toString() { + return String.format( + "Iterator iterating over unit names; next value is \"%s\"", + this.peek()); + } + } + + // the map that created this set + private final PrefixedUnitMap map; + + /** + * Creates the {@code PrefixedUnitNameSet}. + * + * @param map map that created this set + * @since 2019-04-13 + * @since v0.2.0 + */ + public PrefixedUnitNameSet(final PrefixedUnitMap map) { + this.map = map; + } + + @Override + public boolean add(final String e) { + throw new UnsupportedOperationException( + "Cannot add to an immutable set"); + } + + @Override + public boolean addAll(final Collection c) { + throw new UnsupportedOperationException( + "Cannot add to an immutable set"); + } + + @Override + public void clear() { + throw new UnsupportedOperationException( + "Cannot clear an immutable set"); + } + + @Override + public boolean contains(final Object o) { + return this.map.containsKey(o); + } + + @Override + public boolean containsAll(final Collection c) { + for (final Object o : c) + if (!this.contains(o)) + return false; + return true; + } + + @Override + public boolean isEmpty() { + return this.map.isEmpty(); + } + + @Override + public Iterator iterator() { + return new PrefixedUnitNameIterator(this.map); + } + + @Override + public boolean remove(final Object o) { + throw new UnsupportedOperationException( + "Cannot remove from an immutable set"); + } + + @Override + public boolean removeAll(final Collection c) { + throw new UnsupportedOperationException( + "Cannot remove from an immutable set"); + } + + @Override + public boolean removeIf(final Predicate filter) { + throw new UnsupportedOperationException( + "Cannot remove from an immutable set"); + } + + @Override + public boolean retainAll(final Collection c) { + throw new UnsupportedOperationException( + "Cannot remove from an immutable set"); + } + + @Override + public int size() { + if (this.map.units.isEmpty()) + return 0; + else { + if (this.map.prefixes.isEmpty()) + return this.map.units.size(); + else + // infinite set + return Integer.MAX_VALUE; + } + } + + /** + * @throws IllegalStateException if the set is infinite in size + */ + @Override + public Object[] toArray() { + if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) + return super.toArray(); + else + // infinite set + throw new IllegalStateException( + "Cannot make an infinite set into an array."); + + } + + /** + * @throws IllegalStateException if the set is infinite in size + */ + @Override + public T[] toArray(final T[] a) { + if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) + return super.toArray(a); + else + // infinite set + throw new IllegalStateException( + "Cannot make an infinite set into an array."); + } + + @Override + public String toString() { + if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) + return super.toString(); + else + return String.format( + "Infinite set of name-unit entries created from units %s and prefixes %s", + this.map.units, this.map.prefixes); + } + } + + /** + * The units stored in this collection, without prefixes. + * + * @since 2019-04-13 + * @since v0.2.0 + */ + private final Map units; + + /** + * The available prefixes for use. + * + * @since 2019-04-13 + * @since v0.2.0 + */ + private final Map prefixes; + + // caches + private transient Collection values = null; + private transient Set keySet = null; + private transient Set> entrySet = null; + + /** + * Creates the {@code PrefixedUnitMap}. + * + * @param units map mapping unit names to units + * @param prefixes map mapping prefix names to prefixes + * @since 2019-04-13 + * @since v0.2.0 + */ + public PrefixedUnitMap(final Map units, + final Map prefixes) { + // I am making unmodifiable maps to ensure I don't accidentally make + // changes. + this.units = Collections.unmodifiableMap(units); + this.prefixes = Collections.unmodifiableMap(prefixes); + } + + @Override + public void clear() { + throw new UnsupportedOperationException( + "Cannot clear an immutable map"); + } + + @Override + public Unit compute(final String key, + final BiFunction remappingFunction) { + throw new UnsupportedOperationException( + "Cannot edit an immutable map"); + } + + @Override + public Unit computeIfAbsent(final String key, + final Function mappingFunction) { + throw new UnsupportedOperationException( + "Cannot edit an immutable map"); + } + + @Override + public Unit computeIfPresent(final String key, + final BiFunction remappingFunction) { + throw new UnsupportedOperationException( + "Cannot edit an immutable map"); + } + + @Override + public boolean containsKey(final Object key) { + // First, test if there is a unit with the key + if (this.units.containsKey(key)) + return true; + + // Next, try to cast it to String + if (!(key instanceof String)) + throw new IllegalArgumentException( + "Attempted to test for a unit using a non-string name."); + final String unitName = (String) key; + + // Then, look for the longest prefix that is attached to a valid unit + String longestPrefix = null; + int longestLength = 0; + + for (final String prefixName : this.prefixes.keySet()) { + // a prefix name is valid if: + // - it is prefixed (i.e. the unit name starts with it) + // - it is longer than the existing largest prefix (since I am + // looking for the longest valid prefix) + // - the part after the prefix is a valid unit name + // - the unit described that name is a linear unit (since only + // linear units can have prefixes) + if (unitName.startsWith(prefixName) + && prefixName.length() > longestLength) { + final String rest = unitName.substring(prefixName.length()); + if (this.containsKey(rest) + && this.get(rest) instanceof LinearUnit) { + longestPrefix = prefixName; + longestLength = prefixName.length(); + } + } + } + + return longestPrefix != null; + } + + /** + * {@inheritDoc} + * + *

    + * Because of ambiguities between prefixes (i.e. kilokilo = mega), this + * method only tests for prefixless units. + *

    + */ + @Override + public boolean containsValue(final Object value) { + return this.units.containsValue(value); + } + + @Override + public Set> entrySet() { + if (this.entrySet == null) { + this.entrySet = new PrefixedUnitEntrySet(this); + } + return this.entrySet; + } + + @Override + public Unit get(final Object key) { + // First, test if there is a unit with the key + if (this.units.containsKey(key)) + return this.units.get(key); + + // Next, try to cast it to String + if (!(key instanceof String)) + throw new IllegalArgumentException( + "Attempted to obtain a unit using a non-string name."); + final String unitName = (String) key; + + // Then, look for the longest prefix that is attached to a valid unit + String longestPrefix = null; + int longestLength = 0; + + for (final String prefixName : this.prefixes.keySet()) { + // a prefix name is valid if: + // - it is prefixed (i.e. the unit name starts with it) + // - it is longer than the existing largest prefix (since I am + // looking for the longest valid prefix) + // - the part after the prefix is a valid unit name + // - the unit described that name is a linear unit (since only + // linear units can have prefixes) + if (unitName.startsWith(prefixName) + && prefixName.length() > longestLength) { + final String rest = unitName.substring(prefixName.length()); + if (this.containsKey(rest) + && this.get(rest) instanceof LinearUnit) { + longestPrefix = prefixName; + longestLength = prefixName.length(); + } + } + } + + // if none found, returns null + if (longestPrefix == null) + return null; + else { + // get necessary data + final String rest = unitName.substring(longestLength); + // this cast will not fail because I verified that it would work + // before selecting this prefix + final LinearUnit unit = (LinearUnit) this.get(rest); + final UnitPrefix prefix = this.prefixes.get(longestPrefix); + + return unit.withPrefix(prefix); + } + } + + @Override + public boolean isEmpty() { + return this.units.isEmpty(); + } + + @Override + public Set keySet() { + if (this.keySet == null) { + this.keySet = new PrefixedUnitNameSet(this); + } + return this.keySet; + } + + @Override + public Unit merge(final String key, final Unit value, + final BiFunction remappingFunction) { + throw new UnsupportedOperationException( + "Cannot merge into an immutable map"); + } + + @Override + public Unit put(final String key, final Unit value) { + throw new UnsupportedOperationException( + "Cannot add entries to an immutable map"); + } + + @Override + public void putAll(final Map m) { + throw new UnsupportedOperationException( + "Cannot add entries to an immutable map"); + } + + @Override + public Unit putIfAbsent(final String key, final Unit value) { + throw new UnsupportedOperationException( + "Cannot add entries to an immutable map"); + } + + @Override + public Unit remove(final Object key) { + throw new UnsupportedOperationException( + "Cannot remove entries from an immutable map"); + } + + @Override + public boolean remove(final Object key, final Object value) { + throw new UnsupportedOperationException( + "Cannot remove entries from an immutable map"); + } + + @Override + public Unit replace(final String key, final Unit value) { + throw new UnsupportedOperationException( + "Cannot replace entries in an immutable map"); + } + + @Override + public boolean replace(final String key, final Unit oldValue, + final Unit newValue) { + throw new UnsupportedOperationException( + "Cannot replace entries in an immutable map"); + } + + @Override + public void replaceAll( + final BiFunction function) { + throw new UnsupportedOperationException( + "Cannot replace entries in an immutable map"); + } + + @Override + public int size() { + if (this.units.isEmpty()) + return 0; + else { + if (this.prefixes.isEmpty()) + return this.units.size(); + else + // infinite set + return Integer.MAX_VALUE; + } + } + + @Override + public String toString() { + if (this.units.isEmpty() || this.prefixes.isEmpty()) + return super.toString(); + else + return String.format( + "Infinite map of name-unit entries created from units %s and prefixes %s", + this.units, this.prefixes); + } + + /** + * {@inheritDoc} + * + *

    + * Because of ambiguities between prefixes (i.e. kilokilo = mega), this + * method ignores prefixes. + *

    + */ + @Override + public Collection values() { + if (this.values == null) { + this.values = Collections + .unmodifiableCollection(this.units.values()); + } + return this.values; + } + } + + /** + * Replacements done to *all* expression types + */ + private static final Map EXPRESSION_REPLACEMENTS = new HashMap<>(); + + // add data to expression replacements + static { + // add spaces around operators + for (final String operator : Arrays.asList("\\*", "/", "\\^")) { + EXPRESSION_REPLACEMENTS.put(Pattern.compile(operator), + " " + operator + " "); + } + + // replace multiple spaces with a single space + EXPRESSION_REPLACEMENTS.put(Pattern.compile(" +"), " "); + // place brackets around any expression of the form "number unit", with or + // without the space + EXPRESSION_REPLACEMENTS.put(Pattern.compile("((?:-?[1-9]\\d*|0)" // integer + + "(?:\\.\\d+(?:[eE]\\d+))?)" // optional decimal point with numbers + // after it + + "\\s*" // optional space(s) + + "([a-zA-Z]+(?:\\^\\d+)?" // any string of letters + + "(?:\\s+[a-zA-Z]+(?:\\^\\d+)?))" // optional other letters + + "(?!-?\\d)" // no number directly afterwards (avoids matching + // "1e3") + ), "\\($1 $2\\)"); + } + + /** + * A regular expression that separates names and expressions in unit files. + */ + private static final Pattern NAME_EXPRESSION = Pattern + .compile("(\\S+)\\s+(\\S.*)"); + + /** + * The exponent operator + * + * @param base base of exponentiation + * @param exponentUnit exponent + * @return result + * @since 2019-04-10 + * @since v0.2.0 + */ + private static final LinearUnit exponentiateUnits(final LinearUnit base, + final LinearUnit exponentUnit) { + // exponent function - first check if o2 is a number, + if (exponentUnit.getBase().equals(SI.ONE.getBase())) { + // then check if it is an integer, + final double exponent = exponentUnit.getConversionFactor(); + if (DecimalComparison.equals(exponent % 1, 0)) + // then exponentiate + return base.toExponent((int) (exponent + 0.5)); + else + // not an integer + throw new UnsupportedOperationException( + "Decimal exponents are currently not supported."); + } else + // not a number + throw new IllegalArgumentException("Exponents must be numbers."); + } + + /** + * The exponent operator + * + * @param base base of exponentiation + * @param exponentUnit exponent + * @return result + * @since 2020-08-04 + */ + private static final LinearUnitValue exponentiateUnitValues( + final LinearUnitValue base, final LinearUnitValue exponentValue) { + // exponent function - first check if o2 is a number, + if (exponentValue.canConvertTo(SI.ONE)) { + // then check if it is an integer, + final double exponent = exponentValue.getValueExact(); + if (DecimalComparison.equals(exponent % 1, 0)) + // then exponentiate + return base.toExponent((int) (exponent + 0.5)); + else + // not an integer + throw new UnsupportedOperationException( + "Decimal exponents are currently not supported."); + } else + // not a number + throw new IllegalArgumentException("Exponents must be numbers."); + } + + /** + * The units in this system, excluding prefixes. + * + * @since 2019-01-07 + * @since v0.1.0 + */ + private final Map prefixlessUnits; + + /** + * The unit prefixes in this system. + * + * @since 2019-01-14 + * @since v0.1.0 + */ + private final Map prefixes; + + /** + * The dimensions in this system. + * + * @since 2019-03-14 + * @since v0.2.0 + */ + private final Map> dimensions; + + /** + * A map mapping strings to units (including prefixes) + * + * @since 2019-04-13 + * @since v0.2.0 + */ + private final Map units; + + /** + * The rule that specifies when prefix repetition is allowed. It takes in one + * argument: a list of the prefixes being applied to the unit + *

    + * The prefixes are inputted in application order. This means that + * testing whether "kilomegagigametre" is a valid unit is equivalent to + * running the following code (assuming all variables are defined correctly): + *
    + * {@code prefixRepetitionRule.test(Arrays.asList(giga, mega, kilo))} + */ + private Predicate> prefixRepetitionRule; + + /** + * A parser that can parse unit expressions. + * + * @since 2019-03-22 + * @since v0.2.0 + */ + private final ExpressionParser unitExpressionParser = new ExpressionParser.Builder<>( + this::getLinearUnit).addBinaryOperator("+", (o1, o2) -> o1.plus(o2), 0) + .addBinaryOperator("-", (o1, o2) -> o1.minus(o2), 0) + .addBinaryOperator("*", (o1, o2) -> o1.times(o2), 1) + .addSpaceFunction("*") + .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 1) + .addBinaryOperator("^", UnitDatabase::exponentiateUnits, 2) + .build(); + + /** + * A parser that can parse unit value expressions. + * + * @since 2020-08-04 + */ + private final ExpressionParser unitValueExpressionParser = new ExpressionParser.Builder<>( + this::getLinearUnitValue) + .addBinaryOperator("+", (o1, o2) -> o1.plus(o2), 0) + .addBinaryOperator("-", (o1, o2) -> o1.minus(o2), 0) + .addBinaryOperator("*", (o1, o2) -> o1.times(o2), 1) + .addSpaceFunction("*") + .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 1) + .addBinaryOperator("^", UnitDatabase::exponentiateUnitValues, 2) + .build(); + + /** + * A parser that can parse unit prefix expressions + * + * @since 2019-04-13 + * @since v0.2.0 + */ + private final ExpressionParser prefixExpressionParser = new ExpressionParser.Builder<>( + this::getPrefix).addBinaryOperator("*", (o1, o2) -> o1.times(o2), 0) + .addSpaceFunction("*") + .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 0) + .addBinaryOperator("^", + (o1, o2) -> o1.toExponent(o2.getMultiplier()), 1) + .build(); + + /** + * A parser that can parse unit dimension expressions. + * + * @since 2019-04-13 + * @since v0.2.0 + */ + private final ExpressionParser> unitDimensionParser = new ExpressionParser.Builder<>( + this::getDimension).addBinaryOperator("*", (o1, o2) -> o1.times(o2), 0) + .addSpaceFunction("*") + .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 0).build(); + + /** + * Creates the {@code UnitsDatabase}. + * + * @since 2019-01-10 + * @since v0.1.0 + */ + public UnitDatabase() { + this(prefixes -> true); + } + + /** + * Creates the {@code UnitsDatabase} + * + * @param prefixRepetitionRule the rule that determines when prefix + * repetition is allowed + * @since 2020-08-26 + */ + public UnitDatabase(Predicate> prefixRepetitionRule) { + this.prefixlessUnits = new HashMap<>(); + this.prefixes = new HashMap<>(); + this.dimensions = new HashMap<>(); + this.prefixRepetitionRule = prefixRepetitionRule; + this.units = ConditionalExistenceCollections.conditionalExistenceMap( + new PrefixedUnitMap(this.prefixlessUnits, this.prefixes), + entry -> this.prefixRepetitionRule + .test(this.getPrefixesFromName(entry.getKey()))); + } + + /** + * Adds a unit dimension to the database. + * + * @param name dimension's name + * @param dimension dimension to add + * @throws NullPointerException if name or dimension is null + * @since 2019-03-14 + * @since v0.2.0 + */ + public void addDimension(final String name, + final ObjectProduct dimension) { + this.dimensions.put( + Objects.requireNonNull(name, "name must not be null."), + Objects.requireNonNull(dimension, "dimension must not be null.")); + } + + /** + * Adds to the list from a line in a unit dimension file. + * + * @param line line to look at + * @param lineCounter number of line, for error messages + * @since 2019-04-10 + * @since v0.2.0 + */ + private void addDimensionFromLine(final String line, + final long lineCounter) { + // ignore lines that start with a # sign - they're comments + if (line.isEmpty()) + return; + if (line.contains("#")) { + this.addDimensionFromLine(line.substring(0, line.indexOf("#")), + lineCounter); + return; + } + + // divide line into name and expression + final Matcher lineMatcher = NAME_EXPRESSION.matcher(line); + if (!lineMatcher.matches()) + throw new IllegalArgumentException(String.format( + "Error at line %d: Lines of a dimension file must consist of a dimension name, then spaces or tabs, then a dimension expression.", + lineCounter)); + final String name = lineMatcher.group(1); + final String expression = lineMatcher.group(2); + + if (name.endsWith(" ")) { + System.err.printf("Warning - line %d's dimension name ends in a space", + lineCounter); + } + + // if expression is "!", search for an existing dimension + // if no unit found, throw an error + if (expression.equals("!")) { + if (!this.containsDimensionName(name)) + throw new IllegalArgumentException(String.format( + "! used but no dimension found (line %d).", lineCounter)); + } else { + // it's a unit, get the unit + final ObjectProduct dimension; + try { + dimension = this.getDimensionFromExpression(expression); + } catch (final IllegalArgumentException e) { + System.err.printf("Parsing error on line %d:%n", lineCounter); + throw e; + } + + this.addDimension(name, dimension); + } + } + + /** + * Adds a unit prefix to the database. + * + * @param name prefix's name + * @param prefix prefix to add + * @throws NullPointerException if name or prefix is null + * @since 2019-01-14 + * @since v0.1.0 + */ + public void addPrefix(final String name, final UnitPrefix prefix) { + this.prefixes.put(Objects.requireNonNull(name, "name must not be null."), + Objects.requireNonNull(prefix, "prefix must not be null.")); + } + + /** + * Adds a unit to the database. + * + * @param name unit's name + * @param unit unit to add + * @throws NullPointerException if unit is null + * @since 2019-01-10 + * @since v0.1.0 + */ + public void addUnit(final String name, final Unit unit) { + this.prefixlessUnits.put( + Objects.requireNonNull(name, "name must not be null."), + Objects.requireNonNull(unit, "unit must not be null.")); + } + + /** + * Adds to the list from a line in a unit file. + * + * @param line line to look at + * @param lineCounter number of line, for error messages + * @since 2019-04-10 + * @since v0.2.0 + */ + private void addUnitOrPrefixFromLine(final String line, + final long lineCounter) { + // ignore lines that start with a # sign - they're comments + if (line.isEmpty()) + return; + if (line.contains("#")) { + this.addUnitOrPrefixFromLine(line.substring(0, line.indexOf("#")), + lineCounter); + return; + } + + // divide line into name and expression + final Matcher lineMatcher = NAME_EXPRESSION.matcher(line); + if (!lineMatcher.matches()) + throw new IllegalArgumentException(String.format( + "Error at line %d: Lines of a unit file must consist of a unit name, then spaces or tabs, then a unit expression.", + lineCounter)); + final String name = lineMatcher.group(1); + + final String expression = lineMatcher.group(2); + + if (name.endsWith(" ")) { + System.err.printf("Warning - line %d's unit name ends in a space", + lineCounter); + } + + // if expression is "!", search for an existing unit + // if no unit found, throw an error + if (expression.equals("!")) { + if (!this.containsUnitName(name)) + throw new IllegalArgumentException(String + .format("! used but no unit found (line %d).", lineCounter)); + } else { + if (name.endsWith("-")) { + final UnitPrefix prefix; + try { + prefix = this.getPrefixFromExpression(expression); + } catch (final IllegalArgumentException e) { + System.err.printf("Parsing error on line %d:%n", lineCounter); + throw e; + } + this.addPrefix(name.substring(0, name.length() - 1), prefix); + } else { + // it's a unit, get the unit + final Unit unit; + try { + unit = this.getUnitFromExpression(expression); + } catch (final IllegalArgumentException e) { + System.err.printf("Parsing error on line %d:%n", lineCounter); + throw e; + } + + this.addUnit(name, unit); + } + } + } + + /** + * Tests if the database has a unit dimension with this name. + * + * @param name name to test + * @return if database contains name + * @since 2019-03-14 + * @since v0.2.0 + */ + public boolean containsDimensionName(final String name) { + return this.dimensions.containsKey(name); + } + + /** + * Tests if the database has a unit prefix with this name. + * + * @param name name to test + * @return if database contains name + * @since 2019-01-13 + * @since v0.1.0 + */ + public boolean containsPrefixName(final String name) { + return this.prefixes.containsKey(name); + } + + /** + * Tests if the database has a unit with this name, taking prefixes into + * consideration + * + * @param name name to test + * @return if database contains name + * @since 2019-01-13 + * @since v0.1.0 + */ + public boolean containsUnitName(final String name) { + return this.units.containsKey(name); + } + + /** + * @return a map mapping dimension names to dimensions + * @since 2019-04-13 + * @since v0.2.0 + */ + public Map> dimensionMap() { + return Collections.unmodifiableMap(this.dimensions); + } + + /** + * Evaluates a unit expression, following the same rules as + * {@link #getUnitFromExpression}. + * + * @param expression expression to parse + * @return {@code LinearUnitValue} representing value of expression + * @since 2020-08-04 + */ + public LinearUnitValue evaluateUnitExpression(final String expression) { + Objects.requireNonNull(expression, "expression must not be null."); + + // attempt to get a unit as an alias, or a number with precision first + if (this.containsUnitName(expression)) + return this.getLinearUnitValue(expression); + + // force operators to have spaces + String modifiedExpression = expression; + modifiedExpression = modifiedExpression.replaceAll("\\+", " \\+ "); + modifiedExpression = modifiedExpression.replaceAll("-", " - "); + + // format expression + for (final Entry replacement : EXPRESSION_REPLACEMENTS + .entrySet()) { + modifiedExpression = replacement.getKey().matcher(modifiedExpression) + .replaceAll(replacement.getValue()); + } + + // the previous operation breaks negative numbers, fix them! + // (i.e. -2 becomes - 2) + // FIXME the previous operaton also breaks stuff like "1e-5" + for (int i = 0; i < modifiedExpression.length(); i++) { + if (modifiedExpression.charAt(i) == '-' + && (i < 2 || Arrays.asList('+', '-', '*', '/', '^') + .contains(modifiedExpression.charAt(i - 2)))) { + // found a broken negative number + modifiedExpression = modifiedExpression.substring(0, i + 1) + + modifiedExpression.substring(i + 2); + } + } + + return this.unitValueExpressionParser.parseExpression(modifiedExpression); + } + + /** + * Gets a unit dimension from the database using its name. + * + *

    + * This method accepts exponents, like "L^3" + *

    + * + * @param name dimension's name + * @return dimension + * @since 2019-03-14 + * @since v0.2.0 + */ + public ObjectProduct getDimension(final String name) { + Objects.requireNonNull(name, "name must not be null."); + if (name.contains("^")) { + final String[] baseAndExponent = name.split("\\^"); + + final ObjectProduct base = this + .getDimension(baseAndExponent[0]); + + final int exponent; + try { + exponent = Integer + .parseInt(baseAndExponent[baseAndExponent.length - 1]); + } catch (final NumberFormatException e2) { + throw new IllegalArgumentException("Exponent must be an integer."); + } + + return base.toExponent(exponent); + } + return this.dimensions.get(name); + } + + /** + * Uses the database's data to parse an expression into a unit dimension + *

    + * The expression is a series of any of the following: + *

      + *
    • The name of a unit dimension, which multiplies or divides the result + * based on preceding operators
    • + *
    • The operators '*' and '/', which multiply and divide (note that just + * putting two unit dimensions next to each other is equivalent to + * multiplication)
    • + *
    • The operator '^' which exponentiates. Exponents must be integers.
    • + *
    + * + * @param expression expression to parse + * @throws IllegalArgumentException if the expression cannot be parsed + * @throws NullPointerException if expression is null + * @since 2019-04-13 + * @since v0.2.0 + */ + public ObjectProduct getDimensionFromExpression( + final String expression) { + Objects.requireNonNull(expression, "expression must not be null."); + + // attempt to get a dimension as an alias first + if (this.containsDimensionName(expression)) + return this.getDimension(expression); + + // force operators to have spaces + String modifiedExpression = expression; + + // format expression + for (final Entry replacement : EXPRESSION_REPLACEMENTS + .entrySet()) { + modifiedExpression = replacement.getKey().matcher(modifiedExpression) + .replaceAll(replacement.getValue()); + } + modifiedExpression = modifiedExpression.replaceAll(" *\\^ *", "\\^"); + + return this.unitDimensionParser.parseExpression(modifiedExpression); + } + + /** + * Gets a unit. If it is linear, cast it to a LinearUnit and return it. + * Otherwise, throw an {@code IllegalArgumentException}. + * + * @param name unit's name + * @return unit + * @since 2019-03-22 + * @since v0.2.0 + */ + private LinearUnit getLinearUnit(final String name) { + // see if I am using a function-unit like tempC(100) + Objects.requireNonNull(name, "name may not be null"); + if (name.contains("(") && name.contains(")")) { + // break it into function name and value + final List parts = Arrays.asList(name.split("\\(")); + if (parts.size() != 2) + throw new IllegalArgumentException( + "Format nonlinear units like: unit(value)."); + + // solve the function + final Unit unit = this.getUnit(parts.get(0)); + final double value = Double.parseDouble( + parts.get(1).substring(0, parts.get(1).length() - 1)); + return LinearUnit.fromUnitValue(unit, value); + } else { + // get a linear unit + final Unit unit = this.getUnit(name); + + if (unit instanceof LinearUnit) + return (LinearUnit) unit; + else + throw new IllegalArgumentException( + String.format("%s is not a linear unit.", name)); + } + } + + /** + * Gets a {@code LinearUnitValue} from a unit name. Nonlinear units will be + * converted to their base units. + * + * @param name name of unit + * @return {@code LinearUnitValue} instance + * @since 2020-08-04 + */ + private LinearUnitValue getLinearUnitValue(final String name) { + try { + // try to parse it as a number - otherwise it is not a number! + final BigDecimal number = new BigDecimal(name); + + final double uncertainty = Math.pow(10, -number.scale()); + return LinearUnitValue.of(SI.ONE, + UncertainDouble.of(number.doubleValue(), uncertainty)); + } catch (final NumberFormatException e) { + return LinearUnitValue.getExact(this.getLinearUnit(name), 1); + } + } + + /** + * Gets a unit prefix from the database from its name + * + * @param name prefix's name + * @return prefix + * @since 2019-01-10 + * @since v0.1.0 + */ + public UnitPrefix getPrefix(final String name) { + try { + return UnitPrefix.valueOf(Double.parseDouble(name)); + } catch (final NumberFormatException e) { + return this.prefixes.get(name); + } + } + + /** + * Gets all of the prefixes that are on a unit name, in application order. + * + * @param unitName name of unit + * @return prefixes + * @since 2020-08-26 + */ + List getPrefixesFromName(final String unitName) { + final List prefixes = new ArrayList<>(); + String name = unitName; + + while (!this.prefixlessUnits.containsKey(name)) { + // find the longest prefix + String longestPrefixName = null; + int longestLength = name.length(); + + while (longestPrefixName == null) { + longestLength--; + if (longestLength <= 0) + throw new AssertionError( + "No prefix found in " + name + ", but it is not a unit!"); + if (this.prefixes.containsKey(name.substring(0, longestLength))) { + longestPrefixName = name.substring(0, longestLength); + } + } + + // longest prefix found! + final UnitPrefix prefix = this.getPrefix(longestPrefixName); + prefixes.add(0, prefix); + name = name.substring(longestLength); + } + return prefixes; + } + + /** + * Gets a unit prefix from a prefix expression + *

    + * Currently, prefix expressions are much simpler than unit expressions: They + * are either a number or the name of another prefix + *

    + * + * @param expression expression to input + * @return prefix + * @throws IllegalArgumentException if expression cannot be parsed + * @throws NullPointerException if any argument is null + * @since 2019-01-14 + * @since v0.1.0 + */ + public UnitPrefix getPrefixFromExpression(final String expression) { + Objects.requireNonNull(expression, "expression must not be null."); + + // attempt to get a unit as an alias first + if (this.containsUnitName(expression)) + return this.getPrefix(expression); + + // force operators to have spaces + String modifiedExpression = expression; + + // format expression + for (final Entry replacement : EXPRESSION_REPLACEMENTS + .entrySet()) { + modifiedExpression = replacement.getKey().matcher(modifiedExpression) + .replaceAll(replacement.getValue()); + } + + return this.prefixExpressionParser.parseExpression(modifiedExpression); + } + + /** + * @return the prefixRepetitionRule + * @since 2020-08-26 + */ + public final Predicate> getPrefixRepetitionRule() { + return this.prefixRepetitionRule; + } + + /** + * Gets a unit from the database from its name, looking for prefixes. + * + * @param name unit's name + * @return unit + * @since 2019-01-10 + * @since v0.1.0 + */ + public Unit getUnit(final String name) { + try { + final double value = Double.parseDouble(name); + return SI.ONE.times(value); + } catch (final NumberFormatException e) { + final Unit unit = this.units.get(name); + if (unit == null) + throw new NoSuchElementException("No unit " + name); + else if (unit.getPrimaryName().isEmpty()) + return unit.withName(NameSymbol.ofName(name)); + else if (!unit.getPrimaryName().get().equals(name)) { + final Set otherNames = new HashSet<>(unit.getOtherNames()); + otherNames.add(unit.getPrimaryName().get()); + return unit.withName(NameSymbol.ofNullable(name, + unit.getSymbol().orElse(null), otherNames)); + } else if (!unit.getOtherNames().contains(name)) { + final Set otherNames = new HashSet<>(unit.getOtherNames()); + otherNames.add(name); + return unit.withName( + NameSymbol.ofNullable(unit.getPrimaryName().orElse(null), + unit.getSymbol().orElse(null), otherNames)); + } else + return unit; + } + + } + + /** + * Uses the database's unit data to parse an expression into a unit + *

    + * The expression is a series of any of the following: + *

      + *
    • The name of a unit, which multiplies or divides the result based on + * preceding operators
    • + *
    • The operators '*' and '/', which multiply and divide (note that just + * putting two units or values next to each other is equivalent to + * multiplication)
    • + *
    • The operator '^' which exponentiates. Exponents must be integers.
    • + *
    • A number which is multiplied or divided
    • + *
    + * This method only works with linear units. + * + * @param expression expression to parse + * @throws IllegalArgumentException if the expression cannot be parsed + * @throws NullPointerException if expression is null + * @since 2019-01-07 + * @since v0.1.0 + */ + public Unit getUnitFromExpression(final String expression) { + Objects.requireNonNull(expression, "expression must not be null."); + + // attempt to get a unit as an alias first + if (this.containsUnitName(expression)) + return this.getUnit(expression); + + // force operators to have spaces + String modifiedExpression = expression; + modifiedExpression = modifiedExpression.replaceAll("\\+", " \\+ "); + modifiedExpression = modifiedExpression.replaceAll("-", " - "); + + // format expression + for (final Entry replacement : EXPRESSION_REPLACEMENTS + .entrySet()) { + modifiedExpression = replacement.getKey().matcher(modifiedExpression) + .replaceAll(replacement.getValue()); + } + + // the previous operation breaks negative numbers, fix them! + // (i.e. -2 becomes - 2) + for (int i = 0; i < modifiedExpression.length(); i++) { + if (modifiedExpression.charAt(i) == '-' + && (i < 2 || Arrays.asList('+', '-', '*', '/', '^') + .contains(modifiedExpression.charAt(i - 2)))) { + // found a broken negative number + modifiedExpression = modifiedExpression.substring(0, i + 1) + + modifiedExpression.substring(i + 2); + } + } + + return this.unitExpressionParser.parseExpression(modifiedExpression); + } + + /** + * Adds all dimensions from a file, using data from the database to parse + * them. + *

    + * Each line in the file should consist of a name and an expression (parsed + * by getDimensionFromExpression) separated by any number of tab characters. + *

    + *

    + * Allowed exceptions: + *

      + *
    • Anything after a '#' character is considered a comment and + * ignored.
    • + *
    • Blank lines are also ignored
    • + *
    • If an expression consists of a single exclamation point, instead of + * parsing it, this method will search the database for an existing unit. If + * no unit is found, an IllegalArgumentException is thrown. This is used to + * define initial units and ensure that the database contains them.
    • + *
    + * + * @param file file to read + * @throws IllegalArgumentException if the file cannot be parsed, found or + * read + * @throws NullPointerException if file is null + * @since 2019-01-13 + * @since v0.1.0 + */ + public void loadDimensionFile(final Path file) { + Objects.requireNonNull(file, "file must not be null."); + try { + long lineCounter = 0; + for (final String line : Files.readAllLines(file)) { + this.addDimensionFromLine(line, ++lineCounter); + } + } catch (final FileNotFoundException e) { + throw new IllegalArgumentException("Could not find file " + file, e); + } catch (final IOException e) { + throw new IllegalArgumentException("Could not read file " + file, e); + } + } + + /** + * Adds all units from a file, using data from the database to parse them. + *

    + * Each line in the file should consist of a name and an expression (parsed + * by getUnitFromExpression) separated by any number of tab characters. + *

    + *

    + * Allowed exceptions: + *

      + *
    • Anything after a '#' character is considered a comment and + * ignored.
    • + *
    • Blank lines are also ignored
    • + *
    • If an expression consists of a single exclamation point, instead of + * parsing it, this method will search the database for an existing unit. If + * no unit is found, an IllegalArgumentException is thrown. This is used to + * define initial units and ensure that the database contains them.
    • + *
    + * + * @param file file to read + * @throws IllegalArgumentException if the file cannot be parsed, found or + * read + * @throws NullPointerException if file is null + * @since 2019-01-13 + * @since v0.1.0 + */ + public void loadUnitsFile(final Path file) { + Objects.requireNonNull(file, "file must not be null."); + try { + long lineCounter = 0; + for (final String line : Files.readAllLines(file)) { + this.addUnitOrPrefixFromLine(line, ++lineCounter); + } + } catch (final FileNotFoundException e) { + throw new IllegalArgumentException("Could not find file " + file, e); + } catch (final IOException e) { + throw new IllegalArgumentException("Could not read file " + file, e); + } + } + + /** + * @return a map mapping prefix names to prefixes + * @since 2019-04-13 + * @since v0.2.0 + */ + public Map prefixMap() { + return Collections.unmodifiableMap(this.prefixes); + } + + /** + * @param prefixRepetitionRule the prefixRepetitionRule to set + * @since 2020-08-26 + */ + public final void setPrefixRepetitionRule( + Predicate> prefixRepetitionRule) { + this.prefixRepetitionRule = prefixRepetitionRule; + } + + /** + * @return a string stating the number of units, prefixes and dimensions in + * the database + */ + @Override + public String toString() { + return String.format( + "Unit Database with %d units, %d unit prefixes and %d dimensions", + this.prefixlessUnits.size(), this.prefixes.size(), + this.dimensions.size()); + } + + /** + * Returns a map mapping unit names to units, including units with prefixes. + *

    + * The returned map is infinite in size if there is at least one unit and at + * least one prefix. If it is infinite, some operations that only work with + * finite collections, like converting name/entry sets to arrays, will throw + * an {@code IllegalStateException}. + *

    + *

    + * Specifically, the operations that will throw an IllegalStateException if + * the map is infinite in size are: + *

      + *
    • {@code unitMap.entrySet().toArray()} (either overloading)
    • + *
    • {@code unitMap.keySet().toArray()} (either overloading)
    • + *
    + *

    + *

    + * Because of ambiguities between prefixes (i.e. kilokilo = mega), the map's + * {@link PrefixedUnitMap#containsValue containsValue} and + * {@link PrefixedUnitMap#values() values()} methods currently ignore + * prefixes. + *

    + * + * @return a map mapping unit names to units, including prefixed names + * @since 2019-04-13 + * @since v0.2.0 + */ + public Map unitMap() { + return this.units; // PrefixedUnitMap is immutable so I don't need to make + // an unmodifiable map. + } + + /** + * @return a map mapping unit names to units, ignoring prefixes + * @since 2019-04-13 + * @since v0.2.0 + */ + public Map unitMapPrefixless() { + return Collections.unmodifiableMap(this.prefixlessUnits); + } +} diff --git a/src/main/java/org/unitConverter/unit/UnitPrefix.java b/src/main/java/org/unitConverter/unit/UnitPrefix.java new file mode 100644 index 0000000..31cc0b3 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/UnitPrefix.java @@ -0,0 +1,242 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import org.unitConverter.math.DecimalComparison; + +/** + * A prefix that can be applied to a {@code LinearUnit} to multiply it by some value + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +public final class UnitPrefix { + /** + * Gets a {@code UnitPrefix} from a multiplier + * + * @param multiplier + * multiplier of prefix + * @return prefix + * @since 2019-10-16 + */ + public static UnitPrefix valueOf(final double multiplier) { + return new UnitPrefix(multiplier, NameSymbol.EMPTY); + } + + /** + * Gets a {@code UnitPrefix} from a multiplier and a name + * + * @param multiplier + * multiplier of prefix + * @param ns + * name(s) and symbol of prefix + * @return prefix + * @since 2019-10-16 + * @throws NullPointerException + * if ns is null + */ + public static UnitPrefix valueOf(final double multiplier, final NameSymbol ns) { + return new UnitPrefix(multiplier, Objects.requireNonNull(ns, "ns must not be null.")); + } + + /** + * This prefix's primary name + */ + private final Optional primaryName; + + /** + * This prefix's symbol + */ + private final Optional symbol; + + /** + * Other names and symbols used by this prefix + */ + private final Set otherNames; + + /** + * The number that this prefix multiplies units by + * + * @since 2019-10-16 + */ + private final double multiplier; + + /** + * Creates the {@code DefaultUnitPrefix}. + * + * @param multiplier + * @since 2019-01-14 + * @since v0.2.0 + */ + private UnitPrefix(final double multiplier, final NameSymbol ns) { + this.multiplier = multiplier; + this.primaryName = ns.getPrimaryName(); + this.symbol = ns.getSymbol(); + this.otherNames = ns.getOtherNames(); + } + + /** + * Divides this prefix by a scalar + * + * @param divisor + * number to divide by + * @return quotient of prefix and scalar + * @since 2019-10-16 + */ + public UnitPrefix dividedBy(final double divisor) { + return valueOf(this.getMultiplier() / divisor); + } + + /** + * Divides this prefix by {@code other}. + * + * @param other + * prefix to divide by + * @return quotient of prefixes + * @since 2019-04-13 + * @since v0.2.0 + */ + public UnitPrefix dividedBy(final UnitPrefix other) { + return valueOf(this.getMultiplier() / other.getMultiplier()); + } + + /** + * {@inheritDoc} + * + * Uses the prefix's multiplier to determine equality. + */ + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof UnitPrefix)) + return false; + final UnitPrefix other = (UnitPrefix) obj; + return DecimalComparison.equals(this.getMultiplier(), other.getMultiplier()); + } + + /** + * @return prefix's multiplier + * @since 2019-11-26 + */ + public double getMultiplier() { + return this.multiplier; + } + + /** + * @return other names + * @since 2019-11-26 + */ + public final Set getOtherNames() { + return this.otherNames; + } + + /** + * @return primary name + * @since 2019-11-26 + */ + public final Optional getPrimaryName() { + return this.primaryName; + } + + /** + * @return symbol + * @since 2019-11-26 + */ + public final Optional getSymbol() { + return this.symbol; + } + + /** + * {@inheritDoc} + * + * Uses the prefix's multiplier to determine a hash code. + */ + @Override + public int hashCode() { + return DecimalComparison.hash(this.getMultiplier()); + } + + /** + * Multiplies this prefix by a scalar + * + * @param multiplicand + * number to multiply by + * @return product of prefix and scalar + * @since 2019-10-16 + */ + public UnitPrefix times(final double multiplicand) { + return valueOf(this.getMultiplier() * multiplicand); + } + + /** + * Multiplies this prefix by {@code other}. + * + * @param other + * prefix to multiply by + * @return product of prefixes + * @since 2019-04-13 + * @since v0.2.0 + */ + public UnitPrefix times(final UnitPrefix other) { + return valueOf(this.getMultiplier() * other.getMultiplier()); + } + + /** + * Raises this prefix to an exponent. + * + * @param exponent + * exponent to raise to + * @return result of exponentiation. + * @since 2019-04-13 + * @since v0.2.0 + */ + public UnitPrefix toExponent(final double exponent) { + return valueOf(Math.pow(this.getMultiplier(), exponent)); + } + + /** + * @return a string describing the prefix and its multiplier + */ + @Override + public String toString() { + if (this.primaryName.isPresent()) + return String.format("%s (\u00D7 %s)", this.primaryName.get(), this.multiplier); + else if (this.symbol.isPresent()) + return String.format("%s (\u00D7 %s)", this.symbol.get(), this.multiplier); + else + return String.format("Unit Prefix (\u00D7 %s)", this.multiplier); + } + + /** + * @param ns + * name(s) and symbol to use + * @return copy of this prefix with provided name(s) and symbol + * @since 2019-11-26 + * @throws NullPointerException + * if ns is null + */ + public UnitPrefix withName(final NameSymbol ns) { + return valueOf(this.multiplier, ns); + } +} diff --git a/src/main/java/org/unitConverter/unit/UnitValue.java b/src/main/java/org/unitConverter/unit/UnitValue.java new file mode 100644 index 0000000..c138332 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/UnitValue.java @@ -0,0 +1,172 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.Objects; +import java.util.Optional; + +/** + * A value expressed in a unit. + * + * Unless otherwise indicated, all methods in this class throw a + * {@code NullPointerException} when an argument is null. + * + * @author Adrien Hopkins + * @since 2020-07-26 + */ +public final class UnitValue { + /** + * Creates a {@code UnitValue} from a unit and the associated value. + * + * @param unit unit to use + * @param value value to use + * @return {@code UnitValue} instance + */ + public static UnitValue of(Unit unit, double value) { + return new UnitValue( + Objects.requireNonNull(unit, "unit must not be null"), value); + } + + private final Unit unit; + private final double value; + + /** + * @param unit the unit being used + * @param value the value being represented + */ + private UnitValue(Unit unit, Double value) { + this.unit = unit; + this.value = value; + } + + /** + * @return true if this value can be converted to {@code other}. + * @since 2020-10-01 + */ + public final boolean canConvertTo(Unit other) { + return this.unit.canConvertTo(other); + } + + /** + * @return true if this value can be converted to {@code other}. + * @since 2020-10-01 + */ + public final boolean canConvertTo(Unitlike other) { + return this.unit.canConvertTo(other); + } + + /** + * Returns a UnitlikeValue that represents the same value expressed in a + * different unitlike form. + * + * @param other new unit to express value in + * @return value expressed in {@code other} + */ + public final , W> UnitlikeValue convertTo( + U other) { + return UnitlikeValue.of(other, + this.unit.convertTo(other, this.getValue())); + } + + /** + * Returns a UnitValue that represents the same value expressed in a + * different unit + * + * @param other new unit to express value in + * @return value expressed in {@code other} + */ + public final UnitValue convertTo(Unit other) { + return UnitValue.of(other, + this.getUnit().convertTo(other, this.getValue())); + } + + /** + * Returns this unit value represented as a {@code LinearUnitValue} with this + * unit's base unit as the base. + * + * @param ns name and symbol for the base unit, use NameSymbol.EMPTY if not + * needed. + * @since 2020-09-29 + */ + public final LinearUnitValue convertToBase(NameSymbol ns) { + final LinearUnit base = LinearUnit.getBase(this.unit).withName(ns); + return this.convertToLinear(base); + } + + /** + * @return a {@code LinearUnitValue} that is equivalent to this value. It + * will have zero uncertainty. + * @since 2020-09-29 + */ + public final LinearUnitValue convertToLinear(LinearUnit other) { + return LinearUnitValue.getExact(other, + this.getUnit().convertTo(other, this.getValue())); + } + + /** + * Returns true if this and obj represent the same value, regardless of + * whether or not they are expressed in the same unit. So (1000 m).equals(1 + * km) returns true. + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof UnitValue)) + return false; + final UnitValue other = (UnitValue) obj; + return Objects.equals(this.getUnit().getBase(), other.getUnit().getBase()) + && Double.doubleToLongBits( + this.getUnit().convertToBase(this.getValue())) == Double + .doubleToLongBits( + other.getUnit().convertToBase(other.getValue())); + } + + /** + * @return the unit + * @since 2020-09-29 + */ + public final Unit getUnit() { + return this.unit; + } + + /** + * @return the value + * @since 2020-09-29 + */ + public final double getValue() { + return this.value; + } + + @Override + public int hashCode() { + return Objects.hash(this.getUnit().getBase(), + this.getUnit().convertFromBase(this.getValue())); + } + + @Override + public String toString() { + final Optional primaryName = this.getUnit().getPrimaryName(); + final Optional symbol = this.getUnit().getSymbol(); + if (primaryName.isEmpty() && symbol.isEmpty()) { + final double baseValue = this.getUnit().convertToBase(this.getValue()); + return String.format("%s unnamed unit (= %s %s)", this.getValue(), + baseValue, this.getUnit().getBase()); + } else { + final String unitName = symbol.orElse(primaryName.get()); + return this.getValue() + " " + unitName; + } + } +} diff --git a/src/main/java/org/unitConverter/unit/Unitlike.java b/src/main/java/org/unitConverter/unit/Unitlike.java new file mode 100644 index 0000000..8077771 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/Unitlike.java @@ -0,0 +1,260 @@ +/** + * Copyright (C) 2020 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.DoubleFunction; +import java.util.function.ToDoubleFunction; + +import org.unitConverter.math.ObjectProduct; + +/** + * An object that can convert a value between multiple forms (instances of the + * object); like a unit but the "converted value" can be any type. + * + * @since 2020-09-07 + */ +public abstract class Unitlike implements Nameable { + /** + * Returns a unitlike form from its base and the functions it uses to convert + * to and from its base. + * + * @param base unitlike form's base + * @param converterFrom function that accepts a value expressed in the + * unitlike form's base and returns that value expressed + * in this unitlike form. + * @param converterTo function that accepts a value expressed in the + * unitlike form and returns that value expressed in the + * unit's base. + * @return a unitlike form that uses the provided functions to convert. + * @since 2020-09-07 + * @throws NullPointerException if any argument is null + */ + public static final Unitlike fromConversionFunctions( + final ObjectProduct base, + final DoubleFunction converterFrom, + final ToDoubleFunction converterTo) { + return new FunctionalUnitlike<>(base, NameSymbol.EMPTY, converterFrom, + converterTo); + } + + /** + * Returns a unitlike form from its base and the functions it uses to convert + * to and from its base. + * + * @param base unitlike form's base + * @param converterFrom function that accepts a value expressed in the + * unitlike form's base and returns that value expressed + * in this unitlike form. + * @param converterTo function that accepts a value expressed in the + * unitlike form and returns that value expressed in the + * unit's base. + * @param ns names and symbol of unit + * @return a unitlike form that uses the provided functions to convert. + * @since 2020-09-07 + * @throws NullPointerException if any argument is null + */ + public static final Unitlike fromConversionFunctions( + final ObjectProduct base, + final DoubleFunction converterFrom, + final ToDoubleFunction converterTo, final NameSymbol ns) { + return new FunctionalUnitlike<>(base, ns, converterFrom, converterTo); + } + + /** + * The combination of units that this unit is based on. + * + * @since 2019-10-16 + */ + private final ObjectProduct unitBase; + + /** + * This unit's name(s) and symbol + * + * @since 2020-09-07 + */ + private final NameSymbol nameSymbol; + + /** + * Cache storing the result of getDimension() + * + * @since 2019-10-16 + */ + private transient ObjectProduct dimension = null; + + /** + * @param unitBase + * @since 2020-09-07 + */ + protected Unitlike(ObjectProduct unitBase, NameSymbol ns) { + this.unitBase = Objects.requireNonNull(unitBase, + "unitBase may not be null"); + this.nameSymbol = Objects.requireNonNull(ns, "ns may not be null"); + } + + /** + * Checks if a value expressed in this unitlike form can be converted to a + * value expressed in {@code other} + * + * @param other unit or unitlike form to test with + * @return true if they are compatible + * @since 2019-01-13 + * @since v0.1.0 + * @throws NullPointerException if other is null + */ + public final boolean canConvertTo(final Unit other) { + Objects.requireNonNull(other, "other must not be null."); + return Objects.equals(this.getBase(), other.getBase()); + } + + /** + * Checks if a value expressed in this unitlike form can be converted to a + * value expressed in {@code other} + * + * @param other unit or unitlike form to test with + * @return true if they are compatible + * @since 2019-01-13 + * @since v0.1.0 + * @throws NullPointerException if other is null + */ + public final boolean canConvertTo(final Unitlike other) { + Objects.requireNonNull(other, "other must not be null."); + return Objects.equals(this.getBase(), other.getBase()); + } + + protected abstract V convertFromBase(double value); + + /** + * Converts a value expressed in this unitlike form to a value expressed in + * {@code other}. + * + * @implSpec If conversion is possible, this implementation returns + * {@code other.convertFromBase(this.convertToBase(value))}. + * Therefore, overriding either of those methods will change the + * output of this method. + * + * @param other unit to convert to + * @param value value to convert + * @return converted value + * @since 2019-05-22 + * @throws IllegalArgumentException if {@code other} is incompatible for + * conversion with this unitlike form (as + * tested by {@link Unit#canConvertTo}). + * @throws NullPointerException if other is null + */ + public final double convertTo(final Unit other, final V value) { + Objects.requireNonNull(other, "other must not be null."); + if (this.canConvertTo(other)) + return other.convertFromBase(this.convertToBase(value)); + else + throw new IllegalArgumentException( + String.format("Cannot convert from %s to %s.", this, other)); + } + + /** + * Converts a value expressed in this unitlike form to a value expressed in + * {@code other}. + * + * @implSpec If conversion is possible, this implementation returns + * {@code other.convertFromBase(this.convertToBase(value))}. + * Therefore, overriding either of those methods will change the + * output of this method. + * + * @param other unitlike form to convert to + * @param value value to convert + * @param type of value to convert to + * @return converted value + * @since 2020-09-07 + * @throws IllegalArgumentException if {@code other} is incompatible for + * conversion with this unitlike form (as + * tested by {@link Unit#canConvertTo}). + * @throws NullPointerException if other is null + */ + public final W convertTo(final Unitlike other, final V value) { + Objects.requireNonNull(other, "other must not be null."); + if (this.canConvertTo(other)) + return other.convertFromBase(this.convertToBase(value)); + else + throw new IllegalArgumentException( + String.format("Cannot convert from %s to %s.", this, other)); + } + + protected abstract double convertToBase(V value); + + /** + * @return combination of units that this unit is based on + * @since 2018-12-22 + * @since v0.1.0 + */ + public final ObjectProduct getBase() { + return this.unitBase; + } + + /** + * @return dimension measured by this unit + * @since 2018-12-22 + * @since v0.1.0 + */ + public final ObjectProduct getDimension() { + if (this.dimension == null) { + final Map mapping = this.unitBase.exponentMap(); + final Map dimensionMap = new HashMap<>(); + + for (final BaseUnit key : mapping.keySet()) { + dimensionMap.put(key.getBaseDimension(), mapping.get(key)); + } + + this.dimension = ObjectProduct.fromExponentMapping(dimensionMap); + } + return this.dimension; + } + + /** + * @return the nameSymbol + * @since 2020-09-07 + */ + @Override + public final NameSymbol getNameSymbol() { + return this.nameSymbol; + } + + @Override + public String toString() { + return this.getPrimaryName().orElse("Unnamed unitlike form") + + (this.getSymbol().isPresent() + ? String.format(" (%s)", this.getSymbol().get()) + : "") + + ", derived from " + + this.getBase().toString(u -> u.getSymbol().get()) + + (this.getOtherNames().isEmpty() ? "" + : ", also called " + String.join(", ", this.getOtherNames())); + } + + /** + * @param ns name(s) and symbol to use + * @return a copy of this unitlike form with provided name(s) and symbol + * @since 2020-09-07 + * @throws NullPointerException if ns is null + */ + public Unitlike withName(final NameSymbol ns) { + return fromConversionFunctions(this.getBase(), this::convertFromBase, + this::convertToBase, + Objects.requireNonNull(ns, "ns must not be null.")); + } +} diff --git a/src/main/java/org/unitConverter/unit/UnitlikeValue.java b/src/main/java/org/unitConverter/unit/UnitlikeValue.java new file mode 100644 index 0000000..79201c4 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/UnitlikeValue.java @@ -0,0 +1,174 @@ +/** + * Copyright (C) 2020 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import java.util.Optional; + +/** + * + * @since 2020-09-07 + */ +final class UnitlikeValue, V> { + /** + * Gets a {@code UnitlikeValue}. + * + * @since 2020-10-02 + */ + public static , V> UnitlikeValue of(T unitlike, + V value) { + return new UnitlikeValue<>(unitlike, value); + } + + private final T unitlike; + private final V value; + + /** + * @param unitlike + * @param value + * @since 2020-09-07 + */ + private UnitlikeValue(T unitlike, V value) { + this.unitlike = unitlike; + this.value = value; + } + + /** + * @return true if this value can be converted to {@code other}. + * @since 2020-10-01 + */ + public final boolean canConvertTo(Unit other) { + return this.unitlike.canConvertTo(other); + } + + /** + * @return true if this value can be converted to {@code other}. + * @since 2020-10-01 + */ + public final boolean canConvertTo(Unitlike other) { + return this.unitlike.canConvertTo(other); + } + + /** + * Returns a UnitlikeValue that represents the same value expressed in a + * different unitlike form. + * + * @param other new unit to express value in + * @return value expressed in {@code other} + */ + public final , W> UnitlikeValue convertTo( + U other) { + return UnitlikeValue.of(other, + this.unitlike.convertTo(other, this.getValue())); + } + + /** + * Returns a UnitValue that represents the same value expressed in a + * different unit + * + * @param other new unit to express value in + * @return value expressed in {@code other} + */ + public final UnitValue convertTo(Unit other) { + return UnitValue.of(other, + this.unitlike.convertTo(other, this.getValue())); + } + + /** + * Returns this unit value represented as a {@code LinearUnitValue} with this + * unit's base unit as the base. + * + * @param ns name and symbol for the base unit, use NameSymbol.EMPTY if not + * needed. + * @since 2020-09-29 + */ + public final LinearUnitValue convertToBase(NameSymbol ns) { + final LinearUnit base = LinearUnit.getBase(this.unitlike).withName(ns); + return this.convertToLinear(base); + } + + /** + * @return a {@code LinearUnitValue} that is equivalent to this value. It + * will have zero uncertainty. + * @since 2020-09-29 + */ + public final LinearUnitValue convertToLinear(LinearUnit other) { + return LinearUnitValue.getExact(other, + this.getUnitlike().convertTo(other, this.getValue())); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!(obj instanceof UnitlikeValue)) + return false; + final UnitlikeValue other = (UnitlikeValue) obj; + if (this.getUnitlike() == null) { + if (other.getUnitlike() != null) + return false; + } else if (!this.getUnitlike().equals(other.getUnitlike())) + return false; + if (this.getValue() == null) { + if (other.getValue() != null) + return false; + } else if (!this.getValue().equals(other.getValue())) + return false; + return true; + } + + /** + * @return the unitlike + * @since 2020-09-29 + */ + public final Unitlike getUnitlike() { + return this.unitlike; + } + + /** + * @return the value + * @since 2020-09-29 + */ + public final V getValue() { + return this.value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + (this.getUnitlike() == null ? 0 : this.getUnitlike().hashCode()); + result = prime * result + + (this.getValue() == null ? 0 : this.getValue().hashCode()); + return result; + } + + @Override + public String toString() { + final Optional primaryName = this.getUnitlike().getPrimaryName(); + final Optional symbol = this.getUnitlike().getSymbol(); + if (primaryName.isEmpty() && symbol.isEmpty()) { + final double baseValue = this.getUnitlike() + .convertToBase(this.getValue()); + return String.format("%s unnamed unit (= %s %s)", this.getValue(), + baseValue, this.getUnitlike().getBase()); + } else { + final String unitName = symbol.orElse(primaryName.get()); + return this.getValue() + " " + unitName; + } + } +} diff --git a/src/main/java/org/unitConverter/unit/package-info.java b/src/main/java/org/unitConverter/unit/package-info.java new file mode 100644 index 0000000..2f0e097 --- /dev/null +++ b/src/main/java/org/unitConverter/unit/package-info.java @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +/** + * Everything to do with the units that make up Unit Converter. + * + * @author Adrien Hopkins + * @since 2019-10-16 + * @since v0.1.0 + */ +package org.unitConverter.unit; \ No newline at end of file diff --git a/src/main/resources/about.txt b/src/main/resources/about.txt new file mode 100644 index 0000000..1bad9e8 --- /dev/null +++ b/src/main/resources/about.txt @@ -0,0 +1,12 @@ +About Unit Converter v0.2.0 + +Copyright Notice: + +Unit Converter Copyright (C) 2018-2021 Adrien Hopkins +This program comes with ABSOLUTELY NO WARRANTY; +for details read the LICENSE file, section 15 + +This is free software, and you are welcome to redistribute +it under certain conditions; for details go to + +or read the LICENSE file. \ No newline at end of file diff --git a/src/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java b/src/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java deleted file mode 100644 index bdc3a2e..0000000 --- a/src/org/unitConverter/converterGUI/DefaultPrefixRepetitionRule.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @since 2020-08-26 - */ -package org.unitConverter.converterGUI; - -import java.util.List; -import java.util.function.Predicate; - -import org.unitConverter.unit.SI; -import org.unitConverter.unit.UnitPrefix; - -/** - * A rule that specifies whether prefix repetition is allowed - * - * @since 2020-08-26 - */ -enum DefaultPrefixRepetitionRule implements Predicate> { - NO_REPETITION { - @Override - public boolean test(List prefixes) { - return prefixes.size() <= 1; - } - }, - NO_RESTRICTION { - @Override - public boolean test(List prefixes) { - return true; - } - }, - /** - * You are allowed to have any number of Yotta/Yocto followed by possibly one - * Kilo-Zetta/Milli-Zepto followed by possibly one Deca/Hecto. Same for - * reducing prefixes, don't mix magnifying and reducing. Non-metric - * (including binary) prefixes can't be repeated. - */ - COMPLEX_REPETITION { - @Override - public boolean test(List prefixes) { - // determine whether we are magnifying or reducing - final boolean magnifying; - if (prefixes.isEmpty()) - return true; - else if (prefixes.get(0).getMultiplier() > 1) { - magnifying = true; - } else { - magnifying = false; - } - - // if the first prefix is non-metric (including binary prefixes), - // assume we are using non-metric prefixes - // non-metric prefixes are allowed, but can't be repeated. - if (!SI.DECIMAL_PREFIXES.contains(prefixes.get(0))) - return NO_REPETITION.test(prefixes); - - int part = 0; // 0=yotta/yoctos, 1=kilo-zetta/milli-zepto, - // 2=deka,hecto,deci,centi - - for (final UnitPrefix prefix : prefixes) { - // check that the current prefix is metric and appropriately - // magnifying/reducing - if (!SI.DECIMAL_PREFIXES.contains(prefix)) - return false; - if (magnifying != prefix.getMultiplier() > 1) - return false; - - // check if the current prefix is correct - // since part is set *after* this check, part designates the state - // of the *previous* prefix - switch (part) { - case 0: - // do nothing, any prefix is valid after a yotta - break; - case 1: - // after a kilo-zetta, only deka/hecto are valid - if (SI.THOUSAND_PREFIXES.contains(prefix)) - return false; - break; - case 2: - // deka/hecto must be the last prefix, so this is always invalid - return false; - } - - // set part - if (SI.YOTTA.equals(prefix) || SI.YOCTO.equals(prefix)) { - part = 0; - } else if (SI.THOUSAND_PREFIXES.contains(prefix)) { - part = 1; - } else { - part = 2; - } - } - return true; - } - }; -} diff --git a/src/org/unitConverter/converterGUI/DelegateListModel.java b/src/org/unitConverter/converterGUI/DelegateListModel.java deleted file mode 100644 index b80f63d..0000000 --- a/src/org/unitConverter/converterGUI/DelegateListModel.java +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Copyright (C) 2018 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.converterGUI; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; - -import javax.swing.AbstractListModel; - -/** - * A list model that delegates to a list. - *

    - * It is recommended to use the delegate methods in DelegateListModel instead of the delegated list's methods because - * the delegate methods handle updating the list. - *

    - * - * @author Adrien Hopkins - * @since 2019-01-14 - * @since v0.1.0 - */ -final class DelegateListModel extends AbstractListModel implements List { - /** - * @since 2019-01-14 - * @since v0.1.0 - */ - private static final long serialVersionUID = 8985494428224810045L; - - /** - * The list that this model is a delegate to. - * - * @since 2019-01-14 - * @since v0.1.0 - */ - private final List delegate; - - /** - * Creates an empty {@code DelegateListModel}. - * - * @since 2019-04-13 - */ - public DelegateListModel() { - this(new ArrayList<>()); - } - - /** - * Creates the {@code DelegateListModel}. - * - * @param delegate - * list to delegate - * @since 2019-01-14 - * @since v0.1.0 - */ - public DelegateListModel(final List delegate) { - this.delegate = delegate; - } - - @Override - public boolean add(final E element) { - final int index = this.delegate.size(); - final boolean success = this.delegate.add(element); - this.fireIntervalAdded(this, index, index); - return success; - } - - @Override - public void add(final int index, final E element) { - this.delegate.add(index, element); - this.fireIntervalAdded(this, index, index); - } - - @Override - public boolean addAll(final Collection c) { - boolean changed = false; - for (final E e : c) { - if (this.add(e)) { - changed = true; - } - } - return changed; - } - - @Override - public boolean addAll(final int index, final Collection c) { - for (final E e : c) { - this.add(index, e); - } - return !c.isEmpty(); // Since this is a list, it will always change if c has elements. - } - - @Override - public void clear() { - final int oldSize = this.delegate.size(); - this.delegate.clear(); - if (oldSize >= 1) { - this.fireIntervalRemoved(this, 0, oldSize - 1); - } - } - - @Override - public boolean contains(final Object elem) { - return this.delegate.contains(elem); - } - - @Override - public boolean containsAll(final Collection c) { - for (final Object e : c) { - if (!c.contains(e)) - return false; - } - return true; - } - - @Override - public E get(final int index) { - return this.delegate.get(index); - } - - @Override - public E getElementAt(final int index) { - return this.delegate.get(index); - } - - @Override - public int getSize() { - return this.delegate.size(); - } - - @Override - public int indexOf(final Object elem) { - return this.delegate.indexOf(elem); - } - - @Override - public boolean isEmpty() { - return this.delegate.isEmpty(); - } - - @Override - public Iterator iterator() { - return this.delegate.iterator(); - } - - @Override - public int lastIndexOf(final Object elem) { - return this.delegate.lastIndexOf(elem); - } - - @Override - public ListIterator listIterator() { - return this.delegate.listIterator(); - } - - @Override - public ListIterator listIterator(final int index) { - return this.delegate.listIterator(index); - } - - @Override - public E remove(final int index) { - final E returnValue = this.delegate.get(index); - this.delegate.remove(index); - this.fireIntervalRemoved(this, index, index); - return returnValue; - } - - @Override - public boolean remove(final Object o) { - final int index = this.delegate.indexOf(o); - final boolean returnValue = this.delegate.remove(o); - this.fireIntervalRemoved(this, index, index); - return returnValue; - } - - @Override - public boolean removeAll(final Collection c) { - boolean changed = false; - for (final Object e : c) { - if (this.remove(e)) { - changed = true; - } - } - return changed; - } - - @Override - public boolean retainAll(final Collection c) { - final int oldSize = this.size(); - final boolean returnValue = this.delegate.retainAll(c); - this.fireIntervalRemoved(this, this.size(), oldSize - 1); - return returnValue; - } - - @Override - public E set(final int index, final E element) { - final E returnValue = this.delegate.get(index); - this.delegate.set(index, element); - this.fireContentsChanged(this, index, index); - return returnValue; - } - - @Override - public int size() { - return this.delegate.size(); - } - - @Override - public List subList(final int fromIndex, final int toIndex) { - return this.delegate.subList(fromIndex, toIndex); - } - - @Override - public Object[] toArray() { - return this.delegate.toArray(); - } - - @Override - public T[] toArray(final T[] a) { - return this.delegate.toArray(a); - } - - @Override - public String toString() { - return this.delegate.toString(); - } -} diff --git a/src/org/unitConverter/converterGUI/FilterComparator.java b/src/org/unitConverter/converterGUI/FilterComparator.java deleted file mode 100644 index 7b17bfc..0000000 --- a/src/org/unitConverter/converterGUI/FilterComparator.java +++ /dev/null @@ -1,129 +0,0 @@ -/** - * Copyright (C) 2018 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.converterGUI; - -import java.util.Comparator; -import java.util.Objects; - -/** - * A comparator that compares strings using a filter. - * - * @author Adrien Hopkins - * @since 2019-01-15 - * @since v0.1.0 - */ -final class FilterComparator implements Comparator { - /** - * The filter that the comparator is filtered by. - * - * @since 2019-01-15 - * @since v0.1.0 - */ - private final String filter; - /** - * The comparator to use if the arguments are otherwise equal. - * - * @since 2019-01-15 - * @since v0.1.0 - */ - private final Comparator comparator; - /** - * Whether or not the comparison is case-sensitive. - * - * @since 2019-04-14 - * @since v0.2.0 - */ - private final boolean caseSensitive; - - /** - * Creates the {@code FilterComparator}. - * - * @param filter - * @since 2019-01-15 - * @since v0.1.0 - */ - public FilterComparator(final String filter) { - this(filter, null); - } - - /** - * Creates the {@code FilterComparator}. - * - * @param filter - * string to filter by - * @param comparator - * comparator to fall back to if all else fails, null is compareTo. - * @throws NullPointerException - * if filter is null - * @since 2019-01-15 - * @since v0.1.0 - */ - public FilterComparator(final String filter, final Comparator comparator) { - this(filter, comparator, false); - } - - /** - * Creates the {@code FilterComparator}. - * - * @param filter - * string to filter by - * @param comparator - * comparator to fall back to if all else fails, null is compareTo. - * @param caseSensitive - * whether or not the comparator is case-sensitive - * @throws NullPointerException - * if filter is null - * @since 2019-04-14 - * @since v0.2.0 - */ - public FilterComparator(final String filter, final Comparator comparator, final boolean caseSensitive) { - this.filter = Objects.requireNonNull(filter, "filter must not be null."); - this.comparator = comparator; - this.caseSensitive = caseSensitive; - } - - @Override - public int compare(final String arg0, final String arg1) { - // if this is case insensitive, make them lowercase - final String str0, str1; - if (this.caseSensitive) { - str0 = arg0; - str1 = arg1; - } else { - str0 = arg0.toLowerCase(); - str1 = arg1.toLowerCase(); - } - - // elements that start with the filter always go first - if (str0.startsWith(this.filter) && !str1.startsWith(this.filter)) - return -1; - else if (!str0.startsWith(this.filter) && str1.startsWith(this.filter)) - return 1; - - // elements that contain the filter but don't start with them go next - if (str0.contains(this.filter) && !str1.contains(this.filter)) - return -1; - else if (!str0.contains(this.filter) && !str1.contains(this.filter)) - return 1; - - // other elements go last - if (this.comparator == null) - return str0.compareTo(str1); - else - return this.comparator.compare(str0, str1); - } -} diff --git a/src/org/unitConverter/converterGUI/GridBagBuilder.java b/src/org/unitConverter/converterGUI/GridBagBuilder.java deleted file mode 100644 index f1229b2..0000000 --- a/src/org/unitConverter/converterGUI/GridBagBuilder.java +++ /dev/null @@ -1,479 +0,0 @@ -/** - * Copyright (C) 2018 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.converterGUI; - -import java.awt.GridBagConstraints; -import java.awt.Insets; - -/** - * A builder for Java's {@link java.awt.GridBagConstraints} class. - * - * @author Adrien Hopkins - * @since 2018-11-30 - * @since v0.1.0 - */ -final class GridBagBuilder { - /** - * The built {@code GridBagConstraints}'s {@code gridx} property. - *

    - * Specifies the cell containing the leading edge of the component's display area, where the first cell in a row has - * gridx=0. The leading edge of a component's display area is its left edge for a horizontal, - * left-to-right container and its right edge for a horizontal, right-to-left container. The value - * RELATIVE specifies that the component be placed immediately following the component that was added - * to the container just before this component was added. - *

    - * The default value is RELATIVE. gridx should be a non-negative value. - * - * @serial - * @see #clone() - * @see java.awt.GridBagConstraints#gridy - * @see java.awt.ComponentOrientation - */ - private final int gridx; - - /** - * The built {@code GridBagConstraints}'s {@code gridy} property. - *

    - * Specifies the cell at the top of the component's display area, where the topmost cell has gridy=0. - * The value RELATIVE specifies that the component be placed just below the component that was added to - * the container just before this component was added. - *

    - * The default value is RELATIVE. gridy should be a non-negative value. - * - * @serial - * @see #clone() - * @see java.awt.GridBagConstraints#gridx - */ - private final int gridy; - - /** - * The built {@code GridBagConstraints}'s {@code gridwidth} property. - *

    - * Specifies the number of cells in a row for the component's display area. - *

    - * Use REMAINDER to specify that the component's display area will be from gridx to the - * last cell in the row. Use RELATIVE to specify that the component's display area will be from - * gridx to the next to the last one in its row. - *

    - * gridwidth should be non-negative and the default value is 1. - * - * @serial - * @see #clone() - * @see java.awt.GridBagConstraints#gridheight - */ - private final int gridwidth; - - /** - * The built {@code GridBagConstraints}'s {@code gridheight} property. - *

    - * Specifies the number of cells in a column for the component's display area. - *

    - * Use REMAINDER to specify that the component's display area will be from gridy to the - * last cell in the column. Use RELATIVE to specify that the component's display area will be from - * gridy to the next to the last one in its column. - *

    - * gridheight should be a non-negative value and the default value is 1. - * - * @serial - * @see #clone() - * @see java.awt.GridBagConstraints#gridwidth - */ - private final int gridheight; - - /** - * The built {@code GridBagConstraints}'s {@code weightx} property. - *

    - * Specifies how to distribute extra horizontal space. - *

    - * The grid bag layout manager calculates the weight of a column to be the maximum weightx of all the - * components in a column. If the resulting layout is smaller horizontally than the area it needs to fill, the extra - * space is distributed to each column in proportion to its weight. A column that has a weight of zero receives no - * extra space. - *

    - * If all the weights are zero, all the extra space appears between the grids of the cell and the left and right - * edges. - *

    - * The default value of this field is 0. weightx should be a non-negative value. - * - * @serial - * @see #clone() - * @see java.awt.GridBagConstraints#weighty - */ - private double weightx; - - /** - * The built {@code GridBagConstraints}'s {@code weighty} property. - *

    - * Specifies how to distribute extra vertical space. - *

    - * The grid bag layout manager calculates the weight of a row to be the maximum weighty of all the - * components in a row. If the resulting layout is smaller vertically than the area it needs to fill, the extra - * space is distributed to each row in proportion to its weight. A row that has a weight of zero receives no extra - * space. - *

    - * If all the weights are zero, all the extra space appears between the grids of the cell and the top and bottom - * edges. - *

    - * The default value of this field is 0. weighty should be a non-negative value. - * - * @serial - * @see #clone() - * @see java.awt.GridBagConstraints#weightx - */ - private double weighty; - - /** - * The built {@code GridBagConstraints}'s {@code anchor} property. - *

    - * This field is used when the component is smaller than its display area. It determines where, within the display - * area, to place the component. - *

    - * There are three kinds of possible values: orientation relative, baseline relative and absolute. Orientation - * relative values are interpreted relative to the container's component orientation property, baseline relative - * values are interpreted relative to the baseline and absolute values are not. The absolute values are: - * CENTER, NORTH, NORTHEAST, EAST, SOUTHEAST, - * SOUTH, SOUTHWEST, WEST, and NORTHWEST. The orientation - * relative values are: PAGE_START, PAGE_END, LINE_START, - * LINE_END, FIRST_LINE_START, FIRST_LINE_END, LAST_LINE_START - * and LAST_LINE_END. The baseline relative values are: BASELINE, - * BASELINE_LEADING, BASELINE_TRAILING, ABOVE_BASELINE, - * ABOVE_BASELINE_LEADING, ABOVE_BASELINE_TRAILING, BELOW_BASELINE, - * BELOW_BASELINE_LEADING, and BELOW_BASELINE_TRAILING. The default value is - * CENTER. - * - * @serial - * @see #clone() - * @see java.awt.ComponentOrientation - */ - private int anchor; - - /** - * The built {@code GridBagConstraints}'s {@code fill} property. - *

    - * This field is used when the component's display area is larger than the component's requested size. It determines - * whether to resize the component, and if so, how. - *

    - * The following values are valid for fill: - * - *

      - *
    • NONE: Do not resize the component. - *
    • HORIZONTAL: Make the component wide enough to fill its display area horizontally, but do not - * change its height. - *
    • VERTICAL: Make the component tall enough to fill its display area vertically, but do not change - * its width. - *
    • BOTH: Make the component fill its display area entirely. - *
    - *

    - * The default value is NONE. - * - * @serial - * @see #clone() - */ - private int fill; - - /** - * The built {@code GridBagConstraints}'s {@code insets} property. - *

    - * This field specifies the external padding of the component, the minimum amount of space between the component and - * the edges of its display area. - *

    - * The default value is new Insets(0, 0, 0, 0). - * - * @serial - * @see #clone() - */ - private Insets insets; - - /** - * The built {@code GridBagConstraints}'s {@code ipadx} property. - *

    - * This field specifies the internal padding of the component, how much space to add to the minimum width of the - * component. The width of the component is at least its minimum width plus ipadx pixels. - *

    - * The default value is 0. - * - * @serial - * @see #clone() - * @see java.awt.GridBagConstraints#ipady - */ - private int ipadx; - - /** - * The built {@code GridBagConstraints}'s {@code ipady} property. - *

    - * This field specifies the internal padding, that is, how much space to add to the minimum height of the component. - * The height of the component is at least its minimum height plus ipady pixels. - *

    - * The default value is 0. - * - * @serial - * @see #clone() - * @see java.awt.GridBagConstraints#ipadx - */ - private int ipady; - - /** - * @param gridx - * x position - * @param gridy - * y position - * @since 2018-11-30 - * @since v0.1.0 - */ - public GridBagBuilder(final int gridx, final int gridy) { - this(gridx, gridy, 1, 1); - } - - /** - * @param gridx - * x position - * @param gridy - * y position - * @param gridwidth - * number of cells occupied horizontally - * @param gridheight - * number of cells occupied vertically - * @since 2018-11-30 - * @since v0.1.0 - */ - public GridBagBuilder(final int gridx, final int gridy, final int gridwidth, final int gridheight) { - this(gridx, gridy, gridwidth, gridheight, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, - new Insets(0, 0, 0, 0), 0, 0); - } - - /** - * @param gridx - * x position - * @param gridy - * y position - * @param gridwidth - * number of cells occupied horizontally - * @param gridheight - * number of cells occupied vertically - * @param weightx - * @param weighty - * @param anchor - * @param fill - * @param insets - * @param ipadx - * @param ipady - * @since 2018-11-30 - * @since v0.1.0 - */ - private GridBagBuilder(final int gridx, final int gridy, final int gridwidth, final int gridheight, - final double weightx, final double weighty, final int anchor, final int fill, final Insets insets, - final int ipadx, final int ipady) { - super(); - this.gridx = gridx; - this.gridy = gridy; - this.gridwidth = gridwidth; - this.gridheight = gridheight; - this.weightx = weightx; - this.weighty = weighty; - this.anchor = anchor; - this.fill = fill; - this.insets = (Insets) insets.clone(); - this.ipadx = ipadx; - this.ipady = ipady; - } - - /** - * @return {@code GridBagConstraints} created by this builder - * @since 2018-11-30 - * @since v0.1.0 - */ - public GridBagConstraints build() { - return new GridBagConstraints(this.gridx, this.gridy, this.gridwidth, this.gridheight, this.weightx, - this.weighty, this.anchor, this.fill, this.insets, this.ipadx, this.ipady); - } - - /** - * @return anchor - * @since 2018-11-30 - * @since v0.1.0 - */ - public int getAnchor() { - return this.anchor; - } - - /** - * @return fill - * @since 2018-11-30 - * @since v0.1.0 - */ - public int getFill() { - return this.fill; - } - - /** - * @return gridheight - * @since 2018-11-30 - * @since v0.1.0 - */ - public int getGridheight() { - return this.gridheight; - } - - /** - * @return gridwidth - * @since 2018-11-30 - * @since v0.1.0 - */ - public int getGridwidth() { - return this.gridwidth; - } - - /** - * @return gridx - * @since 2018-11-30 - * @since v0.1.0 - */ - public int getGridx() { - return this.gridx; - } - - /** - * @return gridy - * @since 2018-11-30 - * @since v0.1.0 - */ - public int getGridy() { - return this.gridy; - } - - /** - * @return insets - * @since 2018-11-30 - * @since v0.1.0 - */ - public Insets getInsets() { - return this.insets; - } - - /** - * @return ipadx - * @since 2018-11-30 - * @since v0.1.0 - */ - public int getIpadx() { - return this.ipadx; - } - - /** - * @return ipady - * @since 2018-11-30 - * @since v0.1.0 - */ - public int getIpady() { - return this.ipady; - } - - /** - * @return weightx - * @since 2018-11-30 - * @since v0.1.0 - */ - public double getWeightx() { - return this.weightx; - } - - /** - * @return weighty - * @since 2018-11-30 - * @since v0.1.0 - */ - public double getWeighty() { - return this.weighty; - } - - /** - * @param anchor - * anchor to set - * @since 2018-11-30 - * @since v0.1.0 - */ - public GridBagBuilder setAnchor(final int anchor) { - this.anchor = anchor; - return this; - } - - /** - * @param fill - * fill to set - * @since 2018-11-30 - * @since v0.1.0 - */ - public GridBagBuilder setFill(final int fill) { - this.fill = fill; - return this; - } - - /** - * @param insets - * insets to set - * @since 2018-11-30 - * @since v0.1.0 - */ - public GridBagBuilder setInsets(final Insets insets) { - this.insets = insets; - return this; - } - - /** - * @param ipadx - * ipadx to set - * @since 2018-11-30 - * @since v0.1.0 - */ - public GridBagBuilder setIpadx(final int ipadx) { - this.ipadx = ipadx; - return this; - } - - /** - * @param ipady - * ipady to set - * @since 2018-11-30 - * @since v0.1.0 - */ - public GridBagBuilder setIpady(final int ipady) { - this.ipady = ipady; - return this; - } - - /** - * @param weightx - * weightx to set - * @since 2018-11-30 - * @since v0.1.0 - */ - public GridBagBuilder setWeightx(final double weightx) { - this.weightx = weightx; - return this; - } - - /** - * @param weighty - * weighty to set - * @since 2018-11-30 - * @since v0.1.0 - */ - public GridBagBuilder setWeighty(final double weighty) { - this.weighty = weighty; - return this; - } -} diff --git a/src/org/unitConverter/converterGUI/MutablePredicate.java b/src/org/unitConverter/converterGUI/MutablePredicate.java deleted file mode 100644 index e15b3cd..0000000 --- a/src/org/unitConverter/converterGUI/MutablePredicate.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.converterGUI; - -import java.util.function.Predicate; - -/** - * A container for a predicate, which can be changed later. - * - * @author Adrien Hopkins - * @since 2019-04-13 - * @since v0.2.0 - */ -final class MutablePredicate implements Predicate { - /** - * The predicate stored in this {@code MutablePredicate} - * - * @since 2019-04-13 - * @since v0.2.0 - */ - private Predicate predicate; - - /** - * Creates the {@code MutablePredicate}. - * - * @since 2019-04-13 - * @since v0.2.0 - */ - public MutablePredicate(final Predicate predicate) { - this.predicate = predicate; - } - - /** - * @return predicate - * @since 2019-04-13 - * @since v0.2.0 - */ - public final Predicate getPredicate() { - return this.predicate; - } - - /** - * @param predicate - * new value of predicate - * @since 2019-04-13 - * @since v0.2.0 - */ - public final void setPredicate(final Predicate predicate) { - this.predicate = predicate; - } - - @Override - public boolean test(final T t) { - return this.predicate.test(t); - } -} diff --git a/src/org/unitConverter/converterGUI/SearchBoxList.java b/src/org/unitConverter/converterGUI/SearchBoxList.java deleted file mode 100644 index 10ef589..0000000 --- a/src/org/unitConverter/converterGUI/SearchBoxList.java +++ /dev/null @@ -1,307 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.converterGUI; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.function.Predicate; - -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; - -/** - * @author Adrien Hopkins - * @since 2019-04-13 - * @since v0.2.0 - */ -final class SearchBoxList extends JPanel { - - /** - * @since 2019-04-13 - * @since v0.2.0 - */ - private static final long serialVersionUID = 6226930279415983433L; - - /** - * The text to place in an empty search box. - * - * @since 2019-04-13 - * @since v0.2.0 - */ - private static final String EMPTY_TEXT = "Search..."; - - /** - * The color to use for an empty foreground. - * - * @since 2019-04-13 - * @since v0.2.0 - */ - private static final Color EMPTY_FOREGROUND = new Color(192, 192, 192); - - // the components - private final Collection itemsToFilter; - private final DelegateListModel listModel; - private final JTextField searchBox; - private final JList searchItems; - - private boolean searchBoxEmpty = true; - - // I need to do this because, for some reason, Swing is auto-focusing my - // search box without triggering a focus - // event. - private boolean searchBoxFocused = false; - - private Predicate customSearchFilter = o -> true; - private final Comparator defaultOrdering; - private final boolean caseSensitive; - - /** - * Creates the {@code SearchBoxList}. - * - * @param itemsToFilter items to put in the list - * @since 2019-04-14 - */ - public SearchBoxList(final Collection itemsToFilter) { - this(itemsToFilter, null, false); - } - - /** - * Creates the {@code SearchBoxList}. - * - * @param itemsToFilter items to put in the list - * @param defaultOrdering default ordering of items after filtration - * (null=Comparable) - * @param caseSensitive whether or not the filtration is case-sensitive - * - * @since 2019-04-13 - * @since v0.2.0 - */ - public SearchBoxList(final Collection itemsToFilter, - final Comparator defaultOrdering, - final boolean caseSensitive) { - super(new BorderLayout(), true); - this.itemsToFilter = itemsToFilter; - this.defaultOrdering = defaultOrdering; - this.caseSensitive = caseSensitive; - - // create the components - this.listModel = new DelegateListModel<>(new ArrayList<>(itemsToFilter)); - this.searchItems = new JList<>(this.listModel); - - this.searchBox = new JTextField(EMPTY_TEXT); - this.searchBox.setForeground(EMPTY_FOREGROUND); - - // add them to the panel - this.add(this.searchBox, BorderLayout.PAGE_START); - this.add(new JScrollPane(this.searchItems), BorderLayout.CENTER); - - // set up the search box - this.searchBox.addFocusListener(new FocusListener() { - @Override - public void focusGained(final FocusEvent e) { - SearchBoxList.this.searchBoxFocusGained(e); - } - - @Override - public void focusLost(final FocusEvent e) { - SearchBoxList.this.searchBoxFocusLost(e); - } - }); - - this.searchBox.addCaretListener(e -> this.searchBoxTextChanged()); - this.searchBoxEmpty = true; - } - - /** - * Adds an additional filter for searching. - * - * @param filter filter to add. - * @since 2019-04-13 - * @since v0.2.0 - */ - public void addSearchFilter(final Predicate filter) { - this.customSearchFilter = this.customSearchFilter.and(filter); - } - - /** - * Resets the search filter. - * - * @since 2019-04-13 - * @since v0.2.0 - */ - public void clearSearchFilters() { - this.customSearchFilter = o -> true; - } - - /** - * @return this component's search box component - * @since 2019-04-14 - * @since v0.2.0 - */ - public final JTextField getSearchBox() { - return this.searchBox; - } - - /** - * @param searchText text to search for - * @return a filter that filters out that text, based on this list's case - * sensitive setting - * @since 2019-04-14 - * @since v0.2.0 - */ - private Predicate getSearchFilter(final String searchText) { - if (this.caseSensitive) - return string -> string.contains(searchText); - else - return string -> string.toLowerCase() - .contains(searchText.toLowerCase()); - } - - /** - * @return this component's list component - * @since 2019-04-14 - * @since v0.2.0 - */ - public final JList getSearchList() { - return this.searchItems; - } - - /** - * @return index selected in item list - * @since 2019-04-14 - * @since v0.2.0 - */ - public int getSelectedIndex() { - return this.searchItems.getSelectedIndex(); - } - - /** - * @return value selected in item list - * @since 2019-04-13 - * @since v0.2.0 - */ - public String getSelectedValue() { - return this.searchItems.getSelectedValue(); - } - - /** - * Re-applies the filters. - * - * @since 2019-04-13 - * @since v0.2.0 - */ - public void reapplyFilter() { - final String searchText = this.searchBoxEmpty ? "" - : this.searchBox.getText(); - final FilterComparator comparator = new FilterComparator(searchText, - this.defaultOrdering, this.caseSensitive); - final Predicate searchFilter = this.getSearchFilter(searchText); - - this.listModel.clear(); - this.itemsToFilter.forEach(string -> { - if (searchFilter.test(string)) { - this.listModel.add(string); - } - }); - - // applies the custom filters - this.listModel.removeIf(this.customSearchFilter.negate()); - - // sorts the remaining items - this.listModel.sort(comparator); - } - - /** - * Runs whenever the search box gains focus. - * - * @param e focus event - * @since 2019-04-13 - * @since v0.2.0 - */ - private void searchBoxFocusGained(final FocusEvent e) { - this.searchBoxFocused = true; - if (this.searchBoxEmpty) { - this.searchBox.setText(""); - this.searchBox.setForeground(Color.BLACK); - } - } - - /** - * Runs whenever the search box loses focus. - * - * @param e focus event - * @since 2019-04-13 - * @since v0.2.0 - */ - private void searchBoxFocusLost(final FocusEvent e) { - this.searchBoxFocused = false; - if (this.searchBoxEmpty) { - this.searchBox.setText(EMPTY_TEXT); - this.searchBox.setForeground(EMPTY_FOREGROUND); - } - } - - /** - * Runs whenever the text in the search box is changed. - *

    - * Reapplies the search filter, and custom filters. - *

    - * - * @since 2019-04-14 - * @since v0.2.0 - */ - private void searchBoxTextChanged() { - if (this.searchBoxFocused) { - this.searchBoxEmpty = this.searchBox.getText().equals(""); - } - final String searchText = this.searchBoxEmpty ? "" - : this.searchBox.getText(); - final FilterComparator comparator = new FilterComparator(searchText, - this.defaultOrdering, this.caseSensitive); - final Predicate searchFilter = this.getSearchFilter(searchText); - - // initialize list with items that match the filter then sort - this.listModel.clear(); - this.itemsToFilter.forEach(string -> { - if (searchFilter.test(string)) { - this.listModel.add(string); - } - }); - - // applies the custom filters - this.listModel.removeIf(this.customSearchFilter.negate()); - - // sorts the remaining items - this.listModel.sort(comparator); - } - - /** - * Manually updates the search box's item list. - * - * @since 2020-08-27 - */ - public void updateList() { - this.searchBoxTextChanged(); - } -} diff --git a/src/org/unitConverter/converterGUI/UnitConverterGUI.java b/src/org/unitConverter/converterGUI/UnitConverterGUI.java deleted file mode 100644 index 6ddc4a0..0000000 --- a/src/org/unitConverter/converterGUI/UnitConverterGUI.java +++ /dev/null @@ -1,1424 +0,0 @@ -/** - * Copyright (C) 2018-2021 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.converterGUI; - -import java.awt.BorderLayout; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.event.KeyEvent; -import java.io.BufferedWriter; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; -import java.nio.file.Files; -import java.nio.file.Path; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import javax.swing.BorderFactory; -import javax.swing.BoxLayout; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JFormattedTextField; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JScrollPane; -import javax.swing.JSlider; -import javax.swing.JTabbedPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import javax.swing.WindowConstants; -import javax.swing.border.TitledBorder; - -import org.unitConverter.math.ConditionalExistenceCollections; -import org.unitConverter.math.ObjectProduct; -import org.unitConverter.unit.BaseDimension; -import org.unitConverter.unit.BritishImperial; -import org.unitConverter.unit.LinearUnit; -import org.unitConverter.unit.LinearUnitValue; -import org.unitConverter.unit.NameSymbol; -import org.unitConverter.unit.SI; -import org.unitConverter.unit.Unit; -import org.unitConverter.unit.UnitDatabase; -import org.unitConverter.unit.UnitPrefix; -import org.unitConverter.unit.UnitValue; - -/** - * @author Adrien Hopkins - * @since 2018-12-27 - * @since v0.1.0 - */ -final class UnitConverterGUI { - /** - * A tab in the View. - */ - private enum Pane { - UNIT_CONVERTER, EXPRESSION_CONVERTER, UNIT_VIEWER, PREFIX_VIEWER, ABOUT, - SETTINGS; - } - - private static class Presenter { - /** The default place where settings are stored. */ - private static final String DEFAULT_SETTINGS_FILEPATH = "settings.txt"; - /** The default place where units are stored. */ - private static final Path DEFAULT_UNITS_FILE = Path.of("unitsfile.txt"); - /** The default place where dimensions are stored. */ - private static final Path DEFAULT_DIMENSION_FILE = Path - .of("dimensionfile.txt"); - /** The default place where exceptions are stored. */ - private static final Path DEFAULT_EXCEPTIONS_FILE = Path - .of("metric_exceptions.txt"); - - /** - * Adds default units and dimensions to a database. - * - * @param database database to add to - * @since 2019-04-14 - * @since v0.2.0 - */ - private static void addDefaults(final UnitDatabase database) { - database.addUnit("metre", SI.METRE); - database.addUnit("kilogram", SI.KILOGRAM); - database.addUnit("gram", SI.KILOGRAM.dividedBy(1000)); - database.addUnit("second", SI.SECOND); - database.addUnit("ampere", SI.AMPERE); - database.addUnit("kelvin", SI.KELVIN); - database.addUnit("mole", SI.MOLE); - database.addUnit("candela", SI.CANDELA); - database.addUnit("bit", SI.BIT); - database.addUnit("unit", SI.ONE); - // nonlinear units - must be loaded manually - database.addUnit("tempCelsius", SI.CELSIUS); - database.addUnit("tempFahrenheit", BritishImperial.FAHRENHEIT); - - // load initial dimensions - database.addDimension("LENGTH", SI.Dimensions.LENGTH); - database.addDimension("MASS", SI.Dimensions.MASS); - database.addDimension("TIME", SI.Dimensions.TIME); - database.addDimension("TEMPERATURE", SI.Dimensions.TEMPERATURE); - } - - /** - * @return {@code line} with any comments removed. - * @since 2021-03-13 - */ - private static final String withoutComments(String line) { - final int index = line.indexOf('#'); - return index == -1 ? line : line.substring(index); - } - - /** The presenter's associated view. */ - private final View view; - - /** The units known by the program. */ - private final UnitDatabase database; - - /** The names of all of the units */ - private final List unitNames; - - /** The names of all of the prefixes */ - private final List prefixNames; - - /** The names of all of the dimensions */ - private final List dimensionNames; - - /** Unit names that are ignored by the metric-only/imperial-only filter */ - private final Set metricExceptions; - - private final Comparator prefixNameComparator; - - /** A boolean remembering whether or not one-way conversion is on */ - private boolean oneWay = true; - - /** The prefix rule */ - private DefaultPrefixRepetitionRule prefixRule = null; - // conditions for existence of From and To entries - // used for one-way conversion - private final MutablePredicate fromExistenceCondition = new MutablePredicate<>( - s -> true); - - private final MutablePredicate toExistenceCondition = new MutablePredicate<>( - s -> true); - - /* - * Rounding-related settings. I am using my own system, and not - * MathContext, because MathContext does not support decimal place based - * or scientific rounding, only significant digit based rounding. - */ - private int precision = 6; - - private RoundingType roundingType = RoundingType.SIGNIFICANT_DIGITS; - - /** - * Creates the presenter. - * - * @param view presenter's associated view - * @since 2018-12-27 - * @since v0.1.0 - */ - Presenter(final View view) { - this.view = view; - - // load initial units - this.database = new UnitDatabase( - DefaultPrefixRepetitionRule.NO_RESTRICTION); - Presenter.addDefaults(this.database); - - this.database.loadUnitsFile(DEFAULT_UNITS_FILE); - this.database.loadDimensionFile(DEFAULT_DIMENSION_FILE); - - // load metric exceptions - try { - this.metricExceptions = Files.readAllLines(DEFAULT_EXCEPTIONS_FILE) - .stream().map(Presenter::withoutComments) - .filter(s -> !s.isBlank()).collect(Collectors.toSet()); - } catch (final IOException e) { - throw new AssertionError("Loading of metric_exceptions.txt failed.", - e); - } - - // load settings - requires database to exist - this.loadSettings(); - - // a comparator that can be used to compare prefix names - // any name that does not exist is less than a name that does. - // otherwise, they are compared by value - this.prefixNameComparator = (o1, o2) -> { - if (!Presenter.this.database.containsPrefixName(o1)) - return -1; - else if (!Presenter.this.database.containsPrefixName(o2)) - return 1; - - final UnitPrefix p1 = Presenter.this.database.getPrefix(o1); - final UnitPrefix p2 = Presenter.this.database.getPrefix(o2); - - if (p1.getMultiplier() < p2.getMultiplier()) - return -1; - else if (p1.getMultiplier() > p2.getMultiplier()) - return 1; - - return o1.compareTo(o2); - }; - - this.unitNames = new ArrayList<>( - this.database.unitMapPrefixless().keySet()); - this.unitNames.sort(null); // sorts it using Comparable - - this.prefixNames = new ArrayList<>(this.database.prefixMap().keySet()); - this.prefixNames.sort(this.prefixNameComparator); // sorts it using my - // comparator - - this.dimensionNames = new DelegateListModel<>( - new ArrayList<>(this.database.dimensionMap().keySet())); - this.dimensionNames.sort(null); // sorts it using Comparable - - // a Predicate that returns true iff the argument is a full base unit - final Predicate isFullBase = unit -> unit instanceof LinearUnit - && ((LinearUnit) unit).isBase(); - - // print out unit counts - System.out.printf( - "Successfully loaded %d units with %d unit names (%d base units).%n", - new HashSet<>(this.database.unitMapPrefixless().values()).size(), - this.database.unitMapPrefixless().size(), - new HashSet<>(this.database.unitMapPrefixless().values()) - .stream().filter(isFullBase).count()); - } - - /** - * Converts in the dimension-based converter - * - * @since 2019-04-13 - * @since v0.2.0 - */ - public final void convertDimensionBased() { - final String fromSelection = this.view.getFromSelection(); - if (fromSelection == null) { - this.view.showErrorDialog("Error", - "No unit selected in From field"); - return; - } - final String toSelection = this.view.getToSelection(); - if (toSelection == null) { - this.view.showErrorDialog("Error", "No unit selected in To field"); - return; - } - - final Unit from = this.database.getUnit(fromSelection); - final Unit to = this.database.getUnit(toSelection) - .withName(NameSymbol.ofName(toSelection)); - - final UnitValue beforeValue; - try { - beforeValue = UnitValue.of(from, - this.view.getDimensionConverterInput()); - } catch (final ParseException e) { - this.view.showErrorDialog("Error", - "Error in parsing: " + e.getMessage()); - return; - } - final UnitValue value = beforeValue.convertTo(to); - - final String output = this.getRoundedString(value); - - this.view.setDimensionConverterOutputText( - String.format("%s = %s", beforeValue, output)); - } - - /** - * Runs whenever the convert button is pressed. - * - *

    - * Reads and parses a unit expression from the from and to boxes, then - * converts {@code from} to {@code to}. Any errors are shown in - * JOptionPanes. - *

    - * - * @since 2019-01-26 - * @since v0.1.0 - */ - public final void convertExpressions() { - final String fromUnitString = this.view.getFromText(); - final String toUnitString = this.view.getToText(); - - if (fromUnitString.isEmpty()) { - this.view.showErrorDialog("Parse Error", - "Please enter a unit expression in the From: box."); - return; - } - if (toUnitString.isEmpty()) { - this.view.showErrorDialog("Parse Error", - "Please enter a unit expression in the To: box."); - return; - } - - final LinearUnitValue from; - final Unit to; - try { - from = this.database.evaluateUnitExpression(fromUnitString); - } catch (final IllegalArgumentException | NoSuchElementException e) { - this.view.showErrorDialog("Parse Error", - "Could not recognize text in From entry: " + e.getMessage()); - return; - } - try { - to = this.database.getUnitFromExpression(toUnitString); - } catch (final IllegalArgumentException | NoSuchElementException e) { - this.view.showErrorDialog("Parse Error", - "Could not recognize text in To entry: " + e.getMessage()); - return; - } - - if (to instanceof LinearUnit) { - // convert to LinearUnitValue - final LinearUnitValue from2; - final LinearUnit to2 = ((LinearUnit) to) - .withName(NameSymbol.ofName(toUnitString)); - final boolean useSlash; - - if (from.canConvertTo(to2)) { - from2 = from; - useSlash = false; - } else if (LinearUnitValue.ONE.dividedBy(from).canConvertTo(to2)) { - from2 = LinearUnitValue.ONE.dividedBy(from); - useSlash = true; - } else { - // if I can't convert, leave - this.view.showErrorDialog("Conversion Error", - String.format("Cannot convert between %s and %s", - fromUnitString, toUnitString)); - return; - } - - final LinearUnitValue converted = from2.convertTo(to2); - this.view.setExpressionConverterOutputText((useSlash ? "1 / " : "") - + String.format("%s = %s", fromUnitString, - this.getRoundedString(converted, false))); - return; - } else { - // convert to UnitValue - final UnitValue from2 = from.asUnitValue(); - if (from2.canConvertTo(to)) { - final UnitValue converted = from2.convertTo(to); - - this.view - .setExpressionConverterOutputText(String.format("%s = %s", - fromUnitString, this.getRoundedString(converted))); - } else { - // if I can't convert, leave - this.view.showErrorDialog("Conversion Error", - String.format("Cannot convert between %s and %s", - fromUnitString, toUnitString)); - } - } - } - - /** - * @return a list of all of the unit dimensions - * @since 2019-04-13 - * @since v0.2.0 - */ - public final List dimensionNameList() { - return this.dimensionNames; - } - - /** - * @return a list of all the entries in the dimension-based converter's - * From box - * @since 2020-08-27 - */ - public final Set fromEntries() { - return ConditionalExistenceCollections.conditionalExistenceSet( - this.unitNameSet(), this.fromExistenceCondition); - } - - /** - * @return a comparator to compare prefix names - * @since 2019-04-14 - * @since v0.2.0 - */ - public final Comparator getPrefixNameComparator() { - return this.prefixNameComparator; - } - - /** - * Like {@link LinearUnitValue#toString(boolean)}, but obeys this unit - * converter's rounding settings. - * - * @since 2020-08-04 - */ - private final String getRoundedString(final LinearUnitValue value, - boolean showUncertainty) { - switch (this.roundingType) { - case DECIMAL_PLACES: - case SIGNIFICANT_DIGITS: - return this.getRoundedString(value.asUnitValue()); - case SCIENTIFIC: - return value.toString(showUncertainty); - default: - throw new AssertionError("Invalid switch condition."); - } - } - - /** - * Like {@link UnitValue#toString()}, but obeys this unit converter's - * rounding settings. - * - * @since 2020-08-04 - */ - private final String getRoundedString(final UnitValue value) { - final BigDecimal unrounded = new BigDecimal(value.getValue()); - final BigDecimal rounded; - int precision = this.precision; - - switch (this.roundingType) { - case DECIMAL_PLACES: - rounded = unrounded.setScale(precision, RoundingMode.HALF_EVEN); - break; - case SCIENTIFIC: - precision = 12; - //$FALL-THROUGH$ - case SIGNIFICANT_DIGITS: - rounded = unrounded - .round(new MathContext(precision, RoundingMode.HALF_EVEN)); - break; - default: - throw new AssertionError("Invalid switch condition."); - } - - String output = rounded.toString(); - - // remove trailing zeroes - if (output.contains(".")) { - while (output.endsWith("0")) { - output = output.substring(0, output.length() - 1); - } - if (output.endsWith(".")) { - output = output.substring(0, output.length() - 1); - } - } - - return output + " " + value.getUnit().getPrimaryName().get(); - } - - /** - * @return The file where settings are stored; - * @since 2020-12-11 - */ - private final Path getSettingsFile() { - return Path.of(DEFAULT_SETTINGS_FILEPATH); - } - - /** - * Loads settings from the settings file. - * - * @since 2021-02-17 - */ - public final void loadSettings() { - try { - // read file line by line - final int lineNum = 0; - for (final String line : Files - .readAllLines(this.getSettingsFile())) { - final int equalsIndex = line.indexOf('='); - if (equalsIndex == -1) - throw new IllegalStateException( - "Settings file is malformed at line " + lineNum); - - final String param = line.substring(0, equalsIndex); - final String value = line.substring(equalsIndex + 1); - - switch (param) { - // set manually to avoid the unnecessary saving of the non-manual - // methods - case "precision": - this.precision = Integer.valueOf(value); - break; - case "rounding_type": - this.roundingType = RoundingType.valueOf(value); - break; - case "prefix_rule": - this.prefixRule = DefaultPrefixRepetitionRule.valueOf(value); - this.database.setPrefixRepetitionRule(this.prefixRule); - break; - case "one_way": - this.oneWay = Boolean.valueOf(value); - if (this.oneWay) { - this.fromExistenceCondition.setPredicate( - unitName -> this.metricExceptions.contains(unitName) - || !this.database.getUnit(unitName) - .isMetric()); - this.toExistenceCondition.setPredicate( - unitName -> this.metricExceptions.contains(unitName) - || this.database.getUnit(unitName).isMetric()); - } else { - this.fromExistenceCondition.setPredicate(unitName -> true); - this.toExistenceCondition.setPredicate(unitName -> true); - } - break; - default: - System.err.printf("Warning: unrecognized setting \"%s\".", - param); - break; - } - } - } catch (final IOException e) {} - } - - /** - * @return a set of all prefix names in the database - * @since 2019-04-14 - * @since v0.2.0 - */ - public final Set prefixNameSet() { - return this.database.prefixMap().keySet(); - } - - /** - * Runs whenever a prefix is selected in the viewer. - *

    - * Shows its information in the text box to the right. - *

    - * - * @since 2019-01-15 - * @since v0.1.0 - */ - public final void prefixSelected() { - final String prefixName = this.view.getPrefixViewerSelection(); - if (prefixName == null) - return; - else { - final UnitPrefix prefix = this.database.getPrefix(prefixName); - - this.view.setPrefixTextBoxText(String.format("%s%nMultiplier: %s", - prefixName, prefix.getMultiplier())); - } - } - - /** - * Saves the settings to the settings file. - * - * @since 2021-02-17 - */ - public final void saveSettings() { - try (BufferedWriter writer = Files - .newBufferedWriter(this.getSettingsFile())) { - writer.write(String.format("precision=%d\n", this.precision)); - writer.write( - String.format("rounding_type=%s\n", this.roundingType)); - writer.write(String.format("prefix_rule=%s\n", this.prefixRule)); - writer.write(String.format("one_way=%s\n", this.oneWay)); - } catch (final IOException e) { - e.printStackTrace(); - this.view.showErrorDialog("I/O Error", - "Error occurred while saving settings: " - + e.getLocalizedMessage()); - } - } - - /** - * Enables or disables one-way conversion. - * - * @param oneWay whether one-way conversion should be on (true) or off - * (false) - * @since 2020-08-27 - */ - public final void setOneWay(boolean oneWay) { - this.oneWay = oneWay; - if (oneWay) { - this.fromExistenceCondition.setPredicate( - unitName -> this.metricExceptions.contains(unitName) - || !this.database.getUnit(unitName).isMetric()); - this.toExistenceCondition.setPredicate( - unitName -> this.metricExceptions.contains(unitName) - || this.database.getUnit(unitName).isMetric()); - } else { - this.fromExistenceCondition.setPredicate(unitName -> true); - this.toExistenceCondition.setPredicate(unitName -> true); - } - - this.saveSettings(); - } - - /** - * @param precision new value of precision - * @since 2019-01-15 - * @since v0.1.0 - */ - public final void setPrecision(final int precision) { - this.precision = precision; - - this.saveSettings(); - } - - /** - * @param prefixRepetitionRule the prefixRepetitionRule to set - * @since 2020-08-26 - */ - public void setPrefixRepetitionRule( - Predicate> prefixRepetitionRule) { - if (prefixRepetitionRule instanceof DefaultPrefixRepetitionRule) { - this.prefixRule = (DefaultPrefixRepetitionRule) prefixRepetitionRule; - } else { - this.prefixRule = null; - } - this.database.setPrefixRepetitionRule(prefixRepetitionRule); - - this.saveSettings(); - } - - /** - * @param roundingType the roundingType to set - * @since 2020-07-16 - */ - public final void setRoundingType(RoundingType roundingType) { - this.roundingType = roundingType; - - this.saveSettings(); - } - - /** - * @return a list of all the entries in the dimension-based converter's To - * box - * @since 2020-08-27 - */ - public final Set toEntries() { - return ConditionalExistenceCollections.conditionalExistenceSet( - this.unitNameSet(), this.toExistenceCondition); - } - - /** - * Returns true if and only if the unit represented by {@code unitName} - * has the dimension represented by {@code dimensionName}. - * - * @param unitName name of unit to test - * @param dimensionName name of dimension to test - * @return whether unit has dimenision - * @since 2019-04-13 - * @since v0.2.0 - */ - public final boolean unitMatchesDimension(final String unitName, - final String dimensionName) { - final Unit unit = this.database.getUnit(unitName); - final ObjectProduct dimension = this.database - .getDimension(dimensionName); - return unit.getDimension().equals(dimension); - } - - /** - * Runs whenever a unit is selected in the viewer. - *

    - * Shows its information in the text box to the right. - *

    - * - * @since 2019-01-15 - * @since v0.1.0 - */ - public final void unitNameSelected() { - final String unitName = this.view.getUnitViewerSelection(); - if (unitName == null) - return; - else { - final Unit unit = this.database.getUnit(unitName); - - this.view.setUnitTextBoxText(unit.toString()); - } - } - - /** - * @return a set of all of the unit names - * @since 2019-04-14 - * @since v0.2.0 - */ - private final Set unitNameSet() { - return this.database.unitMapPrefixless().keySet(); - } - } - - /** - * Different types of rounding. - * - * Significant digits: Rounds to a number of digits. i.e. with precision 5, - * 12345.6789 rounds to 12346. Decimal places: Rounds to a number of digits - * after the decimal point, i.e. with precision 5, 12345.6789 rounds to - * 12345.67890. Scientific: Rounds based on the number of digits and - * operations, following standard scientific rounding. - */ - private static enum RoundingType { - SIGNIFICANT_DIGITS, DECIMAL_PLACES, SCIENTIFIC; - } - - private static class View { - private static final NumberFormat NUMBER_FORMATTER = new DecimalFormat(); - - /** The view's frame. */ - private final JFrame frame; - /** The view's associated presenter. */ - private final Presenter presenter; - /** The master pane containing all of the tabs. */ - private final JTabbedPane masterPane; - - // DIMENSION-BASED CONVERTER - /** The panel for inputting values in the dimension-based converter */ - private final JTextField valueInput; - /** The panel for "From" in the dimension-based converter */ - private final SearchBoxList fromSearch; - /** The panel for "To" in the dimension-based converter */ - private final SearchBoxList toSearch; - /** The output area in the dimension-based converter */ - private final JTextArea dimensionBasedOutput; - - // EXPRESSION-BASED CONVERTER - /** The "From" entry in the conversion panel */ - private final JTextField fromEntry; - /** The "To" entry in the conversion panel */ - private final JTextField toEntry; - /** The output area in the conversion panel */ - private final JTextArea output; - - // UNIT AND PREFIX VIEWERS - /** The searchable list of unit names in the unit viewer */ - private final SearchBoxList unitNameList; - /** The searchable list of prefix names in the prefix viewer */ - private final SearchBoxList prefixNameList; - /** The text box for unit data in the unit viewer */ - private final JTextArea unitTextBox; - /** The text box for prefix data in the prefix viewer */ - private final JTextArea prefixTextBox; - - /** - * Creates the {@code View}. - * - * @since 2019-01-14 - * @since v0.1.0 - */ - public View() { - this.presenter = new Presenter(this); - this.frame = new JFrame("Unit Converter"); - this.frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - - // enable system look and feel - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (ClassNotFoundException | InstantiationException - | IllegalAccessException | UnsupportedLookAndFeelException e) { - // oh well, just use default theme - System.err.println("Failed to enable system look-and-feel."); - e.printStackTrace(); - } - - // create the components - this.masterPane = new JTabbedPane(); - this.unitNameList = new SearchBoxList(this.presenter.unitNameSet()); - this.prefixNameList = new SearchBoxList(this.presenter.prefixNameSet(), - this.presenter.getPrefixNameComparator(), true); - this.unitTextBox = new JTextArea(); - this.prefixTextBox = new JTextArea(); - this.fromSearch = new SearchBoxList(this.presenter.fromEntries()); - this.toSearch = new SearchBoxList(this.presenter.toEntries()); - this.valueInput = new JFormattedTextField(NUMBER_FORMATTER); - this.dimensionBasedOutput = new JTextArea(2, 32); - this.fromEntry = new JTextField(); - this.toEntry = new JTextField(); - this.output = new JTextArea(2, 32); - - // create more components - this.initComponents(); - - this.frame.pack(); - } - - /** - * @return the currently selected pane. - * @throws AssertionError if no pane (or an invalid pane) is selected - */ - public Pane getActivePane() { - switch (this.masterPane.getSelectedIndex()) { - case 0: - return Pane.UNIT_CONVERTER; - case 1: - return Pane.EXPRESSION_CONVERTER; - case 2: - return Pane.UNIT_VIEWER; - case 3: - return Pane.PREFIX_VIEWER; - case 4: - return Pane.ABOUT; - case 5: - return Pane.SETTINGS; - default: - throw new AssertionError("No selected pane, or invalid pane."); - } - } - - /** - * @return value in dimension-based converter - * @throws ParseException - * @since 2020-07-07 - */ - public double getDimensionConverterInput() throws ParseException { - final Number value = NUMBER_FORMATTER.parse(this.valueInput.getText()); - if (value instanceof Double) - return (double) value; - else if (value instanceof Long) - return ((Long) value).longValue(); - else - throw new AssertionError(); - } - - /** - * @return selection in "From" selector in dimension-based converter - * @since 2019-04-13 - * @since v0.2.0 - */ - public String getFromSelection() { - return this.fromSearch.getSelectedValue(); - } - - /** - * @return text in "From" box in converter panel - * @since 2019-01-15 - * @since v0.1.0 - */ - public String getFromText() { - return this.fromEntry.getText(); - } - - /** - * @return index of selected prefix in prefix viewer - * @since 2019-01-15 - * @since v0.1.0 - */ - public String getPrefixViewerSelection() { - return this.prefixNameList.getSelectedValue(); - } - - /** - * @return selection in "To" selector in dimension-based converter - * @since 2019-04-13 - * @since v0.2.0 - */ - public String getToSelection() { - return this.toSearch.getSelectedValue(); - } - - /** - * @return text in "To" box in converter panel - * @since 2019-01-26 - * @since v0.1.0 - */ - public String getToText() { - return this.toEntry.getText(); - } - - /** - * @return index of selected unit in unit viewer - * @since 2019-01-15 - * @since v0.1.0 - */ - public String getUnitViewerSelection() { - return this.unitNameList.getSelectedValue(); - } - - /** - * Starts up the application. - * - * @since 2018-12-27 - * @since v0.1.0 - */ - public final void init() { - this.frame.setVisible(true); - } - - /** - * Initializes the view's components. - * - * @since 2018-12-27 - * @since v0.1.0 - */ - private final void initComponents() { - final JPanel masterPanel = new JPanel(); - this.frame.add(masterPanel); - - masterPanel.setLayout(new BorderLayout()); - - { // pane with all of the tabs - masterPanel.add(this.masterPane, BorderLayout.CENTER); - - // update stuff - this.masterPane.addChangeListener(e -> this.update()); - - { // a panel for unit conversion using a selector - final JPanel convertUnitPanel = new JPanel(); - this.masterPane.addTab("Convert Units", convertUnitPanel); - this.masterPane.setMnemonicAt(0, KeyEvent.VK_U); - - convertUnitPanel.setLayout(new BorderLayout()); - - { // panel for input part - final JPanel inputPanel = new JPanel(); - convertUnitPanel.add(inputPanel, BorderLayout.CENTER); - - inputPanel.setLayout(new GridLayout(1, 3)); - - final JComboBox dimensionSelector = new JComboBox<>( - this.presenter.dimensionNameList() - .toArray(new String[0])); - dimensionSelector.setSelectedItem("LENGTH"); - - // handle dimension filter - final MutablePredicate dimensionFilter = new MutablePredicate<>( - s -> true); - - // panel for From things - inputPanel.add(this.fromSearch); - - this.fromSearch.addSearchFilter(dimensionFilter); - - { // for dimension selector and arrow that represents - // conversion - final JPanel inBetweenPanel = new JPanel(); - inputPanel.add(inBetweenPanel); - - inBetweenPanel.setLayout(new BorderLayout()); - - { // dimension selector - inBetweenPanel.add(dimensionSelector, - BorderLayout.PAGE_START); - } - - { // the arrow in the middle - final JLabel arrowLabel = new JLabel("->"); - inBetweenPanel.add(arrowLabel, BorderLayout.CENTER); - } - } - - // panel for To things - - inputPanel.add(this.toSearch); - - this.toSearch.addSearchFilter(dimensionFilter); - - // code for dimension filter - dimensionSelector.addItemListener(e -> { - dimensionFilter.setPredicate(string -> View.this.presenter - .unitMatchesDimension(string, - (String) dimensionSelector.getSelectedItem())); - this.fromSearch.reapplyFilter(); - this.toSearch.reapplyFilter(); - }); - - // apply the item listener once because I have a default - // selection - dimensionFilter.setPredicate(string -> View.this.presenter - .unitMatchesDimension(string, - (String) dimensionSelector.getSelectedItem())); - this.fromSearch.reapplyFilter(); - this.toSearch.reapplyFilter(); - } - - { // panel for submit and output, and also value entry - final JPanel outputPanel = new JPanel(); - convertUnitPanel.add(outputPanel, BorderLayout.PAGE_END); - - outputPanel.setLayout(new GridLayout(3, 1)); - - { // unit input - final JPanel valueInputPanel = new JPanel(); - outputPanel.add(valueInputPanel); - - valueInputPanel.setLayout(new BorderLayout()); - - { // prompt - final JLabel valuePrompt = new JLabel( - "Value to convert: "); - valueInputPanel.add(valuePrompt, - BorderLayout.LINE_START); - } - - { // value to convert - valueInputPanel.add(this.valueInput, - BorderLayout.CENTER); - } - } - - { // button to convert - final JButton convertButton = new JButton("Convert"); - outputPanel.add(convertButton); - - convertButton.addActionListener( - e -> this.presenter.convertDimensionBased()); - convertButton.setMnemonic(KeyEvent.VK_ENTER); - } - - { // output of conversion - outputPanel.add(this.dimensionBasedOutput); - this.dimensionBasedOutput.setEditable(false); - } - } - } - - { // panel for unit conversion using expressions - final JPanel convertExpressionPanel = new JPanel(); - this.masterPane.addTab("Convert Unit Expressions", - convertExpressionPanel); - this.masterPane.setMnemonicAt(1, KeyEvent.VK_E); - - convertExpressionPanel.setLayout(new GridLayout(4, 1)); - - { // panel for units to convert from - final JPanel fromPanel = new JPanel(); - convertExpressionPanel.add(fromPanel); - - fromPanel.setBorder(BorderFactory.createTitledBorder("From")); - fromPanel.setLayout(new GridLayout(1, 1)); - - { // entry for units - fromPanel.add(this.fromEntry); - } - } - - { // panel for units to convert to - final JPanel toPanel = new JPanel(); - convertExpressionPanel.add(toPanel); - - toPanel.setBorder(BorderFactory.createTitledBorder("To")); - toPanel.setLayout(new GridLayout(1, 1)); - - { // entry for units - toPanel.add(this.toEntry); - } - } - - { // button to convert - final JButton convertButton = new JButton("Convert"); - convertExpressionPanel.add(convertButton); - - convertButton.addActionListener( - e -> this.presenter.convertExpressions()); - convertButton.setMnemonic(KeyEvent.VK_ENTER); - } - - { // output of conversion - final JPanel outputPanel = new JPanel(); - convertExpressionPanel.add(outputPanel); - - outputPanel - .setBorder(BorderFactory.createTitledBorder("Output")); - outputPanel.setLayout(new GridLayout(1, 1)); - - { // output - outputPanel.add(this.output); - this.output.setEditable(false); - } - } - } - - { // panel to look up units - final JPanel unitLookupPanel = new JPanel(); - this.masterPane.addTab("Unit Viewer", unitLookupPanel); - this.masterPane.setMnemonicAt(2, KeyEvent.VK_V); - - unitLookupPanel.setLayout(new GridLayout()); - - { // search panel - unitLookupPanel.add(this.unitNameList); - - this.unitNameList.getSearchList().addListSelectionListener( - e -> this.presenter.unitNameSelected()); - } - - { // the text box for unit's toString - unitLookupPanel.add(this.unitTextBox); - this.unitTextBox.setEditable(false); - this.unitTextBox.setLineWrap(true); - } - } - - { // panel to look up prefixes - final JPanel prefixLookupPanel = new JPanel(); - this.masterPane.addTab("Prefix Viewer", prefixLookupPanel); - this.masterPane.setMnemonicAt(3, KeyEvent.VK_P); - - prefixLookupPanel.setLayout(new GridLayout(1, 2)); - - { // panel for listing and seaching - prefixLookupPanel.add(this.prefixNameList); - - this.prefixNameList.getSearchList().addListSelectionListener( - e -> this.presenter.prefixSelected()); - } - - { // the text box for prefix's toString - prefixLookupPanel.add(this.prefixTextBox); - this.prefixTextBox.setEditable(false); - this.prefixTextBox.setLineWrap(true); - } - } - - { // Info panel - final JPanel infoPanel = new JPanel(); - this.masterPane.addTab("\uD83D\uDEC8", // info (i) character - new JScrollPane(infoPanel)); - - final JTextArea infoTextArea = new JTextArea(); - infoTextArea.setEditable(false); - infoTextArea.setOpaque(false); - infoPanel.add(infoTextArea); - - // get info text - final String infoText; - try { - final Path aboutFile = Path.of("src", "about.txt"); - infoText = Files.readAllLines(aboutFile).stream() - .map(Presenter::withoutComments) - .collect(Collectors.joining("\n")); - } catch (final IOException e) { - throw new AssertionError("I/O exception loading about.txt"); - } - infoTextArea.setText(infoText); - } - - { // Settings panel - final JPanel settingsPanel = new JPanel(); - this.masterPane.addTab("\u2699", new JScrollPane(settingsPanel)); - this.masterPane.setMnemonicAt(5, KeyEvent.VK_S); - - settingsPanel.setLayout( - new BoxLayout(settingsPanel, BoxLayout.PAGE_AXIS)); - - { // rounding settings - final JPanel roundingPanel = new JPanel(); - settingsPanel.add(roundingPanel); - roundingPanel - .setBorder(new TitledBorder("Rounding Settings")); - roundingPanel.setLayout(new GridBagLayout()); - - // rounding rule selection - final ButtonGroup roundingRuleButtons = new ButtonGroup(); - - final JLabel roundingRuleLabel = new JLabel("Rounding Rule:"); - roundingPanel.add(roundingRuleLabel, new GridBagBuilder(0, 0) - .setAnchor(GridBagConstraints.LINE_START).build()); - - final JRadioButton fixedPrecision = new JRadioButton( - "Fixed Precision"); - if (this.presenter.roundingType == RoundingType.SIGNIFICANT_DIGITS) { - fixedPrecision.setSelected(true); - } - fixedPrecision.addActionListener(e -> this.presenter - .setRoundingType(RoundingType.SIGNIFICANT_DIGITS)); - roundingRuleButtons.add(fixedPrecision); - roundingPanel.add(fixedPrecision, new GridBagBuilder(0, 1) - .setAnchor(GridBagConstraints.LINE_START).build()); - - final JRadioButton fixedDecimals = new JRadioButton( - "Fixed Decimal Places"); - if (this.presenter.roundingType == RoundingType.DECIMAL_PLACES) { - fixedDecimals.setSelected(true); - } - fixedDecimals.addActionListener(e -> this.presenter - .setRoundingType(RoundingType.DECIMAL_PLACES)); - roundingRuleButtons.add(fixedDecimals); - roundingPanel.add(fixedDecimals, new GridBagBuilder(0, 2) - .setAnchor(GridBagConstraints.LINE_START).build()); - - final JRadioButton relativePrecision = new JRadioButton( - "Scientific Precision"); - if (this.presenter.roundingType == RoundingType.SCIENTIFIC) { - relativePrecision.setSelected(true); - } - relativePrecision.addActionListener(e -> this.presenter - .setRoundingType(RoundingType.SCIENTIFIC)); - roundingRuleButtons.add(relativePrecision); - roundingPanel.add(relativePrecision, new GridBagBuilder(0, 3) - .setAnchor(GridBagConstraints.LINE_START).build()); - - final JLabel sliderLabel = new JLabel("Precision:"); - roundingPanel.add(sliderLabel, new GridBagBuilder(0, 4) - .setAnchor(GridBagConstraints.LINE_START).build()); - - final JSlider sigDigSlider = new JSlider(0, 12); - roundingPanel.add(sigDigSlider, new GridBagBuilder(0, 5) - .setAnchor(GridBagConstraints.LINE_START).build()); - - sigDigSlider.setMajorTickSpacing(4); - sigDigSlider.setMinorTickSpacing(1); - sigDigSlider.setSnapToTicks(true); - sigDigSlider.setPaintTicks(true); - sigDigSlider.setPaintLabels(true); - sigDigSlider.setValue(this.presenter.precision); - - sigDigSlider.addChangeListener(e -> this.presenter - .setPrecision(sigDigSlider.getValue())); - } - - { // prefix repetition settings - final JPanel prefixRepetitionPanel = new JPanel(); - settingsPanel.add(prefixRepetitionPanel); - prefixRepetitionPanel.setBorder( - new TitledBorder("Prefix Repetition Settings")); - prefixRepetitionPanel.setLayout(new GridBagLayout()); - - // prefix rules - final ButtonGroup prefixRuleButtons = new ButtonGroup(); - - final JRadioButton noRepetition = new JRadioButton( - "No Repetition"); - if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.NO_REPETITION) { - noRepetition.setSelected(true); - } - noRepetition.addActionListener( - e -> this.presenter.setPrefixRepetitionRule( - DefaultPrefixRepetitionRule.NO_REPETITION)); - prefixRuleButtons.add(noRepetition); - prefixRepetitionPanel.add(noRepetition, - new GridBagBuilder(0, 0) - .setAnchor(GridBagConstraints.LINE_START) - .build()); - - final JRadioButton noRestriction = new JRadioButton( - "No Restriction"); - if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.NO_RESTRICTION) { - noRestriction.setSelected(true); - } - noRestriction.addActionListener( - e -> this.presenter.setPrefixRepetitionRule( - DefaultPrefixRepetitionRule.NO_RESTRICTION)); - prefixRuleButtons.add(noRestriction); - prefixRepetitionPanel.add(noRestriction, - new GridBagBuilder(0, 1) - .setAnchor(GridBagConstraints.LINE_START) - .build()); - - final JRadioButton customRepetition = new JRadioButton( - "Complex Repetition"); - if (this.presenter.prefixRule == DefaultPrefixRepetitionRule.COMPLEX_REPETITION) { - customRepetition.setSelected(true); - } - customRepetition.addActionListener( - e -> this.presenter.setPrefixRepetitionRule( - DefaultPrefixRepetitionRule.COMPLEX_REPETITION)); - prefixRuleButtons.add(customRepetition); - prefixRepetitionPanel.add(customRepetition, - new GridBagBuilder(0, 2) - .setAnchor(GridBagConstraints.LINE_START) - .build()); - } - - { // search settings - final JPanel searchingPanel = new JPanel(); - settingsPanel.add(searchingPanel); - searchingPanel.setBorder(new TitledBorder("Search Settings")); - searchingPanel.setLayout(new GridBagLayout()); - - // searching rules - final ButtonGroup searchRuleButtons = new ButtonGroup(); - - final JRadioButton noPrefixes = new JRadioButton( - "Never Include Prefixed Units"); - noPrefixes.setEnabled(false); - searchRuleButtons.add(noPrefixes); - searchingPanel.add(noPrefixes, new GridBagBuilder(0, 0) - .setAnchor(GridBagConstraints.LINE_START).build()); - - final JRadioButton fixedPrefixes = new JRadioButton( - "Include Some Prefixes"); - fixedPrefixes.setEnabled(false); - searchRuleButtons.add(fixedPrefixes); - searchingPanel.add(fixedPrefixes, new GridBagBuilder(0, 1) - .setAnchor(GridBagConstraints.LINE_START).build()); - - final JRadioButton explicitPrefixes = new JRadioButton( - "Include Explicit Prefixes"); - explicitPrefixes.setEnabled(false); - searchRuleButtons.add(explicitPrefixes); - searchingPanel.add(explicitPrefixes, new GridBagBuilder(0, 2) - .setAnchor(GridBagConstraints.LINE_START).build()); - - final JRadioButton alwaysInclude = new JRadioButton( - "Include All Single Prefixes"); - alwaysInclude.setEnabled(false); - searchRuleButtons.add(alwaysInclude); - searchingPanel.add(alwaysInclude, new GridBagBuilder(0, 3) - .setAnchor(GridBagConstraints.LINE_START).build()); - } - - { // miscellaneous settings - final JPanel miscPanel = new JPanel(); - settingsPanel.add(miscPanel); - miscPanel - .setBorder(new TitledBorder("Miscellaneous Settings")); - miscPanel.setLayout(new GridBagLayout()); - - final JCheckBox oneWay = new JCheckBox( - "Convert One Way Only"); - oneWay.setSelected(this.presenter.oneWay); - oneWay.addItemListener( - e -> this.presenter.setOneWay(e.getStateChange() == 1)); - miscPanel.add(oneWay, new GridBagBuilder(0, 0) - .setAnchor(GridBagConstraints.LINE_START).build()); - - final JCheckBox showAllVariations = new JCheckBox( - "Show Symbols in \"Convert Units\""); - showAllVariations.setSelected(true); - showAllVariations.setEnabled(false); - miscPanel.add(showAllVariations, new GridBagBuilder(0, 1) - .setAnchor(GridBagConstraints.LINE_START).build()); - - final JButton unitFileButton = new JButton( - "Manage Unit Data Files"); - unitFileButton.setEnabled(false); - miscPanel.add(unitFileButton, new GridBagBuilder(0, 2) - .setAnchor(GridBagConstraints.LINE_START).build()); - } - } - } - } - - /** - * Sets the text in the output of the dimension-based converter. - * - * @param text text to set - * @since 2019-04-13 - * @since v0.2.0 - */ - public void setDimensionConverterOutputText(final String text) { - this.dimensionBasedOutput.setText(text); - } - - /** - * Sets the text in the output of the conversion panel. - * - * @param text text to set - * @since 2019-01-15 - * @since v0.1.0 - */ - public void setExpressionConverterOutputText(final String text) { - this.output.setText(text); - } - - /** - * Sets the text of the prefix text box in the prefix viewer. - * - * @param text text to set - * @since 2019-01-15 - * @since v0.1.0 - */ - public void setPrefixTextBoxText(final String text) { - this.prefixTextBox.setText(text); - } - - /** - * Sets the text of the unit text box in the unit viewer. - * - * @param text text to set - * @since 2019-01-15 - * @since v0.1.0 - */ - public void setUnitTextBoxText(final String text) { - this.unitTextBox.setText(text); - } - - /** - * Shows an error dialog. - * - * @param title title of dialog - * @param message message in dialog - * @since 2019-01-14 - * @since v0.1.0 - */ - public void showErrorDialog(final String title, final String message) { - JOptionPane.showMessageDialog(this.frame, message, title, - JOptionPane.ERROR_MESSAGE); - } - - public void update() { - switch (this.getActivePane()) { - case UNIT_CONVERTER: - this.fromSearch.updateList(); - this.toSearch.updateList(); - break; - default: - // do nothing, for now - break; - } - } - } - - public static void main(final String[] args) { - new View().init(); - } -} diff --git a/src/org/unitConverter/converterGUI/package-info.java b/src/org/unitConverter/converterGUI/package-info.java deleted file mode 100644 index d85ecab..0000000 --- a/src/org/unitConverter/converterGUI/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -/** - * The GUI interface of the Unit Converter. - * - * @author Adrien Hopkins - * @since 2019-01-25 - * @since v0.2.0 - */ -package org.unitConverter.converterGUI; \ No newline at end of file diff --git a/src/org/unitConverter/math/ConditionalExistenceCollections.java b/src/org/unitConverter/math/ConditionalExistenceCollections.java deleted file mode 100644 index ac1c0cf..0000000 --- a/src/org/unitConverter/math/ConditionalExistenceCollections.java +++ /dev/null @@ -1,468 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.math; - -import java.util.AbstractCollection; -import java.util.AbstractMap; -import java.util.AbstractSet; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.function.Predicate; - -/** - * Elements in these wrapper collections only exist if they pass a condition. - *

    - * All of the collections in this class are "views" of the provided collections. - * They are mutable if the provided collections are mutable, they allow null if - * the provided collections allow null, they will reflect changes in the - * provided collection, etc. - *

    - * The modification operations will always run the corresponding operations, - * even if the conditional existence collection doesn't change. For example, if - * you have a set that ignores even numbers, add(2) will still add a 2 to the - * backing set (but the conditional existence set will say it doesn't exist). - *

    - * The returned collections do not pass the hashCode and equals - * operations through to the backing collections, but rely on {@code Object}'s - * {@code equals} and {@code hashCode} methods. This is necessary to preserve - * the contracts of these operations in the case that the backing collections - * are sets or lists. - *

    - * Other than that, the only difference between the provided collections and - * the returned collections are that elements don't exist if they don't pass the - * provided condition. - * - * - * @author Adrien Hopkins - * @since 2019-10-17 - */ -// TODO add conditional existence Lists and Sorted/Navigable Sets/Maps -public final class ConditionalExistenceCollections { - /** - * Elements in this collection only exist if they meet a condition. - * - * @author Adrien Hopkins - * @since 2019-10-17 - * @param type of element in collection - */ - static final class ConditionalExistenceCollection - extends AbstractCollection { - final Collection collection; - final Predicate existenceCondition; - - /** - * Creates the {@code ConditionalExistenceCollection}. - * - * @param collection - * @param existenceCondition - * @since 2019-10-17 - */ - private ConditionalExistenceCollection(final Collection collection, - final Predicate existenceCondition) { - this.collection = collection; - this.existenceCondition = existenceCondition; - } - - @Override - public boolean add(final E e) { - return this.collection.add(e) && this.existenceCondition.test(e); - } - - @Override - public void clear() { - this.collection.clear(); - } - - @Override - public boolean contains(final Object o) { - if (!this.collection.contains(o)) - return false; - - // this collection can only contain instances of E - // since the object is in the collection, we know that it must be an - // instance of E - // therefore this cast will always work - @SuppressWarnings("unchecked") - final E e = (E) o; - - return this.existenceCondition.test(e); - } - - @Override - public Iterator iterator() { - return conditionalExistenceIterator(this.collection.iterator(), - this.existenceCondition); - } - - @Override - public boolean remove(final Object o) { - // remove() must be first in the && statement, otherwise it may not - // execute - final boolean containedObject = this.contains(o); - return this.collection.remove(o) && containedObject; - } - - @Override - public int size() { - return (int) this.collection.stream().filter(this.existenceCondition) - .count(); - } - - @Override - public Object[] toArray() { - // ensure the toArray operation is supported - this.collection.toArray(); - - // if it works, do it for real - return super.toArray(); - } - - @Override - public T[] toArray(T[] a) { - // ensure the toArray operation is supported - this.collection.toArray(); - - // if it works, do it for real - return super.toArray(a); - } - } - - /** - * Elements in this wrapper iterator only exist if they pass a condition. - * - * @author Adrien Hopkins - * @since 2019-10-17 - * @param type of elements in iterator - */ - static final class ConditionalExistenceIterator implements Iterator { - final Iterator iterator; - final Predicate existenceCondition; - E nextElement; - boolean hasNext; - - /** - * Creates the {@code ConditionalExistenceIterator}. - * - * @param iterator - * @param condition - * @since 2019-10-17 - */ - private ConditionalExistenceIterator(final Iterator iterator, - final Predicate condition) { - this.iterator = iterator; - this.existenceCondition = condition; - this.getAndSetNextElement(); - } - - /** - * Gets the next element, and sets nextElement and hasNext accordingly. - * - * @since 2019-10-17 - */ - private void getAndSetNextElement() { - do { - if (!this.iterator.hasNext()) { - this.nextElement = null; - this.hasNext = false; - return; - } - this.nextElement = this.iterator.next(); - } while (!this.existenceCondition.test(this.nextElement)); - this.hasNext = true; - } - - @Override - public boolean hasNext() { - return this.hasNext; - } - - @Override - public E next() { - if (this.hasNext()) { - final E next = this.nextElement; - this.getAndSetNextElement(); - return next; - } else - throw new NoSuchElementException(); - } - - @Override - public void remove() { - this.iterator.remove(); - } - } - - /** - * Mappings in this map only exist if the entry passes some condition. - * - * @author Adrien Hopkins - * @since 2019-10-17 - * @param key type - * @param value type - */ - static final class ConditionalExistenceMap extends AbstractMap { - Map map; - Predicate> entryExistenceCondition; - - /** - * Creates the {@code ConditionalExistenceMap}. - * - * @param map - * @param entryExistenceCondition - * @since 2019-10-17 - */ - private ConditionalExistenceMap(final Map map, - final Predicate> entryExistenceCondition) { - this.map = map; - this.entryExistenceCondition = entryExistenceCondition; - } - - @Override - public boolean containsKey(final Object key) { - if (!this.map.containsKey(key)) - return false; - - // only instances of K have mappings in the backing map - // since we know that key is a valid key, it must be an instance of K - @SuppressWarnings("unchecked") - final K keyAsK = (K) key; - - // get and test entry - final V value = this.map.get(key); - final Entry entry = new SimpleEntry<>(keyAsK, value); - return this.entryExistenceCondition.test(entry); - } - - @Override - public Set> entrySet() { - return conditionalExistenceSet(this.map.entrySet(), - this.entryExistenceCondition); - } - - @Override - public V get(final Object key) { - return this.containsKey(key) ? this.map.get(key) : null; - } - - private final Entry getEntry(K key) { - return new Entry() { - @Override - public K getKey() { - return key; - } - - @Override - public V getValue() { - return ConditionalExistenceMap.this.map.get(key); - } - - @Override - public V setValue(V value) { - return ConditionalExistenceMap.this.map.put(key, value); - } - }; - } - - @Override - public Set keySet() { - return conditionalExistenceSet(super.keySet(), - k -> this.entryExistenceCondition.test(this.getEntry(k))); - } - - @Override - public V put(final K key, final V value) { - final V oldValue = this.map.put(key, value); - - // get and test entry - final Entry entry = new SimpleEntry<>(key, oldValue); - return this.entryExistenceCondition.test(entry) ? oldValue : null; - } - - @Override - public V remove(final Object key) { - final V oldValue = this.map.remove(key); - return this.containsKey(key) ? oldValue : null; - } - - @Override - public Collection values() { - // maybe change this to use ConditionalExistenceCollection - return super.values(); - } - } - - /** - * Elements in this set only exist if a certain condition is true. - * - * @author Adrien Hopkins - * @since 2019-10-17 - * @param type of element in set - */ - static final class ConditionalExistenceSet extends AbstractSet { - private final Set set; - private final Predicate existenceCondition; - - /** - * Creates the {@code ConditionalNonexistenceSet}. - * - * @param set set to use - * @param existenceCondition condition where element exists - * @since 2019-10-17 - */ - private ConditionalExistenceSet(final Set set, - final Predicate existenceCondition) { - this.set = set; - this.existenceCondition = existenceCondition; - } - - /** - * {@inheritDoc} - *

    - * Note that this method returns {@code false} if {@code e} does not pass - * the existence condition. - */ - @Override - public boolean add(final E e) { - return this.set.add(e) && this.existenceCondition.test(e); - } - - @Override - public void clear() { - this.set.clear(); - } - - @Override - public boolean contains(final Object o) { - if (!this.set.contains(o)) - return false; - - // this set can only contain instances of E - // since the object is in the set, we know that it must be an instance - // of E - // therefore this cast will always work - @SuppressWarnings("unchecked") - final E e = (E) o; - - return this.existenceCondition.test(e); - } - - @Override - public Iterator iterator() { - return conditionalExistenceIterator(this.set.iterator(), - this.existenceCondition); - } - - @Override - public boolean remove(final Object o) { - // remove() must be first in the && statement, otherwise it may not - // execute - final boolean containedObject = this.contains(o); - return this.set.remove(o) && containedObject; - } - - @Override - public int size() { - return (int) this.set.stream().filter(this.existenceCondition).count(); - } - - @Override - public Object[] toArray() { - // ensure the toArray operation is supported - this.set.toArray(); - - // if it works, do it for real - return super.toArray(); - } - - @Override - public T[] toArray(T[] a) { - // ensure the toArray operation is supported - this.set.toArray(); - - // if it works, do it for real - return super.toArray(a); - } - } - - /** - * Elements in the returned wrapper collection are ignored if they don't pass - * a condition. - * - * @param type of elements in collection - * @param collection collection to wrap - * @param existenceCondition elements only exist if this returns true - * @return wrapper collection - * @since 2019-10-17 - */ - public static final Collection conditionalExistenceCollection( - final Collection collection, - final Predicate existenceCondition) { - return new ConditionalExistenceCollection<>(collection, - existenceCondition); - } - - /** - * Elements in the returned wrapper iterator are ignored if they don't pass a - * condition. - * - * @param type of elements in iterator - * @param iterator iterator to wrap - * @param existenceCondition elements only exist if this returns true - * @return wrapper iterator - * @since 2019-10-17 - */ - public static final Iterator conditionalExistenceIterator( - final Iterator iterator, final Predicate existenceCondition) { - return new ConditionalExistenceIterator<>(iterator, existenceCondition); - } - - /** - * Mappings in the returned wrapper map are ignored if the corresponding - * entry doesn't pass a condition - * - * @param type of key in map - * @param type of value in map - * @param map map to wrap - * @param entryExistenceCondition mappings only exist if this returns true - * @return wrapper map - * @since 2019-10-17 - */ - public static final Map conditionalExistenceMap( - final Map map, - final Predicate> entryExistenceCondition) { - return new ConditionalExistenceMap<>(map, entryExistenceCondition); - } - - /** - * Elements in the returned wrapper set are ignored if they don't pass a - * condition. - * - * @param type of elements in set - * @param set set to wrap - * @param existenceCondition elements only exist if this returns true - * @return wrapper set - * @since 2019-10-17 - */ - public static final Set conditionalExistenceSet(final Set set, - final Predicate existenceCondition) { - return new ConditionalExistenceSet<>(set, existenceCondition); - } -} diff --git a/src/org/unitConverter/math/ConditionalExistenceCollectionsTest.java b/src/org/unitConverter/math/ConditionalExistenceCollectionsTest.java deleted file mode 100644 index 311ace5..0000000 --- a/src/org/unitConverter/math/ConditionalExistenceCollectionsTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.math; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; - -import org.junit.jupiter.api.Test; -import org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceIterator; - -/** - * Tests the {@link #ConditionalExistenceCollections}. - * - * @author Adrien Hopkins - * @since 2019-10-16 - */ -class ConditionalExistenceCollectionsTest { - - /** - * The returned iterator ignores elements that don't start with "a". - * - * @return test iterator - * @since 2019-10-17 - */ - ConditionalExistenceIterator getTestIterator() { - final List items = Arrays.asList("aa", "ab", "ba"); - final Iterator it = items.iterator(); - final ConditionalExistenceIterator cit = (ConditionalExistenceIterator) ConditionalExistenceCollections - .conditionalExistenceIterator(it, s -> s.startsWith("a")); - return cit; - } - - /** - * The returned map ignores mappings where the value is zero. - * - * @return map to be used for test data - * @since 2019-10-16 - */ - Map getTestMap() { - final Map map = new HashMap<>(); - map.put("one", 1); - map.put("two", 2); - map.put("zero", 0); - map.put("ten", 10); - final Map conditionalMap = ConditionalExistenceCollections.conditionalExistenceMap(map, - e -> !Integer.valueOf(0).equals(e.getValue())); - return conditionalMap; - } - - /** - * Test method for {@link org.unitConverter.math.ZeroIsNullMap#containsKey(java.lang.Object)}. - */ - @Test - void testContainsKeyObject() { - final Map map = this.getTestMap(); - assertTrue(map.containsKey("one")); - assertTrue(map.containsKey("ten")); - assertFalse(map.containsKey("five")); - assertFalse(map.containsKey("zero")); - } - - /** - * Test method for {@link org.unitConverter.math.ZeroIsNullMap#containsValue(java.lang.Object)}. - */ - @Test - void testContainsValueObject() { - final Map map = this.getTestMap(); - assertTrue(map.containsValue(1)); - assertTrue(map.containsValue(10)); - assertFalse(map.containsValue(5)); - assertFalse(map.containsValue(0)); - } - - /** - * Test method for {@link org.unitConverter.math.ZeroIsNullMap#entrySet()}. - */ - @Test - void testEntrySet() { - final Map map = this.getTestMap(); - for (final Entry e : map.entrySet()) { - assertTrue(e.getValue() != 0); - } - } - - /** - * Test method for {@link org.unitConverter.math.ZeroIsNullMap#get(java.lang.Object)}. - */ - @Test - void testGetObject() { - final Map map = this.getTestMap(); - assertEquals(1, map.get("one")); - assertEquals(10, map.get("ten")); - assertEquals(null, map.get("five")); - assertEquals(null, map.get("zero")); - } - - @Test - void testIterator() { - final ConditionalExistenceIterator testIterator = this.getTestIterator(); - - assertTrue(testIterator.hasNext); - assertTrue(testIterator.hasNext()); - assertEquals("aa", testIterator.nextElement); - assertEquals("aa", testIterator.next()); - - assertTrue(testIterator.hasNext); - assertTrue(testIterator.hasNext()); - assertEquals("ab", testIterator.nextElement); - assertEquals("ab", testIterator.next()); - - assertFalse(testIterator.hasNext); - assertFalse(testIterator.hasNext()); - assertEquals(null, testIterator.nextElement); - assertThrows(NoSuchElementException.class, testIterator::next); - } - - /** - * Test method for {@link org.unitConverter.math.ZeroIsNullMap#keySet()}. - */ - @Test - void testKeySet() { - final Map map = this.getTestMap(); - assertFalse(map.keySet().contains("zero")); - } - - /** - * Test method for {@link org.unitConverter.math.ZeroIsNullMap#values()}. - */ - @Test - void testValues() { - final Map map = this.getTestMap(); - assertFalse(map.values().contains(0)); - } - -} diff --git a/src/org/unitConverter/math/DecimalComparison.java b/src/org/unitConverter/math/DecimalComparison.java deleted file mode 100644 index 0f5b91e..0000000 --- a/src/org/unitConverter/math/DecimalComparison.java +++ /dev/null @@ -1,256 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.math; - -import java.math.BigDecimal; - -/** - * A class that contains methods to compare float and double values. - * - * @author Adrien Hopkins - * @since 2019-03-18 - * @since v0.2.0 - */ -public final class DecimalComparison { - /** - * The value used for double comparison. If two double values are within this - * value multiplied by the larger value, they are considered equal. - * - * @since 2019-03-18 - * @since v0.2.0 - */ - public static final double DOUBLE_EPSILON = 1.0e-15; - - /** - * The value used for float comparison. If two float values are within this - * value multiplied by the larger value, they are considered equal. - * - * @since 2019-03-18 - * @since v0.2.0 - */ - public static final float FLOAT_EPSILON = 1.0e-6f; - - /** - * Tests for equality of double values using {@link #DOUBLE_EPSILON}. - *

    - * WARNING: this method is not technically transitive. If a - * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, - * and b and c are off by slightly less than - * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) - * will both return true, but equals(a, c) will return false. However, this - * situation is very unlikely to ever happen in a real programming situation. - *

    - * If this does become a concern, some ways to solve this problem: - *

      - *
    1. Raise the value of epsilon using - * {@link #equals(double, double, double)} (this does not make a violation of - * transitivity impossible, it just significantly reduces the chances of it - * happening) - *
    2. Use {@link BigDecimal} instead of {@code double} (this will make a - * violation of transitivity 100% impossible) - *
    - * - * @param a first value to test - * @param b second value to test - * @return whether they are equal - * @since 2019-03-18 - * @since v0.2.0 - * @see #hashCode(double) - */ - public static final boolean equals(final double a, final double b) { - return DecimalComparison.equals(a, b, DOUBLE_EPSILON); - } - - /** - * Tests for double equality using a custom epsilon value. - * - *

    - * WARNING: this method is not technically transitive. If a - * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, - * and b and c are off by slightly less than - * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) - * will both return true, but equals(a, c) will return false. However, this - * situation is very unlikely to ever happen in a real programming situation. - *

    - * If this does become a concern, some ways to solve this problem: - *

      - *
    1. Raise the value of epsilon (this does not make a violation of - * transitivity impossible, it just significantly reduces the chances of it - * happening) - *
    2. Use {@link BigDecimal} instead of {@code double} (this will make a - * violation of transitivity 100% impossible) - *
    - * - * @param a first value to test - * @param b second value to test - * @param epsilon allowed difference - * @return whether they are equal - * @since 2019-03-18 - * @since v0.2.0 - */ - public static final boolean equals(final double a, final double b, - final double epsilon) { - return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b)); - } - - /** - * Tests for equality of float values using {@link #FLOAT_EPSILON}. - * - *

    - * WARNING: this method is not technically transitive. If a - * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, - * and b and c are off by slightly less than - * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) - * will both return true, but equals(a, c) will return false. However, this - * situation is very unlikely to ever happen in a real programming situation. - *

    - * If this does become a concern, some ways to solve this problem: - *

      - *
    1. Raise the value of epsilon using {@link #equals(float, float, float)} - * (this does not make a violation of transitivity impossible, it just - * significantly reduces the chances of it happening) - *
    2. Use {@link BigDecimal} instead of {@code float} (this will make a - * violation of transitivity 100% impossible) - *
    - * - * @param a first value to test - * @param b second value to test - * @return whether they are equal - * @since 2019-03-18 - * @since v0.2.0 - */ - public static final boolean equals(final float a, final float b) { - return DecimalComparison.equals(a, b, FLOAT_EPSILON); - } - - /** - * Tests for float equality using a custom epsilon value. - * - *

    - * WARNING: this method is not technically transitive. If a - * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, - * and b and c are off by slightly less than - * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) - * will both return true, but equals(a, c) will return false. However, this - * situation is very unlikely to ever happen in a real programming situation. - *

    - * If this does become a concern, some ways to solve this problem: - *

      - *
    1. Raise the value of epsilon (this does not make a violation of - * transitivity impossible, it just significantly reduces the chances of it - * happening) - *
    2. Use {@link BigDecimal} instead of {@code float} (this will make a - * violation of transitivity 100% impossible) - *
    - * - * @param a first value to test - * @param b second value to test - * @param epsilon allowed difference - * @return whether they are equal - * @since 2019-03-18 - * @since v0.2.0 - */ - public static final boolean equals(final float a, final float b, - final float epsilon) { - return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b)); - } - - /** - * Tests for equality of {@code UncertainDouble} values using - * {@link #DOUBLE_EPSILON}. - *

    - * WARNING: this method is not technically transitive. If a - * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, - * and b and c are off by slightly less than - * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) - * will both return true, but equals(a, c) will return false. However, this - * situation is very unlikely to ever happen in a real programming situation. - *

    - * If this does become a concern, some ways to solve this problem: - *

      - *
    1. Raise the value of epsilon using - * {@link #equals(UncertainDouble, UncertainDouble, double)} (this does not - * make a violation of transitivity impossible, it just significantly reduces - * the chances of it happening) - *
    2. Use {@link BigDecimal} instead of {@code double} (this will make a - * violation of transitivity 100% impossible) - *
    - * - * @param a first value to test - * @param b second value to test - * @return whether they are equal - * @since 2020-09-07 - * @see #hashCode(double) - */ - public static final boolean equals(final UncertainDouble a, - final UncertainDouble b) { - return DecimalComparison.equals(a.value(), b.value()) - && DecimalComparison.equals(a.uncertainty(), b.uncertainty()); - } - - /** - * Tests for {@code UncertainDouble} equality using a custom epsilon value. - * - *

    - * WARNING: this method is not technically transitive. If a - * and b are off by slightly less than {@code epsilon * max(abs(a), abs(b))}, - * and b and c are off by slightly less than - * {@code epsilon * max(abs(b), abs(c))}, then equals(a, b) and equals(b, c) - * will both return true, but equals(a, c) will return false. However, this - * situation is very unlikely to ever happen in a real programming situation. - *

    - * If this does become a concern, some ways to solve this problem: - *

      - *
    1. Raise the value of epsilon (this does not make a violation of - * transitivity impossible, it just significantly reduces the chances of it - * happening) - *
    2. Use {@link BigDecimal} instead of {@code double} (this will make a - * violation of transitivity 100% impossible) - *
    - * - * @param a first value to test - * @param b second value to test - * @param epsilon allowed difference - * @return whether they are equal - * @since 2019-03-18 - * @since v0.2.0 - */ - public static final boolean equals(final UncertainDouble a, - final UncertainDouble b, final double epsilon) { - return DecimalComparison.equals(a.value(), b.value(), epsilon) - && DecimalComparison.equals(a.uncertainty(), b.uncertainty(), - epsilon); - } - - /** - * Takes the hash code of doubles. Values that are equal according to - * {@link #equals(double, double)} will have the same hash code. - * - * @param d double to hash - * @return hash code of double - * @since 2019-10-16 - */ - public static final int hash(final double d) { - return Float.hashCode((float) d); - } - - // You may NOT get any DecimalComparison instances - private DecimalComparison() { - throw new AssertionError(); - } - -} diff --git a/src/org/unitConverter/math/ExpressionParser.java b/src/org/unitConverter/math/ExpressionParser.java deleted file mode 100644 index 8a0e97d..0000000 --- a/src/org/unitConverter/math/ExpressionParser.java +++ /dev/null @@ -1,708 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.math; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Deque; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.function.UnaryOperator; - -/** - * An object that can parse expressions with unary or binary operators. - * - * @author Adrien Hopkins - * @param - * type of object that exists in parsed expressions - * @since 2019-03-14 - * @since v0.2.0 - */ -public final class ExpressionParser { - /** - * A builder that can create {@code ExpressionParser} instances. - * - * @author Adrien Hopkins - * @param - * type of object that exists in parsed expressions - * @since 2019-03-17 - * @since v0.2.0 - */ - public static final class Builder { - /** - * A function that obtains a parseable object from a string. For example, an integer {@code ExpressionParser} - * would use {@code Integer::parseInt}. - * - * @since 2019-03-14 - * @since v0.2.0 - */ - private final Function objectObtainer; - - /** - * The function of the space as an operator (like 3 x y) - * - * @since 2019-03-22 - * @since v0.2.0 - */ - private String spaceFunction = null; - - /** - * A map mapping operator strings to operator functions, for unary operators. - * - * @since 2019-03-14 - * @since v0.2.0 - */ - private final Map> unaryOperators; - - /** - * A map mapping operator strings to operator functions, for binary operators. - * - * @since 2019-03-14 - * @since v0.2.0 - */ - private final Map> binaryOperators; - - /** - * Creates the {@code Builder}. - * - * @param objectObtainer - * a function that can turn strings into objects of the type handled by the parser. - * @throws NullPointerException - * if {@code objectObtainer} is null - * @since 2019-03-17 - * @since v0.2.0 - */ - public Builder(final Function objectObtainer) { - this.objectObtainer = Objects.requireNonNull(objectObtainer, "objectObtainer must not be null."); - this.unaryOperators = new HashMap<>(); - this.binaryOperators = new HashMap<>(); - } - - /** - * Adds a binary operator to the builder. - * - * @param text - * text used to reference the operator, like '+' - * @param operator - * operator to add - * @param priority - * operator's priority, which determines which operators are applied first - * @return this builder - * @throws NullPointerException - * if {@code text} or {@code operator} is null - * @since 2019-03-17 - * @since v0.2.0 - */ - public Builder addBinaryOperator(final String text, final BinaryOperator operator, final int priority) { - Objects.requireNonNull(text, "text must not be null."); - Objects.requireNonNull(operator, "operator must not be null."); - - // Unfortunately, I cannot use a lambda because the PriorityBinaryOperator requires arguments. - final PriorityBinaryOperator priorityOperator = new PriorityBinaryOperator(priority) { - @Override - public T apply(final T t, final T u) { - return operator.apply(t, u); - } - - }; - this.binaryOperators.put(text, priorityOperator); - return this; - } - - /** - * Adds a function for spaces. You must use the text of an existing binary operator. - * - * @param operator - * text of operator to use - * @return this builder - * @since 2019-03-22 - * @since v0.2.0 - */ - public Builder addSpaceFunction(final String operator) { - Objects.requireNonNull(operator, "operator must not be null."); - - if (!this.binaryOperators.containsKey(operator)) - throw new IllegalArgumentException(String.format("Could not find binary operator '%s'", operator)); - - this.spaceFunction = operator; - return this; - } - - /** - * Adds a unary operator to the builder. - * - * @param text - * text used to reference the operator, like '-' - * @param operator - * operator to add - * @param priority - * operator's priority, which determines which operators are applied first - * @return this builder - * @throws NullPointerException - * if {@code text} or {@code operator} is null - * @since 2019-03-17 - * @since v0.2.0 - */ - public Builder addUnaryOperator(final String text, final UnaryOperator operator, final int priority) { - Objects.requireNonNull(text, "text must not be null."); - Objects.requireNonNull(operator, "operator must not be null."); - - // Unfortunately, I cannot use a lambda because the PriorityUnaryOperator requires arguments. - final PriorityUnaryOperator priorityOperator = new PriorityUnaryOperator(priority) { - @Override - public T apply(final T t) { - return operator.apply(t); - } - }; - this.unaryOperators.put(text, priorityOperator); - return this; - } - - /** - * @return an {@code ExpressionParser} instance with the properties given to this builder - * @since 2019-03-17 - * @since v0.2.0 - */ - public ExpressionParser build() { - return new ExpressionParser<>(this.objectObtainer, this.unaryOperators, this.binaryOperators, - this.spaceFunction); - } - } - - /** - * A binary operator with a priority field that determines which operators apply first. - * - * @author Adrien Hopkins - * @param - * type of operand and result - * @since 2019-03-17 - * @since v0.2.0 - */ - private static abstract class PriorityBinaryOperator - implements BinaryOperator, Comparable> { - /** - * The operator's priority. Higher-priority operators are applied before lower-priority operators - * - * @since 2019-03-17 - * @since v0.2.0 - */ - private final int priority; - - /** - * Creates the {@code PriorityBinaryOperator}. - * - * @param priority - * operator's priority - * @since 2019-03-17 - * @since v0.2.0 - */ - public PriorityBinaryOperator(final int priority) { - this.priority = priority; - } - - /** - * Compares this object to another by priority. - * - *

    - * {@inheritDoc} - *

    - * - * @since 2019-03-17 - * @since v0.2.0 - */ - @Override - public int compareTo(final PriorityBinaryOperator o) { - if (this.priority < o.priority) - return -1; - else if (this.priority > o.priority) - return 1; - else - return 0; - } - - /** - * @return priority - * @since 2019-03-22 - * @since v0.2.0 - */ - public final int getPriority() { - return this.priority; - } - } - - /** - * A unary operator with a priority field that determines which operators apply first. - * - * @author Adrien Hopkins - * @param - * type of operand and result - * @since 2019-03-17 - * @since v0.2.0 - */ - private static abstract class PriorityUnaryOperator - implements UnaryOperator, Comparable> { - /** - * The operator's priority. Higher-priority operators are applied before lower-priority operators - * - * @since 2019-03-17 - * @since v0.2.0 - */ - private final int priority; - - /** - * Creates the {@code PriorityUnaryOperator}. - * - * @param priority - * operator's priority - * @since 2019-03-17 - * @since v0.2.0 - */ - public PriorityUnaryOperator(final int priority) { - this.priority = priority; - } - - /** - * Compares this object to another by priority. - * - *

    - * {@inheritDoc} - *

    - * - * @since 2019-03-17 - * @since v0.2.0 - */ - @Override - public int compareTo(final PriorityUnaryOperator o) { - if (this.priority < o.priority) - return -1; - else if (this.priority > o.priority) - return 1; - else - return 0; - } - - /** - * @return priority - * @since 2019-03-22 - * @since v0.2.0 - */ - public final int getPriority() { - return this.priority; - } - } - - /** - * The types of tokens that are available. - * - * @author Adrien Hopkins - * @since 2019-03-14 - * @since v0.2.0 - */ - private static enum TokenType { - OBJECT, UNARY_OPERATOR, BINARY_OPERATOR; - } - - /** - * The opening bracket. - * - * @since 2019-03-22 - * @since v0.2.0 - */ - public static final char OPENING_BRACKET = '('; - - /** - * The closing bracket. - * - * @since 2019-03-22 - * @since v0.2.0 - */ - public static final char CLOSING_BRACKET = ')'; - - /** - * Finds the other bracket in a pair of brackets, given the position of one. - * - * @param string - * string that contains brackets - * @param bracketPosition - * position of first bracket - * @return position of matching bracket - * @throws NullPointerException - * if string is null - * @since 2019-03-22 - * @since v0.2.0 - */ - private static int findBracketPair(final String string, final int bracketPosition) { - Objects.requireNonNull(string, "string must not be null."); - - final char openingBracket = string.charAt(bracketPosition); - - // figure out what closing bracket to look for - final char closingBracket; - switch (openingBracket) { - case '(': - closingBracket = ')'; - break; - case '[': - closingBracket = ']'; - break; - case '{': - closingBracket = '}'; - break; - default: - throw new IllegalArgumentException(String.format("Invalid bracket '%s'", openingBracket)); - } - - // level of brackets. every opening bracket increments this; every closing bracket decrements it - int bracketLevel = 0; - - // iterate over the string to find the closing bracket - for (int currentPosition = bracketPosition; currentPosition < string.length(); currentPosition++) { - final char currentCharacter = string.charAt(currentPosition); - - if (currentCharacter == openingBracket) { - bracketLevel++; - } else if (currentCharacter == closingBracket) { - bracketLevel--; - if (bracketLevel == 0) - return currentPosition; - } - } - - throw new IllegalArgumentException("No matching bracket found."); - } - - /** - * A function that obtains a parseable object from a string. For example, an integer {@code ExpressionParser} would - * use {@code Integer::parseInt}. - * - * @since 2019-03-14 - * @since v0.2.0 - */ - private final Function objectObtainer; - - /** - * A map mapping operator strings to operator functions, for unary operators. - * - * @since 2019-03-14 - * @since v0.2.0 - */ - private final Map> unaryOperators; - - /** - * A map mapping operator strings to operator functions, for binary operators. - * - * @since 2019-03-14 - * @since v0.2.0 - */ - private final Map> binaryOperators; - - /** - * The operator for space, or null if spaces have no function. - * - * @since 2019-03-22 - * @since v0.2.0 - */ - private final String spaceOperator; - - /** - * Creates the {@code ExpressionParser}. - * - * @param objectObtainer - * function to get objects from strings - * @param unaryOperators - * unary operators available to the parser - * @param binaryOperators - * binary operators available to the parser - * @param spaceOperator - * operator used by spaces - * @since 2019-03-14 - * @since v0.2.0 - */ - private ExpressionParser(final Function objectObtainer, - final Map> unaryOperators, - final Map> binaryOperators, final String spaceOperator) { - this.objectObtainer = objectObtainer; - this.unaryOperators = unaryOperators; - this.binaryOperators = binaryOperators; - this.spaceOperator = spaceOperator; - } - - /** - * Converts a given mathematical expression to reverse Polish notation (operators after operands). - *

    - * For example,
    - * {@code 2 * (3 + 4)}
    - * becomes
    - * {@code 2 3 4 + *}. - * - * @param expression - * expression - * @return expression in RPN - * @since 2019-03-17 - * @since v0.2.0 - */ - private String convertExpressionToReversePolish(final String expression) { - Objects.requireNonNull(expression, "expression must not be null."); - - final List components = new ArrayList<>(); - - // the part of the expression remaining to parse - String partialExpression = expression; - - // find and deal with brackets - while (partialExpression.indexOf(OPENING_BRACKET) != -1) { - final int openingBracketPosition = partialExpression.indexOf(OPENING_BRACKET); - final int closingBracketPosition = findBracketPair(partialExpression, openingBracketPosition); - - // check for function - if (openingBracketPosition > 0 && partialExpression.charAt(openingBracketPosition - 1) != ' ') { - // function like sin(2) or tempF(32) - // find the position of the last space - int spacePosition = openingBracketPosition; - while (spacePosition >= 0 && partialExpression.charAt(spacePosition) != ' ') { - spacePosition--; - } - // then split the function into pre-function and function, using the space position - components.addAll(Arrays.asList(partialExpression.substring(0, spacePosition + 1).split(" "))); - components.add(partialExpression.substring(spacePosition + 1, closingBracketPosition + 1)); - partialExpression = partialExpression.substring(closingBracketPosition + 1); - } else { - // normal brackets like (1 + 2) * (3 / 5) - components.addAll(Arrays.asList(partialExpression.substring(0, openingBracketPosition).split(" "))); - components.add(this.convertExpressionToReversePolish( - partialExpression.substring(openingBracketPosition + 1, closingBracketPosition))); - partialExpression = partialExpression.substring(closingBracketPosition + 1); - } - } - - // add everything else - components.addAll(Arrays.asList(partialExpression.split(" "))); - - // remove empty entries - while (components.contains("")) { - components.remove(""); - } - - // deal with space multiplication (x y) - if (this.spaceOperator != null) { - for (int i = 0; i < components.size() - 1; i++) { - if (this.getTokenType(components.get(i)) == TokenType.OBJECT - && this.getTokenType(components.get(i + 1)) == TokenType.OBJECT) { - components.add(++i, this.spaceOperator); - } - } - } - - // turn the expression into reverse Polish - while (true) { - final int highestPriorityOperatorPosition = this.findHighestPriorityOperatorPosition(components); - if (highestPriorityOperatorPosition == -1) { - break; - } - - // swap components based on what kind of operator there is - // 1 + 2 becomes 2 1 + - // - 1 becomes 1 - - switch (this.getTokenType(components.get(highestPriorityOperatorPosition))) { - case UNARY_OPERATOR: - final String unaryOperator = components.remove(highestPriorityOperatorPosition); - final String operand = components.remove(highestPriorityOperatorPosition); - components.add(highestPriorityOperatorPosition, operand + " " + unaryOperator); - break; - case BINARY_OPERATOR: - final String binaryOperator = components.remove(highestPriorityOperatorPosition); - final String operand1 = components.remove(highestPriorityOperatorPosition - 1); - final String operand2 = components.remove(highestPriorityOperatorPosition - 1); - components.add(highestPriorityOperatorPosition - 1, - operand2 + " " + operand1 + " " + binaryOperator); - break; - default: - throw new AssertionError("Expected operator, found non-operator."); - } - } - - // join all of the components together, then ensure there is only one space in a row - String expressionRPN = String.join(" ", components).replaceAll(" +", " "); - - while (expressionRPN.charAt(0) == ' ') { - expressionRPN = expressionRPN.substring(1); - } - while (expressionRPN.charAt(expressionRPN.length() - 1) == ' ') { - expressionRPN = expressionRPN.substring(0, expressionRPN.length() - 1); - } - return expressionRPN; - } - - /** - * Finds the position of the highest-priority operator in a list - * - * @param components - * components to test - * @param blacklist - * positions of operators that should be ignored - * @return position of highest priority, or -1 if the list contains no operators - * @throws NullPointerException - * if components is null - * @since 2019-03-22 - * @since v0.2.0 - */ - private int findHighestPriorityOperatorPosition(final List components) { - Objects.requireNonNull(components, "components must not be null."); - // find highest priority - int maxPriority = Integer.MIN_VALUE; - int maxPriorityPosition = -1; - - // go over components one by one - // if it is an operator, test its priority to see if it's max - // if it is, update maxPriority and maxPriorityPosition - for (int i = 0; i < components.size(); i++) { - - switch (this.getTokenType(components.get(i))) { - case UNARY_OPERATOR: - final PriorityUnaryOperator unaryOperator = this.unaryOperators.get(components.get(i)); - final int unaryPriority = unaryOperator.getPriority(); - - if (unaryPriority > maxPriority) { - maxPriority = unaryPriority; - maxPriorityPosition = i; - } - break; - case BINARY_OPERATOR: - final PriorityBinaryOperator binaryOperator = this.binaryOperators.get(components.get(i)); - final int binaryPriority = binaryOperator.getPriority(); - - if (binaryPriority > maxPriority) { - maxPriority = binaryPriority; - maxPriorityPosition = i; - } - break; - default: - break; - } - } - - // max priority position found - return maxPriorityPosition; - } - - /** - * Determines whether an inputted string is an object or an operator - * - * @param token - * string to input - * @return type of token it is - * @throws NullPointerException - * if {@code expression} is null - * @since 2019-03-14 - * @since v0.2.0 - */ - private TokenType getTokenType(final String token) { - Objects.requireNonNull(token, "token must not be null."); - - if (this.unaryOperators.containsKey(token)) - return TokenType.UNARY_OPERATOR; - else if (this.binaryOperators.containsKey(token)) - return TokenType.BINARY_OPERATOR; - else - return TokenType.OBJECT; - } - - /** - * Parses an expression. - * - * @param expression - * expression to parse - * @return result - * @throws NullPointerException - * if {@code expression} is null - * @since 2019-03-14 - * @since v0.2.0 - */ - public T parseExpression(final String expression) { - return this.parseReversePolishExpression(this.convertExpressionToReversePolish(expression)); - } - - /** - * Parses an expression expressed in reverse Polish notation. - * - * @param expression - * expression to parse - * @return result - * @throws NullPointerException - * if {@code expression} is null - * @since 2019-03-14 - * @since v0.2.0 - */ - private T parseReversePolishExpression(final String expression) { - Objects.requireNonNull(expression, "expression must not be null."); - - final Deque stack = new ArrayDeque<>(); - - // iterate over every item in the expression, then - for (final String item : expression.split(" ")) { - // choose a path based on what kind of thing was just read - switch (this.getTokenType(item)) { - - case BINARY_OPERATOR: - if (stack.size() < 2) - throw new IllegalStateException(String.format( - "Attempted to call binary operator %s with only %d arguments.", item, stack.size())); - - // get two arguments and operator, then apply! - final T o1 = stack.pop(); - final T o2 = stack.pop(); - final BinaryOperator binaryOperator = this.binaryOperators.get(item); - - stack.push(binaryOperator.apply(o1, o2)); - break; - - case OBJECT: - // just add it to the stack - stack.push(this.objectObtainer.apply(item)); - break; - - case UNARY_OPERATOR: - if (stack.size() < 1) - throw new IllegalStateException(String.format( - "Attempted to call unary operator %s with only %d arguments.", item, stack.size())); - - // get one argument and operator, then apply! - final T o = stack.pop(); - final UnaryOperator unaryOperator = this.unaryOperators.get(item); - - stack.push(unaryOperator.apply(o)); - break; - default: - throw new AssertionError( - String.format("Internal error: Invalid token type %s.", this.getTokenType(item))); - - } - } - - // return answer, or throw an exception if I can't - if (stack.size() > 1) - throw new IllegalStateException("Computation ended up with more than one answer."); - else if (stack.size() == 0) - throw new IllegalStateException("Computation ended up without an answer."); - return stack.pop(); - } -} diff --git a/src/org/unitConverter/math/ExpressionParserTest.java b/src/org/unitConverter/math/ExpressionParserTest.java deleted file mode 100644 index f3180c1..0000000 --- a/src/org/unitConverter/math/ExpressionParserTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.math; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.Test; - -/** - * A test for the {@code ExpressionParser} class. This is NOT part of this program's public API. - * - * @author Adrien Hopkins - * @since 2019-03-22 - * @since v0.2.0 - */ -class ExpressionParserTest { - private static final ExpressionParser numberParser = new ExpressionParser.Builder<>(Integer::parseInt) - .addBinaryOperator("+", (o1, o2) -> o1 + o2, 0).addBinaryOperator("-", (o1, o2) -> o1 - o2, 0) - .addBinaryOperator("*", (o1, o2) -> o1 * o2, 1).addBinaryOperator("/", (o1, o2) -> o1 / o2, 1) - .addBinaryOperator("^", (o1, o2) -> (int) Math.pow(o1, o2), 2).build(); - - /** - * Test method for {@link org.unitConverter.math.ExpressionParser#parseExpression(java.lang.String)}. - */ - @Test - public void testParseExpression() { - // test parsing of expressions - assertEquals((int) numberParser.parseExpression("1 + 2 ^ 5 * 3"), 97); - assertEquals((int) numberParser.parseExpression("(1 + 2) ^ 5 * 3"), 729); - - // ensure it normally goes left to right - assertEquals((int) numberParser.parseExpression("1 + 2 + 3 + 4"), 10); - assertEquals((int) numberParser.parseExpression("12 - 4 - 3"), 5); - assertEquals((int) numberParser.parseExpression("12 - (4 - 3)"), 11); - assertEquals((int) numberParser.parseExpression("1 / 2 + 3"), 3); - } - -} diff --git a/src/org/unitConverter/math/ObjectProduct.java b/src/org/unitConverter/math/ObjectProduct.java deleted file mode 100644 index bf00647..0000000 --- a/src/org/unitConverter/math/ObjectProduct.java +++ /dev/null @@ -1,284 +0,0 @@ -/** - * Copyright (C) 2018 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.math; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.function.Function; - -/** - * An immutable product of multiple objects of a type, such as base units. The objects can be multiplied and - * exponentiated. - * - * @author Adrien Hopkins - * @since 2019-10-16 - */ -public final class ObjectProduct { - /** - * Returns an empty ObjectProduct of a certain type - * - * @param - * type of objects that can be multiplied - * @return empty product - * @since 2019-10-16 - */ - public static final ObjectProduct empty() { - return new ObjectProduct<>(new HashMap<>()); - } - - /** - * Gets an {@code ObjectProduct} from an object-to-integer mapping - * - * @param - * type of object in product - * @param map - * map mapping objects to exponents - * @return object product - * @since 2019-10-16 - */ - public static final ObjectProduct fromExponentMapping(final Map map) { - return new ObjectProduct<>(new HashMap<>(map)); - } - - /** - * Gets an ObjectProduct that has one of the inputted argument, and nothing else. - * - * @param object - * object that will be in the product - * @return product - * @since 2019-10-16 - * @throws NullPointerException - * if object is null - */ - public static final ObjectProduct oneOf(final T object) { - Objects.requireNonNull(object, "object must not be null."); - final Map map = new HashMap<>(); - map.put(object, 1); - return new ObjectProduct<>(map); - } - - /** - * The objects that make up the product, mapped to their exponents. This map treats zero as null, and is immutable. - * - * @since 2019-10-16 - */ - final Map exponents; - - /** - * Creates the {@code ObjectProduct}. - * - * @param exponents - * objects that make up this product - * @since 2019-10-16 - */ - private ObjectProduct(final Map exponents) { - this.exponents = Collections.unmodifiableMap(ConditionalExistenceCollections.conditionalExistenceMap(exponents, - e -> !Integer.valueOf(0).equals(e.getValue()))); - } - - /** - * Calculates the quotient of two products - * - * @param other - * other product - * @return quotient of two products - * @since 2019-10-16 - * @throws NullPointerException - * if other is null - */ - public ObjectProduct dividedBy(final ObjectProduct other) { - Objects.requireNonNull(other, "other must not be null."); - // get a list of all objects in both sets - final Set objects = new HashSet<>(); - objects.addAll(this.getBaseSet()); - objects.addAll(other.getBaseSet()); - - // get a list of all exponents - final Map map = new HashMap<>(objects.size()); - for (final T key : objects) { - map.put(key, this.getExponent(key) - other.getExponent(key)); - } - - // create the product - return new ObjectProduct<>(map); - } - - // this method relies on the use of ZeroIsNullMap - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (!(obj instanceof ObjectProduct)) - return false; - final ObjectProduct other = (ObjectProduct) obj; - return Objects.equals(this.exponents, other.exponents); - } - - /** - * @return immutable map mapping objects to exponents - * @since 2019-10-16 - */ - public Map exponentMap() { - return this.exponents; - } - - /** - * @return a set of all of the base objects with non-zero exponents that make up this dimension. - * @since 2018-12-12 - * @since v0.1.0 - */ - public final Set getBaseSet() { - final Set dimensions = new HashSet<>(); - - // add all dimensions with a nonzero exponent - zero exponents shouldn't be there in the first place - for (final T dimension : this.exponents.keySet()) { - if (!this.exponents.get(dimension).equals(0)) { - dimensions.add(dimension); - } - } - - return dimensions; - } - - /** - * Gets the exponent for a specific dimension. - * - * @param dimension - * dimension to check - * @return exponent for that dimension - * @since 2018-12-12 - * @since v0.1.0 - */ - public int getExponent(final T dimension) { - return this.exponents.getOrDefault(dimension, 0); - } - - @Override - public int hashCode() { - return Objects.hash(this.exponents); - } - - /** - * @return true if this product is a single object, i.e. it has one exponent of one and no other nonzero exponents - * @since 2019-10-16 - */ - public boolean isSingleObject() { - int oneCount = 0; - boolean twoOrMore = false; // has exponents of 2 or more - for (final T b : this.getBaseSet()) { - if (this.getExponent(b) == 1) { - oneCount++; - } else if (this.getExponent(b) != 0) { - twoOrMore = true; - } - } - return oneCount == 1 && !twoOrMore; - } - - /** - * Multiplies this product by another - * - * @param other - * other product - * @return product of two products - * @since 2019-10-16 - * @throws NullPointerException - * if other is null - */ - public ObjectProduct times(final ObjectProduct other) { - Objects.requireNonNull(other, "other must not be null."); - // get a list of all objects in both sets - final Set objects = new HashSet<>(); - objects.addAll(this.getBaseSet()); - objects.addAll(other.getBaseSet()); - - // get a list of all exponents - final Map map = new HashMap<>(objects.size()); - for (final T key : objects) { - map.put(key, this.getExponent(key) + other.getExponent(key)); - } - - // create the product - return new ObjectProduct<>(map); - } - - /** - * Returns this product, but to an exponent - * - * @param exponent - * exponent - * @return result of exponentiation - * @since 2019-10-16 - */ - public ObjectProduct toExponent(final int exponent) { - final Map map = new HashMap<>(this.exponents); - for (final T key : this.exponents.keySet()) { - map.put(key, this.getExponent(key) * exponent); - } - return new ObjectProduct<>(map); - } - - /** - * Converts this product to a string using the objects' {@link Object#toString()} method. If objects have a long - * toString representation, it is recommended to use {@link #toString(Function)} instead to shorten the returned - * string. - * - *

    - * {@inheritDoc} - */ - @Override - public String toString() { - return this.toString(Object::toString); - } - - /** - * Converts this product to a string. The objects that make up this product are represented by - * {@code objectToString} - * - * @param objectToString - * function to convert objects to strings - * @return string representation of product - * @since 2019-10-16 - */ - public String toString(final Function objectToString) { - final List positiveStringComponents = new ArrayList<>(); - final List negativeStringComponents = new ArrayList<>(); - - // for each base object that makes up this object, add it and its exponent - for (final T object : this.getBaseSet()) { - final int exponent = this.exponents.get(object); - if (exponent > 0) { - positiveStringComponents.add(String.format("%s^%d", objectToString.apply(object), exponent)); - } else if (exponent < 0) { - negativeStringComponents.add(String.format("%s^%d", objectToString.apply(object), -exponent)); - } - } - - final String positiveString = positiveStringComponents.isEmpty() ? "1" - : String.join(" * ", positiveStringComponents); - final String negativeString = negativeStringComponents.isEmpty() ? "" - : " / " + String.join(" * ", negativeStringComponents); - - return positiveString + negativeString; - } -} diff --git a/src/org/unitConverter/math/ObjectProductTest.java b/src/org/unitConverter/math/ObjectProductTest.java deleted file mode 100644 index afd18b7..0000000 --- a/src/org/unitConverter/math/ObjectProductTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright (C) 2018 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.math; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.unitConverter.unit.SI.Dimensions.AREA; -import static org.unitConverter.unit.SI.Dimensions.ENERGY; -import static org.unitConverter.unit.SI.Dimensions.LENGTH; -import static org.unitConverter.unit.SI.Dimensions.MASS; -import static org.unitConverter.unit.SI.Dimensions.MASS_DENSITY; -import static org.unitConverter.unit.SI.Dimensions.QUANTITY; -import static org.unitConverter.unit.SI.Dimensions.TIME; -import static org.unitConverter.unit.SI.Dimensions.VOLUME; - -import org.junit.jupiter.api.Test; -import org.unitConverter.unit.SI; - -/** - * Tests for {@link ObjectProduct} using BaseDimension as a test object. This is NOT part of this program's public API. - * - * @author Adrien Hopkins - * @since 2018-12-12 - * @since v0.1.0 - */ -class ObjectProductTest { - /** - * Tests {@link UnitDimension#equals} - * - * @since 2018-12-12 - * @since v0.1.0 - */ - @Test - public void testEquals() { - assertEquals(LENGTH, LENGTH); - assertFalse(LENGTH.equals(QUANTITY)); - } - - /** - * Tests {@code UnitDimension}'s exponentiation - * - * @since 2019-01-15 - * @since v0.1.0 - */ - @Test - public void testExponents() { - assertEquals(1, LENGTH.getExponent(SI.BaseDimensions.LENGTH)); - assertEquals(3, VOLUME.getExponent(SI.BaseDimensions.LENGTH)); - } - - /** - * Tests {@code UnitDimension}'s multiplication and division. - * - * @since 2018-12-12 - * @since v0.1.0 - */ - @Test - public void testMultiplicationAndDivision() { - assertEquals(AREA, LENGTH.times(LENGTH)); - assertEquals(MASS_DENSITY, MASS.dividedBy(VOLUME)); - assertEquals(ENERGY, AREA.times(MASS).dividedBy(TIME).dividedBy(TIME)); - assertEquals(LENGTH, LENGTH.times(TIME).dividedBy(TIME)); - } -} diff --git a/src/org/unitConverter/math/UncertainDouble.java b/src/org/unitConverter/math/UncertainDouble.java deleted file mode 100644 index 3651bd5..0000000 --- a/src/org/unitConverter/math/UncertainDouble.java +++ /dev/null @@ -1,419 +0,0 @@ -/** - * Copyright (C) 2020 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.math; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A double with an associated uncertainty value. For example, 3.2 ± 0.2. - *

    - * All methods in this class throw a NullPointerException if any of their - * arguments is null. - * - * @since 2020-09-07 - */ -public final class UncertainDouble implements Comparable { - /** - * The exact value 0 - */ - public static final UncertainDouble ZERO = UncertainDouble.of(0, 0); - - /** - * A regular expression that can recognize toString forms - */ - private static final Pattern TO_STRING = Pattern - .compile("([a-zA-Z_0-9\\.\\,]+)" // a number - // optional "± [number]" - + "(?:\\s*(?:±|\\+-)\\s*([a-zA-Z_0-9\\.\\,]+))?"); - - /** - * Parses a string in the form of {@link UncertainDouble#toString(boolean)} - * and returns the corresponding {@code UncertainDouble} instance. - *

    - * This method allows some alternative forms of the string representation, - * such as using "+-" instead of "±". - * - * @param s string to parse - * @return {@code UncertainDouble} instance - * @throws IllegalArgumentException if the string is invalid - * @since 2020-09-07 - */ - public static final UncertainDouble fromString(String s) { - Objects.requireNonNull(s, "s may not be null"); - final Matcher matcher = TO_STRING.matcher(s); - - double value, uncertainty; - try { - value = Double.parseDouble(matcher.group(1)); - } catch (IllegalStateException | NumberFormatException e) { - throw new IllegalArgumentException( - "String " + s + " not in correct format."); - } - - final String uncertaintyString = matcher.group(2); - if (uncertaintyString == null) { - uncertainty = 0; - } else { - try { - uncertainty = Double.parseDouble(uncertaintyString); - } catch (final NumberFormatException e) { - throw new IllegalArgumentException( - "String " + s + " not in correct format."); - } - } - - return UncertainDouble.of(value, uncertainty); - } - - /** - * Gets an {@code UncertainDouble} from its value and absolute - * uncertainty. - * - * @since 2020-09-07 - */ - public static final UncertainDouble of(double value, double uncertainty) { - return new UncertainDouble(value, uncertainty); - } - - /** - * Gets an {@code UncertainDouble} from its value and relative - * uncertainty. - * - * @since 2020-09-07 - */ - public static final UncertainDouble ofRelative(double value, - double relativeUncertainty) { - return new UncertainDouble(value, value * relativeUncertainty); - } - - private final double value; - - private final double uncertainty; - - /** - * @param value - * @param uncertainty - * @since 2020-09-07 - */ - private UncertainDouble(double value, double uncertainty) { - this.value = value; - // uncertainty should only ever be positive - this.uncertainty = Math.abs(uncertainty); - } - - /** - * Compares this {@code UncertainDouble} with another - * {@code UncertainDouble}. - *

    - * This method only compares the values, not the uncertainties. So 3.1 ± 0.5 - * is considered less than 3.2 ± 0.5, even though they are equivalent. - *

    - * Note: The natural ordering of this class is inconsistent with - * equals. Specifically, if two {@code UncertainDouble} instances {@code a} - * and {@code b} have the same value but different uncertainties, - * {@code a.compareTo(b)} will return 0 but {@code a.equals(b)} will return - * {@code false}. - */ - @Override - public final int compareTo(UncertainDouble o) { - return Double.compare(this.value, o.value); - } - - /** - * Returns the quotient of {@code this} and {@code other}. - * - * @since 2020-09-07 - */ - public final UncertainDouble dividedBy(UncertainDouble other) { - Objects.requireNonNull(other, "other may not be null"); - return UncertainDouble.ofRelative(this.value / other.value, Math - .hypot(this.relativeUncertainty(), other.relativeUncertainty())); - } - - /** - * Returns the quotient of {@code this} and the exact value {@code other}. - * - * @since 2020-09-07 - */ - public final UncertainDouble dividedByExact(double other) { - return UncertainDouble.of(this.value / other, this.uncertainty / other); - } - - @Override - public final boolean equals(Object obj) { - if (this == obj) - return true; - if (!(obj instanceof UncertainDouble)) - return false; - final UncertainDouble other = (UncertainDouble) obj; - if (Double.compare(this.value, other.value) != 0) - return false; - if (Double.compare(this.uncertainty, other.uncertainty) != 0) - return false; - return true; - } - - /** - * @param other another {@code UncertainDouble} - * @return true iff this and {@code other} are within each other's - * uncertainty range. - * @since 2020-09-07 - */ - public final boolean equivalent(UncertainDouble other) { - Objects.requireNonNull(other, "other may not be null"); - return Math.abs(this.value - other.value) <= Math.min(this.uncertainty, - other.uncertainty); - } - - /** - * Gets the preferred scale for rounding a value for toString. - * - * @since 2020-09-07 - */ - private final int getDisplayScale() { - // round based on uncertainty - // if uncertainty starts with 1 (ignoring zeroes and the decimal - // point), rounds - // so that uncertainty has 2 significant digits. - // otherwise, rounds so that uncertainty has 1 significant digits. - // the value is rounded to the same number of decimal places as the - // uncertainty. - final BigDecimal bigUncertainty = BigDecimal.valueOf(this.uncertainty); - - // the scale that will give the uncertainty two decimal places - final int twoDecimalPlacesScale = bigUncertainty.scale() - - bigUncertainty.precision() + 2; - final BigDecimal roundedUncertainty = bigUncertainty - .setScale(twoDecimalPlacesScale, RoundingMode.HALF_EVEN); - - if (roundedUncertainty.unscaledValue().intValue() >= 20) - return twoDecimalPlacesScale - 1; // one decimal place - else - return twoDecimalPlacesScale; - } - - @Override - public final int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Double.hashCode(this.value); - result = prime * result + Double.hashCode(this.uncertainty); - return result; - } - - /** - * @return true iff the value has no uncertainty - * - * @since 2020-09-07 - */ - public final boolean isExact() { - return this.uncertainty == 0; - } - - /** - * Returns the difference of {@code this} and {@code other}. - * - * @since 2020-09-07 - */ - public final UncertainDouble minus(UncertainDouble other) { - Objects.requireNonNull(other, "other may not be null"); - return UncertainDouble.of(this.value - other.value, - Math.hypot(this.uncertainty, other.uncertainty)); - } - - /** - * Returns the difference of {@code this} and the exact value {@code other}. - * - * @since 2020-09-07 - */ - public final UncertainDouble minusExact(double other) { - return UncertainDouble.of(this.value - other, this.uncertainty); - } - - /** - * Returns the sum of {@code this} and {@code other}. - * - * @since 2020-09-07 - */ - public final UncertainDouble plus(UncertainDouble other) { - Objects.requireNonNull(other, "other may not be null"); - return UncertainDouble.of(this.value + other.value, - Math.hypot(this.uncertainty, other.uncertainty)); - } - - /** - * Returns the sum of {@code this} and the exact value {@code other}. - * - * @since 2020-09-07 - */ - public final UncertainDouble plusExact(double other) { - return UncertainDouble.of(this.value + other, this.uncertainty); - } - - /** - * @return relative uncertainty - * @since 2020-09-07 - */ - public final double relativeUncertainty() { - return this.uncertainty / this.value; - } - - /** - * Returns the product of {@code this} and {@code other}. - * - * @since 2020-09-07 - */ - public final UncertainDouble times(UncertainDouble other) { - Objects.requireNonNull(other, "other may not be null"); - return UncertainDouble.ofRelative(this.value * other.value, Math - .hypot(this.relativeUncertainty(), other.relativeUncertainty())); - } - - /** - * Returns the product of {@code this} and the exact value {@code other}. - * - * @since 2020-09-07 - */ - public final UncertainDouble timesExact(double other) { - return UncertainDouble.of(this.value * other, this.uncertainty * other); - } - - /** - * Returns the result of {@code this} raised to the exponent {@code other}. - * - * @since 2020-09-07 - */ - public final UncertainDouble toExponent(UncertainDouble other) { - Objects.requireNonNull(other, "other may not be null"); - - final double result = Math.pow(this.value, other.value); - final double relativeUncertainty = Math.hypot( - other.value * this.relativeUncertainty(), - Math.log(this.value) * other.uncertainty); - - return UncertainDouble.ofRelative(result, relativeUncertainty); - } - - /** - * Returns the result of {@code this} raised the exact exponent - * {@code other}. - * - * @since 2020-09-07 - */ - public final UncertainDouble toExponentExact(double other) { - return UncertainDouble.ofRelative(Math.pow(this.value, other), - this.relativeUncertainty() * other); - } - - /** - * Returns a string representation of this {@code UncertainDouble}. - *

    - * This method returns the same value as {@link #toString(boolean)}, but - * {@code showUncertainty} is true if and only if the uncertainty is - * non-zero. - * - *

    - * Examples: - * - *

    -	 * UncertainDouble.of(3.27, 0.22).toString() = "3.3 ± 0.2"
    -	 * UncertainDouble.of(3.27, 0.13).toString() = "3.27 ± 0.13"
    -	 * UncertainDouble.of(-5.01, 0).toString() = "-5.01"
    -	 * 
    - * - * @since 2020-09-07 - */ - @Override - public final String toString() { - return this.toString(!this.isExact()); - } - - /** - * Returns a string representation of this {@code UncertainDouble}. - *

    - * If {@code showUncertainty} is true, the string will be of the form "VALUE - * ± UNCERTAINTY", and if it is false the string will be of the form "VALUE" - *

    - * VALUE represents a string representation of this {@code UncertainDouble}'s - * value. If the uncertainty is non-zero, the string will be rounded to the - * same precision as the uncertainty, otherwise it will not be rounded. The - * string is still rounded if {@code showUncertainty} is false.
    - * UNCERTAINTY represents a string representation of this - * {@code UncertainDouble}'s uncertainty. If the uncertainty ends in 1X - * (where X represents any digit) it will be rounded to two significant - * digits otherwise it will be rounded to one significant digit. - *

    - * Examples: - * - *

    -	 * UncertainDouble.of(3.27, 0.22).toString(false) = "3.3"
    -	 * UncertainDouble.of(3.27, 0.22).toString(true) = "3.3 ± 0.2"
    -	 * UncertainDouble.of(3.27, 0.13).toString(false) = "3.27"
    -	 * UncertainDouble.of(3.27, 0.13).toString(true) = "3.27 ± 0.13"
    -	 * UncertainDouble.of(-5.01, 0).toString(false) = "-5.01"
    -	 * UncertainDouble.of(-5.01, 0).toString(true) = "-5.01 ± 0.0"
    -	 * 
    - * - * @since 2020-09-07 - */ - public final String toString(boolean showUncertainty) { - String valueString, uncertaintyString; - - // generate the string representation of value and uncertainty - if (this.isExact()) { - uncertaintyString = "0.0"; - valueString = Double.toString(this.value); - - } else { - // round the value and uncertainty according to getDisplayScale() - final BigDecimal bigValue = BigDecimal.valueOf(this.value); - final BigDecimal bigUncertainty = BigDecimal.valueOf(this.uncertainty); - - final int displayScale = this.getDisplayScale(); - final BigDecimal roundedUncertainty = bigUncertainty - .setScale(displayScale, RoundingMode.HALF_EVEN); - final BigDecimal roundedValue = bigValue.setScale(displayScale, - RoundingMode.HALF_EVEN); - - valueString = roundedValue.toString(); - uncertaintyString = roundedUncertainty.toString(); - } - - // return "value" or "value ± uncertainty" depending on showUncertainty - return valueString + (showUncertainty ? " ± " + uncertaintyString : ""); - } - - /** - * @return absolute uncertainty - * @since 2020-09-07 - */ - public final double uncertainty() { - return this.uncertainty; - } - - /** - * @return value without uncertainty - * @since 2020-09-07 - */ - public final double value() { - return this.value; - } -} diff --git a/src/org/unitConverter/math/package-info.java b/src/org/unitConverter/math/package-info.java deleted file mode 100644 index 65727e4..0000000 --- a/src/org/unitConverter/math/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -/** - * Supplementary classes that are not related to units, but are necessary for their function. - * - * @author Adrien Hopkins - * @since 2019-03-14 - * @since v0.2.0 - */ -package org.unitConverter.math; \ No newline at end of file diff --git a/src/org/unitConverter/package-info.java b/src/org/unitConverter/package-info.java deleted file mode 100644 index 23dd165..0000000 --- a/src/org/unitConverter/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -/** - * A program that converts units. - * - * @author Adrien Hopkins - * @version v0.2.0 - * @since 2019-01-25 - */ -package org.unitConverter; \ No newline at end of file diff --git a/src/org/unitConverter/unit/BaseDimension.java b/src/org/unitConverter/unit/BaseDimension.java deleted file mode 100644 index 8e63a17..0000000 --- a/src/org/unitConverter/unit/BaseDimension.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.Objects; - -/** - * A dimension that defines a {@code BaseUnit} - * - * @author Adrien Hopkins - * @since 2019-10-16 - */ -public final class BaseDimension { - /** - * Gets a {@code BaseDimension} with the provided name and symbol. - * - * @param name - * name of dimension - * @param symbol - * symbol used for dimension - * @return dimension - * @since 2019-10-16 - */ - public static BaseDimension valueOf(final String name, final String symbol) { - return new BaseDimension(name, symbol); - } - - /** - * The name of the dimension. - */ - private final String name; - /** - * The symbol used by the dimension. Symbols should be short, generally one or two characters. - */ - private final String symbol; - - /** - * Creates the {@code BaseDimension}. - * - * @param name - * name of unit - * @param symbol - * symbol of unit - * @throws NullPointerException - * if any argument is null - * @since 2019-10-16 - */ - private BaseDimension(final String name, final String symbol) { - this.name = Objects.requireNonNull(name, "name must not be null."); - this.symbol = Objects.requireNonNull(symbol, "symbol must not be null."); - } - - /** - * @return name - * @since 2019-10-16 - */ - public final String getName() { - return this.name; - } - - /** - * @return symbol - * @since 2019-10-16 - */ - public final String getSymbol() { - return this.symbol; - } - - @Override - public String toString() { - return String.format("%s (%s)", this.getName(), this.getSymbol()); - } -} diff --git a/src/org/unitConverter/unit/BaseUnit.java b/src/org/unitConverter/unit/BaseUnit.java deleted file mode 100644 index 6757bd0..0000000 --- a/src/org/unitConverter/unit/BaseUnit.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -/** - * A unit that other units are defined by. - *

    - * Note that BaseUnits must have names and symbols. This is because they - * are used for toString code. Therefore, the Optionals provided by - * {@link #getPrimaryName} and {@link #getSymbol} will always contain a value. - * - * @author Adrien Hopkins - * @since 2019-10-16 - */ -public final class BaseUnit extends Unit { - /** - * Gets a base unit from the dimension it measures, its name and its symbol. - * - * @param dimension dimension measured by this unit - * @param name name of unit - * @param symbol symbol of unit - * @return base unit - * @since 2019-10-16 - */ - public static BaseUnit valueOf(final BaseDimension dimension, - final String name, final String symbol) { - return new BaseUnit(dimension, name, symbol, new HashSet<>()); - } - - /** - * Gets a base unit from the dimension it measures, its name and its symbol. - * - * @param dimension dimension measured by this unit - * @param name name of unit - * @param symbol symbol of unit - * @return base unit - * @since 2019-10-21 - */ - public static BaseUnit valueOf(final BaseDimension dimension, - final String name, final String symbol, final Set otherNames) { - return new BaseUnit(dimension, name, symbol, otherNames); - } - - /** - * The dimension measured by this base unit. - */ - private final BaseDimension dimension; - - /** - * Creates the {@code BaseUnit}. - * - * @param dimension dimension of unit - * @param primaryName name of unit - * @param symbol symbol of unit - * @throws NullPointerException if any argument is null - * @since 2019-10-16 - */ - private BaseUnit(final BaseDimension dimension, final String primaryName, - final String symbol, final Set otherNames) { - super(primaryName, symbol, otherNames); - this.dimension = Objects.requireNonNull(dimension, - "dimension must not be null."); - } - - /** - * Returns a {@code LinearUnit} with this unit as a base and a conversion - * factor of 1. This operation must be done in order to allow units to be - * created with operations. - * - * @return this unit as a {@code LinearUnit} - * @since 2019-10-16 - */ - public LinearUnit asLinearUnit() { - return LinearUnit.valueOf(this.getBase(), 1); - } - - @Override - protected double convertFromBase(final double value) { - return value; - } - - @Override - protected double convertToBase(final double value) { - return value; - } - - /** - * @return dimension - * @since 2019-10-16 - */ - public final BaseDimension getBaseDimension() { - return this.dimension; - } - - @Override - public String toString() { - return this.getPrimaryName().orElse("Unnamed unit") - + (this.getSymbol().isPresent() - ? String.format(" (%s)", this.getSymbol().get()) - : ""); - } - - @Override - public BaseUnit withName(final NameSymbol ns) { - Objects.requireNonNull(ns, "ns must not be null."); - if (!ns.getPrimaryName().isPresent()) - throw new IllegalArgumentException( - "BaseUnits must have primary names."); - if (!ns.getSymbol().isPresent()) - throw new IllegalArgumentException("BaseUnits must have symbols."); - return BaseUnit.valueOf(this.getBaseDimension(), - ns.getPrimaryName().get(), ns.getSymbol().get(), - ns.getOtherNames()); - } -} diff --git a/src/org/unitConverter/unit/BritishImperial.java b/src/org/unitConverter/unit/BritishImperial.java deleted file mode 100644 index ea23cd1..0000000 --- a/src/org/unitConverter/unit/BritishImperial.java +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -/** - * A static utility class that contains units in the British Imperial system. - * - * @author Adrien Hopkins - * @since 2019-10-21 - */ -public final class BritishImperial { - /** - * Imperial units that measure area - * - * @author Adrien Hopkins - * @since 2019-11-08 - */ - public static final class Area { - public static final LinearUnit SQUARE_FOOT = Length.FOOT.toExponent(2); - public static final LinearUnit SQUARE_YARD = Length.YARD.toExponent(2); - public static final LinearUnit SQUARE_MILE = Length.MILE.toExponent(2); - public static final LinearUnit PERCH = Length.ROD.times(Length.ROD); - public static final LinearUnit ROOD = Length.ROD.times(Length.FURLONG); - public static final LinearUnit ACRE = Length.FURLONG.times(Length.CHAIN); - } - - /** - * Imperial units that measure length - * - * @author Adrien Hopkins - * @since 2019-10-28 - */ - public static final class Length { - /** - * According to the International Yard and Pound of 1959, a yard is defined as exactly 0.9144 metres. - */ - public static final LinearUnit YARD = SI.METRE.times(0.9144); - public static final LinearUnit FOOT = YARD.dividedBy(3); - public static final LinearUnit INCH = FOOT.dividedBy(12); - public static final LinearUnit THOU = INCH.dividedBy(1000); - public static final LinearUnit CHAIN = YARD.times(22); - public static final LinearUnit FURLONG = CHAIN.times(10); - public static final LinearUnit MILE = FURLONG.times(8); - public static final LinearUnit LEAGUE = MILE.times(3); - - public static final LinearUnit NAUTICAL_MILE = SI.METRE.times(1852); - public static final LinearUnit CABLE = NAUTICAL_MILE.dividedBy(10); - public static final LinearUnit FATHOM = CABLE.dividedBy(100); - - public static final LinearUnit ROD = YARD.times(5.5); - public static final LinearUnit LINK = ROD.dividedBy(25); - } - - /** - * British Imperial units that measure mass. - * - * @author Adrien Hopkins - * @since 2019-11-08 - */ - public static final class Mass { - public static final LinearUnit POUND = SI.GRAM.times(453.59237); - public static final LinearUnit OUNCE = POUND.dividedBy(16); - public static final LinearUnit DRACHM = POUND.dividedBy(256); - public static final LinearUnit GRAIN = POUND.dividedBy(7000); - public static final LinearUnit STONE = POUND.times(14); - public static final LinearUnit QUARTER = STONE.times(2); - public static final LinearUnit HUNDREDWEIGHT = QUARTER.times(4); - public static final LinearUnit LONG_TON = HUNDREDWEIGHT.times(20); - public static final LinearUnit SLUG = SI.KILOGRAM.times(14.59390294); - } - - /** - * British Imperial units that measure volume - * - * @author Adrien Hopkins - * @since 2019-11-08 - */ - public static final class Volume { - public static final LinearUnit FLUID_OUNCE = SI.LITRE.withPrefix(SI.MILLI).times(28.4130625); - public static final LinearUnit GILL = FLUID_OUNCE.times(5); - public static final LinearUnit PINT = FLUID_OUNCE.times(20); - public static final LinearUnit QUART = PINT.times(2); - public static final LinearUnit GALLON = QUART.times(4); - public static final LinearUnit PECK = GALLON.times(2); - public static final LinearUnit BUSHEL = PECK.times(4); - - public static final LinearUnit CUBIC_INCH = Length.INCH.toExponent(3); - public static final LinearUnit CUBIC_FOOT = Length.FOOT.toExponent(3); - public static final LinearUnit CUBIC_YARD = Length.YARD.toExponent(3); - public static final LinearUnit ACRE_FOOT = Area.ACRE.times(Length.FOOT); - } - - public static final LinearUnit OUNCE_FORCE = Mass.OUNCE.times(SI.Constants.EARTH_GRAVITY); - public static final LinearUnit POUND_FORCE = Mass.POUND.times(SI.Constants.EARTH_GRAVITY); - - public static final LinearUnit BRITISH_THERMAL_UNIT = SI.JOULE.times(1055.06); - public static final LinearUnit CALORIE = SI.JOULE.times(4.184); - public static final LinearUnit KILOCALORIE = SI.JOULE.times(4184); - - public static final Unit FAHRENHEIT = Unit.fromConversionFunctions(SI.KELVIN.getBase(), - tempK -> tempK * 1.8 - 459.67, tempF -> (tempF + 459.67) / 1.8); -} diff --git a/src/org/unitConverter/unit/FunctionalUnit.java b/src/org/unitConverter/unit/FunctionalUnit.java deleted file mode 100644 index 586e0d7..0000000 --- a/src/org/unitConverter/unit/FunctionalUnit.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.Objects; -import java.util.function.DoubleUnaryOperator; - -import org.unitConverter.math.ObjectProduct; - -/** - * A unit that uses functional objects to convert to and from its base. - * - * @author Adrien Hopkins - * @since 2019-05-22 - */ -final class FunctionalUnit extends Unit { - /** - * A function that accepts a value expressed in the unit's base and returns that value expressed in this unit. - * - * @since 2019-05-22 - */ - private final DoubleUnaryOperator converterFrom; - - /** - * A function that accepts a value expressed in the unit and returns that value expressed in the unit's base. - * - * @since 2019-05-22 - */ - private final DoubleUnaryOperator converterTo; - - /** - * Creates the {@code FunctionalUnit}. - * - * @param base - * unit's base - * @param converterFrom - * function that accepts a value expressed in the unit's base and returns that value expressed in this - * unit. - * @param converterTo - * function that accepts a value expressed in the unit and returns that value expressed in the unit's - * base. - * @throws NullPointerException - * if any argument is null - * @since 2019-05-22 - */ - public FunctionalUnit(final ObjectProduct base, final DoubleUnaryOperator converterFrom, - final DoubleUnaryOperator converterTo) { - super(base, NameSymbol.EMPTY); - this.converterFrom = Objects.requireNonNull(converterFrom, "converterFrom must not be null."); - this.converterTo = Objects.requireNonNull(converterTo, "converterTo must not be null."); - } - - /** - * Creates the {@code FunctionalUnit}. - * - * @param base - * unit's base - * @param converterFrom - * function that accepts a value expressed in the unit's base and returns that value expressed in this - * unit. - * @param converterTo - * function that accepts a value expressed in the unit and returns that value expressed in the unit's - * base. - * @throws NullPointerException - * if any argument is null - * @since 2019-05-22 - */ - public FunctionalUnit(final ObjectProduct base, final DoubleUnaryOperator converterFrom, - final DoubleUnaryOperator converterTo, final NameSymbol ns) { - super(base, ns); - this.converterFrom = Objects.requireNonNull(converterFrom, "converterFrom must not be null."); - this.converterTo = Objects.requireNonNull(converterTo, "converterTo must not be null."); - } - - /** - * {@inheritDoc} - * - * Uses {@code converterFrom} to convert. - */ - @Override - public double convertFromBase(final double value) { - return this.converterFrom.applyAsDouble(value); - } - - /** - * {@inheritDoc} - * - * Uses {@code converterTo} to convert. - */ - @Override - public double convertToBase(final double value) { - return this.converterTo.applyAsDouble(value); - } - -} diff --git a/src/org/unitConverter/unit/FunctionalUnitlike.java b/src/org/unitConverter/unit/FunctionalUnitlike.java deleted file mode 100644 index 21c1fca..0000000 --- a/src/org/unitConverter/unit/FunctionalUnitlike.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (C) 2020 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.function.DoubleFunction; -import java.util.function.ToDoubleFunction; - -import org.unitConverter.math.ObjectProduct; - -/** - * A unitlike form that converts using two conversion functions. - * - * @since 2020-09-07 - */ -final class FunctionalUnitlike extends Unitlike { - /** - * A function that accepts a value in the unitlike form's base and returns a - * value in the unitlike form. - * - * @since 2020-09-07 - */ - private final DoubleFunction converterFrom; - - /** - * A function that accepts a value in the unitlike form and returns a value - * in the unitlike form's base. - */ - private final ToDoubleFunction converterTo; - - /** - * Creates the {@code FunctionalUnitlike}. - * - * @param base unitlike form's base - * @param converterFrom function that accepts a value in the unitlike form's - * base and returns a value in the unitlike form. - * @param converterTo function that accepts a value in the unitlike form - * and returns a value in the unitlike form's base. - * @throws NullPointerException if any argument is null - * @since 2019-05-22 - */ - protected FunctionalUnitlike(ObjectProduct unitBase, NameSymbol ns, - DoubleFunction converterFrom, ToDoubleFunction converterTo) { - super(unitBase, ns); - this.converterFrom = converterFrom; - this.converterTo = converterTo; - } - - @Override - protected V convertFromBase(double value) { - return this.converterFrom.apply(value); - } - - @Override - protected double convertToBase(V value) { - return this.converterTo.applyAsDouble(value); - } - -} diff --git a/src/org/unitConverter/unit/LinearUnit.java b/src/org/unitConverter/unit/LinearUnit.java deleted file mode 100644 index b7f33d5..0000000 --- a/src/org/unitConverter/unit/LinearUnit.java +++ /dev/null @@ -1,441 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.Objects; - -import org.unitConverter.math.DecimalComparison; -import org.unitConverter.math.ObjectProduct; -import org.unitConverter.math.UncertainDouble; - -/** - * A unit that can be expressed as a product of its base and a number. For - * example, kilometres, inches and pounds. - * - * @author Adrien Hopkins - * @since 2019-10-16 - */ -public final class LinearUnit extends Unit { - /** - * Gets a {@code LinearUnit} from a unit and a value. For example, converts - * '59 °F' to a linear unit with the value of '288.15 K' - * - * @param unit unit to convert - * @param value value to convert - * @return value expressed as a {@code LinearUnit} - * @since 2019-10-16 - * @throws NullPointerException if unit is null - */ - public static LinearUnit fromUnitValue(final Unit unit, final double value) { - return new LinearUnit( - Objects.requireNonNull(unit, "unit must not be null.").getBase(), - unit.convertToBase(value), NameSymbol.EMPTY); - } - - /** - * Gets a {@code LinearUnit} from a unit and a value. For example, converts - * '59 °F' to a linear unit with the value of '288.15 K' - * - * @param unit unit to convert - * @param value value to convert - * @param ns name(s) and symbol of unit - * @return value expressed as a {@code LinearUnit} - * @since 2019-10-21 - * @throws NullPointerException if unit or ns is null - */ - public static LinearUnit fromUnitValue(final Unit unit, final double value, - final NameSymbol ns) { - return new LinearUnit( - Objects.requireNonNull(unit, "unit must not be null.").getBase(), - unit.convertToBase(value), ns); - } - - /** - * @return the base unit associated with {@code unit}, as a - * {@code LinearUnit}. - * @since 2020-10-02 - */ - public static LinearUnit getBase(final Unit unit) { - return new LinearUnit(unit.getBase(), 1, NameSymbol.EMPTY); - } - - /** - * @return the base unit associated with {@code unitlike}, as a - * {@code LinearUnit}. - * @since 2020-10-02 - */ - public static LinearUnit getBase(final Unitlike unit) { - return new LinearUnit(unit.getBase(), 1, NameSymbol.EMPTY); - } - - /** - * Gets a {@code LinearUnit} from a unit base and a conversion factor. In - * other words, gets the product of {@code unitBase} and - * {@code conversionFactor}, expressed as a {@code LinearUnit}. - * - * @param unitBase unit base to multiply by - * @param conversionFactor number to multiply base by - * @return product of base and conversion factor - * @since 2019-10-16 - * @throws NullPointerException if unitBase is null - */ - public static LinearUnit valueOf(final ObjectProduct unitBase, - final double conversionFactor) { - return new LinearUnit(unitBase, conversionFactor, NameSymbol.EMPTY); - } - - /** - * Gets a {@code LinearUnit} from a unit base and a conversion factor. In - * other words, gets the product of {@code unitBase} and - * {@code conversionFactor}, expressed as a {@code LinearUnit}. - * - * @param unitBase unit base to multiply by - * @param conversionFactor number to multiply base by - * @param ns name(s) and symbol of unit - * @return product of base and conversion factor - * @since 2019-10-21 - * @throws NullPointerException if unitBase is null - */ - public static LinearUnit valueOf(final ObjectProduct unitBase, - final double conversionFactor, final NameSymbol ns) { - return new LinearUnit(unitBase, conversionFactor, ns); - } - - /** - * The value of this unit as represented in its base form. Mathematically, - * - *

    -	 * this = conversionFactor * getBase()
    -	 * 
    - * - * @since 2019-10-16 - */ - private final double conversionFactor; - - /** - * Creates the {@code LinearUnit}. - * - * @param unitBase base of linear unit - * @param conversionFactor conversion factor between base and unit - * @since 2019-10-16 - */ - private LinearUnit(final ObjectProduct unitBase, - final double conversionFactor, final NameSymbol ns) { - super(unitBase, ns); - this.conversionFactor = conversionFactor; - } - - /** - * {@inheritDoc} - * - * Converts by dividing by {@code conversionFactor} - */ - @Override - protected double convertFromBase(final double value) { - return value / this.getConversionFactor(); - } - - /** - * Converts an {@code UncertainDouble} value expressed in this unit to an - * {@code UncertainValue} value expressed in {@code other}. - * - * @param other unit to convert to - * @param value value to convert - * @return converted value - * @since 2019-09-07 - * @throws IllegalArgumentException if {@code other} is incompatible for - * conversion with this unit (as tested by - * {@link Unit#canConvertTo}). - * @throws NullPointerException if value or other is null - */ - public UncertainDouble convertTo(LinearUnit other, UncertainDouble value) { - Objects.requireNonNull(other, "other must not be null."); - Objects.requireNonNull(value, "value may not be null."); - if (this.canConvertTo(other)) - return value.timesExact( - this.getConversionFactor() / other.getConversionFactor()); - else - throw new IllegalArgumentException( - String.format("Cannot convert from %s to %s.", this, other)); - - } - - /** - * {@inheritDoc} - * - * Converts by multiplying by {@code conversionFactor} - */ - @Override - protected double convertToBase(final double value) { - return value * this.getConversionFactor(); - } - - /** - * Converts an {@code UncertainDouble} to the base unit. - * - * @since 2020-09-07 - */ - UncertainDouble convertToBase(final UncertainDouble value) { - return value.timesExact(this.getConversionFactor()); - } - - /** - * Divides this unit by a scalar. - * - * @param divisor scalar to divide by - * @return quotient - * @since 2018-12-23 - * @since v0.1.0 - */ - public LinearUnit dividedBy(final double divisor) { - return valueOf(this.getBase(), this.getConversionFactor() / divisor); - } - - /** - * Returns the quotient of this unit and another. - * - * @param divisor unit to divide by - * @return quotient of two units - * @throws NullPointerException if {@code divisor} is null - * @since 2018-12-22 - * @since v0.1.0 - */ - public LinearUnit dividedBy(final LinearUnit divisor) { - Objects.requireNonNull(divisor, "other must not be null"); - - // divide the units - final ObjectProduct base = this.getBase() - .dividedBy(divisor.getBase()); - return valueOf(base, - this.getConversionFactor() / divisor.getConversionFactor()); - } - - /** - * {@inheritDoc} - * - * Uses the base and conversion factor of units to test for equality. - */ - @Override - public boolean equals(final Object obj) { - if (!(obj instanceof LinearUnit)) - return false; - final LinearUnit other = (LinearUnit) obj; - return Objects.equals(this.getBase(), other.getBase()) - && DecimalComparison.equals(this.getConversionFactor(), - other.getConversionFactor()); - } - - /** - * @return conversion factor - * @since 2019-10-16 - */ - public double getConversionFactor() { - return this.conversionFactor; - } - - /** - * {@inheritDoc} - * - * Uses the base and conversion factor to compute a hash code. - */ - @Override - public int hashCode() { - return 31 * this.getBase().hashCode() - + DecimalComparison.hash(this.getConversionFactor()); - } - - /** - * @return whether this unit is equivalent to a {@code BaseUnit} (i.e. there - * is a {@code BaseUnit b} where - * {@code b.asLinearUnit().equals(this)} returns {@code true}.) - * @since 2019-10-16 - */ - public boolean isBase() { - return this.isCoherent() && this.getBase().isSingleObject(); - } - - /** - * @return whether this unit is coherent (i.e. has conversion factor 1) - * @since 2019-10-16 - */ - public boolean isCoherent() { - return this.getConversionFactor() == 1; - } - - /** - * Returns the difference of this unit and another. - *

    - * Two units can be subtracted if they have the same base. Note that - * {@link #canConvertTo} can be used to determine this. If {@code subtrahend} - * does not meet this condition, an {@code IllegalArgumentException} will be - * thrown. - *

    - * - * @param subtrahend unit to subtract - * @return difference of units - * @throws IllegalArgumentException if {@code subtrahend} is not compatible - * for subtraction as described above - * @throws NullPointerException if {@code subtrahend} is null - * @since 2019-03-17 - * @since v0.2.0 - */ - public LinearUnit minus(final LinearUnit subtrahend) { - Objects.requireNonNull(subtrahend, "addend must not be null."); - - // reject subtrahends that cannot be added to this unit - if (!this.getBase().equals(subtrahend.getBase())) - throw new IllegalArgumentException(String.format( - "Incompatible units for subtraction \"%s\" and \"%s\".", this, - subtrahend)); - - // subtract the units - return valueOf(this.getBase(), - this.getConversionFactor() - subtrahend.getConversionFactor()); - } - - /** - * Returns the sum of this unit and another. - *

    - * Two units can be added if they have the same base. Note that - * {@link #canConvertTo} can be used to determine this. If {@code addend} - * does not meet this condition, an {@code IllegalArgumentException} will be - * thrown. - *

    - * - * @param addend unit to add - * @return sum of units - * @throws IllegalArgumentException if {@code addend} is not compatible for - * addition as described above - * @throws NullPointerException if {@code addend} is null - * @since 2019-03-17 - * @since v0.2.0 - */ - public LinearUnit plus(final LinearUnit addend) { - Objects.requireNonNull(addend, "addend must not be null."); - - // reject addends that cannot be added to this unit - if (!this.getBase().equals(addend.getBase())) - throw new IllegalArgumentException(String.format( - "Incompatible units for addition \"%s\" and \"%s\".", this, - addend)); - - // add the units - return valueOf(this.getBase(), - this.getConversionFactor() + addend.getConversionFactor()); - } - - /** - * Multiplies this unit by a scalar. - * - * @param multiplier scalar to multiply by - * @return product - * @since 2018-12-23 - * @since v0.1.0 - */ - public LinearUnit times(final double multiplier) { - return valueOf(this.getBase(), this.getConversionFactor() * multiplier); - } - - /** - * Returns the product of this unit and another. - * - * @param multiplier unit to multiply by - * @return product of two units - * @throws NullPointerException if {@code multiplier} is null - * @since 2018-12-22 - * @since v0.1.0 - */ - public LinearUnit times(final LinearUnit multiplier) { - Objects.requireNonNull(multiplier, "other must not be null"); - - // multiply the units - final ObjectProduct base = this.getBase() - .times(multiplier.getBase()); - return valueOf(base, - this.getConversionFactor() * multiplier.getConversionFactor()); - } - - /** - * Returns this unit but to an exponent. - * - * @param exponent exponent to exponentiate unit to - * @return exponentiated unit - * @since 2019-01-15 - * @since v0.1.0 - */ - public LinearUnit toExponent(final int exponent) { - return valueOf(this.getBase().toExponent(exponent), - Math.pow(this.conversionFactor, exponent)); - } - - /** - * @return a string providing a definition of this unit - * @since 2019-10-21 - */ - @Override - public String toString() { - return this.getPrimaryName().orElse("Unnamed unit") - + (this.getSymbol().isPresent() - ? String.format(" (%s)", this.getSymbol().get()) - : "") - + ", " + Double.toString(this.conversionFactor) + " * " - + this.getBase().toString(u -> u.getSymbol().get()); - } - - @Override - public LinearUnit withName(final NameSymbol ns) { - return valueOf(this.getBase(), this.getConversionFactor(), ns); - } - - /** - * Returns the result of applying {@code prefix} to this unit. - *

    - * If this unit and the provided prefix have a primary name, the returned - * unit will have a primary name (prefix's name + unit's name).
    - * If this unit and the provided prefix have a symbol, the returned unit will - * have a symbol.
    - * This method ignores alternate names of both this unit and the provided - * prefix. - * - * @param prefix prefix to apply - * @return unit with prefix - * @since 2019-03-18 - * @since v0.2.0 - * @throws NullPointerException if prefix is null - */ - public LinearUnit withPrefix(final UnitPrefix prefix) { - final LinearUnit unit = this.times(prefix.getMultiplier()); - - // create new name and symbol, if possible - final String name; - if (this.getPrimaryName().isPresent() - && prefix.getPrimaryName().isPresent()) { - name = prefix.getPrimaryName().get() + this.getPrimaryName().get(); - } else { - name = null; - } - - final String symbol; - if (this.getSymbol().isPresent() && prefix.getSymbol().isPresent()) { - symbol = prefix.getSymbol().get() + this.getSymbol().get(); - } else { - symbol = null; - } - - return unit.withName(NameSymbol.ofNullable(name, symbol)); - } -} diff --git a/src/org/unitConverter/unit/LinearUnitValue.java b/src/org/unitConverter/unit/LinearUnitValue.java deleted file mode 100644 index 8de734e..0000000 --- a/src/org/unitConverter/unit/LinearUnitValue.java +++ /dev/null @@ -1,341 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.Objects; -import java.util.Optional; - -import org.unitConverter.math.DecimalComparison; -import org.unitConverter.math.UncertainDouble; - -/** - * A possibly uncertain value expressed in a linear unit. - * - * Unless otherwise indicated, all methods in this class throw a - * {@code NullPointerException} when an argument is null. - * - * @author Adrien Hopkins - * @since 2020-07-26 - */ -public final class LinearUnitValue { - public static final LinearUnitValue ONE = getExact(SI.ONE, 1); - - /** - * Gets an exact {@code LinearUnitValue} - * - * @param unit unit to express with - * @param value value to express - * @return exact {@code LinearUnitValue} instance - * @since 2020-07-26 - */ - public static final LinearUnitValue getExact(final LinearUnit unit, - final double value) { - return new LinearUnitValue( - Objects.requireNonNull(unit, "unit must not be null"), - UncertainDouble.of(value, 0)); - } - - /** - * Gets an uncertain {@code LinearUnitValue} - * - * @param unit unit to express with - * @param value value to express - * @param uncertainty absolute uncertainty of value - * @return uncertain {@code LinearUnitValue} instance - * @since 2020-07-26 - */ - public static final LinearUnitValue of(final LinearUnit unit, - final UncertainDouble value) { - return new LinearUnitValue( - Objects.requireNonNull(unit, "unit must not be null"), - Objects.requireNonNull(value, "value may not be null")); - } - - private final LinearUnit unit; - - private final UncertainDouble value; - - /** - * @param unit unit to express as - * @param value value to express - * @since 2020-07-26 - */ - private LinearUnitValue(final LinearUnit unit, final UncertainDouble value) { - this.unit = unit; - this.value = value; - } - - /** - * @return this value as a {@code UnitValue}. All uncertainty information is - * removed from the returned value. - * @since 2020-08-04 - */ - public final UnitValue asUnitValue() { - return UnitValue.of(this.unit, this.value.value()); - } - - /** - * @param other a {@code LinearUnit} - * @return true iff this value can be represented with {@code other}. - * @since 2020-07-26 - */ - public final boolean canConvertTo(final LinearUnit other) { - return this.unit.canConvertTo(other); - } - - /** - * Returns a LinearUnitValue that represents the same value expressed in a - * different unit - * - * @param other new unit to express value in - * @return value expressed in {@code other} - * @since 2020-07-26 - */ - public final LinearUnitValue convertTo(final LinearUnit other) { - return LinearUnitValue.of(other, this.unit.convertTo(other, this.value)); - } - - /** - * Divides this value by a scalar - * - * @param divisor value to divide by - * @return multiplied value - * @since 2020-07-28 - */ - public LinearUnitValue dividedBy(final double divisor) { - return LinearUnitValue.of(this.unit, this.value.dividedByExact(divisor)); - } - - /** - * Divides this value by another value - * - * @param divisor value to multiply by - * @return quotient - * @since 2020-07-28 - */ - public LinearUnitValue dividedBy(final LinearUnitValue divisor) { - return LinearUnitValue.of(this.unit.dividedBy(divisor.unit), - this.value.dividedBy(divisor.value)); - } - - /** - * Returns true if this and obj represent the same value, regardless of - * whether or not they are expressed in the same unit. So (1000 m).equals(1 - * km) returns true. - * - * @since 2020-07-26 - * @see #equals(Object, boolean) - */ - @Override - public boolean equals(final Object obj) { - if (!(obj instanceof LinearUnitValue)) - return false; - final LinearUnitValue other = (LinearUnitValue) obj; - return Objects.equals(this.unit.getBase(), other.unit.getBase()) - && this.unit.convertToBase(this.value) - .equals(other.unit.convertToBase(other.value)); - } - - /** - * Returns true if this and obj represent the same value, regardless of - * whether or not they are expressed in the same unit. So (1000 m).equals(1 - * km) returns true. - *

    - * If avoidFPErrors is true, this method will attempt to avoid floating-point - * errors, at the cost of not always being transitive. - * - * @since 2020-07-28 - */ - public boolean equals(final Object obj, final boolean avoidFPErrors) { - if (!avoidFPErrors) - return this.equals(obj); - if (!(obj instanceof LinearUnitValue)) - return false; - final LinearUnitValue other = (LinearUnitValue) obj; - return Objects.equals(this.unit.getBase(), other.unit.getBase()) - && DecimalComparison.equals(this.unit.convertToBase(this.value), - other.unit.convertToBase(other.value)); - } - - /** - * @param other another {@code LinearUnitValue} - * @return true iff this and other are within each other's uncertainty range - * - * @since 2020-07-26 - */ - public boolean equivalent(final LinearUnitValue other) { - if (other == null - || !Objects.equals(this.unit.getBase(), other.unit.getBase())) - return false; - final LinearUnit base = LinearUnit.valueOf(this.unit.getBase(), 1); - final LinearUnitValue thisBase = this.convertTo(base); - final LinearUnitValue otherBase = other.convertTo(base); - - return thisBase.value.equivalent(otherBase.value); - } - - /** - * @return the unit - * @since 2020-09-29 - */ - public final LinearUnit getUnit() { - return this.unit; - } - - /** - * @return the value - * @since 2020-09-29 - */ - public final UncertainDouble getValue() { - return this.value; - } - - /** - * @return the exact value - * @since 2020-09-07 - */ - public final double getValueExact() { - return this.value.value(); - } - - @Override - public int hashCode() { - return Objects.hash(this.unit.getBase(), - this.unit.convertToBase(this.getValue())); - } - - /** - * Returns the difference of this value and another, expressed in this - * value's unit - * - * @param subtrahend value to subtract - * @return difference of values - * @throws IllegalArgumentException if {@code subtrahend} has a unit that is - * not compatible for addition - * @since 2020-07-26 - */ - public LinearUnitValue minus(final LinearUnitValue subtrahend) { - Objects.requireNonNull(subtrahend, "subtrahend may not be null"); - - if (!this.canConvertTo(subtrahend.unit)) - throw new IllegalArgumentException(String.format( - "Incompatible units for subtraction \"%s\" and \"%s\".", - this.unit, subtrahend.unit)); - - final LinearUnitValue otherConverted = subtrahend.convertTo(this.unit); - return LinearUnitValue.of(this.unit, - this.value.minus(otherConverted.value)); - } - - /** - * Returns the sum of this value and another, expressed in this value's unit - * - * @param addend value to add - * @return sum of values - * @throws IllegalArgumentException if {@code addend} has a unit that is not - * compatible for addition - * @since 2020-07-26 - */ - public LinearUnitValue plus(final LinearUnitValue addend) { - Objects.requireNonNull(addend, "addend may not be null"); - - if (!this.canConvertTo(addend.unit)) - throw new IllegalArgumentException(String.format( - "Incompatible units for addition \"%s\" and \"%s\".", this.unit, - addend.unit)); - - final LinearUnitValue otherConverted = addend.convertTo(this.unit); - return LinearUnitValue.of(this.unit, - this.value.plus(otherConverted.value)); - } - - /** - * Multiplies this value by a scalar - * - * @param multiplier value to multiply by - * @return multiplied value - * @since 2020-07-28 - */ - public LinearUnitValue times(final double multiplier) { - return LinearUnitValue.of(this.unit, this.value.timesExact(multiplier)); - } - - /** - * Multiplies this value by another value - * - * @param multiplier value to multiply by - * @return product - * @since 2020-07-28 - */ - public LinearUnitValue times(final LinearUnitValue multiplier) { - return LinearUnitValue.of(this.unit.times(multiplier.unit), - this.value.times(multiplier.value)); - } - - /** - * Raises a value to an exponent - * - * @param exponent exponent to raise to - * @return result of exponentiation - * @since 2020-07-28 - */ - public LinearUnitValue toExponent(final int exponent) { - return LinearUnitValue.of(this.unit.toExponent(exponent), - this.value.toExponentExact(exponent)); - } - - @Override - public String toString() { - return this.toString(!this.value.isExact()); - } - - /** - * Returns a string representing the object.
    - * If the attached unit has a name or symbol, the string looks like "12 km". - * Otherwise, it looks like "13 unnamed unit (= 2 m/s)". - *

    - * If showUncertainty is true, strings like "35 ± 8" are shown instead of - * single numbers. - *

    - * Non-exact values are rounded intelligently based on their uncertainty. - * - * @since 2020-07-26 - */ - public String toString(final boolean showUncertainty) { - final Optional primaryName = this.unit.getPrimaryName(); - final Optional symbol = this.unit.getSymbol(); - final String chosenName = symbol.orElse(primaryName.orElse(null)); - - final UncertainDouble baseValue = this.unit.convertToBase(this.value); - - // get rounded strings - // if showUncertainty is true, add brackets around the string - final String valueString = showUncertainty ? "(" - : "" + this.value.toString(showUncertainty) - + (showUncertainty ? ")" : ""); - final String baseValueString = showUncertainty ? "(" - : "" + baseValue.toString(showUncertainty) - + (showUncertainty ? ")" : ""); - - // create string - if (primaryName.isEmpty() && symbol.isEmpty()) - return String.format("%s unnamed unit (= %s %s)", valueString, - baseValueString, this.unit.getBase()); - else - return String.format("%s %s", valueString, chosenName); - } -} diff --git a/src/org/unitConverter/unit/MultiUnit.java b/src/org/unitConverter/unit/MultiUnit.java deleted file mode 100644 index a1623f8..0000000 --- a/src/org/unitConverter/unit/MultiUnit.java +++ /dev/null @@ -1,160 +0,0 @@ -/** - * Copyright (C) 2020 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.unitConverter.math.ObjectProduct; - -/** - * A combination of units, like "5 foot + 7 inch". All but the last units should - * have a whole number value associated with them. - * - * @since 2020-10-02 - */ -public final class MultiUnit extends Unitlike> { - /** - * Creates a {@code MultiUnit} from its units. It will not have a name or - * symbol. - * - * @since 2020-10-03 - */ - public static final MultiUnit of(LinearUnit... units) { - return of(Arrays.asList(units)); - } - - /** - * Creates a {@code MultiUnit} from its units. It will not have a name or - * symbol. - * - * @since 2020-10-03 - */ - public static final MultiUnit of(List units) { - if (units.size() < 1) - throw new IllegalArgumentException("Must have at least one unit"); - final ObjectProduct unitBase = units.get(0).getBase(); - for (final LinearUnit unit : units) { - if (!unitBase.equals(unit.getBase())) - throw new IllegalArgumentException( - "All units must have the same base."); - } - return new MultiUnit(new ArrayList<>(units), unitBase, NameSymbol.EMPTY); - } - - /** - * The units that make up this value. - */ - private final List units; - - /** - * Creates a {@code MultiUnit}. - * - * @since 2020-10-03 - */ - private MultiUnit(List units, ObjectProduct unitBase, - NameSymbol ns) { - super(unitBase, ns); - this.units = units; - } - - @Override - protected List convertFromBase(double value) { - final List values = new ArrayList<>(this.units.size()); - double temp = value; - - for (final LinearUnit unit : this.units.subList(0, - this.units.size() - 1)) { - values.add(Math.floor(temp / unit.getConversionFactor())); - temp %= unit.getConversionFactor(); - } - - values.add(this.units.size() - 1, - this.units.get(this.units.size() - 1).convertFromBase(temp)); - - return values; - } - - /** - * Converts a value expressed in this unitlike form to a value expressed in - * {@code other}. - * - * @implSpec If conversion is possible, this implementation returns - * {@code other.convertFromBase(this.convertToBase(value))}. - * Therefore, overriding either of those methods will change the - * output of this method. - * - * @param other unit to convert to - * @param value value to convert - * @return converted value - * @since 2020-10-03 - * @throws IllegalArgumentException if {@code other} is incompatible for - * conversion with this unitlike form (as - * tested by {@link Unit#canConvertTo}). - * @throws NullPointerException if other is null - */ - public final , V> V convertTo(U other, - double... values) { - final List valueList = new ArrayList<>(values.length); - for (final double d : values) { - valueList.add(d); - } - - return this.convertTo(other, valueList); - } - - /** - * Converts a value expressed in this unitlike form to a value expressed in - * {@code other}. - * - * @implSpec If conversion is possible, this implementation returns - * {@code other.convertFromBase(this.convertToBase(value))}. - * Therefore, overriding either of those methods will change the - * output of this method. - * - * @param other unit to convert to - * @param value value to convert - * @return converted value - * @since 2020-10-03 - * @throws IllegalArgumentException if {@code other} is incompatible for - * conversion with this unitlike form (as - * tested by {@link Unit#canConvertTo}). - * @throws NullPointerException if other is null - */ - public final double convertTo(Unit other, double... values) { - final List valueList = new ArrayList<>(values.length); - for (final double d : values) { - valueList.add(d); - } - - return this.convertTo(other, valueList); - } - - @Override - protected double convertToBase(List value) { - if (value.size() != this.units.size()) - throw new IllegalArgumentException("Wrong number of values for " - + this.units.size() + "-unit MultiUnit."); - - double baseValue = 0; - for (int i = 0; i < this.units.size(); i++) { - baseValue += value.get(i) * this.units.get(i).getConversionFactor(); - } - return baseValue; - } -} diff --git a/src/org/unitConverter/unit/MultiUnitTest.java b/src/org/unitConverter/unit/MultiUnitTest.java deleted file mode 100644 index 5ea9d07..0000000 --- a/src/org/unitConverter/unit/MultiUnitTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Copyright (C) 2020 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; - -import org.junit.jupiter.api.Test; - -/** - * Tests related to the {@code MultiUnit}. - * - * @since 2020-10-03 - */ -class MultiUnitTest { - - @Test - final void testConvert() { - final Random rng = ThreadLocalRandom.current(); - final MultiUnit footInch = MultiUnit.of(BritishImperial.Length.FOOT, - BritishImperial.Length.INCH); - - assertEquals(1702.0, footInch.convertTo(SI.METRE.withPrefix(SI.MILLI), - Arrays.asList(5.0, 7.0)), 1.0); - - for (int i = 0; i < 1000; i++) { - final double feet = rng.nextInt(1000); - final double inches = rng.nextDouble() * 12; - final double millimetres = feet * 304.8 + inches * 25.4; - - final List feetAndInches = SI.METRE.withPrefix(SI.MILLI) - .convertTo(footInch, millimetres); - assertEquals(feet, feetAndInches.get(0), 1e-10); - assertEquals(inches, feetAndInches.get(1), 1e-10); - } - } - - /** - * Test method for - * {@link org.unitConverter.unit.MultiUnit#convertFromBase(double)}. - */ - @Test - final void testConvertFromBase() { - final Random rng = ThreadLocalRandom.current(); - final MultiUnit footInch = MultiUnit.of(BritishImperial.Length.FOOT, - BritishImperial.Length.INCH); - - // 1.7 m =~ 5' + 7" - final List values = footInch.convertFromBase(1.7018); - - assertEquals(5, values.get(0)); - assertEquals(7, values.get(1), 1e-12); - - for (int i = 0; i < 1000; i++) { - final double feet = rng.nextInt(1000); - final double inches = rng.nextDouble() * 12; - final double metres = feet * 0.3048 + inches * 0.0254; - - final List feetAndInches = footInch.convertFromBase(metres); - assertEquals(feet, feetAndInches.get(0), 1e-10); - assertEquals(inches, feetAndInches.get(1), 1e-10); - } - } - - /** - * Test method for - * {@link org.unitConverter.unit.MultiUnit#convertToBase(java.util.List)}. - */ - @Test - final void testConvertToBase() { - final Random rng = ThreadLocalRandom.current(); - final MultiUnit footInch = MultiUnit.of(BritishImperial.Length.FOOT, - BritishImperial.Length.INCH); - - // 1.7 m =~ 5' + 7" - assertEquals(1.7018, footInch.convertToBase(Arrays.asList(5.0, 7.0)), - 1e-12); - - for (int i = 0; i < 1000; i++) { - final double feet = rng.nextInt(1000); - final double inches = rng.nextDouble() * 12; - final double metres = feet * 0.3048 + inches * 0.0254; - - assertEquals(metres, - footInch.convertToBase(Arrays.asList(feet, inches)), 1e-12); - } - } -} diff --git a/src/org/unitConverter/unit/NameSymbol.java b/src/org/unitConverter/unit/NameSymbol.java deleted file mode 100644 index 8d8302a..0000000 --- a/src/org/unitConverter/unit/NameSymbol.java +++ /dev/null @@ -1,280 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; - -/** - * A class that can be used to specify names and a symbol for a unit. - * - * @author Adrien Hopkins - * @since 2019-10-21 - */ -public final class NameSymbol { - public static final NameSymbol EMPTY = new NameSymbol(Optional.empty(), - Optional.empty(), new HashSet<>()); - - /** - * Creates a {@code NameSymbol}, ensuring that if primaryName is null and - * otherNames is not empty, one name is moved from otherNames to primaryName - * - * Ensure that otherNames is a copy of the inputted argument. - */ - private static final NameSymbol create(final String name, - final String symbol, final Set otherNames) { - final Optional primaryName; - - if (name == null && !otherNames.isEmpty()) { - // get primary name and remove it from savedNames - final Iterator it = otherNames.iterator(); - assert it.hasNext(); - primaryName = Optional.of(it.next()); - otherNames.remove(primaryName.get()); - } else { - primaryName = Optional.ofNullable(name); - } - - return new NameSymbol(primaryName, Optional.ofNullable(symbol), - otherNames); - } - - /** - * Gets a {@code NameSymbol} with a primary name, a symbol and no other - * names. - * - * @param name name to use - * @param symbol symbol to use - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException if name or symbol is null - */ - public static final NameSymbol of(final String name, final String symbol) { - return new NameSymbol(Optional.of(name), Optional.of(symbol), - new HashSet<>()); - } - - /** - * Gets a {@code NameSymbol} with a primary name, a symbol and additional - * names. - * - * @param name name to use - * @param symbol symbol to use - * @param otherNames other names to use - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException if any argument is null - */ - public static final NameSymbol of(final String name, final String symbol, - final Set otherNames) { - return new NameSymbol(Optional.of(name), Optional.of(symbol), - new HashSet<>(Objects.requireNonNull(otherNames, - "otherNames must not be null."))); - } - - /** - * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional - * names. - * - * @param name name to use - * @param symbol symbol to use - * @param otherNames other names to use - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException if any argument is null - */ - public static final NameSymbol of(final String name, final String symbol, - final String... otherNames) { - return new NameSymbol(Optional.of(name), Optional.of(symbol), - new HashSet<>(Arrays.asList(Objects.requireNonNull(otherNames, - "otherNames must not be null.")))); - } - - /** - * Gets a {@code NameSymbol} with a primary name, no symbol, and no other - * names. - * - * @param name name to use - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException if name is null - */ - public static final NameSymbol ofName(final String name) { - return new NameSymbol(Optional.of(name), Optional.empty(), - new HashSet<>()); - } - - /** - * Gets a {@code NameSymbol} with a primary name, a symbol and additional - * names. - *

    - * If any argument is null, this static factory replaces it with an empty - * Optional or empty Set. - *

    - * If {@code name} is null and {@code otherNames} is not empty, a primary - * name will be picked from {@code otherNames}. This name will not appear in - * getOtherNames(). - * - * @param name name to use - * @param symbol symbol to use - * @param otherNames other names to use - * @return NameSymbol instance - * @since 2019-11-26 - */ - public static final NameSymbol ofNullable(final String name, - final String symbol, final Set otherNames) { - return NameSymbol.create(name, symbol, - otherNames == null ? new HashSet<>() : new HashSet<>(otherNames)); - } - - /** - * h * Gets a {@code NameSymbol} with a primary name, a symbol and additional - * names. - *

    - * If any argument is null, this static factory replaces it with an empty - * Optional or empty Set. - *

    - * If {@code name} is null and {@code otherNames} is not empty, a primary - * name will be picked from {@code otherNames}. This name will not appear in - * getOtherNames(). - * - * @param name name to use - * @param symbol symbol to use - * @param otherNames other names to use - * @return NameSymbol instance - * @since 2019-11-26 - */ - public static final NameSymbol ofNullable(final String name, - final String symbol, final String... otherNames) { - return create(name, symbol, otherNames == null ? new HashSet<>() - : new HashSet<>(Arrays.asList(otherNames))); - } - - /** - * Gets a {@code NameSymbol} with a symbol and no names. - * - * @param symbol symbol to use - * @return NameSymbol instance - * @since 2019-10-21 - * @throws NullPointerException if symbol is null - */ - public static final NameSymbol ofSymbol(final String symbol) { - return new NameSymbol(Optional.empty(), Optional.of(symbol), - new HashSet<>()); - } - - private final Optional primaryName; - private final Optional symbol; - - private final Set otherNames; - - /** - * Creates the {@code NameSymbol}. - * - * @param primaryName primary name of unit - * @param symbol symbol used to represent unit - * @param otherNames other names and/or spellings, should be a mutable copy - * of the argument - * @since 2019-10-21 - */ - private NameSymbol(final Optional primaryName, - final Optional symbol, final Set otherNames) { - this.primaryName = primaryName; - this.symbol = symbol; - otherNames.remove(null); - this.otherNames = Collections.unmodifiableSet(otherNames); - - if (this.primaryName.isEmpty()) { - assert this.otherNames.isEmpty(); - } - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!(obj instanceof NameSymbol)) - return false; - final NameSymbol other = (NameSymbol) obj; - if (this.otherNames == null) { - if (other.otherNames != null) - return false; - } else if (!this.otherNames.equals(other.otherNames)) - return false; - if (this.primaryName == null) { - if (other.primaryName != null) - return false; - } else if (!this.primaryName.equals(other.primaryName)) - return false; - if (this.symbol == null) { - if (other.symbol != null) - return false; - } else if (!this.symbol.equals(other.symbol)) - return false; - return true; - } - - /** - * @return otherNames - * @since 2019-10-21 - */ - public final Set getOtherNames() { - return this.otherNames; - } - - /** - * @return primaryName - * @since 2019-10-21 - */ - public final Optional getPrimaryName() { - return this.primaryName; - } - - /** - * @return symbol - * @since 2019-10-21 - */ - public final Optional getSymbol() { - return this.symbol; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + (this.otherNames == null ? 0 : this.otherNames.hashCode()); - result = prime * result - + (this.primaryName == null ? 0 : this.primaryName.hashCode()); - result = prime * result - + (this.symbol == null ? 0 : this.symbol.hashCode()); - return result; - } - - /** - * @return true iff this {@code NameSymbol} contains no names or symbols. - */ - public final boolean isEmpty() { - // if primaryName is empty, otherNames must also be empty - return this.primaryName.isEmpty() && this.symbol.isEmpty(); - } -} \ No newline at end of file diff --git a/src/org/unitConverter/unit/Nameable.java b/src/org/unitConverter/unit/Nameable.java deleted file mode 100644 index 36740ab..0000000 --- a/src/org/unitConverter/unit/Nameable.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (C) 2020 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.Optional; -import java.util.Set; - -/** - * An object that can hold one or more names, and possibly a symbol. The name - * and symbol data should be immutable. - * - * @since 2020-09-07 - */ -public interface Nameable { - /** - * @return a {@code NameSymbol} that contains this object's primary name, - * symbol and other names - * @since 2020-09-07 - */ - NameSymbol getNameSymbol(); - - /** - * @return set of alternate names - * @since 2020-09-07 - */ - default Set getOtherNames() { - return this.getNameSymbol().getOtherNames(); - } - - /** - * @return preferred name of object - * @since 2020-09-07 - */ - default Optional getPrimaryName() { - return this.getNameSymbol().getPrimaryName(); - } - - /** - * @return short symbol representing object - * @since 2020-09-07 - */ - default Optional getSymbol() { - return this.getNameSymbol().getSymbol(); - } -} diff --git a/src/org/unitConverter/unit/SI.java b/src/org/unitConverter/unit/SI.java deleted file mode 100644 index c88d2bc..0000000 --- a/src/org/unitConverter/unit/SI.java +++ /dev/null @@ -1,479 +0,0 @@ -/** - * Copyright (C) 2018 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.Set; - -import org.unitConverter.math.ObjectProduct; - -/** - * All of the units, prefixes and dimensions that are used by the SI, as well as - * some outside the SI. - * - *

    - * This class does not include prefixed units. To obtain prefixed units, use - * {@link LinearUnit#withPrefix}: - * - *

    - * LinearUnit KILOMETRE = SI.METRE.withPrefix(SI.KILO);
    - * 
    - * - * - * @author Adrien Hopkins - * @since 2019-10-16 - */ -public final class SI { - /// dimensions used by SI units - // base dimensions, as BaseDimensions - public static final class BaseDimensions { - public static final BaseDimension LENGTH = BaseDimension.valueOf("Length", - "L"); - public static final BaseDimension MASS = BaseDimension.valueOf("Mass", - "M"); - public static final BaseDimension TIME = BaseDimension.valueOf("Time", - "T"); - public static final BaseDimension ELECTRIC_CURRENT = BaseDimension - .valueOf("Electric Current", "I"); - public static final BaseDimension TEMPERATURE = BaseDimension - .valueOf("Temperature", "\u0398"); // theta symbol - public static final BaseDimension QUANTITY = BaseDimension - .valueOf("Quantity", "N"); - public static final BaseDimension LUMINOUS_INTENSITY = BaseDimension - .valueOf("Luminous Intensity", "J"); - public static final BaseDimension INFORMATION = BaseDimension - .valueOf("Information", "Info"); // non-SI - public static final BaseDimension CURRENCY = BaseDimension - .valueOf("Currency", "$$"); // non-SI - - // You may NOT get SI.BaseDimensions instances! - private BaseDimensions() { - throw new AssertionError(); - } - } - - /// base units of the SI - // suppressing warnings since these are the same object, but in a different - /// form (class) - @SuppressWarnings("hiding") - public static final class BaseUnits { - public static final BaseUnit METRE = BaseUnit - .valueOf(BaseDimensions.LENGTH, "metre", "m"); - public static final BaseUnit KILOGRAM = BaseUnit - .valueOf(BaseDimensions.MASS, "kilogram", "kg"); - public static final BaseUnit SECOND = BaseUnit - .valueOf(BaseDimensions.TIME, "second", "s"); - public static final BaseUnit AMPERE = BaseUnit - .valueOf(BaseDimensions.ELECTRIC_CURRENT, "ampere", "A"); - public static final BaseUnit KELVIN = BaseUnit - .valueOf(BaseDimensions.TEMPERATURE, "kelvin", "K"); - public static final BaseUnit MOLE = BaseUnit - .valueOf(BaseDimensions.QUANTITY, "mole", "mol"); - public static final BaseUnit CANDELA = BaseUnit - .valueOf(BaseDimensions.LUMINOUS_INTENSITY, "candela", "cd"); - public static final BaseUnit BIT = BaseUnit - .valueOf(BaseDimensions.INFORMATION, "bit", "b"); - public static final BaseUnit DOLLAR = BaseUnit - .valueOf(BaseDimensions.CURRENCY, "dollar", "$"); - - public static final Set BASE_UNITS = Set.of(METRE, KILOGRAM, - SECOND, AMPERE, KELVIN, MOLE, CANDELA, BIT); - - // You may NOT get SI.BaseUnits instances! - private BaseUnits() { - throw new AssertionError(); - } - } - - /** - * Constants that relate to the SI or other systems. - * - * @author Adrien Hopkins - * @since 2019-11-08 - */ - public static final class Constants { - public static final LinearUnit EARTH_GRAVITY = METRE.dividedBy(SECOND) - .dividedBy(SECOND).times(9.80665); - } - - // dimensions used in the SI, as ObjectProducts - public static final class Dimensions { - public static final ObjectProduct EMPTY = ObjectProduct - .empty(); - public static final ObjectProduct LENGTH = ObjectProduct - .oneOf(BaseDimensions.LENGTH); - public static final ObjectProduct MASS = ObjectProduct - .oneOf(BaseDimensions.MASS); - public static final ObjectProduct TIME = ObjectProduct - .oneOf(BaseDimensions.TIME); - public static final ObjectProduct ELECTRIC_CURRENT = ObjectProduct - .oneOf(BaseDimensions.ELECTRIC_CURRENT); - public static final ObjectProduct TEMPERATURE = ObjectProduct - .oneOf(BaseDimensions.TEMPERATURE); - public static final ObjectProduct QUANTITY = ObjectProduct - .oneOf(BaseDimensions.QUANTITY); - public static final ObjectProduct LUMINOUS_INTENSITY = ObjectProduct - .oneOf(BaseDimensions.LUMINOUS_INTENSITY); - public static final ObjectProduct INFORMATION = ObjectProduct - .oneOf(BaseDimensions.INFORMATION); - public static final ObjectProduct CURRENCY = ObjectProduct - .oneOf(BaseDimensions.CURRENCY); - - // derived dimensions without named SI units - public static final ObjectProduct AREA = LENGTH - .times(LENGTH); - public static final ObjectProduct VOLUME = AREA - .times(LENGTH); - public static final ObjectProduct VELOCITY = LENGTH - .dividedBy(TIME); - public static final ObjectProduct ACCELERATION = VELOCITY - .dividedBy(TIME); - public static final ObjectProduct WAVENUMBER = EMPTY - .dividedBy(LENGTH); - public static final ObjectProduct MASS_DENSITY = MASS - .dividedBy(VOLUME); - public static final ObjectProduct SURFACE_DENSITY = MASS - .dividedBy(AREA); - public static final ObjectProduct SPECIFIC_VOLUME = VOLUME - .dividedBy(MASS); - public static final ObjectProduct CURRENT_DENSITY = ELECTRIC_CURRENT - .dividedBy(AREA); - public static final ObjectProduct MAGNETIC_FIELD_STRENGTH = ELECTRIC_CURRENT - .dividedBy(LENGTH); - public static final ObjectProduct CONCENTRATION = QUANTITY - .dividedBy(VOLUME); - public static final ObjectProduct MASS_CONCENTRATION = CONCENTRATION - .times(MASS); - public static final ObjectProduct LUMINANCE = LUMINOUS_INTENSITY - .dividedBy(AREA); - public static final ObjectProduct REFRACTIVE_INDEX = VELOCITY - .dividedBy(VELOCITY); - public static final ObjectProduct REFRACTIVE_PERMEABILITY = EMPTY - .times(EMPTY); - public static final ObjectProduct ANGLE = LENGTH - .dividedBy(LENGTH); - public static final ObjectProduct SOLID_ANGLE = AREA - .dividedBy(AREA); - - // derived dimensions with named SI units - public static final ObjectProduct FREQUENCY = EMPTY - .dividedBy(TIME); - public static final ObjectProduct FORCE = MASS - .times(ACCELERATION); - public static final ObjectProduct ENERGY = FORCE - .times(LENGTH); - public static final ObjectProduct POWER = ENERGY - .dividedBy(TIME); - public static final ObjectProduct ELECTRIC_CHARGE = ELECTRIC_CURRENT - .times(TIME); - public static final ObjectProduct VOLTAGE = ENERGY - .dividedBy(ELECTRIC_CHARGE); - public static final ObjectProduct CAPACITANCE = ELECTRIC_CHARGE - .dividedBy(VOLTAGE); - public static final ObjectProduct ELECTRIC_RESISTANCE = VOLTAGE - .dividedBy(ELECTRIC_CURRENT); - public static final ObjectProduct ELECTRIC_CONDUCTANCE = ELECTRIC_CURRENT - .dividedBy(VOLTAGE); - public static final ObjectProduct MAGNETIC_FLUX = VOLTAGE - .times(TIME); - public static final ObjectProduct MAGNETIC_FLUX_DENSITY = MAGNETIC_FLUX - .dividedBy(AREA); - public static final ObjectProduct INDUCTANCE = MAGNETIC_FLUX - .dividedBy(ELECTRIC_CURRENT); - public static final ObjectProduct LUMINOUS_FLUX = LUMINOUS_INTENSITY - .times(SOLID_ANGLE); - public static final ObjectProduct ILLUMINANCE = LUMINOUS_FLUX - .dividedBy(AREA); - public static final ObjectProduct SPECIFIC_ENERGY = ENERGY - .dividedBy(MASS); - public static final ObjectProduct CATALYTIC_ACTIVITY = QUANTITY - .dividedBy(TIME); - - // You may NOT get SI.Dimension instances! - private Dimensions() { - throw new AssertionError(); - } - } - - /// The units of the SI - public static final LinearUnit ONE = LinearUnit - .valueOf(ObjectProduct.empty(), 1); - - public static final LinearUnit METRE = BaseUnits.METRE.asLinearUnit() - .withName(NameSymbol.of("metre", "m", "meter")); - public static final LinearUnit KILOGRAM = BaseUnits.KILOGRAM.asLinearUnit() - .withName(NameSymbol.of("kilogram", "kg")); - public static final LinearUnit SECOND = BaseUnits.SECOND.asLinearUnit() - .withName(NameSymbol.of("second", "s", "sec")); - public static final LinearUnit AMPERE = BaseUnits.AMPERE.asLinearUnit() - .withName(NameSymbol.of("ampere", "A")); - public static final LinearUnit KELVIN = BaseUnits.KELVIN.asLinearUnit() - .withName(NameSymbol.of("kelvin", "K")); - public static final LinearUnit MOLE = BaseUnits.MOLE.asLinearUnit() - .withName(NameSymbol.of("mole", "mol")); - public static final LinearUnit CANDELA = BaseUnits.CANDELA.asLinearUnit() - .withName(NameSymbol.of("candela", "cd")); - public static final LinearUnit BIT = BaseUnits.BIT.asLinearUnit() - .withName(NameSymbol.of("bit", "b")); - public static final LinearUnit DOLLAR = BaseUnits.DOLLAR.asLinearUnit() - .withName(NameSymbol.of("dollar", "$")); - // Non-base units - public static final LinearUnit RADIAN = METRE.dividedBy(METRE) - .withName(NameSymbol.of("radian", "rad")); - - public static final LinearUnit STERADIAN = RADIAN.times(RADIAN) - .withName(NameSymbol.of("steradian", "sr")); - public static final LinearUnit HERTZ = ONE.dividedBy(SECOND) - .withName(NameSymbol.of("hertz", "Hz")); - // for periodic phenomena - public static final LinearUnit NEWTON = KILOGRAM.times(METRE) - .dividedBy(SECOND.times(SECOND)) - .withName(NameSymbol.of("newton", "N")); - public static final LinearUnit PASCAL = NEWTON.dividedBy(METRE.times(METRE)) - .withName(NameSymbol.of("pascal", "Pa")); - public static final LinearUnit JOULE = NEWTON.times(METRE) - .withName(NameSymbol.of("joule", "J")); - public static final LinearUnit WATT = JOULE.dividedBy(SECOND) - .withName(NameSymbol.of("watt", "W")); - public static final LinearUnit COULOMB = AMPERE.times(SECOND) - .withName(NameSymbol.of("coulomb", "C")); - public static final LinearUnit VOLT = JOULE.dividedBy(COULOMB) - .withName(NameSymbol.of("volt", "V")); - public static final LinearUnit FARAD = COULOMB.dividedBy(VOLT) - .withName(NameSymbol.of("farad", "F")); - public static final LinearUnit OHM = VOLT.dividedBy(AMPERE) - .withName(NameSymbol.of("ohm", "\u03A9")); // omega - public static final LinearUnit SIEMENS = ONE.dividedBy(OHM) - .withName(NameSymbol.of("siemens", "S")); - public static final LinearUnit WEBER = VOLT.times(SECOND) - .withName(NameSymbol.of("weber", "Wb")); - public static final LinearUnit TESLA = WEBER.dividedBy(METRE.times(METRE)) - .withName(NameSymbol.of("tesla", "T")); - public static final LinearUnit HENRY = WEBER.dividedBy(AMPERE) - .withName(NameSymbol.of("henry", "H")); - public static final LinearUnit LUMEN = CANDELA.times(STERADIAN) - .withName(NameSymbol.of("lumen", "lm")); - public static final LinearUnit LUX = LUMEN.dividedBy(METRE.times(METRE)) - .withName(NameSymbol.of("lux", "lx")); - public static final LinearUnit BEQUEREL = ONE.dividedBy(SECOND) - .withName(NameSymbol.of("bequerel", "Bq")); - // for activity referred to a nucleotide - public static final LinearUnit GRAY = JOULE.dividedBy(KILOGRAM) - .withName(NameSymbol.of("grey", "Gy")); - // for absorbed dose - public static final LinearUnit SIEVERT = JOULE.dividedBy(KILOGRAM) - .withName(NameSymbol.of("sievert", "Sv")); - // for dose equivalent - public static final LinearUnit KATAL = MOLE.dividedBy(SECOND) - .withName(NameSymbol.of("katal", "kat")); - // common derived units included for convenience - public static final LinearUnit GRAM = KILOGRAM.dividedBy(1000) - .withName(NameSymbol.of("gram", "g")); - - public static final LinearUnit SQUARE_METRE = METRE.toExponent(2) - .withName(NameSymbol.of("square metre", "m^2", "square meter", - "metre squared", "meter squared")); - public static final LinearUnit CUBIC_METRE = METRE.toExponent(3) - .withName(NameSymbol.of("cubic metre", "m^3", "cubic meter", - "metre cubed", "meter cubed")); - public static final LinearUnit METRE_PER_SECOND = METRE.dividedBy(SECOND) - .withName( - NameSymbol.of("metre per second", "m/s", "meter per second")); - // Non-SI units included for convenience - public static final Unit CELSIUS = Unit - .fromConversionFunctions(KELVIN.getBase(), tempK -> tempK - 273.15, - tempC -> tempC + 273.15) - .withName(NameSymbol.of("degree Celsius", "\u00B0C")); - - public static final LinearUnit MINUTE = SECOND.times(60) - .withName(NameSymbol.of("minute", "min")); - public static final LinearUnit HOUR = MINUTE.times(60) - .withName(NameSymbol.of("hour", "h", "hr")); - public static final LinearUnit DAY = HOUR.times(60) - .withName(NameSymbol.of("day", "d")); - public static final LinearUnit KILOMETRE_PER_HOUR = METRE.times(1000) - .dividedBy(HOUR).withName(NameSymbol.of("kilometre per hour", "km/h", - "kilometer per hour")); - public static final LinearUnit DEGREE = RADIAN.times(360 / (2 * Math.PI)) - .withName(NameSymbol.of("degree", "\u00B0", "deg")); - public static final LinearUnit ARCMINUTE = DEGREE.dividedBy(60) - .withName(NameSymbol.of("arcminute", "arcmin")); - public static final LinearUnit ARCSECOND = ARCMINUTE.dividedBy(60) - .withName(NameSymbol.of("arcsecond", "arcsec")); - public static final LinearUnit ASTRONOMICAL_UNIT = METRE - .times(149597870700.0) - .withName(NameSymbol.of("astronomical unit", "au")); - public static final LinearUnit PARSEC = ASTRONOMICAL_UNIT - .dividedBy(ARCSECOND).withName(NameSymbol.of("parsec", "pc")); - public static final LinearUnit HECTARE = METRE.times(METRE).times(10000.0) - .withName(NameSymbol.of("hectare", "ha")); - public static final LinearUnit LITRE = METRE.times(METRE).times(METRE) - .dividedBy(1000.0).withName(NameSymbol.of("litre", "L", "l", "liter")); - public static final LinearUnit TONNE = KILOGRAM.times(1000.0) - .withName(NameSymbol.of("tonne", "t", "metric ton")); - public static final LinearUnit DALTON = KILOGRAM.times(1.660539040e-27) - .withName(NameSymbol.of("dalton", "Da", "atomic unit", "u")); // approximate - // value - public static final LinearUnit ELECTRONVOLT = JOULE.times(1.602176634e-19) - .withName(NameSymbol.of("electron volt", "eV")); - public static final LinearUnit BYTE = BIT.times(8) - .withName(NameSymbol.of("byte", "B")); - public static final Unit NEPER = Unit.fromConversionFunctions(ONE.getBase(), - pr -> 0.5 * Math.log(pr), Np -> Math.exp(2 * Np)) - .withName(NameSymbol.of("neper", "Np")); - public static final Unit BEL = Unit.fromConversionFunctions(ONE.getBase(), - pr -> Math.log10(pr), dB -> Math.pow(10, dB)) - .withName(NameSymbol.of("bel", "B")); - public static final Unit DECIBEL = Unit - .fromConversionFunctions(ONE.getBase(), pr -> 10 * Math.log10(pr), - dB -> Math.pow(10, dB / 10)) - .withName(NameSymbol.of("decibel", "dB")); - - /// The prefixes of the SI - // expanding decimal prefixes - public static final UnitPrefix KILO = UnitPrefix.valueOf(1e3) - .withName(NameSymbol.of("kilo", "k", "K")); - public static final UnitPrefix MEGA = UnitPrefix.valueOf(1e6) - .withName(NameSymbol.of("mega", "M")); - public static final UnitPrefix GIGA = UnitPrefix.valueOf(1e9) - .withName(NameSymbol.of("giga", "G")); - public static final UnitPrefix TERA = UnitPrefix.valueOf(1e12) - .withName(NameSymbol.of("tera", "T")); - public static final UnitPrefix PETA = UnitPrefix.valueOf(1e15) - .withName(NameSymbol.of("peta", "P")); - public static final UnitPrefix EXA = UnitPrefix.valueOf(1e18) - .withName(NameSymbol.of("exa", "E")); - public static final UnitPrefix ZETTA = UnitPrefix.valueOf(1e21) - .withName(NameSymbol.of("zetta", "Z")); - public static final UnitPrefix YOTTA = UnitPrefix.valueOf(1e24) - .withName(NameSymbol.of("yotta", "Y")); - - // contracting decimal prefixes - public static final UnitPrefix MILLI = UnitPrefix.valueOf(1e-3) - .withName(NameSymbol.of("milli", "m")); - public static final UnitPrefix MICRO = UnitPrefix.valueOf(1e-6) - .withName(NameSymbol.of("micro", "\u03BC", "u")); // mu - public static final UnitPrefix NANO = UnitPrefix.valueOf(1e-9) - .withName(NameSymbol.of("nano", "n")); - public static final UnitPrefix PICO = UnitPrefix.valueOf(1e-12) - .withName(NameSymbol.of("pico", "p")); - public static final UnitPrefix FEMTO = UnitPrefix.valueOf(1e-15) - .withName(NameSymbol.of("femto", "f")); - public static final UnitPrefix ATTO = UnitPrefix.valueOf(1e-18) - .withName(NameSymbol.of("atto", "a")); - public static final UnitPrefix ZEPTO = UnitPrefix.valueOf(1e-21) - .withName(NameSymbol.of("zepto", "z")); - public static final UnitPrefix YOCTO = UnitPrefix.valueOf(1e-24) - .withName(NameSymbol.of("yocto", "y")); - - // prefixes that don't match the pattern of thousands - public static final UnitPrefix DEKA = UnitPrefix.valueOf(1e1) - .withName(NameSymbol.of("deka", "da", "deca", "D")); - public static final UnitPrefix HECTO = UnitPrefix.valueOf(1e2) - .withName(NameSymbol.of("hecto", "h", "H", "hekto")); - public static final UnitPrefix DECI = UnitPrefix.valueOf(1e-1) - .withName(NameSymbol.of("deci", "d")); - public static final UnitPrefix CENTI = UnitPrefix.valueOf(1e-2) - .withName(NameSymbol.of("centi", "c")); - public static final UnitPrefix KIBI = UnitPrefix.valueOf(1024) - .withName(NameSymbol.of("kibi", "Ki")); - public static final UnitPrefix MEBI = KIBI.times(1024) - .withName(NameSymbol.of("mebi", "Mi")); - public static final UnitPrefix GIBI = MEBI.times(1024) - .withName(NameSymbol.of("gibi", "Gi")); - public static final UnitPrefix TEBI = GIBI.times(1024) - .withName(NameSymbol.of("tebi", "Ti")); - public static final UnitPrefix PEBI = TEBI.times(1024) - .withName(NameSymbol.of("pebi", "Pi")); - public static final UnitPrefix EXBI = PEBI.times(1024) - .withName(NameSymbol.of("exbi", "Ei")); - - // a few prefixed units - public static final LinearUnit MICROMETRE = SI.METRE.withPrefix(SI.MICRO); - public static final LinearUnit MILLIMETRE = SI.METRE.withPrefix(SI.MILLI); - public static final LinearUnit KILOMETRE = SI.METRE.withPrefix(SI.KILO); - public static final LinearUnit MEGAMETRE = SI.METRE.withPrefix(SI.MEGA); - - public static final LinearUnit MICROLITRE = SI.LITRE.withPrefix(SI.MICRO); - public static final LinearUnit MILLILITRE = SI.LITRE.withPrefix(SI.MILLI); - public static final LinearUnit KILOLITRE = SI.LITRE.withPrefix(SI.KILO); - public static final LinearUnit MEGALITRE = SI.LITRE.withPrefix(SI.MEGA); - - public static final LinearUnit MICROSECOND = SI.SECOND.withPrefix(SI.MICRO); - public static final LinearUnit MILLISECOND = SI.SECOND.withPrefix(SI.MILLI); - public static final LinearUnit KILOSECOND = SI.SECOND.withPrefix(SI.KILO); - public static final LinearUnit MEGASECOND = SI.SECOND.withPrefix(SI.MEGA); - - public static final LinearUnit MICROGRAM = SI.GRAM.withPrefix(SI.MICRO); - public static final LinearUnit MILLIGRAM = SI.GRAM.withPrefix(SI.MILLI); - public static final LinearUnit MEGAGRAM = SI.GRAM.withPrefix(SI.MEGA); - - public static final LinearUnit MICRONEWTON = SI.NEWTON.withPrefix(SI.MICRO); - public static final LinearUnit MILLINEWTON = SI.NEWTON.withPrefix(SI.MILLI); - public static final LinearUnit KILONEWTON = SI.NEWTON.withPrefix(SI.KILO); - public static final LinearUnit MEGANEWTON = SI.NEWTON.withPrefix(SI.MEGA); - - public static final LinearUnit MICROJOULE = SI.JOULE.withPrefix(SI.MICRO); - public static final LinearUnit MILLIJOULE = SI.JOULE.withPrefix(SI.MILLI); - public static final LinearUnit KILOJOULE = SI.JOULE.withPrefix(SI.KILO); - public static final LinearUnit MEGAJOULE = SI.JOULE.withPrefix(SI.MEGA); - - public static final LinearUnit MICROWATT = SI.WATT.withPrefix(SI.MICRO); - public static final LinearUnit MILLIWATT = SI.WATT.withPrefix(SI.MILLI); - public static final LinearUnit KILOWATT = SI.WATT.withPrefix(SI.KILO); - public static final LinearUnit MEGAWATT = SI.WATT.withPrefix(SI.MEGA); - - public static final LinearUnit MICROCOULOMB = SI.COULOMB - .withPrefix(SI.MICRO); - public static final LinearUnit MILLICOULOMB = SI.COULOMB - .withPrefix(SI.MILLI); - public static final LinearUnit KILOCOULOMB = SI.COULOMB.withPrefix(SI.KILO); - public static final LinearUnit MEGACOULOMB = SI.COULOMB.withPrefix(SI.MEGA); - - public static final LinearUnit MICROAMPERE = SI.AMPERE.withPrefix(SI.MICRO); - public static final LinearUnit MILLIAMPERE = SI.AMPERE.withPrefix(SI.MILLI); - - public static final LinearUnit MICROVOLT = SI.VOLT.withPrefix(SI.MICRO); - public static final LinearUnit MILLIVOLT = SI.VOLT.withPrefix(SI.MILLI); - public static final LinearUnit KILOVOLT = SI.VOLT.withPrefix(SI.KILO); - public static final LinearUnit MEGAVOLT = SI.VOLT.withPrefix(SI.MEGA); - - public static final LinearUnit KILOOHM = SI.OHM.withPrefix(SI.KILO); - public static final LinearUnit MEGAOHM = SI.OHM.withPrefix(SI.MEGA); - - // sets of prefixes - public static final Set ALL_PREFIXES = Set.of(DEKA, HECTO, KILO, - MEGA, GIGA, TERA, PETA, EXA, ZETTA, YOTTA, DECI, CENTI, MILLI, MICRO, - NANO, PICO, FEMTO, ATTO, ZEPTO, YOCTO, KIBI, MEBI, GIBI, TEBI, PEBI, - EXBI); - - public static final Set DECIMAL_PREFIXES = Set.of(DEKA, HECTO, - KILO, MEGA, GIGA, TERA, PETA, EXA, ZETTA, YOTTA, DECI, CENTI, MILLI, - MICRO, NANO, PICO, FEMTO, ATTO, ZEPTO, YOCTO); - public static final Set THOUSAND_PREFIXES = Set.of(KILO, MEGA, - GIGA, TERA, PETA, EXA, ZETTA, YOTTA, MILLI, MICRO, NANO, PICO, FEMTO, - ATTO, ZEPTO, YOCTO); - public static final Set MAGNIFYING_PREFIXES = Set.of(DEKA, HECTO, - KILO, MEGA, GIGA, TERA, PETA, EXA, ZETTA, YOTTA, KIBI, MEBI, GIBI, - TEBI, PEBI, EXBI); - public static final Set REDUCING_PREFIXES = Set.of(DECI, CENTI, - MILLI, MICRO, NANO, PICO, FEMTO, ATTO, ZEPTO, YOCTO); - - // You may NOT get SI instances! - private SI() { - throw new AssertionError(); - } -} diff --git a/src/org/unitConverter/unit/USCustomary.java b/src/org/unitConverter/unit/USCustomary.java deleted file mode 100644 index 1c4bcfe..0000000 --- a/src/org/unitConverter/unit/USCustomary.java +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -/** - * A static utility class that contains units in the US Customary system. - * - * @author Adrien Hopkins - * @since 2019-10-21 - */ -public final class USCustomary { - /** - * US Customary units that measure area - * - * @author Adrien Hopkins - * @since 2019-11-08 - */ - public static final class Area { - public static final LinearUnit SQUARE_SURVEY_FOOT = Length.SURVEY_FOOT.times(Length.SURVEY_FOOT); - public static final LinearUnit SQUARE_CHAIN = Length.SURVEY_CHAIN.times(Length.SURVEY_CHAIN); - public static final LinearUnit ACRE = Length.SURVEY_CHAIN.times(Length.SURVEY_FURLONG); - public static final LinearUnit SECTION = Length.SURVEY_MILE.times(Length.SURVEY_MILE); - public static final LinearUnit SURVEY_TOWNSHIP = SECTION.times(36); - } - - /** - * US Customary units that measure length - * - * @author Adrien Hopkins - * @since 2019-10-28 - */ - public static final class Length { - public static final LinearUnit FOOT = BritishImperial.Length.FOOT; - public static final LinearUnit INCH = BritishImperial.Length.INCH; - public static final LinearUnit HAND = INCH.times(4); - public static final LinearUnit PICA = INCH.dividedBy(6); - public static final LinearUnit POINT = PICA.dividedBy(12); - public static final LinearUnit YARD = BritishImperial.Length.YARD; - public static final LinearUnit MILE = BritishImperial.Length.MILE; - - public static final LinearUnit SURVEY_FOOT = SI.METRE.times(1200.0 / 3937.0); - public static final LinearUnit SURVEY_LINK = SURVEY_FOOT.times(33.0 / 50.0); - public static final LinearUnit SURVEY_ROD = SURVEY_FOOT.times(16.5); - public static final LinearUnit SURVEY_CHAIN = SURVEY_ROD.times(4); - public static final LinearUnit SURVEY_FURLONG = SURVEY_CHAIN.times(10); - public static final LinearUnit SURVEY_MILE = SURVEY_FURLONG.times(8); - public static final LinearUnit SURVEY_LEAGUE = SURVEY_MILE.times(3); - - public static final LinearUnit NAUTICAL_MILE = BritishImperial.Length.NAUTICAL_MILE; - public static final LinearUnit FATHOM = YARD.times(2); - public static final LinearUnit CABLE = FATHOM.times(120); - } - - /** - * mass units - * - * @author Adrien Hopkins - * @since 2019-11-08 - */ - public static final class Mass { - public static final LinearUnit GRAIN = BritishImperial.Mass.GRAIN; - public static final LinearUnit DRAM = BritishImperial.Mass.DRACHM; - public static final LinearUnit OUNCE = BritishImperial.Mass.OUNCE; - public static final LinearUnit POUND = BritishImperial.Mass.POUND; - public static final LinearUnit HUNDREDWEIGHT = POUND.times(100); - public static final LinearUnit SHORT_TON = HUNDREDWEIGHT.times(20); - - // troy system for precious metals - public static final LinearUnit PENNYWEIGHT = GRAIN.times(24); - public static final LinearUnit TROY_OUNCE = PENNYWEIGHT.times(20); - public static final LinearUnit TROY_POUND = TROY_OUNCE.times(12); - } - - /** - * Volume units - * - * @author Adrien Hopkins - * @since 2019-11-08 - */ - public static final class Volume { - public static final LinearUnit CUBIC_INCH = Length.INCH.toExponent(3); - public static final LinearUnit CUBIC_FOOT = Length.FOOT.toExponent(3); - public static final LinearUnit CUBIC_YARD = Length.YARD.toExponent(3); - public static final LinearUnit ACRE_FOOT = Area.ACRE.times(Length.FOOT); - - public static final LinearUnit MINIM = SI.LITRE.withPrefix(SI.MICRO).times(61.611519921875); - public static final LinearUnit FLUID_DRAM = MINIM.times(60); - public static final LinearUnit TEASPOON = MINIM.times(80); - public static final LinearUnit TABLESPOON = TEASPOON.times(3); - public static final LinearUnit FLUID_OUNCE = TABLESPOON.times(2); - public static final LinearUnit SHOT = TABLESPOON.times(3); - public static final LinearUnit GILL = FLUID_OUNCE.times(4); - public static final LinearUnit CUP = GILL.times(2); - public static final LinearUnit PINT = CUP.times(2); - public static final LinearUnit QUART = PINT.times(2); - public static final LinearUnit GALLON = QUART.times(4); - public static final LinearUnit BARREL = GALLON.times(31.5); - public static final LinearUnit OIL_BARREL = GALLON.times(42); - public static final LinearUnit HOGSHEAD = GALLON.times(63); - - public static final LinearUnit DRY_PINT = SI.LITRE.times(0.5506104713575); - public static final LinearUnit DRY_QUART = DRY_PINT.times(2); - public static final LinearUnit DRY_GALLON = DRY_QUART.times(4); - public static final LinearUnit PECK = DRY_GALLON.times(2); - public static final LinearUnit BUSHEL = PECK.times(4); - public static final LinearUnit DRY_BARREL = CUBIC_INCH.times(7056); - } - - public static final LinearUnit OUNCE_FORCE = BritishImperial.OUNCE_FORCE; - public static final LinearUnit POUND_FORCE = BritishImperial.POUND_FORCE; - - public static final LinearUnit BRITISH_THERMAL_UNIT = BritishImperial.BRITISH_THERMAL_UNIT; - public static final LinearUnit CALORIE = BritishImperial.CALORIE; - public static final LinearUnit KILOCALORIE = BritishImperial.KILOCALORIE; - public static final LinearUnit FOOT_POUND = POUND_FORCE.times(Length.FOOT); - - public static final LinearUnit HORSEPOWER = Length.FOOT.times(POUND_FORCE).dividedBy(SI.MINUTE).times(33000); - public static final LinearUnit POUND_PER_SQUARE_INCH = POUND_FORCE.dividedBy(Length.INCH.toExponent(2)); - - public static final Unit FAHRENHEIT = BritishImperial.FAHRENHEIT; -} diff --git a/src/org/unitConverter/unit/Unit.java b/src/org/unitConverter/unit/Unit.java deleted file mode 100644 index 0a3298f..0000000 --- a/src/org/unitConverter/unit/Unit.java +++ /dev/null @@ -1,377 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.function.DoubleUnaryOperator; - -import org.unitConverter.math.DecimalComparison; -import org.unitConverter.math.ObjectProduct; - -/** - * A unit that is composed of base units. - * - * @author Adrien Hopkins - * @since 2019-10-16 - */ -public abstract class Unit implements Nameable { - /** - * Returns a unit from its base and the functions it uses to convert to and - * from its base. - * - *

    - * For example, to get a unit representing the degree Celsius, the following - * code can be used: - * - * {@code Unit.fromConversionFunctions(SI.KELVIN, tempK -> tempK - 273.15, tempC -> tempC + 273.15);} - *

    - * - * @param base unit's base - * @param converterFrom function that accepts a value expressed in the unit's - * base and returns that value expressed in this unit. - * @param converterTo function that accepts a value expressed in the unit - * and returns that value expressed in the unit's base. - * @return a unit that uses the provided functions to convert. - * @since 2019-05-22 - * @throws NullPointerException if any argument is null - */ - public static final Unit fromConversionFunctions( - final ObjectProduct base, - final DoubleUnaryOperator converterFrom, - final DoubleUnaryOperator converterTo) { - return new FunctionalUnit(base, converterFrom, converterTo); - } - - /** - * Returns a unit from its base and the functions it uses to convert to and - * from its base. - * - *

    - * For example, to get a unit representing the degree Celsius, the following - * code can be used: - * - * {@code Unit.fromConversionFunctions(SI.KELVIN, tempK -> tempK - 273.15, tempC -> tempC + 273.15);} - *

    - * - * @param base unit's base - * @param converterFrom function that accepts a value expressed in the unit's - * base and returns that value expressed in this unit. - * @param converterTo function that accepts a value expressed in the unit - * and returns that value expressed in the unit's base. - * @param ns names and symbol of unit - * @return a unit that uses the provided functions to convert. - * @since 2019-05-22 - * @throws NullPointerException if any argument is null - */ - public static final Unit fromConversionFunctions( - final ObjectProduct base, - final DoubleUnaryOperator converterFrom, - final DoubleUnaryOperator converterTo, final NameSymbol ns) { - return new FunctionalUnit(base, converterFrom, converterTo, ns); - } - - /** - * The combination of units that this unit is based on. - * - * @since 2019-10-16 - */ - private final ObjectProduct unitBase; - - /** - * This unit's name(s) and symbol - * - * @since 2020-09-07 - */ - private final NameSymbol nameSymbol; - - /** - * Cache storing the result of getDimension() - * - * @since 2019-10-16 - */ - private transient ObjectProduct dimension = null; - - /** - * Creates the {@code Unit}. - * - * @param unitBase base of unit - * @param ns names and symbol of unit - * @since 2019-10-16 - * @throws NullPointerException if unitBase or ns is null - */ - Unit(ObjectProduct unitBase, NameSymbol ns) { - this.unitBase = Objects.requireNonNull(unitBase, - "unitBase may not be null"); - this.nameSymbol = Objects.requireNonNull(ns, "ns may not be null"); - } - - /** - * A constructor that constructs {@code BaseUnit} instances. - * - * @since 2019-10-16 - */ - Unit(final String primaryName, final String symbol, - final Set otherNames) { - if (this instanceof BaseUnit) { - this.unitBase = ObjectProduct.oneOf((BaseUnit) this); - } else - throw new AssertionError(); - this.nameSymbol = NameSymbol.of(primaryName, symbol, - new HashSet<>(otherNames)); - } - - /** - * @return this unit as a {@link Unitlike} - * @since 2020-09-07 - */ - public final Unitlike asUnitlike() { - return Unitlike.fromConversionFunctions(this.getBase(), - this::convertFromBase, this::convertToBase, this.getNameSymbol()); - } - - /** - * Checks if a value expressed in this unit can be converted to a value - * expressed in {@code other} - * - * @param other unit or unitlike form to test with - * @return true if they are compatible - * @since 2019-01-13 - * @since v0.1.0 - * @throws NullPointerException if other is null - */ - public final boolean canConvertTo(final Unit other) { - Objects.requireNonNull(other, "other must not be null."); - return Objects.equals(this.getBase(), other.getBase()); - } - - /** - * Checks if a value expressed in this unit can be converted to a value - * expressed in {@code other} - * - * @param other unit or unitlike form to test with - * @return true if they are compatible - * @since 2019-01-13 - * @since v0.1.0 - * @throws NullPointerException if other is null - */ - public final boolean canConvertTo(final Unitlike other) { - Objects.requireNonNull(other, "other must not be null."); - return Objects.equals(this.getBase(), other.getBase()); - } - - /** - * Converts from a value expressed in this unit's base unit to a value - * expressed in this unit. - *

    - * This must be the inverse of {@code convertToBase}, so - * {@code convertFromBase(convertToBase(value))} must be equal to - * {@code value} for any value, ignoring precision loss by roundoff error. - *

    - *

    - * If this unit is a base unit, this method should return - * {@code value}. - *

    - * - * @implSpec This method is used by {@link #convertTo}, and its behaviour - * affects the behaviour of {@code convertTo}. - * - * @param value value expressed in base unit - * @return value expressed in this unit - * @since 2018-12-22 - * @since v0.1.0 - */ - protected abstract double convertFromBase(double value); - - /** - * Converts a value expressed in this unit to a value expressed in - * {@code other}. - * - * @implSpec If unit conversion is possible, this implementation returns - * {@code other.convertFromBase(this.convertToBase(value))}. - * Therefore, overriding either of those methods will change the - * output of this method. - * - * @param other unit to convert to - * @param value value to convert - * @return converted value - * @since 2019-05-22 - * @throws IllegalArgumentException if {@code other} is incompatible for - * conversion with this unit (as tested by - * {@link Unit#canConvertTo}). - * @throws NullPointerException if other is null - */ - public final double convertTo(final Unit other, final double value) { - Objects.requireNonNull(other, "other must not be null."); - if (this.canConvertTo(other)) - return other.convertFromBase(this.convertToBase(value)); - else - throw new IllegalArgumentException( - String.format("Cannot convert from %s to %s.", this, other)); - } - - /** - * Converts a value expressed in this unit to a value expressed in - * {@code other}. - * - * @implSpec If conversion is possible, this implementation returns - * {@code other.convertFromBase(this.convertToBase(value))}. - * Therefore, overriding either of those methods will change the - * output of this method. - * - * @param other unitlike form to convert to - * @param value value to convert - * @param type of value to convert to - * @return converted value - * @since 2020-09-07 - * @throws IllegalArgumentException if {@code other} is incompatible for - * conversion with this unit (as tested by - * {@link Unit#canConvertTo}). - * @throws NullPointerException if other is null - */ - public final W convertTo(final Unitlike other, final double value) { - Objects.requireNonNull(other, "other must not be null."); - if (this.canConvertTo(other)) - return other.convertFromBase(this.convertToBase(value)); - else - throw new IllegalArgumentException( - String.format("Cannot convert from %s to %s.", this, other)); - } - - /** - * Converts from a value expressed in this unit to a value expressed in this - * unit's base unit. - *

    - * This must be the inverse of {@code convertFromBase}, so - * {@code convertToBase(convertFromBase(value))} must be equal to - * {@code value} for any value, ignoring precision loss by roundoff error. - *

    - *

    - * If this unit is a base unit, this method should return - * {@code value}. - *

    - * - * @implSpec This method is used by {@link #convertTo}, and its behaviour - * affects the behaviour of {@code convertTo}. - * - * @param value value expressed in this unit - * @return value expressed in base unit - * @since 2018-12-22 - * @since v0.1.0 - */ - protected abstract double convertToBase(double value); - - /** - * @return combination of units that this unit is based on - * @since 2018-12-22 - * @since v0.1.0 - */ - public final ObjectProduct getBase() { - return this.unitBase; - } - - /** - * @return dimension measured by this unit - * @since 2018-12-22 - * @since v0.1.0 - */ - public final ObjectProduct getDimension() { - if (this.dimension == null) { - final Map mapping = this.unitBase.exponentMap(); - final Map dimensionMap = new HashMap<>(); - - for (final BaseUnit key : mapping.keySet()) { - dimensionMap.put(key.getBaseDimension(), mapping.get(key)); - } - - this.dimension = ObjectProduct.fromExponentMapping(dimensionMap); - } - return this.dimension; - } - - /** - * @return the nameSymbol - * @since 2020-09-07 - */ - @Override - public final NameSymbol getNameSymbol() { - return this.nameSymbol; - } - - /** - * Returns true iff this unit is metric. - *

    - * "Metric" is defined by three conditions: - *

      - *
    • Must be an instance of {@link LinearUnit}.
    • - *
    • Must be based on the SI base units (as determined by getBase())
    • - *
    • The conversion factor must be a power of 10.
    • - *
    - *

    - * Note that this definition excludes some units that many would consider - * "metric", such as the degree Celsius (fails the first condition), - * calories, minutes and hours (fail the third condition). - *

    - * All SI units (as designated by the BIPM) except the degree Celsius are - * considered "metric" by this definition. - * - * @since 2020-08-27 - */ - public final boolean isMetric() { - // first condition - check that it is a linear unit - if (!(this instanceof LinearUnit)) - return false; - final LinearUnit linear = (LinearUnit) this; - - // second condition - check that - for (final BaseUnit b : linear.getBase().getBaseSet()) { - if (!SI.BaseUnits.BASE_UNITS.contains(b)) - return false; - } - - // third condition - check that conversion factor is a power of 10 - return DecimalComparison - .equals(Math.log10(linear.getConversionFactor()) % 1.0, 0); - } - - @Override - public String toString() { - return this.getPrimaryName().orElse("Unnamed unit") - + (this.getSymbol().isPresent() - ? String.format(" (%s)", this.getSymbol().get()) - : "") - + ", derived from " - + this.getBase().toString(u -> u.getSymbol().get()) - + (this.getOtherNames().isEmpty() ? "" - : ", also called " + String.join(", ", this.getOtherNames())); - } - - /** - * @param ns name(s) and symbol to use - * @return a copy of this unit with provided name(s) and symbol - * @since 2019-10-21 - * @throws NullPointerException if ns is null - */ - public Unit withName(final NameSymbol ns) { - return fromConversionFunctions(this.getBase(), this::convertFromBase, - this::convertToBase, - Objects.requireNonNull(ns, "ns must not be null.")); - } -} diff --git a/src/org/unitConverter/unit/UnitDatabase.java b/src/org/unitConverter/unit/UnitDatabase.java deleted file mode 100644 index 000acf5..0000000 --- a/src/org/unitConverter/unit/UnitDatabase.java +++ /dev/null @@ -1,1991 +0,0 @@ -/** - * Copyright (C) 2018 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.math.BigDecimal; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.AbstractSet; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Set; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.unitConverter.math.ConditionalExistenceCollections; -import org.unitConverter.math.DecimalComparison; -import org.unitConverter.math.ExpressionParser; -import org.unitConverter.math.ObjectProduct; -import org.unitConverter.math.UncertainDouble; - -/** - * A database of units, prefixes and dimensions, and their names. - * - * @author Adrien Hopkins - * @since 2019-01-07 - * @since v0.1.0 - */ -public final class UnitDatabase { - /** - * A map for units that allows the use of prefixes. - *

    - * As this map implementation is intended to be used as a sort of "augmented - * view" of a unit and prefix map, it is unmodifiable but instead reflects - * the changes to the maps passed into it. Do not edit this map, instead edit - * the maps that were passed in during construction. - *

    - *

    - * The rules for applying prefixes onto units are the following: - *

      - *
    • Prefixes can only be applied to linear units.
    • - *
    • Before attempting to search for prefixes in a unit name, this map will - * first search for a unit name. So, if there are two units, "B" and "AB", - * and a prefix "A", this map will favour the unit "AB" over the unit "B" - * with the prefix "A", even though they have the same string.
    • - *
    • Longer prefixes are preferred to shorter prefixes. So, if you have - * units "BC" and "C", and prefixes "AB" and "A", inputting "ABC" will return - * the unit "C" with the prefix "AB", not "BC" with the prefix "A".
    • - *
    - *

    - *

    - * This map is infinite in size if there is at least one unit and at least - * one prefix. If it is infinite, some operations that only work with finite - * collections, like converting name/entry sets to arrays, will throw an - * {@code IllegalStateException}. - *

    - *

    - * Because of ambiguities between prefixes (i.e. kilokilo = mega), - * {@link #containsValue} and {@link #values()} currently ignore prefixes. - *

    - * - * @author Adrien Hopkins - * @since 2019-04-13 - * @since v0.2.0 - */ - private static final class PrefixedUnitMap implements Map { - /** - * The class used for entry sets. - * - *

    - * If the map that created this set is infinite in size (has at least one - * unit and at least one prefix), this set is infinite as well. If this - * set is infinite in size, {@link #toArray} will fail with a - * {@code IllegalStateException} instead of creating an infinite-sized - * array. - *

    - * - * @author Adrien Hopkins - * @since 2019-04-13 - * @since v0.2.0 - */ - private static final class PrefixedUnitEntrySet - extends AbstractSet> { - /** - * The entry for this set. - * - * @author Adrien Hopkins - * @since 2019-04-14 - * @since v0.2.0 - */ - private static final class PrefixedUnitEntry - implements Entry { - private final String key; - private final Unit value; - - /** - * Creates the {@code PrefixedUnitEntry}. - * - * @param key key - * @param value value - * @since 2019-04-14 - * @since v0.2.0 - */ - public PrefixedUnitEntry(final String key, final Unit value) { - this.key = key; - this.value = value; - } - - /** - * @since 2019-05-03 - */ - @Override - public boolean equals(final Object o) { - if (!(o instanceof Map.Entry)) - return false; - final Map.Entry other = (Map.Entry) o; - return Objects.equals(this.getKey(), other.getKey()) - && Objects.equals(this.getValue(), other.getValue()); - } - - @Override - public String getKey() { - return this.key; - } - - @Override - public Unit getValue() { - return this.value; - } - - /** - * @since 2019-05-03 - */ - @Override - public int hashCode() { - return (this.getKey() == null ? 0 : this.getKey().hashCode()) - ^ (this.getValue() == null ? 0 - : this.getValue().hashCode()); - } - - @Override - public Unit setValue(final Unit value) { - throw new UnsupportedOperationException( - "Cannot set value in an immutable entry"); - } - - /** - * Returns a string representation of the entry. The format of the - * string is the string representation of the key, then the equals - * ({@code =}) character, then the string representation of the - * value. - * - * @since 2019-05-03 - */ - @Override - public String toString() { - return this.getKey() + "=" + this.getValue(); - } - } - - /** - * An iterator that iterates over the units of a - * {@code PrefixedUnitNameSet}. - * - * @author Adrien Hopkins - * @since 2019-04-14 - * @since v0.2.0 - */ - private static final class PrefixedUnitEntryIterator - implements Iterator> { - // position in the unit list - private int unitNamePosition = 0; - // the indices of the prefixes attached to the current unit - private final List prefixCoordinates = new ArrayList<>(); - - // values from the unit entry set - private final Map map; - private transient final List unitNames; - private transient final List prefixNames; - - /** - * Creates the - * {@code UnitsDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator}. - * - * @since 2019-04-14 - * @since v0.2.0 - */ - public PrefixedUnitEntryIterator(final PrefixedUnitMap map) { - this.map = map; - this.unitNames = new ArrayList<>(map.units.keySet()); - this.prefixNames = new ArrayList<>(map.prefixes.keySet()); - } - - /** - * @return current unit name - * @since 2019-04-14 - * @since v0.2.0 - */ - private String getCurrentUnitName() { - final StringBuilder unitName = new StringBuilder(); - for (final int i : this.prefixCoordinates) { - unitName.append(this.prefixNames.get(i)); - } - unitName.append(this.unitNames.get(this.unitNamePosition)); - - return unitName.toString(); - } - - @Override - public boolean hasNext() { - if (this.unitNames.isEmpty()) - return false; - else { - if (this.prefixNames.isEmpty()) - return this.unitNamePosition >= this.unitNames.size() - 1; - else - return true; - } - } - - /** - * Changes this iterator's position to the next available one. - * - * @since 2019-04-14 - * @since v0.2.0 - */ - private void incrementPosition() { - this.unitNamePosition++; - - if (this.unitNamePosition >= this.unitNames.size()) { - // we have used all of our units, go to a different prefix - this.unitNamePosition = 0; - - // if the prefix coordinates are empty, then set it to [0] - if (this.prefixCoordinates.isEmpty()) { - this.prefixCoordinates.add(0, 0); - } else { - // get the prefix coordinate to increment, then increment - int i = this.prefixCoordinates.size() - 1; - this.prefixCoordinates.set(i, - this.prefixCoordinates.get(i) + 1); - - // fix any carrying errors - while (i >= 0 && this.prefixCoordinates - .get(i) >= this.prefixNames.size()) { - // carry over - this.prefixCoordinates.set(i--, 0); // null and - // decrement at the - // same time - - if (i < 0) { // we need to add a new coordinate - this.prefixCoordinates.add(0, 0); - } else { // increment an existing one - this.prefixCoordinates.set(i, - this.prefixCoordinates.get(i) + 1); - } - } - } - } - } - - @Override - public Entry next() { - // get next element - final Entry nextEntry = this.peek(); - - // iterate to next position - this.incrementPosition(); - - return nextEntry; - } - - /** - * @return the next element in the iterator, without iterating over - * it - * @since 2019-05-03 - */ - private Entry peek() { - if (!this.hasNext()) - throw new NoSuchElementException("No units left!"); - - // if I have prefixes, ensure I'm not using a nonlinear unit - // since all of the unprefixed stuff is done, just remove - // nonlinear units - if (!this.prefixCoordinates.isEmpty()) { - while (this.unitNamePosition < this.unitNames.size() - && !(this.map.get(this.unitNames.get( - this.unitNamePosition)) instanceof LinearUnit)) { - this.unitNames.remove(this.unitNamePosition); - } - } - - final String nextName = this.getCurrentUnitName(); - - return new PrefixedUnitEntry(nextName, this.map.get(nextName)); - } - - /** - * Returns a string representation of the object. The exact details - * of the representation are unspecified and subject to change. - * - * @since 2019-05-03 - */ - @Override - public String toString() { - return String.format( - "Iterator iterating over name-unit entries; next value is \"%s\"", - this.peek()); - } - } - - // the map that created this set - private final PrefixedUnitMap map; - - /** - * Creates the {@code PrefixedUnitNameSet}. - * - * @param map map that created this set - * @since 2019-04-13 - * @since v0.2.0 - */ - public PrefixedUnitEntrySet(final PrefixedUnitMap map) { - this.map = map; - } - - @Override - public boolean add(final Map.Entry e) { - throw new UnsupportedOperationException( - "Cannot add to an immutable set"); - } - - @Override - public boolean addAll( - final Collection> c) { - throw new UnsupportedOperationException( - "Cannot add to an immutable set"); - } - - @Override - public void clear() { - throw new UnsupportedOperationException( - "Cannot clear an immutable set"); - } - - @Override - public boolean contains(final Object o) { - // get the entry - final Entry entry; - - try { - // This is OK because I'm in a try-catch block, catching the - // exact exception that would be thrown. - @SuppressWarnings("unchecked") - final Entry tempEntry = (Entry) o; - entry = tempEntry; - } catch (final ClassCastException e) { - throw new IllegalArgumentException( - "Attempted to test for an entry using a non-entry."); - } - - return this.map.containsKey(entry.getKey()) - && this.map.get(entry.getKey()).equals(entry.getValue()); - } - - @Override - public boolean containsAll(final Collection c) { - for (final Object o : c) - if (!this.contains(o)) - return false; - return true; - } - - @Override - public boolean isEmpty() { - return this.map.isEmpty(); - } - - @Override - public Iterator> iterator() { - return new PrefixedUnitEntryIterator(this.map); - } - - @Override - public boolean remove(final Object o) { - throw new UnsupportedOperationException( - "Cannot remove from an immutable set"); - } - - @Override - public boolean removeAll(final Collection c) { - throw new UnsupportedOperationException( - "Cannot remove from an immutable set"); - } - - @Override - public boolean removeIf( - final Predicate> filter) { - throw new UnsupportedOperationException( - "Cannot remove from an immutable set"); - } - - @Override - public boolean retainAll(final Collection c) { - throw new UnsupportedOperationException( - "Cannot remove from an immutable set"); - } - - @Override - public int size() { - if (this.map.units.isEmpty()) - return 0; - else { - if (this.map.prefixes.isEmpty()) - return this.map.units.size(); - else - // infinite set - return Integer.MAX_VALUE; - } - } - - /** - * @throws IllegalStateException if the set is infinite in size - */ - @Override - public Object[] toArray() { - if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) - return super.toArray(); - else - // infinite set - throw new IllegalStateException( - "Cannot make an infinite set into an array."); - } - - /** - * @throws IllegalStateException if the set is infinite in size - */ - @Override - public T[] toArray(final T[] a) { - if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) - return super.toArray(a); - else - // infinite set - throw new IllegalStateException( - "Cannot make an infinite set into an array."); - } - - @Override - public String toString() { - if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) - return super.toString(); - else - return String.format( - "Infinite set of name-unit entries created from units %s and prefixes %s", - this.map.units, this.map.prefixes); - } - } - - /** - * The class used for unit name sets. - * - *

    - * If the map that created this set is infinite in size (has at least one - * unit and at least one prefix), this set is infinite as well. If this - * set is infinite in size, {@link #toArray} will fail with a - * {@code IllegalStateException} instead of creating an infinite-sized - * array. - *

    - * - * @author Adrien Hopkins - * @since 2019-04-13 - * @since v0.2.0 - */ - private static final class PrefixedUnitNameSet - extends AbstractSet { - /** - * An iterator that iterates over the units of a - * {@code PrefixedUnitNameSet}. - * - * @author Adrien Hopkins - * @since 2019-04-14 - * @since v0.2.0 - */ - private static final class PrefixedUnitNameIterator - implements Iterator { - // position in the unit list - private int unitNamePosition = 0; - // the indices of the prefixes attached to the current unit - private final List prefixCoordinates = new ArrayList<>(); - - // values from the unit name set - private final Map map; - private transient final List unitNames; - private transient final List prefixNames; - - /** - * Creates the - * {@code UnitsDatabase.PrefixedUnitMap.PrefixedUnitNameSet.PrefixedUnitNameIterator}. - * - * @since 2019-04-14 - * @since v0.2.0 - */ - public PrefixedUnitNameIterator(final PrefixedUnitMap map) { - this.map = map; - this.unitNames = new ArrayList<>(map.units.keySet()); - this.prefixNames = new ArrayList<>(map.prefixes.keySet()); - } - - /** - * @return current unit name - * @since 2019-04-14 - * @since v0.2.0 - */ - private String getCurrentUnitName() { - final StringBuilder unitName = new StringBuilder(); - for (final int i : this.prefixCoordinates) { - unitName.append(this.prefixNames.get(i)); - } - unitName.append(this.unitNames.get(this.unitNamePosition)); - - return unitName.toString(); - } - - @Override - public boolean hasNext() { - if (this.unitNames.isEmpty()) - return false; - else { - if (this.prefixNames.isEmpty()) - return this.unitNamePosition >= this.unitNames.size() - 1; - else - return true; - } - } - - /** - * Changes this iterator's position to the next available one. - * - * @since 2019-04-14 - * @since v0.2.0 - */ - private void incrementPosition() { - this.unitNamePosition++; - - if (this.unitNamePosition >= this.unitNames.size()) { - // we have used all of our units, go to a different prefix - this.unitNamePosition = 0; - - // if the prefix coordinates are empty, then set it to [0] - if (this.prefixCoordinates.isEmpty()) { - this.prefixCoordinates.add(0, 0); - } else { - // get the prefix coordinate to increment, then increment - int i = this.prefixCoordinates.size() - 1; - this.prefixCoordinates.set(i, - this.prefixCoordinates.get(i) + 1); - - // fix any carrying errors - while (i >= 0 && this.prefixCoordinates - .get(i) >= this.prefixNames.size()) { - // carry over - this.prefixCoordinates.set(i--, 0); // null and - // decrement at the - // same time - - if (i < 0) { // we need to add a new coordinate - this.prefixCoordinates.add(0, 0); - } else { // increment an existing one - this.prefixCoordinates.set(i, - this.prefixCoordinates.get(i) + 1); - } - } - } - } - } - - @Override - public String next() { - final String nextName = this.peek(); - - this.incrementPosition(); - - return nextName; - } - - /** - * @return the next element in the iterator, without iterating over - * it - * @since 2019-05-03 - */ - private String peek() { - if (!this.hasNext()) - throw new NoSuchElementException("No units left!"); - // if I have prefixes, ensure I'm not using a nonlinear unit - // since all of the unprefixed stuff is done, just remove - // nonlinear units - if (!this.prefixCoordinates.isEmpty()) { - while (this.unitNamePosition < this.unitNames.size() - && !(this.map.get(this.unitNames.get( - this.unitNamePosition)) instanceof LinearUnit)) { - this.unitNames.remove(this.unitNamePosition); - } - } - - return this.getCurrentUnitName(); - } - - /** - * Returns a string representation of the object. The exact details - * of the representation are unspecified and subject to change. - * - * @since 2019-05-03 - */ - @Override - public String toString() { - return String.format( - "Iterator iterating over unit names; next value is \"%s\"", - this.peek()); - } - } - - // the map that created this set - private final PrefixedUnitMap map; - - /** - * Creates the {@code PrefixedUnitNameSet}. - * - * @param map map that created this set - * @since 2019-04-13 - * @since v0.2.0 - */ - public PrefixedUnitNameSet(final PrefixedUnitMap map) { - this.map = map; - } - - @Override - public boolean add(final String e) { - throw new UnsupportedOperationException( - "Cannot add to an immutable set"); - } - - @Override - public boolean addAll(final Collection c) { - throw new UnsupportedOperationException( - "Cannot add to an immutable set"); - } - - @Override - public void clear() { - throw new UnsupportedOperationException( - "Cannot clear an immutable set"); - } - - @Override - public boolean contains(final Object o) { - return this.map.containsKey(o); - } - - @Override - public boolean containsAll(final Collection c) { - for (final Object o : c) - if (!this.contains(o)) - return false; - return true; - } - - @Override - public boolean isEmpty() { - return this.map.isEmpty(); - } - - @Override - public Iterator iterator() { - return new PrefixedUnitNameIterator(this.map); - } - - @Override - public boolean remove(final Object o) { - throw new UnsupportedOperationException( - "Cannot remove from an immutable set"); - } - - @Override - public boolean removeAll(final Collection c) { - throw new UnsupportedOperationException( - "Cannot remove from an immutable set"); - } - - @Override - public boolean removeIf(final Predicate filter) { - throw new UnsupportedOperationException( - "Cannot remove from an immutable set"); - } - - @Override - public boolean retainAll(final Collection c) { - throw new UnsupportedOperationException( - "Cannot remove from an immutable set"); - } - - @Override - public int size() { - if (this.map.units.isEmpty()) - return 0; - else { - if (this.map.prefixes.isEmpty()) - return this.map.units.size(); - else - // infinite set - return Integer.MAX_VALUE; - } - } - - /** - * @throws IllegalStateException if the set is infinite in size - */ - @Override - public Object[] toArray() { - if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) - return super.toArray(); - else - // infinite set - throw new IllegalStateException( - "Cannot make an infinite set into an array."); - - } - - /** - * @throws IllegalStateException if the set is infinite in size - */ - @Override - public T[] toArray(final T[] a) { - if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) - return super.toArray(a); - else - // infinite set - throw new IllegalStateException( - "Cannot make an infinite set into an array."); - } - - @Override - public String toString() { - if (this.map.units.isEmpty() || this.map.prefixes.isEmpty()) - return super.toString(); - else - return String.format( - "Infinite set of name-unit entries created from units %s and prefixes %s", - this.map.units, this.map.prefixes); - } - } - - /** - * The units stored in this collection, without prefixes. - * - * @since 2019-04-13 - * @since v0.2.0 - */ - private final Map units; - - /** - * The available prefixes for use. - * - * @since 2019-04-13 - * @since v0.2.0 - */ - private final Map prefixes; - - // caches - private transient Collection values = null; - private transient Set keySet = null; - private transient Set> entrySet = null; - - /** - * Creates the {@code PrefixedUnitMap}. - * - * @param units map mapping unit names to units - * @param prefixes map mapping prefix names to prefixes - * @since 2019-04-13 - * @since v0.2.0 - */ - public PrefixedUnitMap(final Map units, - final Map prefixes) { - // I am making unmodifiable maps to ensure I don't accidentally make - // changes. - this.units = Collections.unmodifiableMap(units); - this.prefixes = Collections.unmodifiableMap(prefixes); - } - - @Override - public void clear() { - throw new UnsupportedOperationException( - "Cannot clear an immutable map"); - } - - @Override - public Unit compute(final String key, - final BiFunction remappingFunction) { - throw new UnsupportedOperationException( - "Cannot edit an immutable map"); - } - - @Override - public Unit computeIfAbsent(final String key, - final Function mappingFunction) { - throw new UnsupportedOperationException( - "Cannot edit an immutable map"); - } - - @Override - public Unit computeIfPresent(final String key, - final BiFunction remappingFunction) { - throw new UnsupportedOperationException( - "Cannot edit an immutable map"); - } - - @Override - public boolean containsKey(final Object key) { - // First, test if there is a unit with the key - if (this.units.containsKey(key)) - return true; - - // Next, try to cast it to String - if (!(key instanceof String)) - throw new IllegalArgumentException( - "Attempted to test for a unit using a non-string name."); - final String unitName = (String) key; - - // Then, look for the longest prefix that is attached to a valid unit - String longestPrefix = null; - int longestLength = 0; - - for (final String prefixName : this.prefixes.keySet()) { - // a prefix name is valid if: - // - it is prefixed (i.e. the unit name starts with it) - // - it is longer than the existing largest prefix (since I am - // looking for the longest valid prefix) - // - the part after the prefix is a valid unit name - // - the unit described that name is a linear unit (since only - // linear units can have prefixes) - if (unitName.startsWith(prefixName) - && prefixName.length() > longestLength) { - final String rest = unitName.substring(prefixName.length()); - if (this.containsKey(rest) - && this.get(rest) instanceof LinearUnit) { - longestPrefix = prefixName; - longestLength = prefixName.length(); - } - } - } - - return longestPrefix != null; - } - - /** - * {@inheritDoc} - * - *

    - * Because of ambiguities between prefixes (i.e. kilokilo = mega), this - * method only tests for prefixless units. - *

    - */ - @Override - public boolean containsValue(final Object value) { - return this.units.containsValue(value); - } - - @Override - public Set> entrySet() { - if (this.entrySet == null) { - this.entrySet = new PrefixedUnitEntrySet(this); - } - return this.entrySet; - } - - @Override - public Unit get(final Object key) { - // First, test if there is a unit with the key - if (this.units.containsKey(key)) - return this.units.get(key); - - // Next, try to cast it to String - if (!(key instanceof String)) - throw new IllegalArgumentException( - "Attempted to obtain a unit using a non-string name."); - final String unitName = (String) key; - - // Then, look for the longest prefix that is attached to a valid unit - String longestPrefix = null; - int longestLength = 0; - - for (final String prefixName : this.prefixes.keySet()) { - // a prefix name is valid if: - // - it is prefixed (i.e. the unit name starts with it) - // - it is longer than the existing largest prefix (since I am - // looking for the longest valid prefix) - // - the part after the prefix is a valid unit name - // - the unit described that name is a linear unit (since only - // linear units can have prefixes) - if (unitName.startsWith(prefixName) - && prefixName.length() > longestLength) { - final String rest = unitName.substring(prefixName.length()); - if (this.containsKey(rest) - && this.get(rest) instanceof LinearUnit) { - longestPrefix = prefixName; - longestLength = prefixName.length(); - } - } - } - - // if none found, returns null - if (longestPrefix == null) - return null; - else { - // get necessary data - final String rest = unitName.substring(longestLength); - // this cast will not fail because I verified that it would work - // before selecting this prefix - final LinearUnit unit = (LinearUnit) this.get(rest); - final UnitPrefix prefix = this.prefixes.get(longestPrefix); - - return unit.withPrefix(prefix); - } - } - - @Override - public boolean isEmpty() { - return this.units.isEmpty(); - } - - @Override - public Set keySet() { - if (this.keySet == null) { - this.keySet = new PrefixedUnitNameSet(this); - } - return this.keySet; - } - - @Override - public Unit merge(final String key, final Unit value, - final BiFunction remappingFunction) { - throw new UnsupportedOperationException( - "Cannot merge into an immutable map"); - } - - @Override - public Unit put(final String key, final Unit value) { - throw new UnsupportedOperationException( - "Cannot add entries to an immutable map"); - } - - @Override - public void putAll(final Map m) { - throw new UnsupportedOperationException( - "Cannot add entries to an immutable map"); - } - - @Override - public Unit putIfAbsent(final String key, final Unit value) { - throw new UnsupportedOperationException( - "Cannot add entries to an immutable map"); - } - - @Override - public Unit remove(final Object key) { - throw new UnsupportedOperationException( - "Cannot remove entries from an immutable map"); - } - - @Override - public boolean remove(final Object key, final Object value) { - throw new UnsupportedOperationException( - "Cannot remove entries from an immutable map"); - } - - @Override - public Unit replace(final String key, final Unit value) { - throw new UnsupportedOperationException( - "Cannot replace entries in an immutable map"); - } - - @Override - public boolean replace(final String key, final Unit oldValue, - final Unit newValue) { - throw new UnsupportedOperationException( - "Cannot replace entries in an immutable map"); - } - - @Override - public void replaceAll( - final BiFunction function) { - throw new UnsupportedOperationException( - "Cannot replace entries in an immutable map"); - } - - @Override - public int size() { - if (this.units.isEmpty()) - return 0; - else { - if (this.prefixes.isEmpty()) - return this.units.size(); - else - // infinite set - return Integer.MAX_VALUE; - } - } - - @Override - public String toString() { - if (this.units.isEmpty() || this.prefixes.isEmpty()) - return super.toString(); - else - return String.format( - "Infinite map of name-unit entries created from units %s and prefixes %s", - this.units, this.prefixes); - } - - /** - * {@inheritDoc} - * - *

    - * Because of ambiguities between prefixes (i.e. kilokilo = mega), this - * method ignores prefixes. - *

    - */ - @Override - public Collection values() { - if (this.values == null) { - this.values = Collections - .unmodifiableCollection(this.units.values()); - } - return this.values; - } - } - - /** - * Replacements done to *all* expression types - */ - private static final Map EXPRESSION_REPLACEMENTS = new HashMap<>(); - - // add data to expression replacements - static { - // add spaces around operators - for (final String operator : Arrays.asList("\\*", "/", "\\^")) { - EXPRESSION_REPLACEMENTS.put(Pattern.compile(operator), - " " + operator + " "); - } - - // replace multiple spaces with a single space - EXPRESSION_REPLACEMENTS.put(Pattern.compile(" +"), " "); - // place brackets around any expression of the form "number unit", with or - // without the space - EXPRESSION_REPLACEMENTS.put(Pattern.compile("((?:-?[1-9]\\d*|0)" // integer - + "(?:\\.\\d+(?:[eE]\\d+))?)" // optional decimal point with numbers - // after it - + "\\s*" // optional space(s) - + "([a-zA-Z]+(?:\\^\\d+)?" // any string of letters - + "(?:\\s+[a-zA-Z]+(?:\\^\\d+)?))" // optional other letters - + "(?!-?\\d)" // no number directly afterwards (avoids matching - // "1e3") - ), "\\($1 $2\\)"); - } - - /** - * A regular expression that separates names and expressions in unit files. - */ - private static final Pattern NAME_EXPRESSION = Pattern - .compile("(\\S+)\\s+(\\S.*)"); - - /** - * The exponent operator - * - * @param base base of exponentiation - * @param exponentUnit exponent - * @return result - * @since 2019-04-10 - * @since v0.2.0 - */ - private static final LinearUnit exponentiateUnits(final LinearUnit base, - final LinearUnit exponentUnit) { - // exponent function - first check if o2 is a number, - if (exponentUnit.getBase().equals(SI.ONE.getBase())) { - // then check if it is an integer, - final double exponent = exponentUnit.getConversionFactor(); - if (DecimalComparison.equals(exponent % 1, 0)) - // then exponentiate - return base.toExponent((int) (exponent + 0.5)); - else - // not an integer - throw new UnsupportedOperationException( - "Decimal exponents are currently not supported."); - } else - // not a number - throw new IllegalArgumentException("Exponents must be numbers."); - } - - /** - * The exponent operator - * - * @param base base of exponentiation - * @param exponentUnit exponent - * @return result - * @since 2020-08-04 - */ - private static final LinearUnitValue exponentiateUnitValues( - final LinearUnitValue base, final LinearUnitValue exponentValue) { - // exponent function - first check if o2 is a number, - if (exponentValue.canConvertTo(SI.ONE)) { - // then check if it is an integer, - final double exponent = exponentValue.getValueExact(); - if (DecimalComparison.equals(exponent % 1, 0)) - // then exponentiate - return base.toExponent((int) (exponent + 0.5)); - else - // not an integer - throw new UnsupportedOperationException( - "Decimal exponents are currently not supported."); - } else - // not a number - throw new IllegalArgumentException("Exponents must be numbers."); - } - - /** - * The units in this system, excluding prefixes. - * - * @since 2019-01-07 - * @since v0.1.0 - */ - private final Map prefixlessUnits; - - /** - * The unit prefixes in this system. - * - * @since 2019-01-14 - * @since v0.1.0 - */ - private final Map prefixes; - - /** - * The dimensions in this system. - * - * @since 2019-03-14 - * @since v0.2.0 - */ - private final Map> dimensions; - - /** - * A map mapping strings to units (including prefixes) - * - * @since 2019-04-13 - * @since v0.2.0 - */ - private final Map units; - - /** - * The rule that specifies when prefix repetition is allowed. It takes in one - * argument: a list of the prefixes being applied to the unit - *

    - * The prefixes are inputted in application order. This means that - * testing whether "kilomegagigametre" is a valid unit is equivalent to - * running the following code (assuming all variables are defined correctly): - *
    - * {@code prefixRepetitionRule.test(Arrays.asList(giga, mega, kilo))} - */ - private Predicate> prefixRepetitionRule; - - /** - * A parser that can parse unit expressions. - * - * @since 2019-03-22 - * @since v0.2.0 - */ - private final ExpressionParser unitExpressionParser = new ExpressionParser.Builder<>( - this::getLinearUnit).addBinaryOperator("+", (o1, o2) -> o1.plus(o2), 0) - .addBinaryOperator("-", (o1, o2) -> o1.minus(o2), 0) - .addBinaryOperator("*", (o1, o2) -> o1.times(o2), 1) - .addSpaceFunction("*") - .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 1) - .addBinaryOperator("^", UnitDatabase::exponentiateUnits, 2) - .build(); - - /** - * A parser that can parse unit value expressions. - * - * @since 2020-08-04 - */ - private final ExpressionParser unitValueExpressionParser = new ExpressionParser.Builder<>( - this::getLinearUnitValue) - .addBinaryOperator("+", (o1, o2) -> o1.plus(o2), 0) - .addBinaryOperator("-", (o1, o2) -> o1.minus(o2), 0) - .addBinaryOperator("*", (o1, o2) -> o1.times(o2), 1) - .addSpaceFunction("*") - .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 1) - .addBinaryOperator("^", UnitDatabase::exponentiateUnitValues, 2) - .build(); - - /** - * A parser that can parse unit prefix expressions - * - * @since 2019-04-13 - * @since v0.2.0 - */ - private final ExpressionParser prefixExpressionParser = new ExpressionParser.Builder<>( - this::getPrefix).addBinaryOperator("*", (o1, o2) -> o1.times(o2), 0) - .addSpaceFunction("*") - .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 0) - .addBinaryOperator("^", - (o1, o2) -> o1.toExponent(o2.getMultiplier()), 1) - .build(); - - /** - * A parser that can parse unit dimension expressions. - * - * @since 2019-04-13 - * @since v0.2.0 - */ - private final ExpressionParser> unitDimensionParser = new ExpressionParser.Builder<>( - this::getDimension).addBinaryOperator("*", (o1, o2) -> o1.times(o2), 0) - .addSpaceFunction("*") - .addBinaryOperator("/", (o1, o2) -> o1.dividedBy(o2), 0).build(); - - /** - * Creates the {@code UnitsDatabase}. - * - * @since 2019-01-10 - * @since v0.1.0 - */ - public UnitDatabase() { - this(prefixes -> true); - } - - /** - * Creates the {@code UnitsDatabase} - * - * @param prefixRepetitionRule the rule that determines when prefix - * repetition is allowed - * @since 2020-08-26 - */ - public UnitDatabase(Predicate> prefixRepetitionRule) { - this.prefixlessUnits = new HashMap<>(); - this.prefixes = new HashMap<>(); - this.dimensions = new HashMap<>(); - this.prefixRepetitionRule = prefixRepetitionRule; - this.units = ConditionalExistenceCollections.conditionalExistenceMap( - new PrefixedUnitMap(this.prefixlessUnits, this.prefixes), - entry -> this.prefixRepetitionRule - .test(this.getPrefixesFromName(entry.getKey()))); - } - - /** - * Adds a unit dimension to the database. - * - * @param name dimension's name - * @param dimension dimension to add - * @throws NullPointerException if name or dimension is null - * @since 2019-03-14 - * @since v0.2.0 - */ - public void addDimension(final String name, - final ObjectProduct dimension) { - this.dimensions.put( - Objects.requireNonNull(name, "name must not be null."), - Objects.requireNonNull(dimension, "dimension must not be null.")); - } - - /** - * Adds to the list from a line in a unit dimension file. - * - * @param line line to look at - * @param lineCounter number of line, for error messages - * @since 2019-04-10 - * @since v0.2.0 - */ - private void addDimensionFromLine(final String line, - final long lineCounter) { - // ignore lines that start with a # sign - they're comments - if (line.isEmpty()) - return; - if (line.contains("#")) { - this.addDimensionFromLine(line.substring(0, line.indexOf("#")), - lineCounter); - return; - } - - // divide line into name and expression - final Matcher lineMatcher = NAME_EXPRESSION.matcher(line); - if (!lineMatcher.matches()) - throw new IllegalArgumentException(String.format( - "Error at line %d: Lines of a dimension file must consist of a dimension name, then spaces or tabs, then a dimension expression.", - lineCounter)); - final String name = lineMatcher.group(1); - final String expression = lineMatcher.group(2); - - if (name.endsWith(" ")) { - System.err.printf("Warning - line %d's dimension name ends in a space", - lineCounter); - } - - // if expression is "!", search for an existing dimension - // if no unit found, throw an error - if (expression.equals("!")) { - if (!this.containsDimensionName(name)) - throw new IllegalArgumentException(String.format( - "! used but no dimension found (line %d).", lineCounter)); - } else { - // it's a unit, get the unit - final ObjectProduct dimension; - try { - dimension = this.getDimensionFromExpression(expression); - } catch (final IllegalArgumentException e) { - System.err.printf("Parsing error on line %d:%n", lineCounter); - throw e; - } - - this.addDimension(name, dimension); - } - } - - /** - * Adds a unit prefix to the database. - * - * @param name prefix's name - * @param prefix prefix to add - * @throws NullPointerException if name or prefix is null - * @since 2019-01-14 - * @since v0.1.0 - */ - public void addPrefix(final String name, final UnitPrefix prefix) { - this.prefixes.put(Objects.requireNonNull(name, "name must not be null."), - Objects.requireNonNull(prefix, "prefix must not be null.")); - } - - /** - * Adds a unit to the database. - * - * @param name unit's name - * @param unit unit to add - * @throws NullPointerException if unit is null - * @since 2019-01-10 - * @since v0.1.0 - */ - public void addUnit(final String name, final Unit unit) { - this.prefixlessUnits.put( - Objects.requireNonNull(name, "name must not be null."), - Objects.requireNonNull(unit, "unit must not be null.")); - } - - /** - * Adds to the list from a line in a unit file. - * - * @param line line to look at - * @param lineCounter number of line, for error messages - * @since 2019-04-10 - * @since v0.2.0 - */ - private void addUnitOrPrefixFromLine(final String line, - final long lineCounter) { - // ignore lines that start with a # sign - they're comments - if (line.isEmpty()) - return; - if (line.contains("#")) { - this.addUnitOrPrefixFromLine(line.substring(0, line.indexOf("#")), - lineCounter); - return; - } - - // divide line into name and expression - final Matcher lineMatcher = NAME_EXPRESSION.matcher(line); - if (!lineMatcher.matches()) - throw new IllegalArgumentException(String.format( - "Error at line %d: Lines of a unit file must consist of a unit name, then spaces or tabs, then a unit expression.", - lineCounter)); - final String name = lineMatcher.group(1); - - final String expression = lineMatcher.group(2); - - if (name.endsWith(" ")) { - System.err.printf("Warning - line %d's unit name ends in a space", - lineCounter); - } - - // if expression is "!", search for an existing unit - // if no unit found, throw an error - if (expression.equals("!")) { - if (!this.containsUnitName(name)) - throw new IllegalArgumentException(String - .format("! used but no unit found (line %d).", lineCounter)); - } else { - if (name.endsWith("-")) { - final UnitPrefix prefix; - try { - prefix = this.getPrefixFromExpression(expression); - } catch (final IllegalArgumentException e) { - System.err.printf("Parsing error on line %d:%n", lineCounter); - throw e; - } - this.addPrefix(name.substring(0, name.length() - 1), prefix); - } else { - // it's a unit, get the unit - final Unit unit; - try { - unit = this.getUnitFromExpression(expression); - } catch (final IllegalArgumentException e) { - System.err.printf("Parsing error on line %d:%n", lineCounter); - throw e; - } - - this.addUnit(name, unit); - } - } - } - - /** - * Tests if the database has a unit dimension with this name. - * - * @param name name to test - * @return if database contains name - * @since 2019-03-14 - * @since v0.2.0 - */ - public boolean containsDimensionName(final String name) { - return this.dimensions.containsKey(name); - } - - /** - * Tests if the database has a unit prefix with this name. - * - * @param name name to test - * @return if database contains name - * @since 2019-01-13 - * @since v0.1.0 - */ - public boolean containsPrefixName(final String name) { - return this.prefixes.containsKey(name); - } - - /** - * Tests if the database has a unit with this name, taking prefixes into - * consideration - * - * @param name name to test - * @return if database contains name - * @since 2019-01-13 - * @since v0.1.0 - */ - public boolean containsUnitName(final String name) { - return this.units.containsKey(name); - } - - /** - * @return a map mapping dimension names to dimensions - * @since 2019-04-13 - * @since v0.2.0 - */ - public Map> dimensionMap() { - return Collections.unmodifiableMap(this.dimensions); - } - - /** - * Evaluates a unit expression, following the same rules as - * {@link #getUnitFromExpression}. - * - * @param expression expression to parse - * @return {@code LinearUnitValue} representing value of expression - * @since 2020-08-04 - */ - public LinearUnitValue evaluateUnitExpression(final String expression) { - Objects.requireNonNull(expression, "expression must not be null."); - - // attempt to get a unit as an alias, or a number with precision first - if (this.containsUnitName(expression)) - return this.getLinearUnitValue(expression); - - // force operators to have spaces - String modifiedExpression = expression; - modifiedExpression = modifiedExpression.replaceAll("\\+", " \\+ "); - modifiedExpression = modifiedExpression.replaceAll("-", " - "); - - // format expression - for (final Entry replacement : EXPRESSION_REPLACEMENTS - .entrySet()) { - modifiedExpression = replacement.getKey().matcher(modifiedExpression) - .replaceAll(replacement.getValue()); - } - - // the previous operation breaks negative numbers, fix them! - // (i.e. -2 becomes - 2) - // FIXME the previous operaton also breaks stuff like "1e-5" - for (int i = 0; i < modifiedExpression.length(); i++) { - if (modifiedExpression.charAt(i) == '-' - && (i < 2 || Arrays.asList('+', '-', '*', '/', '^') - .contains(modifiedExpression.charAt(i - 2)))) { - // found a broken negative number - modifiedExpression = modifiedExpression.substring(0, i + 1) - + modifiedExpression.substring(i + 2); - } - } - - return this.unitValueExpressionParser.parseExpression(modifiedExpression); - } - - /** - * Gets a unit dimension from the database using its name. - * - *

    - * This method accepts exponents, like "L^3" - *

    - * - * @param name dimension's name - * @return dimension - * @since 2019-03-14 - * @since v0.2.0 - */ - public ObjectProduct getDimension(final String name) { - Objects.requireNonNull(name, "name must not be null."); - if (name.contains("^")) { - final String[] baseAndExponent = name.split("\\^"); - - final ObjectProduct base = this - .getDimension(baseAndExponent[0]); - - final int exponent; - try { - exponent = Integer - .parseInt(baseAndExponent[baseAndExponent.length - 1]); - } catch (final NumberFormatException e2) { - throw new IllegalArgumentException("Exponent must be an integer."); - } - - return base.toExponent(exponent); - } - return this.dimensions.get(name); - } - - /** - * Uses the database's data to parse an expression into a unit dimension - *

    - * The expression is a series of any of the following: - *

      - *
    • The name of a unit dimension, which multiplies or divides the result - * based on preceding operators
    • - *
    • The operators '*' and '/', which multiply and divide (note that just - * putting two unit dimensions next to each other is equivalent to - * multiplication)
    • - *
    • The operator '^' which exponentiates. Exponents must be integers.
    • - *
    - * - * @param expression expression to parse - * @throws IllegalArgumentException if the expression cannot be parsed - * @throws NullPointerException if expression is null - * @since 2019-04-13 - * @since v0.2.0 - */ - public ObjectProduct getDimensionFromExpression( - final String expression) { - Objects.requireNonNull(expression, "expression must not be null."); - - // attempt to get a dimension as an alias first - if (this.containsDimensionName(expression)) - return this.getDimension(expression); - - // force operators to have spaces - String modifiedExpression = expression; - - // format expression - for (final Entry replacement : EXPRESSION_REPLACEMENTS - .entrySet()) { - modifiedExpression = replacement.getKey().matcher(modifiedExpression) - .replaceAll(replacement.getValue()); - } - modifiedExpression = modifiedExpression.replaceAll(" *\\^ *", "\\^"); - - return this.unitDimensionParser.parseExpression(modifiedExpression); - } - - /** - * Gets a unit. If it is linear, cast it to a LinearUnit and return it. - * Otherwise, throw an {@code IllegalArgumentException}. - * - * @param name unit's name - * @return unit - * @since 2019-03-22 - * @since v0.2.0 - */ - private LinearUnit getLinearUnit(final String name) { - // see if I am using a function-unit like tempC(100) - Objects.requireNonNull(name, "name may not be null"); - if (name.contains("(") && name.contains(")")) { - // break it into function name and value - final List parts = Arrays.asList(name.split("\\(")); - if (parts.size() != 2) - throw new IllegalArgumentException( - "Format nonlinear units like: unit(value)."); - - // solve the function - final Unit unit = this.getUnit(parts.get(0)); - final double value = Double.parseDouble( - parts.get(1).substring(0, parts.get(1).length() - 1)); - return LinearUnit.fromUnitValue(unit, value); - } else { - // get a linear unit - final Unit unit = this.getUnit(name); - - if (unit instanceof LinearUnit) - return (LinearUnit) unit; - else - throw new IllegalArgumentException( - String.format("%s is not a linear unit.", name)); - } - } - - /** - * Gets a {@code LinearUnitValue} from a unit name. Nonlinear units will be - * converted to their base units. - * - * @param name name of unit - * @return {@code LinearUnitValue} instance - * @since 2020-08-04 - */ - private LinearUnitValue getLinearUnitValue(final String name) { - try { - // try to parse it as a number - otherwise it is not a number! - final BigDecimal number = new BigDecimal(name); - - final double uncertainty = Math.pow(10, -number.scale()); - return LinearUnitValue.of(SI.ONE, - UncertainDouble.of(number.doubleValue(), uncertainty)); - } catch (final NumberFormatException e) { - return LinearUnitValue.getExact(this.getLinearUnit(name), 1); - } - } - - /** - * Gets a unit prefix from the database from its name - * - * @param name prefix's name - * @return prefix - * @since 2019-01-10 - * @since v0.1.0 - */ - public UnitPrefix getPrefix(final String name) { - try { - return UnitPrefix.valueOf(Double.parseDouble(name)); - } catch (final NumberFormatException e) { - return this.prefixes.get(name); - } - } - - /** - * Gets all of the prefixes that are on a unit name, in application order. - * - * @param unitName name of unit - * @return prefixes - * @since 2020-08-26 - */ - List getPrefixesFromName(final String unitName) { - final List prefixes = new ArrayList<>(); - String name = unitName; - - while (!this.prefixlessUnits.containsKey(name)) { - // find the longest prefix - String longestPrefixName = null; - int longestLength = name.length(); - - while (longestPrefixName == null) { - longestLength--; - if (longestLength <= 0) - throw new AssertionError( - "No prefix found in " + name + ", but it is not a unit!"); - if (this.prefixes.containsKey(name.substring(0, longestLength))) { - longestPrefixName = name.substring(0, longestLength); - } - } - - // longest prefix found! - final UnitPrefix prefix = this.getPrefix(longestPrefixName); - prefixes.add(0, prefix); - name = name.substring(longestLength); - } - return prefixes; - } - - /** - * Gets a unit prefix from a prefix expression - *

    - * Currently, prefix expressions are much simpler than unit expressions: They - * are either a number or the name of another prefix - *

    - * - * @param expression expression to input - * @return prefix - * @throws IllegalArgumentException if expression cannot be parsed - * @throws NullPointerException if any argument is null - * @since 2019-01-14 - * @since v0.1.0 - */ - public UnitPrefix getPrefixFromExpression(final String expression) { - Objects.requireNonNull(expression, "expression must not be null."); - - // attempt to get a unit as an alias first - if (this.containsUnitName(expression)) - return this.getPrefix(expression); - - // force operators to have spaces - String modifiedExpression = expression; - - // format expression - for (final Entry replacement : EXPRESSION_REPLACEMENTS - .entrySet()) { - modifiedExpression = replacement.getKey().matcher(modifiedExpression) - .replaceAll(replacement.getValue()); - } - - return this.prefixExpressionParser.parseExpression(modifiedExpression); - } - - /** - * @return the prefixRepetitionRule - * @since 2020-08-26 - */ - public final Predicate> getPrefixRepetitionRule() { - return this.prefixRepetitionRule; - } - - /** - * Gets a unit from the database from its name, looking for prefixes. - * - * @param name unit's name - * @return unit - * @since 2019-01-10 - * @since v0.1.0 - */ - public Unit getUnit(final String name) { - try { - final double value = Double.parseDouble(name); - return SI.ONE.times(value); - } catch (final NumberFormatException e) { - final Unit unit = this.units.get(name); - if (unit == null) - throw new NoSuchElementException("No unit " + name); - else if (unit.getPrimaryName().isEmpty()) - return unit.withName(NameSymbol.ofName(name)); - else if (!unit.getPrimaryName().get().equals(name)) { - final Set otherNames = new HashSet<>(unit.getOtherNames()); - otherNames.add(unit.getPrimaryName().get()); - return unit.withName(NameSymbol.ofNullable(name, - unit.getSymbol().orElse(null), otherNames)); - } else if (!unit.getOtherNames().contains(name)) { - final Set otherNames = new HashSet<>(unit.getOtherNames()); - otherNames.add(name); - return unit.withName( - NameSymbol.ofNullable(unit.getPrimaryName().orElse(null), - unit.getSymbol().orElse(null), otherNames)); - } else - return unit; - } - - } - - /** - * Uses the database's unit data to parse an expression into a unit - *

    - * The expression is a series of any of the following: - *

      - *
    • The name of a unit, which multiplies or divides the result based on - * preceding operators
    • - *
    • The operators '*' and '/', which multiply and divide (note that just - * putting two units or values next to each other is equivalent to - * multiplication)
    • - *
    • The operator '^' which exponentiates. Exponents must be integers.
    • - *
    • A number which is multiplied or divided
    • - *
    - * This method only works with linear units. - * - * @param expression expression to parse - * @throws IllegalArgumentException if the expression cannot be parsed - * @throws NullPointerException if expression is null - * @since 2019-01-07 - * @since v0.1.0 - */ - public Unit getUnitFromExpression(final String expression) { - Objects.requireNonNull(expression, "expression must not be null."); - - // attempt to get a unit as an alias first - if (this.containsUnitName(expression)) - return this.getUnit(expression); - - // force operators to have spaces - String modifiedExpression = expression; - modifiedExpression = modifiedExpression.replaceAll("\\+", " \\+ "); - modifiedExpression = modifiedExpression.replaceAll("-", " - "); - - // format expression - for (final Entry replacement : EXPRESSION_REPLACEMENTS - .entrySet()) { - modifiedExpression = replacement.getKey().matcher(modifiedExpression) - .replaceAll(replacement.getValue()); - } - - // the previous operation breaks negative numbers, fix them! - // (i.e. -2 becomes - 2) - for (int i = 0; i < modifiedExpression.length(); i++) { - if (modifiedExpression.charAt(i) == '-' - && (i < 2 || Arrays.asList('+', '-', '*', '/', '^') - .contains(modifiedExpression.charAt(i - 2)))) { - // found a broken negative number - modifiedExpression = modifiedExpression.substring(0, i + 1) - + modifiedExpression.substring(i + 2); - } - } - - return this.unitExpressionParser.parseExpression(modifiedExpression); - } - - /** - * Adds all dimensions from a file, using data from the database to parse - * them. - *

    - * Each line in the file should consist of a name and an expression (parsed - * by getDimensionFromExpression) separated by any number of tab characters. - *

    - *

    - * Allowed exceptions: - *

      - *
    • Anything after a '#' character is considered a comment and - * ignored.
    • - *
    • Blank lines are also ignored
    • - *
    • If an expression consists of a single exclamation point, instead of - * parsing it, this method will search the database for an existing unit. If - * no unit is found, an IllegalArgumentException is thrown. This is used to - * define initial units and ensure that the database contains them.
    • - *
    - * - * @param file file to read - * @throws IllegalArgumentException if the file cannot be parsed, found or - * read - * @throws NullPointerException if file is null - * @since 2019-01-13 - * @since v0.1.0 - */ - public void loadDimensionFile(final Path file) { - Objects.requireNonNull(file, "file must not be null."); - try { - long lineCounter = 0; - for (final String line : Files.readAllLines(file)) { - this.addDimensionFromLine(line, ++lineCounter); - } - } catch (final FileNotFoundException e) { - throw new IllegalArgumentException("Could not find file " + file, e); - } catch (final IOException e) { - throw new IllegalArgumentException("Could not read file " + file, e); - } - } - - /** - * Adds all units from a file, using data from the database to parse them. - *

    - * Each line in the file should consist of a name and an expression (parsed - * by getUnitFromExpression) separated by any number of tab characters. - *

    - *

    - * Allowed exceptions: - *

      - *
    • Anything after a '#' character is considered a comment and - * ignored.
    • - *
    • Blank lines are also ignored
    • - *
    • If an expression consists of a single exclamation point, instead of - * parsing it, this method will search the database for an existing unit. If - * no unit is found, an IllegalArgumentException is thrown. This is used to - * define initial units and ensure that the database contains them.
    • - *
    - * - * @param file file to read - * @throws IllegalArgumentException if the file cannot be parsed, found or - * read - * @throws NullPointerException if file is null - * @since 2019-01-13 - * @since v0.1.0 - */ - public void loadUnitsFile(final Path file) { - Objects.requireNonNull(file, "file must not be null."); - try { - long lineCounter = 0; - for (final String line : Files.readAllLines(file)) { - this.addUnitOrPrefixFromLine(line, ++lineCounter); - } - } catch (final FileNotFoundException e) { - throw new IllegalArgumentException("Could not find file " + file, e); - } catch (final IOException e) { - throw new IllegalArgumentException("Could not read file " + file, e); - } - } - - /** - * @return a map mapping prefix names to prefixes - * @since 2019-04-13 - * @since v0.2.0 - */ - public Map prefixMap() { - return Collections.unmodifiableMap(this.prefixes); - } - - /** - * @param prefixRepetitionRule the prefixRepetitionRule to set - * @since 2020-08-26 - */ - public final void setPrefixRepetitionRule( - Predicate> prefixRepetitionRule) { - this.prefixRepetitionRule = prefixRepetitionRule; - } - - /** - * @return a string stating the number of units, prefixes and dimensions in - * the database - */ - @Override - public String toString() { - return String.format( - "Unit Database with %d units, %d unit prefixes and %d dimensions", - this.prefixlessUnits.size(), this.prefixes.size(), - this.dimensions.size()); - } - - /** - * Returns a map mapping unit names to units, including units with prefixes. - *

    - * The returned map is infinite in size if there is at least one unit and at - * least one prefix. If it is infinite, some operations that only work with - * finite collections, like converting name/entry sets to arrays, will throw - * an {@code IllegalStateException}. - *

    - *

    - * Specifically, the operations that will throw an IllegalStateException if - * the map is infinite in size are: - *

      - *
    • {@code unitMap.entrySet().toArray()} (either overloading)
    • - *
    • {@code unitMap.keySet().toArray()} (either overloading)
    • - *
    - *

    - *

    - * Because of ambiguities between prefixes (i.e. kilokilo = mega), the map's - * {@link PrefixedUnitMap#containsValue containsValue} and - * {@link PrefixedUnitMap#values() values()} methods currently ignore - * prefixes. - *

    - * - * @return a map mapping unit names to units, including prefixed names - * @since 2019-04-13 - * @since v0.2.0 - */ - public Map unitMap() { - return this.units; // PrefixedUnitMap is immutable so I don't need to make - // an unmodifiable map. - } - - /** - * @return a map mapping unit names to units, ignoring prefixes - * @since 2019-04-13 - * @since v0.2.0 - */ - public Map unitMapPrefixless() { - return Collections.unmodifiableMap(this.prefixlessUnits); - } -} diff --git a/src/org/unitConverter/unit/UnitDatabaseTest.java b/src/org/unitConverter/unit/UnitDatabaseTest.java deleted file mode 100644 index 2b981b6..0000000 --- a/src/org/unitConverter/unit/UnitDatabaseTest.java +++ /dev/null @@ -1,309 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Set; - -import org.junit.jupiter.api.Test; - -/** - * A test for the {@link UnitDatabase} class. This is NOT part of this program's - * public API. - * - * @author Adrien Hopkins - * @since 2019-04-14 - * @since v0.2.0 - */ -class UnitDatabaseTest { - // some linear units and one nonlinear - private static final Unit U = SI.METRE; - private static final Unit V = SI.KILOGRAM; - private static final Unit W = SI.SECOND; - - // used for testing expressions - // J = U^2 * V / W^2 - private static final LinearUnit J = SI.KILOGRAM.times(SI.METRE.toExponent(2)) - .dividedBy(SI.SECOND.toExponent(2)); - private static final LinearUnit K = SI.KELVIN; - - private static final Unit NONLINEAR = Unit - .fromConversionFunctions(SI.METRE.getBase(), o -> o + 1, o -> o - 1); - - // make the prefix values prime so I can tell which multiplications were made - private static final UnitPrefix A = UnitPrefix.valueOf(2) - .withName(NameSymbol.ofName("A")); - private static final UnitPrefix B = UnitPrefix.valueOf(3) - .withName(NameSymbol.ofName("B")); - private static final UnitPrefix C = UnitPrefix.valueOf(5) - .withName(NameSymbol.ofName("C")); - private static final UnitPrefix AB = UnitPrefix.valueOf(7); - private static final UnitPrefix BC = UnitPrefix.valueOf(11); - - /** - * Confirms that operations that shouldn't function for infinite databases - * throw an {@code IllegalStateException}. - * - * @since 2019-05-03 - */ - @Test - // @Timeout(value = 5, unit = TimeUnit.SECONDS) - public void testInfiniteSetExceptions() { - // load units - final UnitDatabase infiniteDatabase = new UnitDatabase(); - - infiniteDatabase.addUnit("J", J); - infiniteDatabase.addUnit("K", K); - - infiniteDatabase.addPrefix("A", A); - infiniteDatabase.addPrefix("B", B); - infiniteDatabase.addPrefix("C", C); - - final Set> entrySet = infiniteDatabase.unitMap() - .entrySet(); - final Set keySet = infiniteDatabase.unitMap().keySet(); - assertThrows(IllegalStateException.class, () -> entrySet.toArray()); - assertThrows(IllegalStateException.class, () -> keySet.toArray()); - } - - /** - * Test that prefixes correctly apply to units. - * - * @since 2019-04-14 - * @since v0.2.0 - */ - @Test - public void testPrefixes() { - final UnitDatabase database = new UnitDatabase(); - - database.addUnit("U", U); - database.addUnit("V", V); - database.addUnit("W", W); - - database.addPrefix("A", A); - database.addPrefix("B", B); - database.addPrefix("C", C); - - // test the getPrefixesFromName method - final List expected = Arrays.asList(C, B, A); - assertEquals(expected, database.getPrefixesFromName("ABCU")); - - // get the product - final Unit abcuNonlinear = database.getUnit("ABCU"); - assert abcuNonlinear instanceof LinearUnit; - - final LinearUnit abcu = (LinearUnit) abcuNonlinear; - assertEquals(A.getMultiplier() * B.getMultiplier() * C.getMultiplier(), - abcu.getConversionFactor(), 1e-15); - } - - /** - * Tests the functionnalites of the prefixless unit map. - * - *

    - * The map should be an auto-updating view of the units in the database. - *

    - * - * @since 2019-04-14 - * @since v0.2.0 - */ - @Test - public void testPrefixlessUnitMap() { - final UnitDatabase database = new UnitDatabase(); - final Map prefixlessUnits = database.unitMapPrefixless(); - - database.addUnit("U", U); - database.addUnit("V", V); - database.addUnit("W", W); - - // this should work because the map should be an auto-updating view - assertTrue(prefixlessUnits.containsKey("U")); - assertFalse(prefixlessUnits.containsKey("Z")); - - assertTrue(prefixlessUnits.containsValue(U)); - assertFalse(prefixlessUnits.containsValue(NONLINEAR)); - } - - /** - * Tests that the database correctly stores and retrieves units, ignoring - * prefixes. - * - * @since 2019-04-14 - * @since v0.2.0 - */ - @Test - public void testPrefixlessUnits() { - final UnitDatabase database = new UnitDatabase(); - - database.addUnit("U", U); - database.addUnit("V", V); - database.addUnit("W", W); - - assertTrue(database.containsUnitName("U")); - assertFalse(database.containsUnitName("Z")); - - assertEquals(U, database.getUnit("U")); - assertThrows(NoSuchElementException.class, () -> database.getUnit("Z")); - } - - /** - * Test that unit expressions return the correct value. - * - * @since 2019-04-14 - * @since v0.2.0 - */ - @Test - public void testUnitExpressions() { - // load units - final UnitDatabase database = new UnitDatabase(); - - database.addUnit("U", U); - database.addUnit("V", V); - database.addUnit("W", W); - database.addUnit("fj", J.times(5)); - database.addUnit("ej", J.times(8)); - - database.addPrefix("A", A); - database.addPrefix("B", B); - database.addPrefix("C", C); - - // first test - test prefixes and operations - final Unit expected1 = J.withPrefix(A).withPrefix(B).withPrefix(C) - .withPrefix(C); - final Unit actual1 = database.getUnitFromExpression("ABV * CU^2 / W / W"); - - assertEquals(expected1, actual1); - - // second test - test addition and subtraction - final Unit expected2 = J.times(58); - final Unit actual2 = database.getUnitFromExpression("2 fj + 6 ej"); - - assertEquals(expected2, actual2); - } - - /** - * Tests both the unit name iterator and the name-unit entry iterator - * - * @since 2019-04-14 - * @since v0.2.0 - */ - @Test - public void testUnitIterator() { - // load units - final UnitDatabase database = new UnitDatabase(); - - database.addUnit("J", J); - database.addUnit("K", K); - - database.addPrefix("A", A); - database.addPrefix("B", B); - database.addPrefix("C", C); - - final int NUM_UNITS = database.unitMapPrefixless().size(); - final int NUM_PREFIXES = database.prefixMap().size(); - - final Iterator nameIterator = database.unitMap().keySet() - .iterator(); - final Iterator> entryIterator = database.unitMap() - .entrySet().iterator(); - - int expectedLength = 1; - int unitsWithThisLengthSoFar = 0; - - // loop 1000 times - for (int i = 0; i < 1000; i++) { - // expected length of next - if (unitsWithThisLengthSoFar >= NUM_UNITS - * (int) Math.pow(NUM_PREFIXES, expectedLength - 1)) { - expectedLength++; - unitsWithThisLengthSoFar = 0; - } - - // test that stuff is valid - final String nextName = nameIterator.next(); - final Unit nextUnit = database.getUnit(nextName); - final Entry nextEntry = entryIterator.next(); - - assertEquals(expectedLength, nextName.length()); - assertEquals(nextName, nextEntry.getKey()); - assertEquals(nextUnit, nextEntry.getValue()); - - unitsWithThisLengthSoFar++; - } - - // test toString for consistency - final String entryIteratorString = entryIterator.toString(); - for (int i = 0; i < 3; i++) { - assertEquals(entryIteratorString, entryIterator.toString()); - } - - final String nameIteratorString = nameIterator.toString(); - for (int i = 0; i < 3; i++) { - assertEquals(nameIteratorString, nameIterator.toString()); - } - } - - /** - * Determine, given a unit name that could mean multiple things, which - * meaning is chosen. - *

    - * For example, "ABCU" could mean "A-B-C-U", "AB-C-U", or "A-BC-U". In this - * case, "AB-C-U" is the correct choice. - *

    - * - * @since 2019-04-14 - * @since v0.2.0 - */ - @Test - public void testUnitPrefixCombinations() { - // load units - final UnitDatabase database = new UnitDatabase(); - - database.addUnit("J", J); - - database.addPrefix("A", A); - database.addPrefix("B", B); - database.addPrefix("C", C); - database.addPrefix("AB", AB); - database.addPrefix("BC", BC); - - // test 1 - AB-C-J vs A-BC-J vs A-B-C-J - final Unit expected1 = J.withPrefix(AB).withPrefix(C); - final Unit actual1 = database.getUnit("ABCJ"); - - assertEquals(expected1, actual1); - - // test 2 - ABC-J vs AB-CJ vs AB-C-J - database.addUnit("CJ", J.times(13)); - database.addPrefix("ABC", UnitPrefix.valueOf(17)); - - final Unit expected2 = J.times(17); - final Unit actual2 = database.getUnit("ABCJ"); - - assertEquals(expected2, actual2); - } -} diff --git a/src/org/unitConverter/unit/UnitPrefix.java b/src/org/unitConverter/unit/UnitPrefix.java deleted file mode 100644 index 31cc0b3..0000000 --- a/src/org/unitConverter/unit/UnitPrefix.java +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.Objects; -import java.util.Optional; -import java.util.Set; - -import org.unitConverter.math.DecimalComparison; - -/** - * A prefix that can be applied to a {@code LinearUnit} to multiply it by some value - * - * @author Adrien Hopkins - * @since 2019-10-16 - */ -public final class UnitPrefix { - /** - * Gets a {@code UnitPrefix} from a multiplier - * - * @param multiplier - * multiplier of prefix - * @return prefix - * @since 2019-10-16 - */ - public static UnitPrefix valueOf(final double multiplier) { - return new UnitPrefix(multiplier, NameSymbol.EMPTY); - } - - /** - * Gets a {@code UnitPrefix} from a multiplier and a name - * - * @param multiplier - * multiplier of prefix - * @param ns - * name(s) and symbol of prefix - * @return prefix - * @since 2019-10-16 - * @throws NullPointerException - * if ns is null - */ - public static UnitPrefix valueOf(final double multiplier, final NameSymbol ns) { - return new UnitPrefix(multiplier, Objects.requireNonNull(ns, "ns must not be null.")); - } - - /** - * This prefix's primary name - */ - private final Optional primaryName; - - /** - * This prefix's symbol - */ - private final Optional symbol; - - /** - * Other names and symbols used by this prefix - */ - private final Set otherNames; - - /** - * The number that this prefix multiplies units by - * - * @since 2019-10-16 - */ - private final double multiplier; - - /** - * Creates the {@code DefaultUnitPrefix}. - * - * @param multiplier - * @since 2019-01-14 - * @since v0.2.0 - */ - private UnitPrefix(final double multiplier, final NameSymbol ns) { - this.multiplier = multiplier; - this.primaryName = ns.getPrimaryName(); - this.symbol = ns.getSymbol(); - this.otherNames = ns.getOtherNames(); - } - - /** - * Divides this prefix by a scalar - * - * @param divisor - * number to divide by - * @return quotient of prefix and scalar - * @since 2019-10-16 - */ - public UnitPrefix dividedBy(final double divisor) { - return valueOf(this.getMultiplier() / divisor); - } - - /** - * Divides this prefix by {@code other}. - * - * @param other - * prefix to divide by - * @return quotient of prefixes - * @since 2019-04-13 - * @since v0.2.0 - */ - public UnitPrefix dividedBy(final UnitPrefix other) { - return valueOf(this.getMultiplier() / other.getMultiplier()); - } - - /** - * {@inheritDoc} - * - * Uses the prefix's multiplier to determine equality. - */ - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof UnitPrefix)) - return false; - final UnitPrefix other = (UnitPrefix) obj; - return DecimalComparison.equals(this.getMultiplier(), other.getMultiplier()); - } - - /** - * @return prefix's multiplier - * @since 2019-11-26 - */ - public double getMultiplier() { - return this.multiplier; - } - - /** - * @return other names - * @since 2019-11-26 - */ - public final Set getOtherNames() { - return this.otherNames; - } - - /** - * @return primary name - * @since 2019-11-26 - */ - public final Optional getPrimaryName() { - return this.primaryName; - } - - /** - * @return symbol - * @since 2019-11-26 - */ - public final Optional getSymbol() { - return this.symbol; - } - - /** - * {@inheritDoc} - * - * Uses the prefix's multiplier to determine a hash code. - */ - @Override - public int hashCode() { - return DecimalComparison.hash(this.getMultiplier()); - } - - /** - * Multiplies this prefix by a scalar - * - * @param multiplicand - * number to multiply by - * @return product of prefix and scalar - * @since 2019-10-16 - */ - public UnitPrefix times(final double multiplicand) { - return valueOf(this.getMultiplier() * multiplicand); - } - - /** - * Multiplies this prefix by {@code other}. - * - * @param other - * prefix to multiply by - * @return product of prefixes - * @since 2019-04-13 - * @since v0.2.0 - */ - public UnitPrefix times(final UnitPrefix other) { - return valueOf(this.getMultiplier() * other.getMultiplier()); - } - - /** - * Raises this prefix to an exponent. - * - * @param exponent - * exponent to raise to - * @return result of exponentiation. - * @since 2019-04-13 - * @since v0.2.0 - */ - public UnitPrefix toExponent(final double exponent) { - return valueOf(Math.pow(this.getMultiplier(), exponent)); - } - - /** - * @return a string describing the prefix and its multiplier - */ - @Override - public String toString() { - if (this.primaryName.isPresent()) - return String.format("%s (\u00D7 %s)", this.primaryName.get(), this.multiplier); - else if (this.symbol.isPresent()) - return String.format("%s (\u00D7 %s)", this.symbol.get(), this.multiplier); - else - return String.format("Unit Prefix (\u00D7 %s)", this.multiplier); - } - - /** - * @param ns - * name(s) and symbol to use - * @return copy of this prefix with provided name(s) and symbol - * @since 2019-11-26 - * @throws NullPointerException - * if ns is null - */ - public UnitPrefix withName(final NameSymbol ns) { - return valueOf(this.multiplier, ns); - } -} diff --git a/src/org/unitConverter/unit/UnitTest.java b/src/org/unitConverter/unit/UnitTest.java deleted file mode 100644 index c0711dc..0000000 --- a/src/org/unitConverter/unit/UnitTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Copyright (C) 2018 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import static org.junit.Assert.assertFalse; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; - -import org.junit.jupiter.api.Test; -import org.unitConverter.math.DecimalComparison; - -/** - * Testing the various Unit classes. This is NOT part of this program's public - * API. - * - * @author Adrien Hopkins - * @since 2018-12-22 - * @since v0.1.0 - */ -class UnitTest { - /** A random number generator */ - private static final Random rng = ThreadLocalRandom.current(); - - @Test - public void testAdditionAndSubtraction() { - final LinearUnit inch = SI.METRE.times(0.0254) - .withName(NameSymbol.of("inch", "in")); - final LinearUnit foot = SI.METRE.times(0.3048) - .withName(NameSymbol.of("foot", "ft")); - - assertEquals(inch.plus(foot), SI.METRE.times(0.3302)); - assertEquals(foot.minus(inch), SI.METRE.times(0.2794)); - - // test with LinearUnitValue - final LinearUnitValue value1 = LinearUnitValue.getExact(SI.METRE, 15); - final LinearUnitValue value2 = LinearUnitValue.getExact(foot, 120); - final LinearUnitValue value3 = LinearUnitValue.getExact(SI.METRE, 0.5); - final LinearUnitValue value4 = LinearUnitValue.getExact(SI.KILOGRAM, 60); - - // make sure addition is done correctly - assertEquals(51.576, value1.plus(value2).getValueExact(), 0.001); - assertEquals(15.5, value1.plus(value3).getValueExact()); - assertEquals(52.076, value1.plus(value2).plus(value3).getValueExact(), - 0.001); - - // make sure addition uses the correct unit, and is still associative - // (ignoring floating-point rounding errors) - assertEquals(SI.METRE, value1.plus(value2).getUnit()); - assertEquals(SI.METRE, value1.plus(value2).plus(value3).getUnit()); - assertEquals(foot, value2.plus(value1).getUnit()); - assertTrue(value1.plus(value2).equals(value2.plus(value1), true)); - - // make sure errors happen when they should - assertThrows(IllegalArgumentException.class, () -> value1.plus(value4)); - } - - @Test - public void testConversion() { - final LinearUnit metre = SI.METRE; - final Unit inch = metre.times(0.0254); - - final UnitValue value = UnitValue.of(inch, 75); - - assertEquals(1.9, inch.convertTo(metre, 75), 0.01); - assertEquals(1.9, value.convertTo(metre).getValue(), 0.01); - - // try random stuff - for (int i = 0; i < 1000; i++) { - // initiate random values - final double conversionFactor = UnitTest.rng.nextDouble() * 1000000; - final double testValue = UnitTest.rng.nextDouble() * 1000000; - final double expected = testValue * conversionFactor; - - // test - final Unit unit = SI.METRE.times(conversionFactor); - final double actual = unit.convertToBase(testValue); - - assertEquals(actual, expected, - expected * DecimalComparison.DOUBLE_EPSILON); - } - } - - @Test - public void testEquals() { - final LinearUnit metre = SI.METRE; - final Unit meter = SI.BaseUnits.METRE.asLinearUnit(); - - assertEquals(metre, meter); - } - - @Test - public void testIsMetric() { - final Unit metre = SI.METRE; - final Unit megasecond = SI.SECOND.withPrefix(SI.MEGA); - final Unit hour = SI.HOUR; - - assertTrue(metre.isMetric()); - assertTrue(megasecond.isMetric()); - assertFalse(hour.isMetric()); - } - - @Test - public void testMultiplicationAndDivision() { - // test unit-times-unit multiplication - final LinearUnit generatedJoule = SI.KILOGRAM - .times(SI.METRE.toExponent(2)).dividedBy(SI.SECOND.toExponent(2)); - final LinearUnit actualJoule = SI.JOULE; - - assertEquals(generatedJoule, actualJoule); - - // test multiplication by conversion factors - final LinearUnit kilometre = SI.METRE.times(1000); - final LinearUnit hour = SI.SECOND.times(3600); - final LinearUnit generatedKPH = kilometre.dividedBy(hour); - - final LinearUnit actualKPH = SI.METRE.dividedBy(SI.SECOND).dividedBy(3.6); - - assertEquals(generatedKPH, actualKPH); - } - - @Test - public void testPrefixes() { - final LinearUnit generatedKilometre = SI.METRE.withPrefix(SI.KILO); - final LinearUnit actualKilometre = SI.METRE.times(1000); - - assertEquals(generatedKilometre, actualKilometre); - } -} diff --git a/src/org/unitConverter/unit/UnitValue.java b/src/org/unitConverter/unit/UnitValue.java deleted file mode 100644 index c138332..0000000 --- a/src/org/unitConverter/unit/UnitValue.java +++ /dev/null @@ -1,172 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.Objects; -import java.util.Optional; - -/** - * A value expressed in a unit. - * - * Unless otherwise indicated, all methods in this class throw a - * {@code NullPointerException} when an argument is null. - * - * @author Adrien Hopkins - * @since 2020-07-26 - */ -public final class UnitValue { - /** - * Creates a {@code UnitValue} from a unit and the associated value. - * - * @param unit unit to use - * @param value value to use - * @return {@code UnitValue} instance - */ - public static UnitValue of(Unit unit, double value) { - return new UnitValue( - Objects.requireNonNull(unit, "unit must not be null"), value); - } - - private final Unit unit; - private final double value; - - /** - * @param unit the unit being used - * @param value the value being represented - */ - private UnitValue(Unit unit, Double value) { - this.unit = unit; - this.value = value; - } - - /** - * @return true if this value can be converted to {@code other}. - * @since 2020-10-01 - */ - public final boolean canConvertTo(Unit other) { - return this.unit.canConvertTo(other); - } - - /** - * @return true if this value can be converted to {@code other}. - * @since 2020-10-01 - */ - public final boolean canConvertTo(Unitlike other) { - return this.unit.canConvertTo(other); - } - - /** - * Returns a UnitlikeValue that represents the same value expressed in a - * different unitlike form. - * - * @param other new unit to express value in - * @return value expressed in {@code other} - */ - public final , W> UnitlikeValue convertTo( - U other) { - return UnitlikeValue.of(other, - this.unit.convertTo(other, this.getValue())); - } - - /** - * Returns a UnitValue that represents the same value expressed in a - * different unit - * - * @param other new unit to express value in - * @return value expressed in {@code other} - */ - public final UnitValue convertTo(Unit other) { - return UnitValue.of(other, - this.getUnit().convertTo(other, this.getValue())); - } - - /** - * Returns this unit value represented as a {@code LinearUnitValue} with this - * unit's base unit as the base. - * - * @param ns name and symbol for the base unit, use NameSymbol.EMPTY if not - * needed. - * @since 2020-09-29 - */ - public final LinearUnitValue convertToBase(NameSymbol ns) { - final LinearUnit base = LinearUnit.getBase(this.unit).withName(ns); - return this.convertToLinear(base); - } - - /** - * @return a {@code LinearUnitValue} that is equivalent to this value. It - * will have zero uncertainty. - * @since 2020-09-29 - */ - public final LinearUnitValue convertToLinear(LinearUnit other) { - return LinearUnitValue.getExact(other, - this.getUnit().convertTo(other, this.getValue())); - } - - /** - * Returns true if this and obj represent the same value, regardless of - * whether or not they are expressed in the same unit. So (1000 m).equals(1 - * km) returns true. - */ - @Override - public boolean equals(Object obj) { - if (!(obj instanceof UnitValue)) - return false; - final UnitValue other = (UnitValue) obj; - return Objects.equals(this.getUnit().getBase(), other.getUnit().getBase()) - && Double.doubleToLongBits( - this.getUnit().convertToBase(this.getValue())) == Double - .doubleToLongBits( - other.getUnit().convertToBase(other.getValue())); - } - - /** - * @return the unit - * @since 2020-09-29 - */ - public final Unit getUnit() { - return this.unit; - } - - /** - * @return the value - * @since 2020-09-29 - */ - public final double getValue() { - return this.value; - } - - @Override - public int hashCode() { - return Objects.hash(this.getUnit().getBase(), - this.getUnit().convertFromBase(this.getValue())); - } - - @Override - public String toString() { - final Optional primaryName = this.getUnit().getPrimaryName(); - final Optional symbol = this.getUnit().getSymbol(); - if (primaryName.isEmpty() && symbol.isEmpty()) { - final double baseValue = this.getUnit().convertToBase(this.getValue()); - return String.format("%s unnamed unit (= %s %s)", this.getValue(), - baseValue, this.getUnit().getBase()); - } else { - final String unitName = symbol.orElse(primaryName.get()); - return this.getValue() + " " + unitName; - } - } -} diff --git a/src/org/unitConverter/unit/Unitlike.java b/src/org/unitConverter/unit/Unitlike.java deleted file mode 100644 index 8077771..0000000 --- a/src/org/unitConverter/unit/Unitlike.java +++ /dev/null @@ -1,260 +0,0 @@ -/** - * Copyright (C) 2020 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.function.DoubleFunction; -import java.util.function.ToDoubleFunction; - -import org.unitConverter.math.ObjectProduct; - -/** - * An object that can convert a value between multiple forms (instances of the - * object); like a unit but the "converted value" can be any type. - * - * @since 2020-09-07 - */ -public abstract class Unitlike implements Nameable { - /** - * Returns a unitlike form from its base and the functions it uses to convert - * to and from its base. - * - * @param base unitlike form's base - * @param converterFrom function that accepts a value expressed in the - * unitlike form's base and returns that value expressed - * in this unitlike form. - * @param converterTo function that accepts a value expressed in the - * unitlike form and returns that value expressed in the - * unit's base. - * @return a unitlike form that uses the provided functions to convert. - * @since 2020-09-07 - * @throws NullPointerException if any argument is null - */ - public static final Unitlike fromConversionFunctions( - final ObjectProduct base, - final DoubleFunction converterFrom, - final ToDoubleFunction converterTo) { - return new FunctionalUnitlike<>(base, NameSymbol.EMPTY, converterFrom, - converterTo); - } - - /** - * Returns a unitlike form from its base and the functions it uses to convert - * to and from its base. - * - * @param base unitlike form's base - * @param converterFrom function that accepts a value expressed in the - * unitlike form's base and returns that value expressed - * in this unitlike form. - * @param converterTo function that accepts a value expressed in the - * unitlike form and returns that value expressed in the - * unit's base. - * @param ns names and symbol of unit - * @return a unitlike form that uses the provided functions to convert. - * @since 2020-09-07 - * @throws NullPointerException if any argument is null - */ - public static final Unitlike fromConversionFunctions( - final ObjectProduct base, - final DoubleFunction converterFrom, - final ToDoubleFunction converterTo, final NameSymbol ns) { - return new FunctionalUnitlike<>(base, ns, converterFrom, converterTo); - } - - /** - * The combination of units that this unit is based on. - * - * @since 2019-10-16 - */ - private final ObjectProduct unitBase; - - /** - * This unit's name(s) and symbol - * - * @since 2020-09-07 - */ - private final NameSymbol nameSymbol; - - /** - * Cache storing the result of getDimension() - * - * @since 2019-10-16 - */ - private transient ObjectProduct dimension = null; - - /** - * @param unitBase - * @since 2020-09-07 - */ - protected Unitlike(ObjectProduct unitBase, NameSymbol ns) { - this.unitBase = Objects.requireNonNull(unitBase, - "unitBase may not be null"); - this.nameSymbol = Objects.requireNonNull(ns, "ns may not be null"); - } - - /** - * Checks if a value expressed in this unitlike form can be converted to a - * value expressed in {@code other} - * - * @param other unit or unitlike form to test with - * @return true if they are compatible - * @since 2019-01-13 - * @since v0.1.0 - * @throws NullPointerException if other is null - */ - public final boolean canConvertTo(final Unit other) { - Objects.requireNonNull(other, "other must not be null."); - return Objects.equals(this.getBase(), other.getBase()); - } - - /** - * Checks if a value expressed in this unitlike form can be converted to a - * value expressed in {@code other} - * - * @param other unit or unitlike form to test with - * @return true if they are compatible - * @since 2019-01-13 - * @since v0.1.0 - * @throws NullPointerException if other is null - */ - public final boolean canConvertTo(final Unitlike other) { - Objects.requireNonNull(other, "other must not be null."); - return Objects.equals(this.getBase(), other.getBase()); - } - - protected abstract V convertFromBase(double value); - - /** - * Converts a value expressed in this unitlike form to a value expressed in - * {@code other}. - * - * @implSpec If conversion is possible, this implementation returns - * {@code other.convertFromBase(this.convertToBase(value))}. - * Therefore, overriding either of those methods will change the - * output of this method. - * - * @param other unit to convert to - * @param value value to convert - * @return converted value - * @since 2019-05-22 - * @throws IllegalArgumentException if {@code other} is incompatible for - * conversion with this unitlike form (as - * tested by {@link Unit#canConvertTo}). - * @throws NullPointerException if other is null - */ - public final double convertTo(final Unit other, final V value) { - Objects.requireNonNull(other, "other must not be null."); - if (this.canConvertTo(other)) - return other.convertFromBase(this.convertToBase(value)); - else - throw new IllegalArgumentException( - String.format("Cannot convert from %s to %s.", this, other)); - } - - /** - * Converts a value expressed in this unitlike form to a value expressed in - * {@code other}. - * - * @implSpec If conversion is possible, this implementation returns - * {@code other.convertFromBase(this.convertToBase(value))}. - * Therefore, overriding either of those methods will change the - * output of this method. - * - * @param other unitlike form to convert to - * @param value value to convert - * @param type of value to convert to - * @return converted value - * @since 2020-09-07 - * @throws IllegalArgumentException if {@code other} is incompatible for - * conversion with this unitlike form (as - * tested by {@link Unit#canConvertTo}). - * @throws NullPointerException if other is null - */ - public final W convertTo(final Unitlike other, final V value) { - Objects.requireNonNull(other, "other must not be null."); - if (this.canConvertTo(other)) - return other.convertFromBase(this.convertToBase(value)); - else - throw new IllegalArgumentException( - String.format("Cannot convert from %s to %s.", this, other)); - } - - protected abstract double convertToBase(V value); - - /** - * @return combination of units that this unit is based on - * @since 2018-12-22 - * @since v0.1.0 - */ - public final ObjectProduct getBase() { - return this.unitBase; - } - - /** - * @return dimension measured by this unit - * @since 2018-12-22 - * @since v0.1.0 - */ - public final ObjectProduct getDimension() { - if (this.dimension == null) { - final Map mapping = this.unitBase.exponentMap(); - final Map dimensionMap = new HashMap<>(); - - for (final BaseUnit key : mapping.keySet()) { - dimensionMap.put(key.getBaseDimension(), mapping.get(key)); - } - - this.dimension = ObjectProduct.fromExponentMapping(dimensionMap); - } - return this.dimension; - } - - /** - * @return the nameSymbol - * @since 2020-09-07 - */ - @Override - public final NameSymbol getNameSymbol() { - return this.nameSymbol; - } - - @Override - public String toString() { - return this.getPrimaryName().orElse("Unnamed unitlike form") - + (this.getSymbol().isPresent() - ? String.format(" (%s)", this.getSymbol().get()) - : "") - + ", derived from " - + this.getBase().toString(u -> u.getSymbol().get()) - + (this.getOtherNames().isEmpty() ? "" - : ", also called " + String.join(", ", this.getOtherNames())); - } - - /** - * @param ns name(s) and symbol to use - * @return a copy of this unitlike form with provided name(s) and symbol - * @since 2020-09-07 - * @throws NullPointerException if ns is null - */ - public Unitlike withName(final NameSymbol ns) { - return fromConversionFunctions(this.getBase(), this::convertFromBase, - this::convertToBase, - Objects.requireNonNull(ns, "ns must not be null.")); - } -} diff --git a/src/org/unitConverter/unit/UnitlikeValue.java b/src/org/unitConverter/unit/UnitlikeValue.java deleted file mode 100644 index 79201c4..0000000 --- a/src/org/unitConverter/unit/UnitlikeValue.java +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Copyright (C) 2020 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.unitConverter.unit; - -import java.util.Optional; - -/** - * - * @since 2020-09-07 - */ -final class UnitlikeValue, V> { - /** - * Gets a {@code UnitlikeValue}. - * - * @since 2020-10-02 - */ - public static , V> UnitlikeValue of(T unitlike, - V value) { - return new UnitlikeValue<>(unitlike, value); - } - - private final T unitlike; - private final V value; - - /** - * @param unitlike - * @param value - * @since 2020-09-07 - */ - private UnitlikeValue(T unitlike, V value) { - this.unitlike = unitlike; - this.value = value; - } - - /** - * @return true if this value can be converted to {@code other}. - * @since 2020-10-01 - */ - public final boolean canConvertTo(Unit other) { - return this.unitlike.canConvertTo(other); - } - - /** - * @return true if this value can be converted to {@code other}. - * @since 2020-10-01 - */ - public final boolean canConvertTo(Unitlike other) { - return this.unitlike.canConvertTo(other); - } - - /** - * Returns a UnitlikeValue that represents the same value expressed in a - * different unitlike form. - * - * @param other new unit to express value in - * @return value expressed in {@code other} - */ - public final , W> UnitlikeValue convertTo( - U other) { - return UnitlikeValue.of(other, - this.unitlike.convertTo(other, this.getValue())); - } - - /** - * Returns a UnitValue that represents the same value expressed in a - * different unit - * - * @param other new unit to express value in - * @return value expressed in {@code other} - */ - public final UnitValue convertTo(Unit other) { - return UnitValue.of(other, - this.unitlike.convertTo(other, this.getValue())); - } - - /** - * Returns this unit value represented as a {@code LinearUnitValue} with this - * unit's base unit as the base. - * - * @param ns name and symbol for the base unit, use NameSymbol.EMPTY if not - * needed. - * @since 2020-09-29 - */ - public final LinearUnitValue convertToBase(NameSymbol ns) { - final LinearUnit base = LinearUnit.getBase(this.unitlike).withName(ns); - return this.convertToLinear(base); - } - - /** - * @return a {@code LinearUnitValue} that is equivalent to this value. It - * will have zero uncertainty. - * @since 2020-09-29 - */ - public final LinearUnitValue convertToLinear(LinearUnit other) { - return LinearUnitValue.getExact(other, - this.getUnitlike().convertTo(other, this.getValue())); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!(obj instanceof UnitlikeValue)) - return false; - final UnitlikeValue other = (UnitlikeValue) obj; - if (this.getUnitlike() == null) { - if (other.getUnitlike() != null) - return false; - } else if (!this.getUnitlike().equals(other.getUnitlike())) - return false; - if (this.getValue() == null) { - if (other.getValue() != null) - return false; - } else if (!this.getValue().equals(other.getValue())) - return false; - return true; - } - - /** - * @return the unitlike - * @since 2020-09-29 - */ - public final Unitlike getUnitlike() { - return this.unitlike; - } - - /** - * @return the value - * @since 2020-09-29 - */ - public final V getValue() { - return this.value; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result - + (this.getUnitlike() == null ? 0 : this.getUnitlike().hashCode()); - result = prime * result - + (this.getValue() == null ? 0 : this.getValue().hashCode()); - return result; - } - - @Override - public String toString() { - final Optional primaryName = this.getUnitlike().getPrimaryName(); - final Optional symbol = this.getUnitlike().getSymbol(); - if (primaryName.isEmpty() && symbol.isEmpty()) { - final double baseValue = this.getUnitlike() - .convertToBase(this.getValue()); - return String.format("%s unnamed unit (= %s %s)", this.getValue(), - baseValue, this.getUnitlike().getBase()); - } else { - final String unitName = symbol.orElse(primaryName.get()); - return this.getValue() + " " + unitName; - } - } -} diff --git a/src/org/unitConverter/unit/package-info.java b/src/org/unitConverter/unit/package-info.java deleted file mode 100644 index 2f0e097..0000000 --- a/src/org/unitConverter/unit/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (C) 2019 Adrien Hopkins - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -/** - * Everything to do with the units that make up Unit Converter. - * - * @author Adrien Hopkins - * @since 2019-10-16 - * @since v0.1.0 - */ -package org.unitConverter.unit; \ No newline at end of file diff --git a/src/test/java/org/unitConverter/math/ConditionalExistenceCollectionsTest.java b/src/test/java/org/unitConverter/math/ConditionalExistenceCollectionsTest.java new file mode 100644 index 0000000..311ace5 --- /dev/null +++ b/src/test/java/org/unitConverter/math/ConditionalExistenceCollectionsTest.java @@ -0,0 +1,159 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.math; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; + +import org.junit.jupiter.api.Test; +import org.unitConverter.math.ConditionalExistenceCollections.ConditionalExistenceIterator; + +/** + * Tests the {@link #ConditionalExistenceCollections}. + * + * @author Adrien Hopkins + * @since 2019-10-16 + */ +class ConditionalExistenceCollectionsTest { + + /** + * The returned iterator ignores elements that don't start with "a". + * + * @return test iterator + * @since 2019-10-17 + */ + ConditionalExistenceIterator getTestIterator() { + final List items = Arrays.asList("aa", "ab", "ba"); + final Iterator it = items.iterator(); + final ConditionalExistenceIterator cit = (ConditionalExistenceIterator) ConditionalExistenceCollections + .conditionalExistenceIterator(it, s -> s.startsWith("a")); + return cit; + } + + /** + * The returned map ignores mappings where the value is zero. + * + * @return map to be used for test data + * @since 2019-10-16 + */ + Map getTestMap() { + final Map map = new HashMap<>(); + map.put("one", 1); + map.put("two", 2); + map.put("zero", 0); + map.put("ten", 10); + final Map conditionalMap = ConditionalExistenceCollections.conditionalExistenceMap(map, + e -> !Integer.valueOf(0).equals(e.getValue())); + return conditionalMap; + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#containsKey(java.lang.Object)}. + */ + @Test + void testContainsKeyObject() { + final Map map = this.getTestMap(); + assertTrue(map.containsKey("one")); + assertTrue(map.containsKey("ten")); + assertFalse(map.containsKey("five")); + assertFalse(map.containsKey("zero")); + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#containsValue(java.lang.Object)}. + */ + @Test + void testContainsValueObject() { + final Map map = this.getTestMap(); + assertTrue(map.containsValue(1)); + assertTrue(map.containsValue(10)); + assertFalse(map.containsValue(5)); + assertFalse(map.containsValue(0)); + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#entrySet()}. + */ + @Test + void testEntrySet() { + final Map map = this.getTestMap(); + for (final Entry e : map.entrySet()) { + assertTrue(e.getValue() != 0); + } + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#get(java.lang.Object)}. + */ + @Test + void testGetObject() { + final Map map = this.getTestMap(); + assertEquals(1, map.get("one")); + assertEquals(10, map.get("ten")); + assertEquals(null, map.get("five")); + assertEquals(null, map.get("zero")); + } + + @Test + void testIterator() { + final ConditionalExistenceIterator testIterator = this.getTestIterator(); + + assertTrue(testIterator.hasNext); + assertTrue(testIterator.hasNext()); + assertEquals("aa", testIterator.nextElement); + assertEquals("aa", testIterator.next()); + + assertTrue(testIterator.hasNext); + assertTrue(testIterator.hasNext()); + assertEquals("ab", testIterator.nextElement); + assertEquals("ab", testIterator.next()); + + assertFalse(testIterator.hasNext); + assertFalse(testIterator.hasNext()); + assertEquals(null, testIterator.nextElement); + assertThrows(NoSuchElementException.class, testIterator::next); + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#keySet()}. + */ + @Test + void testKeySet() { + final Map map = this.getTestMap(); + assertFalse(map.keySet().contains("zero")); + } + + /** + * Test method for {@link org.unitConverter.math.ZeroIsNullMap#values()}. + */ + @Test + void testValues() { + final Map map = this.getTestMap(); + assertFalse(map.values().contains(0)); + } + +} diff --git a/src/test/java/org/unitConverter/math/ExpressionParserTest.java b/src/test/java/org/unitConverter/math/ExpressionParserTest.java new file mode 100644 index 0000000..f3180c1 --- /dev/null +++ b/src/test/java/org/unitConverter/math/ExpressionParserTest.java @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.math; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +/** + * A test for the {@code ExpressionParser} class. This is NOT part of this program's public API. + * + * @author Adrien Hopkins + * @since 2019-03-22 + * @since v0.2.0 + */ +class ExpressionParserTest { + private static final ExpressionParser numberParser = new ExpressionParser.Builder<>(Integer::parseInt) + .addBinaryOperator("+", (o1, o2) -> o1 + o2, 0).addBinaryOperator("-", (o1, o2) -> o1 - o2, 0) + .addBinaryOperator("*", (o1, o2) -> o1 * o2, 1).addBinaryOperator("/", (o1, o2) -> o1 / o2, 1) + .addBinaryOperator("^", (o1, o2) -> (int) Math.pow(o1, o2), 2).build(); + + /** + * Test method for {@link org.unitConverter.math.ExpressionParser#parseExpression(java.lang.String)}. + */ + @Test + public void testParseExpression() { + // test parsing of expressions + assertEquals((int) numberParser.parseExpression("1 + 2 ^ 5 * 3"), 97); + assertEquals((int) numberParser.parseExpression("(1 + 2) ^ 5 * 3"), 729); + + // ensure it normally goes left to right + assertEquals((int) numberParser.parseExpression("1 + 2 + 3 + 4"), 10); + assertEquals((int) numberParser.parseExpression("12 - 4 - 3"), 5); + assertEquals((int) numberParser.parseExpression("12 - (4 - 3)"), 11); + assertEquals((int) numberParser.parseExpression("1 / 2 + 3"), 3); + } + +} diff --git a/src/test/java/org/unitConverter/math/ObjectProductTest.java b/src/test/java/org/unitConverter/math/ObjectProductTest.java new file mode 100644 index 0000000..afd18b7 --- /dev/null +++ b/src/test/java/org/unitConverter/math/ObjectProductTest.java @@ -0,0 +1,78 @@ +/** + * Copyright (C) 2018 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.math; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.unitConverter.unit.SI.Dimensions.AREA; +import static org.unitConverter.unit.SI.Dimensions.ENERGY; +import static org.unitConverter.unit.SI.Dimensions.LENGTH; +import static org.unitConverter.unit.SI.Dimensions.MASS; +import static org.unitConverter.unit.SI.Dimensions.MASS_DENSITY; +import static org.unitConverter.unit.SI.Dimensions.QUANTITY; +import static org.unitConverter.unit.SI.Dimensions.TIME; +import static org.unitConverter.unit.SI.Dimensions.VOLUME; + +import org.junit.jupiter.api.Test; +import org.unitConverter.unit.SI; + +/** + * Tests for {@link ObjectProduct} using BaseDimension as a test object. This is NOT part of this program's public API. + * + * @author Adrien Hopkins + * @since 2018-12-12 + * @since v0.1.0 + */ +class ObjectProductTest { + /** + * Tests {@link UnitDimension#equals} + * + * @since 2018-12-12 + * @since v0.1.0 + */ + @Test + public void testEquals() { + assertEquals(LENGTH, LENGTH); + assertFalse(LENGTH.equals(QUANTITY)); + } + + /** + * Tests {@code UnitDimension}'s exponentiation + * + * @since 2019-01-15 + * @since v0.1.0 + */ + @Test + public void testExponents() { + assertEquals(1, LENGTH.getExponent(SI.BaseDimensions.LENGTH)); + assertEquals(3, VOLUME.getExponent(SI.BaseDimensions.LENGTH)); + } + + /** + * Tests {@code UnitDimension}'s multiplication and division. + * + * @since 2018-12-12 + * @since v0.1.0 + */ + @Test + public void testMultiplicationAndDivision() { + assertEquals(AREA, LENGTH.times(LENGTH)); + assertEquals(MASS_DENSITY, MASS.dividedBy(VOLUME)); + assertEquals(ENERGY, AREA.times(MASS).dividedBy(TIME).dividedBy(TIME)); + assertEquals(LENGTH, LENGTH.times(TIME).dividedBy(TIME)); + } +} diff --git a/src/test/java/org/unitConverter/unit/MultiUnitTest.java b/src/test/java/org/unitConverter/unit/MultiUnitTest.java new file mode 100644 index 0000000..5ea9d07 --- /dev/null +++ b/src/test/java/org/unitConverter/unit/MultiUnitTest.java @@ -0,0 +1,106 @@ +/** + * Copyright (C) 2020 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +import org.junit.jupiter.api.Test; + +/** + * Tests related to the {@code MultiUnit}. + * + * @since 2020-10-03 + */ +class MultiUnitTest { + + @Test + final void testConvert() { + final Random rng = ThreadLocalRandom.current(); + final MultiUnit footInch = MultiUnit.of(BritishImperial.Length.FOOT, + BritishImperial.Length.INCH); + + assertEquals(1702.0, footInch.convertTo(SI.METRE.withPrefix(SI.MILLI), + Arrays.asList(5.0, 7.0)), 1.0); + + for (int i = 0; i < 1000; i++) { + final double feet = rng.nextInt(1000); + final double inches = rng.nextDouble() * 12; + final double millimetres = feet * 304.8 + inches * 25.4; + + final List feetAndInches = SI.METRE.withPrefix(SI.MILLI) + .convertTo(footInch, millimetres); + assertEquals(feet, feetAndInches.get(0), 1e-10); + assertEquals(inches, feetAndInches.get(1), 1e-10); + } + } + + /** + * Test method for + * {@link org.unitConverter.unit.MultiUnit#convertFromBase(double)}. + */ + @Test + final void testConvertFromBase() { + final Random rng = ThreadLocalRandom.current(); + final MultiUnit footInch = MultiUnit.of(BritishImperial.Length.FOOT, + BritishImperial.Length.INCH); + + // 1.7 m =~ 5' + 7" + final List values = footInch.convertFromBase(1.7018); + + assertEquals(5, values.get(0)); + assertEquals(7, values.get(1), 1e-12); + + for (int i = 0; i < 1000; i++) { + final double feet = rng.nextInt(1000); + final double inches = rng.nextDouble() * 12; + final double metres = feet * 0.3048 + inches * 0.0254; + + final List feetAndInches = footInch.convertFromBase(metres); + assertEquals(feet, feetAndInches.get(0), 1e-10); + assertEquals(inches, feetAndInches.get(1), 1e-10); + } + } + + /** + * Test method for + * {@link org.unitConverter.unit.MultiUnit#convertToBase(java.util.List)}. + */ + @Test + final void testConvertToBase() { + final Random rng = ThreadLocalRandom.current(); + final MultiUnit footInch = MultiUnit.of(BritishImperial.Length.FOOT, + BritishImperial.Length.INCH); + + // 1.7 m =~ 5' + 7" + assertEquals(1.7018, footInch.convertToBase(Arrays.asList(5.0, 7.0)), + 1e-12); + + for (int i = 0; i < 1000; i++) { + final double feet = rng.nextInt(1000); + final double inches = rng.nextDouble() * 12; + final double metres = feet * 0.3048 + inches * 0.0254; + + assertEquals(metres, + footInch.convertToBase(Arrays.asList(feet, inches)), 1e-12); + } + } +} diff --git a/src/test/java/org/unitConverter/unit/UnitDatabaseTest.java b/src/test/java/org/unitConverter/unit/UnitDatabaseTest.java new file mode 100644 index 0000000..f0ba8e5 --- /dev/null +++ b/src/test/java/org/unitConverter/unit/UnitDatabaseTest.java @@ -0,0 +1,309 @@ +/** + * Copyright (C) 2019 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +/** + * A test for the {@link UnitDatabase} class. This is NOT part of this program's + * public API. + * + * @author Adrien Hopkins + * @since 2019-04-14 + * @since v0.2.0 + */ +class UnitDatabaseTest { + // some linear units and one nonlinear + private static final Unit U = SI.METRE; + private static final Unit V = SI.KILOGRAM; + private static final Unit W = SI.SECOND; + + // used for testing expressions + // J = U^2 * V / W^2 + private static final LinearUnit J = SI.KILOGRAM.times(SI.METRE.toExponent(2)) + .dividedBy(SI.SECOND.toExponent(2)); + private static final LinearUnit K = SI.KELVIN; + + private static final Unit NONLINEAR = Unit + .fromConversionFunctions(SI.METRE.getBase(), o -> o + 1, o -> o - 1); + + // make the prefix values prime so I can tell which multiplications were made + private static final UnitPrefix A = UnitPrefix.valueOf(2) + .withName(NameSymbol.ofName("A")); + private static final UnitPrefix B = UnitPrefix.valueOf(3) + .withName(NameSymbol.ofName("B")); + private static final UnitPrefix C = UnitPrefix.valueOf(5) + .withName(NameSymbol.ofName("C")); + private static final UnitPrefix AB = UnitPrefix.valueOf(7); + private static final UnitPrefix BC = UnitPrefix.valueOf(11); + + /** + * Confirms that operations that shouldn't function for infinite databases + * throw an {@code IllegalStateException}. + * + * @since 2019-05-03 + */ +// @Test +// @Timeout(value = 1, unit = TimeUnit.SECONDS) + public void testInfiniteSetExceptions() { + // load units + final UnitDatabase infiniteDatabase = new UnitDatabase(); + + infiniteDatabase.addUnit("J", J); + infiniteDatabase.addUnit("K", K); + + infiniteDatabase.addPrefix("A", A); + infiniteDatabase.addPrefix("B", B); + infiniteDatabase.addPrefix("C", C); + + final Set> entrySet = infiniteDatabase.unitMap() + .entrySet(); + final Set keySet = infiniteDatabase.unitMap().keySet(); + assertThrows(IllegalStateException.class, () -> entrySet.toArray()); + assertThrows(IllegalStateException.class, () -> keySet.toArray()); + } + + /** + * Test that prefixes correctly apply to units. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testPrefixes() { + final UnitDatabase database = new UnitDatabase(); + + database.addUnit("U", U); + database.addUnit("V", V); + database.addUnit("W", W); + + database.addPrefix("A", A); + database.addPrefix("B", B); + database.addPrefix("C", C); + + // test the getPrefixesFromName method + final List expected = Arrays.asList(C, B, A); + assertEquals(expected, database.getPrefixesFromName("ABCU")); + + // get the product + final Unit abcuNonlinear = database.getUnit("ABCU"); + assert abcuNonlinear instanceof LinearUnit; + + final LinearUnit abcu = (LinearUnit) abcuNonlinear; + assertEquals(A.getMultiplier() * B.getMultiplier() * C.getMultiplier(), + abcu.getConversionFactor(), 1e-15); + } + + /** + * Tests the functionnalites of the prefixless unit map. + * + *

    + * The map should be an auto-updating view of the units in the database. + *

    + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testPrefixlessUnitMap() { + final UnitDatabase database = new UnitDatabase(); + final Map prefixlessUnits = database.unitMapPrefixless(); + + database.addUnit("U", U); + database.addUnit("V", V); + database.addUnit("W", W); + + // this should work because the map should be an auto-updating view + assertTrue(prefixlessUnits.containsKey("U")); + assertFalse(prefixlessUnits.containsKey("Z")); + + assertTrue(prefixlessUnits.containsValue(U)); + assertFalse(prefixlessUnits.containsValue(NONLINEAR)); + } + + /** + * Tests that the database correctly stores and retrieves units, ignoring + * prefixes. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testPrefixlessUnits() { + final UnitDatabase database = new UnitDatabase(); + + database.addUnit("U", U); + database.addUnit("V", V); + database.addUnit("W", W); + + assertTrue(database.containsUnitName("U")); + assertFalse(database.containsUnitName("Z")); + + assertEquals(U, database.getUnit("U")); + assertThrows(NoSuchElementException.class, () -> database.getUnit("Z")); + } + + /** + * Test that unit expressions return the correct value. + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testUnitExpressions() { + // load units + final UnitDatabase database = new UnitDatabase(); + + database.addUnit("U", U); + database.addUnit("V", V); + database.addUnit("W", W); + database.addUnit("fj", J.times(5)); + database.addUnit("ej", J.times(8)); + + database.addPrefix("A", A); + database.addPrefix("B", B); + database.addPrefix("C", C); + + // first test - test prefixes and operations + final Unit expected1 = J.withPrefix(A).withPrefix(B).withPrefix(C) + .withPrefix(C); + final Unit actual1 = database.getUnitFromExpression("ABV * CU^2 / W / W"); + + assertEquals(expected1, actual1); + + // second test - test addition and subtraction + final Unit expected2 = J.times(58); + final Unit actual2 = database.getUnitFromExpression("2 fj + 6 ej"); + + assertEquals(expected2, actual2); + } + + /** + * Tests both the unit name iterator and the name-unit entry iterator + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testUnitIterator() { + // load units + final UnitDatabase database = new UnitDatabase(); + + database.addUnit("J", J); + database.addUnit("K", K); + + database.addPrefix("A", A); + database.addPrefix("B", B); + database.addPrefix("C", C); + + final int NUM_UNITS = database.unitMapPrefixless().size(); + final int NUM_PREFIXES = database.prefixMap().size(); + + final Iterator nameIterator = database.unitMap().keySet() + .iterator(); + final Iterator> entryIterator = database.unitMap() + .entrySet().iterator(); + + int expectedLength = 1; + int unitsWithThisLengthSoFar = 0; + + // loop 1000 times + for (int i = 0; i < 1000; i++) { + // expected length of next + if (unitsWithThisLengthSoFar >= NUM_UNITS + * (int) Math.pow(NUM_PREFIXES, expectedLength - 1)) { + expectedLength++; + unitsWithThisLengthSoFar = 0; + } + + // test that stuff is valid + final String nextName = nameIterator.next(); + final Unit nextUnit = database.getUnit(nextName); + final Entry nextEntry = entryIterator.next(); + + assertEquals(expectedLength, nextName.length()); + assertEquals(nextName, nextEntry.getKey()); + assertEquals(nextUnit, nextEntry.getValue()); + + unitsWithThisLengthSoFar++; + } + + // test toString for consistency + final String entryIteratorString = entryIterator.toString(); + for (int i = 0; i < 3; i++) { + assertEquals(entryIteratorString, entryIterator.toString()); + } + + final String nameIteratorString = nameIterator.toString(); + for (int i = 0; i < 3; i++) { + assertEquals(nameIteratorString, nameIterator.toString()); + } + } + + /** + * Determine, given a unit name that could mean multiple things, which + * meaning is chosen. + *

    + * For example, "ABCU" could mean "A-B-C-U", "AB-C-U", or "A-BC-U". In this + * case, "AB-C-U" is the correct choice. + *

    + * + * @since 2019-04-14 + * @since v0.2.0 + */ + @Test + public void testUnitPrefixCombinations() { + // load units + final UnitDatabase database = new UnitDatabase(); + + database.addUnit("J", J); + + database.addPrefix("A", A); + database.addPrefix("B", B); + database.addPrefix("C", C); + database.addPrefix("AB", AB); + database.addPrefix("BC", BC); + + // test 1 - AB-C-J vs A-BC-J vs A-B-C-J + final Unit expected1 = J.withPrefix(AB).withPrefix(C); + final Unit actual1 = database.getUnit("ABCJ"); + + assertEquals(expected1, actual1); + + // test 2 - ABC-J vs AB-CJ vs AB-C-J + database.addUnit("CJ", J.times(13)); + database.addPrefix("ABC", UnitPrefix.valueOf(17)); + + final Unit expected2 = J.times(17); + final Unit actual2 = database.getUnit("ABCJ"); + + assertEquals(expected2, actual2); + } +} diff --git a/src/test/java/org/unitConverter/unit/UnitTest.java b/src/test/java/org/unitConverter/unit/UnitTest.java new file mode 100644 index 0000000..3b594f2 --- /dev/null +++ b/src/test/java/org/unitConverter/unit/UnitTest.java @@ -0,0 +1,146 @@ +/** + * Copyright (C) 2018 Adrien Hopkins + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.unitConverter.unit; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +import org.junit.jupiter.api.Test; +import org.unitConverter.math.DecimalComparison; + +/** + * Testing the various Unit classes. This is NOT part of this program's public + * API. + * + * @author Adrien Hopkins + * @since 2018-12-22 + * @since v0.1.0 + */ +class UnitTest { + /** A random number generator */ + private static final Random rng = ThreadLocalRandom.current(); + + @Test + public void testAdditionAndSubtraction() { + final LinearUnit inch = SI.METRE.times(0.0254) + .withName(NameSymbol.of("inch", "in")); + final LinearUnit foot = SI.METRE.times(0.3048) + .withName(NameSymbol.of("foot", "ft")); + + assertEquals(inch.plus(foot), SI.METRE.times(0.3302)); + assertEquals(foot.minus(inch), SI.METRE.times(0.2794)); + + // test with LinearUnitValue + final LinearUnitValue value1 = LinearUnitValue.getExact(SI.METRE, 15); + final LinearUnitValue value2 = LinearUnitValue.getExact(foot, 120); + final LinearUnitValue value3 = LinearUnitValue.getExact(SI.METRE, 0.5); + final LinearUnitValue value4 = LinearUnitValue.getExact(SI.KILOGRAM, 60); + + // make sure addition is done correctly + assertEquals(51.576, value1.plus(value2).getValueExact(), 0.001); + assertEquals(15.5, value1.plus(value3).getValueExact()); + assertEquals(52.076, value1.plus(value2).plus(value3).getValueExact(), + 0.001); + + // make sure addition uses the correct unit, and is still associative + // (ignoring floating-point rounding errors) + assertEquals(SI.METRE, value1.plus(value2).getUnit()); + assertEquals(SI.METRE, value1.plus(value2).plus(value3).getUnit()); + assertEquals(foot, value2.plus(value1).getUnit()); + assertTrue(value1.plus(value2).equals(value2.plus(value1), true)); + + // make sure errors happen when they should + assertThrows(IllegalArgumentException.class, () -> value1.plus(value4)); + } + + @Test + public void testConversion() { + final LinearUnit metre = SI.METRE; + final Unit inch = metre.times(0.0254); + + final UnitValue value = UnitValue.of(inch, 75); + + assertEquals(1.9, inch.convertTo(metre, 75), 0.01); + assertEquals(1.9, value.convertTo(metre).getValue(), 0.01); + + // try random stuff + for (int i = 0; i < 1000; i++) { + // initiate random values + final double conversionFactor = UnitTest.rng.nextDouble() * 1000000; + final double testValue = UnitTest.rng.nextDouble() * 1000000; + final double expected = testValue * conversionFactor; + + // test + final Unit unit = SI.METRE.times(conversionFactor); + final double actual = unit.convertToBase(testValue); + + assertEquals(actual, expected, + expected * DecimalComparison.DOUBLE_EPSILON); + } + } + + @Test + public void testEquals() { + final LinearUnit metre = SI.METRE; + final Unit meter = SI.BaseUnits.METRE.asLinearUnit(); + + assertEquals(metre, meter); + } + + @Test + public void testIsMetric() { + final Unit metre = SI.METRE; + final Unit megasecond = SI.SECOND.withPrefix(SI.MEGA); + final Unit hour = SI.HOUR; + + assertTrue(metre.isMetric()); + assertTrue(megasecond.isMetric()); + assertFalse(hour.isMetric()); + } + + @Test + public void testMultiplicationAndDivision() { + // test unit-times-unit multiplication + final LinearUnit generatedJoule = SI.KILOGRAM + .times(SI.METRE.toExponent(2)).dividedBy(SI.SECOND.toExponent(2)); + final LinearUnit actualJoule = SI.JOULE; + + assertEquals(generatedJoule, actualJoule); + + // test multiplication by conversion factors + final LinearUnit kilometre = SI.METRE.times(1000); + final LinearUnit hour = SI.SECOND.times(3600); + final LinearUnit generatedKPH = kilometre.dividedBy(hour); + + final LinearUnit actualKPH = SI.METRE.dividedBy(SI.SECOND).dividedBy(3.6); + + assertEquals(generatedKPH, actualKPH); + } + + @Test + public void testPrefixes() { + final LinearUnit generatedKilometre = SI.METRE.withPrefix(SI.KILO); + final LinearUnit actualKilometre = SI.METRE.times(1000); + + assertEquals(generatedKilometre, actualKilometre); + } +} -- cgit v1.2.3 From 32f390a86ac9b868b7eb9c1d47875c6a990b6d11 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 27 Mar 2021 16:38:21 -0500 Subject: Finalized the upgrade to Java 11 --- .../math/ConditionalExistenceCollections.java | 2 +- .../org/unitConverter/math/ExpressionParser.java | 537 +++++++++++---------- 2 files changed, 283 insertions(+), 256 deletions(-) diff --git a/src/main/java/org/unitConverter/math/ConditionalExistenceCollections.java b/src/main/java/org/unitConverter/math/ConditionalExistenceCollections.java index ac1c0cf..000658b 100644 --- a/src/main/java/org/unitConverter/math/ConditionalExistenceCollections.java +++ b/src/main/java/org/unitConverter/math/ConditionalExistenceCollections.java @@ -263,7 +263,7 @@ public final class ConditionalExistenceCollections { } private final Entry getEntry(K key) { - return new Entry() { + return new Entry<>() { @Override public K getKey() { return key; diff --git a/src/main/java/org/unitConverter/math/ExpressionParser.java b/src/main/java/org/unitConverter/math/ExpressionParser.java index 8a0e97d..deee51d 100644 --- a/src/main/java/org/unitConverter/math/ExpressionParser.java +++ b/src/main/java/org/unitConverter/math/ExpressionParser.java @@ -32,8 +32,7 @@ import java.util.function.UnaryOperator; * An object that can parse expressions with unary or binary operators. * * @author Adrien Hopkins - * @param - * type of object that exists in parsed expressions + * @param type of object that exists in parsed expressions * @since 2019-03-14 * @since v0.2.0 */ @@ -42,21 +41,21 @@ public final class ExpressionParser { * A builder that can create {@code ExpressionParser} instances. * * @author Adrien Hopkins - * @param - * type of object that exists in parsed expressions + * @param type of object that exists in parsed expressions * @since 2019-03-17 * @since v0.2.0 */ public static final class Builder { /** - * A function that obtains a parseable object from a string. For example, an integer {@code ExpressionParser} - * would use {@code Integer::parseInt}. + * A function that obtains a parseable object from a string. For example, + * an integer {@code ExpressionParser} would use + * {@code Integer::parseInt}. * * @since 2019-03-14 * @since v0.2.0 */ private final Function objectObtainer; - + /** * The function of the space as an operator (like 3 x y) * @@ -64,110 +63,115 @@ public final class ExpressionParser { * @since v0.2.0 */ private String spaceFunction = null; - + /** - * A map mapping operator strings to operator functions, for unary operators. + * A map mapping operator strings to operator functions, for unary + * operators. * * @since 2019-03-14 * @since v0.2.0 */ private final Map> unaryOperators; - + /** - * A map mapping operator strings to operator functions, for binary operators. + * A map mapping operator strings to operator functions, for binary + * operators. * * @since 2019-03-14 * @since v0.2.0 */ private final Map> binaryOperators; - + /** * Creates the {@code Builder}. * - * @param objectObtainer - * a function that can turn strings into objects of the type handled by the parser. - * @throws NullPointerException - * if {@code objectObtainer} is null + * @param objectObtainer a function that can turn strings into objects of + * the type handled by the parser. + * @throws NullPointerException if {@code objectObtainer} is null * @since 2019-03-17 * @since v0.2.0 */ public Builder(final Function objectObtainer) { - this.objectObtainer = Objects.requireNonNull(objectObtainer, "objectObtainer must not be null."); + this.objectObtainer = Objects.requireNonNull(objectObtainer, + "objectObtainer must not be null."); this.unaryOperators = new HashMap<>(); this.binaryOperators = new HashMap<>(); } - + /** * Adds a binary operator to the builder. * - * @param text - * text used to reference the operator, like '+' - * @param operator - * operator to add - * @param priority - * operator's priority, which determines which operators are applied first + * @param text text used to reference the operator, like '+' + * @param operator operator to add + * @param priority operator's priority, which determines which operators + * are applied first * @return this builder - * @throws NullPointerException - * if {@code text} or {@code operator} is null + * @throws NullPointerException if {@code text} or {@code operator} is + * null * @since 2019-03-17 * @since v0.2.0 */ - public Builder addBinaryOperator(final String text, final BinaryOperator operator, final int priority) { + public Builder addBinaryOperator(final String text, + final BinaryOperator operator, final int priority) { Objects.requireNonNull(text, "text must not be null."); Objects.requireNonNull(operator, "operator must not be null."); - - // Unfortunately, I cannot use a lambda because the PriorityBinaryOperator requires arguments. - final PriorityBinaryOperator priorityOperator = new PriorityBinaryOperator(priority) { + + // Unfortunately, I cannot use a lambda because the + // PriorityBinaryOperator requires arguments. + final PriorityBinaryOperator priorityOperator = new PriorityBinaryOperator<>( + priority) { @Override public T apply(final T t, final T u) { return operator.apply(t, u); } - + }; this.binaryOperators.put(text, priorityOperator); return this; } - + /** - * Adds a function for spaces. You must use the text of an existing binary operator. + * Adds a function for spaces. You must use the text of an existing binary + * operator. * - * @param operator - * text of operator to use + * @param operator text of operator to use * @return this builder * @since 2019-03-22 * @since v0.2.0 */ public Builder addSpaceFunction(final String operator) { Objects.requireNonNull(operator, "operator must not be null."); - + if (!this.binaryOperators.containsKey(operator)) - throw new IllegalArgumentException(String.format("Could not find binary operator '%s'", operator)); - + throw new IllegalArgumentException(String + .format("Could not find binary operator '%s'", operator)); + this.spaceFunction = operator; return this; } - + /** * Adds a unary operator to the builder. * - * @param text - * text used to reference the operator, like '-' - * @param operator - * operator to add - * @param priority - * operator's priority, which determines which operators are applied first + * @param text text used to reference the operator, like '-' + * @param operator operator to add + * @param priority operator's priority, which determines which operators + * are applied first * @return this builder - * @throws NullPointerException - * if {@code text} or {@code operator} is null + * @throws NullPointerException if {@code text} or {@code operator} is + * null * @since 2019-03-17 * @since v0.2.0 */ - public Builder addUnaryOperator(final String text, final UnaryOperator operator, final int priority) { + public Builder addUnaryOperator(final String text, + final UnaryOperator operator, final int priority) { Objects.requireNonNull(text, "text must not be null."); Objects.requireNonNull(operator, "operator must not be null."); - - // Unfortunately, I cannot use a lambda because the PriorityUnaryOperator requires arguments. - final PriorityUnaryOperator priorityOperator = new PriorityUnaryOperator(priority) { + + // Unfortunately, I cannot use a lambda because the + // PriorityUnaryOperator requires arguments. + final PriorityUnaryOperator priorityOperator = new PriorityUnaryOperator<>( + priority) { @Override public T apply(final T t) { return operator.apply(t); @@ -176,49 +180,50 @@ public final class ExpressionParser { this.unaryOperators.put(text, priorityOperator); return this; } - + /** - * @return an {@code ExpressionParser} instance with the properties given to this builder + * @return an {@code ExpressionParser} instance with the properties + * given to this builder * @since 2019-03-17 * @since v0.2.0 */ public ExpressionParser build() { - return new ExpressionParser<>(this.objectObtainer, this.unaryOperators, this.binaryOperators, - this.spaceFunction); + return new ExpressionParser<>(this.objectObtainer, this.unaryOperators, + this.binaryOperators, this.spaceFunction); } } - + /** - * A binary operator with a priority field that determines which operators apply first. + * A binary operator with a priority field that determines which operators + * apply first. * * @author Adrien Hopkins - * @param - * type of operand and result + * @param type of operand and result * @since 2019-03-17 * @since v0.2.0 */ private static abstract class PriorityBinaryOperator implements BinaryOperator, Comparable> { /** - * The operator's priority. Higher-priority operators are applied before lower-priority operators + * The operator's priority. Higher-priority operators are applied before + * lower-priority operators * * @since 2019-03-17 * @since v0.2.0 */ private final int priority; - + /** * Creates the {@code PriorityBinaryOperator}. * - * @param priority - * operator's priority + * @param priority operator's priority * @since 2019-03-17 * @since v0.2.0 */ public PriorityBinaryOperator(final int priority) { this.priority = priority; } - + /** * Compares this object to another by priority. * @@ -238,7 +243,7 @@ public final class ExpressionParser { else return 0; } - + /** * @return priority * @since 2019-03-22 @@ -248,38 +253,38 @@ public final class ExpressionParser { return this.priority; } } - + /** - * A unary operator with a priority field that determines which operators apply first. + * A unary operator with a priority field that determines which operators + * apply first. * * @author Adrien Hopkins - * @param - * type of operand and result + * @param type of operand and result * @since 2019-03-17 * @since v0.2.0 */ private static abstract class PriorityUnaryOperator implements UnaryOperator, Comparable> { /** - * The operator's priority. Higher-priority operators are applied before lower-priority operators + * The operator's priority. Higher-priority operators are applied before + * lower-priority operators * * @since 2019-03-17 * @since v0.2.0 */ private final int priority; - + /** * Creates the {@code PriorityUnaryOperator}. * - * @param priority - * operator's priority + * @param priority operator's priority * @since 2019-03-17 * @since v0.2.0 */ public PriorityUnaryOperator(final int priority) { this.priority = priority; } - + /** * Compares this object to another by priority. * @@ -299,7 +304,7 @@ public final class ExpressionParser { else return 0; } - + /** * @return priority * @since 2019-03-22 @@ -309,7 +314,7 @@ public final class ExpressionParser { return this.priority; } } - + /** * The types of tokens that are available. * @@ -320,7 +325,7 @@ public final class ExpressionParser { private static enum TokenType { OBJECT, UNARY_OPERATOR, BINARY_OPERATOR; } - + /** * The opening bracket. * @@ -328,7 +333,7 @@ public final class ExpressionParser { * @since v0.2.0 */ public static final char OPENING_BRACKET = '('; - + /** * The closing bracket. * @@ -336,48 +341,49 @@ public final class ExpressionParser { * @since v0.2.0 */ public static final char CLOSING_BRACKET = ')'; - + /** * Finds the other bracket in a pair of brackets, given the position of one. * - * @param string - * string that contains brackets - * @param bracketPosition - * position of first bracket + * @param string string that contains brackets + * @param bracketPosition position of first bracket * @return position of matching bracket - * @throws NullPointerException - * if string is null + * @throws NullPointerException if string is null * @since 2019-03-22 * @since v0.2.0 */ - private static int findBracketPair(final String string, final int bracketPosition) { + private static int findBracketPair(final String string, + final int bracketPosition) { Objects.requireNonNull(string, "string must not be null."); - + final char openingBracket = string.charAt(bracketPosition); - + // figure out what closing bracket to look for final char closingBracket; switch (openingBracket) { - case '(': - closingBracket = ')'; - break; - case '[': - closingBracket = ']'; - break; - case '{': - closingBracket = '}'; - break; - default: - throw new IllegalArgumentException(String.format("Invalid bracket '%s'", openingBracket)); + case '(': + closingBracket = ')'; + break; + case '[': + closingBracket = ']'; + break; + case '{': + closingBracket = '}'; + break; + default: + throw new IllegalArgumentException( + String.format("Invalid bracket '%s'", openingBracket)); } - - // level of brackets. every opening bracket increments this; every closing bracket decrements it + + // level of brackets. every opening bracket increments this; every closing + // bracket decrements it int bracketLevel = 0; - + // iterate over the string to find the closing bracket - for (int currentPosition = bracketPosition; currentPosition < string.length(); currentPosition++) { + for (int currentPosition = bracketPosition; currentPosition < string + .length(); currentPosition++) { final char currentCharacter = string.charAt(currentPosition); - + if (currentCharacter == openingBracket) { bracketLevel++; } else if (currentCharacter == closingBracket) { @@ -386,19 +392,19 @@ public final class ExpressionParser { return currentPosition; } } - + throw new IllegalArgumentException("No matching bracket found."); } - + /** - * A function that obtains a parseable object from a string. For example, an integer {@code ExpressionParser} would - * use {@code Integer::parseInt}. + * A function that obtains a parseable object from a string. For example, an + * integer {@code ExpressionParser} would use {@code Integer::parseInt}. * * @since 2019-03-14 * @since v0.2.0 */ private final Function objectObtainer; - + /** * A map mapping operator strings to operator functions, for unary operators. * @@ -406,15 +412,16 @@ public final class ExpressionParser { * @since v0.2.0 */ private final Map> unaryOperators; - + /** - * A map mapping operator strings to operator functions, for binary operators. + * A map mapping operator strings to operator functions, for binary + * operators. * * @since 2019-03-14 * @since v0.2.0 */ private final Map> binaryOperators; - + /** * The operator for space, or null if spaces have no function. * @@ -422,127 +429,144 @@ public final class ExpressionParser { * @since v0.2.0 */ private final String spaceOperator; - + /** * Creates the {@code ExpressionParser}. * - * @param objectObtainer - * function to get objects from strings - * @param unaryOperators - * unary operators available to the parser - * @param binaryOperators - * binary operators available to the parser - * @param spaceOperator - * operator used by spaces + * @param objectObtainer function to get objects from strings + * @param unaryOperators unary operators available to the parser + * @param binaryOperators binary operators available to the parser + * @param spaceOperator operator used by spaces * @since 2019-03-14 * @since v0.2.0 */ private ExpressionParser(final Function objectObtainer, final Map> unaryOperators, - final Map> binaryOperators, final String spaceOperator) { + final Map> binaryOperators, + final String spaceOperator) { this.objectObtainer = objectObtainer; this.unaryOperators = unaryOperators; this.binaryOperators = binaryOperators; this.spaceOperator = spaceOperator; } - + /** - * Converts a given mathematical expression to reverse Polish notation (operators after operands). + * Converts a given mathematical expression to reverse Polish notation + * (operators after operands). *

    * For example,
    * {@code 2 * (3 + 4)}
    * becomes
    * {@code 2 3 4 + *}. * - * @param expression - * expression + * @param expression expression * @return expression in RPN * @since 2019-03-17 * @since v0.2.0 */ private String convertExpressionToReversePolish(final String expression) { Objects.requireNonNull(expression, "expression must not be null."); - + final List components = new ArrayList<>(); - + // the part of the expression remaining to parse String partialExpression = expression; - + // find and deal with brackets while (partialExpression.indexOf(OPENING_BRACKET) != -1) { - final int openingBracketPosition = partialExpression.indexOf(OPENING_BRACKET); - final int closingBracketPosition = findBracketPair(partialExpression, openingBracketPosition); - + final int openingBracketPosition = partialExpression + .indexOf(OPENING_BRACKET); + final int closingBracketPosition = findBracketPair(partialExpression, + openingBracketPosition); + // check for function - if (openingBracketPosition > 0 && partialExpression.charAt(openingBracketPosition - 1) != ' ') { + if (openingBracketPosition > 0 + && partialExpression.charAt(openingBracketPosition - 1) != ' ') { // function like sin(2) or tempF(32) // find the position of the last space int spacePosition = openingBracketPosition; - while (spacePosition >= 0 && partialExpression.charAt(spacePosition) != ' ') { + while (spacePosition >= 0 + && partialExpression.charAt(spacePosition) != ' ') { spacePosition--; } - // then split the function into pre-function and function, using the space position - components.addAll(Arrays.asList(partialExpression.substring(0, spacePosition + 1).split(" "))); - components.add(partialExpression.substring(spacePosition + 1, closingBracketPosition + 1)); - partialExpression = partialExpression.substring(closingBracketPosition + 1); + // then split the function into pre-function and function, using the + // space position + components.addAll(Arrays.asList(partialExpression + .substring(0, spacePosition + 1).split(" "))); + components.add(partialExpression.substring(spacePosition + 1, + closingBracketPosition + 1)); + partialExpression = partialExpression + .substring(closingBracketPosition + 1); } else { // normal brackets like (1 + 2) * (3 / 5) - components.addAll(Arrays.asList(partialExpression.substring(0, openingBracketPosition).split(" "))); + components.addAll(Arrays.asList(partialExpression + .substring(0, openingBracketPosition).split(" "))); components.add(this.convertExpressionToReversePolish( - partialExpression.substring(openingBracketPosition + 1, closingBracketPosition))); - partialExpression = partialExpression.substring(closingBracketPosition + 1); + partialExpression.substring(openingBracketPosition + 1, + closingBracketPosition))); + partialExpression = partialExpression + .substring(closingBracketPosition + 1); } } - + // add everything else components.addAll(Arrays.asList(partialExpression.split(" "))); - + // remove empty entries while (components.contains("")) { components.remove(""); } - + // deal with space multiplication (x y) if (this.spaceOperator != null) { for (int i = 0; i < components.size() - 1; i++) { - if (this.getTokenType(components.get(i)) == TokenType.OBJECT - && this.getTokenType(components.get(i + 1)) == TokenType.OBJECT) { + if (this.getTokenType(components.get(i)) == TokenType.OBJECT && this + .getTokenType(components.get(i + 1)) == TokenType.OBJECT) { components.add(++i, this.spaceOperator); } } } - + // turn the expression into reverse Polish while (true) { - final int highestPriorityOperatorPosition = this.findHighestPriorityOperatorPosition(components); + final int highestPriorityOperatorPosition = this + .findHighestPriorityOperatorPosition(components); if (highestPriorityOperatorPosition == -1) { break; } - + // swap components based on what kind of operator there is // 1 + 2 becomes 2 1 + // - 1 becomes 1 - - switch (this.getTokenType(components.get(highestPriorityOperatorPosition))) { - case UNARY_OPERATOR: - final String unaryOperator = components.remove(highestPriorityOperatorPosition); - final String operand = components.remove(highestPriorityOperatorPosition); - components.add(highestPriorityOperatorPosition, operand + " " + unaryOperator); - break; - case BINARY_OPERATOR: - final String binaryOperator = components.remove(highestPriorityOperatorPosition); - final String operand1 = components.remove(highestPriorityOperatorPosition - 1); - final String operand2 = components.remove(highestPriorityOperatorPosition - 1); - components.add(highestPriorityOperatorPosition - 1, - operand2 + " " + operand1 + " " + binaryOperator); - break; - default: - throw new AssertionError("Expected operator, found non-operator."); + switch (this + .getTokenType(components.get(highestPriorityOperatorPosition))) { + case UNARY_OPERATOR: + final String unaryOperator = components + .remove(highestPriorityOperatorPosition); + final String operand = components + .remove(highestPriorityOperatorPosition); + components.add(highestPriorityOperatorPosition, + operand + " " + unaryOperator); + break; + case BINARY_OPERATOR: + final String binaryOperator = components + .remove(highestPriorityOperatorPosition); + final String operand1 = components + .remove(highestPriorityOperatorPosition - 1); + final String operand2 = components + .remove(highestPriorityOperatorPosition - 1); + components.add(highestPriorityOperatorPosition - 1, + operand2 + " " + operand1 + " " + binaryOperator); + break; + default: + throw new AssertionError("Expected operator, found non-operator."); } } - - // join all of the components together, then ensure there is only one space in a row + + // join all of the components together, then ensure there is only one + // space in a row String expressionRPN = String.join(" ", components).replaceAll(" +", " "); - + while (expressionRPN.charAt(0) == ' ') { expressionRPN = expressionRPN.substring(1); } @@ -551,73 +575,72 @@ public final class ExpressionParser { } return expressionRPN; } - + /** * Finds the position of the highest-priority operator in a list * - * @param components - * components to test - * @param blacklist - * positions of operators that should be ignored - * @return position of highest priority, or -1 if the list contains no operators - * @throws NullPointerException - * if components is null + * @param components components to test + * @param blacklist positions of operators that should be ignored + * @return position of highest priority, or -1 if the list contains no + * operators + * @throws NullPointerException if components is null * @since 2019-03-22 * @since v0.2.0 */ - private int findHighestPriorityOperatorPosition(final List components) { + private int findHighestPriorityOperatorPosition( + final List components) { Objects.requireNonNull(components, "components must not be null."); // find highest priority int maxPriority = Integer.MIN_VALUE; int maxPriorityPosition = -1; - + // go over components one by one // if it is an operator, test its priority to see if it's max // if it is, update maxPriority and maxPriorityPosition for (int i = 0; i < components.size(); i++) { - + switch (this.getTokenType(components.get(i))) { - case UNARY_OPERATOR: - final PriorityUnaryOperator unaryOperator = this.unaryOperators.get(components.get(i)); - final int unaryPriority = unaryOperator.getPriority(); - - if (unaryPriority > maxPriority) { - maxPriority = unaryPriority; - maxPriorityPosition = i; - } - break; - case BINARY_OPERATOR: - final PriorityBinaryOperator binaryOperator = this.binaryOperators.get(components.get(i)); - final int binaryPriority = binaryOperator.getPriority(); - - if (binaryPriority > maxPriority) { - maxPriority = binaryPriority; - maxPriorityPosition = i; - } - break; - default: - break; + case UNARY_OPERATOR: + final PriorityUnaryOperator unaryOperator = this.unaryOperators + .get(components.get(i)); + final int unaryPriority = unaryOperator.getPriority(); + + if (unaryPriority > maxPriority) { + maxPriority = unaryPriority; + maxPriorityPosition = i; + } + break; + case BINARY_OPERATOR: + final PriorityBinaryOperator binaryOperator = this.binaryOperators + .get(components.get(i)); + final int binaryPriority = binaryOperator.getPriority(); + + if (binaryPriority > maxPriority) { + maxPriority = binaryPriority; + maxPriorityPosition = i; + } + break; + default: + break; } } - + // max priority position found return maxPriorityPosition; } - + /** * Determines whether an inputted string is an object or an operator * - * @param token - * string to input + * @param token string to input * @return type of token it is - * @throws NullPointerException - * if {@code expression} is null + * @throws NullPointerException if {@code expression} is null * @since 2019-03-14 * @since v0.2.0 */ private TokenType getTokenType(final String token) { Objects.requireNonNull(token, "token must not be null."); - + if (this.unaryOperators.containsKey(token)) return TokenType.UNARY_OPERATOR; else if (this.binaryOperators.containsKey(token)) @@ -625,84 +648,88 @@ public final class ExpressionParser { else return TokenType.OBJECT; } - + /** * Parses an expression. * - * @param expression - * expression to parse + * @param expression expression to parse * @return result - * @throws NullPointerException - * if {@code expression} is null + * @throws NullPointerException if {@code expression} is null * @since 2019-03-14 * @since v0.2.0 */ public T parseExpression(final String expression) { - return this.parseReversePolishExpression(this.convertExpressionToReversePolish(expression)); + return this.parseReversePolishExpression( + this.convertExpressionToReversePolish(expression)); } - + /** * Parses an expression expressed in reverse Polish notation. * - * @param expression - * expression to parse + * @param expression expression to parse * @return result - * @throws NullPointerException - * if {@code expression} is null + * @throws NullPointerException if {@code expression} is null * @since 2019-03-14 * @since v0.2.0 */ private T parseReversePolishExpression(final String expression) { Objects.requireNonNull(expression, "expression must not be null."); - + final Deque stack = new ArrayDeque<>(); - + // iterate over every item in the expression, then for (final String item : expression.split(" ")) { // choose a path based on what kind of thing was just read switch (this.getTokenType(item)) { - - case BINARY_OPERATOR: - if (stack.size() < 2) - throw new IllegalStateException(String.format( - "Attempted to call binary operator %s with only %d arguments.", item, stack.size())); - - // get two arguments and operator, then apply! - final T o1 = stack.pop(); - final T o2 = stack.pop(); - final BinaryOperator binaryOperator = this.binaryOperators.get(item); - - stack.push(binaryOperator.apply(o1, o2)); - break; - - case OBJECT: - // just add it to the stack - stack.push(this.objectObtainer.apply(item)); - break; - - case UNARY_OPERATOR: - if (stack.size() < 1) - throw new IllegalStateException(String.format( - "Attempted to call unary operator %s with only %d arguments.", item, stack.size())); - - // get one argument and operator, then apply! - final T o = stack.pop(); - final UnaryOperator unaryOperator = this.unaryOperators.get(item); - - stack.push(unaryOperator.apply(o)); - break; - default: - throw new AssertionError( - String.format("Internal error: Invalid token type %s.", this.getTokenType(item))); - + + case BINARY_OPERATOR: + if (stack.size() < 2) + throw new IllegalStateException(String.format( + "Attempted to call binary operator %s with only %d arguments.", + item, stack.size())); + + // get two arguments and operator, then apply! + final T o1 = stack.pop(); + final T o2 = stack.pop(); + final BinaryOperator binaryOperator = this.binaryOperators + .get(item); + + stack.push(binaryOperator.apply(o1, o2)); + break; + + case OBJECT: + // just add it to the stack + stack.push(this.objectObtainer.apply(item)); + break; + + case UNARY_OPERATOR: + if (stack.size() < 1) + throw new IllegalStateException(String.format( + "Attempted to call unary operator %s with only %d arguments.", + item, stack.size())); + + // get one argument and operator, then apply! + final T o = stack.pop(); + final UnaryOperator unaryOperator = this.unaryOperators + .get(item); + + stack.push(unaryOperator.apply(o)); + break; + default: + throw new AssertionError( + String.format("Internal error: Invalid token type %s.", + this.getTokenType(item))); + } } - + // return answer, or throw an exception if I can't if (stack.size() > 1) - throw new IllegalStateException("Computation ended up with more than one answer."); + throw new IllegalStateException( + "Computation ended up with more than one answer."); else if (stack.size() == 0) - throw new IllegalStateException("Computation ended up without an answer."); + throw new IllegalStateException( + "Computation ended up without an answer."); return stack.pop(); } } -- cgit v1.2.3 From c767cfda66e22f6e6b2f87b3a4ded850352e909d Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 27 Mar 2021 16:48:14 -0500 Subject: Added a test coverage report to the build process --- build.gradle | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.gradle b/build.gradle index 9d054c3..11bf07b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ plugins { id "java" id "application" + id "jacoco" } java { @@ -24,6 +25,15 @@ test { testLogging { events 'passed', 'skipped', 'failed' } + finalizedBy jacocoTestReport +} + +jacoco { + toolVersion = "0.8.6" +} + +jacocoTestReport { + dependsOn test } run { -- cgit v1.2.3 From 3e6fee9561a00e5d9958c5685336c9d68c8629e1 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 27 Mar 2021 18:00:14 -0500 Subject: Used resources instead of Paths to make the generated jar work --- bin/main/.gitignore | 3 + build.gradle | 16 +- dimensionfile.txt | 18 -- metric_exceptions.txt | 19 -- .../converterGUI/UnitConverterGUI.java | 97 ++++++-- .../java/org/unitConverter/unit/UnitDatabase.java | 34 +++ src/main/resources/dimensionfile.txt | 18 ++ src/main/resources/metric_exceptions.txt | 19 ++ src/main/resources/unitsfile.txt | 267 +++++++++++++++++++++ unitsfile.txt | 267 --------------------- 10 files changed, 426 insertions(+), 332 deletions(-) delete mode 100644 dimensionfile.txt delete mode 100644 metric_exceptions.txt create mode 100644 src/main/resources/dimensionfile.txt create mode 100644 src/main/resources/metric_exceptions.txt create mode 100644 src/main/resources/unitsfile.txt delete mode 100644 unitsfile.txt diff --git a/bin/main/.gitignore b/bin/main/.gitignore index b2d0b77..e5fcaae 100644 --- a/bin/main/.gitignore +++ b/bin/main/.gitignore @@ -1,2 +1,5 @@ /about.txt /org/ +/dimensionfile.txt +/metric_exceptions.txt +/unitsfile.txt diff --git a/build.gradle b/build.gradle index 11bf07b..1a2ef44 100644 --- a/build.gradle +++ b/build.gradle @@ -20,12 +20,18 @@ dependencies { testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' } +jar { + manifest { + attributes 'Main-Class': "org.unitConverter.converterGUI.UnitConverterGUI" + } +} + test { - useJUnitPlatform() - testLogging { - events 'passed', 'skipped', 'failed' - } - finalizedBy jacocoTestReport + useJUnitPlatform() + testLogging { + events 'passed', 'skipped', 'failed' + } + finalizedBy jacocoTestReport } jacoco { diff --git a/dimensionfile.txt b/dimensionfile.txt deleted file mode 100644 index 3485de5..0000000 --- a/dimensionfile.txt +++ /dev/null @@ -1,18 +0,0 @@ -# A file for the unit dimensions in my unit converter program - -# SI Base Dimensions -# ! means "look for an existing dimension which I will load at the start" -# This is necessary because every dimension must be defined by others, and I need somewhere to start. - -# I have excluded electric current, quantity and luminous intensity since their units are exclusively SI. - -LENGTH ! -MASS ! -TIME ! -TEMPERATURE ! - -# Derived Dimensions -AREA LENGTH^2 -VOLUME LENGTH^3 -VELOCITY LENGTH / TIME -ENERGY MASS * VELOCITY^2 \ No newline at end of file diff --git a/metric_exceptions.txt b/metric_exceptions.txt deleted file mode 100644 index 73748c0..0000000 --- a/metric_exceptions.txt +++ /dev/null @@ -1,19 +0,0 @@ -# This is a list of exceptions for the one-way conversion mode -# Units in this list will be included in both From: and To: -# regardless of whether or not one-way conversion is enabled. - -tempC -tempCelsius -s -second -min -minute -h -hour -d -day -wk -week -gregorianmonth -gregorianyear -km/h \ No newline at end of file diff --git a/src/main/java/org/unitConverter/converterGUI/UnitConverterGUI.java b/src/main/java/org/unitConverter/converterGUI/UnitConverterGUI.java index c046846..ee1bcc3 100644 --- a/src/main/java/org/unitConverter/converterGUI/UnitConverterGUI.java +++ b/src/main/java/org/unitConverter/converterGUI/UnitConverterGUI.java @@ -23,6 +23,7 @@ import java.awt.GridLayout; import java.awt.event.KeyEvent; import java.io.BufferedWriter; import java.io.IOException; +import java.io.InputStream; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; @@ -36,6 +37,7 @@ import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; +import java.util.Scanner; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -93,13 +95,11 @@ final class UnitConverterGUI { /** The default place where settings are stored. */ private static final String DEFAULT_SETTINGS_FILEPATH = "settings.txt"; /** The default place where units are stored. */ - private static final Path DEFAULT_UNITS_FILE = Path.of("unitsfile.txt"); + private static final String DEFAULT_UNITS_FILEPATH = "/unitsfile.txt"; /** The default place where dimensions are stored. */ - private static final Path DEFAULT_DIMENSION_FILE = Path - .of("dimensionfile.txt"); + private static final String DEFAULT_DIMENSIONS_FILEPATH = "/dimensionfile.txt"; /** The default place where exceptions are stored. */ - private static final Path DEFAULT_EXCEPTIONS_FILE = Path - .of("metric_exceptions.txt"); + private static final String DEFAULT_EXCEPTIONS_FILEPATH = "/metric_exceptions.txt"; /** * Adds default units and dimensions to a database. @@ -130,6 +130,41 @@ final class UnitConverterGUI { database.addDimension("TEMPERATURE", SI.Dimensions.TEMPERATURE); } + /** + * Gets the text of a resource file as a set of strings (each one is one + * line of the text). + * + * @param filename filename to get resource from + * @return contents of file + * @since 2021-03-27 + */ + public static final List getLinesFromResource(String filename) { + final List lines = new ArrayList<>(); + + try (InputStream stream = inputStream(filename); + Scanner scanner = new Scanner(stream)) { + while (scanner.hasNextLine()) { + lines.add(scanner.nextLine()); + } + } catch (final IOException e) { + throw new AssertionError( + "Error occurred while loading file " + filename, e); + } + + return lines; + } + + /** + * Gets an input stream for a resource file. + * + * @param filepath file to use as resource + * @return obtained Path + * @since 2021-03-27 + */ + private static final InputStream inputStream(String filepath) { + return UnitConverterGUI.class.getResourceAsStream(filepath); + } + /** * @return {@code line} with any comments removed. * @since 2021-03-13 @@ -161,9 +196,9 @@ final class UnitConverterGUI { /** A boolean remembering whether or not one-way conversion is on */ private boolean oneWay = true; - /** The prefix rule */ private DefaultPrefixRepetitionRule prefixRule = null; + // conditions for existence of From and To entries // used for one-way conversion private final MutablePredicate fromExistenceCondition = new MutablePredicate<>( @@ -196,21 +231,44 @@ final class UnitConverterGUI { DefaultPrefixRepetitionRule.NO_RESTRICTION); Presenter.addDefaults(this.database); - this.database.loadUnitsFile(DEFAULT_UNITS_FILE); - this.database.loadDimensionFile(DEFAULT_DIMENSION_FILE); + // load units and prefixes + try (final InputStream units = inputStream(DEFAULT_UNITS_FILEPATH)) { + this.database.loadUnitsFromStream(units); + } catch (final IOException e) { + throw new AssertionError("Loading of unitsfile.txt failed.", e); + } + + // load dimensions + try (final InputStream dimensions = inputStream( + DEFAULT_DIMENSIONS_FILEPATH)) { + this.database.loadDimensionsFromStream(dimensions); + } catch (final IOException e) { + throw new AssertionError("Loading of dimensionfile.txt failed.", e); + } // load metric exceptions try { - this.metricExceptions = Files.readAllLines(DEFAULT_EXCEPTIONS_FILE) - .stream().map(Presenter::withoutComments) - .filter(s -> !s.isBlank()).collect(Collectors.toSet()); + this.metricExceptions = new HashSet<>(); + try (InputStream exceptions = inputStream( + DEFAULT_EXCEPTIONS_FILEPATH); + Scanner scanner = new Scanner(exceptions)) { + while (scanner.hasNextLine()) { + final String line = Presenter + .withoutComments(scanner.nextLine()); + if (!line.isBlank()) { + this.metricExceptions.add(line); + } + } + } } catch (final IOException e) { throw new AssertionError("Loading of metric_exceptions.txt failed.", e); } // load settings - requires database to exist - this.loadSettings(); + if (Files.exists(this.getSettingsFile())) { + this.loadSettings(); + } // a comparator that can be used to compare prefix names // any name that does not exist is less than a name that does. @@ -1139,17 +1197,10 @@ final class UnitConverterGUI { infoPanel.add(infoTextArea); // get info text - final String infoText; - try { - final Path aboutFile = Path.of("src", "main", "resources", - "about.txt"); - infoText = Files.readAllLines(aboutFile).stream() - .map(Presenter::withoutComments) - .collect(Collectors.joining("\n")); - } catch (final IOException e) { - throw new AssertionError("I/O exception loading about.txt", - e); - } + final String infoText = Presenter + .getLinesFromResource("/about.txt").stream() + .map(Presenter::withoutComments) + .collect(Collectors.joining("\n")); infoTextArea.setText(infoText); } diff --git a/src/main/java/org/unitConverter/unit/UnitDatabase.java b/src/main/java/org/unitConverter/unit/UnitDatabase.java index 000acf5..6322fef 100644 --- a/src/main/java/org/unitConverter/unit/UnitDatabase.java +++ b/src/main/java/org/unitConverter/unit/UnitDatabase.java @@ -18,6 +18,7 @@ package org.unitConverter.unit; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.math.BigDecimal; import java.nio.file.Files; import java.nio.file.Path; @@ -34,6 +35,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.Scanner; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Function; @@ -1879,6 +1881,22 @@ public final class UnitDatabase { } } + /** + * Adds all dimensions from a {@code InputStream}. Otherwise, works like + * {@link #loadDimensionFile}. + * + * @param stream stream to load from + * @since 2021-03-27 + */ + public void loadDimensionsFromStream(final InputStream stream) { + try (final Scanner scanner = new Scanner(stream)) { + long lineCounter = 0; + while (scanner.hasNextLine()) { + this.addDimensionFromLine(scanner.nextLine(), ++lineCounter); + } + } + } + /** * Adds all units from a file, using data from the database to parse them. *

    @@ -1918,6 +1936,22 @@ public final class UnitDatabase { } } + /** + * Adds all units from a {@code InputStream}. Otherwise, works like + * {@link #loadUnitsFile}. + * + * @param stream stream to load from + * @since 2021-03-27 + */ + public void loadUnitsFromStream(InputStream stream) { + try (final Scanner scanner = new Scanner(stream)) { + long lineCounter = 0; + while (scanner.hasNextLine()) { + this.addUnitOrPrefixFromLine(scanner.nextLine(), ++lineCounter); + } + } + } + /** * @return a map mapping prefix names to prefixes * @since 2019-04-13 diff --git a/src/main/resources/dimensionfile.txt b/src/main/resources/dimensionfile.txt new file mode 100644 index 0000000..3485de5 --- /dev/null +++ b/src/main/resources/dimensionfile.txt @@ -0,0 +1,18 @@ +# A file for the unit dimensions in my unit converter program + +# SI Base Dimensions +# ! means "look for an existing dimension which I will load at the start" +# This is necessary because every dimension must be defined by others, and I need somewhere to start. + +# I have excluded electric current, quantity and luminous intensity since their units are exclusively SI. + +LENGTH ! +MASS ! +TIME ! +TEMPERATURE ! + +# Derived Dimensions +AREA LENGTH^2 +VOLUME LENGTH^3 +VELOCITY LENGTH / TIME +ENERGY MASS * VELOCITY^2 \ No newline at end of file diff --git a/src/main/resources/metric_exceptions.txt b/src/main/resources/metric_exceptions.txt new file mode 100644 index 0000000..73748c0 --- /dev/null +++ b/src/main/resources/metric_exceptions.txt @@ -0,0 +1,19 @@ +# This is a list of exceptions for the one-way conversion mode +# Units in this list will be included in both From: and To: +# regardless of whether or not one-way conversion is enabled. + +tempC +tempCelsius +s +second +min +minute +h +hour +d +day +wk +week +gregorianmonth +gregorianyear +km/h \ No newline at end of file diff --git a/src/main/resources/unitsfile.txt b/src/main/resources/unitsfile.txt new file mode 100644 index 0000000..eafe885 --- /dev/null +++ b/src/main/resources/unitsfile.txt @@ -0,0 +1,267 @@ +# A file for the units in my unit converter program + +# SI Base Units +# ! means "look for an existing unit which I will load at the start" +# This is necessary because every unit must be defined by others, and I need somewhere to start. + +metre ! +kilogram ! +second ! +ampere ! +kelvin ! +mole ! +candela ! + +# Symbols and aliases for base units + +meter metre +m metre +kg kilogram +s second +A ampere +K kelvin +mol mole +cd candela + +# the bit and byte, units of information + +bit ! +b bit +byte 8 bit +B byte + +# SI prefixes + +deca- 10 +deka- deca +hecto- 100 +kilo- 1e3 +mega- 1e6 +giga- 1e9 +tera- 1e12 +peta- 1e15 +exa- 1e18 +zetta- 1e21 +yotta- 1e24 + +deci- 1e-1 +centi- 1e-2 +milli- 1e-3 +micro- 1e-6 +nano- 1e-9 +pico- 1e-12 +femto- 1e-15 +atto- 1e-18 +zepto- 1e-21 +yocto- 1e-24 + +da- deca +D- deca +h- hecto +H- hecto +k- kilo +K- kilo +M- mega +G- giga +T- tera +P- peta +E- exa +Z- zetta +Y- yotta + +d- deci +c- centi +m- milli +u- micro +n- nano +p- pico +f- femto +a- atto +z- zepto +y- yocto + +# Binary prefixes (i.e. metric but 1024 replaces 1000) + +kibi- 1024^1 +mebi- 1024^2 +gibi- 1024^3 +tebi- 1024^4 +pebi- 1024^5 +exbi- 1024^6 +Ki- kibi +Mi- mebi +Gi- gibi +Ti- tebi +Pi- pebi +Ei- exbi + +# Derived SI units +# Note: it is best to have these before any non-SI units + +newton kg m / s^2 +N newton +pascal N / m^2 +Pa pascal +joule N m +J joule +watt J/s +W watt +coulomb A s +C coulomb +volt W/A +V volt +ohm V/A +siemens A/V +S siemens +farad C/V +F farad +weber V s +Wb weber +henry V s / A +H henry +tesla Wb / m^2 +T tesla +hertz 1 / s +Hz hertz + +gram millikg +g gram + +# Angle units and constants + +# Tau is the circle constant, equal to a circle's diameter divided by its radius +tau 6.28318530717958 +# Another common circle constant +pi tau / 2 + +radian m / m +rad radian +steradian m^2 / m^2 +sr steradian +degree tau / 360 radian +deg degree +° degree + +# Nonlinear units, which are not supported by the file reader and must be defined manually +# Use tempC(100) for 100 degrees Celsius + +tempCelsius ! +tempFahrenheit ! +tempC tempCelsius +tempF tempFahrenheit + +# Common time units +minute 60 second +min minute +hour 3600 second +h hour +day 86400 second +d day +week 7 day +wk week +julianyear 365.25 day +gregorianyear 365.2425 day +gregorianmonth gregorianyear / 12 + +# Other non-SI "metric" units +litre 0.001 m^3 +liter litre +l litre +L litre +tonne 1000 kg +t tonne +are 100 m^2 +hectare hectoare +arcminute 1 / 60 degree +arcmin arcminute +arcsecond 1 / 60 arcminute +arcsec arcsecond + +# constants +waterdensity kilogram / litre + +# Imperial length units +foot 0.3048 m +ft foot +inch foot / 12 +in inch +yard 3 foot +yd yard +mile 1760 yard +mi mile + +# Compressed notation +kph km / hour +mph mile / hour + +# Imperial weight units +pound 0.45359237 kg +lb pound +ounce pound / 16 +oz ounce +stone 14 lb +UShundredweight 100 lb +UKhundredweight 8 stone +USimperialton 20 UShundredweight +UKimperialton 10 UKhundredweight + +# Imperial volume units +UKfluidounce ounce / waterdensity +UKfloz UKfluidounce +UKcup 10 UKfloz +UKpint 2 UKcup +UKquart 2 UKpint +UKgallon 4 UKquart +UKgal UKgallon + +USgallon 231 inch^3 +USgal USgallon +USquart USgallon / 4 +USpint USquart / 2 +UScup USpint / 2 +USfluidounce UScup / 8 +USfloz USfluidounce +UStablespoon USfluidounce / 2 +UStbsp UStablespoon +USteaspoon UStablespoon / 3 +UStsp USteaspoon + +# Metric versions! +# tsp = 5 mL, tbsp = 15 mL, floz = 30 mL, cup = 240 mL, pint = 480 mL, quart = 960 mL, gallon = 3840 mL +# only metrictsp, metrictbsp and metriccup are common, the rest are derived from the US formulae with 240 mL cup +metricteaspoon 5 mL +teaspoon metricteaspoon +tsp metricteaspoon +metrictablespoon 3 metricteaspoon +tablespoon metrictablespoon +tbsp metrictablespoon +metricfluidounce 2 metrictablespoon +metriccup 8 metricfluidounce +cup metriccup +metricpint 2 metriccup +pint metricpint +metricquart 2 metricpint +quart metricquart +metricgallon 4 metricquart + +# Energy units +calorie 4.18 J +cal calorie +Calorie kilocalorie +Cal Calorie +Wh W h + +# Extra units to only include in the dimension-based converter +km km +cm cm +mm mm +mg mg +mL mL +ml ml +kJ kJ +MJ MJ +kWh kWh +m/s m / s +km/h km / h +ft/s foot / s +mi/h mile / hour \ No newline at end of file diff --git a/unitsfile.txt b/unitsfile.txt deleted file mode 100644 index eafe885..0000000 --- a/unitsfile.txt +++ /dev/null @@ -1,267 +0,0 @@ -# A file for the units in my unit converter program - -# SI Base Units -# ! means "look for an existing unit which I will load at the start" -# This is necessary because every unit must be defined by others, and I need somewhere to start. - -metre ! -kilogram ! -second ! -ampere ! -kelvin ! -mole ! -candela ! - -# Symbols and aliases for base units - -meter metre -m metre -kg kilogram -s second -A ampere -K kelvin -mol mole -cd candela - -# the bit and byte, units of information - -bit ! -b bit -byte 8 bit -B byte - -# SI prefixes - -deca- 10 -deka- deca -hecto- 100 -kilo- 1e3 -mega- 1e6 -giga- 1e9 -tera- 1e12 -peta- 1e15 -exa- 1e18 -zetta- 1e21 -yotta- 1e24 - -deci- 1e-1 -centi- 1e-2 -milli- 1e-3 -micro- 1e-6 -nano- 1e-9 -pico- 1e-12 -femto- 1e-15 -atto- 1e-18 -zepto- 1e-21 -yocto- 1e-24 - -da- deca -D- deca -h- hecto -H- hecto -k- kilo -K- kilo -M- mega -G- giga -T- tera -P- peta -E- exa -Z- zetta -Y- yotta - -d- deci -c- centi -m- milli -u- micro -n- nano -p- pico -f- femto -a- atto -z- zepto -y- yocto - -# Binary prefixes (i.e. metric but 1024 replaces 1000) - -kibi- 1024^1 -mebi- 1024^2 -gibi- 1024^3 -tebi- 1024^4 -pebi- 1024^5 -exbi- 1024^6 -Ki- kibi -Mi- mebi -Gi- gibi -Ti- tebi -Pi- pebi -Ei- exbi - -# Derived SI units -# Note: it is best to have these before any non-SI units - -newton kg m / s^2 -N newton -pascal N / m^2 -Pa pascal -joule N m -J joule -watt J/s -W watt -coulomb A s -C coulomb -volt W/A -V volt -ohm V/A -siemens A/V -S siemens -farad C/V -F farad -weber V s -Wb weber -henry V s / A -H henry -tesla Wb / m^2 -T tesla -hertz 1 / s -Hz hertz - -gram millikg -g gram - -# Angle units and constants - -# Tau is the circle constant, equal to a circle's diameter divided by its radius -tau 6.28318530717958 -# Another common circle constant -pi tau / 2 - -radian m / m -rad radian -steradian m^2 / m^2 -sr steradian -degree tau / 360 radian -deg degree -° degree - -# Nonlinear units, which are not supported by the file reader and must be defined manually -# Use tempC(100) for 100 degrees Celsius - -tempCelsius ! -tempFahrenheit ! -tempC tempCelsius -tempF tempFahrenheit - -# Common time units -minute 60 second -min minute -hour 3600 second -h hour -day 86400 second -d day -week 7 day -wk week -julianyear 365.25 day -gregorianyear 365.2425 day -gregorianmonth gregorianyear / 12 - -# Other non-SI "metric" units -litre 0.001 m^3 -liter litre -l litre -L litre -tonne 1000 kg -t tonne -are 100 m^2 -hectare hectoare -arcminute 1 / 60 degree -arcmin arcminute -arcsecond 1 / 60 arcminute -arcsec arcsecond - -# constants -waterdensity kilogram / litre - -# Imperial length units -foot 0.3048 m -ft foot -inch foot / 12 -in inch -yard 3 foot -yd yard -mile 1760 yard -mi mile - -# Compressed notation -kph km / hour -mph mile / hour - -# Imperial weight units -pound 0.45359237 kg -lb pound -ounce pound / 16 -oz ounce -stone 14 lb -UShundredweight 100 lb -UKhundredweight 8 stone -USimperialton 20 UShundredweight -UKimperialton 10 UKhundredweight - -# Imperial volume units -UKfluidounce ounce / waterdensity -UKfloz UKfluidounce -UKcup 10 UKfloz -UKpint 2 UKcup -UKquart 2 UKpint -UKgallon 4 UKquart -UKgal UKgallon - -USgallon 231 inch^3 -USgal USgallon -USquart USgallon / 4 -USpint USquart / 2 -UScup USpint / 2 -USfluidounce UScup / 8 -USfloz USfluidounce -UStablespoon USfluidounce / 2 -UStbsp UStablespoon -USteaspoon UStablespoon / 3 -UStsp USteaspoon - -# Metric versions! -# tsp = 5 mL, tbsp = 15 mL, floz = 30 mL, cup = 240 mL, pint = 480 mL, quart = 960 mL, gallon = 3840 mL -# only metrictsp, metrictbsp and metriccup are common, the rest are derived from the US formulae with 240 mL cup -metricteaspoon 5 mL -teaspoon metricteaspoon -tsp metricteaspoon -metrictablespoon 3 metricteaspoon -tablespoon metrictablespoon -tbsp metrictablespoon -metricfluidounce 2 metrictablespoon -metriccup 8 metricfluidounce -cup metriccup -metricpint 2 metriccup -pint metricpint -metricquart 2 metricpint -quart metricquart -metricgallon 4 metricquart - -# Energy units -calorie 4.18 J -cal calorie -Calorie kilocalorie -Cal Calorie -Wh W h - -# Extra units to only include in the dimension-based converter -km km -cm cm -mm mm -mg mg -mL mL -ml ml -kJ kJ -MJ MJ -kWh kWh -m/s m / s -km/h km / h -ft/s foot / s -mi/h mile / hour \ No newline at end of file -- cgit v1.2.3 From 0f9a56ac310a1276dbf3b42859a2374828223879 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 27 Mar 2021 18:07:18 -0500 Subject: Fixed the gitignore file --- .gitignore | 5 +++++ settings.txt | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) delete mode 100644 settings.txt diff --git a/.gitignore b/.gitignore index 1b6985c..eb4cd1a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,8 @@ # Ignore Gradle build output directory build + +# Unit Converter gitignore files +*.class +*~ +settings.txt \ No newline at end of file diff --git a/settings.txt b/settings.txt deleted file mode 100644 index 6a9d120..0000000 --- a/settings.txt +++ /dev/null @@ -1,4 +0,0 @@ -precision=6 -rounding_type=SCIENTIFIC -prefix_rule=COMPLEX_REPETITION -one_way=true -- cgit v1.2.3