From 761ba0b6627df8bc9f6ab41c94f349c84d378609 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 3 Oct 2020 12:01:34 -0500 Subject: Added extra prefixed units to the SI class. --- src/org/unitConverter/unit/SI.java | 50 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/org/unitConverter/unit/SI.java b/src/org/unitConverter/unit/SI.java index 1a9eaf1..0a1bb9b 100644 --- a/src/org/unitConverter/unit/SI.java +++ b/src/org/unitConverter/unit/SI.java @@ -262,6 +262,56 @@ public final class SI { 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); // You may NOT get SI instances! private SI() { throw new AssertionError(); -- cgit v1.2.3 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.
-
-
-
    -
  • -

    Overview

    -

    The Overview page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.

    -
  • -
  • -

    Package

    -

    Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain six categories:

    -
      -
    • Interfaces (italic)
    • -
    • Classes
    • -
    • Enums
    • -
    • Exceptions
    • -
    • Errors
    • -
    • Annotation Types
    • -
    -
  • -
  • -

    Class/Interface

    -

    Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:

    -
      -
    • Class inheritance diagram
    • -
    • Direct Subclasses
    • -
    • All Known Subinterfaces
    • -
    • All Known Implementing Classes
    • -
    • Class/interface declaration
    • -
    • Class/interface description
    • -
    -
      -
    • Nested Class Summary
    • -
    • Field Summary
    • -
    • Constructor Summary
    • -
    • Method Summary
    • -
    -
      -
    • Field Detail
    • -
    • Constructor Detail
    • -
    • Method Detail
    • -
    -

    Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.

    -
  • -
  • -

    Annotation Type

    -

    Each annotation type has its own separate page with the following sections:

    -
      -
    • Annotation Type declaration
    • -
    • Annotation Type description
    • -
    • Required Element Summary
    • -
    • Optional Element Summary
    • -
    • Element Detail
    • -
    -
  • -
  • -

    Enum

    -

    Each enum has its own separate page with the following sections:

    -
      -
    • Enum declaration
    • -
    • Enum description
    • -
    • Enum Constant Summary
    • -
    • Enum Constant Detail
    • -
    -
  • -
  • -

    Use

    -

    Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its Use page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.

    -
  • -
  • -

    Tree (Class Hierarchy)

    -

    There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.

    -
      -
    • When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
    • -
    • When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
    • -
    -
  • -
  • -

    Deprecated API

    -

    The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.

    -
  • -
  • -

    Index

    -

    The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.

    -
  • -
  • -

    Prev/Next

    -

    These links take you to the next or previous class, interface, package, or related page.

    -
  • -
  • -

    Frames/No Frames

    -

    These links show and hide the HTML frames. All pages are available with or without frames.

    -
  • -
  • -

    All Classes

    -

    The All Classes link shows all classes and interfaces except non-static nested types.

    -
  • -
  • -

    Serialized Form

    -

    Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.

    -
  • -
  • -

    Constant Field Values

    -

    The Constant Field Values page lists the static final fields and their values.

    -
  • -
-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 From 277500e27010839e03659870bc5890f1535aa8c8 Mon Sep 17 00:00:00 2001 From: Adrien Hopkins Date: Sat, 22 May 2021 14:03:45 -0500 Subject: Gradle changes --- bin/.gitignore | 2 ++ bin/main/.gitignore | 5 ----- bin/test/.gitignore | 1 - build.gradle | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) create mode 100644 bin/.gitignore delete mode 100644 bin/main/.gitignore delete mode 100644 bin/test/.gitignore diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000..7eed456 --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1,2 @@ +/main/ +/test/ diff --git a/bin/main/.gitignore b/bin/main/.gitignore deleted file mode 100644 index e5fcaae..0000000 --- a/bin/main/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/about.txt -/org/ -/dimensionfile.txt -/metric_exceptions.txt -/unitsfile.txt diff --git a/bin/test/.gitignore b/bin/test/.gitignore deleted file mode 100644 index cf1db2e..0000000 --- a/bin/test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/org/ diff --git a/build.gradle b/build.gradle index 1a2ef44..2922695 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ dependencies { jar { manifest { - attributes 'Main-Class': "org.unitConverter.converterGUI.UnitConverterGUI" + attributes 'Main-Class': mainClassName } } -- cgit v1.2.3