From a2056b72692febf796b314dc0ce88aa46ca8a632 Mon Sep 17 00:00:00 2001
From: Seokhyun Lee <7948302+henrylee97@users.noreply.github.com>
Date: Fri, 1 Dec 2023 02:14:33 +0900
Subject: [PATCH] refactor(java): commons-lang A-classes (#132)
refactor(java): commons-lang ArrayUtils
---
Java-base/commons-lang/Dockerfile | 28 +
Java-base/commons-lang/run.sh | 1 +
Java-base/commons-lang/src/.travis.yml | 25 +
Java-base/commons-lang/src/CONTRIBUTING.md | 97 +
Java-base/commons-lang/src/LICENSE.txt | 202 +
Java-base/commons-lang/src/NOTICE.txt | 8 +
Java-base/commons-lang/src/README.md | 106 +
Java-base/commons-lang/src/RELEASE-NOTES.txt | 922 ++
Java-base/commons-lang/src/checkstyle.xml | 46 +
.../src/findbugs-exclude-filter.xml | 157 +
Java-base/commons-lang/src/pom.xml | 812 ++
.../commons-lang/src/src/assembly/bin.xml | 46 +
.../commons-lang/src/src/assembly/src.xml | 43 +
.../commons-lang/src/src/changes/changes.xml | 911 ++
.../src/src/changes/release-notes.vm | 140 +
.../apache/commons/lang3/AnnotationUtils.java | 370 +
.../org/apache/commons/lang3/ArrayUtils.java | 7970 +++++++++++++++
.../org/apache/commons/lang3/BitField.java | 322 +
.../apache/commons/lang3/BooleanUtils.java | 1104 +++
.../apache/commons/lang3/CharEncoding.java | 103 +
.../org/apache/commons/lang3/CharRange.java | 359 +
.../commons/lang3/CharSequenceUtils.java | 229 +
.../org/apache/commons/lang3/CharSet.java | 295 +
.../apache/commons/lang3/CharSetUtils.java | 263 +
.../org/apache/commons/lang3/CharUtils.java | 552 ++
.../apache/commons/lang3/ClassPathUtils.java | 130 +
.../org/apache/commons/lang3/ClassUtils.java | 1334 +++
.../org/apache/commons/lang3/Conversion.java | 1565 +++
.../org/apache/commons/lang3/EnumUtils.java | 310 +
.../org/apache/commons/lang3/JavaVersion.java | 229 +
.../org/apache/commons/lang3/LocaleUtils.java | 327 +
.../lang3/NotImplementedException.java | 127 +
.../org/apache/commons/lang3/ObjectUtils.java | 1016 ++
.../commons/lang3/RandomStringUtils.java | 455 +
.../org/apache/commons/lang3/RandomUtils.java | 227 +
.../java/org/apache/commons/lang3/Range.java | 487 +
.../commons/lang3/SerializationException.java | 77 +
.../commons/lang3/SerializationUtils.java | 339 +
.../commons/lang3/StringEscapeUtils.java | 804 ++
.../org/apache/commons/lang3/StringUtils.java | 8822 +++++++++++++++++
.../org/apache/commons/lang3/SystemUtils.java | 1724 ++++
.../org/apache/commons/lang3/ThreadUtils.java | 460 +
.../org/apache/commons/lang3/Validate.java | 1342 +++
.../apache/commons/lang3/builder/Builder.java | 88 +
.../lang3/builder/CompareToBuilder.java | 1033 ++
.../apache/commons/lang3/builder/Diff.java | 117 +
.../commons/lang3/builder/DiffBuilder.java | 1022 ++
.../commons/lang3/builder/DiffResult.java | 207 +
.../commons/lang3/builder/Diffable.java | 53 +
.../commons/lang3/builder/EqualsBuilder.java | 973 ++
.../commons/lang3/builder/EqualsExclude.java | 36 +
.../lang3/builder/HashCodeBuilder.java | 996 ++
.../lang3/builder/HashCodeExclude.java | 36 +
.../apache/commons/lang3/builder/IDKey.java | 72 +
.../MultilineRecursiveToStringStyle.java | 219 +
.../lang3/builder/RecursiveToStringStyle.java | 99 +
.../builder/ReflectionToStringBuilder.java | 719 ++
.../lang3/builder/StandardToStringStyle.java | 559 ++
.../lang3/builder/ToStringBuilder.java | 1079 ++
.../lang3/builder/ToStringExclude.java | 35 +
.../commons/lang3/builder/ToStringStyle.java | 2641 +++++
.../commons/lang3/builder/package-info.java | 33 +
.../concurrent/AbstractCircuitBreaker.java | 165 +
.../lang3/concurrent/AtomicInitializer.java | 106 +
.../concurrent/AtomicSafeInitializer.java | 96 +
.../concurrent/BackgroundInitializer.java | 334 +
.../lang3/concurrent/BasicThreadFactory.java | 381 +
.../CallableBackgroundInitializer.java | 125 +
.../lang3/concurrent/CircuitBreaker.java | 94 +
.../concurrent/CircuitBreakingException.java | 67 +
.../lang3/concurrent/ConcurrentException.java | 69 +
.../concurrent/ConcurrentInitializer.java | 53 +
.../ConcurrentRuntimeException.java | 71 +
.../lang3/concurrent/ConcurrentUtils.java | 392 +
.../lang3/concurrent/ConstantInitializer.java | 129 +
.../concurrent/EventCountCircuitBreaker.java | 568 ++
.../lang3/concurrent/LazyInitializer.java | 121 +
.../MultiBackgroundInitializer.java | 351 +
.../concurrent/ThresholdCircuitBreaker.java | 128 +
.../lang3/concurrent/TimedSemaphore.java | 470 +
.../lang3/concurrent/package-info.java | 438 +
.../lang3/event/EventListenerSupport.java | 340 +
.../commons/lang3/event/EventUtils.java | 129 +
.../commons/lang3/event/package-info.java | 22 +
.../lang3/exception/CloneFailedException.java | 62 +
.../lang3/exception/ContextedException.java | 256 +
.../exception/ContextedRuntimeException.java | 257 +
.../exception/DefaultExceptionContext.java | 165 +
.../lang3/exception/ExceptionContext.java | 103 +
.../lang3/exception/ExceptionUtils.java | 824 ++
.../commons/lang3/exception/package-info.java | 26 +
.../apache/commons/lang3/math/Fraction.java | 939 ++
.../commons/lang3/math/IEEE754rUtils.java | 267 +
.../commons/lang3/math/NumberUtils.java | 1633 +++
.../commons/lang3/math/package-info.java | 33 +
.../apache/commons/lang3/mutable/Mutable.java | 53 +
.../commons/lang3/mutable/MutableBoolean.java | 214 +
.../commons/lang3/mutable/MutableByte.java | 392 +
.../commons/lang3/mutable/MutableDouble.java | 419 +
.../commons/lang3/mutable/MutableFloat.java | 420 +
.../commons/lang3/mutable/MutableInt.java | 382 +
.../commons/lang3/mutable/MutableLong.java | 382 +
.../commons/lang3/mutable/MutableObject.java | 127 +
.../commons/lang3/mutable/MutableShort.java | 392 +
.../commons/lang3/mutable/package-info.java | 24 +
.../apache/commons/lang3/package-info.java | 124 +
.../lang3/reflect/ConstructorUtils.java | 301 +
.../commons/lang3/reflect/FieldUtils.java | 839 ++
.../lang3/reflect/InheritanceUtils.java | 67 +
.../commons/lang3/reflect/MemberUtils.java | 304 +
.../commons/lang3/reflect/MethodUtils.java | 872 ++
.../commons/lang3/reflect/TypeLiteral.java | 123 +
.../commons/lang3/reflect/TypeUtils.java | 1851 ++++
.../apache/commons/lang3/reflect/Typed.java | 34 +
.../commons/lang3/reflect/package-info.java | 23 +
.../commons/lang3/text/CompositeFormat.java | 114 +
.../lang3/text/ExtendedMessageFormat.java | 528 +
.../commons/lang3/text/FormatFactory.java | 41 +
.../commons/lang3/text/FormattableUtils.java | 150 +
.../apache/commons/lang3/text/StrBuilder.java | 3127 ++++++
.../apache/commons/lang3/text/StrLookup.java | 180 +
.../apache/commons/lang3/text/StrMatcher.java | 441 +
.../commons/lang3/text/StrSubstitutor.java | 1230 +++
.../commons/lang3/text/StrTokenizer.java | 1113 +++
.../apache/commons/lang3/text/WordUtils.java | 737 ++
.../commons/lang3/text/package-info.java | 27 +
.../text/translate/AggregateTranslator.java | 59 +
.../translate/CharSequenceTranslator.java | 135 +
.../text/translate/CodePointTranslator.java | 51 +
.../lang3/text/translate/EntityArrays.java | 424 +
.../text/translate/JavaUnicodeEscaper.java | 113 +
.../text/translate/LookupTranslator.java | 91 +
.../text/translate/NumericEntityEscaper.java | 118 +
.../translate/NumericEntityUnescaper.java | 138 +
.../lang3/text/translate/OctalUnescaper.java | 79 +
.../lang3/text/translate/UnicodeEscaper.java | 138 +
.../text/translate/UnicodeUnescaper.java | 64 +
.../UnicodeUnpairedSurrogateRemover.java | 40 +
.../lang3/text/translate/package-info.java | 24 +
.../lang3/time/CalendarReflection.java | 99 +
.../commons/lang3/time/DateFormatUtils.java | 407 +
.../apache/commons/lang3/time/DateParser.java | 127 +
.../commons/lang3/time/DatePrinter.java | 178 +
.../apache/commons/lang3/time/DateUtils.java | 1855 ++++
.../lang3/time/DurationFormatUtils.java | 691 ++
.../commons/lang3/time/FastDateFormat.java | 671 ++
.../commons/lang3/time/FastDateParser.java | 988 ++
.../commons/lang3/time/FastDatePrinter.java | 1572 +++
.../commons/lang3/time/FormatCache.java | 265 +
.../apache/commons/lang3/time/StopWatch.java | 514 +
.../commons/lang3/time/package-info.java | 28 +
.../commons/lang3/tuple/ImmutablePair.java | 103 +
.../commons/lang3/tuple/ImmutableTriple.java | 104 +
.../commons/lang3/tuple/MutablePair.java | 123 +
.../commons/lang3/tuple/MutableTriple.java | 133 +
.../org/apache/commons/lang3/tuple/Pair.java | 179 +
.../apache/commons/lang3/tuple/Triple.java | 160 +
.../commons/lang3/tuple/package-info.java | 22 +
Java-base/commons-lang/src/src/media/logo.xcf | Bin 0 -> 19992 bytes
.../src/src/site/resources/.htaccess | 1 +
.../src/src/site/resources/download_lang.cgi | 4 +
.../src/src/site/resources/images/logo.png | Bin 0 -> 11862 bytes
.../resources/lang2-lang3-clirr-report.html | 265 +
.../src/src/site/resources/profile.cobertura | 0
.../release-notes/RELEASE-NOTES-1.0.1.txt | 48 +
.../release-notes/RELEASE-NOTES-1.0.txt | 146 +
.../release-notes/RELEASE-NOTES-2.0.txt | 661 ++
.../release-notes/RELEASE-NOTES-2.1.txt | 135 +
.../release-notes/RELEASE-NOTES-2.2.txt | 112 +
.../release-notes/RELEASE-NOTES-2.3.txt | 90 +
.../release-notes/RELEASE-NOTES-2.4.txt | 124 +
.../release-notes/RELEASE-NOTES-2.5.txt | 83 +
.../release-notes/RELEASE-NOTES-2.6.txt | 59 +
.../release-notes/RELEASE-NOTES-3.0.1.txt | 42 +
.../release-notes/RELEASE-NOTES-3.0.txt | 155 +
.../release-notes/RELEASE-NOTES-3.1.txt | 40 +
.../release-notes/RELEASE-NOTES-3.2.1.txt | 418 +
.../release-notes/RELEASE-NOTES-3.2.txt | 406 +
.../release-notes/RELEASE-NOTES-3.3.1.txt | 479 +
.../release-notes/RELEASE-NOTES-3.3.2.txt | 492 +
.../release-notes/RELEASE-NOTES-3.3.txt | 483 +
.../release-notes/RELEASE-NOTES-3.4.txt | 625 ++
Java-base/commons-lang/src/src/site/site.xml | 46 +
.../src/src/site/xdoc/article2_4.xml | 195 +
.../src/src/site/xdoc/article2_5.xml | 135 +
.../src/src/site/xdoc/article3_0.xml | 208 +
.../src/src/site/xdoc/building.xml | 73 +
.../src/src/site/xdoc/developerguide.xml | 151 +
.../src/src/site/xdoc/download_lang.xml | 184 +
.../commons-lang/src/src/site/xdoc/index.xml | 117 +
.../src/src/site/xdoc/issue-tracking.xml | 102 +
.../src/src/site/xdoc/mail-lists.xml | 202 +
.../src/src/site/xdoc/proposal.xml | 97 +
.../src/src/site/xdoc/release-history.xml | 113 +
.../src/src/site/xdoc/upgradeto2_0.xml | 688 ++
.../src/src/site/xdoc/upgradeto2_1.xml | 163 +
.../src/src/site/xdoc/upgradeto2_2.xml | 110 +
.../src/src/site/xdoc/upgradeto2_3.xml | 118 +
.../src/src/site/xdoc/upgradeto2_4.xml | 153 +
.../src/src/site/xdoc/upgradeto2_5.xml | 105 +
.../src/src/site/xdoc/upgradeto2_6.xml | 87 +
.../src/src/site/xdoc/upgradeto3_0.xml | 172 +
.../src/src/site/xdoc/userguide.xml | 34 +
.../commons/lang3/AnnotationUtilsTest.java | 507 +
.../commons/lang3/ArrayUtilsAddTest.java | 610 ++
.../lang3/ArrayUtilsRemoveMultipleTest.java | 1051 ++
.../commons/lang3/ArrayUtilsRemoveTest.java | 674 ++
.../apache/commons/lang3/ArrayUtilsTest.java | 4444 +++++++++
.../apache/commons/lang3/BitFieldTest.java | 259 +
.../commons/lang3/BooleanUtilsTest.java | 1016 ++
.../commons/lang3/CharEncodingTest.java | 70 +
.../apache/commons/lang3/CharRangeTest.java | 400 +
.../commons/lang3/CharSequenceUtilsTest.java | 185 +
.../org/apache/commons/lang3/CharSetTest.java | 477 +
.../commons/lang3/CharSetUtilsTest.java | 252 +
.../commons/lang3/CharUtilsPerfRun.java | 161 +
.../apache/commons/lang3/CharUtilsTest.java | 363 +
.../commons/lang3/ClassPathUtilsTest.java | 114 +
.../apache/commons/lang3/ClassUtilsTest.java | 1275 +++
.../apache/commons/lang3/ConversionTest.java | 1822 ++++
.../apache/commons/lang3/EnumUtilsTest.java | 427 +
.../commons/lang3/HashSetvBitSetTest.java | 174 +
.../apache/commons/lang3/JavaVersionTest.java | 75 +
.../apache/commons/lang3/LocaleUtilsTest.java | 590 ++
.../lang3/NotImplementedExceptionTest.java | 54 +
.../apache/commons/lang3/ObjectUtilsTest.java | 712 ++
.../commons/lang3/RandomStringUtilsTest.java | 529 +
.../apache/commons/lang3/RandomUtilsTest.java | 241 +
.../org/apache/commons/lang3/RangeTest.java | 394 +
.../commons/lang3/SerializationUtilsTest.java | 433 +
.../commons/lang3/StringEscapeUtilsTest.java | 616 ++
.../lang3/StringUtilsContainsTest.java | 477 +
.../lang3/StringUtilsEmptyBlankTest.java | 114 +
.../lang3/StringUtilsEqualsIndexOfTest.java | 768 ++
.../commons/lang3/StringUtilsIsTest.java | 173 +
.../lang3/StringUtilsStartsEndsWithTest.java | 199 +
.../lang3/StringUtilsSubstringTest.java | 331 +
.../apache/commons/lang3/StringUtilsTest.java | 3035 ++++++
.../lang3/StringUtilsTrimStripTest.java | 239 +
.../apache/commons/lang3/SystemUtilsTest.java | 521 +
.../apache/commons/lang3/ThreadUtilsTest.java | 370 +
.../apache/commons/lang3/ValidateTest.java | 1179 +++
.../lang3/builder/CompareToBuilderTest.java | 1165 +++
.../builder/DefaultToStringStyleTest.java | 129 +
.../lang3/builder/DiffBuilderTest.java | 508 +
.../commons/lang3/builder/DiffResultTest.java | 147 +
.../commons/lang3/builder/DiffTest.java | 70 +
.../lang3/builder/EqualsBuilderTest.java | 1184 +++
.../HashCodeBuilderAndEqualsBuilderTest.java | 138 +
.../lang3/builder/HashCodeBuilderTest.java | 613 ++
.../lang3/builder/JsonToStringStyleTest.java | 376 +
.../builder/MultiLineToStringStyleTest.java | 130 +
.../MultilineRecursiveToStringStyleTest.java | 263 +
.../builder/NoClassNameToStringStyleTest.java | 127 +
.../NoFieldNamesToStringStyleTest.java | 129 +
.../builder/RecursiveToStringStyleTest.java | 161 +
...lectionToStringBuilderConcurrencyTest.java | 121 +
.../ReflectionToStringBuilderExcludeTest.java | 136 +
...tringBuilderExcludeWithAnnotationTest.java | 57 +
...ngBuilderMutateInspectConcurrencyTest.java | 107 +
.../ReflectionToStringBuilderTest.java | 28 +
.../builder/ShortPrefixToStringStyleTest.java | 129 +
.../builder/SimpleToStringStyleTest.java | 127 +
.../builder/StandardToStringStyleTest.java | 144 +
.../lang3/builder/ToStringBuilderTest.java | 1048 ++
.../builder/ToStringStyleConcurrencyTest.java | 112 +
.../lang3/builder/ToStringStyleTest.java | 138 +
.../AbstractConcurrentInitializerTest.java | 120 +
.../concurrent/AtomicInitializerTest.java | 37 +
.../concurrent/AtomicSafeInitializerTest.java | 79 +
.../concurrent/BackgroundInitializerTest.java | 319 +
.../concurrent/BasicThreadFactoryTest.java | 300 +
.../CallableBackgroundInitializerTest.java | 105 +
.../lang3/concurrent/ConcurrentUtilsTest.java | 581 ++
.../concurrent/ConstantInitializerTest.java | 133 +
.../EventCountCircuitBreakerTest.java | 401 +
.../lang3/concurrent/LazyInitializerTest.java | 56 +
.../MultiBackgroundInitializerTest.java | 412 +
.../ThresholdCircuitBreakerTest.java | 87 +
.../lang3/concurrent/TimedSemaphoreTest.java | 565 ++
.../lang3/event/EventListenerSupportTest.java | 231 +
.../commons/lang3/event/EventUtilsTest.java | 280 +
.../AbstractExceptionContextTest.java | 187 +
.../exception/ContextedExceptionTest.java | 110 +
.../ContextedRuntimeExceptionTest.java | 114 +
.../DefaultExceptionContextTest.java | 40 +
.../lang3/exception/ExceptionUtilsTest.java | 626 ++
.../commons/lang3/math/FractionTest.java | 1367 +++
.../commons/lang3/math/IEEE754rUtilsTest.java | 105 +
.../commons/lang3/math/NumberUtilsTest.java | 1554 +++
.../lang3/mutable/MutableBooleanTest.java | 140 +
.../lang3/mutable/MutableByteTest.java | 269 +
.../lang3/mutable/MutableDoubleTest.java | 281 +
.../lang3/mutable/MutableFloatTest.java | 281 +
.../commons/lang3/mutable/MutableIntTest.java | 279 +
.../lang3/mutable/MutableLongTest.java | 273 +
.../lang3/mutable/MutableObjectTest.java | 96 +
.../lang3/mutable/MutableShortTest.java | 264 +
.../lang3/reflect/ConstructorUtilsTest.java | 293 +
.../commons/lang3/reflect/FieldUtilsTest.java | 1355 +++
.../lang3/reflect/InheritanceUtilsTest.java | 79 +
.../lang3/reflect/MethodUtilsTest.java | 792 ++
.../lang3/reflect/TypeLiteralTest.java | 56 +
.../commons/lang3/reflect/TypeUtilsTest.java | 841 ++
.../commons/lang3/reflect/testbed/Ambig.java | 26 +
.../lang3/reflect/testbed/Annotated.java | 28 +
.../lang3/reflect/testbed/AnotherChild.java | 23 +
.../lang3/reflect/testbed/AnotherParent.java | 23 +
.../commons/lang3/reflect/testbed/Bar.java | 25 +
.../commons/lang3/reflect/testbed/Foo.java | 25 +
.../reflect/testbed/GenericConsumer.java | 21 +
.../lang3/reflect/testbed/GenericParent.java | 28 +
.../reflect/testbed/GenericTypeHolder.java | 29 +
.../lang3/reflect/testbed/Grandchild.java | 23 +
.../commons/lang3/reflect/testbed/Parent.java | 31 +
.../testbed/PrivatelyShadowedChild.java | 27 +
.../lang3/reflect/testbed/PublicChild.java | 23 +
.../testbed/PubliclyShadowedChild.java | 26 +
.../reflect/testbed/StaticContainer.java | 58 +
.../reflect/testbed/StaticContainerChild.java | 23 +
.../testbed/StringParameterizedChild.java | 27 +
.../test/NotVisibleExceptionFactory.java | 52 +
.../commons/lang3/test/SystemDefaults.java | 40 +
.../lang3/test/SystemDefaultsSwitch.java | 113 +
.../lang3/test/SystemDefaultsSwitchTest.java | 88 +
.../lang3/text/CompositeFormatTest.java | 85 +
.../lang3/text/ExtendedMessageFormatTest.java | 484 +
.../lang3/text/FormattableUtilsTest.java | 115 +
.../text/StrBuilderAppendInsertTest.java | 1607 +++
.../commons/lang3/text/StrBuilderTest.java | 2005 ++++
.../commons/lang3/text/StrLookupTest.java | 116 +
.../commons/lang3/text/StrMatcherTest.java | 215 +
.../lang3/text/StrSubstitutorTest.java | 740 ++
.../commons/lang3/text/StrTokenizerTest.java | 879 ++
.../commons/lang3/text/WordUtilsTest.java | 421 +
.../text/translate/EntityArraysTest.java | 72 +
.../text/translate/LookupTranslatorTest.java | 51 +
.../translate/NumericEntityEscaperTest.java | 68 +
.../translate/NumericEntityUnescaperTest.java | 80 +
.../text/translate/OctalUnescaperTest.java | 81 +
.../text/translate/UnicodeEscaperTest.java | 55 +
.../text/translate/UnicodeUnescaperTest.java | 60 +
.../UnicodeUnpairedSurrogateRemoverTest.java | 46 +
.../lang3/time/DateFormatUtilsTest.java | 274 +
.../lang3/time/DateUtilsFragmentTest.java | 592 ++
.../lang3/time/DateUtilsRoundingTest.java | 727 ++
.../commons/lang3/time/DateUtilsTest.java | 1747 ++++
.../lang3/time/DurationFormatUtilsTest.java | 631 ++
.../lang3/time/FastDateFormatTest.java | 328 +
.../lang3/time/FastDateFormat_ParserTest.java | 33 +
.../time/FastDateFormat_PrinterTest.java | 33 +
.../lang3/time/FastDateParserSDFTest.java | 230 +
.../lang3/time/FastDateParserTest.java | 720 ++
.../time/FastDateParser_MoreOrLessTest.java | 113 +
.../FastDateParser_TimeZoneStrategyTest.java | 66 +
.../lang3/time/FastDatePrinterTest.java | 438 +
.../time/FastDatePrinterTimeZonesTest.java | 64 +
.../commons/lang3/time/StopWatchTest.java | 303 +
.../commons/lang3/time/WeekYearTest.java | 90 +
.../lang3/tuple/ImmutablePairTest.java | 100 +
.../lang3/tuple/ImmutableTripleTest.java | 112 +
.../commons/lang3/tuple/MutablePairTest.java | 108 +
.../lang3/tuple/MutableTripleTest.java | 120 +
.../apache/commons/lang3/tuple/PairTest.java | 119 +
.../commons/lang3/tuple/TripleTest.java | 125 +
.../src/src/test/resources/java.policy | 377 +
.../src/src/test/resources/lang-708-input.txt | 1 +
Java/commons-lang-ArrayUtils_1021/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1021/buggy.java | 7992 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1021/npe.json | 7 +
Java/commons-lang-ArrayUtils_1061/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1061/buggy.java | 7992 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1061/npe.json | 7 +
Java/commons-lang-ArrayUtils_1101/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1101/buggy.java | 7992 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1101/npe.json | 7 +
Java/commons-lang-ArrayUtils_1141/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1141/buggy.java | 7992 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1141/npe.json | 7 +
Java/commons-lang-ArrayUtils_1181/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1181/buggy.java | 7992 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1181/npe.json | 7 +
Java/commons-lang-ArrayUtils_1221/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1221/buggy.java | 7992 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1221/npe.json | 7 +
Java/commons-lang-ArrayUtils_1383/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1383/buggy.java | 7993 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1383/npe.json | 7 +
Java/commons-lang-ArrayUtils_1417/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1417/buggy.java | 7982 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1417/npe.json | 7 +
Java/commons-lang-ArrayUtils_1431/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1431/buggy.java | 7978 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1431/npe.json | 7 +
Java/commons-lang-ArrayUtils_1445/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1445/buggy.java | 7978 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1445/npe.json | 7 +
Java/commons-lang-ArrayUtils_1459/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1459/buggy.java | 7978 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1459/npe.json | 7 +
Java/commons-lang-ArrayUtils_1473/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1473/buggy.java | 7978 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1473/npe.json | 7 +
Java/commons-lang-ArrayUtils_1487/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1487/buggy.java | 7978 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1487/npe.json | 7 +
Java/commons-lang-ArrayUtils_1501/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1501/buggy.java | 7978 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1501/npe.json | 7 +
Java/commons-lang-ArrayUtils_1515/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1515/buggy.java | 7978 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1515/npe.json | 7 +
Java/commons-lang-ArrayUtils_1529/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1529/buggy.java | 7978 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1529/npe.json | 7 +
Java/commons-lang-ArrayUtils_1553/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1553/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1553/npe.json | 7 +
Java/commons-lang-ArrayUtils_1586/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1586/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1586/npe.json | 7 +
Java/commons-lang-ArrayUtils_1619/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1619/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1619/npe.json | 7 +
Java/commons-lang-ArrayUtils_1652/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1652/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1652/npe.json | 7 +
Java/commons-lang-ArrayUtils_1685/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1685/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1685/npe.json | 7 +
Java/commons-lang-ArrayUtils_1718/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1718/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1718/npe.json | 7 +
Java/commons-lang-ArrayUtils_1751/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1751/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1751/npe.json | 7 +
Java/commons-lang-ArrayUtils_176/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_176/buggy.java | 7984 +++++++++++++++
.../commons-lang-ArrayUtils_176/metadata.json | 21 +
Java/commons-lang-ArrayUtils_176/npe.json | 7 +
Java/commons-lang-ArrayUtils_1784/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1784/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1784/npe.json | 7 +
Java/commons-lang-ArrayUtils_1817/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_1817/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_1817/npe.json | 7 +
Java/commons-lang-ArrayUtils_239/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_239/buggy.java | 7996 +++++++++++++++
.../commons-lang-ArrayUtils_239/metadata.json | 21 +
Java/commons-lang-ArrayUtils_239/npe.json | 7 +
Java/commons-lang-ArrayUtils_3216/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3216/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3216/npe.json | 7 +
Java/commons-lang-ArrayUtils_3222/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3222/buggy.java | 7982 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3222/npe.json | 7 +
Java/commons-lang-ArrayUtils_324/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_324/buggy.java | 7987 +++++++++++++++
.../commons-lang-ArrayUtils_324/metadata.json | 21 +
Java/commons-lang-ArrayUtils_324/npe.json | 7 +
Java/commons-lang-ArrayUtils_3267/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3267/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3267/npe.json | 7 +
Java/commons-lang-ArrayUtils_3275/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3275/buggy.java | 7984 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3275/npe.json | 7 +
Java/commons-lang-ArrayUtils_3335/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3335/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3335/npe.json | 7 +
Java/commons-lang-ArrayUtils_3378/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3378/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3378/npe.json | 7 +
Java/commons-lang-ArrayUtils_340/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_340/buggy.java | 7980 +++++++++++++++
.../commons-lang-ArrayUtils_340/metadata.json | 21 +
Java/commons-lang-ArrayUtils_340/npe.json | 7 +
Java/commons-lang-ArrayUtils_3438/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3438/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3438/npe.json | 7 +
Java/commons-lang-ArrayUtils_3481/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3481/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3481/npe.json | 7 +
Java/commons-lang-ArrayUtils_3541/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3541/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3541/npe.json | 7 +
Java/commons-lang-ArrayUtils_356/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_356/buggy.java | 7980 +++++++++++++++
.../commons-lang-ArrayUtils_356/metadata.json | 21 +
Java/commons-lang-ArrayUtils_356/npe.json | 7 +
Java/commons-lang-ArrayUtils_3584/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3584/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3584/npe.json | 7 +
Java/commons-lang-ArrayUtils_3646/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3646/buggy.java | 7988 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3646/npe.json | 7 +
Java/commons-lang-ArrayUtils_3691/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3691/buggy.java | 7988 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3691/npe.json | 7 +
Java/commons-lang-ArrayUtils_372/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_372/buggy.java | 7980 +++++++++++++++
.../commons-lang-ArrayUtils_372/metadata.json | 21 +
Java/commons-lang-ArrayUtils_372/npe.json | 7 +
Java/commons-lang-ArrayUtils_3752/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3752/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3752/npe.json | 7 +
Java/commons-lang-ArrayUtils_3795/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_3795/buggy.java | 7987 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_3795/npe.json | 7 +
Java/commons-lang-ArrayUtils_388/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_388/buggy.java | 7980 +++++++++++++++
.../commons-lang-ArrayUtils_388/metadata.json | 21 +
Java/commons-lang-ArrayUtils_388/npe.json | 7 +
Java/commons-lang-ArrayUtils_404/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_404/buggy.java | 7980 +++++++++++++++
.../commons-lang-ArrayUtils_404/metadata.json | 21 +
Java/commons-lang-ArrayUtils_404/npe.json | 7 +
Java/commons-lang-ArrayUtils_420/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_420/buggy.java | 7980 +++++++++++++++
.../commons-lang-ArrayUtils_420/metadata.json | 21 +
Java/commons-lang-ArrayUtils_420/npe.json | 7 +
Java/commons-lang-ArrayUtils_4271/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4271/buggy.java | 7986 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4271/npe.json | 7 +
Java/commons-lang-ArrayUtils_4293/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4293/buggy.java | 7981 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4293/npe.json | 7 +
Java/commons-lang-ArrayUtils_4301/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4301/buggy.java | 7982 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4301/npe.json | 7 +
Java/commons-lang-ArrayUtils_4315/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4315/buggy.java | 7980 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4315/npe.json | 7 +
Java/commons-lang-ArrayUtils_4339/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4339/buggy.java | 7984 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4339/npe.json | 7 +
Java/commons-lang-ArrayUtils_436/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_436/buggy.java | 7980 +++++++++++++++
.../commons-lang-ArrayUtils_436/metadata.json | 21 +
Java/commons-lang-ArrayUtils_436/npe.json | 7 +
Java/commons-lang-ArrayUtils_4361/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4361/buggy.java | 7981 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4361/npe.json | 7 +
Java/commons-lang-ArrayUtils_4369/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4369/buggy.java | 7982 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4369/npe.json | 7 +
Java/commons-lang-ArrayUtils_4383/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4383/buggy.java | 7980 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4383/npe.json | 7 +
Java/commons-lang-ArrayUtils_4407/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4407/buggy.java | 7984 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4407/npe.json | 7 +
Java/commons-lang-ArrayUtils_4429/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4429/buggy.java | 7981 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4429/npe.json | 7 +
Java/commons-lang-ArrayUtils_4437/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4437/buggy.java | 7982 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4437/npe.json | 7 +
Java/commons-lang-ArrayUtils_4451/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4451/buggy.java | 7980 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4451/npe.json | 7 +
Java/commons-lang-ArrayUtils_4475/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4475/buggy.java | 7984 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4475/npe.json | 7 +
Java/commons-lang-ArrayUtils_4497/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4497/buggy.java | 7981 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4497/npe.json | 7 +
Java/commons-lang-ArrayUtils_4505/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4505/buggy.java | 7982 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4505/npe.json | 7 +
Java/commons-lang-ArrayUtils_4519/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4519/buggy.java | 7980 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4519/npe.json | 7 +
Java/commons-lang-ArrayUtils_452/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_452/buggy.java | 7980 +++++++++++++++
.../commons-lang-ArrayUtils_452/metadata.json | 21 +
Java/commons-lang-ArrayUtils_452/npe.json | 7 +
Java/commons-lang-ArrayUtils_4543/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4543/buggy.java | 7984 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4543/npe.json | 7 +
Java/commons-lang-ArrayUtils_4565/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4565/buggy.java | 7981 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4565/npe.json | 7 +
Java/commons-lang-ArrayUtils_4573/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4573/buggy.java | 7982 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4573/npe.json | 7 +
Java/commons-lang-ArrayUtils_4587/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4587/buggy.java | 7980 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4587/npe.json | 7 +
Java/commons-lang-ArrayUtils_4611/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4611/buggy.java | 7984 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4611/npe.json | 7 +
Java/commons-lang-ArrayUtils_4633/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4633/buggy.java | 7981 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4633/npe.json | 7 +
Java/commons-lang-ArrayUtils_4641/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4641/buggy.java | 7982 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4641/npe.json | 7 +
Java/commons-lang-ArrayUtils_4655/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4655/buggy.java | 7980 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4655/npe.json | 7 +
Java/commons-lang-ArrayUtils_4679/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4679/buggy.java | 7984 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4679/npe.json | 7 +
Java/commons-lang-ArrayUtils_4701/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4701/buggy.java | 7981 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4701/npe.json | 7 +
Java/commons-lang-ArrayUtils_4709/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4709/buggy.java | 7982 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4709/npe.json | 7 +
Java/commons-lang-ArrayUtils_4723/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4723/buggy.java | 7980 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4723/npe.json | 7 +
Java/commons-lang-ArrayUtils_4745/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4745/buggy.java | 7980 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4745/npe.json | 7 +
Java/commons-lang-ArrayUtils_478/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_478/buggy.java | 7988 +++++++++++++++
.../commons-lang-ArrayUtils_478/metadata.json | 21 +
Java/commons-lang-ArrayUtils_478/npe.json | 7 +
Java/commons-lang-ArrayUtils_4780/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4780/buggy.java | 7984 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4780/npe.json | 7 +
Java/commons-lang-ArrayUtils_4802/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4802/buggy.java | 7981 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4802/npe.json | 7 +
Java/commons-lang-ArrayUtils_4810/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4810/buggy.java | 7982 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4810/npe.json | 7 +
Java/commons-lang-ArrayUtils_4824/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_4824/buggy.java | 7980 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_4824/npe.json | 7 +
Java/commons-lang-ArrayUtils_5062/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5062/buggy.java | 7998 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5062/npe.json | 7 +
Java/commons-lang-ArrayUtils_5109/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5109/buggy.java | 7990 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5109/npe.json | 7 +
Java/commons-lang-ArrayUtils_5138/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5138/buggy.java | 7990 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5138/npe.json | 7 +
Java/commons-lang-ArrayUtils_5167/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5167/buggy.java | 7990 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5167/npe.json | 7 +
Java/commons-lang-ArrayUtils_5196/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5196/buggy.java | 7990 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5196/npe.json | 7 +
Java/commons-lang-ArrayUtils_5225/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5225/buggy.java | 7990 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5225/npe.json | 7 +
Java/commons-lang-ArrayUtils_5254/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5254/buggy.java | 7990 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5254/npe.json | 7 +
Java/commons-lang-ArrayUtils_5283/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5283/buggy.java | 7990 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5283/npe.json | 7 +
Java/commons-lang-ArrayUtils_5312/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5312/buggy.java | 7990 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5312/npe.json | 7 +
Java/commons-lang-ArrayUtils_5354/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5354/buggy.java | 8000 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5354/npe.json | 7 +
Java/commons-lang-ArrayUtils_5356/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5356/buggy.java | 8004 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5356/npe.json | 7 +
Java/commons-lang-ArrayUtils_5634/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5634/buggy.java | 8003 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5634/npe.json | 7 +
Java/commons-lang-ArrayUtils_5636/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5636/buggy.java | 8007 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5636/npe.json | 7 +
Java/commons-lang-ArrayUtils_5906/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_5906/buggy.java | 7980 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_5906/npe.json | 7 +
Java/commons-lang-ArrayUtils_6617/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_6617/buggy.java | 8000 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_6617/npe.json | 7 +
Java/commons-lang-ArrayUtils_6627/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_6627/buggy.java | 8002 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_6627/npe.json | 7 +
Java/commons-lang-ArrayUtils_6708/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_6708/buggy.java | 7997 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_6708/npe.json | 7 +
Java/commons-lang-ArrayUtils_6718/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_6718/buggy.java | 8000 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_6718/npe.json | 7 +
Java/commons-lang-ArrayUtils_6796/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_6796/buggy.java | 7997 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_6796/npe.json | 7 +
Java/commons-lang-ArrayUtils_6806/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_6806/buggy.java | 8000 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_6806/npe.json | 7 +
Java/commons-lang-ArrayUtils_6894/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_6894/buggy.java | 8000 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_6894/npe.json | 7 +
Java/commons-lang-ArrayUtils_6972/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_6972/buggy.java | 7997 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_6972/npe.json | 7 +
Java/commons-lang-ArrayUtils_6982/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_6982/buggy.java | 8000 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_6982/npe.json | 7 +
Java/commons-lang-ArrayUtils_7060/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_7060/buggy.java | 7997 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_7060/npe.json | 7 +
Java/commons-lang-ArrayUtils_7070/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_7070/buggy.java | 8000 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_7070/npe.json | 7 +
Java/commons-lang-ArrayUtils_7148/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_7148/buggy.java | 7997 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_7148/npe.json | 7 +
Java/commons-lang-ArrayUtils_7158/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_7158/buggy.java | 8000 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_7158/npe.json | 7 +
Java/commons-lang-ArrayUtils_7236/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_7236/buggy.java | 7997 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_7236/npe.json | 7 +
Java/commons-lang-ArrayUtils_7246/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_7246/buggy.java | 8000 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_7246/npe.json | 7 +
Java/commons-lang-ArrayUtils_7320/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_7320/buggy.java | 7998 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_7320/npe.json | 7 +
Java/commons-lang-ArrayUtils_7330/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_7330/buggy.java | 8001 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_7330/npe.json | 7 +
Java/commons-lang-ArrayUtils_7460/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_7460/buggy.java | 7979 +++++++++++++++
.../metadata.json | 21 +
Java/commons-lang-ArrayUtils_7460/npe.json | 7 +
Java/commons-lang-ArrayUtils_941/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_941/buggy.java | 7992 +++++++++++++++
.../commons-lang-ArrayUtils_941/metadata.json | 21 +
Java/commons-lang-ArrayUtils_941/npe.json | 7 +
Java/commons-lang-ArrayUtils_981/Dockerfile | 18 +
Java/commons-lang-ArrayUtils_981/buggy.java | 7992 +++++++++++++++
.../commons-lang-ArrayUtils_981/metadata.json | 21 +
Java/commons-lang-ArrayUtils_981/npe.json | 7 +
839 files changed, 1096003 insertions(+)
create mode 100644 Java-base/commons-lang/Dockerfile
create mode 100755 Java-base/commons-lang/run.sh
create mode 100644 Java-base/commons-lang/src/.travis.yml
create mode 100644 Java-base/commons-lang/src/CONTRIBUTING.md
create mode 100644 Java-base/commons-lang/src/LICENSE.txt
create mode 100644 Java-base/commons-lang/src/NOTICE.txt
create mode 100644 Java-base/commons-lang/src/README.md
create mode 100644 Java-base/commons-lang/src/RELEASE-NOTES.txt
create mode 100644 Java-base/commons-lang/src/checkstyle.xml
create mode 100644 Java-base/commons-lang/src/findbugs-exclude-filter.xml
create mode 100644 Java-base/commons-lang/src/pom.xml
create mode 100644 Java-base/commons-lang/src/src/assembly/bin.xml
create mode 100644 Java-base/commons-lang/src/src/assembly/src.xml
create mode 100644 Java-base/commons-lang/src/src/changes/changes.xml
create mode 100644 Java-base/commons-lang/src/src/changes/release-notes.vm
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/AnnotationUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ArrayUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/BitField.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/BooleanUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharEncoding.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharRange.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSequenceUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSet.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSetUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ClassPathUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ClassUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Conversion.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/EnumUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/JavaVersion.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/LocaleUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/NotImplementedException.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ObjectUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/RandomStringUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/RandomUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Range.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SerializationException.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SerializationUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/StringEscapeUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/StringUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SystemUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ThreadUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Validate.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/Builder.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/Diff.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/DiffBuilder.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/DiffResult.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/Diffable.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
create mode 100755 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/EqualsExclude.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java
create mode 100755 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/HashCodeExclude.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/IDKey.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/MultilineRecursiveToStringStyle.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/RecursiveToStringStyle.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/StandardToStringStyle.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/ToStringBuilder.java
create mode 100755 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/ToStringExclude.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/ToStringStyle.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/builder/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/AbstractCircuitBreaker.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/AtomicInitializer.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/AtomicSafeInitializer.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/BackgroundInitializer.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/BasicThreadFactory.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/CallableBackgroundInitializer.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/CircuitBreaker.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/CircuitBreakingException.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/ConcurrentException.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/ConcurrentInitializer.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/ConcurrentRuntimeException.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/ConcurrentUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/ConstantInitializer.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/EventCountCircuitBreaker.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/LazyInitializer.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/MultiBackgroundInitializer.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/ThresholdCircuitBreaker.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/TimedSemaphore.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/concurrent/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/event/EventListenerSupport.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/event/EventUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/event/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/exception/CloneFailedException.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/exception/ContextedException.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/exception/ContextedRuntimeException.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/exception/DefaultExceptionContext.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/exception/ExceptionContext.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/exception/ExceptionUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/exception/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/math/Fraction.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/math/IEEE754rUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/math/NumberUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/math/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/mutable/Mutable.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/mutable/MutableBoolean.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/mutable/MutableByte.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/mutable/MutableDouble.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/mutable/MutableFloat.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/mutable/MutableInt.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/mutable/MutableLong.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/mutable/MutableObject.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/mutable/MutableShort.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/mutable/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/reflect/ConstructorUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/reflect/InheritanceUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/reflect/MemberUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/reflect/TypeLiteral.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/reflect/Typed.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/reflect/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/CompositeFormat.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/ExtendedMessageFormat.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/FormatFactory.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/FormattableUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/StrBuilder.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/StrLookup.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/StrMatcher.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/StrSubstitutor.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/StrTokenizer.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/WordUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/AggregateTranslator.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/CharSequenceTranslator.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/CodePointTranslator.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/EntityArrays.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/JavaUnicodeEscaper.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/LookupTranslator.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/NumericEntityEscaper.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/NumericEntityUnescaper.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/OctalUnescaper.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/UnicodeEscaper.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/UnicodeUnescaper.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/UnicodeUnpairedSurrogateRemover.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/text/translate/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/CalendarReflection.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/DateFormatUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/DateParser.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/DatePrinter.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/DateUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/DurationFormatUtils.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/FastDateFormat.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/FastDateParser.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/FormatCache.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/StopWatch.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/time/package-info.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/tuple/ImmutablePair.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/tuple/ImmutableTriple.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/tuple/MutablePair.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/tuple/MutableTriple.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/tuple/Pair.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/tuple/Triple.java
create mode 100644 Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/tuple/package-info.java
create mode 100644 Java-base/commons-lang/src/src/media/logo.xcf
create mode 100644 Java-base/commons-lang/src/src/site/resources/.htaccess
create mode 100755 Java-base/commons-lang/src/src/site/resources/download_lang.cgi
create mode 100644 Java-base/commons-lang/src/src/site/resources/images/logo.png
create mode 100644 Java-base/commons-lang/src/src/site/resources/lang2-lang3-clirr-report.html
create mode 100644 Java-base/commons-lang/src/src/site/resources/profile.cobertura
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-1.0.1.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-1.0.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-2.0.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-2.1.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-2.2.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-2.3.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-2.4.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-2.5.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-2.6.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-3.0.1.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-3.0.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-3.1.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-3.2.1.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-3.2.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-3.3.1.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-3.3.2.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-3.3.txt
create mode 100644 Java-base/commons-lang/src/src/site/resources/release-notes/RELEASE-NOTES-3.4.txt
create mode 100644 Java-base/commons-lang/src/src/site/site.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/article2_4.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/article2_5.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/article3_0.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/building.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/developerguide.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/download_lang.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/index.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/issue-tracking.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/mail-lists.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/proposal.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/release-history.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/upgradeto2_0.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/upgradeto2_1.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/upgradeto2_2.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/upgradeto2_3.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/upgradeto2_4.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/upgradeto2_5.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/upgradeto2_6.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/upgradeto3_0.xml
create mode 100644 Java-base/commons-lang/src/src/site/xdoc/userguide.xml
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/AnnotationUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/ArrayUtilsAddTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/ArrayUtilsRemoveMultipleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/ArrayUtilsRemoveTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/BitFieldTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/BooleanUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/CharEncodingTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/CharRangeTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/CharSequenceUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/CharSetTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/CharSetUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/CharUtilsPerfRun.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/CharUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/ClassPathUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/ClassUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/ConversionTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/EnumUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/HashSetvBitSetTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/JavaVersionTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/LocaleUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/NotImplementedExceptionTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/ObjectUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/RandomStringUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/RandomUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/RangeTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/SerializationUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/StringEscapeUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/StringUtilsContainsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/StringUtilsEmptyBlankTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/StringUtilsIsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/StringUtilsStartsEndsWithTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/StringUtilsSubstringTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/StringUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/StringUtilsTrimStripTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/SystemUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/ThreadUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/ValidateTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/CompareToBuilderTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/DefaultToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/DiffBuilderTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/DiffResultTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/DiffTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/HashCodeBuilderAndEqualsBuilderTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/HashCodeBuilderTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/JsonToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/MultiLineToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/MultilineRecursiveToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/NoClassNameToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/NoFieldNamesToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/RecursiveToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderConcurrencyTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeWithAnnotationTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderMutateInspectConcurrencyTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/ShortPrefixToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/SimpleToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/StandardToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/ToStringBuilderTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/ToStringStyleConcurrencyTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/builder/ToStringStyleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/AbstractConcurrentInitializerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/AtomicInitializerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/AtomicSafeInitializerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/BackgroundInitializerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/BasicThreadFactoryTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/CallableBackgroundInitializerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/ConcurrentUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/ConstantInitializerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/EventCountCircuitBreakerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/LazyInitializerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/MultiBackgroundInitializerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/ThresholdCircuitBreakerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/concurrent/TimedSemaphoreTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/event/EventListenerSupportTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/event/EventUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/exception/AbstractExceptionContextTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/exception/ContextedExceptionTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/exception/ContextedRuntimeExceptionTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/exception/DefaultExceptionContextTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/math/FractionTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/math/IEEE754rUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/mutable/MutableBooleanTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/mutable/MutableByteTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/mutable/MutableDoubleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/mutable/MutableFloatTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/mutable/MutableIntTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/mutable/MutableLongTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/mutable/MutableObjectTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/mutable/MutableShortTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/ConstructorUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/FieldUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/InheritanceUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/MethodUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/TypeLiteralTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/Ambig.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/Annotated.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/AnotherChild.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/AnotherParent.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/Bar.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/Foo.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/GenericConsumer.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/GenericParent.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/GenericTypeHolder.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/Grandchild.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/Parent.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/PrivatelyShadowedChild.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/PublicChild.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/PubliclyShadowedChild.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/StaticContainer.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/StaticContainerChild.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/reflect/testbed/StringParameterizedChild.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/test/NotVisibleExceptionFactory.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/test/SystemDefaults.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/test/SystemDefaultsSwitch.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/test/SystemDefaultsSwitchTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/CompositeFormatTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/ExtendedMessageFormatTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/FormattableUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/StrBuilderAppendInsertTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/StrBuilderTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/StrLookupTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/StrMatcherTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/StrSubstitutorTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/StrTokenizerTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/WordUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/translate/EntityArraysTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/translate/LookupTranslatorTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/translate/NumericEntityEscaperTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/translate/NumericEntityUnescaperTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/translate/OctalUnescaperTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/translate/UnicodeEscaperTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/translate/UnicodeUnescaperTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/text/translate/UnicodeUnpairedSurrogateRemoverTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/DateUtilsFragmentTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/DateUtilsRoundingTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/DateUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/FastDateFormat_ParserTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/FastDateFormat_PrinterTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/FastDateParser_MoreOrLessTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/FastDateParser_TimeZoneStrategyTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTimeZonesTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/StopWatchTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/time/WeekYearTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/tuple/ImmutablePairTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/tuple/ImmutableTripleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/tuple/MutablePairTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/tuple/MutableTripleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/tuple/PairTest.java
create mode 100644 Java-base/commons-lang/src/src/test/java/org/apache/commons/lang3/tuple/TripleTest.java
create mode 100644 Java-base/commons-lang/src/src/test/resources/java.policy
create mode 100644 Java-base/commons-lang/src/src/test/resources/lang-708-input.txt
create mode 100644 Java/commons-lang-ArrayUtils_1021/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1021/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1021/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1021/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1061/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1061/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1061/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1061/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1101/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1101/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1101/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1101/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1141/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1141/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1141/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1141/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1181/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1181/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1181/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1181/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1221/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1221/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1221/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1221/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1383/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1383/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1383/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1383/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1417/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1417/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1417/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1417/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1431/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1431/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1431/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1431/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1445/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1445/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1445/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1445/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1459/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1459/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1459/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1459/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1473/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1473/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1473/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1473/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1487/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1487/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1487/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1487/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1501/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1501/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1501/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1501/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1515/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1515/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1515/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1515/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1529/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1529/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1529/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1529/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1553/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1553/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1553/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1553/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1586/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1586/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1586/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1586/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1619/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1619/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1619/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1619/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1652/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1652/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1652/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1652/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1685/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1685/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1685/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1685/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1718/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1718/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1718/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1718/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1751/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1751/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1751/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1751/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_176/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_176/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_176/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_176/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1784/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1784/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1784/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1784/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_1817/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_1817/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_1817/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_1817/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_239/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_239/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_239/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_239/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3216/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3216/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3216/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3216/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3222/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3222/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3222/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3222/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_324/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_324/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_324/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_324/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3267/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3267/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3267/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3267/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3275/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3275/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3275/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3275/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3335/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3335/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3335/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3335/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3378/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3378/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3378/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3378/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_340/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_340/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_340/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_340/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3438/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3438/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3438/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3438/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3481/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3481/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3481/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3481/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3541/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3541/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3541/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3541/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_356/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_356/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_356/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_356/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3584/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3584/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3584/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3584/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3646/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3646/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3646/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3646/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3691/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3691/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3691/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3691/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_372/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_372/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_372/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_372/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3752/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3752/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3752/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3752/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_3795/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_3795/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_3795/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_3795/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_388/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_388/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_388/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_388/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_404/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_404/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_404/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_404/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_420/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_420/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_420/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_420/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4271/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4271/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4271/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4271/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4293/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4293/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4293/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4293/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4301/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4301/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4301/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4301/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4315/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4315/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4315/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4315/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4339/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4339/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4339/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4339/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_436/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_436/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_436/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_436/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4361/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4361/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4361/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4361/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4369/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4369/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4369/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4369/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4383/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4383/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4383/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4383/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4407/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4407/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4407/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4407/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4429/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4429/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4429/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4429/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4437/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4437/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4437/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4437/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4451/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4451/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4451/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4451/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4475/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4475/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4475/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4475/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4497/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4497/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4497/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4497/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4505/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4505/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4505/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4505/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4519/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4519/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4519/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4519/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_452/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_452/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_452/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_452/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4543/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4543/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4543/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4543/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4565/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4565/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4565/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4565/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4573/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4573/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4573/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4573/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4587/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4587/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4587/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4587/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4611/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4611/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4611/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4611/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4633/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4633/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4633/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4633/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4641/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4641/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4641/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4641/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4655/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4655/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4655/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4655/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4679/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4679/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4679/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4679/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4701/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4701/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4701/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4701/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4709/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4709/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4709/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4709/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4723/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4723/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4723/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4723/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4745/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4745/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4745/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4745/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_478/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_478/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_478/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_478/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4780/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4780/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4780/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4780/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4802/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4802/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4802/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4802/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4810/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4810/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4810/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4810/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_4824/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_4824/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_4824/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_4824/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5062/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5062/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5062/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5062/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5109/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5109/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5109/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5109/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5138/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5138/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5138/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5138/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5167/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5167/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5167/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5167/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5196/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5196/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5196/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5196/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5225/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5225/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5225/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5225/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5254/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5254/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5254/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5254/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5283/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5283/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5283/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5283/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5312/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5312/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5312/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5312/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5354/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5354/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5354/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5354/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5356/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5356/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5356/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5356/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5634/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5634/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5634/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5634/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5636/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5636/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5636/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5636/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_5906/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_5906/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_5906/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_5906/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_6617/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_6617/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_6617/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_6617/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_6627/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_6627/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_6627/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_6627/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_6708/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_6708/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_6708/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_6708/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_6718/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_6718/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_6718/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_6718/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_6796/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_6796/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_6796/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_6796/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_6806/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_6806/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_6806/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_6806/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_6894/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_6894/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_6894/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_6894/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_6972/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_6972/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_6972/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_6972/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_6982/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_6982/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_6982/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_6982/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_7060/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_7060/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_7060/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_7060/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_7070/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_7070/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_7070/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_7070/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_7148/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_7148/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_7148/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_7148/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_7158/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_7158/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_7158/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_7158/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_7236/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_7236/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_7236/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_7236/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_7246/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_7246/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_7246/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_7246/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_7320/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_7320/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_7320/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_7320/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_7330/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_7330/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_7330/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_7330/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_7460/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_7460/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_7460/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_7460/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_941/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_941/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_941/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_941/npe.json
create mode 100644 Java/commons-lang-ArrayUtils_981/Dockerfile
create mode 100644 Java/commons-lang-ArrayUtils_981/buggy.java
create mode 100644 Java/commons-lang-ArrayUtils_981/metadata.json
create mode 100644 Java/commons-lang-ArrayUtils_981/npe.json
diff --git a/Java-base/commons-lang/Dockerfile b/Java-base/commons-lang/Dockerfile
new file mode 100644
index 000000000..e208c4890
--- /dev/null
+++ b/Java-base/commons-lang/Dockerfile
@@ -0,0 +1,28 @@
+FROM ubuntu:22.04
+
+RUN export DEBIAN_FRONTEND=noninteractive \
+ && apt-get update \
+ && apt-get install -y software-properties-common \
+ && add-apt-repository ppa:deadsnakes/ppa \
+ && apt-get update \
+ && apt-get install -y \
+ build-essential \
+ git \
+ vim \
+ jq \
+ && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/list/*
+
+RUN apt-get -y install sudo \
+ openjdk-8-jdk \
+ maven
+
+RUN bash -c "echo 2 | update-alternatives --config java"
+
+COPY src /workspace
+WORKDIR /workspace
+
+RUN mvn install -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false
+
+RUN mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100
+
+ENV TZ=Asia/Seoul
diff --git a/Java-base/commons-lang/run.sh b/Java-base/commons-lang/run.sh
new file mode 100755
index 000000000..517752736
--- /dev/null
+++ b/Java-base/commons-lang/run.sh
@@ -0,0 +1 @@
+docker run --rm -it tmp-npe bash
diff --git a/Java-base/commons-lang/src/.travis.yml b/Java-base/commons-lang/src/.travis.yml
new file mode 100644
index 000000000..7733fe424
--- /dev/null
+++ b/Java-base/commons-lang/src/.travis.yml
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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
+#
+# http://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.
+
+language: java
+sudo: false
+
+jdk:
+ - openjdk6
+ - openjdk7
+ - oraclejdk8
+
+after_success:
+ - mvn clean cobertura:cobertura coveralls:report
diff --git a/Java-base/commons-lang/src/CONTRIBUTING.md b/Java-base/commons-lang/src/CONTRIBUTING.md
new file mode 100644
index 000000000..bc418fc26
--- /dev/null
+++ b/Java-base/commons-lang/src/CONTRIBUTING.md
@@ -0,0 +1,97 @@
+
+
+Contributing to Apache Commons Lang
+======================
+
+You have found a bug or you have an idea for a cool new feature? Contributing code is a great way to give something back to
+the open source community. Before you dig right into the code there are a few guidelines that we need contributors to
+follow so that we can have a chance of keeping on top of things.
+
+Getting Started
+---------------
+
++ Make sure you have a [JIRA account](https://issues.apache.org/jira/).
++ Make sure you have a [GitHub account](https://github.com/signup/free).
++ If you're planning to implement a new feature it makes sense to discuss you're changes on the [dev list](https://commons.apache.org/mail-lists.html) first. This way you can make sure you're not wasting your time on something that isn't considered to be in Apache Commons Lang's scope.
++ Submit a ticket for your issue, assuming one does not already exist.
+ + Clearly describe the issue including steps to reproduce when it is a bug.
+ + Make sure you fill in the earliest version that you know has the issue.
++ Fork the repository on GitHub.
+
+Making Changes
+--------------
+
++ Create a topic branch from where you want to base your work (this is usually the master/trunk branch).
++ Make commits of logical units.
++ Respect the original code style:
+ + Only use spaces for indentation.
+ + Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change.
+ + Check for unnecessary whitespace with git diff --check before committing.
++ Make sure your commit messages are in the proper format. Your commit message should contain the key of the JIRA issue.
++ Make sure you have added the necessary tests for your changes.
++ Run all the tests with `mvn clean verify` to assure nothing else was accidentally broken.
+
+Making Trivial Changes
+----------------------
+
+For changes of a trivial nature to comments and documentation, it is not always necessary to create a new ticket in JIRA.
+In this case, it is appropriate to start the first line of a commit with '(doc)' instead of a ticket number.
+
+Submitting Changes
+------------------
+
++ Sign the [Contributor License Agreement][cla] if you haven't already.
++ Push your changes to a topic branch in your fork of the repository.
++ Submit a pull request to the repository in the apache organization.
++ Update your JIRA ticket and include a link to the pull request in the ticket.
+
+Additional Resources
+--------------------
+
++ [Contributing patches](https://commons.apache.org/patches.html)
++ [Apache Commons Lang JIRA project page](https://issues.apache.org/jira/browse/LANG)
++ [Contributor License Agreement][cla]
++ [General GitHub documentation](https://help.github.com/)
++ [GitHub pull request documentation](https://help.github.com/send-pull-requests/)
++ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
++ #apachecommons IRC channel on freenode.org
+
+[cla]:https://www.apache.org/licenses/#clas
diff --git a/Java-base/commons-lang/src/LICENSE.txt b/Java-base/commons-lang/src/LICENSE.txt
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/Java-base/commons-lang/src/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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
+
+ http://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.
diff --git a/Java-base/commons-lang/src/NOTICE.txt b/Java-base/commons-lang/src/NOTICE.txt
new file mode 100644
index 000000000..aac9dceff
--- /dev/null
+++ b/Java-base/commons-lang/src/NOTICE.txt
@@ -0,0 +1,8 @@
+Apache Commons Lang
+Copyright 2001-2016 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+This product includes software from the Spring Framework,
+under the Apache License 2.0 (see: StringUtils.containsWhitespace())
diff --git a/Java-base/commons-lang/src/README.md b/Java-base/commons-lang/src/README.md
new file mode 100644
index 000000000..c3763fd6a
--- /dev/null
+++ b/Java-base/commons-lang/src/README.md
@@ -0,0 +1,106 @@
+
+
+Apache Commons Lang
+===================
+
+[![Build Status](https://travis-ci.org/apache/commons-lang.svg?branch=master)](https://travis-ci.org/apache/commons-lang)
+[![Coverage Status](https://coveralls.io/repos/apache/commons-lang/badge.svg?branch=master)](https://coveralls.io/r/apache/commons-lang)
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.commons/commons-lang3/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.commons/commons-lang3/)
+[![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)
+
+Apache Commons Lang, a package of Java utility classes for the
+ classes that are in java.lang's hierarchy, or are considered to be so
+ standard as to justify existence in java.lang.
+
+Documentation
+-------------
+
+More information can be found on the [homepage](https://commons.apache.org/proper/commons-lang).
+The [JavaDoc](https://commons.apache.org/proper/commons-lang/javadocs/api-release) can be browsed.
+Questions related to the usage of Apache Commons Lang should be posted to the [user mailing list][ml].
+
+Where can I get the latest release?
+-----------------------------------
+You can download source and binaries from our [download page](https://commons.apache.org/proper/commons-lang/download_lang.cgi).
+
+Alternatively you can pull it from the central Maven repositories:
+
+```xml
+
+ org.apache.commons
+ commons-lang3
+ 3.5
+
+```
+
+Contributing
+------------
+
+We accept PRs via github. The [developer mailing list][ml] is the main channel of communication for contributors.
+There are some guidelines which will make applying PRs easier for us:
++ No tabs! Please use spaces for indentation.
++ Respect the code style.
++ Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change.
++ Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running ```mvn clean test```.
+
+If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas).
+You can learn more about contributing via GitHub in our [contribution guidelines](CONTRIBUTING.md).
+
+License
+-------
+Code is under the [Apache Licence v2](https://www.apache.org/licenses/LICENSE-2.0.txt).
+
+Donations
+---------
+You like Apache Commons Lang? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support the development.
+
+Additional Resources
+--------------------
+
++ [Apache Commons Homepage](https://commons.apache.org/)
++ [Apache Bugtracker (JIRA)](https://issues.apache.org/jira/)
++ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
++ #apachecommons IRC channel on freenode.org
+
+[ml]:https://commons.apache.org/mail-lists.html
+
diff --git a/Java-base/commons-lang/src/RELEASE-NOTES.txt b/Java-base/commons-lang/src/RELEASE-NOTES.txt
new file mode 100644
index 000000000..9eba1b543
--- /dev/null
+++ b/Java-base/commons-lang/src/RELEASE-NOTES.txt
@@ -0,0 +1,922 @@
+ Apache Commons Lang
+ Version 3.5
+ Release Notes
+
+
+INTRODUCTION:
+
+This document contains the release notes for the 3.5 version of
+Apache Commons Lang as well as a history all changes in the Commons Lang 3.x
+release line. Commons Lang is a set of utility functions and reusable
+components that should be of use in any Java environment. Commons Lang 3.5 at
+least requires Java 6.0.
+
+For the advice on upgrading from 2.x to 3.x, see the following page:
+
+ http://commons.apache.org/lang/article3_0.html
+
+HIGHLIGHTS
+==========
+
+Some of the highlights in this release include:
+
+o Added Java 9 detection to org.apache.commons.lang3.SystemUtils.
+o Support for shifting and swapping elements in
+ org.apache.commons.lang3.ArrayUtils.
+o New methods for generating random strings from different character classes
+ including alphabetic, alpha-numeric and ASCII added to
+ org.apache.commons.lang3.RandomStringUtils.
+o Numerous extensions to org.apache.commons.lang3.StringUtils including
+ null safe compare variants, more remove and replace variants, rotation and
+ truncation.
+o Added org.apache.commons.lang3.ThreadUtils - a utility class to work with
+ instances of java.lang.Thread and java.lang.ThreadGroup.
+o Added annotations @EqualsExclude, @HashCodeExclude and @ToStringEclude to
+ mark fields which should be ignored by the reflective builders in the
+ org.apache.commons.lang3.builder package.
+o Support for various modify and retrieve value use cases added to the classes
+ in org.apache.commons.lang3.mutable.
+
+COMPATIBILITY
+=============
+
+Apache Commons Lang 3.5 is binary compatible with the 3.4 release. Users
+should not experience any problems when upgrading vom 3.4 to 3.5.
+
+There has been an addition to the org.apache.commons.lang3.time.DatePrinter
+interface:
+
+o Added method 'public boolean parse(java.lang.String, java.text.ParsePosition,
+ java.util.Calendar)'
+o Added method 'public java.lang.Appendable format(long, java.lang.Appendable)'
+o Added method 'public java.lang.Appendable format(java.util.Date,
+ java.lang.Appendable)'
+o Added method 'public java.lang.Appendable format(java.util.Calendar,
+ java.lang.Appendable)'
+
+For this reason 3.5 is not strictly source compatible to 3.4. Since the
+DatePrinter interface is not meant to be implemented by clients, this
+change it not considered to cause any problems.
+
+JAVA 9 SUPPORT
+==============
+
+Java 9 introduces a new version-string scheme. Details of this new scheme are
+documented in JEP-223 (http://openjdk.java.net/jeps/223). In order to support
+JEP-223 two classes had to be changed:
+
+o org.apache.commons.lang3.JavaVersion
+ deprecated enum constant JAVA_1_9
+ introduced enum constant JAVA_9
+
+o org.apache.commons.lang3.SystemUtils
+ deprecated constant IS_JAVA_1_9
+ introduced constant IS_JAVA_9
+
+For more information see LANG-1197
+(https://issues.apache.org/jira/browse/LANG-1197). All other APIs are expected
+to work with Java 9.
+
+BUILDING ON JAVA 9
+==================
+
+Java 8 introduced the Unicode Consortium's Common Locale Data Repository as
+alternative source for locale data. Java 9 will use the CLDR provider as
+default provider for locale data (see http://openjdk.java.net/jeps/252). This
+causes an number of locale-sensitive test in Commons Lang to fail. In order
+to build Commons Lang 3.5 on Java 9, the locale provider has to be set to
+'JRE':
+
+ mvn -Djava.locale.providers=JRE clean install
+
+We are currently investigating ways to support building on Java 9 without
+further configuration. For more information see:
+https://issues.apache.org/jira/browse/LANG-1265
+
+
+NEW FEATURES
+==============
+
+o LANG-1275: Added a tryAcquire() method to TimedSemaphore.
+o LANG-1255: Add DateUtils.toCalendar(Date, TimeZone). Thanks to Kaiyuan Wang.
+o LANG-1023: Add WordUtils.wrap overload with customizable breakable character.
+ Thanks to Marko Bekhta.
+o LANG-787: Add method removeIgnoreCase(String, String) to StringUtils. Thanks
+ to Gokul Nanthakumar C.
+o LANG-1224: Extend RandomStringUtils with methods that generate strings
+ between a min and max length. Thanks to Caleb Cushing.
+o LANG-1257: Add APIs StringUtils.wrapIfMissing(String, char|String). Thanks to
+ Gary Gregory.
+o LANG-1253: Add RandomUtils#nextBoolean() method. Thanks to adilek.
+o LANG-1085: Add a circuit breaker implementation. Thanks to Oliver Heger and
+ Bruno P. Kinoshita.
+o LANG-1013: Add StringUtils.truncate(). Thanks to Thiago Andrade.
+o LANG-1195: Enhance MethodUtils to allow invocation of private methods. Thanks
+ to Derek C. Ashmore.
+o LANG-1189: Add getAndIncrement/getAndDecrement/getAndAdd/incrementAndGet/
+ decrementAndGet/addAndGet in Mutable* classes. Thanks to
+ Haiyang Li and Matthew Bartenschlag.
+o LANG-1225: Add RandomStringUtils#randomGraph and #randomPrint which match
+ corresponding regular expression class. Thanks to Caleb Cushing.
+o LANG-1223: Add StopWatch#getTime(TimeUnit). Thanks to Nick Manley.
+o LANG-781: Add methods to ObjectUtils class to check for null elements in the
+ array. Thanks to Krzysztof Wolny.
+o LANG-1228: Prefer Throwable.getCause() in ExceptionUtils.getCause().
+ Thanks to Brad Hess.
+o LANG-1233: DiffBuilder add method to allow appending from a DiffResult.
+ Thanks to Nick Manley.
+o LANG-1168: Add SystemUtils.IS_OS_WINDOWS_10 property.
+ Thanks to Pascal Schumacher.
+o LANG-1115: Add support for varargs in ConstructorUtils, MemberUtils, and
+ MethodUtils. Thanks to Jim Lloyd and Joe Ferner.
+o LANG-1134: Add methods to check numbers against NaN and inifinite to
+ Validate. Thanks to Alan Smithee.
+o LANG-1220: Add tests for missed branches in DateUtils.
+ Thanks to Casey Scarborough.
+o LANG-1146: z/OS identification in SystemUtils.
+ Thanks to Gabor Liptak.
+o LANG-1192: FastDateFormat support of the week-year component (uppercase 'Y').
+ Thanks to Dominik Stadler.
+o LANG-1169: Add StringUtils methods to compare a string to multiple strings.
+ Thanks to Rafal Glowinski, Robert Parr and Arman Sharif.
+o LANG-1185: Add remove by regular expression methods in StringUtils.
+o LANG-1139: Add replace by regular expression methods in StringUtils.
+o LANG-1171: Add compare methods in StringUtils.
+o LANG-1174: Add sugar to RandomUtils. Thanks to Punkratz312.
+o LANG-1154: FastDateFormat APIs that use a StringBuilder. Thanks to
+ Gary Gregory.
+o LANG-1149: Ability to throw checked exceptions without declaring them. Thanks
+ to Gregory Zak.
+o LANG-1153: Implement ParsePosition api for FastDateParser.
+o LANG-1137: Add check for duplicate event listener in EventListenerSupport.
+ Thanks to Matthew Aguirre.
+o LANG-1135: Add method containsAllWords to WordUtils. Thanks to
+ Eduardo Martins.
+o LANG-1132: ReflectionToStringBuilder doesn't throw IllegalArgumentException
+ when the constructor's object param is null. Thanks to Jack Tan.
+o LANG-701: StringUtils join with var args. Thanks to James Sawle.
+o LANG-1105: Add ThreadUtils - A utility class which provides helper methods
+ related to java.lang.Thread Issue: LANG-1105. Thanks to
+ Hendrik Saly.
+o LANG-1031: Add annotations to exclude fields from ReflectionEqualsBuilder,
+ ReflectionToStringBuilder and ReflectionHashCodeBuilder. Thanks
+ to Felipe Adorno.
+o LANG-1127: Use JUnit rules to set and reset the default Locale and TimeZone.
+o LANG-1119: Add rotate(string, int) method to StringUtils. Thanks to
+ Loic Guibert.
+o LANG-1099: Add swap and shift operations for arrays to ArrayUtils. Thanks to
+ Adrian Ber.
+o LANG-1050: Change nullToEmpty methods to generics. Thanks to James Sawle.
+o LANG-1074: Add a method to ArrayUtils for removing all occurrences of a given
+ element Issue: LANG-1074. Thanks to Haiyang Li.
+
+FIXED BUGS
+============
+
+o LANG-1261: ArrayUtils.contains returns false for instances of subtypes.
+o LANG-1252: Rename NumberUtils.isNumber, isCreatable to better reflect
+ createNumber. Also, accommodated for "+" symbol as prefix in
+ isCreatable and isNumber. Thanks to Rob Tompkins.
+o LANG-1230: Remove unnecessary synchronization from registry lookup in
+ EqualsBuilder and HashCodeBuilder. Thanks to Philippe Marschall.
+o LANG-1214: Handle "void" in ClassUtils.getClass(). Thanks to Henry Tung.
+o LANG-1250: SerializationUtils#deserialize has unnecessary code and a comment
+ for that. Thanks to Glease Wang.
+o LANG-1190: TypeUtils.isAssignable throws NullPointerException when fromType
+ has type variables and toType generic superclass specifies type
+ variable. Thanks to Pascal Schumacher.
+o LANG-1226: StringUtils#normalizeSpace does not trim the string anymore.
+ Thanks to Pascal Schumacher.
+o LANG-1251: SerializationUtils.ClassLoaderAwareObjectInputStream should use
+ static initializer to initialize primitiveTypes map. Thanks to
+ Takuya Ueshin.
+o LANG-1248: FastDatePrinter Memory allocation regression. Thanks to
+ Benoit Wiart.
+o LANG-1018: Fix precision loss on NumberUtils.createNumber(String). Thanks to
+ Nick Manley.
+o LANG-1199: Fix implementation of StringUtils.getJaroWinklerDistance(). Thanks
+ to M. Steiger.
+o LANG-1244: Fix dead links in StringUtils.getLevenshteinDistance() javadoc.
+ Thanks to jjbankert.
+o LANG-1242: "\u2284":"?" mapping missing from
+ EntityArrays#HTML40_EXTENDED_ESCAPE. Thanks to Neal Stewart.
+o LANG-901: StringUtils#startsWithAny/endsWithAny is case sensitive -
+ documented as case insensitive. Thanks to Matthew Bartenschlag.
+o LANG-1232: DiffBuilder: Add null check on fieldName when appending Object or
+ Object[]. Thanks to Nick Manley.
+o LANG-1178: ArrayUtils.removeAll(Object array, int... indices) should do the
+ clone, not its callers. Thanks to Henri Yandell.
+o LANG-1120: StringUtils.stripAccents should remove accents from "Ł" and "ł".
+ Thanks to kaching88.
+o LANG-1205: NumberUtils.createNumber() behaves inconsistently with
+ NumberUtils.isNumber(). Thanks to pbrose.
+o LANG-1222: Fix for incorrect comment on StringUtils.containsIgnoreCase
+ method. Thanks to Adam J.
+o LANG-1221: Fix typo on appendIfMissing javadoc. Thanks to Pierre Templier.
+o LANG-1202: parseDateStrictly does't pass specified locale. Thanks to
+ Markus Jelsma.
+o LANG-1219: FastDateFormat doesn't respect summer daylight in some localized
+ strings. Thanks to Jarek.
+o LANG-1175: Remove Ant-based build.
+o LANG-1194: Limit max heap memory for consistent Travis CI build.
+o LANG-1186: Fix NullPointerException in FastDateParser$TimeZoneStrategy.
+ Thanks to NickManley.
+o LANG-1193: ordinalIndexOf("abc", "ab", 1) gives incorrect answer of -1
+ (correct answer should be 0); revert fix for LANG-1077. Thanks to
+ Qin Li.
+o LANG-1002: Several predefined ISO FastDateFormats in DateFormatUtils are
+ incorrect. Thanks to Michael Osipov.
+o LANG-1152: StringIndexOutOfBoundsException or field over-write for large year
+ fields in FastDateParser. Thanks to Pas Filip.
+o LANG-1141: StrLookup.systemPropertiesLookup() no longer reacts on changes on
+ system properties.
+o LANG-1147: EnumUtils *BitVector issue with more than 32 values Enum. Thanks
+ to Loic Guibert.
+o LANG-1059: Capitalize javadoc is incorrect. Thanks to Colin Casey.
+o LANG-1122: Inconsistent behavior of swap for malformed inputs. Thanks to
+ Adrian Ber.
+o LANG-1130: Fix critical issues reported by SonarQube.
+o LANG-1131: StrBuilder.equals(StrBuilder) doesn't check for null inputs.
+o LANG-1128: JsonToStringStyle doesn't handle chars and objects correctly.
+ Thanks to Jack Tan.
+o LANG-1126: DateFormatUtilsTest.testSMTP depends on the default Locale.
+o LANG-1123: Unit test FastDatePrinterTimeZonesTest needs a timezone set.
+ Thanks to Christian P. Momon.
+o LANG-916: DateFormatUtils.format does not correctly change Calendar
+ TimeZone in certain situations. Thanks to Christian P. Momon.
+o LANG-1116: DateUtilsTest.testLang530 fails for some timezones. Thanks to
+ Aaron Sheldon.
+o LANG-1114: TypeUtils.ParameterizedType#equals doesn't work with wildcard
+ types. Thanks to Andy Coates.
+o LANG-1118: StringUtils.repeat('z', -1) throws NegativeArraySizeException.
+ Thanks to Loic Guibert.
+o LANG-1111: Fix FindBugs warnings in DurationFormatUtils.
+o LANG-1162: StringUtils#equals fails with Index OOBE on non-Strings with
+ identical leading prefix..
+o LANG-1163: There are no tests for CharSequenceUtils.regionMatches.
+o LANG-1200: Fix JavaDoc of StringUtils.ordinalIndexOf. Thanks to BarkZhang.
+o LANG-1191: Incorrect Javadoc
+ StringUtils.containsAny(CharSequence, CharSequence...). Thanks to
+ qed, Brent Worden and Gary Gregory.
+
+CHANGES
+=========
+o LANG-1197: Prepare Java 9 detection.
+o LANG-1262: CompareToBuilder.append(Object, Object, Comparator) method is too
+ big to be inlined. Thanks to Ruslan Cheremin.
+o LANG-1259: JavaDoc for ArrayUtils.isNotEmpty() is slightly misleading. Thanks
+ to Dominik Stadler.
+o LANG-1247: FastDatePrinter generates extra Date objects. Thanks to
+ Benoit Wiart.
+o LANG-1229: HashCodeBuilder.append(Object,Object) is too big to be inlined,
+ which prevents whole builder to be scalarized. Thanks to
+ Ruslan Cheremin.
+o LANG-1243: Simplify ArrayUtils removeElements by using new decrementAndGet()
+ method.
+o LANG-1240: Optimize BitField constructor implementation. Thanks to zhanhb.
+o LANG-1206: Improve CharSetUtils.squeeze() performance. Thanks to
+ Mohammed Alfallaj.
+o LANG-1176: Improve ArrayUtils removeElements time complexity to O(n). Thanks
+ to Jeffery Yuan.
+o LANG-1234: getLevenshteinDistance with a threshold: optimize implementation
+ if the strings lengths differ more than the threshold. Thanks to
+ Jonatan Jönsson.
+o LANG-1151: Performance improvements for NumberUtils.isParsable. Thanks to
+ Juan Pablo Santos Rodríguez.
+o LANG-1218: EqualsBuilder.append(Object,Object) is too big to be inlined,
+ which prevents whole builder to be scalarized. Thanks to
+ Ruslan Cheremin.
+o LANG-1210: StringUtils#startsWithAny has error in Javadoc. Thanks to
+ Matthias Niehoff.
+o LANG-1208: StrSubstitutor can preserve escapes. Thanks to Samuel Karp.
+o LANG-1182: Clarify JavaDoc of StringUtils.containsAny(). Thanks to
+ Larry West and Pascal Schumacher.
+o LANG-1183: Making replacePattern/removePattern methods null safe in
+ StringUtils.
+o LANG-1057: Replace StringBuilder with String concatenation for better
+ optimization. Thanks to Otávio Santana.
+o LANG-1075: Deprecate SystemUtils.FILE_SEPARATOR and
+ SystemUtils.PATH_SEPARATOR.
+o LANG-979: TypeUtils.parameterizeWithOwner - wrong format descriptor for
+ "invalid number of type parameters". Thanks to Bruno P. Kinoshita.
+o LANG-1112: MultilineRecursiveToStringStyle largely unusable due to being
+ package-private.
+o LANG-1058: StringUtils.uncapitalize performance improvement. Thanks to
+ Leo Wang.
+o LANG-1069: CharSet.getInstance documentation does not clearly explain how
+ to include negation character in set. Thanks to Arno Noordover.
+o LANG-1107: Fix parsing edge cases in FastDateParser.
+o LANG-1273: Added new property IS_OS_MAC_OSX_EL_CAPITAN in SystemUtils. Thanks
+ to Jake Wang.
+
+ Release Notes for version 3.4
+
+
+COMPATIBILITY
+=============
+
+Commons Lang 3.4 is fully binary compatible to the last release and can
+therefore be used as a drop in replacement for 3.3.2. Note that the value of
+org.apache.commons.lang3.time.DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN
+has changed, which may affect clients using the constant. Furthermore the
+constant is used internally in
+o DurationFormatUtils.formatDurationISO(long)
+o DurationFormatUtils.formatPeriodISO(long, long)
+
+For more information see https://issues.apache.org/jira/browse/LANG-1000.
+
+NEW FEATURES
+==============
+
+o LANG-821: Support OS X versions in SystemUtils. Thanks to Timo Kockert.
+o LANG-1103: Add SystemUtils.IS_JAVA_1_9
+o LANG-1093: Add ClassUtils.getAbbreviatedName(). Thanks to Fabian Lange.
+o LANG-1082: Add option to disable the "objectsTriviallyEqual" test in
+ DiffBuilder. Thanks to Jonathan Baker.
+o LANG-1015: Add JsonToStringStyle implementation to ToStringStyle. Thanks to
+ Thiago Andrade.
+o LANG-1080: Add NoClassNameToStringStyle implementation of ToStringStyle.
+ Thanks to Innokenty Shuvalov.
+o LANG-883: Add StringUtils.containsAny(CharSequence, CharSequence...) method.
+ Thanks to Daniel Stewart.
+o LANG-1052: Multiline recursive to string style. Thanks to Jan Matèrne.
+o LANG-536: Add isSorted() to ArrayUtils. Thanks to James Sawle.
+o LANG-1033: Add StringUtils.countMatches(CharSequence, char)
+o LANG-1021: Provide methods to retrieve all fields/methods annotated with a
+ specific type. Thanks to Alexander Müller.
+o LANG-1016: NumberUtils#isParsable method(s). Thanks to
+ Juan Pablo Santos Rodríguez.
+o LANG-999: Add fuzzy String matching logic to StringUtils. Thanks to
+ Ben Ripkens.
+o LANG-994: Add zero copy read method to StrBuilder. Thanks to
+ Mikhail Mazursky.
+o LANG-993: Add zero copy write method to StrBuilder. Thanks to
+ Mikhail Mazursky.
+o LANG-1044: Add method MethodUtils.invokeExactMethod(Object, String)
+o LANG-1045: Add method MethodUtils.invokeMethod(Object, String)
+
+FIXED BUGS
+============
+
+o LANG-794: SystemUtils.IS_OS_WINDOWS_2008, VISTA are incorrect. Thanks to
+ Timo Kockert.
+o LANG-1104: Parse test fails for TimeZone America/Sao_Paulo
+o LANG-948: Exception while using ExtendedMessageFormat and escaping braces.
+ Thanks to Andrey Khobnya.
+o LANG-1092: Wrong formating of time zones with daylight saving time in
+ FastDatePrinter
+o LANG-1090: FastDateParser does not set error indication in ParsePosition
+o LANG-1089: FastDateParser does not handle excess hours as per
+ SimpleDateFormat
+o LANG-1061: FastDateParser error - timezones not handled correctly. Thanks to
+ dmeneses.
+o LANG-1087: NumberUtils#createNumber() returns positive BigDecimal when
+ negative Float is expected. Thanks to Renat Zhilkibaev.
+o LANG-1081: DiffBuilder.append(String, Object left, Object right) does not do
+ a left.equals(right) check. Thanks to Jonathan Baker.
+o LANG-1055: StrSubstitutor.replaceSystemProperties does not work consistently.
+ Thanks to Jonathan Baker.
+o LANG-1083: Add (T) casts to get unit tests to pass in old JDK. Thanks to
+ Jonathan Baker.
+o LANG-1073: Read wrong component type of array in add in ArrayUtils.
+ Thanks to haiyang li.
+o LANG-1077: StringUtils.ordinalIndexOf("aaaaaa", "aa", 2) != 3 in StringUtils.
+ Thanks to haiyang li.
+o LANG-1072: Duplicated "0x" check in createBigInteger in NumberUtils. Thanks
+ to haiyang li.
+o LANG-1064: StringUtils.abbreviate description doesn't agree with the
+ examples. Thanks to B.J. Herbison.
+o LANG-1041: Fix MethodUtilsTest so it does not depend on JDK method ordering.
+ Thanks to Alexandre Bartel.
+o LANG-1000: ParseException when trying to parse UTC dates with Z as zone
+ designator using DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT
+o LANG-1035: Javadoc for EqualsBuilder.reflectionEquals() is unclear
+o LANG-1001: ISO 8601 misspelled throughout the Javadocs. Thanks to
+ Michael Osipov.
+o LANG-1088: FastDateParser should be case insensitive
+o LANG-995: Fix bug with stripping spaces on last line in WordUtils.wrap().
+ Thanks to Andrey Khobnya.
+
+CHANGES
+=========
+
+o LANG-1102: Make logic for comparing OS versions in SystemUtils smarter
+o LANG-1091: Shutdown thread pools in test cases. Thanks to Fabian Lange.
+o LANG-1101: FastDateParser and FastDatePrinter support 'X' format
+o LANG-1100: Avoid memory allocation when using date formating to StringBuffer.
+ Thanks to mbracher.
+o LANG-935: Possible performance improvement on string escape functions.
+ Thanks to Fabian Lange, Thomas Neidhart.
+o LANG-1098: Avoid String allocation in StrBuilder.append(CharSequence). Thanks
+ to Mikhail Mazurskiy, Fabian Lange.
+o LANG-1098: Update maven-checkstyle-plugin to 2.14. Thanks to Micha? Kordas.
+o LANG-1097: Update org.easymock:easymock to 3.3.1. Thanks to Micha? Kordas.
+o LANG-1096: Update maven-pmd-plugin to 3.4. Thanks to Micha? Kordas.
+o LANG-1095: Update maven-antrun-plugin to 1.8. Thanks to Micha? Kordas.
+o LANG-877: Performance improvements for StringEscapeUtils. Thanks to
+ Fabian Lange.
+o LANG-1071: Fix wrong examples in JavaDoc of
+ StringUtils.replaceEachRepeatedly(...),
+ StringUtils.replaceEach(...) Thanks to Arno Noordover.
+o LANG-827: CompareToBuilder's doc doesn't specify precedence of fields it
+ uses in performing comparisons
+o LANG-1020: Improve performance of normalize space. Thanks to Libor Ondrusek.
+o LANG-1027: org.apache.commons.lang3.SystemUtils#isJavaVersionAtLeast should
+ return true by default
+o LANG-1026: Bring static method references in StringUtils to consistent style.
+ Thanks to Alex Yursha.
+o LANG-1017: Use non-ASCII digits in Javadoc examples for
+ StringUtils.isNumeric. Thanks to Christoph Schneegans.
+o LANG-1008: Change min/max methods in NumberUtils/IEEE754rUtils from array
+ input parameters to varargs. Thanks to Thiago Andrade.
+o LANG-1006: Add wrap (with String or char) to StringUtils. Thanks to
+ Thiago Andrade.
+o LANG-1005: Extend DurationFormatUtils#formatDurationISO default pattern to
+ match #formatDurationHMS. Thanks to Michael Osipov.
+o LANG-1007: Fixing NumberUtils JAVADoc comments for max methods. Thanks to
+ Thiago Andrade.
+o LANG-731: Better Javadoc for BitField class
+o LANG-1004: DurationFormatUtils#formatDurationHMS implementation does not
+ correspond to Javadoc and vice versa. Thanks to Michael Osipov.
+o LANG-1003: DurationFormatUtils are not able to handle negative
+ durations/periods
+o LANG-998: Javadoc is not clear on preferred pattern to instantiate
+ FastDateParser / FastDatePrinter
+
+ Release Notes for version 3.3.2
+
+NEW FEATURES
+==============
+
+o LANG-989: Add org.apache.commons.lang3.SystemUtils.IS_JAVA_1_8
+
+FIXED BUGS
+============
+
+o LANG-992: NumberUtils#isNumber() returns false for "0.0", "0.4790", et al
+
+ Release Notes for version 3.3.1
+
+FIXED BUGS
+============
+
+o LANG-987: DateUtils.getFragmentInDays(Date, Calendar.MONTH) returns wrong
+ days
+o LANG-983: DurationFormatUtils does not describe format string fully
+o LANG-981: DurationFormatUtils#lexx does not detect unmatched quote char
+o LANG-984: DurationFormatUtils does not handle large durations correctly
+o LANG-982: DurationFormatUtils.formatDuration(61999, "s.SSSS") - ms field
+ size should be 4 digits
+o LANG-978: Failing tests with Java 8 b128
+
+ Release Notes for version 3.3
+
+NEW FEATURES
+==============
+
+o LANG-955: Add methods for removing all invalid characters according to
+ XML 1.0 and XML 1.1 in an input string to StringEscapeUtils.
+ Thanks to Adam Hooper.
+o LANG-970: Add APIs MutableBoolean setTrue() and setFalse()
+o LANG-962: Add SerializationUtils.roundtrip(T extends Serializable) to
+ serialize then deserialize
+o LANG-637: There should be a DifferenceBuilder with a
+ ReflectionDifferenceBuilder implementation
+o LANG-944: Add the Jaro-Winkler string distance algorithm to StringUtils.
+ Thanks to Rekha Joshi.
+o LANG-417: New class ClassPathUtils with methods for turning FQN into
+ resource path
+o LANG-834: Validate: add inclusiveBetween and exclusiveBetween overloads
+ for primitive types
+o LANG-900: New RandomUtils class. Thanks to Duncan Jones.
+o LANG-966: Add IBM OS/400 detection
+
+FIXED BUGS
+============
+
+o LANG-621: ReflectionToStringBuilder.toString does not debug 3rd party object
+ fields within 3rd party object. Thanks to Philip Hodges,
+ Thomas Neidhart.
+o LANG-977: NumericEntityEscaper incorrectly encodes supplementary characters.
+ Thanks to Chris Karcher.
+o LANG-973: Make some private fields final
+o LANG-971: NumberUtils#isNumber(String) fails to reject invalid Octal numbers
+o LANG-972: NumberUtils#isNumber does not allow for hex 0XABCD
+o LANG-969: StringUtils.toEncodedString(byte[], Charset) needlessly throws
+ UnsupportedEncodingException. Thanks to Matt Bishop.
+o LANG-946: ConstantInitializerTest fails when building with IBM JDK 7
+o LANG-954: uncaught PatternSyntaxException in FastDateFormat on Android.
+ Thanks to Michael Keppler.
+o LANG-936: StringUtils.getLevenshteinDistance with too big of a threshold
+ returns wrong result. Thanks to Yaniv Kunda, Eli Lindsey.
+o LANG-943: Test DurationFormatUtilsTest.testEdgeDuration fails in
+ JDK 1.6, 1.7 and 1.8, BRST time zone
+o LANG-613: ConstructorUtils.getAccessibleConstructor() Does Not Check the
+ Accessibility of Enclosing Classes
+o LANG-951: Fragments are wrong by 1 day when using fragment YEAR or MONTH.
+ Thanks to Sebastian Götz.
+o LANG-950: FastDateParser does not handle two digit year parsing like
+ SimpleDateFormat
+o LANG-949: FastDateParserTest.testParses does not test FastDateParser
+o LANG-915: Wrong locale handling in LocaleUtils.toLocale().
+ Thanks to Sergio Fernández.
+
+CHANGES
+=========
+
+o LANG-961: org.apache.commons.lang3.reflect.FieldUtils.removeFinalModifier(Field)
+ does not clean up after itself
+o LANG-958: FastDateParser javadoc incorrectly states that SimpleDateFormat
+ is used internally
+o LANG-956: Improve JavaDoc of WordUtils.wrap methods
+o LANG-939: Move Documentation from user guide to package-info files
+o LANG-953: Convert package.html files to package-info.java files
+o LANG-940: Fix deprecation warnings
+o LANG-819: EnumUtils.generateBitVector needs a "? extends"
+
+ Release Notes for version 3.2.1
+
+BUG FIXES
+===========
+
+o LANG-937: Fix missing Hamcrest dependency in Ant Build
+o LANG-941: Test failure in LocaleUtilsTest when building with JDK 8
+o LANG-942: Test failure in FastDateParserTest and FastDateFormat_ParserTest
+ when building with JDK8. Thanks to Bruno P. Kinoshita,
+ Henri Yandell.
+o LANG-938: Build fails with test failures when building with JDK 8
+
+ Release Notes for version 3.2
+
+COMPATIBILITY WITH 3.1
+========================
+
+This release introduces backwards incompatible changes in
+org.apache.commons.lang3.time.FastDateFormat:
+o Method 'protected java.util.List parsePattern()' has been removed
+o Method 'protected java.lang.String parseToken(java.lang.String, int[])' has
+ been removed
+o Method 'protected org.apache.commons.lang3.time.FastDateFormat$NumberRule
+ selectNumberRule(int, int)' has been removed
+
+These changes were the result of [LANG-462]. It is assumed that this change
+will not break clients as Charles Honton pointed out on 25/Jan/12:
+"
+ 1. Methods "FastDateFormat$NumberRule selectNumberRule(int, int)" and
+ "List parsePattern()" couldn't have been overridden because
+ NumberRule and Rule were private to FastDateFormat.
+ 2. Due to the factory pattern used, it's unlikely other two methods would have
+ been overridden.
+ 3. The four methods are highly implementation specific. I consider it a
+ mistake that the methods were exposed.
+"
+For more information see https://issues.apache.org/jira/browse/LANG-462.
+
+NEW FEATURES
+==============
+
+o LANG-934: Add removeFinalModifier to FieldUtils
+o LANG-863: Method returns number of inheritance hops between parent and
+ subclass. Thanks to Daneel S. Yaitskov.
+o LANG-774: Added isStarted, isSuspended and isStopped to StopWatch.
+ Thanks to Erhan Bagdemir.
+o LANG-848: Added StringUtils.isBlank/isEmpty CharSequence... methods.
+ Thanks to Alexander Muthmann.
+o LANG-926: Added ArrayUtils.reverse(array, from, to) methods.
+o LANG-795: StringUtils.toString(byte[], String) deprecated in favour of a new
+ StringUtils.toString(byte[], CharSet). Thanks to Aaron Digulla.
+o LANG-893: StrSubstitutor now supports default values for variables.
+ Thanks to Woonsan Ko.
+o LANG-913: Adding .gitignore to commons-lang. Thanks to Allon Mureinik.
+o LANG-837: Add ObjectUtils.toIdentityString methods that support
+ StringBuilder, StrBuilder, and Appendable.
+o LANG-886: Added CharSetUtils.containsAny(String, String).
+o LANG-797: Added escape/unescapeJson to StringEscapeUtils.
+o LANG-875: Added appendIfMissing and prependIfMissing methods to StringUtils.
+o LANG-870: Add StringUtils.LF and StringUtils.CR values.
+o LANG-873: Add FieldUtils getAllFields() to return all the fields defined in
+ the given class and super classes.
+o LANG-835: StrBuilder should support StringBuilder as an input parameter.
+o LANG-857: StringIndexOutOfBoundsException in CharSequenceTranslator.
+o LANG-856: Code refactoring in NumberUtils.
+o LANG-855: NumberUtils#createBigInteger does not allow for hex and octal
+ numbers.
+o LANG-854: NumberUtils#createNumber - does not allow for hex numbers to be
+ larger than Long.
+o LANG-853: StringUtils join APIs for primitives.
+o LANG-841: Add StringUtils API to call String.replaceAll in DOTALL a.k.a.
+ single-line mode.
+o LANG-825: Create StrBuilder APIs similar to
+ String.format(String, Object...).
+o LANG-675: Add Triple class (ternary version of Pair).
+o LANG-462: FastDateFormat supports parse methods.
+
+BUG FIXES
+===========
+
+o LANG-932: Spelling fixes. Thanks to Ville Skyttä.
+o LANG-929: OctalUnescaper tried to parse all of \279.
+o LANG-928: OctalUnescaper had bugs when parsing octals starting with a zero.
+o LANG-905: EqualsBuilder returned true when comparing arrays, even when the
+ elements are different.
+o LANG-917: Fixed exception when combining custom and choice format in
+ ExtendedMessageFormat. Thanks to Arne Burmeister.
+o LANG-902: RandomStringUtils.random javadoc was incorrectly promising letters
+ and numbers would, as opposed to may, appear Issue:. Thanks to
+ Andrzej Winnicki.
+o LANG-921: BooleanUtils.xor(boolean...) produces wrong results.
+o LANG-896: BooleanUtils.toBoolean(String str) javadoc is not updated. Thanks
+ to Mark Bryan Yu.
+o LANG-879: LocaleUtils test fails with new Locale "ja_JP_JP_#u-ca-japanese"
+ of JDK7.
+o LANG-836: StrSubstitutor does not support StringBuilder or CharSequence.
+ Thanks to Arnaud Brunet.
+o LANG-693: Method createNumber from NumberUtils doesn't work for floating
+ point numbers other than Float Issue: LANG-693. Thanks to
+ Calvin Echols.
+o LANG-887: FastDateFormat does not use the locale specific cache correctly.
+o LANG-754: ClassUtils.getShortName(String) will now only do a reverse lookup
+ for array types.
+o LANG-881: NumberUtils.createNumber() Javadoc says it does not work for octal
+ numbers.
+o LANG-865: LocaleUtils.toLocale does not parse strings starting with an
+ underscore.
+o LANG-858: StringEscapeUtils.escapeJava() and escapeEcmaScript() do not
+ output the escaped surrogate pairs that are Java parsable.
+o LANG-849: FastDateFormat and FastDatePrinter generates Date objects
+ wastefully.
+o LANG-845: Spelling fixes.
+o LANG-844: Fix examples contained in javadoc of StringUtils.center methods.
+o LANG-832: FastDateParser does not handle unterminated quotes correctly.
+o LANG-831: FastDateParser does not handle white-space properly.
+o LANG-830: FastDateParser could use \Q \E to quote regexes.
+o LANG-828: FastDateParser does not handle non-Gregorian calendars properly.
+o LANG-826: FastDateParser does not handle non-ASCII digits correctly.
+o LANG-822: NumberUtils#createNumber - bad behaviour for leading "--".
+o LANG-818: FastDateFormat's "z" pattern does not respect timezone of Calendar
+ instances passed to format().
+o LANG-817: Add org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS_8.
+o LANG-813: StringUtils.equalsIgnoreCase doesn't check string reference
+ equality.
+o LANG-810: StringUtils.join() endIndex, bugged for loop.
+o LANG-807: RandomStringUtils throws confusing IAE when end <= start.
+o LANG-805: RandomStringUtils.random(count, 0, 0, false, false, universe,
+ random) always throws java.lang.ArrayIndexOutOfBoundsException.
+o LANG-802: LocaleUtils - unnecessary recursive call in SyncAvoid class.
+o LANG-800: Javadoc bug in DateUtils#ceiling for Calendar and Object versions.
+o LANG-788: SerializationUtils throws ClassNotFoundException when cloning
+ primitive classes.
+o LANG-786: StringUtils equals() relies on undefined behavior.
+o LANG-783: Documentation bug: StringUtils.split.
+o LANG-777: jar contains velocity template of release notes.
+o LANG-776: TypeUtilsTest contains incorrect type assignability assertion.
+o LANG-775: TypeUtils.getTypeArguments() misses type arguments for
+ partially-assigned classes.
+o LANG-773: ImmutablePair doc contains nonsense text.
+o LANG-772: ClassUtils.PACKAGE_SEPARATOR Javadoc contains garbage text.
+o LANG-765: EventListenerSupport.ProxyInvocationHandler no longer defines
+ serialVersionUID.
+o LANG-764: StrBuilder is now serializable.
+o LANG-761: Fix Javadoc Ant warnings.
+o LANG-747: NumberUtils does not handle Long Hex numbers.
+o LANG-743: Javadoc bug in static inner class DateIterator.
+
+CHANGES
+=========
+
+o LANG-931: Misleading Javadoc comment in StrBuilderReader class. Thanks
+ to Christoph Schneegans.
+o LANG-910: StringUtils.normalizeSpace now handles non-breaking spaces
+ (Unicode 00A0). Thanks to Timur Yarosh.
+o LANG-804: Redundant check for zero in HashCodeBuilder ctor. Thanks to
+ Allon Mureinik.
+o LANG-884: Simplify FastDateFormat; eliminate boxing.
+o LANG-882: LookupTranslator now works with implementations of CharSequence
+ other than String.
+o LANG-846: Provide CharSequenceUtils.regionMatches with a proper green
+ implementation instead of inefficiently converting to Strings.
+o LANG-839: ArrayUtils removeElements methods use unnecessary HashSet.
+o LANG-838: ArrayUtils removeElements methods clone temporary index arrays
+ unnecessarily.
+o LANG-799: DateUtils#parseDate uses default locale; add Locale support.
+o LANG-798: Use generics in SerializationUtils.
+
+CHANGES WITHOUT TICKET
+========================
+
+o Fixed URLs in javadoc to point to new oracle.com pages
+
+
+ Release Notes for version 3.1
+
+NEW FEATURES
+==============
+
+o LANG-801: Add Conversion utility to convert between data types on byte level
+o LANG-760: Add API StringUtils.toString(byte[] intput, String charsetName)
+o LANG-756: Add APIs ClassUtils.isPrimitiveWrapper(Class>) and
+ isPrimitiveOrWrapper(Class>)
+o LANG-695: SystemUtils.IS_OS_UNIX doesn't recognize FreeBSD as a Unix system
+
+BUG FIXES
+===========
+
+o LANG-749: Incorrect Bundle-SymbolicName in Manifest
+o LANG-746: NumberUtils does not handle upper-case hex: 0X and -0X
+o LANG-744: StringUtils throws java.security.AccessControlException on Google
+ App Engine
+o LANG-741: Ant build has wrong component.name
+o LANG-698: Document that the Mutable numbers don't work as expected with
+ String.format
+
+CHANGES
+=========
+
+o LANG-758: Add an example with whitespace in StringUtils.defaultIfEmpty
+o LANG-752: Fix createLong() so it behaves like createInteger()
+o LANG-751: Include the actual type in the Validate.isInstance and
+ isAssignableFrom exception messages
+o LANG-748: Deprecating chomp(String, String)
+o LANG-736: CharUtils static final array CHAR_STRING is not needed to compute
+ CHAR_STRING_ARRAY
+
+
+ Release Notes for version 3.0
+
+ADDITIONS
+===========
+
+o LANG-276: MutableBigDecimal and MutableBigInteger.
+o LANG-285: Wish : method unaccent.
+o LANG-358: ObjectUtils.coalesce.
+o LANG-386: LeftOf/RightOfNumber in Range convenience methods necessary.
+o LANG-435: Add ClassUtils.isAssignable() variants with autoboxing.
+o LANG-444: StringUtils.emptyToNull.
+o LANG-482: Enhance StrSubstitutor to support nested ${var-${subvr}} expansion
+o LANG-482: StrSubstitutor now supports substitution in variable names.
+o LANG-496: A generic implementation of the Lazy initialization pattern.
+o LANG-497: Addition of ContextedException and ContextedRuntimeException.
+o LANG-498: Add StringEscapeUtils.escapeText() methods.
+o LANG-499: Add support for the handling of ExecutionExceptions.
+o LANG-501: Add support for background initialization.
+o LANG-529: Add a concurrent package.
+o LANG-533: Validate: support for validating blank strings.
+o LANG-537: Add ArrayUtils.toArray to create generic arrays.
+o LANG-545: Add ability to create a Future for a constant.
+o LANG-546: Add methods to Validate to check whether the index is valid for
+ the array/list/string.
+o LANG-553: Add TypeUtils class to provide utility code for working with generic
+ types.
+o LANG-559: Added isAssignableFrom and isInstanceOf validation methods.
+o LANG-559: Added validState validation method.
+o LANG-560: New TimedSemaphore class.
+o LANG-582: Provide an implementation of the ThreadFactory interface.
+o LANG-588: Create a basic Pair class.
+o LANG-594: DateUtils equal & compare functions up to most significant field.
+o LANG-601: Add Builder Interface / Update Builders to Implement It.
+o LANG-609: Support lazy initialization using atomic variables
+o LANG-610: Extend exception handling in ConcurrentUtils to runtime exceptions.
+o LANG-614: StringUtils.endsWithAny method
+o LANG-640: Add normalizeSpace to StringUtils
+o LANG-644: Provide documentation about the new concurrent package
+o LANG-649: BooleanUtils.toBooleanObject to support single character input
+o LANG-651: Add AnnotationUtils
+o LANG-653: Provide a very basic ConcurrentInitializer implementation
+o LANG-655: Add StringUtils.defaultIfBlank()
+o LANG-667: Add a Null-safe compare() method to ObjectUtils
+o LANG-676: Documented potential NPE if auto-boxing occurs for some BooleanUtils
+ methods
+o LANG-678: Add support for ConcurrentMap.putIfAbsent()
+o LANG-692: Add hashCodeMulti varargs method
+o LANG-697: Add FormattableUtils class
+o LANG-684: Levenshtein Distance Within a Given Threshold
+
+REMOVALS
+==========
+
+o LANG-438: Remove @deprecateds.
+o LANG-492: Remove code handled now by the JDK.
+o LANG-493: Remove code that does not hold enough value to remain.
+o LANG-590: Remove JDK 1.2/1.3 bug handling in
+ StringUtils.indexOf(String, String, int).
+o LANG-673: WordUtils.abbreviate() removed
+o LANG-691: Removed DateUtils.UTC_TIME_ZONE
+
+IMPROVEMENTS
+==============
+
+o LANG-290: EnumUtils for JDK 5.0.
+o LANG-336: Finally start using generics.
+o LANG-355: StrBuilder should implement CharSequence and Appendable.
+o LANG-396: Investigate for vararg usages.
+o LANG-424: Improve Javadoc for StringUtils class.
+o LANG-458: Refactor Validate.java to eliminate code redundancy.
+o LANG-479: Document where in SVN trunk is.
+o LANG-504: bring ArrayUtils.isEmpty to the generics world.
+o LANG-505: Rewrite StringEscapeUtils.
+o LANG-507: StringEscapeUtils.unescapeJava should support \u+ notation.
+o LANG-510: Convert StringUtils API to take CharSequence.
+o LANG-513: Better EnumUtils.
+o LANG-528: Mutable classes should implement an appropriately typed Mutable
+ interface.
+o LANG-539: Compile commons.lang for CDC 1.1/Foundation 1.1.
+o LANG-540: Make NumericEntityEscaper immutable.
+o LANG-541: Replace StringBuffer with StringBuilder.
+o LANG-548: Use Iterable on API instead of Collection.
+o LANG-551: Replace Range classes with generic version.
+o LANG-562: Change Maven groupId.
+o LANG-563: Change Java package name.
+o LANG-570: Do the test cases really still require main() and suite() methods?
+o LANG-579: Add new Validate methods.
+o LANG-599: ClassUtils.getClass(): Allow Dots as Inner Class Separators.
+o LANG-605: DefaultExceptionContext overwrites values in recursive situations.
+o LANG-668: Change ObjectUtils min() & max() functions to use varargs rather
+ than just two parameters
+o LANG-681: Push down WordUtils to "text" sub-package.
+o LANG-711: Add includeantruntime=false to javac targets to quell warnings in
+ ant 1.8.1 and better (and modest performance gain).
+o LANG-713: Increase test coverage of FieldUtils read methods and tweak
+ javadoc.
+o LANG-718: build.xml Java 1.5+ updates.
+
+BUG FIXES
+===========
+
+o LANG-11: Depend on JDK 1.5+.
+o LANG-302: StrBuilder does not implement clone().
+o LANG-339: StringEscapeUtils.escapeHtml() escapes multibyte characters like
+ Chinese, Japanese, etc.
+o LANG-369: ExceptionUtils not thread-safe.
+o LANG-418: Javadoc incorrect for StringUtils.endsWithIgnoreCase.
+o LANG-428: StringUtils.isAlpha, isAlphanumeric and isNumeric now return false
+ for ""
+o LANG-439: StringEscapeUtils.escapeHTML() does not escape chars (0x00-0x20).
+o LANG-448: Lower Ascii Characters don't get encoded by Entities.java.
+o LANG-468: JDK 1.5 build/runtime failure on LANG-393 (EqualsBuilder).
+o LANG-474: Fixes for thread safety.
+o LANG-478: StopWatch does not resist to system time changes.
+o LANG-480: StringEscapeUtils.escapeHtml incorrectly converts unicode
+ characters above U+00FFFF into 2 characters.
+o LANG-481: Possible race-conditions in hashCode of the range classes.
+o LANG-564: Improve StrLookup API documentation.
+o LANG-568: @SuppressWarnings("unchecked") is used too generally.
+o LANG-571: ArrayUtils.add(T[: array, T element) can create unexpected
+ ClassCastException.
+o LANG-585: exception.DefaultExceptionContext.getFormattedExceptionMessage
+ catches Throwable.
+o LANG-596: StrSubstitutor should also handle the default properties of a
+ java.util.Properties class
+o LANG-600: Javadoc is incorrect for public static int
+ lastIndexOf(String str, String searchStr).
+o LANG-602: ContextedRuntimeException no longer an 'unchecked' exception.
+o LANG-606: EqualsBuilder causes StackOverflowException.
+o LANG-608: Some StringUtils methods should take an int character instead of
+ char to use String API features.
+o LANG-617: StringEscapeUtils.escapeXML() can't process UTF-16 supplementary
+ characters
+o LANG-624: SystemUtils.getJavaVersionAsFloat throws
+ StringIndexOutOfBoundsException on Android runtime/Dalvik VM
+o LANG-629: Charset may not be threadsafe, because the HashSet is not synch.
+o LANG-638: NumberUtils createNumber throws a StringIndexOutOfBoundsException
+ when argument containing "e" and "E" is passed in
+o LANG-643: Javadoc StringUtils.left() claims to throw on negative len, but
+ doesn't
+o LANG-645: FastDateFormat.format() outputs incorrect week of year because
+ locale isn't respected
+o LANG-646: StringEscapeUtils.unescapeJava doesn't handle octal escapes and
+ Unicode with extra u
+o LANG-656: Example StringUtils.indexOfAnyBut("zzabyycdxx", '') = 0 incorrect
+o LANG-658: Some Entitys like Ö are not matched properly against its
+ ISO8859-1 representation
+o LANG-659: EntityArrays typo: {"\u2122", "−"}, // minus sign, U+2212
+ ISOtech
+o LANG-66: StringEscaper.escapeXml() escapes characters > 0x7f.
+o LANG-662: org.apache.commons.lang3.math.Fraction does not reduce
+ (Integer.MIN_VALUE, 2^k)
+o LANG-663: org.apache.commons.lang3.math.Fraction does not always succeed in
+ multiplyBy and divideBy
+o LANG-664: NumberUtils.isNumber(String) is not right when the String is
+ "1.1L"
+o LANG-672: Doc bug in DateUtils#ceiling
+o LANG-677: DateUtils.isSameLocalTime compares using 12 hour clock and not
+ 24 hour
+o LANG-685: EqualsBuilder synchronizes on HashCodeBuilder.
+o LANG-703: StringUtils.join throws NPE when toString returns null for one of
+ objects in collection
+o LANG-710: StringIndexOutOfBoundsException when calling unescapeHtml4("")
+o LANG-714: StringUtils doc/comment spelling fixes.
+o LANG-715: CharSetUtils.squeeze() speedup.
+o LANG-716: swapCase and *capitalize speedups.
+
+
+Historical list of changes: http://commons.apache.org/lang/changes-report.html
+
+For complete information on Commons Lang, including instructions on how to
+submit bug reports, patches, or suggestions for improvement, see the
+Apache Commons Lang website:
+
+http://commons.apache.org/lang/
+
+Have fun!
+-Apache Commons Lang team
+
diff --git a/Java-base/commons-lang/src/checkstyle.xml b/Java-base/commons-lang/src/checkstyle.xml
new file mode 100644
index 000000000..79943fb21
--- /dev/null
+++ b/Java-base/commons-lang/src/checkstyle.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Java-base/commons-lang/src/findbugs-exclude-filter.xml b/Java-base/commons-lang/src/findbugs-exclude-filter.xml
new file mode 100644
index 000000000..def3ec884
--- /dev/null
+++ b/Java-base/commons-lang/src/findbugs-exclude-filter.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Java-base/commons-lang/src/pom.xml b/Java-base/commons-lang/src/pom.xml
new file mode 100644
index 000000000..d78a87bac
--- /dev/null
+++ b/Java-base/commons-lang/src/pom.xml
@@ -0,0 +1,812 @@
+
+
+
+
+ org.apache.commons
+ commons-parent
+ 41
+
+ 4.0.0
+ org.apache.commons
+ commons-lang3
+ 3.5
+ Apache Commons Lang
+
+ 2001
+
+ Apache Commons Lang, a package of Java utility classes for the
+ classes that are in java.lang's hierarchy, or are considered to be so
+ standard as to justify existence in java.lang.
+
+
+ http://commons.apache.org/proper/commons-lang/
+
+
+ jira
+ http://issues.apache.org/jira/browse/LANG
+
+
+
+ scm:git:http://git-wip-us.apache.org/repos/asf/commons-lang.git
+ scm:git:https://git-wip-us.apache.org/repos/asf/commons-lang.git
+ https://git-wip-us.apache.org/repos/asf?p=commons-lang.git
+ LANG_3_5
+
+
+
+
+ Daniel Rall
+ dlr
+ dlr@finemaltcoding.com
+ CollabNet, Inc.
+
+ Java Developer
+
+
+
+ Stephen Colebourne
+ scolebourne
+ scolebourne@joda.org
+ SITA ATS Ltd
+ 0
+
+ Java Developer
+
+
+
+ Henri Yandell
+ bayard
+ bayard@apache.org
+
+
+ Java Developer
+
+
+
+ Steven Caswell
+ scaswell
+ stevencaswell@apache.org
+
+
+ Java Developer
+
+ -5
+
+
+ Robert Burrell Donkin
+ rdonkin
+ rdonkin@apache.org
+
+
+ Java Developer
+
+
+
+ Gary D. Gregory
+ ggregory
+ ggregory@apache.org
+ -5
+
+ Java Developer
+
+
+
+ Fredrik Westermarck
+ fredrik
+
+
+
+ Java Developer
+
+
+
+ James Carman
+ jcarman
+ jcarman@apache.org
+ Carman Consulting, Inc.
+
+ Java Developer
+
+
+
+ Niall Pemberton
+ niallp
+
+ Java Developer
+
+
+
+ Matt Benson
+ mbenson
+
+ Java Developer
+
+
+
+ Joerg Schaible
+ joehni
+ joerg.schaible@gmx.de
+
+ Java Developer
+
+ +1
+
+
+ Oliver Heger
+ oheger
+ oheger@apache.org
+ +1
+
+ Java Developer
+
+
+
+ Paul Benedict
+ pbenedict
+ pbenedict@apache.org
+
+ Java Developer
+
+
+
+ Benedikt Ritter
+ britter
+ britter@apache.org
+
+ Java Developer
+
+
+
+ Duncan Jones
+ djones
+ djones@apache.org
+ 0
+
+ Java Developer
+
+
+
+ Loic Guibert
+ lguibert
+ lguibert@apache.org
+ +4
+
+ Java Developer
+
+
+
+ Rob Tompkins
+ chtompki
+ chtompki@apache.org
+ -5
+
+ Java Developer
+
+
+
+
+
+ C. Scott Ananian
+
+
+ Chris Audley
+
+
+ Stephane Bailliez
+
+
+ Michael Becke
+
+
+ Benjamin Bentmann
+
+
+ Ola Berg
+
+
+ Nathan Beyer
+
+
+ Stefan Bodewig
+
+
+ Janek Bogucki
+
+
+ Mike Bowler
+
+
+ Sean Brown
+
+
+ Alexander Day Chaffee
+
+
+ Al Chou
+
+
+ Greg Coladonato
+
+
+ Maarten Coene
+
+
+ Justin Couch
+
+
+ Michael Davey
+
+
+ Norm Deane
+
+
+ Morgan Delagrange
+
+
+ Ringo De Smet
+
+
+ Russel Dittmar
+
+
+ Steve Downey
+
+
+ Matthias Eichel
+
+
+ Christopher Elkins
+
+
+ Chris Feldhacker
+
+
+ Roland Foerther
+
+
+ Pete Gieser
+
+
+ Jason Gritman
+
+
+ Matthew Hawthorne
+
+
+ Michael Heuer
+
+
+ Chas Honton
+
+
+ Chris Hyzer
+
+
+ Paul Jack
+
+
+ Marc Johnson
+
+
+ Shaun Kalley
+
+
+ Tetsuya Kaneuchi
+
+
+ Nissim Karpenstein
+
+
+ Ed Korthof
+
+
+ Holger Krauth
+
+
+ Rafal Krupinski
+
+
+ Rafal Krzewski
+
+
+ David Leppik
+
+
+ Eli Lindsey
+
+
+ Sven Ludwig
+
+
+ Craig R. McClanahan
+
+
+ Rand McNeely
+
+
+ Hendrik Maryns
+
+
+ Dave Meikle
+
+
+ Nikolay Metchev
+
+
+ Kasper Nielsen
+
+
+ Tim O'Brien
+
+
+ Brian S O'Neill
+
+
+ Andrew C. Oliver
+
+
+ Alban Peignier
+
+
+ Moritz Petersen
+
+
+ Dmitri Plotnikov
+
+
+ Neeme Praks
+
+
+ Eric Pugh
+
+
+ Stephen Putman
+
+
+ Travis Reeder
+
+
+ Antony Riley
+
+
+ Valentin Rocher
+
+
+ Scott Sanders
+
+
+ James Sawle
+
+
+ Ralph Schaer
+
+
+ Henning P. Schmiedehausen
+
+
+ Sean Schofield
+
+
+ Robert Scholte
+
+
+ Reuben Sivan
+
+
+ Ville Skytta
+
+
+ David M. Sledge
+
+
+ Michael A. Smith
+
+
+ Jan Sorensen
+
+
+ Glen Stampoultzis
+
+
+ Scott Stanchfield
+
+
+ Jon S. Stevens
+
+
+ Sean C. Sullivan
+
+
+ Ashwin Suresh
+
+
+ Helge Tesgaard
+
+
+ Arun Mammen Thomas
+
+
+ Masato Tezuka
+
+
+ Daniel Trebbien
+
+
+ Jeff Varszegi
+
+
+ Chris Webb
+
+
+ Mario Winterer
+
+
+ Stepan Koltsov
+
+
+ Holger Hoffstatte
+
+
+ Derek C. Ashmore
+
+
+ Sebastien Riou
+
+
+ Allon Mureinik
+
+
+ Adam Hooper
+
+
+ Chris Karcher
+
+
+ Michael Osipov
+
+
+ Thiago Andrade
+
+
+ Jonathan Baker
+
+
+ Mikhail Mazursky
+
+
+ Fabian Lange
+
+
+ Michał Kordas
+
+
+ Felipe Adorno
+
+
+ Adrian Ber
+
+
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.hamcrest
+ hamcrest-all
+ 1.3
+ test
+
+
+
+ commons-io
+ commons-io
+ 2.5
+ test
+
+
+
+ org.easymock
+ easymock
+ 3.4
+ test
+
+
+
+
+
+ apache.website
+ Apache Commons Site
+ scm:svn:https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-lang/
+
+
+
+
+ -Xmx512m
+ ISO-8859-1
+ UTF-8
+ 1.6
+ 1.6
+
+ lang3
+
+ 3.5
+ (Java 6.0+)
+
+ 2.6
+ (Requires Java 1.2 or later)
+
+ commons-lang-${commons.release.2.version}
+ LANG
+ 12310481
+
+ lang
+ https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-lang
+ site-content
+ utf-8
+
+
+ 2.8
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ plain
+
+
+ **/*Test.java
+
+ random
+
+
+
+
+
+
+ maven-assembly-plugin
+
+
+ src/assembly/bin.xml
+ src/assembly/src.xml
+
+ gnu
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-scm-publish-plugin
+
+
+ javadocs
+
+
+
+
+
+
+
+
+
+
+ maven-checkstyle-plugin
+ 2.15
+
+ ${basedir}/checkstyle.xml
+ false
+
+
+
+
+ checkstyle
+
+
+
+
+
+
+ org.codehaus.mojo
+ findbugs-maven-plugin
+
+ ${commons.findbugs.version}
+
+ ${basedir}/findbugs-exclude-filter.xml
+
+
+
+ maven-pmd-plugin
+ 3.5
+
+ ${maven.compiler.target}
+
+
+
+ org.codehaus.mojo
+ taglist-maven-plugin
+ 2.4
+
+
+
+
+ Needs Work
+
+
+ TODO
+ exact
+
+
+ FIXME
+ exact
+
+
+ XXX
+ exact
+
+
+
+
+ Noteable Markers
+
+
+ NOTE
+ exact
+
+
+ NOPMD
+ exact
+
+
+ NOSONAR
+ exact
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ javancss-maven-plugin
+ 2.1
+
+
+ org.apache.rat
+ apache-rat-plugin
+
+
+ site-content/**
+ src/site/resources/.htaccess
+ src/site/resources/download_lang.cgi
+ src/site/resources/release-notes/RELEASE-NOTES-*.txt
+ src/test/resources/lang-708-input.txt
+
+
+
+
+
+
+
+
+ setup-checkout
+
+
+ site-content
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ prepare-checkout
+ pre-site
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ travis
+
+
+ env.TRAVIS
+ true
+
+
+
+
+
+ org.codehaus.mojo
+ cobertura-maven-plugin
+ ${commons.cobertura.version}
+
+
+ xml
+
+
+
+
+ org.eluder.coveralls
+ coveralls-maven-plugin
+ 3.1.0
+
+
+
+
+
+
+
diff --git a/Java-base/commons-lang/src/src/assembly/bin.xml b/Java-base/commons-lang/src/src/assembly/bin.xml
new file mode 100644
index 000000000..fb1e07c9a
--- /dev/null
+++ b/Java-base/commons-lang/src/src/assembly/bin.xml
@@ -0,0 +1,46 @@
+
+
+ bin
+
+ tar.gz
+ zip
+
+ false
+
+
+
+ LICENSE.txt
+ NOTICE.txt
+ RELEASE-NOTES.txt
+ README.md
+ CONTRIBUTING.md
+
+
+
+ target
+
+
+ *.jar
+
+
+
+ target/site/apidocs
+ apidocs
+
+
+
diff --git a/Java-base/commons-lang/src/src/assembly/src.xml b/Java-base/commons-lang/src/src/assembly/src.xml
new file mode 100644
index 000000000..e2d2af623
--- /dev/null
+++ b/Java-base/commons-lang/src/src/assembly/src.xml
@@ -0,0 +1,43 @@
+
+
+ src
+
+ tar.gz
+ zip
+
+ ${project.artifactId}-${commons.release.version}-src
+
+
+
+ .travis.yml
+ checkstyle.xml
+ findbugs-exclude-filter.xml
+ LICENSE.txt
+ NOTICE.txt
+ pom.xml
+ PROPOSAL.html
+ RELEASE-NOTES.txt
+ README.md
+ CONTRIBUTING.md
+
+
+
+ src
+
+
+
diff --git a/Java-base/commons-lang/src/src/changes/changes.xml b/Java-base/commons-lang/src/src/changes/changes.xml
new file mode 100644
index 000000000..35f66269b
--- /dev/null
+++ b/Java-base/commons-lang/src/src/changes/changes.xml
@@ -0,0 +1,911 @@
+
+
+
+
+
+
+
+
+ Apache Commons Lang Changes
+
+
+
+
+ Added a tryAcquire() method to TimedSemaphore.
+ Added a new property IS_OS_MAC_OSX_EL_CAPITAN in SystemUtils
+ Add DateUtils.toCalendar(Date, TimeZone)
+ Add WordUtils.wrap overload with customizable breakable character
+ Add method removeIgnoreCase(String, String) to StringUtils
+ ArrayUtils.contains returns false for instances of subtypes
+ Prepare Java 9 detection
+ Rename NumberUtils.isNumber, isCreatable to better reflect createNumber. Also, accommodated for "+" symbol as prefix in isCreatable and isNumber.
+ CompareToBuilder.append(Object, Object, Comparator) method is too big to be inlined
+ Remove unnecessary synchronization from registry lookup in EqualsBuilder and HashCodeBuilder
+ Extend RandomStringUtils with methods that generate strings between a min and max length
+ Handle "void" in ClassUtils.getClass()
+ SerializationUtils#deserialize has unnecessary code and a comment for that
+ JavaDoc for ArrayUtils.isNotEmpty() is slightly misleading
+ Add APIs StringUtils.wrapIfMissing(String, char|String)
+ TypeUtils.isAssignable throws NullPointerException when fromType has type variables and toType generic superclass specifies type variable
+ StringUtils#normalizeSpace does not trim the string anymore
+ SerializationUtils.ClassLoaderAwareObjectInputStream should use static initializer to initialize primitiveTypes map
+ [GitHub issue #170] Add RandomUtils#nextBoolean() method
+ FastDatePrinter Memory allocation regression
+ FastDatePrinter generates extra Date objects
+ Fix precision loss on NumberUtils.createNumber(String)
+ HashCodeBuilder.append(Object,Object) is too big to be inlined, which prevents whole builder to be scalarized
+ Add a circuit breaker implementation
+ Add StringUtils.truncate()
+ Enhance MethodUtils to allow invocation of private methods
+ Fix implementation of StringUtils.getJaroWinklerDistance()
+ Fix dead links in StringUtils.getLevenshteinDistance() javadoc
+ "\u2284":"⊄" mapping missing from EntityArrays#HTML40_EXTENDED_ESCAPE
+ Simplify ArrayUtils removeElements by using new decrementAndGet() method
+ Add getAndIncrement/getAndDecrement/getAndAdd/incrementAndGet/decrementAndGet/addAndGet in Mutable* classes
+ Optimize BitField constructor implementation
+ Improve CharSetUtils.squeeze() performance
+ Add RandomStringUtils#randomGraph and #randomPrint which match corresponding regular expression class
+ StringUtils#startsWithAny/endsWithAny is case sensitive - documented as case insensitive
+ Add StopWatch#getTime(TimeUnit)
+ Add methods to ObjectUtils class to check for null elements in the array
+ Prefer Throwable.getCause() in ExceptionUtils.getCause()
+ DiffBuilder add method to allow appending from a DiffResult
+ Improve ArrayUtils removeElements time complexity to O(n)
+ getLevenshteinDistance with a threshold: optimize implementation if the strings lengths differ more than the threshold
+ Add SystemUtils.IS_OS_WINDOWS_10 property
+ DiffBuilder: Add null check on fieldName when appending Object or Object[]
+ ArrayUtils.removeAll(Object array, int... indices) should do the clone, not its callers
+ Performance improvements for NumberUtils.isParsable
+ StringUtils.stripAccents should remove accents from "Ł" and "ł".
+ EqualsBuilder.append(Object,Object) is too big to be inlined, which prevents whole builder to be scalarized
+ NumberUtils.createNumber() behaves inconsistently with NumberUtils.isNumber()
+ Add support for varargs in ConstructorUtils, MemberUtils, and MethodUtils
+ Add methods to check numbers against NaN and inifinite to Validate
+ Fix for incorrect comment on StringUtils.containsIgnoreCase method
+ Fix typo on appendIfMissing javadoc
+ Add tests for missed branches in DateUtils
+ parseDateStrictly does't pass specified locale
+ FastDateFormat doesn't respect summer daylight in some localized strings
+ z/OS identification in SystemUtils
+ StringUtils#startsWithAny has error in Javadoc
+ StrSubstitutor can preserve escapes
+ Remove Ant-based build
+ FastDateFormat support of the week-year component (uppercase 'Y')
+ Limit max heap memory for consistent Travis CI build
+ Fix NullPointerException in FastDateParser$TimeZoneStrategy
+ ordinalIndexOf("abc", "ab", 1) gives incorrect answer of -1 (correct answer should be 0); revert fix for LANG-1077
+ Clarify JavaDoc of StringUtils.containsAny()
+ Add StringUtils methods to compare a string to multiple strings
+ Add remove by regular expression methods in StringUtils
+ Making replacePattern/removePattern methods null safe in StringUtils
+ Add replace by regular expression methods in StringUtils
+ Add compare methods in StringUtils
+ Add sugar to RandomUtils
+ Replace StringBuilder with String concatenation for better optimization
+ Deprecate SystemUtils.FILE_SEPARATOR and SystemUtils.PATH_SEPARATOR
+ FastDateFormat APIs that use a StringBuilder
+ Ability to throw checked exceptions without declaring them
+ Several predefined ISO FastDateFormats in DateFormatUtils are incorrect
+ StringIndexOutOfBoundsException or field over-write for large year fields in FastDateParser
+ Implement ParsePosition api for FastDateParser
+ StrLookup.systemPropertiesLookup() no longer reacts on changes on system properties
+ EnumUtils *BitVector issue with more than 32 values Enum
+ Capitalize javadoc is incorrect
+ Add check for duplicate event listener in EventListenerSupport
+ FastDateParser_TimeZoneStrategyTest#testTimeZoneStrategyPattern fails on Windows with German Locale
+ Add method containsAllWords to WordUtils
+ ReflectionToStringBuilder doesn't throw IllegalArgumentException when the constructor's object param is null
+ Inconsistent behavior of swap for malformed inputs
+ StringUtils join with var args
+ Fix critical issues reported by SonarQube
+ StrBuilder.equals(StrBuilder) doesn't check for null inputs
+ Add ThreadUtils - A utility class which provides helper methods related to java.lang.Thread
+ Add annotations to exclude fields from ReflectionEqualsBuilder, ReflectionToStringBuilder and ReflectionHashCodeBuilder
+ Use JUnit rules to set and reset the default Locale and TimeZone
+ JsonToStringStyle doesn't handle chars and objects correctly
+ DateFormatUtilsTest.testSMTP depends on the default Locale
+ Unit test FastDatePrinterTimeZonesTest needs a timezone set
+ CLONE - DateFormatUtils.format does not correctly change Calendar TimeZone in certain situations
+ DateUtilsTest.testLang530 fails for some timezones
+ TypeUtils.ParameterizedType#equals doesn't work with wildcard types
+ Add rotate(string, int) method to StringUtils
+ StringUtils.repeat('z', -1) throws NegativeArraySizeException
+ Add swap and shift operations for arrays to ArrayUtils
+ TypeUtils.parameterizeWithOwner - wrong format descriptor for "invalid number of type parameters".
+ MultilineRecursiveToStringStyle largely unusable due to being package-private.
+ StringUtils.uncapitalize performance improvement
+ CharSet.getInstance documentation does not clearly explain how to include negation character in set
+ Change nullToEmpty methods to generics
+ Fix FindBugs warnings in DurationFormatUtils
+ Add a method to ArrayUtils for removing all occurrences of a given element
+ Fix parsing edge cases in FastDateParser
+ StringUtils#equals fails with Index OOBE on non-Strings with identical leading prefix
+ There are no tests for CharSequenceUtils.regionMatches
+ StringUtils.ordinalIndexOf: Add missing right parenthesis in JavaDoc example
+ Incorrect Javadoc StringUtils.containsAny(CharSequence, CharSequence...)
+ Added new property IS_OS_MAC_OSX_EL_CAPITAN in SystemUtils
+
+
+
+ Support OS X versions in SystemUtils
+ SystemUtils.IS_OS_WINDOWS_2008, VISTA are incorrect
+ Parse test fails for TimeZone America/Sao_Paulo
+ Add SystemUtils.IS_JAVA_1_9
+ Make logic for comparing OS versions in SystemUtils smarter
+ Shutdown thread pools in test cases
+ FastDateParser and FastDatePrinter support 'X' format
+ Avoid memory allocation when using date formating to StringBuffer
+ Possible performance improvement on string escape functions
+ Exception while using ExtendedMessageFormat and escaping braces
+ Avoid String allocation in StrBuilder.append(CharSequence)
+ Update maven-checkstyle-plugin to 2.14
+ Update org.easymock:easymock to 3.3.1
+ Update maven-pmd-plugin to 3.4
+ Update maven-antrun-plugin to 1.8
+ Wrong formating of time zones with daylight saving time in FastDatePrinter
+ Performance improvements for StringEscapeUtils
+ Add ClassUtils.getAbbreviatedName()
+ FastDateParser does not set error indication in ParsePosition
+ FastDateParser does not handle excess hours as per SimpleDateFormat
+ FastDateParser error - timezones not handled correctly
+ NumberUtils#createNumber() returns positive BigDecimal when negative Float is expected
+ DiffBuilder.append(String, Object left, Object right) does not do a left.equals(right) check
+ StrSubstitutor.replaceSystemProperties does not work consistently
+ Add option to disable the "objectsTriviallyEqual" test in DiffBuilder
+ Add (T) casts to get unit tests to pass in old JDK
+ Add JsonToStringStyle implementation to ToStringStyle
+ Add NoClassNameToStringStyle implementation of ToStringStyle
+ Fix wrong examples in JavaDoc of StringUtils.replaceEachRepeatedly(...), StringUtils.replaceEach(...)
+ Add StringUtils.containsAny(CharSequence, CharSequence...) method
+ Read wrong component type of array in add in ArrayUtils
+ StringUtils.ordinalIndexOf("aaaaaa", "aa", 2) != 3 in StringUtils
+ Duplicated "0x" check in createBigInteger in NumberUtils
+ StringUtils.abbreviate description doesn't agree with the examples
+ Multiline recursive to string style
+ Add isSorted() to ArrayUtils
+ Fix MethodUtilsTest so it does not depend on JDK method ordering
+ CompareToBuilder's doc doesn't specify precedence of fields it uses in performing comparisons
+ ParseException when trying to parse UTC dates with Z as zone designator using DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT
+ Javadoc for EqualsBuilder.reflectionEquals() is unclear
+ Improve performance of normalize space
+ Add StringUtils.countMatches(CharSequence, char)
+ org.apache.commons.lang3.SystemUtils#isJavaVersionAtLeast should return true by default
+ Provide methods to retrieve all fields/methods annotated with a specific type
+ Bring static method references in StringUtils to consistent style
+ NumberUtils#isParsable method(s)
+ Use non-ASCII digits in Javadoc examples for StringUtils.isNumeric
+ Change min/max methods in NumberUtils/IEEE754rUtils from array input parameters to varargs
+ Add fuzzy String matching logic to StringUtils
+ Add wrap (with String or char) to StringUtils
+ Extend DurationFormatUtils#formatDurationISO default pattern to match #formatDurationHMS
+ Fixing NumberUtils JAVADoc comments for max methods
+ Better Javadoc for BitField class
+ DurationFormatUtils#formatDurationHMS implementation does not correspond to Javadoc and vice versa
+ DurationFormatUtils are not able to handle negative durations/periods
+ ISO 8601 misspelled throughout the Javadocs
+ Add zero copy read method to StrBuilder
+ Add zero copy write method to StrBuilder
+ Javadoc is not clear on preferred pattern to instantiate FastDateParser / FastDatePrinter
+ FastDateParser should be case insensitive
+ Fix bug with stripping spaces on last line in WordUtils.wrap()
+ Add method org.apache.commons.lang3.reflect.MethodUtils.invokeExactMethod(Object, String)
+ Add method org.apache.commons.lang3.reflect.MethodUtils.invokeMethod(Object, String)
+
+
+
+ NumberUtils#isNumber() returns false for "0.0", "0.4790", et al
+ Add org.apache.commons.lang3.SystemUtils.IS_JAVA_1_8
+
+
+
+ DateUtils.getFragmentInDays(Date, Calendar.MONTH) returns wrong days
+ DurationFormatUtils does not describe format string fully
+ DurationFormatUtils#lexx does not detect unmatched quote char
+ DurationFormatUtils does not handle large durations correctly
+ DurationFormatUtils.formatDuration(61999, "s.SSSS") - ms field size should be 4 digits
+ Failing tests with Java 8 b128
+
+
+
+ ReflectionToStringBuilder.toString does not debug 3rd party object fields within 3rd party object
+ Add methods for removing all invalid characters according to XML 1.0 and XML 1.1 in an input string to StringEscapeUtils
+ NumericEntityEscaper incorrectly encodes supplementary characters
+ Make some private fields final
+ NumberUtils#isNumber(String) fails to reject invalid Octal numbers
+ NumberUtils#isNumber does not allow for hex 0XABCD
+ StringUtils.toEncodedString(byte[], Charset) needlessly throws UnsupportedEncodingException
+ Add APIs MutableBoolean setTrue() and setFalse()
+ ConstantInitializerTest fails when building with IBM JDK 7
+ Add SerializationUtils.roundtrip(T extends Serializable) to serialize then deserialize
+ org.apache.commons.lang3.reflect.FieldUtils.removeFinalModifier(Field) does not clean up after itself
+ FastDateParser javadoc incorrectly states that SimpleDateFormat is used internally
+ There should be a DifferenceBuilder with a ReflectionDifferenceBuilder implementation
+ uncaught PatternSyntaxException in FastDateFormat on Android
+ Improve JavaDoc of WordUtils.wrap methods
+ Add the Jaro-Winkler string distance algorithm to StringUtils
+ StringUtils.getLevenshteinDistance with too big of a threshold returns wrong result
+ Test DurationFormatUtilsTest.testEdgeDuration fails in JDK 1.6, 1.7 and 1.8, BRST time zone
+ ConstructorUtils.getAccessibleConstructor() Does Not Check the Accessibility of Enclosing Classes
+ Fragments are wrong by 1 day when using fragment YEAR or MONTH
+ New class ClassPathUtils with methods for turning FQN into resource path
+ Move Documentation from user guide to package-info files
+ Convert package.html files to package-info.java files
+ FastDateParser does not handle two digit year parsing like SimpleDateFormat
+ FastDateParserTest.testParses does not test FastDateParser
+ Fix deprecation warnings
+ EnumUtils.generateBitVector needs a "? extends"
+ Validate: add inclusiveBetween and exclusiveBetween overloads for primitive types
+ New RandomUtils class
+ Wrong locale handling in LocaleUtils.toLocale()
+ Add IBM OS/400 detection
+
+
+
+ Fix missing Hamcrest dependency in Ant Build
+ Test failure in LocaleUtilsTest when building with JDK 8
+ Test failure in FastDateParserTest and FastDateFormat_ParserTest when building with JDK8
+ Build fails with test failures when building with JDK 8
+
+
+
+ Add removeFinalModifier to FieldUtils
+ Method returns number of inheritance hops between parent and subclass
+ Spelling fixes
+ Misleading Javadoc comment in StrBuilderReader class
+ OctalUnescaper tried to parse all of \279
+ OctalUnescaper had bugs when parsing octals starting with a zero
+ EqualsBuilder returned true when comparing arrays, even when the elements are different
+ Added isStarted, isSuspended and isStopped to StopWatch
+ Fixed exception when combining custom and choice format in ExtendedMessageFormat
+ Added StringUtils.isBlank/isEmpty CharSequence... methods
+ Added ArrayUtils.reverse(array, from, to) methods
+ StringUtils.toString(byte[], String) deprecated in favour of a new StringUtils.toString(byte[], CharSet)
+ RandomStringUtils.random javadoc was incorrectly promising letters and numbers would, as opposed to may, appear
+ BooleanUtils.xor(boolean...) produces wrong results
+ StringUtils.normalizeSpace now handles non-breaking spaces (Unicode 00A0)
+ Redundant check for zero in HashCodeBuilder ctor
+ StrSubstitutor now supports default values for variables
+ Adding .gitignore to commons-lang
+ Add ObjectUtils.toIdentityString methods that support StringBuilder, StrBuilder, and Appendable
+ BooleanUtils.toBoolean(String str) javadoc is not updated
+ LocaleUtils test fails with new Locale "ja_JP_JP_#u-ca-japanese" of JDK7
+ StrSubstitutor does not support StringBuilder or CharSequence
+ Method createNumber from NumberUtils doesn't work for floating point numbers other than Float
+ FastDateFormat does not use the locale specific cache correctly
+ Simplify FastDateFormat; eliminate boxing
+ LookupTranslator now works with implementations of CharSequence other than String
+ ClassUtils.getShortName(String) will now only do a reverse lookup for array types
+ Added CharSetUtils.containsAny(String, String)
+ Provide CharSequenceUtils.regionMatches with a proper green implementation instead of inefficiently converting to Strings
+ Added escape/unescapeJson to StringEscapeUtils
+ Added appendIfMissing and prependIfMissing methods to StringUtils
+ NumberUtils.createNumber() Javadoc says it does not work for octal numbers
+ Fixed URLs in javadoc to point to new oracle.com pages
+ Add StringUtils.LF and StringUtils.CR values
+ Add FieldUtils getAllFields() to return all the fields defined in the given class and super classes
+ LocaleUtils.toLocale does not parse strings starting with an underscore
+ StrBuilder should support StringBuilder as an input parameter
+ StringEscapeUtils.escapeJava() and escapeEcmaScript() do not output the escaped surrogate pairs that are Java parsable
+ StringIndexOutOfBoundsException in CharSequenceTranslator
+ Code refactoring in NumberUtils
+ NumberUtils#createBigInteger does not allow for hex and octal numbers
+ NumberUtils#createNumber - does not allow for hex numbers to be larger than Long
+ StringUtils join APIs for primitives
+ FastDateFormat and FastDatePrinter generates Date objects wastefully
+ Spelling fixes
+ Fix examples contained in javadoc of StringUtils.center methods
+ Add StringUtils API to call String.replaceAll in DOTALL a.k.a. single-line mode
+ ArrayUtils removeElements methods use unnecessary HashSet
+ ArrayUtils removeElements methods clone temporary index arrays unnecessarily
+ FastDateParser does not handle unterminated quotes correctly
+ FastDateParser does not handle white-space properly
+ FastDateParser could use \Q \E to quote regexes
+ FastDateParser does not handle non-Gregorian calendars properly
+ FastDateParser does not handle non-ASCII digits correctly
+ Create StrBuilder APIs similar to String.format(String, Object...)
+ NumberUtils#createNumber - bad behaviour for leading "--"
+ FastDateFormat's "z" pattern does not respect timezone of Calendar instances passed to format()
+ Add org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS_8
+ StringUtils.equalsIgnoreCase doesn't check string reference equality
+ StringUtils.join() endIndex, bugged for loop
+ RandomStringUtils throws confusing IAE when end <= start
+ RandomStringUtils.random(count, 0, 0, false, false, universe, random) always throws java.lang.ArrayIndexOutOfBoundsException
+ LocaleUtils - unnecessary recursive call in SyncAvoid class.
+ Javadoc bug in DateUtils#ceiling for Calendar and Object versions.
+ DateUtils#parseDate uses default locale; add Locale support
+ Use generics in SerializationUtils
+ SerializationUtils throws ClassNotFoundException when cloning primitive classes
+ StringUtils equals() relies on undefined behavior
+ Documentation bug: StringUtils.split
+ jar contains velocity template of release notes
+ TypeUtilsTest contains incorrect type assignability assertion
+ TypeUtils.getTypeArguments() misses type arguments for partially-assigned classes
+ ImmutablePair doc contains nonsense text
+ ClassUtils.PACKAGE_SEPARATOR Javadoc contains garbage text
+ EventListenerSupport.ProxyInvocationHandler no longer defines serialVersionUID
+ StrBuilder is now serializable
+ Fix Javadoc Ant warnings
+ NumberUtils does not handle Long Hex numbers
+ Javadoc bug in static inner class DateIterator
+ Add Triple class (ternary version of Pair)
+ FastDateFormat supports parse methods
+
+
+
+ Add API StringUtils.toString(byte[] intput, String charsetName)
+ Add an example with whitespace in StringUtils.defaultIfEmpty
+ Add APIs ClassUtils.isPrimitiveWrapper(Class<?>) and isPrimitiveOrWrapper(Class<?>)
+ Fix createLong() so it behaves like createInteger()
+ Include the actual type in the Validate.isInstance and isAssignableFrom exception messages
+ Incorrect Bundle-SymbolicName in Manifest
+ Deprecating chomp(String, String)
+ NumberUtils does not handle upper-case hex: 0X and -0X
+ StringUtils throws java.security.AccessControlException on Google App Engine
+ Ant build has wrong component.name
+ CharUtils static final array CHAR_STRING is not needed to compute CHAR_STRING_ARRAY
+ Document that the Mutable numbers don't work as expected with String.format
+ SystemUtils.IS_OS_UNIX doesn't recognize FreeBSD as a Unix system
+
+
+
+ SerializationUtils.clone: Fallback to context classloader if class not found in current classloader.
+ ToStringBuilderTest.testReflectionHierarchyArrayList fails with IBM JDK 6.
+ StringEscapeUtils.escapeXml(input) wrong when input contains characters in Supplementary Planes.
+ StringEscapeUtils.escapeEcmaScript from lang3 cuts off long unicode string.
+ Improve exception message when StringUtils.replaceEachRepeatedly detects recursion.
+ Specify source encoding for Ant build.
+ Complement ArrayUtils.addAll() variants with by-index and by-value removal methods.
+ Add Range<T> Range<T>.intersectionWith(Range<T>).
+ Add mode and median Comparable... methods to ObjectUtils.
+ Add BooleanUtils.and + or varargs methods.
+ EnumSet -> bit vector.
+ The CHAR_ARRAY cache in CharUtils duplicates the cache in java.lang.Character.
+ Deprecate CharUtils.toCharacterObject(char) in favor of java.lang.Character.valueOf(char).
+ Missing method getRawMessage for ContextedException and ContextedRuntimeException.
+ Use internal Java's Number caches instead creating new objects.
+
+
+
+ StringEscapeUtils.escapeXml(input) outputs wrong results when an input contains characters in Supplementary Planes.
+ build.xml Java 1.5+ updates.
+ swapCase and *capitalize speedups.
+ CharSetUtils.squeeze() speedup.
+ StringUtils doc/comment spelling fixes.
+ Increase test coverage of FieldUtils read methods and tweak Javadoc.
+ Add includeantruntime=false to javac targets to quell warnings in ant 1.8.1 and better (and modest performance gain).
+ StringIndexOutOfBoundsException when calling unescapeHtml4("").
+ StringEscapeUtils.escapeEcmaScript from lang3 cuts off long Unicode string.
+ StringUtils.join throws NPE when toString returns null for one of objects in collection.
+ Add FormattableUtils class.
+ Add ClassUtils.getSimpleName() methods.
+ Add hashCodeMulti varargs method.
+ Removed DateUtils.UTC_TIME_ZONE.
+ Convert more of the StringUtils API to take CharSequence.
+ EqualsBuilder synchronizes on HashCodeBuilder.
+ StringUtils.isAlpha, isAlphanumeric and isNumeric now return false for "".
+ Add support for ConcurrentMap.putIfAbsent().
+ Documented potential NPE if auto-boxing occurs for some BooleanUtils methods.
+ DateUtils.isSameLocalTime compares using 12 hour clock and not 24 hour.
+ Extend exception handling in ConcurrentUtils to runtime exceptions.
+ SystemUtils.getJavaVersionAsFloat throws StringIndexOutOfBoundsException on Android runtime/Dalvik VM.
+ WordUtils.abbreviate() removed.
+ Doc bug in DateUtils#ceiling.
+ StringEscapeUtils.unescapeJava doesn't handle octal escapes and Unicode with extra u.
+ org.apache.commons.lang3.math.Fraction does not reduce (Integer.MIN_VALUE, 2^k).
+ org.apache.commons.lang3.math.Fraction does not always succeed in multiplyBy and divideBy.
+ Change ObjectUtils min() & max() functions to use varargs rather than just two parameters.
+ Add a Null-safe compare() method to ObjectUtils.
+ NumberUtils.isNumber(String) is not right when the String is "1.1L".
+ EntityArrays typo: {"\u2122", "−"}, // minus sign, U+2212 ISOtech.
+ Some Entitys like Ö are not matched properly against its ISO8859-1 representation.
+ Example StringUtils.indexOfAnyBut("zzabyycdxx", '') = 0 incorrect.
+ Add StringUtils.defaultIfBlank().
+ Provide a very basic ConcurrentInitializer implementation.
+ Support lazy initialization using atomic variables.
+ Enhance StrSubstitutor to support nested ${var-${subvr}} expansion.
+ Provide documentation about the new concurrent package.
+ Charset may not be threadsafe, because the HashSet is not synch.
+ StringEscapeUtils.escapeXML() can't process UTF-16 supplementary characters.
+ StringUtils.endsWithAny method.
+ Add AnnotationUtils.
+ BooleanUtils.toBooleanObject to support single character input.
+ FastDateFormat.format() outputs incorrect week of year because locale isn't respected.
+ StrSubstitutor should also handle the default properties of a java.util.Properties class.
+ Javadoc StringUtils.left() claims to throw on negative len, but doesn't.
+ Add normalizeSpace to StringUtils.
+ NumberUtils createNumber throws a StringIndexOutOfBoundsException when argument containing "e" and "E" is passed in.
+
+ NOTE: The below were included in the Commons Lang 3.0-beta release.
+ Convert StringUtils API to take CharSequence.
+ Push down WordUtils to "text" sub-package.
+ Extend exception handling in ConcurrentUtils to runtime exceptions.
+ Some StringUtils methods should take an int character instead of char to use String API features.
+ EqualsBuilder causes StackOverflowException.
+ DefaultExceptionContext overwrites values in recursive situations.
+ ContextedRuntimeException no longer an 'unchecked' exception.
+ Add Builder Interface / Update Builders to Implement It.
+ Javadoc is incorrect for public static int lastIndexOf(String str, String searchStr).
+ ClassUtils.getClass(): Allow Dots as Inner Class Separators.
+ DateUtils equal & compare functions up to most significant field.
+ Remove JDK 1.2/1.3 bug handling in StringUtils.indexOf(String, String, int).
+ Create a basic Pair<L, R> class.
+ exception.DefaultExceptionContext.getFormattedExceptionMessage catches Throwable.
+ Provide an implementation of the ThreadFactory interface.
+ Add new Validate methods.
+ ArrayUtils.add(T[] array, T element) can create unexpected ClassCastException.
+ Do the test cases really still require main() and suite() methods?.
+ @SuppressWarnings("unchecked") is used too generally.
+ Improve StrLookup API documentation.
+ Change Java package name.
+ Change Maven groupId.
+ New TimedSemaphore class.
+ Added validState validation method.
+ Added isAssignableFrom and isInstanceOf validation methods.
+ Add TypeUtils class to provide utility code for working with generic types.
+ Replace Range classes with generic version.
+ Use Iterable on API instead of Collection.
+ Add methods to Validate to check whether the index is valid for the array/list/string.
+ Add ability to create a Future for a constant.
+ Replace StringBuffer with StringBuilder.
+ Make NumericEntityEscaper immutable.
+ Compile commons.lang for CDC 1.1/Foundation 1.1.
+ Add ArrayUtils.toArray to create generic arrays.
+ Validate: support for validating blank strings.
+ Add a concurrent package.
+ Mutable classes should implement an appropriately typed Mutable interface.
+ Better EnumUtils.
+ StringEscapeUtils.unescapeJava should support \u+ notation.
+ Rewrite StringEscapeUtils.
+ bring ArrayUtils.isEmpty to the generics world.
+ Add support for background initialization.
+ Add support for the handling of ExecutionExceptions.
+ Add StringEscapeUtils.escapeText() methods.
+ Addition of ContextedException and ContextedRuntimeException.
+ A generic implementation of the Lazy initialization pattern.
+ Remove code that does not hold enough value to remain.
+ Remove code handled now by the JDK.
+ StrSubstitutor now supports substitution in variable names.
+ Possible race-conditions in hashCode of the range classes.
+ StringEscapeUtils.escapeHtml incorrectly converts Unicode characters above U+00FFFF into 2 characters.
+ Document where in SVN trunk is.
+ StopWatch does not resist to system time changes.
+ Fixes for thread safety.
+ Refactor Validate.java to eliminate code redundancy.
+ Lower Ascii Characters don't get encoded by Entities.java.
+ StringUtils.emptyToNull.
+ StringEscapeUtils.escapeHTML() does not escape chars (0x00-0x20).
+ Remove @deprecateds.
+ Add ClassUtils.isAssignable() variants with autoboxing.
+ Improve Javadoc for StringUtils class.
+ Javadoc incorrect for StringUtils.endsWithIgnoreCase.
+ Investigate for vararg usages.
+ JDK 1.5 build/runtime failure on LANG-393 (EqualsBuilder).
+ LeftOf/RightOfNumber in Range convenience methods necessary.
+ ExceptionUtils not thread-safe.
+ ObjectUtils.coalesce.
+ StrBuilder should implement CharSequence and Appendable.
+ StringEscapeUtils.escapeHtml() escapes multibyte characters like Chinese, Japanese, etc.
+ Finally start using generics.
+ StrBuilder does not implement clone().
+ EnumUtils for JDK 5.0.
+ Wish : method unaccent.
+ MutableBigDecimal and MutableBigInteger.
+ StringEscaper.escapeXml() escapes characters > 0x7f.
+ Depend on JDK 1.5+.
+
+
+
+ BooleanUtils: use same optimization in toBooleanObject(String) as in toBoolean(String).
+ ClassUtils: allow Dots as Inner Class Separators in getClass().
+ DateUtils: equal and compare functions up to most significant field.
+ DateUtils: provide a Date to Calendar convenience method.
+ ObjectUtils: add clone methods to ObjectUtils.
+ ObjectUtils: add a Null-safe compare() method.
+ ObjectUtils: add notEqual() method.
+ StrBuilder: implement clone() method.
+ StringUtils: add a normalizeSpace() method.
+ StringUtils: add endsWithAny() method.
+ StringUtils: add defaultIfBlank() method.
+ StrSubstitutor: add a replace(String, Properties) variant.
+ StrSubstitutor: support substitution in variable names.
+ Use StrBuilder instead of StringBuffer to improve performance where sync. is not an issue.
+ CharSet: make the underlying set synchronized.
+ CompareToBuilder: fix passing along compareTransients to the reflectionCompare method.
+ ExtendedMessageFormat doesn't override equals(Object).
+ FastDateFormat: fix to properly include the locale when formatting a Date.
+ NumberUtils: createNumber() throws a StringIndexOutOfBoundsException when argument containing "e" and "E" is passed in.
+ StringUtils methods do not handle Unicode 2.0+ supplementary characters correctly.
+ SystemUtils: getJavaVersionAsFloat throws StringIndexOutOfBoundsException on Android runtime/Dalvik VM.
+ MemberUtils: getMatchingAccessibleMethod does not correctly handle inheritance and method overloading.
+ Javadoc is incorrect for lastIndexOf() method.
+ Javadoc for HashCodeBuilder.append(boolean) does not match implementation.
+ Javadoc StringUtils.left() claims to throw an exception on negative lenth, but doesn't.
+ Javadoc - document thread safety.
+ Test for StringUtils replaceChars() icelandic characters.
+
+
+
+ ArrayUtils - add isNotEmpty() methods.
+ ArrayUtils - add nullToEmpty() methods.
+ CharRange - provide an iterator that lets you walk the chars in the range.
+ CharRange - add more readable static builder methods.
+ ClassUtils - new isAssignable() methods with autoboxing.
+ ClassUtils - add support to getShortClassName and getPackageName for arrays.
+ DateUtils - add ceiling() method.
+ DateUtils - add parseDateStrictly() method.
+ EqualsBuilder - add reset() method.
+ NumberUtils - add toByte() and toShort() methods.
+ Mutable numbers - add string constructors.
+ MutableBoolean - add toBoolean(), isTrue() and isFalse() methods.
+ StrBuilder - add appendSeparator() methods with an alternative default separator if the StrBuilder is currently empty.
+ SystemUtils - add IS_OS_WINDOWS_7 constant.
+ SystemUtils - add IS_JAVA_1_7 constant for JDK 1.7.
+ StringUtils - add abbreviateMiddle() method.
+ StringUtils - add indexOfIgnoreCase() and lastIndexOfIgnoreCase() methods.
+ StringUtils - add isAllUpperCase() and isAllLowerCase() methods.
+ StringUtils - add lastOrdinalIndexOf() method to complement the existing ordinalIndexOf() method.
+ StringUtils - add repeat() method.
+ StringUtils - add startsWithAny() method.
+ StringUtils - add upperCase(String, Locale) and lowerCase(String, Locale) methods.
+ New Reflection package containing ConstructorUtils, FieldUtils, MemberUtils and MethodUtils.
+ ArrayUtils - addAll() does not handle mixed types very well.
+ CharSet - Synchronizing the COMMON Map so that getInstance doesn't miss a put from a subclass in another thread.
+ ClassUtils - improving performance of getAllInterfaces.
+ ClassUtils - toClass() throws NullPointerException on null array element.
+ DateUtils - Fix parseDate() cannot parse ISO8601 dates produced by FastDateFormat.
+ DateUtils - round() doesn't work correct for Calendar.AM_PM.
+ DateUtils - improve tests.
+ Entities - multithreaded initialization.
+ Entities - missing final modifiers; thread-safety issues.
+ EnumUtils - getEnum() doesn't work well in 1.5+.
+ ExceptionUtils - use immutable lock target.
+ ExtendedMessageFormat - OutOfMemory with a pattern containing single quotes.
+ FastDateFormat - call getTime() on a calendar to ensure timezone is in the right state.
+ FastDateFormat - Remove unused field.
+ LocaleUtils - Initialization of available locales in LocaleUtils can be deferred.
+ NumberUtils - createNumber() thows a StringIndexOutOfBoundsException when only an "l" is passed in.
+ NumberUtils - isNumber(String) and createNumber(String) both modified to support '2.'.
+ StringUtils - improve handling of case-insensitive Strings.
+ StringUtils - replaceEach() no longer NPEs when null appears in the last String[].
+ StringUtils - correct Javadoc for startsWith() and startsWithIgnoreCase().
+ StringEscapeUtils - escapeJava() escapes '/' characters.
+ StringEscapeUtils - change escapeJavaStyleString() to throw UnhandledException instead swallowing IOException and returning null.
+ WordUtils - fix StringIndexOutOfBoundsException when lower is greater than the String length.
+ StrBuilder - Performance improvement by doubling the size of the String in ensureCapacity.
+ Compare, Equals and HashCode builders - use ArrayUtils to avoid creating a temporary List.
+ EqualsBuilder - removing the special handling of BigDecimal (LANG-393) to use compareTo instead of equals because it creates an inequality with HashCodeBuilder.
+ HashCodeBuilder - Performance improvement: check for isArray to short-circuit the 9 instanceof checks.
+ HashCodeBuilder - Changing the hashCode() method to return toHashCode().
+ HashCodeBuilder - reflectionHashCode() can generate incorrect hashcodes.
+ HashCodeBuilder and ToStringStyle - use of ThreadLocal causes memory leaks in container environments.
+ ToStringBuilder - make default style thread-safe.
+ RandomUtils - nextLong() always produces even numbers.
+ RandomUtils - RandomUtils tests are failing frequently.
+
+
+
+ ClassUtils.getShortClassName(String) inefficient.
+ Shouldn't Commons Lang's StringUtils have a "common" string method?.
+ FastDateFormat getDateInstance() and getDateTimeInstance() assume Locale.getDefault() won't change.
+ OSGi-ify Lang.
+ StrBuilder appendFixedWidth does not handle nulls.
+ infinite loop in Fraction.reduce when numerator == 0.
+ FastDateFormat thread safety.
+ ClassUtils.getShortClassName and ClassUtils.getPackageName and class of array.
+ LocaleUtils.toLocale() rejects strings with only language+variant.
+ Enum is not thread-safe.
+ BooleanUtils.toBoolean() - invalid drop-thru in case statement causes StringIndexOutOfBoundsException.
+ ArrayUtils.toClass.
+ Why does appendIdentityToString return null?.
+ NumberUtils.min(floatArray) returns wrong value if floatArray[0] happens to be Float.NaN.
+ Dates.round() behaves incorrectly for minutes and seconds.
+ StringUtils.length(String) returns null-safe length.
+ adding a StringUtils.replace method that takes an array or List of replacement strings.
+ Adding functionality to DateUtils to allow direct setting of various fields.
+ Add escaping for CSV columns to StringEscapeUtils.
+ StringUtils: startsWith / endsWith / startsWithIgnoreCase / endsWithIgnoreCase / removeStartIgnoreCase / removeEndIgnoreCase methods.
+ Extension to ClassUtils: Obtain the primitive class from a wrapper.
+ Javadoc bugs - cannot find object.
+ Optimize HashCodeBuilder.append(Object).
+ http://commons.apache.org/lang/developerguide.html "Building" section is incorrect and incomplete.
+ Ambiguous / confusing names in StringUtils replace* methods.
+ Add new splitByWholeSeparatorPreserveAllTokens() methods to StringUtils.
+ Add getStartTime to StopWatch.
+ Perhaps add containsAny() methods?.
+ Javadoc Example for EqualsBuilder is questionable.
+ EqualsBuilder don't compare BigDecimals correctly.
+ Split camel case strings.
+ Add Calendar flavour format methods to DateFormatUtils.
+ Calculating A date fragment in any time-unit.
+ Memory usage improvement for StringUtils#getLevenshteinDistance().
+ Add ExtendedMessageFormat to org.apache.commons.lang.text.
+ StringEscapeUtils.escapeJavaScript() method did not escape '/' into '\/', it will make IE render page uncorrectly.
+ Add toArray() method to IntRange and LongRange classes.
+ add SystemUtils.IS_OS_WINDOWS_VISTA field.
+ Pointless synchronized in ThreadLocal.initialValue should be removed.
+ ToStringStyle Javadoc should show examples of styles.
+ Documentation bug for ignoreEmptyTokens accessors in StrTokenizer.
+ BooleanUtils toBooleanObject Javadoc does not match implementation.
+ truncateNicely method which avoids truncating in the middle of a word.
+
+
+
+ Use of enum prevents a classloader from being garbage collected resuling in out of memory exceptions.
+ NumberUtils.max(byte[]) and NumberUtils.min(byte[]) are missing.
+ Null-safe comparison methods for finding most recent / least recent dates.
+ StopWatch: suspend() acts as split(), if followed by stop().
+ StrBuilder.replaceAll and StrBuilder.deleteAll can throw ArrayIndexOutOfBoundsException.
+ Bug in method appendFixedWidthPadRight of class StrBuilder causes an ArrayIndexOutOfBoundsException.
+ ToStringBuilder throws StackOverflowError when an Object cycle exists.
+ Create more tests to test out the +=31 replacement code in DurationFormatUtils.
+ StrBuilder contains usages of thisBuf.length when they should use size.
+ Enum Javadoc: 1) outline 5.0 native Enum migration 2) warn not to use the switch() , 3) point out approaches for persistence and gui.
+ Wrong behavior of Entities.unescape.
+ NumberUtils.createNumber throws NumberFormatException for one digit long.
+ NullPointerException in isAvailableLocale(Locale).
+ FastDateFormat.mRules is not transient or serializable.
+ StringUtils.join should allow you to pass a range for it (so it only joins a part of the array).
+ Refactor Entities methods.
+ Tests fail to pass when building with Maven 2.
+ DurationFormatUtils returns wrong result.
+ unescapeXml("&12345678;") should be "&12345678;".
+ Optimize StringEscapeUtils.unescapeXml(String).
+ BooleanUtils isNotTrue/isNotFalse.
+ Extra StrBuilder methods.
+ Add a pair of StringUtils.substringsBetween;String[] methods.
+ HashCodeBuilder throws java.lang.StackOverflowError when an object contains a cycle.
+ Wish for StringUtils.join(Collection, *).
+
+
+
+ StrBuilderTest#testReplaceStringString fails.
+ EqualsBuilder.append(Object[], Object[]) crashes with a NullPointerException if an element of the first array is null.
+ Serialization - not backwards compatible.
+ Replace Clover with Cobertura.
+ ValuedEnum.compareTo(Object other) not typesafe - it easily could be...
+ LocaleUtils test fails under Mustang.
+ Javadoc example for StringUtils.splitByWholeSeparator incorrect.
+ PADDING array in StringUtils overflows on '\uffff'.
+ ClassUtils.primitiveToWrapper and Void.
+ unit test for org.apache.commons.lang.text.StrBuilder.
+ DateUtils.truncate method is buggy when dealing with DST switching hours.
+ RandomStringUtils.random() family of methods create invalid Unicode sequences.
+ StringUtils#getLevenshteinDistance() performance is sub-optimal.
+ Wrong length check in StrTokenizer.StringMatcher.
+ ExceptionUtils goes into infinite loop in getThrowables is throwable.getCause() == throwable.
+ FastDateFormat: wrong format for date "01.01.1000".
+ Unclear Javadoc for DateUtils.iterator().
+ Memory "leak" in StringUtils.
+ StringEscapeUtils should expose escape*() methods taking Writer argument.
+ Fraction.toProperString() returns -1/1 for -1.
+ DurationFormatUtils.formatDurationWords "11 <unit>s" gets converted to "11 <unit>".
+ Performance modifications on StringUtils.replace.
+ StringEscapeUtils.unescapeHtml skips first entity after standalone ampersand.
+ DurationFormatUtils.formatPeriod() returns the wrong result.
+ Request for MutableBoolean implementation.
+ New method for EqualsBuilder.
+ New ExceptionUtils method setCause().
+ Add Mutable<Type> to<Type>() methods.
+ Provides a Class.getPublicMethod which returns public invocable Method.
+ Using ReflectionToStringBuilder and excluding secure fields.
+ add generic add method to DateUtils.
+ Tokenizer Enhancements: reset input string, static CSV/TSV factories.
+ Trivial cleanup of Javadoc in various files.
+ CompositeFormat.
+ Performance boost for RandomStringUtils.
+ Enhanced Class.forName version.
+ Add StringUtils.containsIgnoreCase(...).
+ Support char array converters on ArrayUtils.
+ DurationFormatUtils.formatDurationISO() Javadoc is missing T in duration string between date and time part.
+ Minor build and checkstyle changes.
+ Javadoc errors on StringUtils.splitPreserveAllTokens(String, char).
+ EscapeUtil.escapeHtml() should clarify that it does not escape ' chars to '.
+ Add methods and tests to StrBuilder.
+ replace() length calculation improvement.
+ New interpolation features.
+ Implementation of escape/unescapeHtml methods with Writer.
+ CompareToBuilder excludeFields for reflection method.
+ Add WordUtils.getInitials(String).
+ Error in an example in the Javadoc of the StringUtils.splitPreserveAllTokens() method.
+ ToStringBuilder/HashCodeBuilder Javadoc code examples.
+ Cannot build tests from latest SVN.
+ minor Javadoc improvements for StringUtils.stripXxx() methods.
+ Javadoc for StringUtils.removeEnd is incorrect.
+ Minor tweak to fix of bug # 26616.
+
+
+
+ make optional parameters in FastDateFormat really optional.
+ Nestable.indexOfThrowable(Class) uses Class.equals() to match.
+ buffer under/overrun on Strings.strip, stripStart & stripEnd.
+ ToStringStyle.setArrayEnd(String) doesn't replace null with empty string.
+ New class proposal: CharacterEncoding.
+ SystemUtils fails init on HP-UX.
+ Javadoc - 'four basic XML entities' should be 5 (apos is missing).
+ o.a.c.lang.enum.ValuedEnum: 'enum'is a keyword in JDK1.5.0.
+ StringEscapeUtils.unescapeHtml() doesn't handle an empty entity.
+ EqualsBuilder.append(Object[], Object[]) incorrectly checks that rhs[i] is instance of lhs[i]'s class.
+ Method enums.Enum.equals(Object o) doesn't work correctly.
+ ExceptionUtils.addCauseMethodName(String) does not check for duplicates.
+ Make StopWatch validate state transitions.
+ enum package is not compatible with 1.5 jdk.
+ WordUtils capitalizeFully() throws a null pointer exception.
+ ValuedEnum.
+ parseDate class from HttpClient's DateParser class.
+ ArrayUtils.isEquals() throws ClassCastException when array1 and array2 are different dimension.
+ ClassCastException in Enum.equals(Object).
+ FastDateFormat year bug.
+ unbalanced ReflectionToStringBuilder.
+ FastDateFormat.getDateInstance(int, Locale) always uses the pattern from the first invocation.
+ ReflectionToStringBuilder.toString(null) throws exception by design.
+ Make ClassUtils methods null-safe and not throw an IAE.
+ StringUtils.split ignores empty items.
+ EqualsBuilder.append(Object[], Object[]) throws NPE.
+ ArrayUtils.addAll doesn't always return new array.
+ Enum.equals does not handle different class loaders.
+ Add SystemUtils.AWT_TOOLKIT and others.
+ Throwable cause for NotImplementedException.
+ ClassUtils.primitivesToWrappers method.
+ public static boolean DateUtils.equals(Date dt1, Date dt2) ?.
+ Documentation error in StringUtils.replace.
+ DateUtils constants should be long.
+ DateUtils.truncate() is off by one hour when using a date in DST switch 'zone'.
+ StringEscapeUtils.unescapeHtml() doesn't handle hex entities.
+ new StringUtils.replaceChars behaves differently from old CharSetUtils.translate.
+ last substring returned by StringUtils.split( String, String, int ) is too long.
+ Can't subclass EqualsBuilder because isEquals is private.
+ new StringUtils.split methods that split on the whole separator string.
+ New method for converting a primitive Class to its corresponding wrapper Class.
+ Add convenience format(long) methods to FastDateFormat.
+ Enum's outer class may not be loaded for EnumUtils.
+ WordUtils.capitalizeFully(String str) should take a delimiter.
+ Make Javadoc crosslinking configurable.
+ Minor Javadoc fixes for StringUtils.contains(String, String).
+ Error in Javadoc for StringUtils.chomp(String, String).
+ StringUtils.defaultString: Documentation error.
+ Add hashCode-support to class ObjectUtils.
+ add another "known method" to ExceptionUtils.
+ Enhancement of ExceptionUtils.CAUSE_METHOD_NAMES.
+ DateUtils.truncate oddity at the far end of the Date spectrum.
+ add getLength() method to ArrayUtils.
+ Validate.java: fixes comment skew, removes unused loop counter.
+ StringUtils.isAsciiPrintable().
+ ExceptionUtils: new getCause() methodname (for tomcat-exception).
+ fixes 75 typos.
+ mutable numbers.
+ Javadoc fixes for ClassUtils.
+ Add StringUtils.nIndexOf?.
+ Javadoc fixes for CharSetUtils.
+ Remove redundant check for null separator in StringUtils#join.
+ Class and Package Comparators for ClassUtils.
+ add remove methods to ArrayUtils.
+ WordUtils capitalize improvement.
+ add isEmpty method to ArrayUtils.
+ lang.math.Fraction class deficiencies.
+ Add methods to ArrayUtils: add at end and insert-like ops.
+ Add SystemUtils methods for directory properties.
+ Add method that validates Collection elements are a certain type.
+ elapsed time formatting utility method.
+
+
+
+ Infinite loop in ToStringBuilder.reflectionToString for inner classes.
+ NumberUtils.createBigDecimal("") NPE in Sun 1.3.1_08.
+ Rationalize StringUtils slice functions.
+ SystemUtils.IS_OS_OS2 Javadoc is wrong.
+ A small, but important Javadoc fix for Fraction proper whole and numerator.
+ Adding tolerance to double[] search methods in ArrayUtils.
+ lang.builder classes Javadoc edits (mostly typo fixes).
+ StringUtils Javadoc and test enhancements.
+ SystemUtils.IS_OS_*, IS_JAVA_* are always false.
+ Improve util.Validate tests.
+ maven-beta10 checkstyle problem.
+ StringUtils.chopNewLine - StringIndexOutOfBoundsException.
+ ToStringBuilder doesn't work well in subclasses.
+ static option for reversing the stacktrace.
+ NullPointerException in CompareToBuilder.
+ RandomStringUtils.randomAlpha methods omit 'z'.
+ test.time fails in Japanese (non-us) locale.
+ NumberUtils.isNumber allows illegal trailing characters.
+ Improve Javadoc and overflow behavior of Fraction.
+ RandomStringUtils infloops with length > 1.
+ test.lang fails if compiled with non iso-8859-1 locales.
+ SystemUtils does not play nice in an Applet.
+ time unit tests fail on Sundays.
+ java.lang.ExceptionInInitializerError thrown by JVMRandom constructor.
+ StringUtils.chomp does not match Perl.
+ patch and test case fixing problem with RandomStringUtils.random().
+ General case: infinite loop: ToStringBuilder.reflectionToString.
+ Should ToStringBuilder.reflectionToString handle arrays?.
+ EnumUtils nit: The import java.io.Serializable is never used.
+ Example in Javadoc for ToStringBuilder wrong for append.
+ Added class hierarchy support to HashCodeBuilder.reflectionHashCode().
+ ExceptionUtils new methods.
+ Infinite loop in StringUtils.replace(text, repl, with) + FIX.
+ StackOverflow due to ToStringBuilder.
+ No Javadoc for NestableDelegate.
+ Specify initial size for Enum's HashMap.
+ Enum does not support inner sub-classes.
+ Removed compile warning in ObjectUtils.
+ SystemUtils.IS_JAVA_1_5 Javadoc is wrong.
+ NumberRange inaccurate for Long, etc.
+ Hierarchy support in ToStringBuilder.reflectionToString().
+ StringUtils.countMatches loops forever if substring empty.
+ Javadoc fixes (remove @links to non-public identifiers).
+ Add Javadoc examples and tests for StringUtils.
+ Make NumberUtils null handling consistent.
+ Unused field 'startFinal' in DateIterator.
+ reduce object creation in ToStringBuilder.
+ Improved tests, Javadoc for CharSetUtils, StringEscapeUtils.
+ NumberUtils min/max, BooleanUtils.xor, and ArrayUtils toPrimitive and toObject.
+ Javadoc, tests improvements for CharSet, CharSetUtils.
+ StringUtil enhancement.
+ Javadoc nit.
+ Additional Lang Method Suggestions.
+ Make NestableDelegate methods public instead of package private.
+ Missing @since tags.
+ Refactored reflection feature of ToStringBuilder into new ReflectionToStringBuilder.
+ Typo in documentation.
+ Patch for Javadoc.
+ Add join(..., char c) to StringUtils (and some performance fixes). Even contains tests!.
+ Resurrect the WordWrapUtils from commons-sandbox/utils.
+ EnumTest fails on Linux Sun JDK 1.3.0.
+ What to do with FastDateFormat unused private constructors.
+ Added class hierarchy support to CompareToBuilder.reflectionCompare().
+ Removed compile warning in FastDateFormat.
+ typo in the Javadoc example code.
+ MethodUtils: Removed unused code/unused local vars.
+ Hierarchy support in EqualsBuilder.reflectionEquals().
+ Javadoc Errata.
+ ArrayUtils.contains().
+ More flexibility for getRootCause in ExceptionUtils.
+
+
+
+ NumberRange.getMaximum returns minimum.
+ Enum constructor validations.
+ NestableException/Delegate is not serializable.
+ split using null and max less than actual token count adds "null".
+ ExceptionUtils cannot handle J2EE-Exception in a default way.
+
+
+
+
+
+
+
diff --git a/Java-base/commons-lang/src/src/changes/release-notes.vm b/Java-base/commons-lang/src/src/changes/release-notes.vm
new file mode 100644
index 000000000..c2df2ffa3
--- /dev/null
+++ b/Java-base/commons-lang/src/src/changes/release-notes.vm
@@ -0,0 +1,140 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you 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
+##
+## http://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.
+##
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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
+
+http://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.
+
+
+ ${project.name}
+ Version ${version}
+ Release Notes
+
+
+INTRODUCTION:
+
+This document contains the release notes for the ${version} version of Apache Commons Lang.
+Commons Lang is a set of utility functions and reusable components that should be of use in any
+Java environment.
+
+Lang 3.0 and onwards now targets Java 5.0, making use of features that arrived with Java 5.0 such as generics,
+variable arguments, autoboxing, concurrency and formatted output.
+
+For the advice on upgrading from 2.x to 3.x, see the following page:
+
+ http://commons.apache.org/lang/article3_0.html
+
+$introduction.replaceAll("(?Helper methods for working with {@link Annotation} instances.
+ *
+ * This class contains various utility methods that make working with
+ * annotations simpler.
+ *
+ * {@link Annotation} instances are always proxy objects; unfortunately
+ * dynamic proxies cannot be depended upon to know how to implement certain
+ * methods in the same manner as would be done by "natural" {@link Annotation}s.
+ * The methods presented in this class can be used to avoid that possibility. It
+ * is of course also possible for dynamic proxies to actually delegate their
+ * e.g. {@link Annotation#equals(Object)}/{@link Annotation#hashCode()}/
+ * {@link Annotation#toString()} implementations to {@link AnnotationUtils}.
+ *
+ * #ThreadSafe#
+ *
+ * @since 3.0
+ */
+public class AnnotationUtils {
+
+ /**
+ * A style that prints annotations as recommended.
+ */
+ private static final ToStringStyle TO_STRING_STYLE = new ToStringStyle() {
+ /** Serialization version */
+ private static final long serialVersionUID = 1L;
+
+ {
+ setDefaultFullDetail(true);
+ setArrayContentDetail(true);
+ setUseClassName(true);
+ setUseShortClassName(true);
+ setUseIdentityHashCode(false);
+ setContentStart("(");
+ setContentEnd(")");
+ setFieldSeparator(", ");
+ setArrayStart("[");
+ setArrayEnd("]");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getShortClassName(final java.lang.Class> cls) {
+ Class extends Annotation> annotationType = null;
+ for (final Class> iface : ClassUtils.getAllInterfaces(cls)) {
+ if (Annotation.class.isAssignableFrom(iface)) {
+ @SuppressWarnings("unchecked") // OK because we just checked the assignability
+ final
+ Class extends Annotation> found = (Class extends Annotation>) iface;
+ annotationType = found;
+ break;
+ }
+ }
+ return new StringBuilder(annotationType == null ? StringUtils.EMPTY : annotationType.getName())
+ .insert(0, '@').toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void appendDetail(final StringBuffer buffer, final String fieldName, Object value) {
+ if (value instanceof Annotation) {
+ value = AnnotationUtils.toString((Annotation) value);
+ }
+ super.appendDetail(buffer, fieldName, value);
+ }
+
+ };
+
+ /**
+ * {@code AnnotationUtils} instances should NOT be constructed in
+ * standard programming. Instead, the class should be used statically.
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public AnnotationUtils() {
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if two annotations are equal using the criteria for equality
+ * presented in the {@link Annotation#equals(Object)} API docs.
+ *
+ * @param a1 the first Annotation to compare, {@code null} returns
+ * {@code false} unless both are {@code null}
+ * @param a2 the second Annotation to compare, {@code null} returns
+ * {@code false} unless both are {@code null}
+ * @return {@code true} if the two annotations are {@code equal} or both
+ * {@code null}
+ */
+ public static boolean equals(final Annotation a1, final Annotation a2) {
+ if (a1 == a2) {
+ return true;
+ }
+ if (a1 == null || a2 == null) {
+ return false;
+ }
+ final Class extends Annotation> type = a1.annotationType();
+ final Class extends Annotation> type2 = a2.annotationType();
+ Validate.notNull(type, "Annotation %s with null annotationType()", a1);
+ Validate.notNull(type2, "Annotation %s with null annotationType()", a2);
+ if (!type.equals(type2)) {
+ return false;
+ }
+ try {
+ for (final Method m : type.getDeclaredMethods()) {
+ if (m.getParameterTypes().length == 0
+ && isValidAnnotationMemberType(m.getReturnType())) {
+ final Object v1 = m.invoke(a1);
+ final Object v2 = m.invoke(a2);
+ if (!memberEquals(m.getReturnType(), v1, v2)) {
+ return false;
+ }
+ }
+ }
+ } catch (final IllegalAccessException ex) {
+ return false;
+ } catch (final InvocationTargetException ex) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Generate a hash code for the given annotation using the algorithm
+ * presented in the {@link Annotation#hashCode()} API docs.
+ *
+ * @param a the Annotation for a hash code calculation is desired, not
+ * {@code null}
+ * @return the calculated hash code
+ * @throws RuntimeException if an {@code Exception} is encountered during
+ * annotation member access
+ * @throws IllegalStateException if an annotation method invocation returns
+ * {@code null}
+ */
+ public static int hashCode(final Annotation a) {
+ int result = 0;
+ final Class extends Annotation> type = a.annotationType();
+ for (final Method m : type.getDeclaredMethods()) {
+ try {
+ final Object value = m.invoke(a);
+ if (value == null) {
+ throw new IllegalStateException(
+ String.format("Annotation method %s returned null", m));
+ }
+ result += hashMember(m.getName(), value);
+ } catch (final RuntimeException ex) {
+ throw ex;
+ } catch (final Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Generate a string representation of an Annotation, as suggested by
+ * {@link Annotation#toString()}.
+ *
+ * @param a the annotation of which a string representation is desired
+ * @return the standard string representation of an annotation, not
+ * {@code null}
+ */
+ public static String toString(final Annotation a) {
+ final ToStringBuilder builder = new ToStringBuilder(a, TO_STRING_STYLE);
+ for (final Method m : a.annotationType().getDeclaredMethods()) {
+ if (m.getParameterTypes().length > 0) {
+ continue; //wtf?
+ }
+ try {
+ builder.append(m.getName(), m.invoke(a));
+ } catch (final RuntimeException ex) {
+ throw ex;
+ } catch (final Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ return builder.build();
+ }
+
+ /**
+ * Checks if the specified type is permitted as an annotation member.
+ *
+ * The Java language specification only permits certain types to be used
+ * in annotations. These include {@link String}, {@link Class}, primitive
+ * types, {@link Annotation}, {@link Enum}, and single-dimensional arrays of
+ * these types.
+ *
+ * @param type the type to check, {@code null}
+ * @return {@code true} if the type is a valid type to use in an annotation
+ */
+ public static boolean isValidAnnotationMemberType(Class> type) {
+ if (type == null) {
+ return false;
+ }
+ if (type.isArray()) {
+ type = type.getComponentType();
+ }
+ return type.isPrimitive() || type.isEnum() || type.isAnnotation()
+ || String.class.equals(type) || Class.class.equals(type);
+ }
+
+ //besides modularity, this has the advantage of autoboxing primitives:
+ /**
+ * Helper method for generating a hash code for a member of an annotation.
+ *
+ * @param name the name of the member
+ * @param value the value of the member
+ * @return a hash code for this member
+ */
+ private static int hashMember(final String name, final Object value) {
+ final int part1 = name.hashCode() * 127;
+ if (value.getClass().isArray()) {
+ return part1 ^ arrayMemberHash(value.getClass().getComponentType(), value);
+ }
+ if (value instanceof Annotation) {
+ return part1 ^ hashCode((Annotation) value);
+ }
+ return part1 ^ value.hashCode();
+ }
+
+ /**
+ * Helper method for checking whether two objects of the given type are
+ * equal. This method is used to compare the parameters of two annotation
+ * instances.
+ *
+ * @param type the type of the objects to be compared
+ * @param o1 the first object
+ * @param o2 the second object
+ * @return a flag whether these objects are equal
+ */
+ private static boolean memberEquals(final Class> type, final Object o1, final Object o2) {
+ if (o1 == o2) {
+ return true;
+ }
+ if (o1 == null || o2 == null) {
+ return false;
+ }
+ if (type.isArray()) {
+ return arrayMemberEquals(type.getComponentType(), o1, o2);
+ }
+ if (type.isAnnotation()) {
+ return equals((Annotation) o1, (Annotation) o2);
+ }
+ return o1.equals(o2);
+ }
+
+ /**
+ * Helper method for comparing two objects of an array type.
+ *
+ * @param componentType the component type of the array
+ * @param o1 the first object
+ * @param o2 the second object
+ * @return a flag whether these objects are equal
+ */
+ private static boolean arrayMemberEquals(final Class> componentType, final Object o1, final Object o2) {
+ if (componentType.isAnnotation()) {
+ return annotationArrayMemberEquals((Annotation[]) o1, (Annotation[]) o2);
+ }
+ if (componentType.equals(Byte.TYPE)) {
+ return Arrays.equals((byte[]) o1, (byte[]) o2);
+ }
+ if (componentType.equals(Short.TYPE)) {
+ return Arrays.equals((short[]) o1, (short[]) o2);
+ }
+ if (componentType.equals(Integer.TYPE)) {
+ return Arrays.equals((int[]) o1, (int[]) o2);
+ }
+ if (componentType.equals(Character.TYPE)) {
+ return Arrays.equals((char[]) o1, (char[]) o2);
+ }
+ if (componentType.equals(Long.TYPE)) {
+ return Arrays.equals((long[]) o1, (long[]) o2);
+ }
+ if (componentType.equals(Float.TYPE)) {
+ return Arrays.equals((float[]) o1, (float[]) o2);
+ }
+ if (componentType.equals(Double.TYPE)) {
+ return Arrays.equals((double[]) o1, (double[]) o2);
+ }
+ if (componentType.equals(Boolean.TYPE)) {
+ return Arrays.equals((boolean[]) o1, (boolean[]) o2);
+ }
+ return Arrays.equals((Object[]) o1, (Object[]) o2);
+ }
+
+ /**
+ * Helper method for comparing two arrays of annotations.
+ *
+ * @param a1 the first array
+ * @param a2 the second array
+ * @return a flag whether these arrays are equal
+ */
+ private static boolean annotationArrayMemberEquals(final Annotation[] a1, final Annotation[] a2) {
+ if (a1.length != a2.length) {
+ return false;
+ }
+ for (int i = 0; i < a1.length; i++) {
+ if (!equals(a1[i], a2[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Helper method for generating a hash code for an array.
+ *
+ * @param componentType the component type of the array
+ * @param o the array
+ * @return a hash code for the specified array
+ */
+ private static int arrayMemberHash(final Class> componentType, final Object o) {
+ if (componentType.equals(Byte.TYPE)) {
+ return Arrays.hashCode((byte[]) o);
+ }
+ if (componentType.equals(Short.TYPE)) {
+ return Arrays.hashCode((short[]) o);
+ }
+ if (componentType.equals(Integer.TYPE)) {
+ return Arrays.hashCode((int[]) o);
+ }
+ if (componentType.equals(Character.TYPE)) {
+ return Arrays.hashCode((char[]) o);
+ }
+ if (componentType.equals(Long.TYPE)) {
+ return Arrays.hashCode((long[]) o);
+ }
+ if (componentType.equals(Float.TYPE)) {
+ return Arrays.hashCode((float[]) o);
+ }
+ if (componentType.equals(Double.TYPE)) {
+ return Arrays.hashCode((double[]) o);
+ }
+ if (componentType.equals(Boolean.TYPE)) {
+ return Arrays.hashCode((boolean[]) o);
+ }
+ return Arrays.hashCode((Object[]) o);
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ArrayUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ArrayUtils.java
new file mode 100644
index 000000000..59dcf9d4b
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ArrayUtils.java
@@ -0,0 +1,7970 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.commons.lang3.mutable.MutableInt;
+
+/**
+ * Operations on arrays, primitive arrays (like {@code int[]}) and
+ * primitive wrapper arrays (like {@code Integer[]}).
+ *
+ *
This class tries to handle {@code null} input gracefully.
+ * An exception will not be thrown for a {@code null}
+ * array input. However, an Object array that contains a {@code null}
+ * element may throw an exception. Each method documents its behaviour.
+ *
+ *
#ThreadSafe#
+ * @since 2.0
+ */
+public class ArrayUtils {
+
+ /**
+ * An empty immutable {@code Object} array.
+ */
+ public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+ /**
+ * An empty immutable {@code Class} array.
+ */
+ public static final Class>[] EMPTY_CLASS_ARRAY = new Class[0];
+ /**
+ * An empty immutable {@code String} array.
+ */
+ public static final String[] EMPTY_STRING_ARRAY = new String[0];
+ /**
+ * An empty immutable {@code long} array.
+ */
+ public static final long[] EMPTY_LONG_ARRAY = new long[0];
+ /**
+ * An empty immutable {@code Long} array.
+ */
+ public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];
+ /**
+ * An empty immutable {@code int} array.
+ */
+ public static final int[] EMPTY_INT_ARRAY = new int[0];
+ /**
+ * An empty immutable {@code Integer} array.
+ */
+ public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];
+ /**
+ * An empty immutable {@code short} array.
+ */
+ public static final short[] EMPTY_SHORT_ARRAY = new short[0];
+ /**
+ * An empty immutable {@code Short} array.
+ */
+ public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];
+ /**
+ * An empty immutable {@code byte} array.
+ */
+ public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+ /**
+ * An empty immutable {@code Byte} array.
+ */
+ public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
+ /**
+ * An empty immutable {@code double} array.
+ */
+ public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
+ /**
+ * An empty immutable {@code Double} array.
+ */
+ public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
+ /**
+ * An empty immutable {@code float} array.
+ */
+ public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
+ /**
+ * An empty immutable {@code Float} array.
+ */
+ public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];
+ /**
+ * An empty immutable {@code boolean} array.
+ */
+ public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
+ /**
+ * An empty immutable {@code Boolean} array.
+ */
+ public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];
+ /**
+ * An empty immutable {@code char} array.
+ */
+ public static final char[] EMPTY_CHAR_ARRAY = new char[0];
+ /**
+ * An empty immutable {@code Character} array.
+ */
+ public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];
+
+ /**
+ * The index value when an element is not found in a list or array: {@code -1}.
+ * This value is returned by methods in this class and can also be used in comparisons with values returned by
+ * various method from {@link java.util.List}.
+ */
+ public static final int INDEX_NOT_FOUND = -1;
+
+ /**
+ *
ArrayUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as ArrayUtils.clone(new int[] {2})
.
+ *
+ *
This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public ArrayUtils() {
+ super();
+ }
+
+
+ // NOTE: Cannot use {@code} to enclose text which includes {}, but
is OK
+
+
+ // Basic methods handling multi-dimensional arrays
+ //-----------------------------------------------------------------------
+ /**
+ *
Outputs an array as a String, treating {@code null} as an empty array.
+ *
+ *
Multi-dimensional arrays are handled correctly, including
+ * multi-dimensional primitive arrays.
+ *
+ *
The format is that of Java source code, for example {a,b}
.
+ *
+ * @param array the array to get a toString for, may be {@code null}
+ * @return a String representation of the array, '{}' if null array input
+ */
+ public static String toString(final Object array) {
+ return toString(array, "{}");
+ }
+
+ /**
+ *
Outputs an array as a String handling {@code null}s.
+ *
+ *
Multi-dimensional arrays are handled correctly, including
+ * multi-dimensional primitive arrays.
+ *
+ *
The format is that of Java source code, for example {a,b}
.
+ *
+ * @param array the array to get a toString for, may be {@code null}
+ * @param stringIfNull the String to return if the array is {@code null}
+ * @return a String representation of the array
+ */
+ public static String toString(final Object array, final String stringIfNull) {
+ if (array == null) {
+ return stringIfNull;
+ }
+ return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString();
+ }
+
+ /**
+ *
Get a hash code for an array handling multi-dimensional arrays correctly.
+ *
+ *
Multi-dimensional primitive arrays are also handled correctly by this method.
+ *
+ * @param array the array to get a hash code for, {@code null} returns zero
+ * @return a hash code for the array
+ */
+ public static int hashCode(final Object array) {
+ return new HashCodeBuilder().append(array).toHashCode();
+ }
+
+ /**
+ *
Compares two arrays, using equals(), handling multi-dimensional arrays
+ * correctly.
+ *
+ *
Multi-dimensional primitive arrays are also handled correctly by this method.
+ *
+ * @param array1 the left hand array to compare, may be {@code null}
+ * @param array2 the right hand array to compare, may be {@code null}
+ * @return {@code true} if the arrays are equal
+ * @deprecated this method has been replaced by {@code java.util.Objects.deepEquals(Object, Object)} and will be
+ * removed from future releases.
+ */
+ @Deprecated
+ public static boolean isEquals(final Object array1, final Object array2) {
+ return new EqualsBuilder().append(array1, array2).isEquals();
+ }
+
+ // To map
+ //-----------------------------------------------------------------------
+ /**
+ *
Converts the given array into a {@link java.util.Map}. Each element of the array
+ * must be either a {@link java.util.Map.Entry} or an Array, containing at least two
+ * elements, where the first element is used as key and the second as
+ * value.
+ *
+ *
This method can be used to initialize:
+ *
+ * // Create a Map mapping colors.
+ * Map colorMap = ArrayUtils.toMap(new String[][] {
+ * {"RED", "#FF0000"},
+ * {"GREEN", "#00FF00"},
+ * {"BLUE", "#0000FF"}});
+ *
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array an array whose elements are either a {@link java.util.Map.Entry} or
+ * an Array containing at least two elements, may be {@code null}
+ * @return a {@code Map} that was created from the array
+ * @throws IllegalArgumentException if one element of this Array is
+ * itself an Array containing less then two elements
+ * @throws IllegalArgumentException if the array contains elements other
+ * than {@link java.util.Map.Entry} and an Array
+ */
+ public static Map toMap(final Object[] array) {
+ if (array == null) {
+ return null;
+ }
+ final Map map = new HashMap((int) (array.length * 1.5));
+ for (int i = 0; i < array.length; i++) {
+ final Object object = array[i];
+ if (object instanceof Map.Entry, ?>) {
+ final Map.Entry,?> entry = (Map.Entry,?>) object;
+ map.put(entry.getKey(), entry.getValue());
+ } else if (object instanceof Object[]) {
+ final Object[] entry = (Object[]) object;
+ if (entry.length < 2) {
+ throw new IllegalArgumentException("Array element " + i + ", '"
+ + object
+ + "', has a length less than 2");
+ }
+ map.put(entry[0], entry[1]);
+ } else {
+ throw new IllegalArgumentException("Array element " + i + ", '"
+ + object
+ + "', is neither of type Map.Entry nor an Array");
+ }
+ }
+ return map;
+ }
+
+ // Generic array
+ //-----------------------------------------------------------------------
+ /**
+ * Create a type-safe generic array.
+ *
+ *
The Java language does not allow an array to be created from a generic type:
+ *
+ *
+ public static <T> T[] createAnArray(int size) {
+ return new T[size]; // compiler error here
+ }
+ public static <T> T[] createAnArray(int size) {
+ return (T[])new Object[size]; // ClassCastException at runtime
+ }
+ *
+ *
+ * Therefore new arrays of generic types can be created with this method.
+ * For example, an array of Strings can be created:
+ *
+ *
+ String[] array = ArrayUtils.toArray("1", "2");
+ String[] emptyArray = ArrayUtils.<String>toArray();
+ *
+ *
+ * The method is typically used in scenarios, where the caller itself uses generic types
+ * that have to be combined into an array.
+ *
+ *
Note, this method makes only sense to provide arguments of the same type so that the
+ * compiler can deduce the type of the array itself. While it is possible to select the
+ * type explicitly like in
+ * Number[] array = ArrayUtils.<Number>toArray(Integer.valueOf(42), Double.valueOf(Math.PI))
,
+ * there is no real advantage when compared to
+ * new Number[] {Integer.valueOf(42), Double.valueOf(Math.PI)}
.
+ *
+ * @param the array's element type
+ * @param items the varargs array items, null allowed
+ * @return the array, not null unless a null array is passed in
+ * @since 3.0
+ */
+ public static T[] toArray(final T... items) {
+ return items;
+ }
+
+ // Clone
+ //-----------------------------------------------------------------------
+ /**
+ * Shallow clones an array returning a typecast result and handling
+ * {@code null}.
+ *
+ *
The objects in the array are not cloned, thus there is no special
+ * handling for multi-dimensional arrays.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param the component type of the array
+ * @param array the array to shallow clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static T[] clone(final T[] array) {
+ if (array == null) {
+ return null;
+ }
+ return array.clone();
+ }
+
+ /**
+ * Clones an array returning a typecast result and handling
+ * {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static long[] clone(final long[] array) {
+ if (array == null) {
+ return null;
+ }
+ return array.clone();
+ }
+
+ /**
+ *
Clones an array returning a typecast result and handling
+ * {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static int[] clone(final int[] array) {
+ if (array == null) {
+ return null;
+ }
+ return array.clone();
+ }
+
+ /**
+ *
Clones an array returning a typecast result and handling
+ * {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static short[] clone(final short[] array) {
+ if (array == null) {
+ return null;
+ }
+ return array.clone();
+ }
+
+ /**
+ *
Clones an array returning a typecast result and handling
+ * {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static char[] clone(final char[] array) {
+ if (array == null) {
+ return null;
+ }
+ return array.clone();
+ }
+
+ /**
+ *
Clones an array returning a typecast result and handling
+ * {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static byte[] clone(final byte[] array) {
+ if (array == null) {
+ return null;
+ }
+ return array.clone();
+ }
+
+ /**
+ *
Clones an array returning a typecast result and handling
+ * {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static double[] clone(final double[] array) {
+ if (array == null) {
+ return null;
+ }
+ return array.clone();
+ }
+
+ /**
+ *
Clones an array returning a typecast result and handling
+ * {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static float[] clone(final float[] array) {
+ if (array == null) {
+ return null;
+ }
+ return array.clone();
+ }
+
+ /**
+ *
Clones an array returning a typecast result and handling
+ * {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array the array to clone, may be {@code null}
+ * @return the cloned array, {@code null} if {@code null} input
+ */
+ public static boolean[] clone(final boolean[] array) {
+ if (array == null) {
+ return null;
+ }
+ return array.clone();
+ }
+
+ // nullToEmpty
+ //-----------------------------------------------------------------------
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @param type the class representation of the desired array
+ * @param the class type
+ * @return the same array, {@code public static} empty array if {@code null}
+ * @throws IllegalArgumentException if the type argument is null
+ * @since 3.5
+ */
+ public static T[] nullToEmpty(final T[] array, final Class type) {
+ if (type == null) {
+ throw new IllegalArgumentException("The type must not be null");
+ }
+
+ if (array == null) {
+ return type.cast(Array.newInstance(type.getComponentType(), 0));
+ }
+ return array;
+ }
+
+
+ /**
+ * Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static Object[] nullToEmpty(final Object[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 3.2
+ */
+ public static Class>[] nullToEmpty(final Class>[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_CLASS_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static String[] nullToEmpty(final String[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_STRING_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static long[] nullToEmpty(final long[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_LONG_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static int[] nullToEmpty(final int[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_INT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static short[] nullToEmpty(final short[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_SHORT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static char[] nullToEmpty(final char[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_CHAR_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static byte[] nullToEmpty(final byte[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static double[] nullToEmpty(final double[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_DOUBLE_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static float[] nullToEmpty(final float[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_FLOAT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static boolean[] nullToEmpty(final boolean[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_BOOLEAN_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static Long[] nullToEmpty(final Long[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_LONG_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static Integer[] nullToEmpty(final Integer[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_INTEGER_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static Short[] nullToEmpty(final Short[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_SHORT_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static Character[] nullToEmpty(final Character[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_CHARACTER_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static Byte[] nullToEmpty(final Byte[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_BYTE_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static Double[] nullToEmpty(final Double[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_DOUBLE_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static Float[] nullToEmpty(final Float[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_FLOAT_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ /**
+ *
Defensive programming technique to change a {@code null}
+ * reference to an empty one.
+ *
+ *
This method returns an empty array for a {@code null} input array.
+ *
+ *
As a memory optimizing technique an empty array passed in will be overridden with
+ * the empty {@code public static} references in this class.
+ *
+ * @param array the array to check for {@code null} or empty
+ * @return the same array, {@code public static} empty array if {@code null} or empty input
+ * @since 2.5
+ */
+ public static Boolean[] nullToEmpty(final Boolean[] array) {
+ if (isEmpty(array)) {
+ return EMPTY_BOOLEAN_OBJECT_ARRAY;
+ }
+ return array;
+ }
+
+ // Subarrays
+ //-----------------------------------------------------------------------
+ /**
+ *
Produces a new array containing the elements between
+ * the start and end indices.
+ *
+ *
The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.
+ *
+ *
The component type of the subarray is always the same as
+ * that of the input array. Thus, if the input is an array of type
+ * {@code Date}, the following usage is envisaged:
+ *
+ *
+ * Date[] someDates = (Date[])ArrayUtils.subarray(allDates, 2, 5);
+ *
+ *
+ * @param the component type of the array
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ * @since 2.1
+ * @see Arrays#copyOfRange(Object[], int, int)
+ */
+ public static T[] subarray(final T[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ final int newSize = endIndexExclusive - startIndexInclusive;
+ final Class> type = array.getClass().getComponentType();
+ if (newSize <= 0) {
+ @SuppressWarnings("unchecked") // OK, because array is of type T
+ final T[] emptyArray = (T[]) Array.newInstance(type, 0);
+ return emptyArray;
+ }
+ @SuppressWarnings("unchecked") // OK, because array is of type T
+ final
+ T[] subarray = (T[]) Array.newInstance(type, newSize);
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ * Produces a new {@code long} array containing the elements
+ * between the start and end indices.
+ *
+ *
The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ * @since 2.1
+ * @see Arrays#copyOfRange(long[], int, int)
+ */
+ public static long[] subarray(final long[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ final int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_LONG_ARRAY;
+ }
+
+ final long[] subarray = new long[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ *
Produces a new {@code int} array containing the elements
+ * between the start and end indices.
+ *
+ *
The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ * @since 2.1
+ * @see Arrays#copyOfRange(int[], int, int)
+ */
+ public static int[] subarray(final int[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ final int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_INT_ARRAY;
+ }
+
+ final int[] subarray = new int[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ *
Produces a new {@code short} array containing the elements
+ * between the start and end indices.
+ *
+ *
The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ * @since 2.1
+ * @see Arrays#copyOfRange(short[], int, int)
+ */
+ public static short[] subarray(final short[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ final int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+
+ final short[] subarray = new short[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ *
Produces a new {@code char} array containing the elements
+ * between the start and end indices.
+ *
+ *
The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ * @since 2.1
+ * @see Arrays#copyOfRange(char[], int, int)
+ */
+ public static char[] subarray(final char[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ final int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_CHAR_ARRAY;
+ }
+
+ final char[] subarray = new char[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ *
Produces a new {@code byte} array containing the elements
+ * between the start and end indices.
+ *
+ *
The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ * @since 2.1
+ * @see Arrays#copyOfRange(byte[], int, int)
+ */
+ public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ final int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_BYTE_ARRAY;
+ }
+
+ final byte[] subarray = new byte[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ *
Produces a new {@code double} array containing the elements
+ * between the start and end indices.
+ *
+ *
The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ * @since 2.1
+ * @see Arrays#copyOfRange(double[], int, int)
+ */
+ public static double[] subarray(final double[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ final int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_DOUBLE_ARRAY;
+ }
+
+ final double[] subarray = new double[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ *
Produces a new {@code float} array containing the elements
+ * between the start and end indices.
+ *
+ *
The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ * @since 2.1
+ * @see Arrays#copyOfRange(float[], int, int)
+ */
+ public static float[] subarray(final float[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ final int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_FLOAT_ARRAY;
+ }
+
+ final float[] subarray = new float[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ /**
+ *
Produces a new {@code boolean} array containing the elements
+ * between the start and end indices.
+ *
+ *
The start index is inclusive, the end index exclusive.
+ * Null array input produces null output.
+ *
+ * @param array the array
+ * @param startIndexInclusive the starting index. Undervalue (<0)
+ * is promoted to 0, overvalue (>array.length) results
+ * in an empty array.
+ * @param endIndexExclusive elements up to endIndex-1 are present in the
+ * returned subarray. Undervalue (< startIndex) produces
+ * empty array, overvalue (>array.length) is demoted to
+ * array length.
+ * @return a new array containing the elements between
+ * the start and end indices.
+ * @since 2.1
+ * @see Arrays#copyOfRange(boolean[], int, int)
+ */
+ public static boolean[] subarray(final boolean[] array, int startIndexInclusive, int endIndexExclusive) {
+ if (array == null) {
+ return null;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive > array.length) {
+ endIndexExclusive = array.length;
+ }
+ final int newSize = endIndexExclusive - startIndexInclusive;
+ if (newSize <= 0) {
+ return EMPTY_BOOLEAN_ARRAY;
+ }
+
+ final boolean[] subarray = new boolean[newSize];
+ System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
+ return subarray;
+ }
+
+ // Is same length
+ //-----------------------------------------------------------------------
+ /**
+ *
Checks whether two arrays are the same length, treating
+ * {@code null} arrays as length {@code 0}.
+ *
+ *
Any multi-dimensional aspects of the arrays are ignored.
+ *
+ * @param array1 the first array, may be {@code null}
+ * @param array2 the second array, may be {@code null}
+ * @return {@code true} if length of arrays matches, treating
+ * {@code null} as an empty array
+ */
+ public static boolean isSameLength(final Object[] array1, final Object[] array2) {
+ return getLength(array1) == getLength(array2);
+ }
+
+ /**
+ *
Checks whether two arrays are the same length, treating
+ * {@code null} arrays as length {@code 0}.
+ *
+ * @param array1 the first array, may be {@code null}
+ * @param array2 the second array, may be {@code null}
+ * @return {@code true} if length of arrays matches, treating
+ * {@code null} as an empty array
+ */
+ public static boolean isSameLength(final long[] array1, final long[] array2) {
+ return getLength(array1) == getLength(array2);
+ }
+
+ /**
+ *
Checks whether two arrays are the same length, treating
+ * {@code null} arrays as length {@code 0}.
+ *
+ * @param array1 the first array, may be {@code null}
+ * @param array2 the second array, may be {@code null}
+ * @return {@code true} if length of arrays matches, treating
+ * {@code null} as an empty array
+ */
+ public static boolean isSameLength(final int[] array1, final int[] array2) {
+ return getLength(array1) == getLength(array2);
+ }
+
+ /**
+ *
Checks whether two arrays are the same length, treating
+ * {@code null} arrays as length {@code 0}.
+ *
+ * @param array1 the first array, may be {@code null}
+ * @param array2 the second array, may be {@code null}
+ * @return {@code true} if length of arrays matches, treating
+ * {@code null} as an empty array
+ */
+ public static boolean isSameLength(final short[] array1, final short[] array2) {
+ return getLength(array1) == getLength(array2);
+ }
+
+ /**
+ *
Checks whether two arrays are the same length, treating
+ * {@code null} arrays as length {@code 0}.
+ *
+ * @param array1 the first array, may be {@code null}
+ * @param array2 the second array, may be {@code null}
+ * @return {@code true} if length of arrays matches, treating
+ * {@code null} as an empty array
+ */
+ public static boolean isSameLength(final char[] array1, final char[] array2) {
+ return getLength(array1) == getLength(array2);
+ }
+
+ /**
+ *
Checks whether two arrays are the same length, treating
+ * {@code null} arrays as length {@code 0}.
+ *
+ * @param array1 the first array, may be {@code null}
+ * @param array2 the second array, may be {@code null}
+ * @return {@code true} if length of arrays matches, treating
+ * {@code null} as an empty array
+ */
+ public static boolean isSameLength(final byte[] array1, final byte[] array2) {
+ return getLength(array1) == getLength(array2);
+ }
+
+ /**
+ *
Checks whether two arrays are the same length, treating
+ * {@code null} arrays as length {@code 0}.
+ *
+ * @param array1 the first array, may be {@code null}
+ * @param array2 the second array, may be {@code null}
+ * @return {@code true} if length of arrays matches, treating
+ * {@code null} as an empty array
+ */
+ public static boolean isSameLength(final double[] array1, final double[] array2) {
+ return getLength(array1) == getLength(array2);
+ }
+
+ /**
+ *
Checks whether two arrays are the same length, treating
+ * {@code null} arrays as length {@code 0}.
+ *
+ * @param array1 the first array, may be {@code null}
+ * @param array2 the second array, may be {@code null}
+ * @return {@code true} if length of arrays matches, treating
+ * {@code null} as an empty array
+ */
+ public static boolean isSameLength(final float[] array1, final float[] array2) {
+ return getLength(array1) == getLength(array2);
+ }
+
+ /**
+ *
Checks whether two arrays are the same length, treating
+ * {@code null} arrays as length {@code 0}.
+ *
+ * @param array1 the first array, may be {@code null}
+ * @param array2 the second array, may be {@code null}
+ * @return {@code true} if length of arrays matches, treating
+ * {@code null} as an empty array
+ */
+ public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
+ return getLength(array1) == getLength(array2);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ *
Returns the length of the specified array.
+ * This method can deal with {@code Object} arrays and with primitive arrays.
+ *
+ *
If the input array is {@code null}, {@code 0} is returned.
+ *
+ *
+ * ArrayUtils.getLength(null) = 0
+ * ArrayUtils.getLength([]) = 0
+ * ArrayUtils.getLength([null]) = 1
+ * ArrayUtils.getLength([true, false]) = 2
+ * ArrayUtils.getLength([1, 2, 3]) = 3
+ * ArrayUtils.getLength(["a", "b", "c"]) = 3
+ *
+ *
+ * @param array the array to retrieve the length from, may be null
+ * @return The length of the array, or {@code 0} if the array is {@code null}
+ * @throws IllegalArgumentException if the object argument is not an array.
+ * @since 2.1
+ */
+ public static int getLength(final Object array) {
+ if (array == null) {
+ return 0;
+ }
+ return Array.getLength(array);
+ }
+
+ /**
+ * Checks whether two arrays are the same type taking into account
+ * multi-dimensional arrays.
+ *
+ * @param array1 the first array, must not be {@code null}
+ * @param array2 the second array, must not be {@code null}
+ * @return {@code true} if type of arrays matches
+ * @throws IllegalArgumentException if either array is {@code null}
+ */
+ public static boolean isSameType(final Object array1, final Object array2) {
+ if (array1 == null || array2 == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ }
+ return array1.getClass().getName().equals(array2.getClass().getName());
+ }
+
+ // Reverse
+ //-----------------------------------------------------------------------
+ /**
+ *
Reverses the order of the given array.
+ *
+ *
There is no special handling for multi-dimensional arrays.
+ *
+ *
This method does nothing for a {@code null} input array.
+ *
+ * @param array the array to reverse, may be {@code null}
+ */
+ public static void reverse(final Object[] array) {
+ if (array == null) {
+ return;
+ }
+ reverse(array, 0, array.length);
+ }
+
+ /**
+ *
Reverses the order of the given array.
+ *
+ *
This method does nothing for a {@code null} input array.
+ *
+ * @param array the array to reverse, may be {@code null}
+ */
+ public static void reverse(final long[] array) {
+ if (array == null) {
+ return;
+ }
+ reverse(array, 0, array.length);
+ }
+
+ /**
+ *
Reverses the order of the given array.
+ *
+ *
This method does nothing for a {@code null} input array.
+ *
+ * @param array the array to reverse, may be {@code null}
+ */
+ public static void reverse(final int[] array) {
+ if (array == null) {
+ return;
+ }
+ reverse(array, 0, array.length);
+ }
+
+ /**
+ *
Reverses the order of the given array.
+ *
+ *
This method does nothing for a {@code null} input array.
+ *
+ * @param array the array to reverse, may be {@code null}
+ */
+ public static void reverse(final short[] array) {
+ if (array == null) {
+ return;
+ }
+ reverse(array, 0, array.length);
+ }
+
+ /**
+ *
Reverses the order of the given array.
+ *
+ *
This method does nothing for a {@code null} input array.
+ *
+ * @param array the array to reverse, may be {@code null}
+ */
+ public static void reverse(final char[] array) {
+ if (array == null) {
+ return;
+ }
+ reverse(array, 0, array.length);
+ }
+
+ /**
+ *
Reverses the order of the given array.
+ *
+ *
This method does nothing for a {@code null} input array.
+ *
+ * @param array the array to reverse, may be {@code null}
+ */
+ public static void reverse(final byte[] array) {
+ if (array == null) {
+ return;
+ }
+ reverse(array, 0, array.length);
+ }
+
+ /**
+ *
Reverses the order of the given array.
+ *
+ *
This method does nothing for a {@code null} input array.
+ *
+ * @param array the array to reverse, may be {@code null}
+ */
+ public static void reverse(final double[] array) {
+ if (array == null) {
+ return;
+ }
+ reverse(array, 0, array.length);
+ }
+
+ /**
+ *
Reverses the order of the given array.
+ *
+ *
This method does nothing for a {@code null} input array.
+ *
+ * @param array the array to reverse, may be {@code null}
+ */
+ public static void reverse(final float[] array) {
+ if (array == null) {
+ return;
+ }
+ reverse(array, 0, array.length);
+ }
+
+ /**
+ *
Reverses the order of the given array.
+ *
+ *
This method does nothing for a {@code null} input array.
+ *
+ * @param array the array to reverse, may be {@code null}
+ */
+ public static void reverse(final boolean[] array) {
+ if (array == null) {
+ return;
+ }
+ reverse(array, 0, array.length);
+ }
+
+ /**
+ *
+ * Reverses the order of the given array in the given range.
+ *
+ *
+ * This method does nothing for a {@code null} input array.
+ *
+ * @param array
+ * the array to reverse, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @since 3.2
+ */
+ public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {
+ if (array == null) {
+ return;
+ }
+ int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
+ int j = Math.min(array.length, endIndexExclusive) - 1;
+ boolean tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ *
+ * Reverses the order of the given array in the given range.
+ *
+ *
+ * This method does nothing for a {@code null} input array.
+ *
+ * @param array
+ * the array to reverse, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @since 3.2
+ */
+ public static void reverse(final byte[] array, final int startIndexInclusive, final int endIndexExclusive) {
+ if (array == null) {
+ return;
+ }
+ int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
+ int j = Math.min(array.length, endIndexExclusive) - 1;
+ byte tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ *
+ * Reverses the order of the given array in the given range.
+ *
+ *
+ * This method does nothing for a {@code null} input array.
+ *
+ * @param array
+ * the array to reverse, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @since 3.2
+ */
+ public static void reverse(final char[] array, final int startIndexInclusive, final int endIndexExclusive) {
+ if (array == null) {
+ return;
+ }
+ int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
+ int j = Math.min(array.length, endIndexExclusive) - 1;
+ char tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ *
+ * Reverses the order of the given array in the given range.
+ *
+ *
+ * This method does nothing for a {@code null} input array.
+ *
+ * @param array
+ * the array to reverse, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @since 3.2
+ */
+ public static void reverse(final double[] array, final int startIndexInclusive, final int endIndexExclusive) {
+ if (array == null) {
+ return;
+ }
+ int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
+ int j = Math.min(array.length, endIndexExclusive) - 1;
+ double tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ *
+ * Reverses the order of the given array in the given range.
+ *
+ *
+ * This method does nothing for a {@code null} input array.
+ *
+ * @param array
+ * the array to reverse, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @since 3.2
+ */
+ public static void reverse(final float[] array, final int startIndexInclusive, final int endIndexExclusive) {
+ if (array == null) {
+ return;
+ }
+ int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
+ int j = Math.min(array.length, endIndexExclusive) - 1;
+ float tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ *
+ * Reverses the order of the given array in the given range.
+ *
+ *
+ * This method does nothing for a {@code null} input array.
+ *
+ * @param array
+ * the array to reverse, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @since 3.2
+ */
+ public static void reverse(final int[] array, final int startIndexInclusive, final int endIndexExclusive) {
+ if (array == null) {
+ return;
+ }
+ int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
+ int j = Math.min(array.length, endIndexExclusive) - 1;
+ int tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ *
+ * Reverses the order of the given array in the given range.
+ *
+ *
+ * This method does nothing for a {@code null} input array.
+ *
+ * @param array
+ * the array to reverse, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @since 3.2
+ */
+ public static void reverse(final long[] array, final int startIndexInclusive, final int endIndexExclusive) {
+ if (array == null) {
+ return;
+ }
+ int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
+ int j = Math.min(array.length, endIndexExclusive) - 1;
+ long tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ *
+ * Reverses the order of the given array in the given range.
+ *
+ *
+ * This method does nothing for a {@code null} input array.
+ *
+ * @param array
+ * the array to reverse, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Under value (<0) is promoted to 0, over value (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are reversed in the array. Under value (< start index) results in no
+ * change. Over value (>array.length) is demoted to array length.
+ * @since 3.2
+ */
+ public static void reverse(final Object[] array, final int startIndexInclusive, final int endIndexExclusive) {
+ if (array == null) {
+ return;
+ }
+ int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
+ int j = Math.min(array.length, endIndexExclusive) - 1;
+ Object tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ /**
+ *
+ * Reverses the order of the given array in the given range.
+ *
+ *
+ * This method does nothing for a {@code null} input array.
+ *
+ * @param array
+ * the array to reverse, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @since 3.2
+ */
+ public static void reverse(final short[] array, final int startIndexInclusive, final int endIndexExclusive) {
+ if (array == null) {
+ return;
+ }
+ int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
+ int j = Math.min(array.length, endIndexExclusive) - 1;
+ short tmp;
+ while (j > i) {
+ tmp = array[j];
+ array[j] = array[i];
+ array[i] = tmp;
+ j--;
+ i++;
+ }
+ }
+
+ // Swap
+ //-----------------------------------------------------------------------
+ /**
+ * Swaps two elements in the given array.
+ *
+ *
There is no special handling for multi-dimensional arrays. This method
+ * does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap(["1", "2", "3"], 0, 2) -> ["3", "2", "1"]
+ * ArrayUtils.swap(["1", "2", "3"], 0, 0) -> ["1", "2", "3"]
+ * ArrayUtils.swap(["1", "2", "3"], 1, 0) -> ["2", "1", "3"]
+ * ArrayUtils.swap(["1", "2", "3"], 0, 5) -> ["1", "2", "3"]
+ * ArrayUtils.swap(["1", "2", "3"], -1, 1) -> ["2", "1", "3"]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element to swap
+ * @param offset2 the index of the second element to swap
+ * @since 3.5
+ */
+ public static void swap(final Object[] array, int offset1, int offset2) {
+ if (array == null || array.length == 0) {
+ return;
+ }
+ swap(array, offset1, offset2, 1);
+ }
+
+ /**
+ * Swaps two elements in the given long array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([true, false, true], 0, 2) -> [true, false, true]
+ * ArrayUtils.swap([true, false, true], 0, 0) -> [true, false, true]
+ * ArrayUtils.swap([true, false, true], 1, 0) -> [false, true, true]
+ * ArrayUtils.swap([true, false, true], 0, 5) -> [true, false, true]
+ * ArrayUtils.swap([true, false, true], -1, 1) -> [false, true, true]
+ *
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element to swap
+ * @param offset2 the index of the second element to swap
+ * @since 3.5
+ */
+ public static void swap(final long[] array, int offset1, int offset2) {
+ if (array == null || array.length == 0) {
+ return;
+ }
+ swap(array, offset1, offset2, 1);
+ }
+
+ /**
+ * Swaps two elements in the given int array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
+ * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
+ * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element to swap
+ * @param offset2 the index of the second element to swap
+ * @since 3.5
+ */
+ public static void swap(final int[] array, int offset1, int offset2) {
+ if (array == null || array.length == 0) {
+ return;
+ }
+ swap(array, offset1, offset2, 1);
+ }
+
+ /**
+ * Swaps two elements in the given short array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
+ * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
+ * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element to swap
+ * @param offset2 the index of the second element to swap
+ * @since 3.5
+ */
+ public static void swap(final short[] array, int offset1, int offset2) {
+ if (array == null || array.length == 0) {
+ return;
+ }
+ swap(array, offset1, offset2, 1);
+ }
+
+ /**
+ * Swaps two elements in the given char array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
+ * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
+ * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element to swap
+ * @param offset2 the index of the second element to swap
+ * @since 3.5
+ */
+ public static void swap(final char[] array, int offset1, int offset2) {
+ if (array == null || array.length == 0) {
+ return;
+ }
+ swap(array, offset1, offset2, 1);
+ }
+
+ /**
+ * Swaps two elements in the given byte array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
+ * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
+ * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element to swap
+ * @param offset2 the index of the second element to swap
+ * @since 3.5
+ */
+ public static void swap(final byte[] array, int offset1, int offset2) {
+ if (array == null || array.length == 0) {
+ return;
+ }
+ swap(array, offset1, offset2, 1);
+ }
+
+ /**
+ * Swaps two elements in the given double array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
+ * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
+ * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element to swap
+ * @param offset2 the index of the second element to swap
+ * @since 3.5
+ */
+ public static void swap(final double[] array, int offset1, int offset2) {
+ if (array == null || array.length == 0) {
+ return;
+ }
+ swap(array, offset1, offset2, 1);
+ }
+
+ /**
+ * Swaps two elements in the given float array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
+ * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
+ * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element to swap
+ * @param offset2 the index of the second element to swap
+ * @since 3.5
+ */
+ public static void swap(final float[] array, int offset1, int offset2) {
+ if (array == null || array.length == 0) {
+ return;
+ }
+ swap(array, offset1, offset2, 1);
+ }
+
+ /**
+ * Swaps two elements in the given boolean array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for a {@code null} or empty input array or for overflow indices.
+ * Negative indices are promoted to 0(zero).
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3], 0, 2) -> [3, 2, 1]
+ * ArrayUtils.swap([1, 2, 3], 0, 0) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], 1, 0) -> [2, 1, 3]
+ * ArrayUtils.swap([1, 2, 3], 0, 5) -> [1, 2, 3]
+ * ArrayUtils.swap([1, 2, 3], -1, 1) -> [2, 1, 3]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element to swap
+ * @param offset2 the index of the second element to swap
+ * @since 3.5
+ */
+ public static void swap(final boolean[] array, int offset1, int offset2) {
+ if (array == null || array.length == 0) {
+ return;
+ }
+ swap(array, offset1, offset2, 1);
+ }
+
+ /**
+ * Swaps a series of elements in the given boolean array.
+ *
+ * This method does nothing for a {@code null} or empty input array or
+ * for overflow indices. Negative indices are promoted to 0(zero). If any
+ * of the sub-arrays to swap falls outside of the given array, then the
+ * swap is stopped at the end of the array and as many as possible elements
+ * are swapped.
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([true, false, true, false], 0, 2, 1) -> [true, false, true, false]
+ * ArrayUtils.swap([true, false, true, false], 0, 0, 1) -> [true, false, true, false]
+ * ArrayUtils.swap([true, false, true, false], 0, 2, 2) -> [true, false, true, false]
+ * ArrayUtils.swap([true, false, true, false], -3, 2, 2) -> [true, false, true, false]
+ * ArrayUtils.swap([true, false, true, false], 0, 3, 3) -> [false, false, true, true]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element in the series to swap
+ * @param offset2 the index of the second element in the series to swap
+ * @param len the number of elements to swap starting with the given indices
+ * @since 3.5
+ */
+ public static void swap(final boolean[] array, int offset1, int offset2, int len) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
+ return;
+ }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ boolean aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+ }
+
+ /**
+ * Swaps a series of elements in the given byte array.
+ *
+ * This method does nothing for a {@code null} or empty input array or
+ * for overflow indices. Negative indices are promoted to 0(zero). If any
+ * of the sub-arrays to swap falls outside of the given array, then the
+ * swap is stopped at the end of the array and as many as possible elements
+ * are swapped.
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element in the series to swap
+ * @param offset2 the index of the second element in the series to swap
+ * @param len the number of elements to swap starting with the given indices
+ * @since 3.5
+ */
+ public static void swap(final byte[] array, int offset1, int offset2, int len) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
+ return;
+ }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ byte aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+ }
+
+ /**
+ * Swaps a series of elements in the given char array.
+ *
+ * This method does nothing for a {@code null} or empty input array or
+ * for overflow indices. Negative indices are promoted to 0(zero). If any
+ * of the sub-arrays to swap falls outside of the given array, then the
+ * swap is stopped at the end of the array and as many as possible elements
+ * are swapped.
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element in the series to swap
+ * @param offset2 the index of the second element in the series to swap
+ * @param len the number of elements to swap starting with the given indices
+ * @since 3.5
+ */
+ public static void swap(final char[] array, int offset1, int offset2, int len) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
+ return;
+ }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ char aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+ }
+
+ /**
+ * Swaps a series of elements in the given double array.
+ *
+ * This method does nothing for a {@code null} or empty input array or
+ * for overflow indices. Negative indices are promoted to 0(zero). If any
+ * of the sub-arrays to swap falls outside of the given array, then the
+ * swap is stopped at the end of the array and as many as possible elements
+ * are swapped.
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element in the series to swap
+ * @param offset2 the index of the second element in the series to swap
+ * @param len the number of elements to swap starting with the given indices
+ * @since 3.5
+ */
+ public static void swap(final double[] array, int offset1, int offset2, int len) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
+ return;
+ }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ double aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+ }
+
+ /**
+ * Swaps a series of elements in the given float array.
+ *
+ * This method does nothing for a {@code null} or empty input array or
+ * for overflow indices. Negative indices are promoted to 0(zero). If any
+ * of the sub-arrays to swap falls outside of the given array, then the
+ * swap is stopped at the end of the array and as many as possible elements
+ * are swapped.
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element in the series to swap
+ * @param offset2 the index of the second element in the series to swap
+ * @param len the number of elements to swap starting with the given indices
+ * @since 3.5
+ */
+ public static void swap(final float[] array, int offset1, int offset2, int len) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
+ return;
+ }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ float aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+
+ }
+
+ /**
+ * Swaps a series of elements in the given int array.
+ *
+ * This method does nothing for a {@code null} or empty input array or
+ * for overflow indices. Negative indices are promoted to 0(zero). If any
+ * of the sub-arrays to swap falls outside of the given array, then the
+ * swap is stopped at the end of the array and as many as possible elements
+ * are swapped.
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element in the series to swap
+ * @param offset2 the index of the second element in the series to swap
+ * @param len the number of elements to swap starting with the given indices
+ * @since 3.5
+ */
+ public static void swap(final int[] array, int offset1, int offset2, int len) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
+ return;
+ }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ int aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+ }
+
+ /**
+ * Swaps a series of elements in the given long array.
+ *
+ * This method does nothing for a {@code null} or empty input array or
+ * for overflow indices. Negative indices are promoted to 0(zero). If any
+ * of the sub-arrays to swap falls outside of the given array, then the
+ * swap is stopped at the end of the array and as many as possible elements
+ * are swapped.
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element in the series to swap
+ * @param offset2 the index of the second element in the series to swap
+ * @param len the number of elements to swap starting with the given indices
+ * @since 3.5
+ */
+ public static void swap(final long[] array, int offset1, int offset2, int len) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
+ return;
+ }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ long aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+ }
+
+ /**
+ * Swaps a series of elements in the given array.
+ *
+ * This method does nothing for a {@code null} or empty input array or
+ * for overflow indices. Negative indices are promoted to 0(zero). If any
+ * of the sub-arrays to swap falls outside of the given array, then the
+ * swap is stopped at the end of the array and as many as possible elements
+ * are swapped.
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap(["1", "2", "3", "4"], 0, 2, 1) -> ["3", "2", "1", "4"]
+ * ArrayUtils.swap(["1", "2", "3", "4"], 0, 0, 1) -> ["1", "2", "3", "4"]
+ * ArrayUtils.swap(["1", "2", "3", "4"], 2, 0, 2) -> ["3", "4", "1", "2"]
+ * ArrayUtils.swap(["1", "2", "3", "4"], -3, 2, 2) -> ["3", "4", "1", "2"]
+ * ArrayUtils.swap(["1", "2", "3", "4"], 0, 3, 3) -> ["4", "2", "3", "1"]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element in the series to swap
+ * @param offset2 the index of the second element in the series to swap
+ * @param len the number of elements to swap starting with the given indices
+ * @since 3.5
+ */
+ public static void swap(final Object[] array, int offset1, int offset2, int len) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
+ return;
+ }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ Object aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+ }
+
+ /**
+ * Swaps a series of elements in the given short array.
+ *
+ * This method does nothing for a {@code null} or empty input array or
+ * for overflow indices. Negative indices are promoted to 0(zero). If any
+ * of the sub-arrays to swap falls outside of the given array, then the
+ * swap is stopped at the end of the array and as many as possible elements
+ * are swapped.
+ *
+ * Examples:
+ *
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -> [3, 2, 1, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -> [1, 2, 3, 4]
+ * ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -> [3, 4, 1, 2]
+ * ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -> [4, 2, 3, 1]
+ *
+ *
+ * @param array the array to swap, may be {@code null}
+ * @param offset1 the index of the first element in the series to swap
+ * @param offset2 the index of the second element in the series to swap
+ * @param len the number of elements to swap starting with the given indices
+ * @since 3.5
+ */
+ public static void swap(final short[] array, int offset1, int offset2, int len) {
+ if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
+ return;
+ }
+ if (offset1 < 0) {
+ offset1 = 0;
+ }
+ if (offset2 < 0) {
+ offset2 = 0;
+ }
+ if (offset1 == offset2) {
+ return;
+ }
+ len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
+ for (int i = 0; i < len; i++, offset1++, offset2++) {
+ short aux = array[offset1];
+ array[offset1] = array[offset2];
+ array[offset2] = aux;
+ }
+ }
+
+ // Shift
+ //-----------------------------------------------------------------------
+ /**
+ * Shifts the order of the given array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array the array to shift, may be {@code null}
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final Object[] array, int offset) {
+ if (array == null) {
+ return;
+ }
+ shift(array, 0, array.length, offset);
+ }
+
+ /**
+ * Shifts the order of the given long array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array the array to shift, may be {@code null}
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final long[] array, int offset) {
+ if (array == null) {
+ return;
+ }
+ shift(array, 0, array.length, offset);
+ }
+
+ /**
+ * Shifts the order of the given int array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array the array to shift, may be {@code null}
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final int[] array, int offset) {
+ if (array == null) {
+ return;
+ }
+ shift(array, 0, array.length, offset);
+ }
+
+ /**
+ * Shifts the order of the given short array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array the array to shift, may be {@code null}
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final short[] array, int offset) {
+ if (array == null) {
+ return;
+ }
+ shift(array, 0, array.length, offset);
+ }
+
+ /**
+ * Shifts the order of the given char array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array the array to shift, may be {@code null}
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final char[] array, int offset) {
+ if (array == null) {
+ return;
+ }
+ shift(array, 0, array.length, offset);
+ }
+
+ /**
+ * Shifts the order of the given byte array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array the array to shift, may be {@code null}
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final byte[] array, int offset) {
+ if (array == null) {
+ return;
+ }
+ shift(array, 0, array.length, offset);
+ }
+
+ /**
+ * Shifts the order of the given double array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array the array to shift, may be {@code null}
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final double[] array, int offset) {
+ if (array == null) {
+ return;
+ }
+ shift(array, 0, array.length, offset);
+ }
+
+ /**
+ * Shifts the order of the given float array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array the array to shift, may be {@code null}
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final float[] array, int offset) {
+ if (array == null) {
+ return;
+ }
+ shift(array, 0, array.length, offset);
+ }
+
+ /**
+ * Shifts the order of the given boolean array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array the array to shift, may be {@code null}
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final boolean[] array, int offset) {
+ if (array == null) {
+ return;
+ }
+ shift(array, 0, array.length, offset);
+ }
+
+ /**
+ * Shifts the order of a series of elements in the given boolean array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array
+ * the array to shift, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are shiftd in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final boolean[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
+ if (array == null) {
+ return;
+ }
+ if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
+ return;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive >= array.length) {
+ endIndexExclusive = array.length;
+ }
+ int n = endIndexExclusive - startIndexInclusive;
+ if (n <= 1) {
+ return;
+ }
+ offset %= n;
+ if (offset < 0) {
+ offset += n;
+ }
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
+ while (n > 1 && offset > 0) {
+ int n_offset = n - offset;
+
+ if (offset > n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
+ n = offset;
+ offset -= n_offset;
+ } else if (offset < n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ startIndexInclusive += offset;
+ n = n_offset;
+ } else {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Shifts the order of a series of elements in the given byte array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array
+ * the array to shift, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are shiftd in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final byte[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
+ if (array == null) {
+ return;
+ }
+ if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
+ return;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive >= array.length) {
+ endIndexExclusive = array.length;
+ }
+ int n = endIndexExclusive - startIndexInclusive;
+ if (n <= 1) {
+ return;
+ }
+ offset %= n;
+ if (offset < 0) {
+ offset += n;
+ }
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
+ while (n > 1 && offset > 0) {
+ int n_offset = n - offset;
+
+ if (offset > n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
+ n = offset;
+ offset -= n_offset;
+ } else if (offset < n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ startIndexInclusive += offset;
+ n = n_offset;
+ } else {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Shifts the order of a series of elements in the given char array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array
+ * the array to shift, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are shiftd in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final char[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
+ if (array == null) {
+ return;
+ }
+ if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
+ return;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive >= array.length) {
+ endIndexExclusive = array.length;
+ }
+ int n = endIndexExclusive - startIndexInclusive;
+ if (n <= 1) {
+ return;
+ }
+ offset %= n;
+ if (offset < 0) {
+ offset += n;
+ }
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
+ while (n > 1 && offset > 0) {
+ int n_offset = n - offset;
+
+ if (offset > n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
+ n = offset;
+ offset -= n_offset;
+ } else if (offset < n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ startIndexInclusive += offset;
+ n = n_offset;
+ } else {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Shifts the order of a series of elements in the given double array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array
+ * the array to shift, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are shiftd in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final double[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
+ if (array == null) {
+ return;
+ }
+ if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
+ return;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive >= array.length) {
+ endIndexExclusive = array.length;
+ }
+ int n = endIndexExclusive - startIndexInclusive;
+ if (n <= 1) {
+ return;
+ }
+ offset %= n;
+ if (offset < 0) {
+ offset += n;
+ }
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
+ while (n > 1 && offset > 0) {
+ int n_offset = n - offset;
+
+ if (offset > n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
+ n = offset;
+ offset -= n_offset;
+ } else if (offset < n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ startIndexInclusive += offset;
+ n = n_offset;
+ } else {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Shifts the order of a series of elements in the given float array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array
+ * the array to shift, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are shiftd in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final float[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
+ if (array == null) {
+ return;
+ }
+ if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
+ return;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive >= array.length) {
+ endIndexExclusive = array.length;
+ }
+ int n = endIndexExclusive - startIndexInclusive;
+ if (n <= 1) {
+ return;
+ }
+ offset %= n;
+ if (offset < 0) {
+ offset += n;
+ }
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
+ while (n > 1 && offset > 0) {
+ int n_offset = n - offset;
+
+ if (offset > n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
+ n = offset;
+ offset -= n_offset;
+ } else if (offset < n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ startIndexInclusive += offset;
+ n = n_offset;
+ } else {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Shifts the order of a series of elements in the given int array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array
+ * the array to shift, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are shiftd in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final int[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
+ if (array == null) {
+ return;
+ }
+ if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
+ return;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive >= array.length) {
+ endIndexExclusive = array.length;
+ }
+ int n = endIndexExclusive - startIndexInclusive;
+ if (n <= 1) {
+ return;
+ }
+ offset %= n;
+ if (offset < 0) {
+ offset += n;
+ }
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
+ while (n > 1 && offset > 0) {
+ int n_offset = n - offset;
+
+ if (offset > n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
+ n = offset;
+ offset -= n_offset;
+ } else if (offset < n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ startIndexInclusive += offset;
+ n = n_offset;
+ } else {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Shifts the order of a series of elements in the given long array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array
+ * the array to shift, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are shiftd in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final long[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
+ if (array == null) {
+ return;
+ }
+ if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
+ return;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive >= array.length) {
+ endIndexExclusive = array.length;
+ }
+ int n = endIndexExclusive - startIndexInclusive;
+ if (n <= 1) {
+ return;
+ }
+ offset %= n;
+ if (offset < 0) {
+ offset += n;
+ }
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
+ while (n > 1 && offset > 0) {
+ int n_offset = n - offset;
+
+ if (offset > n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
+ n = offset;
+ offset -= n_offset;
+ } else if (offset < n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ startIndexInclusive += offset;
+ n = n_offset;
+ } else {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Shifts the order of a series of elements in the given array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array
+ * the array to shift, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are shiftd in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final Object[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
+ if (array == null) {
+ return;
+ }
+ if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
+ return;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive >= array.length) {
+ endIndexExclusive = array.length;
+ }
+ int n = endIndexExclusive - startIndexInclusive;
+ if (n <= 1) {
+ return;
+ }
+ offset %= n;
+ if (offset < 0) {
+ offset += n;
+ }
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
+ while (n > 1 && offset > 0) {
+ int n_offset = n - offset;
+
+ if (offset > n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
+ n = offset;
+ offset -= n_offset;
+ } else if (offset < n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ startIndexInclusive += offset;
+ n = n_offset;
+ } else {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Shifts the order of a series of elements in the given short array.
+ *
+ * There is no special handling for multi-dimensional arrays. This method
+ * does nothing for {@code null} or empty input arrays.
+ *
+ * @param array
+ * the array to shift, may be {@code null}
+ * @param startIndexInclusive
+ * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no
+ * change.
+ * @param endIndexExclusive
+ * elements up to endIndex-1 are shifted in the array. Undervalue (< start index) results in no
+ * change. Overvalue (>array.length) is demoted to array length.
+ * @param offset
+ * The number of positions to rotate the elements. If the offset is larger than the number of elements to
+ * rotate, than the effective offset is modulo the number of elements to rotate.
+ * @since 3.5
+ */
+ public static void shift(final short[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
+ if (array == null) {
+ return;
+ }
+ if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
+ return;
+ }
+ if (startIndexInclusive < 0) {
+ startIndexInclusive = 0;
+ }
+ if (endIndexExclusive >= array.length) {
+ endIndexExclusive = array.length;
+ }
+ int n = endIndexExclusive - startIndexInclusive;
+ if (n <= 1) {
+ return;
+ }
+ offset %= n;
+ if (offset < 0) {
+ offset += n;
+ }
+ // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
+ // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
+ while (n > 1 && offset > 0) {
+ int n_offset = n - offset;
+
+ if (offset > n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n - n_offset, n_offset);
+ n = offset;
+ offset -= n_offset;
+ } else if (offset < n_offset) {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ startIndexInclusive += offset;
+ n = n_offset;
+ } else {
+ swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
+ break;
+ }
+ }
+ }
+
+ // IndexOf search
+ // ----------------------------------------------------------------------
+
+ // Object IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * Finds the index of the given object in the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param objectToFind the object to find, may be {@code null}
+ * @return the index of the object within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final Object[] array, final Object objectToFind) {
+ return indexOf(array, objectToFind, 0);
+ }
+
+ /**
+ *
Finds the index of the given object in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param objectToFind the object to find, may be {@code null}
+ * @param startIndex the index to start searching at
+ * @return the index of the object within the array starting at the index,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ if (objectToFind == null) {
+ for (int i = startIndex; i < array.length; i++) {
+ if (array[i] == null) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = startIndex; i < array.length; i++) {
+ if (objectToFind.equals(array[i])) {
+ return i;
+ }
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the last index of the given object within the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to travers backwords looking for the object, may be {@code null}
+ * @param objectToFind the object to find, may be {@code null}
+ * @return the last index of the object within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final Object[] array, final Object objectToFind) {
+ return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
Finds the last index of the given object in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
+ * the array length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be {@code null}
+ * @param objectToFind the object to find, may be {@code null}
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the object within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ if (objectToFind == null) {
+ for (int i = startIndex; i >= 0; i--) {
+ if (array[i] == null) {
+ return i;
+ }
+ }
+ } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
+ for (int i = startIndex; i >= 0; i--) {
+ if (objectToFind.equals(array[i])) {
+ return i;
+ }
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Checks if the object is in the given array.
+ *
+ *
The method returns {@code false} if a {@code null} array is passed in.
+ *
+ * @param array the array to search through
+ * @param objectToFind the object to find
+ * @return {@code true} if the array contains the object
+ */
+ public static boolean contains(final Object[] array, final Object objectToFind) {
+ return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
+ }
+
+ // long IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ *
Finds the index of the given value in the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final long[] array, final long valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ *
Finds the index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final long[] array, final long valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the last index of the given value within the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to travers backwords looking for the object, may be {@code null}
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final long[] array, final long valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
Finds the last index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
+ * array length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Checks if the value is in the given array.
+ *
+ *
The method returns {@code false} if a {@code null} array is passed in.
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return {@code true} if the array contains the object
+ */
+ public static boolean contains(final long[] array, final long valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ // int IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ *
Finds the index of the given value in the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final int[] array, final int valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ *
Finds the index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final int[] array, final int valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the last index of the given value within the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to travers backwords looking for the object, may be {@code null}
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final int[] array, final int valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
Finds the last index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
+ * array length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Checks if the value is in the given array.
+ *
+ *
The method returns {@code false} if a {@code null} array is passed in.
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return {@code true} if the array contains the object
+ */
+ public static boolean contains(final int[] array, final int valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ // short IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ *
Finds the index of the given value in the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final short[] array, final short valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ *
Finds the index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final short[] array, final short valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the last index of the given value within the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to travers backwords looking for the object, may be {@code null}
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final short[] array, final short valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
Finds the last index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
+ * array length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Checks if the value is in the given array.
+ *
+ *
The method returns {@code false} if a {@code null} array is passed in.
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return {@code true} if the array contains the object
+ */
+ public static boolean contains(final short[] array, final short valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ // char IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ *
Finds the index of the given value in the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ * @since 2.1
+ */
+ public static int indexOf(final char[] array, final char valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ *
Finds the index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ * @since 2.1
+ */
+ public static int indexOf(final char[] array, final char valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the last index of the given value within the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to travers backwords looking for the object, may be {@code null}
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ * @since 2.1
+ */
+ public static int lastIndexOf(final char[] array, final char valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
Finds the last index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
+ * array length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ * @since 2.1
+ */
+ public static int lastIndexOf(final char[] array, final char valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Checks if the value is in the given array.
+ *
+ *
The method returns {@code false} if a {@code null} array is passed in.
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return {@code true} if the array contains the object
+ * @since 2.1
+ */
+ public static boolean contains(final char[] array, final char valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ // byte IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ *
Finds the index of the given value in the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final byte[] array, final byte valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ *
Finds the index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final byte[] array, final byte valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the last index of the given value within the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to travers backwords looking for the object, may be {@code null}
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final byte[] array, final byte valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
Finds the last index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
+ * array length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
+ if (array == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Checks if the value is in the given array.
+ *
+ *
The method returns {@code false} if a {@code null} array is passed in.
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return {@code true} if the array contains the object
+ */
+ public static boolean contains(final byte[] array, final byte valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ // double IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ *
Finds the index of the given value in the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final double[] array, final double valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ *
Finds the index of the given value within a given tolerance in the array.
+ * This method will return the index of the first value which falls between the region
+ * defined by valueToFind - tolerance and valueToFind + tolerance.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param tolerance tolerance of the search
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
+ return indexOf(array, valueToFind, 0, tolerance);
+ }
+
+ /**
+ *
Finds the index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final double[] array, final double valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the index of the given value in the array starting at the given index.
+ * This method will return the index of the first value which falls between the region
+ * defined by valueToFind - tolerance and valueToFind + tolerance.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @param tolerance tolerance of the search
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ final double min = valueToFind - tolerance;
+ final double max = valueToFind + tolerance;
+ for (int i = startIndex; i < array.length; i++) {
+ if (array[i] >= min && array[i] <= max) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the last index of the given value within the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to travers backwords looking for the object, may be {@code null}
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final double[] array, final double valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
Finds the last index of the given value within a given tolerance in the array.
+ * This method will return the index of the last value which falls between the region
+ * defined by valueToFind - tolerance and valueToFind + tolerance.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param tolerance tolerance of the search
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
+ }
+
+ /**
+ *
Finds the last index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
+ * array length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the last index of the given value in the array starting at the given index.
+ * This method will return the index of the last value which falls between the region
+ * defined by valueToFind - tolerance and valueToFind + tolerance.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
+ * array length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @param tolerance search for value within plus/minus this amount
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ final double min = valueToFind - tolerance;
+ final double max = valueToFind + tolerance;
+ for (int i = startIndex; i >= 0; i--) {
+ if (array[i] >= min && array[i] <= max) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Checks if the value is in the given array.
+ *
+ *
The method returns {@code false} if a {@code null} array is passed in.
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return {@code true} if the array contains the object
+ */
+ public static boolean contains(final double[] array, final double valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Checks if a value falling within the given tolerance is in the
+ * given array. If the array contains a value within the inclusive range
+ * defined by (value - tolerance) to (value + tolerance).
+ *
+ *
The method returns {@code false} if a {@code null} array
+ * is passed in.
+ *
+ * @param array the array to search
+ * @param valueToFind the value to find
+ * @param tolerance the array contains the tolerance of the search
+ * @return true if value falling within tolerance is in array
+ */
+ public static boolean contains(final double[] array, final double valueToFind, final double tolerance) {
+ return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
+ }
+
+ // float IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ *
Finds the index of the given value in the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final float[] array, final float valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ *
Finds the index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final float[] array, final float valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the last index of the given value within the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to travers backwords looking for the object, may be {@code null}
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final float[] array, final float valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
Finds the last index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
+ * array length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Checks if the value is in the given array.
+ *
+ *
The method returns {@code false} if a {@code null} array is passed in.
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return {@code true} if the array contains the object
+ */
+ public static boolean contains(final float[] array, final float valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ // boolean IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ *
Finds the index of the given value in the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int indexOf(final boolean[] array, final boolean valueToFind) {
+ return indexOf(array, valueToFind, 0);
+ }
+
+ /**
+ *
Finds the index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex is treated as zero. A startIndex larger than the array
+ * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
+ *
+ * @param array the array to search through for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the index to start searching at
+ * @return the index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null}
+ * array input
+ */
+ public static int indexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ for (int i = startIndex; i < array.length; i++) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Finds the last index of the given value within the array.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) if
+ * {@code null} array input.
+ *
+ * @param array the array to travers backwords looking for the object, may be {@code null}
+ * @param valueToFind the object to find
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
+ return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
Finds the last index of the given value in the array starting at the given index.
+ *
+ *
This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
+ *
+ *
A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
+ * the array length will search from the end of the array.
+ *
+ * @param array the array to traverse for looking for the object, may be {@code null}
+ * @param valueToFind the value to find
+ * @param startIndex the start index to travers backwards from
+ * @return the last index of the value within the array,
+ * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
+ */
+ public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
+ if (ArrayUtils.isEmpty(array)) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startIndex < 0) {
+ return INDEX_NOT_FOUND;
+ } else if (startIndex >= array.length) {
+ startIndex = array.length - 1;
+ }
+ for (int i = startIndex; i >= 0; i--) {
+ if (valueToFind == array[i]) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ *
Checks if the value is in the given array.
+ *
+ *
The method returns {@code false} if a {@code null} array is passed in.
+ *
+ * @param array the array to search through
+ * @param valueToFind the value to find
+ * @return {@code true} if the array contains the object
+ */
+ public static boolean contains(final boolean[] array, final boolean valueToFind) {
+ return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
+ }
+
+ // Primitive/Object array converters
+ // ----------------------------------------------------------------------
+
+ // Character array converters
+ // ----------------------------------------------------------------------
+ /**
+ *
Converts an array of object Characters to primitives.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Character} array, may be {@code null}
+ * @return a {@code char} array, {@code null} if null array input
+ * @throws NullPointerException if array content is {@code null}
+ */
+ public static char[] toPrimitive(final Character[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_CHAR_ARRAY;
+ }
+ final char[] result = new char[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].charValue();
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of object Character to primitives handling {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Character} array, may be {@code null}
+ * @param valueForNull the value to insert if {@code null} found
+ * @return a {@code char} array, {@code null} if null array input
+ */
+ public static char[] toPrimitive(final Character[] array, final char valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_CHAR_ARRAY;
+ }
+ final char[] result = new char[array.length];
+ for (int i = 0; i < array.length; i++) {
+ final Character b = array[i];
+ result[i] = (b == null ? valueForNull : b.charValue());
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of primitive chars to objects.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code char} array
+ * @return a {@code Character} array, {@code null} if null array input
+ */
+ public static Character[] toObject(final char[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_CHARACTER_OBJECT_ARRAY;
+ }
+ final Character[] result = new Character[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = Character.valueOf(array[i]);
+ }
+ return result;
+ }
+
+ // Long array converters
+ // ----------------------------------------------------------------------
+ /**
+ *
Converts an array of object Longs to primitives.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Long} array, may be {@code null}
+ * @return a {@code long} array, {@code null} if null array input
+ * @throws NullPointerException if array content is {@code null}
+ */
+ public static long[] toPrimitive(final Long[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_LONG_ARRAY;
+ }
+ final long[] result = new long[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].longValue();
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of object Long to primitives handling {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Long} array, may be {@code null}
+ * @param valueForNull the value to insert if {@code null} found
+ * @return a {@code long} array, {@code null} if null array input
+ */
+ public static long[] toPrimitive(final Long[] array, final long valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_LONG_ARRAY;
+ }
+ final long[] result = new long[array.length];
+ for (int i = 0; i < array.length; i++) {
+ final Long b = array[i];
+ result[i] = (b == null ? valueForNull : b.longValue());
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of primitive longs to objects.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code long} array
+ * @return a {@code Long} array, {@code null} if null array input
+ */
+ public static Long[] toObject(final long[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_LONG_OBJECT_ARRAY;
+ }
+ final Long[] result = new Long[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = Long.valueOf(array[i]);
+ }
+ return result;
+ }
+
+ // Int array converters
+ // ----------------------------------------------------------------------
+ /**
+ *
Converts an array of object Integers to primitives.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Integer} array, may be {@code null}
+ * @return an {@code int} array, {@code null} if null array input
+ * @throws NullPointerException if array content is {@code null}
+ */
+ public static int[] toPrimitive(final Integer[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_INT_ARRAY;
+ }
+ final int[] result = new int[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].intValue();
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of object Integer to primitives handling {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Integer} array, may be {@code null}
+ * @param valueForNull the value to insert if {@code null} found
+ * @return an {@code int} array, {@code null} if null array input
+ */
+ public static int[] toPrimitive(final Integer[] array, final int valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_INT_ARRAY;
+ }
+ final int[] result = new int[array.length];
+ for (int i = 0; i < array.length; i++) {
+ final Integer b = array[i];
+ result[i] = (b == null ? valueForNull : b.intValue());
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of primitive ints to objects.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array an {@code int} array
+ * @return an {@code Integer} array, {@code null} if null array input
+ */
+ public static Integer[] toObject(final int[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_INTEGER_OBJECT_ARRAY;
+ }
+ final Integer[] result = new Integer[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = Integer.valueOf(array[i]);
+ }
+ return result;
+ }
+
+ // Short array converters
+ // ----------------------------------------------------------------------
+ /**
+ *
Converts an array of object Shorts to primitives.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Short} array, may be {@code null}
+ * @return a {@code byte} array, {@code null} if null array input
+ * @throws NullPointerException if array content is {@code null}
+ */
+ public static short[] toPrimitive(final Short[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+ final short[] result = new short[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].shortValue();
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of object Short to primitives handling {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Short} array, may be {@code null}
+ * @param valueForNull the value to insert if {@code null} found
+ * @return a {@code byte} array, {@code null} if null array input
+ */
+ public static short[] toPrimitive(final Short[] array, final short valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_SHORT_ARRAY;
+ }
+ final short[] result = new short[array.length];
+ for (int i = 0; i < array.length; i++) {
+ final Short b = array[i];
+ result[i] = (b == null ? valueForNull : b.shortValue());
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of primitive shorts to objects.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code short} array
+ * @return a {@code Short} array, {@code null} if null array input
+ */
+ public static Short[] toObject(final short[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_SHORT_OBJECT_ARRAY;
+ }
+ final Short[] result = new Short[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = Short.valueOf(array[i]);
+ }
+ return result;
+ }
+
+ // Byte array converters
+ // ----------------------------------------------------------------------
+ /**
+ *
Converts an array of object Bytes to primitives.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Byte} array, may be {@code null}
+ * @return a {@code byte} array, {@code null} if null array input
+ * @throws NullPointerException if array content is {@code null}
+ */
+ public static byte[] toPrimitive(final Byte[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ final byte[] result = new byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].byteValue();
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of object Bytes to primitives handling {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Byte} array, may be {@code null}
+ * @param valueForNull the value to insert if {@code null} found
+ * @return a {@code byte} array, {@code null} if null array input
+ */
+ public static byte[] toPrimitive(final Byte[] array, final byte valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ final byte[] result = new byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ final Byte b = array[i];
+ result[i] = (b == null ? valueForNull : b.byteValue());
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of primitive bytes to objects.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code byte} array
+ * @return a {@code Byte} array, {@code null} if null array input
+ */
+ public static Byte[] toObject(final byte[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BYTE_OBJECT_ARRAY;
+ }
+ final Byte[] result = new Byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = Byte.valueOf(array[i]);
+ }
+ return result;
+ }
+
+ // Double array converters
+ // ----------------------------------------------------------------------
+ /**
+ *
Converts an array of object Doubles to primitives.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Double} array, may be {@code null}
+ * @return a {@code double} array, {@code null} if null array input
+ * @throws NullPointerException if array content is {@code null}
+ */
+ public static double[] toPrimitive(final Double[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_DOUBLE_ARRAY;
+ }
+ final double[] result = new double[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].doubleValue();
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of object Doubles to primitives handling {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Double} array, may be {@code null}
+ * @param valueForNull the value to insert if {@code null} found
+ * @return a {@code double} array, {@code null} if null array input
+ */
+ public static double[] toPrimitive(final Double[] array, final double valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_DOUBLE_ARRAY;
+ }
+ final double[] result = new double[array.length];
+ for (int i = 0; i < array.length; i++) {
+ final Double b = array[i];
+ result[i] = (b == null ? valueForNull : b.doubleValue());
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of primitive doubles to objects.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code double} array
+ * @return a {@code Double} array, {@code null} if null array input
+ */
+ public static Double[] toObject(final double[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_DOUBLE_OBJECT_ARRAY;
+ }
+ final Double[] result = new Double[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = Double.valueOf(array[i]);
+ }
+ return result;
+ }
+
+ // Float array converters
+ // ----------------------------------------------------------------------
+ /**
+ *
Converts an array of object Floats to primitives.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Float} array, may be {@code null}
+ * @return a {@code float} array, {@code null} if null array input
+ * @throws NullPointerException if array content is {@code null}
+ */
+ public static float[] toPrimitive(final Float[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_FLOAT_ARRAY;
+ }
+ final float[] result = new float[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].floatValue();
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of object Floats to primitives handling {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Float} array, may be {@code null}
+ * @param valueForNull the value to insert if {@code null} found
+ * @return a {@code float} array, {@code null} if null array input
+ */
+ public static float[] toPrimitive(final Float[] array, final float valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_FLOAT_ARRAY;
+ }
+ final float[] result = new float[array.length];
+ for (int i = 0; i < array.length; i++) {
+ final Float b = array[i];
+ result[i] = (b == null ? valueForNull : b.floatValue());
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of primitive floats to objects.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code float} array
+ * @return a {@code Float} array, {@code null} if null array input
+ */
+ public static Float[] toObject(final float[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_FLOAT_OBJECT_ARRAY;
+ }
+ final Float[] result = new Float[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = Float.valueOf(array[i]);
+ }
+ return result;
+ }
+
+ /**
+ *
Create an array of primitive type from an array of wrapper types.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array an array of wrapper object
+ * @return an array of the corresponding primitive type, or the original array
+ * @since 3.5
+ */
+ public static Object toPrimitive(final Object array) {
+ if (array == null) {
+ return null;
+ }
+ Class> ct = array.getClass().getComponentType();
+ Class> pt = ClassUtils.wrapperToPrimitive(ct);
+ if(Integer.TYPE.equals(pt)) {
+ return toPrimitive((Integer[]) array);
+ }
+ if(Long.TYPE.equals(pt)) {
+ return toPrimitive((Long[]) array);
+ }
+ if(Short.TYPE.equals(pt)) {
+ return toPrimitive((Short[]) array);
+ }
+ if(Double.TYPE.equals(pt)) {
+ return toPrimitive((Double[]) array);
+ }
+ if(Float.TYPE.equals(pt)) {
+ return toPrimitive((Float[]) array);
+ }
+ return array;
+ }
+
+ // Boolean array converters
+ // ----------------------------------------------------------------------
+ /**
+ *
Converts an array of object Booleans to primitives.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Boolean} array, may be {@code null}
+ * @return a {@code boolean} array, {@code null} if null array input
+ * @throws NullPointerException if array content is {@code null}
+ */
+ public static boolean[] toPrimitive(final Boolean[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BOOLEAN_ARRAY;
+ }
+ final boolean[] result = new boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = array[i].booleanValue();
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of object Booleans to primitives handling {@code null}.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code Boolean} array, may be {@code null}
+ * @param valueForNull the value to insert if {@code null} found
+ * @return a {@code boolean} array, {@code null} if null array input
+ */
+ public static boolean[] toPrimitive(final Boolean[] array, final boolean valueForNull) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BOOLEAN_ARRAY;
+ }
+ final boolean[] result = new boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ final Boolean b = array[i];
+ result[i] = (b == null ? valueForNull : b.booleanValue());
+ }
+ return result;
+ }
+
+ /**
+ *
Converts an array of primitive booleans to objects.
+ *
+ *
This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array a {@code boolean} array
+ * @return a {@code Boolean} array, {@code null} if null array input
+ */
+ public static Boolean[] toObject(final boolean[] array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return EMPTY_BOOLEAN_OBJECT_ARRAY;
+ }
+ final Boolean[] result = new Boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE);
+ }
+ return result;
+ }
+
+ // ----------------------------------------------------------------------
+ /**
+ *
Checks if an array of Objects is empty or {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is empty or {@code null}
+ * @since 2.1
+ */
+ public static boolean isEmpty(final Object[] array) {
+ return getLength(array) == 0;
+ }
+
+ /**
+ *
Checks if an array of primitive longs is empty or {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is empty or {@code null}
+ * @since 2.1
+ */
+ public static boolean isEmpty(final long[] array) {
+ return getLength(array) == 0;
+ }
+
+ /**
+ *
Checks if an array of primitive ints is empty or {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is empty or {@code null}
+ * @since 2.1
+ */
+ public static boolean isEmpty(final int[] array) {
+ return getLength(array) == 0;
+ }
+
+ /**
+ *
Checks if an array of primitive shorts is empty or {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is empty or {@code null}
+ * @since 2.1
+ */
+ public static boolean isEmpty(final short[] array) {
+ return getLength(array) == 0;
+ }
+
+ /**
+ *
Checks if an array of primitive chars is empty or {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is empty or {@code null}
+ * @since 2.1
+ */
+ public static boolean isEmpty(final char[] array) {
+ return getLength(array) == 0;
+ }
+
+ /**
+ *
Checks if an array of primitive bytes is empty or {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is empty or {@code null}
+ * @since 2.1
+ */
+ public static boolean isEmpty(final byte[] array) {
+ return getLength(array) == 0;
+ }
+
+ /**
+ *
Checks if an array of primitive doubles is empty or {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is empty or {@code null}
+ * @since 2.1
+ */
+ public static boolean isEmpty(final double[] array) {
+ return getLength(array) == 0;
+ }
+
+ /**
+ *
Checks if an array of primitive floats is empty or {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is empty or {@code null}
+ * @since 2.1
+ */
+ public static boolean isEmpty(final float[] array) {
+ return getLength(array) == 0;
+ }
+
+ /**
+ *
Checks if an array of primitive booleans is empty or {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is empty or {@code null}
+ * @since 2.1
+ */
+ public static boolean isEmpty(final boolean[] array) {
+ return getLength(array) == 0;
+ }
+
+ // ----------------------------------------------------------------------
+ /**
+ *
Checks if an array of Objects is not empty and not {@code null}.
+ *
+ * @param the component type of the array
+ * @param array the array to test
+ * @return {@code true} if the array is not empty and not {@code null}
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(final T[] array) {
+ return !isEmpty(array);
+ }
+
+ /**
+ * Checks if an array of primitive longs is not empty and not {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is not empty and not {@code null}
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(final long[] array) {
+ return !isEmpty(array);
+ }
+
+ /**
+ *
Checks if an array of primitive ints is not empty and not {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is not empty and not {@code null}
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(final int[] array) {
+ return !isEmpty(array);
+ }
+
+ /**
+ *
Checks if an array of primitive shorts is not empty and not {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is not empty and not {@code null}
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(final short[] array) {
+ return !isEmpty(array);
+ }
+
+ /**
+ *
Checks if an array of primitive chars is not empty and not {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is not empty and not {@code null}
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(final char[] array) {
+ return !isEmpty(array);
+ }
+
+ /**
+ *
Checks if an array of primitive bytes is not empty and not {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is not empty and not {@code null}
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(final byte[] array) {
+ return !isEmpty(array);
+ }
+
+ /**
+ *
Checks if an array of primitive doubles is not empty and not {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is not empty and not {@code null}
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(final double[] array) {
+ return !isEmpty(array);
+ }
+
+ /**
+ *
Checks if an array of primitive floats is not empty and not {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is not empty and not {@code null}
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(final float[] array) {
+ return !isEmpty(array);
+ }
+
+ /**
+ *
Checks if an array of primitive booleans is not empty and not {@code null}.
+ *
+ * @param array the array to test
+ * @return {@code true} if the array is not empty and not {@code null}
+ * @since 2.5
+ */
+ public static boolean isNotEmpty(final boolean[] array) {
+ return !isEmpty(array);
+ }
+
+ /**
+ *
Adds all the elements of the given arrays into a new array.
+ *
The new array contains all of the element of {@code array1} followed
+ * by all of the elements {@code array2}. When an array is returned, it is always
+ * a new array.
+ *
+ *
+ * ArrayUtils.addAll(null, null) = null
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ * ArrayUtils.addAll([null], [null]) = [null, null]
+ * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
+ *
+ *
+ * @param the component type of the array
+ * @param array1 the first array whose elements are added to the new array, may be {@code null}
+ * @param array2 the second array whose elements are added to the new array, may be {@code null}
+ * @return The new array, {@code null} if both arrays are {@code null}.
+ * The type of the new array is the type of the first array,
+ * unless the first array is null, in which case the type is the same as the second array.
+ * @since 2.1
+ * @throws IllegalArgumentException if the array types are incompatible
+ */
+ public static T[] addAll(final T[] array1, final T... array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ final Class> type1 = array1.getClass().getComponentType();
+ @SuppressWarnings("unchecked") // OK, because array is of type T
+ final
+ T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ try {
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ } catch (final ArrayStoreException ase) {
+ // Check if problem was due to incompatible types
+ /*
+ * We do this here, rather than before the copy because:
+ * - it would be a wasted check most of the time
+ * - safer, in case check turns out to be too strict
+ */
+ final Class> type2 = array2.getClass().getComponentType();
+ if (!type1.isAssignableFrom(type2)) {
+ throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
+ + type1.getName(), ase);
+ }
+ throw ase; // No, so rethrow original
+ }
+ return joinedArray;
+ }
+
+ /**
+ * Adds all the elements of the given arrays into a new array.
+ *
The new array contains all of the element of {@code array1} followed
+ * by all of the elements {@code array2}. When an array is returned, it is always
+ * a new array.
+ *
+ *
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ *
+ *
+ * @param array1 the first array whose elements are added to the new array.
+ * @param array2 the second array whose elements are added to the new array.
+ * @return The new boolean[] array.
+ * @since 2.1
+ */
+ public static boolean[] addAll(final boolean[] array1, final boolean... array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ final boolean[] joinedArray = new boolean[array1.length + array2.length];
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+
+ /**
+ * Adds all the elements of the given arrays into a new array.
+ *
The new array contains all of the element of {@code array1} followed
+ * by all of the elements {@code array2}. When an array is returned, it is always
+ * a new array.
+ *
+ *
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ *
+ *
+ * @param array1 the first array whose elements are added to the new array.
+ * @param array2 the second array whose elements are added to the new array.
+ * @return The new char[] array.
+ * @since 2.1
+ */
+ public static char[] addAll(final char[] array1, final char... array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ final char[] joinedArray = new char[array1.length + array2.length];
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+
+ /**
+ * Adds all the elements of the given arrays into a new array.
+ *
The new array contains all of the element of {@code array1} followed
+ * by all of the elements {@code array2}. When an array is returned, it is always
+ * a new array.
+ *
+ *
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ *
+ *
+ * @param array1 the first array whose elements are added to the new array.
+ * @param array2 the second array whose elements are added to the new array.
+ * @return The new byte[] array.
+ * @since 2.1
+ */
+ public static byte[] addAll(final byte[] array1, final byte... array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ final byte[] joinedArray = new byte[array1.length + array2.length];
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+
+ /**
+ * Adds all the elements of the given arrays into a new array.
+ *
The new array contains all of the element of {@code array1} followed
+ * by all of the elements {@code array2}. When an array is returned, it is always
+ * a new array.
+ *
+ *
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ *
+ *
+ * @param array1 the first array whose elements are added to the new array.
+ * @param array2 the second array whose elements are added to the new array.
+ * @return The new short[] array.
+ * @since 2.1
+ */
+ public static short[] addAll(final short[] array1, final short... array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ final short[] joinedArray = new short[array1.length + array2.length];
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+
+ /**
+ * Adds all the elements of the given arrays into a new array.
+ *
The new array contains all of the element of {@code array1} followed
+ * by all of the elements {@code array2}. When an array is returned, it is always
+ * a new array.
+ *
+ *
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ *
+ *
+ * @param array1 the first array whose elements are added to the new array.
+ * @param array2 the second array whose elements are added to the new array.
+ * @return The new int[] array.
+ * @since 2.1
+ */
+ public static int[] addAll(final int[] array1, final int... array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ final int[] joinedArray = new int[array1.length + array2.length];
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+
+ /**
+ * Adds all the elements of the given arrays into a new array.
+ *
The new array contains all of the element of {@code array1} followed
+ * by all of the elements {@code array2}. When an array is returned, it is always
+ * a new array.
+ *
+ *
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ *
+ *
+ * @param array1 the first array whose elements are added to the new array.
+ * @param array2 the second array whose elements are added to the new array.
+ * @return The new long[] array.
+ * @since 2.1
+ */
+ public static long[] addAll(final long[] array1, final long... array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ final long[] joinedArray = new long[array1.length + array2.length];
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+
+ /**
+ * Adds all the elements of the given arrays into a new array.
+ *
The new array contains all of the element of {@code array1} followed
+ * by all of the elements {@code array2}. When an array is returned, it is always
+ * a new array.
+ *
+ *
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ *
+ *
+ * @param array1 the first array whose elements are added to the new array.
+ * @param array2 the second array whose elements are added to the new array.
+ * @return The new float[] array.
+ * @since 2.1
+ */
+ public static float[] addAll(final float[] array1, final float... array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ final float[] joinedArray = new float[array1.length + array2.length];
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+
+ /**
+ * Adds all the elements of the given arrays into a new array.
+ *
The new array contains all of the element of {@code array1} followed
+ * by all of the elements {@code array2}. When an array is returned, it is always
+ * a new array.
+ *
+ *
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ *
+ *
+ * @param array1 the first array whose elements are added to the new array.
+ * @param array2 the second array whose elements are added to the new array.
+ * @return The new double[] array.
+ * @since 2.1
+ */
+ public static double[] addAll(final double[] array1, final double... array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ final double[] joinedArray = new double[array1.length + array2.length];
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ *
+ *
The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element, unless the element itself is null,
+ * in which case the return type is Object[]
+ *
+ *
+ * ArrayUtils.add(null, null) = [null]
+ * ArrayUtils.add(null, "a") = ["a"]
+ * ArrayUtils.add(["a"], null) = ["a", null]
+ * ArrayUtils.add(["a"], "b") = ["a", "b"]
+ * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"]
+ *
+ *
+ * @param the component type of the array
+ * @param array the array to "add" the element to, may be {@code null}
+ * @param element the object to add, may be {@code null}
+ * @return A new array containing the existing elements plus the new element
+ * The returned array type will be that of the input array (unless null),
+ * in which case it will have the same type as the element.
+ * If both are null, an IllegalArgumentException is thrown
+ * @since 2.1
+ * @throws IllegalArgumentException if both arguments are null
+ */
+ public static T[] add(final T[] array, final T element) {
+ Class> type;
+ if (array != null) {
+ type = array.getClass().getComponentType();
+ } else if (element != null) {
+ type = element.getClass();
+ } else {
+ throw new IllegalArgumentException("Arguments cannot both be null");
+ }
+ @SuppressWarnings("unchecked") // type must be T
+ final
+ T[] newArray = (T[]) copyArrayGrow1(array, type);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ *
+ *
The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, true) = [true]
+ * ArrayUtils.add([true], false) = [true, false]
+ * ArrayUtils.add([true, false], true) = [true, false, true]
+ *
+ *
+ * @param array the array to copy and add the element to, may be {@code null}
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static boolean[] add(final boolean[] array, final boolean element) {
+ final boolean[] newArray = (boolean[])copyArrayGrow1(array, Boolean.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ *
+ *
The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ *
+ *
+ * @param array the array to copy and add the element to, may be {@code null}
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static byte[] add(final byte[] array, final byte element) {
+ final byte[] newArray = (byte[])copyArrayGrow1(array, Byte.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ *
+ *
The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, '0') = ['0']
+ * ArrayUtils.add(['1'], '0') = ['1', '0']
+ * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
+ *
+ *
+ * @param array the array to copy and add the element to, may be {@code null}
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static char[] add(final char[] array, final char element) {
+ final char[] newArray = (char[])copyArrayGrow1(array, Character.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ *
+ *
The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ *
+ *
+ * @param array the array to copy and add the element to, may be {@code null}
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static double[] add(final double[] array, final double element) {
+ final double[] newArray = (double[])copyArrayGrow1(array, Double.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ *
+ *
The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ *
+ *
+ * @param array the array to copy and add the element to, may be {@code null}
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static float[] add(final float[] array, final float element) {
+ final float[] newArray = (float[])copyArrayGrow1(array, Float.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ *
+ *
The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ *
+ *
+ * @param array the array to copy and add the element to, may be {@code null}
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static int[] add(final int[] array, final int element) {
+ final int[] newArray = (int[])copyArrayGrow1(array, Integer.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ *
+ *
The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ *
+ *
+ * @param array the array to copy and add the element to, may be {@code null}
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static long[] add(final long[] array, final long element) {
+ final long[] newArray = (long[])copyArrayGrow1(array, Long.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Copies the given array and adds the given element at the end of the new array.
+ *
+ *
The new array contains the same elements of the input
+ * array plus the given element in the last position. The component type of
+ * the new array is the same as that of the input array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, 0) = [0]
+ * ArrayUtils.add([1], 0) = [1, 0]
+ * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
+ *
+ *
+ * @param array the array to copy and add the element to, may be {@code null}
+ * @param element the object to add at the last index of the new array
+ * @return A new array containing the existing elements plus the new element
+ * @since 2.1
+ */
+ public static short[] add(final short[] array, final short element) {
+ final short[] newArray = (short[]) copyArrayGrow1(array, Short.TYPE);
+ newArray[newArray.length - 1] = element;
+ return newArray;
+ }
+
+ /**
+ * Returns a copy of the given array of size 1 greater than the argument.
+ * The last value of the array is left to the default value.
+ *
+ * @param array The array to copy, must not be {@code null}.
+ * @param newArrayComponentType If {@code array} is {@code null}, create a
+ * size 1 array of this type.
+ * @return A new copy of the array of size 1 greater than the input.
+ */
+ private static Object copyArrayGrow1(final Object array, final Class> newArrayComponentType) {
+ if (array != null) {
+ final int arrayLength = Array.getLength(array);
+ final Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
+ System.arraycopy(array, 0, newArray, 0, arrayLength);
+ return newArray;
+ }
+ return Array.newInstance(newArrayComponentType, 1);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, 0, null) = [null]
+ * ArrayUtils.add(null, 0, "a") = ["a"]
+ * ArrayUtils.add(["a"], 1, null) = ["a", null]
+ * ArrayUtils.add(["a"], 1, "b") = ["a", "b"]
+ * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
+ *
+ *
+ * @param the component type of the array
+ * @param array the array to add the element to, may be {@code null}
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index > array.length).
+ * @throws IllegalArgumentException if both array and element are null
+ */
+ public static T[] add(final T[] array, final int index, final T element) {
+ Class> clss = null;
+ if (array != null) {
+ clss = array.getClass().getComponentType();
+ } else if (element != null) {
+ clss = element.getClass();
+ } else {
+ throw new IllegalArgumentException("Array and element cannot both be null");
+ }
+ @SuppressWarnings("unchecked") // the add method creates an array of type clss, which is type T
+ final T[] newArray = (T[]) add(array, index, element, clss);
+ return newArray;
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, 0, true) = [true]
+ * ArrayUtils.add([true], 0, false) = [false, true]
+ * ArrayUtils.add([false], 1, true) = [false, true]
+ * ArrayUtils.add([true, false], 1, true) = [true, true, false]
+ *
+ *
+ * @param array the array to add the element to, may be {@code null}
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index > array.length).
+ */
+ public static boolean[] add(final boolean[] array, final int index, final boolean element) {
+ return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add(null, 0, 'a') = ['a']
+ * ArrayUtils.add(['a'], 0, 'b') = ['b', 'a']
+ * ArrayUtils.add(['a', 'b'], 0, 'c') = ['c', 'a', 'b']
+ * ArrayUtils.add(['a', 'b'], 1, 'k') = ['a', 'k', 'b']
+ * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
+ *
+ *
+ * @param array the array to add the element to, may be {@code null}
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static char[] add(final char[] array, final int index, final char element) {
+ return (char[]) add(array, index, Character.valueOf(element), Character.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add([1], 0, 2) = [2, 1]
+ * ArrayUtils.add([2, 6], 2, 3) = [2, 6, 3]
+ * ArrayUtils.add([2, 6], 0, 1) = [1, 2, 6]
+ * ArrayUtils.add([2, 6, 3], 2, 1) = [2, 6, 1, 3]
+ *
+ *
+ * @param array the array to add the element to, may be {@code null}
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static byte[] add(final byte[] array, final int index, final byte element) {
+ return (byte[]) add(array, index, Byte.valueOf(element), Byte.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add([1], 0, 2) = [2, 1]
+ * ArrayUtils.add([2, 6], 2, 10) = [2, 6, 10]
+ * ArrayUtils.add([2, 6], 0, -4) = [-4, 2, 6]
+ * ArrayUtils.add([2, 6, 3], 2, 1) = [2, 6, 1, 3]
+ *
+ *
+ * @param array the array to add the element to, may be {@code null}
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static short[] add(final short[] array, final int index, final short element) {
+ return (short[]) add(array, index, Short.valueOf(element), Short.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add([1], 0, 2) = [2, 1]
+ * ArrayUtils.add([2, 6], 2, 10) = [2, 6, 10]
+ * ArrayUtils.add([2, 6], 0, -4) = [-4, 2, 6]
+ * ArrayUtils.add([2, 6, 3], 2, 1) = [2, 6, 1, 3]
+ *
+ *
+ * @param array the array to add the element to, may be {@code null}
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static int[] add(final int[] array, final int index, final int element) {
+ return (int[]) add(array, index, Integer.valueOf(element), Integer.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add([1L], 0, 2L) = [2L, 1L]
+ * ArrayUtils.add([2L, 6L], 2, 10L) = [2L, 6L, 10L]
+ * ArrayUtils.add([2L, 6L], 0, -4L) = [-4L, 2L, 6L]
+ * ArrayUtils.add([2L, 6L, 3L], 2, 1L) = [2L, 6L, 1L, 3L]
+ *
+ *
+ * @param array the array to add the element to, may be {@code null}
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static long[] add(final long[] array, final int index, final long element) {
+ return (long[]) add(array, index, Long.valueOf(element), Long.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add([1.1f], 0, 2.2f) = [2.2f, 1.1f]
+ * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f) = [2.3f, 6.4f, 10.5f]
+ * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f) = [-4.8f, 2.6f, 6.7f]
+ * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f) = [2.9f, 6.0f, 1.0f, 0.3f]
+ *
+ *
+ * @param array the array to add the element to, may be {@code null}
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static float[] add(final float[] array, final int index, final float element) {
+ return (float[]) add(array, index, Float.valueOf(element), Float.TYPE);
+ }
+
+ /**
+ * Inserts the specified element at the specified position in the array.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array plus the given element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, a new one element array is returned
+ * whose component type is the same as the element.
+ *
+ *
+ * ArrayUtils.add([1.1], 0, 2.2) = [2.2, 1.1]
+ * ArrayUtils.add([2.3, 6.4], 2, 10.5) = [2.3, 6.4, 10.5]
+ * ArrayUtils.add([2.6, 6.7], 0, -4.8) = [-4.8, 2.6, 6.7]
+ * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0) = [2.9, 6.0, 1.0, 0.3]
+ *
+ *
+ * @param array the array to add the element to, may be {@code null}
+ * @param index the position of the new object
+ * @param element the object to add
+ * @return A new array containing the existing elements and the new element
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index > array.length).
+ */
+ public static double[] add(final double[] array, final int index, final double element) {
+ return (double[]) add(array, index, Double.valueOf(element), Double.TYPE);
+ }
+
+ /**
+ * Underlying implementation of add(array, index, element) methods.
+ * The last parameter is the class, which may not equal element.getClass
+ * for primitives.
+ *
+ * @param array the array to add the element to, may be {@code null}
+ * @param index the position of the new object
+ * @param element the object to add
+ * @param clss the type of the element being added
+ * @return A new array containing the existing elements and the new element
+ */
+ private static Object add(final Object array, final int index, final Object element, final Class> clss) {
+ if (array == null) {
+ if (index != 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
+ }
+ final Object joinedArray = Array.newInstance(clss, 1);
+ Array.set(joinedArray, 0, element);
+ return joinedArray;
+ }
+ final int length = Array.getLength(array);
+ if (index > length || index < 0) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
+ }
+ final Object result = Array.newInstance(clss, length + 1);
+ System.arraycopy(array, 0, result, 0, index);
+ Array.set(result, index, element);
+ if (index < length) {
+ System.arraycopy(array, index, result, index + 1, length - index);
+ }
+ return result;
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (subtracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.remove(["a"], 0) = []
+ * ArrayUtils.remove(["a", "b"], 0) = ["b"]
+ * ArrayUtils.remove(["a", "b"], 1) = ["a"]
+ * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
+ *
+ *
+ * @param the component type of the array
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 2.1
+ */
+ @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
+ public static T[] remove(final T[] array, final int index) {
+ return (T[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (subtracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
+ * ArrayUtils.removeElement(null, "a") = null
+ * ArrayUtils.removeElement([], "a") = []
+ * ArrayUtils.removeElement(["a"], "b") = ["a"]
+ * ArrayUtils.removeElement(["a", "b"], "a") = ["b"]
+ * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
+ *
+ *
+ * @param the component type of the array
+ * @param array the array to remove the element from, may be {@code null}
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static T[] removeElement(final T[] array, final Object element) {
+ final int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (subtracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.remove([true], 0) = []
+ * ArrayUtils.remove([true, false], 0) = [false]
+ * ArrayUtils.remove([true, false], 1) = [true]
+ * ArrayUtils.remove([true, true, false], 1) = [true, false]
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 2.1
+ */
+ public static boolean[] remove(final boolean[] array, final int index) {
+ return (boolean[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (subtracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
+ * ArrayUtils.removeElement(null, true) = null
+ * ArrayUtils.removeElement([], true) = []
+ * ArrayUtils.removeElement([true], false) = [true]
+ * ArrayUtils.removeElement([true, false], false) = [true]
+ * ArrayUtils.removeElement([true, false, true], true) = [false, true]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static boolean[] removeElement(final boolean[] array, final boolean element) {
+ final int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (subtracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.remove([1], 0) = []
+ * ArrayUtils.remove([1, 0], 0) = [0]
+ * ArrayUtils.remove([1, 0], 1) = [1]
+ * ArrayUtils.remove([1, 0, 1], 1) = [1, 1]
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 2.1
+ */
+ public static byte[] remove(final byte[] array, final int index) {
+ return (byte[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (subtracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
+ * ArrayUtils.removeElement(null, 1) = null
+ * ArrayUtils.removeElement([], 1) = []
+ * ArrayUtils.removeElement([1], 0) = [1]
+ * ArrayUtils.removeElement([1, 0], 0) = [1]
+ * ArrayUtils.removeElement([1, 0, 1], 1) = [0, 1]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static byte[] removeElement(final byte[] array, final byte element) {
+ final int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (subtracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.remove(['a'], 0) = []
+ * ArrayUtils.remove(['a', 'b'], 0) = ['b']
+ * ArrayUtils.remove(['a', 'b'], 1) = ['a']
+ * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 2.1
+ */
+ public static char[] remove(final char[] array, final int index) {
+ return (char[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (subtracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
+ * ArrayUtils.removeElement(null, 'a') = null
+ * ArrayUtils.removeElement([], 'a') = []
+ * ArrayUtils.removeElement(['a'], 'b') = ['a']
+ * ArrayUtils.removeElement(['a', 'b'], 'a') = ['b']
+ * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static char[] removeElement(final char[] array, final char element) {
+ final int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (subtracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.remove([1.1], 0) = []
+ * ArrayUtils.remove([2.5, 6.0], 0) = [6.0]
+ * ArrayUtils.remove([2.5, 6.0], 1) = [2.5]
+ * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 2.1
+ */
+ public static double[] remove(final double[] array, final int index) {
+ return (double[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (subtracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
+ * ArrayUtils.removeElement(null, 1.1) = null
+ * ArrayUtils.removeElement([], 1.1) = []
+ * ArrayUtils.removeElement([1.1], 1.2) = [1.1]
+ * ArrayUtils.removeElement([1.1, 2.3], 1.1) = [2.3]
+ * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static double[] removeElement(final double[] array, final double element) {
+ final int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (subtracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.remove([1.1], 0) = []
+ * ArrayUtils.remove([2.5, 6.0], 0) = [6.0]
+ * ArrayUtils.remove([2.5, 6.0], 1) = [2.5]
+ * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 2.1
+ */
+ public static float[] remove(final float[] array, final int index) {
+ return (float[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (subtracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
+ * ArrayUtils.removeElement(null, 1.1) = null
+ * ArrayUtils.removeElement([], 1.1) = []
+ * ArrayUtils.removeElement([1.1], 1.2) = [1.1]
+ * ArrayUtils.removeElement([1.1, 2.3], 1.1) = [2.3]
+ * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static float[] removeElement(final float[] array, final float element) {
+ final int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (subtracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.remove([1], 0) = []
+ * ArrayUtils.remove([2, 6], 0) = [6]
+ * ArrayUtils.remove([2, 6], 1) = [2]
+ * ArrayUtils.remove([2, 6, 3], 1) = [2, 3]
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 2.1
+ */
+ public static int[] remove(final int[] array, final int index) {
+ return (int[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (subtracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
+ * ArrayUtils.removeElement(null, 1) = null
+ * ArrayUtils.removeElement([], 1) = []
+ * ArrayUtils.removeElement([1], 2) = [1]
+ * ArrayUtils.removeElement([1, 3], 1) = [3]
+ * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static int[] removeElement(final int[] array, final int element) {
+ final int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (subtracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.remove([1], 0) = []
+ * ArrayUtils.remove([2, 6], 0) = [6]
+ * ArrayUtils.remove([2, 6], 1) = [2]
+ * ArrayUtils.remove([2, 6, 3], 1) = [2, 3]
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 2.1
+ */
+ public static long[] remove(final long[] array, final int index) {
+ return (long[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (subtracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
+ * ArrayUtils.removeElement(null, 1) = null
+ * ArrayUtils.removeElement([], 1) = []
+ * ArrayUtils.removeElement([1], 2) = [1]
+ * ArrayUtils.removeElement([1, 3], 1) = [3]
+ * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static long[] removeElement(final long[] array, final long element) {
+ final int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (subtracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.remove([1], 0) = []
+ * ArrayUtils.remove([2, 6], 0) = [6]
+ * ArrayUtils.remove([2, 6], 1) = [2]
+ * ArrayUtils.remove([2, 6, 3], 1) = [2, 3]
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 2.1
+ */
+ public static short[] remove(final short[] array, final int index) {
+ return (short[]) remove((Object) array, index);
+ }
+
+ /**
+ * Removes the first occurrence of the specified element from the
+ * specified array. All subsequent elements are shifted to the left
+ * (subtracts one from their indices). If the array doesn't contains
+ * such an element, no elements are removed from the array.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the first occurrence of the specified element. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
+ * ArrayUtils.removeElement(null, 1) = null
+ * ArrayUtils.removeElement([], 1) = []
+ * ArrayUtils.removeElement([1], 2) = [1]
+ * ArrayUtils.removeElement([1, 3], 1) = [3]
+ * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param element the element to be removed
+ * @return A new array containing the existing elements except the first
+ * occurrence of the specified element.
+ * @since 2.1
+ */
+ public static short[] removeElement(final short[] array, final short element) {
+ final int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+ return remove(array, index);
+ }
+
+ /**
+ * Removes the element at the specified position from the specified array.
+ * All subsequent elements are shifted to the left (subtracts one from
+ * their indices).
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except the element on the specified position. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param index the position of the element to be removed
+ * @return A new array containing the existing elements except the element
+ * at the specified position.
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 2.1
+ */
+ private static Object remove(final Object array, final int index) {
+ final int length = getLength(array);
+ if (index < 0 || index >= length) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
+ }
+
+ final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
+ System.arraycopy(array, 0, result, 0, index);
+ if (index < length - 1) {
+ System.arraycopy(array, index + 1, result, index, length - index - 1);
+ }
+
+ return result;
+ }
+
+ /**
+ *
Removes the elements at the specified positions from the specified array.
+ * All remaining elements are shifted to the left.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except those at the specified positions. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
+ * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
+ *
+ *
+ * @param the component type of the array
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param indices the positions of the elements to be removed
+ * @return A new array containing the existing elements except those
+ * at the specified positions.
+ * @throws IndexOutOfBoundsException if any index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 3.0.1
+ */
+ @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
+ public static T[] removeAll(final T[] array, final int... indices) {
+ return (T[]) removeAll((Object) array, indices);
+ }
+
+ /**
+ * Removes occurrences of specified elements, in specified quantities,
+ * from the specified array. All subsequent elements are shifted left.
+ * For any element-to-be-removed specified in greater quantities than
+ * contained in the original array, no change occurs beyond the
+ * removal of the existing matching items.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except for the earliest-encountered occurrences of the specified
+ * elements. The component type of the returned array is always the same
+ * as that of the input array.
+ *
+ *
+ * ArrayUtils.removeElements(null, "a", "b") = null
+ * ArrayUtils.removeElements([], "a", "b") = []
+ * ArrayUtils.removeElements(["a"], "b", "c") = ["a"]
+ * ArrayUtils.removeElements(["a", "b"], "a", "c") = ["b"]
+ * ArrayUtils.removeElements(["a", "b", "a"], "a") = ["b", "a"]
+ * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
+ *
+ *
+ * @param the component type of the array
+ * @param array the array to remove the element from, may be {@code null}
+ * @param values the elements to be removed
+ * @return A new array containing the existing elements except the
+ * earliest-encountered occurrences of the specified elements.
+ * @since 3.0.1
+ */
+ public static T[] removeElements(final T[] array, final T... values) {
+ if (isEmpty(array) || isEmpty(values)) {
+ return clone(array);
+ }
+ final HashMap occurrences = new HashMap(values.length);
+ for (final T v : values) {
+ final MutableInt count = occurrences.get(v);
+ if (count == null) {
+ occurrences.put(v, new MutableInt(1));
+ } else {
+ count.increment();
+ }
+ }
+ final BitSet toRemove = new BitSet();
+ for (int i = 0; i < array.length; i++) {
+ final T key = array[i];
+ final MutableInt count = occurrences.get(key);
+ if (count != null) {
+ if (count.decrementAndGet() == 0) {
+ occurrences.remove(key);
+ }
+ toRemove.set(i);
+ }
+ }
+ @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
+ final
+ T[] result = (T[]) removeAll(array, toRemove);
+ return result;
+ }
+
+ /**
+ * Removes the elements at the specified positions from the specified array.
+ * All remaining elements are shifted to the left.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except those at the specified positions. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.removeAll([1], 0) = []
+ * ArrayUtils.removeAll([2, 6], 0) = [6]
+ * ArrayUtils.removeAll([2, 6], 0, 1) = []
+ * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param indices the positions of the elements to be removed
+ * @return A new array containing the existing elements except those
+ * at the specified positions.
+ * @throws IndexOutOfBoundsException if any index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 3.0.1
+ */
+ public static byte[] removeAll(final byte[] array, final int... indices) {
+ return (byte[]) removeAll((Object) array, indices);
+ }
+
+ /**
+ * Removes occurrences of specified elements, in specified quantities,
+ * from the specified array. All subsequent elements are shifted left.
+ * For any element-to-be-removed specified in greater quantities than
+ * contained in the original array, no change occurs beyond the
+ * removal of the existing matching items.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except for the earliest-encountered occurrences of the specified
+ * elements. The component type of the returned array is always the same
+ * as that of the input array.
+ *
+ *
+ * ArrayUtils.removeElements(null, 1, 2) = null
+ * ArrayUtils.removeElements([], 1, 2) = []
+ * ArrayUtils.removeElements([1], 2, 3) = [1]
+ * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
+ * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
+ * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param values the elements to be removed
+ * @return A new array containing the existing elements except the
+ * earliest-encountered occurrences of the specified elements.
+ * @since 3.0.1
+ */
+ public static byte[] removeElements(final byte[] array, final byte... values) {
+ if (isEmpty(array) || isEmpty(values)) {
+ return clone(array);
+ }
+ final Map occurrences = new HashMap(values.length);
+ for (final byte v : values) {
+ final Byte boxed = Byte.valueOf(v);
+ final MutableInt count = occurrences.get(boxed);
+ if (count == null) {
+ occurrences.put(boxed, new MutableInt(1));
+ } else {
+ count.increment();
+ }
+ }
+ final BitSet toRemove = new BitSet();
+ for (int i = 0; i < array.length; i++) {
+ final byte key = array[i];
+ final MutableInt count = occurrences.get(key);
+ if (count != null) {
+ if (count.decrementAndGet() == 0) {
+ occurrences.remove(key);
+ }
+ toRemove.set(i);
+ }
+ }
+ return (byte[]) removeAll(array, toRemove);
+ }
+
+ /**
+ * Removes the elements at the specified positions from the specified array.
+ * All remaining elements are shifted to the left.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except those at the specified positions. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.removeAll([1], 0) = []
+ * ArrayUtils.removeAll([2, 6], 0) = [6]
+ * ArrayUtils.removeAll([2, 6], 0, 1) = []
+ * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param indices the positions of the elements to be removed
+ * @return A new array containing the existing elements except those
+ * at the specified positions.
+ * @throws IndexOutOfBoundsException if any index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 3.0.1
+ */
+ public static short[] removeAll(final short[] array, final int... indices) {
+ return (short[]) removeAll((Object) array, indices);
+ }
+
+ /**
+ * Removes occurrences of specified elements, in specified quantities,
+ * from the specified array. All subsequent elements are shifted left.
+ * For any element-to-be-removed specified in greater quantities than
+ * contained in the original array, no change occurs beyond the
+ * removal of the existing matching items.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except for the earliest-encountered occurrences of the specified
+ * elements. The component type of the returned array is always the same
+ * as that of the input array.
+ *
+ *
+ * ArrayUtils.removeElements(null, 1, 2) = null
+ * ArrayUtils.removeElements([], 1, 2) = []
+ * ArrayUtils.removeElements([1], 2, 3) = [1]
+ * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
+ * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
+ * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param values the elements to be removed
+ * @return A new array containing the existing elements except the
+ * earliest-encountered occurrences of the specified elements.
+ * @since 3.0.1
+ */
+ public static short[] removeElements(final short[] array, final short... values) {
+ if (isEmpty(array) || isEmpty(values)) {
+ return clone(array);
+ }
+ final HashMap occurrences = new HashMap(values.length);
+ for (final short v : values) {
+ final Short boxed = Short.valueOf(v);
+ final MutableInt count = occurrences.get(boxed);
+ if (count == null) {
+ occurrences.put(boxed, new MutableInt(1));
+ } else {
+ count.increment();
+ }
+ }
+ final BitSet toRemove = new BitSet();
+ for (int i = 0; i < array.length; i++) {
+ final short key = array[i];
+ final MutableInt count = occurrences.get(key);
+ if (count != null) {
+ if (count.decrementAndGet() == 0) {
+ occurrences.remove(key);
+ }
+ toRemove.set(i);
+ }
+ }
+ return (short[]) removeAll(array, toRemove);
+ }
+
+ /**
+ * Removes the elements at the specified positions from the specified array.
+ * All remaining elements are shifted to the left.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except those at the specified positions. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.removeAll([1], 0) = []
+ * ArrayUtils.removeAll([2, 6], 0) = [6]
+ * ArrayUtils.removeAll([2, 6], 0, 1) = []
+ * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param indices the positions of the elements to be removed
+ * @return A new array containing the existing elements except those
+ * at the specified positions.
+ * @throws IndexOutOfBoundsException if any index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 3.0.1
+ */
+ public static int[] removeAll(final int[] array, final int... indices) {
+ return (int[]) removeAll((Object) array, indices);
+ }
+
+ /**
+ * Removes occurrences of specified elements, in specified quantities,
+ * from the specified array. All subsequent elements are shifted left.
+ * For any element-to-be-removed specified in greater quantities than
+ * contained in the original array, no change occurs beyond the
+ * removal of the existing matching items.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except for the earliest-encountered occurrences of the specified
+ * elements. The component type of the returned array is always the same
+ * as that of the input array.
+ *
+ *
+ * ArrayUtils.removeElements(null, 1, 2) = null
+ * ArrayUtils.removeElements([], 1, 2) = []
+ * ArrayUtils.removeElements([1], 2, 3) = [1]
+ * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
+ * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
+ * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param values the elements to be removed
+ * @return A new array containing the existing elements except the
+ * earliest-encountered occurrences of the specified elements.
+ * @since 3.0.1
+ */
+ public static int[] removeElements(final int[] array, final int... values) {
+ if (isEmpty(array) || isEmpty(values)) {
+ return clone(array);
+ }
+ final HashMap occurrences = new HashMap(values.length);
+ for (final int v : values) {
+ final Integer boxed = Integer.valueOf(v);
+ final MutableInt count = occurrences.get(boxed);
+ if (count == null) {
+ occurrences.put(boxed, new MutableInt(1));
+ } else {
+ count.increment();
+ }
+ }
+ final BitSet toRemove = new BitSet();
+ for (int i = 0; i < array.length; i++) {
+ final int key = array[i];
+ final MutableInt count = occurrences.get(key);
+ if (count != null) {
+ if (count.decrementAndGet() == 0) {
+ occurrences.remove(key);
+ }
+ toRemove.set(i);
+ }
+ }
+ return (int[]) removeAll(array, toRemove);
+ }
+
+ /**
+ * Removes the elements at the specified positions from the specified array.
+ * All remaining elements are shifted to the left.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except those at the specified positions. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.removeAll([1], 0) = []
+ * ArrayUtils.removeAll([2, 6], 0) = [6]
+ * ArrayUtils.removeAll([2, 6], 0, 1) = []
+ * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param indices the positions of the elements to be removed
+ * @return A new array containing the existing elements except those
+ * at the specified positions.
+ * @throws IndexOutOfBoundsException if any index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 3.0.1
+ */
+ public static char[] removeAll(final char[] array, final int... indices) {
+ return (char[]) removeAll((Object) array, indices);
+ }
+
+ /**
+ * Removes occurrences of specified elements, in specified quantities,
+ * from the specified array. All subsequent elements are shifted left.
+ * For any element-to-be-removed specified in greater quantities than
+ * contained in the original array, no change occurs beyond the
+ * removal of the existing matching items.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except for the earliest-encountered occurrences of the specified
+ * elements. The component type of the returned array is always the same
+ * as that of the input array.
+ *
+ *
+ * ArrayUtils.removeElements(null, 1, 2) = null
+ * ArrayUtils.removeElements([], 1, 2) = []
+ * ArrayUtils.removeElements([1], 2, 3) = [1]
+ * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
+ * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
+ * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param values the elements to be removed
+ * @return A new array containing the existing elements except the
+ * earliest-encountered occurrences of the specified elements.
+ * @since 3.0.1
+ */
+ public static char[] removeElements(final char[] array, final char... values) {
+ if (isEmpty(array) || isEmpty(values)) {
+ return clone(array);
+ }
+ final HashMap occurrences = new HashMap(values.length);
+ for (final char v : values) {
+ final Character boxed = Character.valueOf(v);
+ final MutableInt count = occurrences.get(boxed);
+ if (count == null) {
+ occurrences.put(boxed, new MutableInt(1));
+ } else {
+ count.increment();
+ }
+ }
+ final BitSet toRemove = new BitSet();
+ for (int i = 0; i < array.length; i++) {
+ final char key = array[i];
+ final MutableInt count = occurrences.get(key);
+ if (count != null) {
+ if (count.decrementAndGet() == 0) {
+ occurrences.remove(key);
+ }
+ toRemove.set(i);
+ }
+ }
+ return (char[]) removeAll(array, toRemove);
+ }
+
+ /**
+ * Removes the elements at the specified positions from the specified array.
+ * All remaining elements are shifted to the left.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except those at the specified positions. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.removeAll([1], 0) = []
+ * ArrayUtils.removeAll([2, 6], 0) = [6]
+ * ArrayUtils.removeAll([2, 6], 0, 1) = []
+ * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param indices the positions of the elements to be removed
+ * @return A new array containing the existing elements except those
+ * at the specified positions.
+ * @throws IndexOutOfBoundsException if any index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 3.0.1
+ */
+ public static long[] removeAll(final long[] array, final int... indices) {
+ return (long[]) removeAll((Object) array, indices);
+ }
+
+ /**
+ * Removes occurrences of specified elements, in specified quantities,
+ * from the specified array. All subsequent elements are shifted left.
+ * For any element-to-be-removed specified in greater quantities than
+ * contained in the original array, no change occurs beyond the
+ * removal of the existing matching items.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except for the earliest-encountered occurrences of the specified
+ * elements. The component type of the returned array is always the same
+ * as that of the input array.
+ *
+ *
+ * ArrayUtils.removeElements(null, 1, 2) = null
+ * ArrayUtils.removeElements([], 1, 2) = []
+ * ArrayUtils.removeElements([1], 2, 3) = [1]
+ * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
+ * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
+ * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param values the elements to be removed
+ * @return A new array containing the existing elements except the
+ * earliest-encountered occurrences of the specified elements.
+ * @since 3.0.1
+ */
+ public static long[] removeElements(final long[] array, final long... values) {
+ if (isEmpty(array) || isEmpty(values)) {
+ return clone(array);
+ }
+ final HashMap occurrences = new HashMap(values.length);
+ for (final long v : values) {
+ final Long boxed = Long.valueOf(v);
+ final MutableInt count = occurrences.get(boxed);
+ if (count == null) {
+ occurrences.put(boxed, new MutableInt(1));
+ } else {
+ count.increment();
+ }
+ }
+ final BitSet toRemove = new BitSet();
+ for (int i = 0; i < array.length; i++) {
+ final long key = array[i];
+ final MutableInt count = occurrences.get(key);
+ if (count != null) {
+ if (count.decrementAndGet() == 0) {
+ occurrences.remove(key);
+ }
+ toRemove.set(i);
+ }
+ }
+ return (long[]) removeAll(array, toRemove);
+ }
+
+ /**
+ * Removes the elements at the specified positions from the specified array.
+ * All remaining elements are shifted to the left.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except those at the specified positions. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.removeAll([1], 0) = []
+ * ArrayUtils.removeAll([2, 6], 0) = [6]
+ * ArrayUtils.removeAll([2, 6], 0, 1) = []
+ * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param indices the positions of the elements to be removed
+ * @return A new array containing the existing elements except those
+ * at the specified positions.
+ * @throws IndexOutOfBoundsException if any index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 3.0.1
+ */
+ public static float[] removeAll(final float[] array, final int... indices) {
+ return (float[]) removeAll((Object) array, indices);
+ }
+
+ /**
+ * Removes occurrences of specified elements, in specified quantities,
+ * from the specified array. All subsequent elements are shifted left.
+ * For any element-to-be-removed specified in greater quantities than
+ * contained in the original array, no change occurs beyond the
+ * removal of the existing matching items.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except for the earliest-encountered occurrences of the specified
+ * elements. The component type of the returned array is always the same
+ * as that of the input array.
+ *
+ *
+ * ArrayUtils.removeElements(null, 1, 2) = null
+ * ArrayUtils.removeElements([], 1, 2) = []
+ * ArrayUtils.removeElements([1], 2, 3) = [1]
+ * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
+ * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
+ * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param values the elements to be removed
+ * @return A new array containing the existing elements except the
+ * earliest-encountered occurrences of the specified elements.
+ * @since 3.0.1
+ */
+ public static float[] removeElements(final float[] array, final float... values) {
+ if (isEmpty(array) || isEmpty(values)) {
+ return clone(array);
+ }
+ final HashMap occurrences = new HashMap(values.length);
+ for (final float v : values) {
+ final Float boxed = Float.valueOf(v);
+ final MutableInt count = occurrences.get(boxed);
+ if (count == null) {
+ occurrences.put(boxed, new MutableInt(1));
+ } else {
+ count.increment();
+ }
+ }
+ final BitSet toRemove = new BitSet();
+ for (int i = 0; i < array.length; i++) {
+ final float key = array[i];
+ final MutableInt count = occurrences.get(key);
+ if (count != null) {
+ if (count.decrementAndGet() == 0) {
+ occurrences.remove(key);
+ }
+ toRemove.set(i);
+ }
+ }
+ return (float[]) removeAll(array, toRemove);
+ }
+
+ /**
+ * Removes the elements at the specified positions from the specified array.
+ * All remaining elements are shifted to the left.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except those at the specified positions. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.removeAll([1], 0) = []
+ * ArrayUtils.removeAll([2, 6], 0) = [6]
+ * ArrayUtils.removeAll([2, 6], 0, 1) = []
+ * ArrayUtils.removeAll([2, 6, 3], 1, 2) = [2]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 2) = [6]
+ * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param indices the positions of the elements to be removed
+ * @return A new array containing the existing elements except those
+ * at the specified positions.
+ * @throws IndexOutOfBoundsException if any index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 3.0.1
+ */
+ public static double[] removeAll(final double[] array, final int... indices) {
+ return (double[]) removeAll((Object) array, indices);
+ }
+
+ /**
+ * Removes occurrences of specified elements, in specified quantities,
+ * from the specified array. All subsequent elements are shifted left.
+ * For any element-to-be-removed specified in greater quantities than
+ * contained in the original array, no change occurs beyond the
+ * removal of the existing matching items.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except for the earliest-encountered occurrences of the specified
+ * elements. The component type of the returned array is always the same
+ * as that of the input array.
+ *
+ *
+ * ArrayUtils.removeElements(null, 1, 2) = null
+ * ArrayUtils.removeElements([], 1, 2) = []
+ * ArrayUtils.removeElements([1], 2, 3) = [1]
+ * ArrayUtils.removeElements([1, 3], 1, 2) = [3]
+ * ArrayUtils.removeElements([1, 3, 1], 1) = [3, 1]
+ * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param values the elements to be removed
+ * @return A new array containing the existing elements except the
+ * earliest-encountered occurrences of the specified elements.
+ * @since 3.0.1
+ */
+ public static double[] removeElements(final double[] array, final double... values) {
+ if (isEmpty(array) || isEmpty(values)) {
+ return clone(array);
+ }
+ final HashMap occurrences = new HashMap(values.length);
+ for (final double v : values) {
+ final Double boxed = Double.valueOf(v);
+ final MutableInt count = occurrences.get(boxed);
+ if (count == null) {
+ occurrences.put(boxed, new MutableInt(1));
+ } else {
+ count.increment();
+ }
+ }
+ final BitSet toRemove = new BitSet();
+ for (int i = 0; i < array.length; i++) {
+ final double key = array[i];
+ final MutableInt count = occurrences.get(key);
+ if (count != null) {
+ if (count.decrementAndGet() == 0) {
+ occurrences.remove(key);
+ }
+ toRemove.set(i);
+ }
+ }
+ return (double[]) removeAll(array, toRemove);
+ }
+
+ /**
+ * Removes the elements at the specified positions from the specified array.
+ * All remaining elements are shifted to the left.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except those at the specified positions. The component
+ * type of the returned array is always the same as that of the input
+ * array.
+ *
+ *
If the input array is {@code null}, an IndexOutOfBoundsException
+ * will be thrown, because in that case no valid index can be specified.
+ *
+ *
+ * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
+ * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
+ *
+ *
+ * @param array the array to remove the element from, may not be {@code null}
+ * @param indices the positions of the elements to be removed
+ * @return A new array containing the existing elements except those
+ * at the specified positions.
+ * @throws IndexOutOfBoundsException if any index is out of range
+ * (index < 0 || index >= array.length), or if the array is {@code null}.
+ * @since 3.0.1
+ */
+ public static boolean[] removeAll(final boolean[] array, final int... indices) {
+ return (boolean[]) removeAll((Object) array, indices);
+ }
+
+ /**
+ * Removes occurrences of specified elements, in specified quantities,
+ * from the specified array. All subsequent elements are shifted left.
+ * For any element-to-be-removed specified in greater quantities than
+ * contained in the original array, no change occurs beyond the
+ * removal of the existing matching items.
+ *
+ *
This method returns a new array with the same elements of the input
+ * array except for the earliest-encountered occurrences of the specified
+ * elements. The component type of the returned array is always the same
+ * as that of the input array.
+ *
+ *
+ * ArrayUtils.removeElements(null, true, false) = null
+ * ArrayUtils.removeElements([], true, false) = []
+ * ArrayUtils.removeElements([true], false, false) = [true]
+ * ArrayUtils.removeElements([true, false], true, true) = [false]
+ * ArrayUtils.removeElements([true, false, true], true) = [false, true]
+ * ArrayUtils.removeElements([true, false, true], true, true) = [false]
+ *
+ *
+ * @param array the array to remove the element from, may be {@code null}
+ * @param values the elements to be removed
+ * @return A new array containing the existing elements except the
+ * earliest-encountered occurrences of the specified elements.
+ * @since 3.0.1
+ */
+ public static boolean[] removeElements(final boolean[] array, final boolean... values) {
+ if (isEmpty(array) || isEmpty(values)) {
+ return clone(array);
+ }
+ final HashMap occurrences = new HashMap(2); // only two possible values here
+ for (final boolean v : values) {
+ final Boolean boxed = Boolean.valueOf(v);
+ final MutableInt count = occurrences.get(boxed);
+ if (count == null) {
+ occurrences.put(boxed, new MutableInt(1));
+ } else {
+ count.increment();
+ }
+ }
+ final BitSet toRemove = new BitSet();
+ for (int i = 0; i < array.length; i++) {
+ final boolean key = array[i];
+ final MutableInt count = occurrences.get(key);
+ if (count != null) {
+ if (count.decrementAndGet() == 0) {
+ occurrences.remove(key);
+ }
+ toRemove.set(i);
+ }
+ }
+ return (boolean[]) removeAll(array, toRemove);
+ }
+
+ /**
+ * Removes multiple array elements specified by index.
+ * @param array source
+ * @param indices to remove
+ * @return new array of same type minus elements specified by unique values of {@code indices}
+ * @since 3.0.1
+ */
+ // package protected for access by unit tests
+ static Object removeAll(final Object array, final int... indices) {
+ final int length = getLength(array);
+ int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
+ int[] clonedIndices = clone(indices);
+ Arrays.sort(clonedIndices);
+
+ // identify length of result array
+ if (isNotEmpty(clonedIndices)) {
+ int i = clonedIndices.length;
+ int prevIndex = length;
+ while (--i >= 0) {
+ final int index = clonedIndices[i];
+ if (index < 0 || index >= length) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
+ }
+ if (index >= prevIndex) {
+ continue;
+ }
+ diff++;
+ prevIndex = index;
+ }
+ }
+
+ // create result array
+ final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
+ if (diff < length) {
+ int end = length; // index just after last copy
+ int dest = length - diff; // number of entries so far not copied
+ for (int i = clonedIndices.length - 1; i >= 0; i--) {
+ final int index = clonedIndices[i];
+ if (end - index > 1) { // same as (cp > 0)
+ final int cp = end - index - 1;
+ dest -= cp;
+ System.arraycopy(array, index + 1, result, dest, cp);
+ // Afer this copy, we still have room for dest items.
+ }
+ end = index;
+ }
+ if (end > 0) {
+ System.arraycopy(array, 0, result, 0, end);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Removes multiple array elements specified by indices.
+ *
+ * @param array source
+ * @param indices to remove
+ * @return new array of same type minus elements specified by the set bits in {@code indices}
+ * @since 3.2
+ */
+ // package protected for access by unit tests
+ static Object removeAll(final Object array, final BitSet indices) {
+ final int srcLength = ArrayUtils.getLength(array);
+ // No need to check maxIndex here, because method only currently called from removeElements()
+ // which guarantee to generate on;y valid bit entries.
+// final int maxIndex = indices.length();
+// if (maxIndex > srcLength) {
+// throw new IndexOutOfBoundsException("Index: " + (maxIndex-1) + ", Length: " + srcLength);
+// }
+ final int removals = indices.cardinality(); // true bits are items to remove
+ final Object result = Array.newInstance(array.getClass().getComponentType(), srcLength - removals);
+ int srcIndex = 0;
+ int destIndex = 0;
+ int count;
+ int set;
+ while ((set = indices.nextSetBit(srcIndex)) != -1) {
+ count = set - srcIndex;
+ if (count > 0) {
+ System.arraycopy(array, srcIndex, result, destIndex, count);
+ destIndex += count;
+ }
+ srcIndex = indices.nextClearBit(set);
+ }
+ count = srcLength - srcIndex;
+ if (count > 0) {
+ System.arraycopy(array, srcIndex, result, destIndex, count);
+ }
+ return result;
+ }
+
+ /**
+ * This method checks whether the provided array is sorted according to the class's
+ * {@code compareTo} method.
+ *
+ * @param array the array to check
+ * @param the datatype of the array to check, it must implement {@code Comparable}
+ * @return whether the array is sorted
+ * @since 3.4
+ */
+ public static > boolean isSorted(final T[] array) {
+ return isSorted(array, new Comparator() {
+ @Override
+ public int compare(T o1, T o2) {
+ return o1.compareTo(o2);
+ }
+ });
+ }
+
+
+ /**
+ * This method checks whether the provided array is sorted according to the provided {@code Comparator}.
+ *
+ * @param array the array to check
+ * @param comparator the {@code Comparator} to compare over
+ * @param the datatype of the array
+ * @return whether the array is sorted
+ * @since 3.4
+ */
+ public static boolean isSorted(final T[] array, final Comparator comparator) {
+ if (comparator == null) {
+ throw new IllegalArgumentException("Comparator should not be null.");
+ }
+
+ if (array == null || array.length < 2) {
+ return true;
+ }
+
+ T previous = array[0];
+ final int n = array.length;
+ for (int i = 1; i < n; i++) {
+ final T current = array[i];
+ if (comparator.compare(previous, current) > 0) {
+ return false;
+ }
+
+ previous = current;
+ }
+ return true;
+ }
+
+ /**
+ * This method checks whether the provided array is sorted according to natural ordering.
+ *
+ * @param array the array to check
+ * @return whether the array is sorted according to natural ordering
+ * @since 3.4
+ */
+ public static boolean isSorted(int[] array) {
+ if (array == null || array.length < 2) {
+ return true;
+ }
+
+ int previous = array[0];
+ final int n = array.length;
+ for (int i = 1; i < n; i++) {
+ final int current = array[i];
+ if (NumberUtils.compare(previous, current) > 0) {
+ return false;
+ }
+
+ previous = current;
+ }
+ return true;
+ }
+
+ /**
+ *
This method checks whether the provided array is sorted according to natural ordering.
+ *
+ * @param array the array to check
+ * @return whether the array is sorted according to natural ordering
+ * @since 3.4
+ */
+ public static boolean isSorted(long[] array) {
+ if (array == null || array.length < 2) {
+ return true;
+ }
+
+ long previous = array[0];
+ final int n = array.length;
+ for (int i = 1; i < n; i++) {
+ final long current = array[i];
+ if (NumberUtils.compare(previous, current) > 0) {
+ return false;
+ }
+
+ previous = current;
+ }
+ return true;
+ }
+
+ /**
+ *
This method checks whether the provided array is sorted according to natural ordering.
+ *
+ * @param array the array to check
+ * @return whether the array is sorted according to natural ordering
+ * @since 3.4
+ */
+ public static boolean isSorted(short[] array) {
+ if (array == null || array.length < 2) {
+ return true;
+ }
+
+ short previous = array[0];
+ final int n = array.length;
+ for (int i = 1; i < n; i++) {
+ final short current = array[i];
+ if (NumberUtils.compare(previous, current) > 0) {
+ return false;
+ }
+
+ previous = current;
+ }
+ return true;
+ }
+
+ /**
+ *
This method checks whether the provided array is sorted according to natural ordering.
+ *
+ * @param array the array to check
+ * @return whether the array is sorted according to natural ordering
+ * @since 3.4
+ */
+ public static boolean isSorted(final double[] array) {
+ if (array == null || array.length < 2) {
+ return true;
+ }
+
+ double previous = array[0];
+ final int n = array.length;
+ for (int i = 1; i < n; i++) {
+ final double current = array[i];
+ if (Double.compare(previous, current) > 0) {
+ return false;
+ }
+
+ previous = current;
+ }
+ return true;
+ }
+
+ /**
+ *
This method checks whether the provided array is sorted according to natural ordering.
+ *
+ * @param array the array to check
+ * @return whether the array is sorted according to natural ordering
+ * @since 3.4
+ */
+ public static boolean isSorted(final float[] array) {
+ if (array == null || array.length < 2) {
+ return true;
+ }
+
+ float previous = array[0];
+ final int n = array.length;
+ for (int i = 1; i < n; i++) {
+ final float current = array[i];
+ if (Float.compare(previous, current) > 0) {
+ return false;
+ }
+
+ previous = current;
+ }
+ return true;
+ }
+
+ /**
+ *
This method checks whether the provided array is sorted according to natural ordering.
+ *
+ * @param array the array to check
+ * @return whether the array is sorted according to natural ordering
+ * @since 3.4
+ */
+ public static boolean isSorted(byte[] array) {
+ if (array == null || array.length < 2) {
+ return true;
+ }
+
+ byte previous = array[0];
+ final int n = array.length;
+ for (int i = 1; i < n; i++) {
+ final byte current = array[i];
+ if (NumberUtils.compare(previous, current) > 0) {
+ return false;
+ }
+
+ previous = current;
+ }
+ return true;
+ }
+
+ /**
+ *
This method checks whether the provided array is sorted according to natural ordering.
+ *
+ * @param array the array to check
+ * @return whether the array is sorted according to natural ordering
+ * @since 3.4
+ */
+ public static boolean isSorted(char[] array) {
+ if (array == null || array.length < 2) {
+ return true;
+ }
+
+ char previous = array[0];
+ final int n = array.length;
+ for (int i = 1; i < n; i++) {
+ final char current = array[i];
+ if (CharUtils.compare(previous, current) > 0) {
+ return false;
+ }
+
+ previous = current;
+ }
+ return true;
+ }
+
+ /**
+ *
This method checks whether the provided array is sorted according to natural ordering
+ * ({@code false} before {@code true}).
+ *
+ * @param array the array to check
+ * @return whether the array is sorted according to natural ordering
+ * @since 3.4
+ */
+ public static boolean isSorted(boolean[] array) {
+ if (array == null || array.length < 2) {
+ return true;
+ }
+
+ boolean previous = array[0];
+ final int n = array.length;
+ for (int i = 1; i < n; i++) {
+ final boolean current = array[i];
+ if (BooleanUtils.compare(previous, current) > 0) {
+ return false;
+ }
+
+ previous = current;
+ }
+ return true;
+ }
+
+ /**
+ * Removes the occurrences of the specified element from the specified boolean array.
+ *
+ *
+ * All subsequent elements are shifted to the left (subtracts one from their indices).
+ * If the array doesn't contains such an element, no elements are removed from the array.
+ * null
will be returned if the input array is null
.
+ *
+ *
+ * @param element the element to remove
+ * @param array the input array
+ *
+ * @return A new array containing the existing elements except the occurrences of the specified element.
+ * @since 3.5
+ */
+ public static boolean[] removeAllOccurences(final boolean[] array, final boolean element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+
+ int[] indices = new int[array.length - index];
+ indices[0] = index;
+ int count = 1;
+
+ while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
+ indices[count++] = index;
+ }
+
+ return removeAll(array, Arrays.copyOf(indices, count));
+ }
+
+ /**
+ * Removes the occurrences of the specified element from the specified char array.
+ *
+ *
+ * All subsequent elements are shifted to the left (subtracts one from their indices).
+ * If the array doesn't contains such an element, no elements are removed from the array.
+ * null
will be returned if the input array is null
.
+ *
+ *
+ * @param element the element to remove
+ * @param array the input array
+ *
+ * @return A new array containing the existing elements except the occurrences of the specified element.
+ * @since 3.5
+ */
+ public static char[] removeAllOccurences(final char[] array, final char element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+
+ int[] indices = new int[array.length - index];
+ indices[0] = index;
+ int count = 1;
+
+ while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
+ indices[count++] = index;
+ }
+
+ return removeAll(array, Arrays.copyOf(indices, count));
+ }
+
+ /**
+ * Removes the occurrences of the specified element from the specified byte array.
+ *
+ *
+ * All subsequent elements are shifted to the left (subtracts one from their indices).
+ * If the array doesn't contains such an element, no elements are removed from the array.
+ * null
will be returned if the input array is null
.
+ *
+ *
+ * @param element the element to remove
+ * @param array the input array
+ *
+ * @return A new array containing the existing elements except the occurrences of the specified element.
+ * @since 3.5
+ */
+ public static byte[] removeAllOccurences(final byte[] array, final byte element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+
+ int[] indices = new int[array.length - index];
+ indices[0] = index;
+ int count = 1;
+
+ while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
+ indices[count++] = index;
+ }
+
+ return removeAll(array, Arrays.copyOf(indices, count));
+ }
+
+ /**
+ * Removes the occurrences of the specified element from the specified short array.
+ *
+ *
+ * All subsequent elements are shifted to the left (subtracts one from their indices).
+ * If the array doesn't contains such an element, no elements are removed from the array.
+ * null
will be returned if the input array is null
.
+ *
+ *
+ * @param element the element to remove
+ * @param array the input array
+ *
+ * @return A new array containing the existing elements except the occurrences of the specified element.
+ * @since 3.5
+ */
+ public static short[] removeAllOccurences(final short[] array, final short element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+
+ int[] indices = new int[array.length - index];
+ indices[0] = index;
+ int count = 1;
+
+ while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
+ indices[count++] = index;
+ }
+
+ return removeAll(array, Arrays.copyOf(indices, count));
+ }
+
+ /**
+ * Removes the occurrences of the specified element from the specified int array.
+ *
+ *
+ * All subsequent elements are shifted to the left (subtracts one from their indices).
+ * If the array doesn't contains such an element, no elements are removed from the array.
+ * null
will be returned if the input array is null
.
+ *
+ *
+ * @param element the element to remove
+ * @param array the input array
+ *
+ * @return A new array containing the existing elements except the occurrences of the specified element.
+ * @since 3.5
+ */
+ public static int[] removeAllOccurences(final int[] array, final int element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+
+ int[] indices = new int[array.length - index];
+ indices[0] = index;
+ int count = 1;
+
+ while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
+ indices[count++] = index;
+ }
+
+ return removeAll(array, Arrays.copyOf(indices, count));
+ }
+
+ /**
+ * Removes the occurrences of the specified element from the specified long array.
+ *
+ *
+ * All subsequent elements are shifted to the left (subtracts one from their indices).
+ * If the array doesn't contains such an element, no elements are removed from the array.
+ * null
will be returned if the input array is null
.
+ *
+ *
+ * @param element the element to remove
+ * @param array the input array
+ *
+ * @return A new array containing the existing elements except the occurrences of the specified element.
+ * @since 3.5
+ */
+ public static long[] removeAllOccurences(final long[] array, final long element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+
+ int[] indices = new int[array.length - index];
+ indices[0] = index;
+ int count = 1;
+
+ while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
+ indices[count++] = index;
+ }
+
+ return removeAll(array, Arrays.copyOf(indices, count));
+ }
+
+ /**
+ * Removes the occurrences of the specified element from the specified float array.
+ *
+ *
+ * All subsequent elements are shifted to the left (subtracts one from their indices).
+ * If the array doesn't contains such an element, no elements are removed from the array.
+ * null
will be returned if the input array is null
.
+ *
+ *
+ * @param element the element to remove
+ * @param array the input array
+ *
+ * @return A new array containing the existing elements except the occurrences of the specified element.
+ * @since 3.5
+ */
+ public static float[] removeAllOccurences(final float[] array, final float element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+
+ int[] indices = new int[array.length - index];
+ indices[0] = index;
+ int count = 1;
+
+ while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
+ indices[count++] = index;
+ }
+
+ return removeAll(array, Arrays.copyOf(indices, count));
+ }
+
+ /**
+ * Removes the occurrences of the specified element from the specified double array.
+ *
+ *
+ * All subsequent elements are shifted to the left (subtracts one from their indices).
+ * If the array doesn't contains such an element, no elements are removed from the array.
+ * null
will be returned if the input array is null
.
+ *
+ *
+ * @param element the element to remove
+ * @param array the input array
+ *
+ * @return A new array containing the existing elements except the occurrences of the specified element.
+ * @since 3.5
+ */
+ public static double[] removeAllOccurences(final double[] array, final double element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+
+ int[] indices = new int[array.length - index];
+ indices[0] = index;
+ int count = 1;
+
+ while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
+ indices[count++] = index;
+ }
+
+ return removeAll(array, Arrays.copyOf(indices, count));
+ }
+
+ /**
+ * Removes the occurrences of the specified element from the specified array.
+ *
+ *
+ * All subsequent elements are shifted to the left (subtracts one from their indices).
+ * If the array doesn't contains such an element, no elements are removed from the array.
+ * null
will be returned if the input array is null
.
+ *
+ *
+ * @param the type of object in the array
+ * @param element the element to remove
+ * @param array the input array
+ *
+ * @return A new array containing the existing elements except the occurrences of the specified element.
+ * @since 3.5
+ */
+ public static T[] removeAllOccurences(final T[] array, final T element) {
+ int index = indexOf(array, element);
+ if (index == INDEX_NOT_FOUND) {
+ return clone(array);
+ }
+
+ int[] indices = new int[array.length - index];
+ indices[0] = index;
+ int count = 1;
+
+ while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
+ indices[count++] = index;
+ }
+
+ return removeAll(array, Arrays.copyOf(indices, count));
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/BitField.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/BitField.java
new file mode 100644
index 000000000..65b465e91
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/BitField.java
@@ -0,0 +1,322 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+/**
+ * Supports operations on bit-mapped fields. Instances of this class can be
+ * used to store a flag or data within an {@code int}, {@code short} or
+ * {@code byte}.
+ *
+ * Each {@code BitField} is constructed with a mask value, which indicates
+ * the bits that will be used to store and retrieve the data for that field.
+ * For instance, the mask {@code 0xFF} indicates the least-significant byte
+ * should be used to store the data.
+ *
+ * As an example, consider a car painting machine that accepts
+ * paint instructions as integers. Bit fields can be used to encode this:
+ *
+ *
+ * // blue, green and red are 1 byte values (0-255) stored in the three least
+ * // significant bytes
+ * BitField blue = new BitField(0xFF);
+ * BitField green = new BitField(0xFF00);
+ * BitField red = new BitField(0xFF0000);
+ *
+ * // anyColor is a flag triggered if any color is used
+ * BitField anyColor = new BitField(0xFFFFFF);
+ *
+ * // isMetallic is a single bit flag
+ * BitField isMetallic = new BitField(0x1000000);
+ *
+ *
+ * Using these {@code BitField} instances, a paint instruction can be
+ * encoded into an integer:
+ *
+ *
+ * int paintInstruction = 0;
+ * paintInstruction = red.setValue(paintInstruction, 35);
+ * paintInstruction = green.setValue(paintInstruction, 100);
+ * paintInstruction = blue.setValue(paintInstruction, 255);
+ *
+ *
+ * Flags and data can be retrieved from the integer:
+ *
+ *
+ * // Prints true if red, green or blue is non-zero
+ * System.out.println(anyColor.isSet(paintInstruction)); // prints true
+ *
+ * // Prints value of red, green and blue
+ * System.out.println(red.getValue(paintInstruction)); // prints 35
+ * System.out.println(green.getValue(paintInstruction)); // prints 100
+ * System.out.println(blue.getValue(paintInstruction)); // prints 255
+ *
+ * // Prints true if isMetallic was set
+ * System.out.println(isMetallic.isSet(paintInstruction)); // prints false
+ *
+ *
+ * @since 2.0
+ */
+public class BitField {
+
+ private final int _mask;
+ private final int _shift_count;
+
+ /**
+ * Creates a BitField instance.
+ *
+ * @param mask the mask specifying which bits apply to this
+ * BitField. Bits that are set in this mask are the bits
+ * that this BitField operates on
+ */
+ public BitField(final int mask) {
+ _mask = mask;
+ _shift_count = mask != 0 ? Integer.numberOfTrailingZeros(mask) : 0;
+ }
+
+ /**
+ * Obtains the value for the specified BitField, appropriately
+ * shifted right.
+ *
+ * Many users of a BitField will want to treat the specified
+ * bits as an int value, and will not want to be aware that the
+ * value is stored as a BitField (and so shifted left so many
+ * bits).
+ *
+ * @see #setValue(int,int)
+ * @param holder the int data containing the bits we're interested
+ * in
+ * @return the selected bits, shifted right appropriately
+ */
+ public int getValue(final int holder) {
+ return getRawValue(holder) >> _shift_count;
+ }
+
+ /**
+ * Obtains the value for the specified BitField, appropriately
+ * shifted right, as a short.
+ *
+ * Many users of a BitField will want to treat the specified
+ * bits as an int value, and will not want to be aware that the
+ * value is stored as a BitField (and so shifted left so many
+ * bits).
+ *
+ * @see #setShortValue(short,short)
+ * @param holder the short data containing the bits we're
+ * interested in
+ * @return the selected bits, shifted right appropriately
+ */
+ public short getShortValue(final short holder) {
+ return (short) getValue(holder);
+ }
+
+ /**
+ * Obtains the value for the specified BitField, unshifted.
+ *
+ * @param holder the int data containing the bits we're
+ * interested in
+ * @return the selected bits
+ */
+ public int getRawValue(final int holder) {
+ return holder & _mask;
+ }
+
+ /**
+ * Obtains the value for the specified BitField, unshifted.
+ *
+ * @param holder the short data containing the bits we're
+ * interested in
+ * @return the selected bits
+ */
+ public short getShortRawValue(final short holder) {
+ return (short) getRawValue(holder);
+ }
+
+ /**
+ * Returns whether the field is set or not.
+ *
+ * This is most commonly used for a single-bit field, which is
+ * often used to represent a boolean value; the results of using
+ * it for a multi-bit field is to determine whether *any* of its
+ * bits are set.
+ *
+ * @param holder the int data containing the bits we're interested
+ * in
+ * @return {@code true} if any of the bits are set,
+ * else {@code false}
+ */
+ public boolean isSet(final int holder) {
+ return (holder & _mask) != 0;
+ }
+
+ /**
+ * Returns whether all of the bits are set or not.
+ *
+ * This is a stricter test than {@link #isSet(int)},
+ * in that all of the bits in a multi-bit set must be set
+ * for this method to return {@code true}.
+ *
+ * @param holder the int data containing the bits we're
+ * interested in
+ * @return {@code true} if all of the bits are set,
+ * else {@code false}
+ */
+ public boolean isAllSet(final int holder) {
+ return (holder & _mask) == _mask;
+ }
+
+ /**
+ * Replaces the bits with new values.
+ *
+ * @see #getValue(int)
+ * @param holder the int data containing the bits we're
+ * interested in
+ * @param value the new value for the specified bits
+ * @return the value of holder with the bits from the value
+ * parameter replacing the old bits
+ */
+ public int setValue(final int holder, final int value) {
+ return (holder & ~_mask) | ((value << _shift_count) & _mask);
+ }
+
+ /**
+ * Replaces the bits with new values.
+ *
+ * @see #getShortValue(short)
+ * @param holder the short data containing the bits we're
+ * interested in
+ * @param value the new value for the specified bits
+ * @return the value of holder with the bits from the value
+ * parameter replacing the old bits
+ */
+ public short setShortValue(final short holder, final short value) {
+ return (short) setValue(holder, value);
+ }
+
+ /**
+ * Clears the bits.
+ *
+ * @param holder the int data containing the bits we're
+ * interested in
+ * @return the value of holder with the specified bits cleared
+ * (set to {@code 0})
+ */
+ public int clear(final int holder) {
+ return holder & ~_mask;
+ }
+
+ /**
+ * Clears the bits.
+ *
+ * @param holder the short data containing the bits we're
+ * interested in
+ * @return the value of holder with the specified bits cleared
+ * (set to {@code 0})
+ */
+ public short clearShort(final short holder) {
+ return (short) clear(holder);
+ }
+
+ /**
+ * Clears the bits.
+ *
+ * @param holder the byte data containing the bits we're
+ * interested in
+ *
+ * @return the value of holder with the specified bits cleared
+ * (set to {@code 0})
+ */
+ public byte clearByte(final byte holder) {
+ return (byte) clear(holder);
+ }
+
+ /**
+ * Sets the bits.
+ *
+ * @param holder the int data containing the bits we're
+ * interested in
+ * @return the value of holder with the specified bits set
+ * to {@code 1}
+ */
+ public int set(final int holder) {
+ return holder | _mask;
+ }
+
+ /**
+ * Sets the bits.
+ *
+ * @param holder the short data containing the bits we're
+ * interested in
+ * @return the value of holder with the specified bits set
+ * to {@code 1}
+ */
+ public short setShort(final short holder) {
+ return (short) set(holder);
+ }
+
+ /**
+ * Sets the bits.
+ *
+ * @param holder the byte data containing the bits we're
+ * interested in
+ *
+ * @return the value of holder with the specified bits set
+ * to {@code 1}
+ */
+ public byte setByte(final byte holder) {
+ return (byte) set(holder);
+ }
+
+ /**
+ * Sets a boolean BitField.
+ *
+ * @param holder the int data containing the bits we're
+ * interested in
+ * @param flag indicating whether to set or clear the bits
+ * @return the value of holder with the specified bits set or
+ * cleared
+ */
+ public int setBoolean(final int holder, final boolean flag) {
+ return flag ? set(holder) : clear(holder);
+ }
+
+ /**
+ * Sets a boolean BitField.
+ *
+ * @param holder the short data containing the bits we're
+ * interested in
+ * @param flag indicating whether to set or clear the bits
+ * @return the value of holder with the specified bits set or
+ * cleared
+ */
+ public short setShortBoolean(final short holder, final boolean flag) {
+ return flag ? setShort(holder) : clearShort(holder);
+ }
+
+ /**
+ * Sets a boolean BitField.
+ *
+ * @param holder the byte data containing the bits we're
+ * interested in
+ * @param flag indicating whether to set or clear the bits
+ * @return the value of holder with the specified bits set or
+ * cleared
+ */
+ public byte setByteBoolean(final byte holder, final boolean flag) {
+ return flag ? setByte(holder) : clearByte(holder);
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/BooleanUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/BooleanUtils.java
new file mode 100644
index 000000000..2c46d5bd3
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/BooleanUtils.java
@@ -0,0 +1,1104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import org.apache.commons.lang3.math.NumberUtils;
+
+/**
+ * Operations on boolean primitives and Boolean objects.
+ *
+ * This class tries to handle {@code null} input gracefully.
+ * An exception will not be thrown for a {@code null} input.
+ * Each method documents its behaviour in more detail.
+ *
+ * #ThreadSafe#
+ * @since 2.0
+ */
+public class BooleanUtils {
+
+ /**
+ * {@code BooleanUtils} instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as {@code BooleanUtils.negate(true);}.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public BooleanUtils() {
+ super();
+ }
+
+ // Boolean utilities
+ //--------------------------------------------------------------------------
+ /**
+ * Negates the specified boolean.
+ *
+ * If {@code null} is passed in, {@code null} will be returned.
+ *
+ * NOTE: This returns null and will throw a NullPointerException if autoboxed to a boolean.
+ *
+ *
+ * BooleanUtils.negate(Boolean.TRUE) = Boolean.FALSE;
+ * BooleanUtils.negate(Boolean.FALSE) = Boolean.TRUE;
+ * BooleanUtils.negate(null) = null;
+ *
+ *
+ * @param bool the Boolean to negate, may be null
+ * @return the negated Boolean, or {@code null} if {@code null} input
+ */
+ public static Boolean negate(final Boolean bool) {
+ if (bool == null) {
+ return null;
+ }
+ return bool.booleanValue() ? Boolean.FALSE : Boolean.TRUE;
+ }
+
+ // boolean Boolean methods
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if a {@code Boolean} value is {@code true},
+ * handling {@code null} by returning {@code false}.
+ *
+ *
+ * BooleanUtils.isTrue(Boolean.TRUE) = true
+ * BooleanUtils.isTrue(Boolean.FALSE) = false
+ * BooleanUtils.isTrue(null) = false
+ *
+ *
+ * @param bool the boolean to check, null returns {@code false}
+ * @return {@code true} only if the input is non-null and true
+ * @since 2.1
+ */
+ public static boolean isTrue(final Boolean bool) {
+ return Boolean.TRUE.equals(bool);
+ }
+
+ /**
+ * Checks if a {@code Boolean} value is not {@code true},
+ * handling {@code null} by returning {@code true}.
+ *
+ *
+ * BooleanUtils.isNotTrue(Boolean.TRUE) = false
+ * BooleanUtils.isNotTrue(Boolean.FALSE) = true
+ * BooleanUtils.isNotTrue(null) = true
+ *
+ *
+ * @param bool the boolean to check, null returns {@code true}
+ * @return {@code true} if the input is null or false
+ * @since 2.3
+ */
+ public static boolean isNotTrue(final Boolean bool) {
+ return !isTrue(bool);
+ }
+
+ /**
+ * Checks if a {@code Boolean} value is {@code false},
+ * handling {@code null} by returning {@code false}.
+ *
+ *
+ * BooleanUtils.isFalse(Boolean.TRUE) = false
+ * BooleanUtils.isFalse(Boolean.FALSE) = true
+ * BooleanUtils.isFalse(null) = false
+ *
+ *
+ * @param bool the boolean to check, null returns {@code false}
+ * @return {@code true} only if the input is non-null and false
+ * @since 2.1
+ */
+ public static boolean isFalse(final Boolean bool) {
+ return Boolean.FALSE.equals(bool);
+ }
+
+ /**
+ * Checks if a {@code Boolean} value is not {@code false},
+ * handling {@code null} by returning {@code true}.
+ *
+ *
+ * BooleanUtils.isNotFalse(Boolean.TRUE) = true
+ * BooleanUtils.isNotFalse(Boolean.FALSE) = false
+ * BooleanUtils.isNotFalse(null) = true
+ *
+ *
+ * @param bool the boolean to check, null returns {@code true}
+ * @return {@code true} if the input is null or true
+ * @since 2.3
+ */
+ public static boolean isNotFalse(final Boolean bool) {
+ return !isFalse(bool);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts a Boolean to a boolean handling {@code null}
+ * by returning {@code false}.
+ *
+ *
+ * BooleanUtils.toBoolean(Boolean.TRUE) = true
+ * BooleanUtils.toBoolean(Boolean.FALSE) = false
+ * BooleanUtils.toBoolean(null) = false
+ *
+ *
+ * @param bool the boolean to convert
+ * @return {@code true} or {@code false}, {@code null} returns {@code false}
+ */
+ public static boolean toBoolean(final Boolean bool) {
+ return bool != null && bool.booleanValue();
+ }
+
+ /**
+ * Converts a Boolean to a boolean handling {@code null}.
+ *
+ *
+ * BooleanUtils.toBooleanDefaultIfNull(Boolean.TRUE, false) = true
+ * BooleanUtils.toBooleanDefaultIfNull(Boolean.FALSE, true) = false
+ * BooleanUtils.toBooleanDefaultIfNull(null, true) = true
+ *
+ *
+ * @param bool the boolean to convert
+ * @param valueIfNull the boolean value to return if {@code null}
+ * @return {@code true} or {@code false}
+ */
+ public static boolean toBooleanDefaultIfNull(final Boolean bool, final boolean valueIfNull) {
+ if (bool == null) {
+ return valueIfNull;
+ }
+ return bool.booleanValue();
+ }
+
+ // Integer to Boolean methods
+ //-----------------------------------------------------------------------
+ /**
+ * Converts an int to a boolean using the convention that {@code zero}
+ * is {@code false}.
+ *
+ *
+ * BooleanUtils.toBoolean(0) = false
+ * BooleanUtils.toBoolean(1) = true
+ * BooleanUtils.toBoolean(2) = true
+ *
+ *
+ * @param value the int to convert
+ * @return {@code true} if non-zero, {@code false}
+ * if zero
+ */
+ public static boolean toBoolean(final int value) {
+ return value != 0;
+ }
+
+ /**
+ * Converts an int to a Boolean using the convention that {@code zero}
+ * is {@code false}.
+ *
+ *
+ * BooleanUtils.toBoolean(0) = Boolean.FALSE
+ * BooleanUtils.toBoolean(1) = Boolean.TRUE
+ * BooleanUtils.toBoolean(2) = Boolean.TRUE
+ *
+ *
+ * @param value the int to convert
+ * @return Boolean.TRUE if non-zero, Boolean.FALSE if zero,
+ * {@code null} if {@code null}
+ */
+ public static Boolean toBooleanObject(final int value) {
+ return value == 0 ? Boolean.FALSE : Boolean.TRUE;
+ }
+
+ /**
+ * Converts an Integer to a Boolean using the convention that {@code zero}
+ * is {@code false}.
+ *
+ * {@code null} will be converted to {@code null}.
+ *
+ * NOTE: This returns null and will throw a NullPointerException if autoboxed to a boolean.
+ *
+ *
+ * BooleanUtils.toBoolean(Integer.valueOf(0)) = Boolean.FALSE
+ * BooleanUtils.toBoolean(Integer.valueOf(1)) = Boolean.TRUE
+ * BooleanUtils.toBoolean(Integer.valueOf(null)) = null
+ *
+ *
+ * @param value the Integer to convert
+ * @return Boolean.TRUE if non-zero, Boolean.FALSE if zero,
+ * {@code null} if {@code null} input
+ */
+ public static Boolean toBooleanObject(final Integer value) {
+ if (value == null) {
+ return null;
+ }
+ return value.intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
+ }
+
+ /**
+ * Converts an int to a boolean specifying the conversion values.
+ *
+ *
+ * BooleanUtils.toBoolean(0, 1, 0) = false
+ * BooleanUtils.toBoolean(1, 1, 0) = true
+ * BooleanUtils.toBoolean(2, 1, 2) = false
+ * BooleanUtils.toBoolean(2, 2, 0) = true
+ *
+ *
+ * @param value the Integer to convert
+ * @param trueValue the value to match for {@code true}
+ * @param falseValue the value to match for {@code false}
+ * @return {@code true} or {@code false}
+ * @throws IllegalArgumentException if no match
+ */
+ public static boolean toBoolean(final int value, final int trueValue, final int falseValue) {
+ if (value == trueValue) {
+ return true;
+ }
+ if (value == falseValue) {
+ return false;
+ }
+ // no match
+ throw new IllegalArgumentException("The Integer did not match either specified value");
+ }
+
+ /**
+ * Converts an Integer to a boolean specifying the conversion values.
+ *
+ *
+ * BooleanUtils.toBoolean(Integer.valueOf(0), Integer.valueOf(1), Integer.valueOf(0)) = false
+ * BooleanUtils.toBoolean(Integer.valueOf(1), Integer.valueOf(1), Integer.valueOf(0)) = true
+ * BooleanUtils.toBoolean(Integer.valueOf(2), Integer.valueOf(1), Integer.valueOf(2)) = false
+ * BooleanUtils.toBoolean(Integer.valueOf(2), Integer.valueOf(2), Integer.valueOf(0)) = true
+ * BooleanUtils.toBoolean(null, null, Integer.valueOf(0)) = true
+ *
+ *
+ * @param value the Integer to convert
+ * @param trueValue the value to match for {@code true}, may be {@code null}
+ * @param falseValue the value to match for {@code false}, may be {@code null}
+ * @return {@code true} or {@code false}
+ * @throws IllegalArgumentException if no match
+ */
+ public static boolean toBoolean(final Integer value, final Integer trueValue, final Integer falseValue) {
+ if (value == null) {
+ if (trueValue == null) {
+ return true;
+ }
+ if (falseValue == null) {
+ return false;
+ }
+ } else if (value.equals(trueValue)) {
+ return true;
+ } else if (value.equals(falseValue)) {
+ return false;
+ }
+ // no match
+ throw new IllegalArgumentException("The Integer did not match either specified value");
+ }
+
+ /**
+ * Converts an int to a Boolean specifying the conversion values.
+ *
+ * NOTE: This returns null and will throw a NullPointerException if autoboxed to a boolean.
+ *
+ *
+ * BooleanUtils.toBooleanObject(0, 0, 2, 3) = Boolean.TRUE
+ * BooleanUtils.toBooleanObject(2, 1, 2, 3) = Boolean.FALSE
+ * BooleanUtils.toBooleanObject(3, 1, 2, 3) = null
+ *
+ *
+ * @param value the Integer to convert
+ * @param trueValue the value to match for {@code true}
+ * @param falseValue the value to match for {@code false}
+ * @param nullValue the value to to match for {@code null}
+ * @return Boolean.TRUE, Boolean.FALSE, or {@code null}
+ * @throws IllegalArgumentException if no match
+ */
+ public static Boolean toBooleanObject(final int value, final int trueValue, final int falseValue, final int nullValue) {
+ if (value == trueValue) {
+ return Boolean.TRUE;
+ }
+ if (value == falseValue) {
+ return Boolean.FALSE;
+ }
+ if (value == nullValue) {
+ return null;
+ }
+ // no match
+ throw new IllegalArgumentException("The Integer did not match any specified value");
+ }
+
+ /**
+ * Converts an Integer to a Boolean specifying the conversion values.
+ *
+ * NOTE: This returns null and will throw a NullPointerException if autoboxed to a boolean.
+ *
+ *
+ * BooleanUtils.toBooleanObject(Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(2), Integer.valueOf(3)) = Boolean.TRUE
+ * BooleanUtils.toBooleanObject(Integer.valueOf(2), Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)) = Boolean.FALSE
+ * BooleanUtils.toBooleanObject(Integer.valueOf(3), Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)) = null
+ *
+ *
+ * @param value the Integer to convert
+ * @param trueValue the value to match for {@code true}, may be {@code null}
+ * @param falseValue the value to match for {@code false}, may be {@code null}
+ * @param nullValue the value to to match for {@code null}, may be {@code null}
+ * @return Boolean.TRUE, Boolean.FALSE, or {@code null}
+ * @throws IllegalArgumentException if no match
+ */
+ public static Boolean toBooleanObject(final Integer value, final Integer trueValue, final Integer falseValue, final Integer nullValue) {
+ if (value == null) {
+ if (trueValue == null) {
+ return Boolean.TRUE;
+ }
+ if (falseValue == null) {
+ return Boolean.FALSE;
+ }
+ if (nullValue == null) {
+ return null;
+ }
+ } else if (value.equals(trueValue)) {
+ return Boolean.TRUE;
+ } else if (value.equals(falseValue)) {
+ return Boolean.FALSE;
+ } else if (value.equals(nullValue)) {
+ return null;
+ }
+ // no match
+ throw new IllegalArgumentException("The Integer did not match any specified value");
+ }
+
+ // Boolean to Integer methods
+ //-----------------------------------------------------------------------
+ /**
+ * Converts a boolean to an int using the convention that
+ * {@code zero} is {@code false}.
+ *
+ *
+ * BooleanUtils.toInteger(true) = 1
+ * BooleanUtils.toInteger(false) = 0
+ *
+ *
+ * @param bool the boolean to convert
+ * @return one if {@code true}, zero if {@code false}
+ */
+ public static int toInteger(final boolean bool) {
+ return bool ? 1 : 0;
+ }
+
+ /**
+ * Converts a boolean to an Integer using the convention that
+ * {@code zero} is {@code false}.
+ *
+ *
+ * BooleanUtils.toIntegerObject(true) = Integer.valueOf(1)
+ * BooleanUtils.toIntegerObject(false) = Integer.valueOf(0)
+ *
+ *
+ * @param bool the boolean to convert
+ * @return one if {@code true}, zero if {@code false}
+ */
+ public static Integer toIntegerObject(final boolean bool) {
+ return bool ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO;
+ }
+
+ /**
+ * Converts a Boolean to a Integer using the convention that
+ * {@code zero} is {@code false}.
+ *
+ * {@code null} will be converted to {@code null}.
+ *
+ *
+ * BooleanUtils.toIntegerObject(Boolean.TRUE) = Integer.valueOf(1)
+ * BooleanUtils.toIntegerObject(Boolean.FALSE) = Integer.valueOf(0)
+ *
+ *
+ * @param bool the Boolean to convert
+ * @return one if Boolean.TRUE, zero if Boolean.FALSE, {@code null} if {@code null}
+ */
+ public static Integer toIntegerObject(final Boolean bool) {
+ if (bool == null) {
+ return null;
+ }
+ return bool.booleanValue() ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO;
+ }
+
+ /**
+ * Converts a boolean to an int specifying the conversion values.
+ *
+ *
+ * BooleanUtils.toInteger(true, 1, 0) = 1
+ * BooleanUtils.toInteger(false, 1, 0) = 0
+ *
+ *
+ * @param bool the to convert
+ * @param trueValue the value to return if {@code true}
+ * @param falseValue the value to return if {@code false}
+ * @return the appropriate value
+ */
+ public static int toInteger(final boolean bool, final int trueValue, final int falseValue) {
+ return bool ? trueValue : falseValue;
+ }
+
+ /**
+ * Converts a Boolean to an int specifying the conversion values.
+ *
+ *
+ * BooleanUtils.toInteger(Boolean.TRUE, 1, 0, 2) = 1
+ * BooleanUtils.toInteger(Boolean.FALSE, 1, 0, 2) = 0
+ * BooleanUtils.toInteger(null, 1, 0, 2) = 2
+ *
+ *
+ * @param bool the Boolean to convert
+ * @param trueValue the value to return if {@code true}
+ * @param falseValue the value to return if {@code false}
+ * @param nullValue the value to return if {@code null}
+ * @return the appropriate value
+ */
+ public static int toInteger(final Boolean bool, final int trueValue, final int falseValue, final int nullValue) {
+ if (bool == null) {
+ return nullValue;
+ }
+ return bool.booleanValue() ? trueValue : falseValue;
+ }
+
+ /**
+ * Converts a boolean to an Integer specifying the conversion values.
+ *
+ *
+ * BooleanUtils.toIntegerObject(true, Integer.valueOf(1), Integer.valueOf(0)) = Integer.valueOf(1)
+ * BooleanUtils.toIntegerObject(false, Integer.valueOf(1), Integer.valueOf(0)) = Integer.valueOf(0)
+ *
+ *
+ * @param bool the to convert
+ * @param trueValue the value to return if {@code true}, may be {@code null}
+ * @param falseValue the value to return if {@code false}, may be {@code null}
+ * @return the appropriate value
+ */
+ public static Integer toIntegerObject(final boolean bool, final Integer trueValue, final Integer falseValue) {
+ return bool ? trueValue : falseValue;
+ }
+
+ /**
+ * Converts a Boolean to an Integer specifying the conversion values.
+ *
+ *
+ * BooleanUtils.toIntegerObject(Boolean.TRUE, Integer.valueOf(1), Integer.valueOf(0), Integer.valueOf(2)) = Integer.valueOf(1)
+ * BooleanUtils.toIntegerObject(Boolean.FALSE, Integer.valueOf(1), Integer.valueOf(0), Integer.valueOf(2)) = Integer.valueOf(0)
+ * BooleanUtils.toIntegerObject(null, Integer.valueOf(1), Integer.valueOf(0), Integer.valueOf(2)) = Integer.valueOf(2)
+ *
+ *
+ * @param bool the Boolean to convert
+ * @param trueValue the value to return if {@code true}, may be {@code null}
+ * @param falseValue the value to return if {@code false}, may be {@code null}
+ * @param nullValue the value to return if {@code null}, may be {@code null}
+ * @return the appropriate value
+ */
+ public static Integer toIntegerObject(final Boolean bool, final Integer trueValue, final Integer falseValue, final Integer nullValue) {
+ if (bool == null) {
+ return nullValue;
+ }
+ return bool.booleanValue() ? trueValue : falseValue;
+ }
+
+ // String to Boolean methods
+ //-----------------------------------------------------------------------
+ /**
+ * Converts a String to a Boolean.
+ *
+ * {@code 'true'}, {@code 'on'}, {@code 'y'}, {@code 't'} or {@code 'yes'}
+ * (case insensitive) will return {@code true}.
+ * {@code 'false'}, {@code 'off'}, {@code 'n'}, {@code 'f'} or {@code 'no'}
+ * (case insensitive) will return {@code false}.
+ * Otherwise, {@code null} is returned.
+ *
+ * NOTE: This returns null and will throw a NullPointerException if autoboxed to a boolean.
+ *
+ *
+ * // N.B. case is not significant
+ * BooleanUtils.toBooleanObject(null) = null
+ * BooleanUtils.toBooleanObject("true") = Boolean.TRUE
+ * BooleanUtils.toBooleanObject("T") = Boolean.TRUE // i.e. T[RUE]
+ * BooleanUtils.toBooleanObject("false") = Boolean.FALSE
+ * BooleanUtils.toBooleanObject("f") = Boolean.FALSE // i.e. f[alse]
+ * BooleanUtils.toBooleanObject("No") = Boolean.FALSE
+ * BooleanUtils.toBooleanObject("n") = Boolean.FALSE // i.e. n[o]
+ * BooleanUtils.toBooleanObject("on") = Boolean.TRUE
+ * BooleanUtils.toBooleanObject("ON") = Boolean.TRUE
+ * BooleanUtils.toBooleanObject("off") = Boolean.FALSE
+ * BooleanUtils.toBooleanObject("oFf") = Boolean.FALSE
+ * BooleanUtils.toBooleanObject("yes") = Boolean.TRUE
+ * BooleanUtils.toBooleanObject("Y") = Boolean.TRUE // i.e. Y[ES]
+ * BooleanUtils.toBooleanObject("blue") = null
+ * BooleanUtils.toBooleanObject("true ") = null // trailing space (too long)
+ * BooleanUtils.toBooleanObject("ono") = null // does not match on or no
+ *
+ *
+ * @param str the String to check; upper and lower case are treated as the same
+ * @return the Boolean value of the string, {@code null} if no match or {@code null} input
+ */
+ public static Boolean toBooleanObject(final String str) {
+ // Previously used equalsIgnoreCase, which was fast for interned 'true'.
+ // Non interned 'true' matched 15 times slower.
+ //
+ // Optimisation provides same performance as before for interned 'true'.
+ // Similar performance for null, 'false', and other strings not length 2/3/4.
+ // 'true'/'TRUE' match 4 times slower, 'tRUE'/'True' 7 times slower.
+ if (str == "true") {
+ return Boolean.TRUE;
+ }
+ if (str == null) {
+ return null;
+ }
+ switch (str.length()) {
+ case 1: {
+ final char ch0 = str.charAt(0);
+ if (ch0 == 'y' || ch0 == 'Y' ||
+ ch0 == 't' || ch0 == 'T') {
+ return Boolean.TRUE;
+ }
+ if (ch0 == 'n' || ch0 == 'N' ||
+ ch0 == 'f' || ch0 == 'F') {
+ return Boolean.FALSE;
+ }
+ break;
+ }
+ case 2: {
+ final char ch0 = str.charAt(0);
+ final char ch1 = str.charAt(1);
+ if ((ch0 == 'o' || ch0 == 'O') &&
+ (ch1 == 'n' || ch1 == 'N') ) {
+ return Boolean.TRUE;
+ }
+ if ((ch0 == 'n' || ch0 == 'N') &&
+ (ch1 == 'o' || ch1 == 'O') ) {
+ return Boolean.FALSE;
+ }
+ break;
+ }
+ case 3: {
+ final char ch0 = str.charAt(0);
+ final char ch1 = str.charAt(1);
+ final char ch2 = str.charAt(2);
+ if ((ch0 == 'y' || ch0 == 'Y') &&
+ (ch1 == 'e' || ch1 == 'E') &&
+ (ch2 == 's' || ch2 == 'S') ) {
+ return Boolean.TRUE;
+ }
+ if ((ch0 == 'o' || ch0 == 'O') &&
+ (ch1 == 'f' || ch1 == 'F') &&
+ (ch2 == 'f' || ch2 == 'F') ) {
+ return Boolean.FALSE;
+ }
+ break;
+ }
+ case 4: {
+ final char ch0 = str.charAt(0);
+ final char ch1 = str.charAt(1);
+ final char ch2 = str.charAt(2);
+ final char ch3 = str.charAt(3);
+ if ((ch0 == 't' || ch0 == 'T') &&
+ (ch1 == 'r' || ch1 == 'R') &&
+ (ch2 == 'u' || ch2 == 'U') &&
+ (ch3 == 'e' || ch3 == 'E') ) {
+ return Boolean.TRUE;
+ }
+ break;
+ }
+ case 5: {
+ final char ch0 = str.charAt(0);
+ final char ch1 = str.charAt(1);
+ final char ch2 = str.charAt(2);
+ final char ch3 = str.charAt(3);
+ final char ch4 = str.charAt(4);
+ if ((ch0 == 'f' || ch0 == 'F') &&
+ (ch1 == 'a' || ch1 == 'A') &&
+ (ch2 == 'l' || ch2 == 'L') &&
+ (ch3 == 's' || ch3 == 'S') &&
+ (ch4 == 'e' || ch4 == 'E') ) {
+ return Boolean.FALSE;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return null;
+ }
+
+ /**
+ * Converts a String to a Boolean throwing an exception if no match.
+ *
+ * NOTE: This returns null and will throw a NullPointerException if autoboxed to a boolean.
+ *
+ *
+ * BooleanUtils.toBooleanObject("true", "true", "false", "null") = Boolean.TRUE
+ * BooleanUtils.toBooleanObject("false", "true", "false", "null") = Boolean.FALSE
+ * BooleanUtils.toBooleanObject("null", "true", "false", "null") = null
+ *
+ *
+ * @param str the String to check
+ * @param trueString the String to match for {@code true} (case sensitive), may be {@code null}
+ * @param falseString the String to match for {@code false} (case sensitive), may be {@code null}
+ * @param nullString the String to match for {@code null} (case sensitive), may be {@code null}
+ * @return the Boolean value of the string, {@code null} if either the String matches {@code nullString}
+ * or if {@code null} input and {@code nullString} is {@code null}
+ * @throws IllegalArgumentException if the String doesn't match
+ */
+ public static Boolean toBooleanObject(final String str, final String trueString, final String falseString, final String nullString) {
+ if (str == null) {
+ if (trueString == null) {
+ return Boolean.TRUE;
+ }
+ if (falseString == null) {
+ return Boolean.FALSE;
+ }
+ if (nullString == null) {
+ return null;
+ }
+ } else if (str.equals(trueString)) {
+ return Boolean.TRUE;
+ } else if (str.equals(falseString)) {
+ return Boolean.FALSE;
+ } else if (str.equals(nullString)) {
+ return null;
+ }
+ // no match
+ throw new IllegalArgumentException("The String did not match any specified value");
+ }
+
+ // String to boolean methods
+ //-----------------------------------------------------------------------
+ /**
+ * Converts a String to a boolean (optimised for performance).
+ *
+ * {@code 'true'}, {@code 'on'}, {@code 'y'}, {@code 't'} or {@code 'yes'}
+ * (case insensitive) will return {@code true}. Otherwise,
+ * {@code false} is returned.
+ *
+ * This method performs 4 times faster (JDK1.4) than
+ * {@code Boolean.valueOf(String)}. However, this method accepts
+ * 'on' and 'yes', 't', 'y' as true values.
+ *
+ *
+ * BooleanUtils.toBoolean(null) = false
+ * BooleanUtils.toBoolean("true") = true
+ * BooleanUtils.toBoolean("TRUE") = true
+ * BooleanUtils.toBoolean("tRUe") = true
+ * BooleanUtils.toBoolean("on") = true
+ * BooleanUtils.toBoolean("yes") = true
+ * BooleanUtils.toBoolean("false") = false
+ * BooleanUtils.toBoolean("x gti") = false
+ * BooleanUtils.toBooleanObject("y") = true
+ * BooleanUtils.toBooleanObject("n") = false
+ * BooleanUtils.toBooleanObject("t") = true
+ * BooleanUtils.toBooleanObject("f") = false
+ *
+ *
+ * @param str the String to check
+ * @return the boolean value of the string, {@code false} if no match or the String is null
+ */
+ public static boolean toBoolean(final String str) {
+ return toBooleanObject(str) == Boolean.TRUE;
+ }
+
+ /**
+ * Converts a String to a Boolean throwing an exception if no match found.
+ *
+ *
+ * BooleanUtils.toBoolean("true", "true", "false") = true
+ * BooleanUtils.toBoolean("false", "true", "false") = false
+ *
+ *
+ * @param str the String to check
+ * @param trueString the String to match for {@code true} (case sensitive), may be {@code null}
+ * @param falseString the String to match for {@code false} (case sensitive), may be {@code null}
+ * @return the boolean value of the string
+ * @throws IllegalArgumentException if the String doesn't match
+ */
+ public static boolean toBoolean(final String str, final String trueString, final String falseString) {
+ if (str == trueString) {
+ return true;
+ } else if (str == falseString) {
+ return false;
+ } else if (str != null) {
+ if (str.equals(trueString)) {
+ return true;
+ } else if (str.equals(falseString)) {
+ return false;
+ }
+ }
+ // no match
+ throw new IllegalArgumentException("The String did not match either specified value");
+ }
+
+ // Boolean to String methods
+ //-----------------------------------------------------------------------
+ /**
+ * Converts a Boolean to a String returning {@code 'true'},
+ * {@code 'false'}, or {@code null}.
+ *
+ *
+ * BooleanUtils.toStringTrueFalse(Boolean.TRUE) = "true"
+ * BooleanUtils.toStringTrueFalse(Boolean.FALSE) = "false"
+ * BooleanUtils.toStringTrueFalse(null) = null;
+ *
+ *
+ * @param bool the Boolean to check
+ * @return {@code 'true'}, {@code 'false'}, or {@code null}
+ */
+ public static String toStringTrueFalse(final Boolean bool) {
+ return toString(bool, "true", "false", null);
+ }
+
+ /**
+ * Converts a Boolean to a String returning {@code 'on'},
+ * {@code 'off'}, or {@code null}.
+ *
+ *
+ * BooleanUtils.toStringOnOff(Boolean.TRUE) = "on"
+ * BooleanUtils.toStringOnOff(Boolean.FALSE) = "off"
+ * BooleanUtils.toStringOnOff(null) = null;
+ *
+ *
+ * @param bool the Boolean to check
+ * @return {@code 'on'}, {@code 'off'}, or {@code null}
+ */
+ public static String toStringOnOff(final Boolean bool) {
+ return toString(bool, "on", "off", null);
+ }
+
+ /**
+ * Converts a Boolean to a String returning {@code 'yes'},
+ * {@code 'no'}, or {@code null}.
+ *
+ *
+ * BooleanUtils.toStringYesNo(Boolean.TRUE) = "yes"
+ * BooleanUtils.toStringYesNo(Boolean.FALSE) = "no"
+ * BooleanUtils.toStringYesNo(null) = null;
+ *
+ *
+ * @param bool the Boolean to check
+ * @return {@code 'yes'}, {@code 'no'}, or {@code null}
+ */
+ public static String toStringYesNo(final Boolean bool) {
+ return toString(bool, "yes", "no", null);
+ }
+
+ /**
+ * Converts a Boolean to a String returning one of the input Strings.
+ *
+ *
+ * BooleanUtils.toString(Boolean.TRUE, "true", "false", null) = "true"
+ * BooleanUtils.toString(Boolean.FALSE, "true", "false", null) = "false"
+ * BooleanUtils.toString(null, "true", "false", null) = null;
+ *
+ *
+ * @param bool the Boolean to check
+ * @param trueString the String to return if {@code true}, may be {@code null}
+ * @param falseString the String to return if {@code false}, may be {@code null}
+ * @param nullString the String to return if {@code null}, may be {@code null}
+ * @return one of the three input Strings
+ */
+ public static String toString(final Boolean bool, final String trueString, final String falseString, final String nullString) {
+ if (bool == null) {
+ return nullString;
+ }
+ return bool.booleanValue() ? trueString : falseString;
+ }
+
+ // boolean to String methods
+ //-----------------------------------------------------------------------
+ /**
+ * Converts a boolean to a String returning {@code 'true'}
+ * or {@code 'false'}.
+ *
+ *
+ * BooleanUtils.toStringTrueFalse(true) = "true"
+ * BooleanUtils.toStringTrueFalse(false) = "false"
+ *
+ *
+ * @param bool the Boolean to check
+ * @return {@code 'true'}, {@code 'false'}, or {@code null}
+ */
+ public static String toStringTrueFalse(final boolean bool) {
+ return toString(bool, "true", "false");
+ }
+
+ /**
+ * Converts a boolean to a String returning {@code 'on'}
+ * or {@code 'off'}.
+ *
+ *
+ * BooleanUtils.toStringOnOff(true) = "on"
+ * BooleanUtils.toStringOnOff(false) = "off"
+ *
+ *
+ * @param bool the Boolean to check
+ * @return {@code 'on'}, {@code 'off'}, or {@code null}
+ */
+ public static String toStringOnOff(final boolean bool) {
+ return toString(bool, "on", "off");
+ }
+
+ /**
+ * Converts a boolean to a String returning {@code 'yes'}
+ * or {@code 'no'}.
+ *
+ *
+ * BooleanUtils.toStringYesNo(true) = "yes"
+ * BooleanUtils.toStringYesNo(false) = "no"
+ *
+ *
+ * @param bool the Boolean to check
+ * @return {@code 'yes'}, {@code 'no'}, or {@code null}
+ */
+ public static String toStringYesNo(final boolean bool) {
+ return toString(bool, "yes", "no");
+ }
+
+ /**
+ * Converts a boolean to a String returning one of the input Strings.
+ *
+ *
+ * BooleanUtils.toString(true, "true", "false") = "true"
+ * BooleanUtils.toString(false, "true", "false") = "false"
+ *
+ *
+ * @param bool the Boolean to check
+ * @param trueString the String to return if {@code true}, may be {@code null}
+ * @param falseString the String to return if {@code false}, may be {@code null}
+ * @return one of the two input Strings
+ */
+ public static String toString(final boolean bool, final String trueString, final String falseString) {
+ return bool ? trueString : falseString;
+ }
+
+ // logical operations
+ // ----------------------------------------------------------------------
+ /**
+ * Performs an and on a set of booleans.
+ *
+ *
+ * BooleanUtils.and(true, true) = true
+ * BooleanUtils.and(false, false) = false
+ * BooleanUtils.and(true, false) = false
+ * BooleanUtils.and(true, true, false) = false
+ * BooleanUtils.and(true, true, true) = true
+ *
+ *
+ * @param array an array of {@code boolean}s
+ * @return {@code true} if the and is successful.
+ * @throws IllegalArgumentException if {@code array} is {@code null}
+ * @throws IllegalArgumentException if {@code array} is empty.
+ * @since 3.0.1
+ */
+ public static boolean and(final boolean... array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ }
+ if (array.length == 0) {
+ throw new IllegalArgumentException("Array is empty");
+ }
+ for (final boolean element : array) {
+ if (!element) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Performs an and on an array of Booleans.
+ *
+ *
+ * BooleanUtils.and(Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
+ * BooleanUtils.and(Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
+ * BooleanUtils.and(Boolean.TRUE, Boolean.FALSE) = Boolean.FALSE
+ * BooleanUtils.and(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
+ * BooleanUtils.and(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE) = Boolean.FALSE
+ * BooleanUtils.and(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE) = Boolean.FALSE
+ *
+ *
+ * @param array an array of {@code Boolean}s
+ * @return {@code true} if the and is successful.
+ * @throws IllegalArgumentException if {@code array} is {@code null}
+ * @throws IllegalArgumentException if {@code array} is empty.
+ * @throws IllegalArgumentException if {@code array} contains a {@code null}
+ * @since 3.0.1
+ */
+ public static Boolean and(final Boolean... array) {
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ }
+ if (array.length == 0) {
+ throw new IllegalArgumentException("Array is empty");
+ }
+ try {
+ final boolean[] primitive = ArrayUtils.toPrimitive(array);
+ return and(primitive) ? Boolean.TRUE : Boolean.FALSE;
+ } catch (final NullPointerException ex) {
+ throw new IllegalArgumentException("The array must not contain any null elements");
+ }
+ }
+
+ /**
+ * Performs an or on a set of booleans.
+ *
+ *
+ * BooleanUtils.or(true, true) = true
+ * BooleanUtils.or(false, false) = false
+ * BooleanUtils.or(true, false) = true
+ * BooleanUtils.or(true, true, false) = true
+ * BooleanUtils.or(true, true, true) = true
+ * BooleanUtils.or(false, false, false) = false
+ *
+ *
+ * @param array an array of {@code boolean}s
+ * @return {@code true} if the or is successful.
+ * @throws IllegalArgumentException if {@code array} is {@code null}
+ * @throws IllegalArgumentException if {@code array} is empty.
+ * @since 3.0.1
+ */
+ public static boolean or(final boolean... array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ }
+ if (array.length == 0) {
+ throw new IllegalArgumentException("Array is empty");
+ }
+ for (final boolean element : array) {
+ if (element) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Performs an or on an array of Booleans.
+ *
+ *
+ * BooleanUtils.or(Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
+ * BooleanUtils.or(Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
+ * BooleanUtils.or(Boolean.TRUE, Boolean.FALSE) = Boolean.TRUE
+ * BooleanUtils.or(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE) = Boolean.TRUE
+ * BooleanUtils.or(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE) = Boolean.TRUE
+ * BooleanUtils.or(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE) = Boolean.TRUE
+ * BooleanUtils.or(Boolean.FALSE, Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE
+ *
+ *
+ * @param array an array of {@code Boolean}s
+ * @return {@code true} if the or is successful.
+ * @throws IllegalArgumentException if {@code array} is {@code null}
+ * @throws IllegalArgumentException if {@code array} is empty.
+ * @throws IllegalArgumentException if {@code array} contains a {@code null}
+ * @since 3.0.1
+ */
+ public static Boolean or(final Boolean... array) {
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ }
+ if (array.length == 0) {
+ throw new IllegalArgumentException("Array is empty");
+ }
+ try {
+ final boolean[] primitive = ArrayUtils.toPrimitive(array);
+ return or(primitive) ? Boolean.TRUE : Boolean.FALSE;
+ } catch (final NullPointerException ex) {
+ throw new IllegalArgumentException("The array must not contain any null elements");
+ }
+ }
+
+ /**
+ * Performs an xor on a set of booleans.
+ *
+ *
+ * BooleanUtils.xor(true, true) = false
+ * BooleanUtils.xor(false, false) = false
+ * BooleanUtils.xor(true, false) = true
+ * BooleanUtils.xor(true, true) = false
+ * BooleanUtils.xor(false, false) = false
+ * BooleanUtils.xor(true, false) = true
+ *
+ *
+ * @param array an array of {@code boolean}s
+ * @return {@code true} if the xor is successful.
+ * @throws IllegalArgumentException if {@code array} is {@code null}
+ * @throws IllegalArgumentException if {@code array} is empty.
+ */
+ public static boolean xor(final boolean... array) {
+ // Validates input
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ }
+ if (array.length == 0) {
+ throw new IllegalArgumentException("Array is empty");
+ }
+
+ // false if the neutral element of the xor operator
+ boolean result = false;
+ for (final boolean element : array) {
+ result ^= element;
+ }
+
+ return result;
+ }
+
+ /**
+ * Performs an xor on an array of Booleans.
+ *
+ *
+ * BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE }) = Boolean.FALSE
+ * BooleanUtils.xor(new Boolean[] { Boolean.FALSE, Boolean.FALSE }) = Boolean.FALSE
+ * BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.FALSE }) = Boolean.TRUE
+ *
+ *
+ * @param array an array of {@code Boolean}s
+ * @return {@code true} if the xor is successful.
+ * @throws IllegalArgumentException if {@code array} is {@code null}
+ * @throws IllegalArgumentException if {@code array} is empty.
+ * @throws IllegalArgumentException if {@code array} contains a {@code null}
+ */
+ public static Boolean xor(final Boolean... array) {
+ if (array == null) {
+ throw new IllegalArgumentException("The Array must not be null");
+ }
+ if (array.length == 0) {
+ throw new IllegalArgumentException("Array is empty");
+ }
+ try {
+ final boolean[] primitive = ArrayUtils.toPrimitive(array);
+ return xor(primitive) ? Boolean.TRUE : Boolean.FALSE;
+ } catch (final NullPointerException ex) {
+ throw new IllegalArgumentException("The array must not contain any null elements");
+ }
+ }
+
+ /**
+ * Compares two {@code boolean} values. This is the same functionality as provided in Java 7.
+ *
+ * @param x the first {@code boolean} to compare
+ * @param y the second {@code boolean} to compare
+ * @return the value {@code 0} if {@code x == y};
+ * a value less than {@code 0} if {@code !x && y}; and
+ * a value greater than {@code 0} if {@code x && !y}
+ * @since 3.4
+ */
+ public static int compare(boolean x, boolean y) {
+ if (x == y) {
+ return 0;
+ }
+ return x ? 1 : -1;
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharEncoding.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharEncoding.java
new file mode 100644
index 000000000..7fe9296a3
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharEncoding.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+
+package org.apache.commons.lang3;
+
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+
+/**
+ * Character encoding names required of every implementation of the Java platform.
+ *
+ * According to JRE character
+ * encoding names :
+ *
+ * Every implementation of the Java platform is required to support the following character encodings.
+ * Consult the release documentation for your implementation to see if any other encodings are supported.
+ *
+ *
+ * @see JRE character encoding names
+ * @since 2.1
+ */
+public class CharEncoding {
+
+ /**
+ * ISO Latin Alphabet #1, also known as ISO-LATIN-1.
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ */
+ public static final String ISO_8859_1 = "ISO-8859-1";
+
+ /**
+ * Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block
+ * of the Unicode character set.
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ */
+ public static final String US_ASCII = "US-ASCII";
+
+ /**
+ * Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial
+ * byte-order mark (either order accepted on input, big-endian used on output).
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ */
+ public static final String UTF_16 = "UTF-16";
+
+ /**
+ * Sixteen-bit Unicode Transformation Format, big-endian byte order.
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ */
+ public static final String UTF_16BE = "UTF-16BE";
+
+ /**
+ * Sixteen-bit Unicode Transformation Format, little-endian byte order.
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ */
+ public static final String UTF_16LE = "UTF-16LE";
+
+ /**
+ * Eight-bit Unicode Transformation Format.
+ *
+ * Every implementation of the Java platform is required to support this character encoding.
+ */
+ public static final String UTF_8 = "UTF-8";
+
+ /**
+ * Returns whether the named charset is supported.
+ *
+ * This is similar to
+ * java.nio.charset.Charset.isSupported(String) but handles more formats
+ *
+ * @param name the name of the requested charset; may be either a canonical name or an alias, null returns false
+ * @return {@code true} if the charset is available in the current Java virtual machine
+ */
+ public static boolean isSupported(final String name) {
+ if (name == null) {
+ return false;
+ }
+ try {
+ return Charset.isSupported(name);
+ } catch (final IllegalCharsetNameException ex) {
+ return false;
+ }
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharRange.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharRange.java
new file mode 100644
index 000000000..2ccda7c4e
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharRange.java
@@ -0,0 +1,359 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * A contiguous range of characters, optionally negated.
+ *
+ * Instances are immutable.
+ *
+ * #ThreadSafe#
+ * @since 1.0
+ */
+// TODO: This is no longer public and will be removed later as CharSet is moved
+// to depend on Range.
+final class CharRange implements Iterable, Serializable {
+
+ /**
+ * Required for serialization support. Lang version 2.0.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 8270183163158333422L;
+
+ /** The first character, inclusive, in the range. */
+ private final char start;
+ /** The last character, inclusive, in the range. */
+ private final char end;
+ /** True if the range is everything except the characters specified. */
+ private final boolean negated;
+
+ /** Cached toString. */
+ private transient String iToString;
+
+ /**
+ * Constructs a {@code CharRange} over a set of characters,
+ * optionally negating the range.
+ *
+ * A negated range includes everything except that defined by the
+ * start and end characters.
+ *
+ * If start and end are in the wrong order, they are reversed.
+ * Thus {@code a-e} is the same as {@code e-a}.
+ *
+ * @param start first character, inclusive, in this range
+ * @param end last character, inclusive, in this range
+ * @param negated true to express everything except the range
+ */
+ private CharRange(char start, char end, final boolean negated) {
+ super();
+ if (start > end) {
+ final char temp = start;
+ start = end;
+ end = temp;
+ }
+
+ this.start = start;
+ this.end = end;
+ this.negated = negated;
+ }
+
+ /**
+ * Constructs a {@code CharRange} over a single character.
+ *
+ * @param ch only character in this range
+ * @return the new CharRange object
+ * @see CharRange#CharRange(char, char, boolean)
+ * @since 2.5
+ */
+ public static CharRange is(final char ch) {
+ return new CharRange(ch, ch, false);
+ }
+
+ /**
+ * Constructs a negated {@code CharRange} over a single character.
+ *
+ * @param ch only character in this range
+ * @return the new CharRange object
+ * @see CharRange#CharRange(char, char, boolean)
+ * @since 2.5
+ */
+ public static CharRange isNot(final char ch) {
+ return new CharRange(ch, ch, true);
+ }
+
+ /**
+ * Constructs a {@code CharRange} over a set of characters.
+ *
+ * @param start first character, inclusive, in this range
+ * @param end last character, inclusive, in this range
+ * @return the new CharRange object
+ * @see CharRange#CharRange(char, char, boolean)
+ * @since 2.5
+ */
+ public static CharRange isIn(final char start, final char end) {
+ return new CharRange(start, end, false);
+ }
+
+ /**
+ * Constructs a negated {@code CharRange} over a set of characters.
+ *
+ * @param start first character, inclusive, in this range
+ * @param end last character, inclusive, in this range
+ * @return the new CharRange object
+ * @see CharRange#CharRange(char, char, boolean)
+ * @since 2.5
+ */
+ public static CharRange isNotIn(final char start, final char end) {
+ return new CharRange(start, end, true);
+ }
+
+ // Accessors
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the start character for this character range.
+ *
+ * @return the start char (inclusive)
+ */
+ public char getStart() {
+ return this.start;
+ }
+
+ /**
+ * Gets the end character for this character range.
+ *
+ * @return the end char (inclusive)
+ */
+ public char getEnd() {
+ return this.end;
+ }
+
+ /**
+ * Is this {@code CharRange} negated.
+ *
+ * A negated range includes everything except that defined by the
+ * start and end characters.
+ *
+ * @return {@code true} if negated
+ */
+ public boolean isNegated() {
+ return negated;
+ }
+
+ // Contains
+ //-----------------------------------------------------------------------
+ /**
+ * Is the character specified contained in this range.
+ *
+ * @param ch the character to check
+ * @return {@code true} if this range contains the input character
+ */
+ public boolean contains(final char ch) {
+ return (ch >= start && ch <= end) != negated;
+ }
+
+ /**
+ * Are all the characters of the passed in range contained in
+ * this range.
+ *
+ * @param range the range to check against
+ * @return {@code true} if this range entirely contains the input range
+ * @throws IllegalArgumentException if {@code null} input
+ */
+ public boolean contains(final CharRange range) {
+ if (range == null) {
+ throw new IllegalArgumentException("The Range must not be null");
+ }
+ if (negated) {
+ if (range.negated) {
+ return start >= range.start && end <= range.end;
+ }
+ return range.end < start || range.start > end;
+ }
+ if (range.negated) {
+ return start == 0 && end == Character.MAX_VALUE;
+ }
+ return start <= range.start && end >= range.end;
+ }
+
+ // Basics
+ //-----------------------------------------------------------------------
+ /**
+ * Compares two CharRange objects, returning true if they represent
+ * exactly the same range of characters defined in the same way.
+ *
+ * @param obj the object to compare to
+ * @return true if equal
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof CharRange == false) {
+ return false;
+ }
+ final CharRange other = (CharRange) obj;
+ return start == other.start && end == other.end && negated == other.negated;
+ }
+
+ /**
+ * Gets a hashCode compatible with the equals method.
+ *
+ * @return a suitable hashCode
+ */
+ @Override
+ public int hashCode() {
+ return 83 + start + 7 * end + (negated ? 1 : 0);
+ }
+
+ /**
+ * Gets a string representation of the character range.
+ *
+ * @return string representation of this range
+ */
+ @Override
+ public String toString() {
+ if (iToString == null) {
+ final StringBuilder buf = new StringBuilder(4);
+ if (isNegated()) {
+ buf.append('^');
+ }
+ buf.append(start);
+ if (start != end) {
+ buf.append('-');
+ buf.append(end);
+ }
+ iToString = buf.toString();
+ }
+ return iToString;
+ }
+
+ // Expansions
+ //-----------------------------------------------------------------------
+ /**
+ * Returns an iterator which can be used to walk through the characters described by this range.
+ *
+ * #NotThreadSafe# the iterator is not thread-safe
+ * @return an iterator to the chars represented by this range
+ * @since 2.5
+ */
+ @Override
+ public Iterator iterator() {
+ return new CharacterIterator(this);
+ }
+
+ /**
+ * Character {@link Iterator}.
+ * #NotThreadSafe#
+ */
+ private static class CharacterIterator implements Iterator {
+ /** The current character */
+ private char current;
+
+ private final CharRange range;
+ private boolean hasNext;
+
+ /**
+ * Construct a new iterator for the character range.
+ *
+ * @param r The character range
+ */
+ private CharacterIterator(final CharRange r) {
+ range = r;
+ hasNext = true;
+
+ if (range.negated) {
+ if (range.start == 0) {
+ if (range.end == Character.MAX_VALUE) {
+ // This range is an empty set
+ hasNext = false;
+ } else {
+ current = (char) (range.end + 1);
+ }
+ } else {
+ current = 0;
+ }
+ } else {
+ current = range.start;
+ }
+ }
+
+ /**
+ * Prepare the next character in the range.
+ */
+ private void prepareNext() {
+ if (range.negated) {
+ if (current == Character.MAX_VALUE) {
+ hasNext = false;
+ } else if (current + 1 == range.start) {
+ if (range.end == Character.MAX_VALUE) {
+ hasNext = false;
+ } else {
+ current = (char) (range.end + 1);
+ }
+ } else {
+ current = (char) (current + 1);
+ }
+ } else if (current < range.end) {
+ current = (char) (current + 1);
+ } else {
+ hasNext = false;
+ }
+ }
+
+ /**
+ * Has the iterator not reached the end character yet?
+ *
+ * @return {@code true} if the iterator has yet to reach the character date
+ */
+ @Override
+ public boolean hasNext() {
+ return hasNext;
+ }
+
+ /**
+ * Return the next character in the iteration
+ *
+ * @return {@code Character} for the next character
+ */
+ @Override
+ public Character next() {
+ if (hasNext == false) {
+ throw new NoSuchElementException();
+ }
+ final char cur = current;
+ prepareNext();
+ return Character.valueOf(cur);
+ }
+
+ /**
+ * Always throws UnsupportedOperationException.
+ *
+ * @throws UnsupportedOperationException
+ * @see java.util.Iterator#remove()
+ */
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSequenceUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSequenceUtils.java
new file mode 100644
index 000000000..a5112d9d0
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSequenceUtils.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+/**
+ * Operations on {@link CharSequence} that are
+ * {@code null} safe.
+ *
+ * @see CharSequence
+ * @since 3.0
+ */
+public class CharSequenceUtils {
+
+ private static final int NOT_FOUND = -1;
+
+ /**
+ * {@code CharSequenceUtils} instances should NOT be constructed in
+ * standard programming.
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public CharSequenceUtils() {
+ super();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a new {@code CharSequence} that is a subsequence of this
+ * sequence starting with the {@code char} value at the specified index.
+ *
+ * This provides the {@code CharSequence} equivalent to {@link String#substring(int)}.
+ * The length (in {@code char}) of the returned sequence is {@code length() - start},
+ * so if {@code start == end} then an empty sequence is returned.
+ *
+ * @param cs the specified subsequence, null returns null
+ * @param start the start index, inclusive, valid
+ * @return a new subsequence, may be null
+ * @throws IndexOutOfBoundsException if {@code start} is negative or if
+ * {@code start} is greater than {@code length()}
+ */
+ public static CharSequence subSequence(final CharSequence cs, final int start) {
+ return cs == null ? null : cs.subSequence(start, cs.length());
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Finds the first index in the {@code CharSequence} that matches the
+ * specified character.
+ *
+ * @param cs the {@code CharSequence} to be processed, not null
+ * @param searchChar the char to be searched for
+ * @param start the start index, negative starts at the string start
+ * @return the index where the search char was found, -1 if not found
+ */
+ static int indexOf(final CharSequence cs, final int searchChar, int start) {
+ if (cs instanceof String) {
+ return ((String) cs).indexOf(searchChar, start);
+ }
+ final int sz = cs.length();
+ if (start < 0) {
+ start = 0;
+ }
+ for (int i = start; i < sz; i++) {
+ if (cs.charAt(i) == searchChar) {
+ return i;
+ }
+ }
+ return NOT_FOUND;
+ }
+
+ /**
+ * Used by the indexOf(CharSequence methods) as a green implementation of indexOf.
+ *
+ * @param cs the {@code CharSequence} to be processed
+ * @param searchChar the {@code CharSequence} to be searched for
+ * @param start the start index
+ * @return the index where the search sequence was found
+ */
+ static int indexOf(final CharSequence cs, final CharSequence searchChar, final int start) {
+ return cs.toString().indexOf(searchChar.toString(), start);
+// if (cs instanceof String && searchChar instanceof String) {
+// // TODO: Do we assume searchChar is usually relatively small;
+// // If so then calling toString() on it is better than reverting to
+// // the green implementation in the else block
+// return ((String) cs).indexOf((String) searchChar, start);
+// } else {
+// // TODO: Implement rather than convert to String
+// return cs.toString().indexOf(searchChar.toString(), start);
+// }
+ }
+
+ /**
+ * Finds the last index in the {@code CharSequence} that matches the
+ * specified character.
+ *
+ * @param cs the {@code CharSequence} to be processed
+ * @param searchChar the char to be searched for
+ * @param start the start index, negative returns -1, beyond length starts at end
+ * @return the index where the search char was found, -1 if not found
+ */
+ static int lastIndexOf(final CharSequence cs, final int searchChar, int start) {
+ if (cs instanceof String) {
+ return ((String) cs).lastIndexOf(searchChar, start);
+ }
+ final int sz = cs.length();
+ if (start < 0) {
+ return NOT_FOUND;
+ }
+ if (start >= sz) {
+ start = sz - 1;
+ }
+ for (int i = start; i >= 0; --i) {
+ if (cs.charAt(i) == searchChar) {
+ return i;
+ }
+ }
+ return NOT_FOUND;
+ }
+
+ /**
+ * Used by the lastIndexOf(CharSequence methods) as a green implementation of lastIndexOf
+ *
+ * @param cs the {@code CharSequence} to be processed
+ * @param searchChar the {@code CharSequence} to be searched for
+ * @param start the start index
+ * @return the index where the search sequence was found
+ */
+ static int lastIndexOf(final CharSequence cs, final CharSequence searchChar, final int start) {
+ return cs.toString().lastIndexOf(searchChar.toString(), start);
+// if (cs instanceof String && searchChar instanceof String) {
+// // TODO: Do we assume searchChar is usually relatively small;
+// // If so then calling toString() on it is better than reverting to
+// // the green implementation in the else block
+// return ((String) cs).lastIndexOf((String) searchChar, start);
+// } else {
+// // TODO: Implement rather than convert to String
+// return cs.toString().lastIndexOf(searchChar.toString(), start);
+// }
+ }
+
+ /**
+ * Green implementation of toCharArray.
+ *
+ * @param cs the {@code CharSequence} to be processed
+ * @return the resulting char array
+ */
+ static char[] toCharArray(final CharSequence cs) {
+ if (cs instanceof String) {
+ return ((String) cs).toCharArray();
+ }
+ final int sz = cs.length();
+ final char[] array = new char[cs.length()];
+ for (int i = 0; i < sz; i++) {
+ array[i] = cs.charAt(i);
+ }
+ return array;
+ }
+
+ /**
+ * Green implementation of regionMatches.
+ *
+ * @param cs the {@code CharSequence} to be processed
+ * @param ignoreCase whether or not to be case insensitive
+ * @param thisStart the index to start on the {@code cs} CharSequence
+ * @param substring the {@code CharSequence} to be looked for
+ * @param start the index to start on the {@code substring} CharSequence
+ * @param length character length of the region
+ * @return whether the region matched
+ */
+ static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,
+ final CharSequence substring, final int start, final int length) {
+ if (cs instanceof String && substring instanceof String) {
+ return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);
+ }
+ int index1 = thisStart;
+ int index2 = start;
+ int tmpLen = length;
+
+ // Extract these first so we detect NPEs the same as the java.lang.String version
+ final int srcLen = cs.length() - thisStart;
+ final int otherLen = substring.length() - start;
+
+ // Check for invalid parameters
+ if (thisStart < 0 || start < 0 || length < 0) {
+ return false;
+ }
+
+ // Check that the regions are long enough
+ if (srcLen < length || otherLen < length) {
+ return false;
+ }
+
+ while (tmpLen-- > 0) {
+ final char c1 = cs.charAt(index1++);
+ final char c2 = substring.charAt(index2++);
+
+ if (c1 == c2) {
+ continue;
+ }
+
+ if (!ignoreCase) {
+ return false;
+ }
+
+ // The same check as in String.regionMatches():
+ if (Character.toUpperCase(c1) != Character.toUpperCase(c2)
+ && Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSet.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSet.java
new file mode 100644
index 000000000..cf3244c40
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSet.java
@@ -0,0 +1,295 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A set of characters.
+ *
+ * Instances are immutable, but instances of subclasses may not be.
+ *
+ * #ThreadSafe#
+ * @since 1.0
+ */
+public class CharSet implements Serializable {
+
+ /**
+ * Required for serialization support. Lang version 2.0.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 5947847346149275958L;
+
+ /**
+ * A CharSet defining no characters.
+ * @since 2.0
+ */
+ public static final CharSet EMPTY = new CharSet((String) null);
+
+ /**
+ * A CharSet defining ASCII alphabetic characters "a-zA-Z".
+ * @since 2.0
+ */
+ public static final CharSet ASCII_ALPHA = new CharSet("a-zA-Z");
+
+ /**
+ * A CharSet defining ASCII alphabetic characters "a-z".
+ * @since 2.0
+ */
+ public static final CharSet ASCII_ALPHA_LOWER = new CharSet("a-z");
+
+ /**
+ * A CharSet defining ASCII alphabetic characters "A-Z".
+ * @since 2.0
+ */
+ public static final CharSet ASCII_ALPHA_UPPER = new CharSet("A-Z");
+
+ /**
+ * A CharSet defining ASCII alphabetic characters "0-9".
+ * @since 2.0
+ */
+ public static final CharSet ASCII_NUMERIC = new CharSet("0-9");
+
+ /**
+ * A Map of the common cases used in the factory.
+ * Subclasses can add more common patterns if desired
+ * @since 2.0
+ */
+ protected static final Map COMMON = Collections.synchronizedMap(new HashMap());
+
+ static {
+ COMMON.put(null, EMPTY);
+ COMMON.put(StringUtils.EMPTY, EMPTY);
+ COMMON.put("a-zA-Z", ASCII_ALPHA);
+ COMMON.put("A-Za-z", ASCII_ALPHA);
+ COMMON.put("a-z", ASCII_ALPHA_LOWER);
+ COMMON.put("A-Z", ASCII_ALPHA_UPPER);
+ COMMON.put("0-9", ASCII_NUMERIC);
+ }
+
+ /** The set of CharRange objects. */
+ private final Set set = Collections.synchronizedSet(new HashSet());
+
+ //-----------------------------------------------------------------------
+ /**
+ * Factory method to create a new CharSet using a special syntax.
+ *
+ *
+ * {@code null} or empty string ("")
+ * - set containing no characters
+ * Single character, such as "a"
+ * - set containing just that character
+ * Multi character, such as "a-e"
+ * - set containing characters from one character to the other
+ * Negated, such as "^a" or "^a-e"
+ * - set containing all characters except those defined
+ * Combinations, such as "abe-g"
+ * - set containing all the characters from the individual sets
+ *
+ *
+ * The matching order is:
+ *
+ * Negated multi character range, such as "^a-e"
+ * Ordinary multi character range, such as "a-e"
+ * Negated single character, such as "^a"
+ * Ordinary single character, such as "a"
+ *
+ *
+ * Matching works left to right. Once a match is found the
+ * search starts again from the next character.
+ *
+ * If the same range is defined twice using the same syntax, only
+ * one range will be kept.
+ * Thus, "a-ca-c" creates only one range of "a-c".
+ *
+ * If the start and end of a range are in the wrong order,
+ * they are reversed. Thus "a-e" is the same as "e-a".
+ * As a result, "a-ee-a" would create only one range,
+ * as the "a-e" and "e-a" are the same.
+ *
+ * The set of characters represented is the union of the specified ranges.
+ *
+ * There are two ways to add a literal negation character ({@code ^}):
+ *
+ * As the last character in a string, e.g. {@code CharSet.getInstance("a-z^")}
+ * As a separate element, e.g. {@code CharSet.getInstance("^","a-z")}
+ *
+ *
+ * Examples using the negation character:
+ *
+ * CharSet.getInstance("^a-c").contains('a') = false
+ * CharSet.getInstance("^a-c").contains('d') = true
+ * CharSet.getInstance("^^a-c").contains('a') = true // (only '^' is negated)
+ * CharSet.getInstance("^^a-c").contains('^') = false
+ * CharSet.getInstance("^a-cd-f").contains('d') = true
+ * CharSet.getInstance("a-c^").contains('^') = true
+ * CharSet.getInstance("^", "a-c").contains('^') = true
+ *
+ *
+ * All CharSet objects returned by this method will be immutable.
+ *
+ * @param setStrs Strings to merge into the set, may be null
+ * @return a CharSet instance
+ * @since 2.4
+ */
+ public static CharSet getInstance(final String... setStrs) {
+ if (setStrs == null) {
+ return null;
+ }
+ if (setStrs.length == 1) {
+ final CharSet common = COMMON.get(setStrs[0]);
+ if (common != null) {
+ return common;
+ }
+ }
+ return new CharSet(setStrs);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Constructs a new CharSet using the set syntax.
+ * Each string is merged in with the set.
+ *
+ * @param set Strings to merge into the initial set
+ * @throws NullPointerException if set is {@code null}
+ */
+ protected CharSet(final String... set) {
+ super();
+ final int sz = set.length;
+ for (int i = 0; i < sz; i++) {
+ add(set[i]);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Add a set definition string to the {@code CharSet}.
+ *
+ * @param str set definition string
+ */
+ protected void add(final String str) {
+ if (str == null) {
+ return;
+ }
+
+ final int len = str.length();
+ int pos = 0;
+ while (pos < len) {
+ final int remainder = len - pos;
+ if (remainder >= 4 && str.charAt(pos) == '^' && str.charAt(pos + 2) == '-') {
+ // negated range
+ set.add(CharRange.isNotIn(str.charAt(pos + 1), str.charAt(pos + 3)));
+ pos += 4;
+ } else if (remainder >= 3 && str.charAt(pos + 1) == '-') {
+ // range
+ set.add(CharRange.isIn(str.charAt(pos), str.charAt(pos + 2)));
+ pos += 3;
+ } else if (remainder >= 2 && str.charAt(pos) == '^') {
+ // negated char
+ set.add(CharRange.isNot(str.charAt(pos + 1)));
+ pos += 2;
+ } else {
+ // char
+ set.add(CharRange.is(str.charAt(pos)));
+ pos += 1;
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the internal set as an array of CharRange objects.
+ *
+ * @return an array of immutable CharRange objects
+ * @since 2.0
+ */
+// NOTE: This is no longer public as CharRange is no longer a public class.
+// It may be replaced when CharSet moves to Range.
+ /*public*/ CharRange[] getCharRanges() {
+ return set.toArray(new CharRange[set.size()]);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Does the {@code CharSet} contain the specified
+ * character {@code ch}.
+ *
+ * @param ch the character to check for
+ * @return {@code true} if the set contains the characters
+ */
+ public boolean contains(final char ch) {
+ for (final CharRange range : set) {
+ if (range.contains(ch)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Basics
+ //-----------------------------------------------------------------------
+ /**
+ * Compares two {@code CharSet} objects, returning true if they represent
+ * exactly the same set of characters defined in the same way.
+ *
+ * The two sets {@code abc} and {@code a-c} are not
+ * equal according to this method.
+ *
+ * @param obj the object to compare to
+ * @return true if equal
+ * @since 2.0
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof CharSet == false) {
+ return false;
+ }
+ final CharSet other = (CharSet) obj;
+ return set.equals(other.set);
+ }
+
+ /**
+ * Gets a hash code compatible with the equals method.
+ *
+ * @return a suitable hash code
+ * @since 2.0
+ */
+ @Override
+ public int hashCode() {
+ return 89 + set.hashCode();
+ }
+
+ /**
+ * Gets a string representation of the set.
+ *
+ * @return string representation of the set
+ */
+ @Override
+ public String toString() {
+ return set.toString();
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSetUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSetUtils.java
new file mode 100644
index 000000000..6284e3811
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/CharSetUtils.java
@@ -0,0 +1,263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+/**
+ * Operations on {@code CharSet} instances.
+ *
+ * This class handles {@code null} input gracefully.
+ * An exception will not be thrown for a {@code null} input.
+ * Each method documents its behaviour in more detail.
+ *
+ * #ThreadSafe#
+ * @see CharSet
+ * @since 1.0
+ */
+public class CharSetUtils {
+
+ /**
+ * CharSetUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as {@code CharSetUtils.evaluateSet(null);}.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public CharSetUtils() {
+ super();
+ }
+
+ // Squeeze
+ //-----------------------------------------------------------------------
+ /**
+ * Squeezes any repetitions of a character that is mentioned in the
+ * supplied set.
+ *
+ *
+ * CharSetUtils.squeeze(null, *) = null
+ * CharSetUtils.squeeze("", *) = ""
+ * CharSetUtils.squeeze(*, null) = *
+ * CharSetUtils.squeeze(*, "") = *
+ * CharSetUtils.squeeze("hello", "k-p") = "helo"
+ * CharSetUtils.squeeze("hello", "a-e") = "hello"
+ *
+ *
+ * @see CharSet#getInstance(java.lang.String...) for set-syntax.
+ * @param str the string to squeeze, may be null
+ * @param set the character set to use for manipulation, may be null
+ * @return the modified String, {@code null} if null string input
+ */
+ public static String squeeze(final String str, final String... set) {
+ if (StringUtils.isEmpty(str) || deepEmpty(set)) {
+ return str;
+ }
+ final CharSet chars = CharSet.getInstance(set);
+ final StringBuilder buffer = new StringBuilder(str.length());
+ final char[] chrs = str.toCharArray();
+ final int sz = chrs.length;
+ char lastChar = chrs[0];
+ char ch = ' ';
+ Character inChars = null;
+ Character notInChars = null;
+ buffer.append(lastChar);
+ for (int i = 1; i < sz; i++) {
+ ch = chrs[i];
+ if (ch == lastChar) {
+ if (inChars != null && ch == inChars) {
+ continue;
+ } else {
+ if (notInChars == null || ch != notInChars) {
+ if (chars.contains(ch)) {
+ inChars = ch;
+ continue;
+ } else {
+ notInChars = ch;
+ }
+ }
+ }
+ }
+ buffer.append(ch);
+ lastChar = ch;
+ }
+ return buffer.toString();
+ }
+
+ // ContainsAny
+ //-----------------------------------------------------------------------
+ /**
+ * Takes an argument in set-syntax, see evaluateSet,
+ * and identifies whether any of the characters are present in the specified string.
+ *
+ *
+ * CharSetUtils.containsAny(null, *) = false
+ * CharSetUtils.containsAny("", *) = false
+ * CharSetUtils.containsAny(*, null) = false
+ * CharSetUtils.containsAny(*, "") = false
+ * CharSetUtils.containsAny("hello", "k-p") = true
+ * CharSetUtils.containsAny("hello", "a-d") = false
+ *
+ *
+ * @see CharSet#getInstance(java.lang.String...) for set-syntax.
+ * @param str String to look for characters in, may be null
+ * @param set String[] set of characters to identify, may be null
+ * @return whether or not the characters in the set are in the primary string
+ * @since 3.2
+ */
+ public static boolean containsAny(final String str, final String... set) {
+ if (StringUtils.isEmpty(str) || deepEmpty(set)) {
+ return false;
+ }
+ final CharSet chars = CharSet.getInstance(set);
+ for (final char c : str.toCharArray()) {
+ if (chars.contains(c)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Count
+ //-----------------------------------------------------------------------
+ /**
+ * Takes an argument in set-syntax, see evaluateSet,
+ * and returns the number of characters present in the specified string.
+ *
+ *
+ * CharSetUtils.count(null, *) = 0
+ * CharSetUtils.count("", *) = 0
+ * CharSetUtils.count(*, null) = 0
+ * CharSetUtils.count(*, "") = 0
+ * CharSetUtils.count("hello", "k-p") = 3
+ * CharSetUtils.count("hello", "a-e") = 1
+ *
+ *
+ * @see CharSet#getInstance(java.lang.String...) for set-syntax.
+ * @param str String to count characters in, may be null
+ * @param set String[] set of characters to count, may be null
+ * @return the character count, zero if null string input
+ */
+ public static int count(final String str, final String... set) {
+ if (StringUtils.isEmpty(str) || deepEmpty(set)) {
+ return 0;
+ }
+ final CharSet chars = CharSet.getInstance(set);
+ int count = 0;
+ for (final char c : str.toCharArray()) {
+ if (chars.contains(c)) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ // Keep
+ //-----------------------------------------------------------------------
+ /**
+ * Takes an argument in set-syntax, see evaluateSet,
+ * and keeps any of characters present in the specified string.
+ *
+ *
+ * CharSetUtils.keep(null, *) = null
+ * CharSetUtils.keep("", *) = ""
+ * CharSetUtils.keep(*, null) = ""
+ * CharSetUtils.keep(*, "") = ""
+ * CharSetUtils.keep("hello", "hl") = "hll"
+ * CharSetUtils.keep("hello", "le") = "ell"
+ *
+ *
+ * @see CharSet#getInstance(java.lang.String...) for set-syntax.
+ * @param str String to keep characters from, may be null
+ * @param set String[] set of characters to keep, may be null
+ * @return the modified String, {@code null} if null string input
+ * @since 2.0
+ */
+ public static String keep(final String str, final String... set) {
+ if (str == null) {
+ return null;
+ }
+ if (str.isEmpty() || deepEmpty(set)) {
+ return StringUtils.EMPTY;
+ }
+ return modify(str, set, true);
+ }
+
+ // Delete
+ //-----------------------------------------------------------------------
+ /**
+ * Takes an argument in set-syntax, see evaluateSet,
+ * and deletes any of characters present in the specified string.
+ *
+ *
+ * CharSetUtils.delete(null, *) = null
+ * CharSetUtils.delete("", *) = ""
+ * CharSetUtils.delete(*, null) = *
+ * CharSetUtils.delete(*, "") = *
+ * CharSetUtils.delete("hello", "hl") = "eo"
+ * CharSetUtils.delete("hello", "le") = "ho"
+ *
+ *
+ * @see CharSet#getInstance(java.lang.String...) for set-syntax.
+ * @param str String to delete characters from, may be null
+ * @param set String[] set of characters to delete, may be null
+ * @return the modified String, {@code null} if null string input
+ */
+ public static String delete(final String str, final String... set) {
+ if (StringUtils.isEmpty(str) || deepEmpty(set)) {
+ return str;
+ }
+ return modify(str, set, false);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Implementation of delete and keep
+ *
+ * @param str String to modify characters within
+ * @param set String[] set of characters to modify
+ * @param expect whether to evaluate on match, or non-match
+ * @return the modified String, not null
+ */
+ private static String modify(final String str, final String[] set, final boolean expect) {
+ final CharSet chars = CharSet.getInstance(set);
+ final StringBuilder buffer = new StringBuilder(str.length());
+ final char[] chrs = str.toCharArray();
+ final int sz = chrs.length;
+ for(int i=0; iOperations on char primitives and Character objects.
+ *
+ * This class tries to handle {@code null} input gracefully.
+ * An exception will not be thrown for a {@code null} input.
+ * Each method documents its behaviour in more detail.
+ *
+ * #ThreadSafe#
+ * @since 2.1
+ */
+public class CharUtils {
+
+ private static final String[] CHAR_STRING_ARRAY = new String[128];
+
+ private static final char[] HEX_DIGITS = new char[] {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+
+ /**
+ * {@code \u000a} linefeed LF ('\n').
+ *
+ * @see JLF: Escape Sequences
+ * for Character and String Literals
+ * @since 2.2
+ */
+ public static final char LF = '\n';
+
+ /**
+ * {@code \u000d} carriage return CR ('\r').
+ *
+ * @see JLF: Escape Sequences
+ * for Character and String Literals
+ * @since 2.2
+ */
+ public static final char CR = '\r';
+
+
+ static {
+ for (char c = 0; c < CHAR_STRING_ARRAY.length; c++) {
+ CHAR_STRING_ARRAY[c] = String.valueOf(c);
+ }
+ }
+
+ /**
+ * {@code CharUtils} instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as {@code CharUtils.toString('c');}.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public CharUtils() {
+ super();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts the character to a Character.
+ *
+ * For ASCII 7 bit characters, this uses a cache that will return the
+ * same Character object each time.
+ *
+ *
+ * CharUtils.toCharacterObject(' ') = ' '
+ * CharUtils.toCharacterObject('A') = 'A'
+ *
+ *
+ * @deprecated Java 5 introduced {@link Character#valueOf(char)} which caches chars 0 through 127.
+ * @param ch the character to convert
+ * @return a Character of the specified character
+ */
+ @Deprecated
+ public static Character toCharacterObject(final char ch) {
+ return Character.valueOf(ch);
+ }
+
+ /**
+ * Converts the String to a Character using the first character, returning
+ * null for empty Strings.
+ *
+ * For ASCII 7 bit characters, this uses a cache that will return the
+ * same Character object each time.
+ *
+ *
+ * CharUtils.toCharacterObject(null) = null
+ * CharUtils.toCharacterObject("") = null
+ * CharUtils.toCharacterObject("A") = 'A'
+ * CharUtils.toCharacterObject("BA") = 'B'
+ *
+ *
+ * @param str the character to convert
+ * @return the Character value of the first letter of the String
+ */
+ public static Character toCharacterObject(final String str) {
+ if (StringUtils.isEmpty(str)) {
+ return null;
+ }
+ return Character.valueOf(str.charAt(0));
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts the Character to a char throwing an exception for {@code null}.
+ *
+ *
+ * CharUtils.toChar(' ') = ' '
+ * CharUtils.toChar('A') = 'A'
+ * CharUtils.toChar(null) throws IllegalArgumentException
+ *
+ *
+ * @param ch the character to convert
+ * @return the char value of the Character
+ * @throws IllegalArgumentException if the Character is null
+ */
+ public static char toChar(final Character ch) {
+ if (ch == null) {
+ throw new IllegalArgumentException("The Character must not be null");
+ }
+ return ch.charValue();
+ }
+
+ /**
+ * Converts the Character to a char handling {@code null}.
+ *
+ *
+ * CharUtils.toChar(null, 'X') = 'X'
+ * CharUtils.toChar(' ', 'X') = ' '
+ * CharUtils.toChar('A', 'X') = 'A'
+ *
+ *
+ * @param ch the character to convert
+ * @param defaultValue the value to use if the Character is null
+ * @return the char value of the Character or the default if null
+ */
+ public static char toChar(final Character ch, final char defaultValue) {
+ if (ch == null) {
+ return defaultValue;
+ }
+ return ch.charValue();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts the String to a char using the first character, throwing
+ * an exception on empty Strings.
+ *
+ *
+ * CharUtils.toChar("A") = 'A'
+ * CharUtils.toChar("BA") = 'B'
+ * CharUtils.toChar(null) throws IllegalArgumentException
+ * CharUtils.toChar("") throws IllegalArgumentException
+ *
+ *
+ * @param str the character to convert
+ * @return the char value of the first letter of the String
+ * @throws IllegalArgumentException if the String is empty
+ */
+ public static char toChar(final String str) {
+ if (StringUtils.isEmpty(str)) {
+ throw new IllegalArgumentException("The String must not be empty");
+ }
+ return str.charAt(0);
+ }
+
+ /**
+ * Converts the String to a char using the first character, defaulting
+ * the value on empty Strings.
+ *
+ *
+ * CharUtils.toChar(null, 'X') = 'X'
+ * CharUtils.toChar("", 'X') = 'X'
+ * CharUtils.toChar("A", 'X') = 'A'
+ * CharUtils.toChar("BA", 'X') = 'B'
+ *
+ *
+ * @param str the character to convert
+ * @param defaultValue the value to use if the Character is null
+ * @return the char value of the first letter of the String or the default if null
+ */
+ public static char toChar(final String str, final char defaultValue) {
+ if (StringUtils.isEmpty(str)) {
+ return defaultValue;
+ }
+ return str.charAt(0);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts the character to the Integer it represents, throwing an
+ * exception if the character is not numeric.
+ *
+ * This method coverts the char '1' to the int 1 and so on.
+ *
+ *
+ * CharUtils.toIntValue('3') = 3
+ * CharUtils.toIntValue('A') throws IllegalArgumentException
+ *
+ *
+ * @param ch the character to convert
+ * @return the int value of the character
+ * @throws IllegalArgumentException if the character is not ASCII numeric
+ */
+ public static int toIntValue(final char ch) {
+ if (isAsciiNumeric(ch) == false) {
+ throw new IllegalArgumentException("The character " + ch + " is not in the range '0' - '9'");
+ }
+ return ch - 48;
+ }
+
+ /**
+ * Converts the character to the Integer it represents, throwing an
+ * exception if the character is not numeric.
+ *
+ * This method coverts the char '1' to the int 1 and so on.
+ *
+ *
+ * CharUtils.toIntValue('3', -1) = 3
+ * CharUtils.toIntValue('A', -1) = -1
+ *
+ *
+ * @param ch the character to convert
+ * @param defaultValue the default value to use if the character is not numeric
+ * @return the int value of the character
+ */
+ public static int toIntValue(final char ch, final int defaultValue) {
+ if (isAsciiNumeric(ch) == false) {
+ return defaultValue;
+ }
+ return ch - 48;
+ }
+
+ /**
+ * Converts the character to the Integer it represents, throwing an
+ * exception if the character is not numeric.
+ *
+ * This method coverts the char '1' to the int 1 and so on.
+ *
+ *
+ * CharUtils.toIntValue('3') = 3
+ * CharUtils.toIntValue(null) throws IllegalArgumentException
+ * CharUtils.toIntValue('A') throws IllegalArgumentException
+ *
+ *
+ * @param ch the character to convert, not null
+ * @return the int value of the character
+ * @throws IllegalArgumentException if the Character is not ASCII numeric or is null
+ */
+ public static int toIntValue(final Character ch) {
+ if (ch == null) {
+ throw new IllegalArgumentException("The character must not be null");
+ }
+ return toIntValue(ch.charValue());
+ }
+
+ /**
+ * Converts the character to the Integer it represents, throwing an
+ * exception if the character is not numeric.
+ *
+ * This method coverts the char '1' to the int 1 and so on.
+ *
+ *
+ * CharUtils.toIntValue(null, -1) = -1
+ * CharUtils.toIntValue('3', -1) = 3
+ * CharUtils.toIntValue('A', -1) = -1
+ *
+ *
+ * @param ch the character to convert
+ * @param defaultValue the default value to use if the character is not numeric
+ * @return the int value of the character
+ */
+ public static int toIntValue(final Character ch, final int defaultValue) {
+ if (ch == null) {
+ return defaultValue;
+ }
+ return toIntValue(ch.charValue(), defaultValue);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts the character to a String that contains the one character.
+ *
+ * For ASCII 7 bit characters, this uses a cache that will return the
+ * same String object each time.
+ *
+ *
+ * CharUtils.toString(' ') = " "
+ * CharUtils.toString('A') = "A"
+ *
+ *
+ * @param ch the character to convert
+ * @return a String containing the one specified character
+ */
+ public static String toString(final char ch) {
+ if (ch < 128) {
+ return CHAR_STRING_ARRAY[ch];
+ }
+ return new String(new char[] {ch});
+ }
+
+ /**
+ * Converts the character to a String that contains the one character.
+ *
+ * For ASCII 7 bit characters, this uses a cache that will return the
+ * same String object each time.
+ *
+ * If {@code null} is passed in, {@code null} will be returned.
+ *
+ *
+ * CharUtils.toString(null) = null
+ * CharUtils.toString(' ') = " "
+ * CharUtils.toString('A') = "A"
+ *
+ *
+ * @param ch the character to convert
+ * @return a String containing the one specified character
+ */
+ public static String toString(final Character ch) {
+ if (ch == null) {
+ return null;
+ }
+ return toString(ch.charValue());
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ * Converts the string to the Unicode format '\u0020'.
+ *
+ * This format is the Java source code format.
+ *
+ *
+ * CharUtils.unicodeEscaped(' ') = "\u0020"
+ * CharUtils.unicodeEscaped('A') = "\u0041"
+ *
+ *
+ * @param ch the character to convert
+ * @return the escaped Unicode string
+ */
+ public static String unicodeEscaped(final char ch) {
+ StringBuilder sb = new StringBuilder(6);
+ sb.append("\\u");
+ sb.append(HEX_DIGITS[(ch >> 12) & 15]);
+ sb.append(HEX_DIGITS[(ch >> 8) & 15]);
+ sb.append(HEX_DIGITS[(ch >> 4) & 15]);
+ sb.append(HEX_DIGITS[(ch) & 15]);
+ return sb.toString();
+ }
+
+ /**
+ * Converts the string to the Unicode format '\u0020'.
+ *
+ * This format is the Java source code format.
+ *
+ * If {@code null} is passed in, {@code null} will be returned.
+ *
+ *
+ * CharUtils.unicodeEscaped(null) = null
+ * CharUtils.unicodeEscaped(' ') = "\u0020"
+ * CharUtils.unicodeEscaped('A') = "\u0041"
+ *
+ *
+ * @param ch the character to convert, may be null
+ * @return the escaped Unicode string, null if null input
+ */
+ public static String unicodeEscaped(final Character ch) {
+ if (ch == null) {
+ return null;
+ }
+ return unicodeEscaped(ch.charValue());
+ }
+
+ //--------------------------------------------------------------------------
+ /**
+ * Checks whether the character is ASCII 7 bit.
+ *
+ *
+ * CharUtils.isAscii('a') = true
+ * CharUtils.isAscii('A') = true
+ * CharUtils.isAscii('3') = true
+ * CharUtils.isAscii('-') = true
+ * CharUtils.isAscii('\n') = true
+ * CharUtils.isAscii('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if less than 128
+ */
+ public static boolean isAscii(final char ch) {
+ return ch < 128;
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit printable.
+ *
+ *
+ * CharUtils.isAsciiPrintable('a') = true
+ * CharUtils.isAsciiPrintable('A') = true
+ * CharUtils.isAsciiPrintable('3') = true
+ * CharUtils.isAsciiPrintable('-') = true
+ * CharUtils.isAsciiPrintable('\n') = false
+ * CharUtils.isAsciiPrintable('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 32 and 126 inclusive
+ */
+ public static boolean isAsciiPrintable(final char ch) {
+ return ch >= 32 && ch < 127;
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit control.
+ *
+ *
+ * CharUtils.isAsciiControl('a') = false
+ * CharUtils.isAsciiControl('A') = false
+ * CharUtils.isAsciiControl('3') = false
+ * CharUtils.isAsciiControl('-') = false
+ * CharUtils.isAsciiControl('\n') = true
+ * CharUtils.isAsciiControl('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if less than 32 or equals 127
+ */
+ public static boolean isAsciiControl(final char ch) {
+ return ch < 32 || ch == 127;
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit alphabetic.
+ *
+ *
+ * CharUtils.isAsciiAlpha('a') = true
+ * CharUtils.isAsciiAlpha('A') = true
+ * CharUtils.isAsciiAlpha('3') = false
+ * CharUtils.isAsciiAlpha('-') = false
+ * CharUtils.isAsciiAlpha('\n') = false
+ * CharUtils.isAsciiAlpha('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 65 and 90 or 97 and 122 inclusive
+ */
+ public static boolean isAsciiAlpha(final char ch) {
+ return isAsciiAlphaUpper(ch) || isAsciiAlphaLower(ch);
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit alphabetic upper case.
+ *
+ *
+ * CharUtils.isAsciiAlphaUpper('a') = false
+ * CharUtils.isAsciiAlphaUpper('A') = true
+ * CharUtils.isAsciiAlphaUpper('3') = false
+ * CharUtils.isAsciiAlphaUpper('-') = false
+ * CharUtils.isAsciiAlphaUpper('\n') = false
+ * CharUtils.isAsciiAlphaUpper('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 65 and 90 inclusive
+ */
+ public static boolean isAsciiAlphaUpper(final char ch) {
+ return ch >= 'A' && ch <= 'Z';
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit alphabetic lower case.
+ *
+ *
+ * CharUtils.isAsciiAlphaLower('a') = true
+ * CharUtils.isAsciiAlphaLower('A') = false
+ * CharUtils.isAsciiAlphaLower('3') = false
+ * CharUtils.isAsciiAlphaLower('-') = false
+ * CharUtils.isAsciiAlphaLower('\n') = false
+ * CharUtils.isAsciiAlphaLower('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 97 and 122 inclusive
+ */
+ public static boolean isAsciiAlphaLower(final char ch) {
+ return ch >= 'a' && ch <= 'z';
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit numeric.
+ *
+ *
+ * CharUtils.isAsciiNumeric('a') = false
+ * CharUtils.isAsciiNumeric('A') = false
+ * CharUtils.isAsciiNumeric('3') = true
+ * CharUtils.isAsciiNumeric('-') = false
+ * CharUtils.isAsciiNumeric('\n') = false
+ * CharUtils.isAsciiNumeric('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 48 and 57 inclusive
+ */
+ public static boolean isAsciiNumeric(final char ch) {
+ return ch >= '0' && ch <= '9';
+ }
+
+ /**
+ * Checks whether the character is ASCII 7 bit numeric.
+ *
+ *
+ * CharUtils.isAsciiAlphanumeric('a') = true
+ * CharUtils.isAsciiAlphanumeric('A') = true
+ * CharUtils.isAsciiAlphanumeric('3') = true
+ * CharUtils.isAsciiAlphanumeric('-') = false
+ * CharUtils.isAsciiAlphanumeric('\n') = false
+ * CharUtils.isAsciiAlphanumeric('©') = false
+ *
+ *
+ * @param ch the character to check
+ * @return true if between 48 and 57 or 65 and 90 or 97 and 122 inclusive
+ */
+ public static boolean isAsciiAlphanumeric(final char ch) {
+ return isAsciiAlpha(ch) || isAsciiNumeric(ch);
+ }
+
+ /**
+ * Compares two {@code char} values numerically. This is the same functionality as provided in Java 7.
+ *
+ * @param x the first {@code char} to compare
+ * @param y the second {@code char} to compare
+ * @return the value {@code 0} if {@code x == y};
+ * a value less than {@code 0} if {@code x < y}; and
+ * a value greater than {@code 0} if {@code x > y}
+ * @since 3.4
+ */
+ public static int compare(char x, char y) {
+ return x-y;
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ClassPathUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ClassPathUtils.java
new file mode 100644
index 000000000..df3773a34
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ClassPathUtils.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+/**
+ * Operations regarding the classpath.
+ *
+ * The methods of this class do not allow {@code null} inputs.
+ *
+ * @since 3.3
+ */
+//@Immutable
+public class ClassPathUtils {
+
+ /**
+ * {@code ClassPathUtils} instances should NOT be constructed in
+ * standard programming. Instead, the class should be used as
+ * {@code ClassPathUtils.toFullyQualifiedName(MyClass.class, "MyClass.properties");}.
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public ClassPathUtils() {
+ super();
+ }
+
+ /**
+ * Returns the fully qualified name for the resource with name {@code resourceName} relative to the given context.
+ *
+ * Note that this method does not check whether the resource actually exists.
+ * It only constructs the name.
+ * Null inputs are not allowed.
+ *
+ *
+ * ClassPathUtils.toFullyQualifiedName(StringUtils.class, "StringUtils.properties") = "org.apache.commons.lang3.StringUtils.properties"
+ *
+ *
+ * @param context The context for constructing the name.
+ * @param resourceName the resource name to construct the fully qualified name for.
+ * @return the fully qualified name of the resource with name {@code resourceName}.
+ * @throws java.lang.NullPointerException if either {@code context} or {@code resourceName} is null.
+ */
+ public static String toFullyQualifiedName(final Class> context, final String resourceName) {
+ Validate.notNull(context, "Parameter '%s' must not be null!", "context" );
+ Validate.notNull(resourceName, "Parameter '%s' must not be null!", "resourceName");
+ return toFullyQualifiedName(context.getPackage(), resourceName);
+ }
+
+ /**
+ * Returns the fully qualified name for the resource with name {@code resourceName} relative to the given context.
+ *
+ * Note that this method does not check whether the resource actually exists.
+ * It only constructs the name.
+ * Null inputs are not allowed.
+ *
+ *
+ * ClassPathUtils.toFullyQualifiedName(StringUtils.class.getPackage(), "StringUtils.properties") = "org.apache.commons.lang3.StringUtils.properties"
+ *
+ *
+ * @param context The context for constructing the name.
+ * @param resourceName the resource name to construct the fully qualified name for.
+ * @return the fully qualified name of the resource with name {@code resourceName}.
+ * @throws java.lang.NullPointerException if either {@code context} or {@code resourceName} is null.
+ */
+ public static String toFullyQualifiedName(final Package context, final String resourceName) {
+ Validate.notNull(context, "Parameter '%s' must not be null!", "context" );
+ Validate.notNull(resourceName, "Parameter '%s' must not be null!", "resourceName");
+ return context.getName() + "." + resourceName;
+ }
+
+ /**
+ * Returns the fully qualified path for the resource with name {@code resourceName} relative to the given context.
+ *
+ * Note that this method does not check whether the resource actually exists.
+ * It only constructs the path.
+ * Null inputs are not allowed.
+ *
+ *
+ * ClassPathUtils.toFullyQualifiedPath(StringUtils.class, "StringUtils.properties") = "org/apache/commons/lang3/StringUtils.properties"
+ *
+ *
+ * @param context The context for constructing the path.
+ * @param resourceName the resource name to construct the fully qualified path for.
+ * @return the fully qualified path of the resource with name {@code resourceName}.
+ * @throws java.lang.NullPointerException if either {@code context} or {@code resourceName} is null.
+ */
+ public static String toFullyQualifiedPath(final Class> context, final String resourceName) {
+ Validate.notNull(context, "Parameter '%s' must not be null!", "context" );
+ Validate.notNull(resourceName, "Parameter '%s' must not be null!", "resourceName");
+ return toFullyQualifiedPath(context.getPackage(), resourceName);
+ }
+
+
+ /**
+ * Returns the fully qualified path for the resource with name {@code resourceName} relative to the given context.
+ *
+ * Note that this method does not check whether the resource actually exists.
+ * It only constructs the path.
+ * Null inputs are not allowed.
+ *
+ *
+ * ClassPathUtils.toFullyQualifiedPath(StringUtils.class.getPackage(), "StringUtils.properties") = "org/apache/commons/lang3/StringUtils.properties"
+ *
+ *
+ * @param context The context for constructing the path.
+ * @param resourceName the resource name to construct the fully qualified path for.
+ * @return the fully qualified path of the resource with name {@code resourceName}.
+ * @throws java.lang.NullPointerException if either {@code context} or {@code resourceName} is null.
+ */
+ public static String toFullyQualifiedPath(final Package context, final String resourceName) {
+ Validate.notNull(context, "Parameter '%s' must not be null!", "context" );
+ Validate.notNull(resourceName, "Parameter '%s' must not be null!", "resourceName");
+ return context.getName().replace('.', '/') + "/" + resourceName;
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ClassUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ClassUtils.java
new file mode 100644
index 000000000..da2a7b2a3
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ClassUtils.java
@@ -0,0 +1,1334 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.mutable.MutableObject;
+
+/**
+ * Operates on classes without using reflection.
+ *
+ * This class handles invalid {@code null} inputs as best it can.
+ * Each method documents its behaviour in more detail.
+ *
+ * The notion of a {@code canonical name} includes the human
+ * readable name for the type, for example {@code int[]}. The
+ * non-canonical method variants work with the JVM names, such as
+ * {@code [I}.
+ *
+ * @since 2.0
+ */
+public class ClassUtils {
+ /**
+ * Inclusivity literals for {@link #hierarchy(Class, Interfaces)}.
+ * @since 3.2
+ */
+ public enum Interfaces {
+ INCLUDE, EXCLUDE
+ }
+
+ /**
+ * The package separator character: '.' == {@value}
.
+ */
+ public static final char PACKAGE_SEPARATOR_CHAR = '.';
+
+ /**
+ * The package separator String: "."
.
+ */
+ public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
+
+ /**
+ * The inner class separator character: '$' == {@value}
.
+ */
+ public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
+
+ /**
+ * The inner class separator String: {@code "$"}.
+ */
+ public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
+
+ /**
+ * Maps names of primitives to their corresponding primitive {@code Class}es.
+ */
+ private static final Map> namePrimitiveMap = new HashMap>();
+ static {
+ namePrimitiveMap.put("boolean", Boolean.TYPE);
+ namePrimitiveMap.put("byte", Byte.TYPE);
+ namePrimitiveMap.put("char", Character.TYPE);
+ namePrimitiveMap.put("short", Short.TYPE);
+ namePrimitiveMap.put("int", Integer.TYPE);
+ namePrimitiveMap.put("long", Long.TYPE);
+ namePrimitiveMap.put("double", Double.TYPE);
+ namePrimitiveMap.put("float", Float.TYPE);
+ namePrimitiveMap.put("void", Void.TYPE);
+ }
+
+ /**
+ * Maps primitive {@code Class}es to their corresponding wrapper {@code Class}.
+ */
+ private static final Map, Class>> primitiveWrapperMap = new HashMap, Class>>();
+ static {
+ primitiveWrapperMap.put(Boolean.TYPE, Boolean.class);
+ primitiveWrapperMap.put(Byte.TYPE, Byte.class);
+ primitiveWrapperMap.put(Character.TYPE, Character.class);
+ primitiveWrapperMap.put(Short.TYPE, Short.class);
+ primitiveWrapperMap.put(Integer.TYPE, Integer.class);
+ primitiveWrapperMap.put(Long.TYPE, Long.class);
+ primitiveWrapperMap.put(Double.TYPE, Double.class);
+ primitiveWrapperMap.put(Float.TYPE, Float.class);
+ primitiveWrapperMap.put(Void.TYPE, Void.TYPE);
+ }
+
+ /**
+ * Maps wrapper {@code Class}es to their corresponding primitive types.
+ */
+ private static final Map, Class>> wrapperPrimitiveMap = new HashMap, Class>>();
+ static {
+ for (final Map.Entry, Class>> entry : primitiveWrapperMap.entrySet()) {
+ final Class> primitiveClass = entry.getKey();
+ final Class> wrapperClass = entry.getValue();
+ if (!primitiveClass.equals(wrapperClass)) {
+ wrapperPrimitiveMap.put(wrapperClass, primitiveClass);
+ }
+ }
+ }
+
+ /**
+ * Maps a primitive class name to its corresponding abbreviation used in array class names.
+ */
+ private static final Map abbreviationMap;
+
+ /**
+ * Maps an abbreviation used in array class names to corresponding primitive class name.
+ */
+ private static final Map reverseAbbreviationMap;
+
+ /**
+ * Feed abbreviation maps
+ */
+ static {
+ final Map m = new HashMap();
+ m.put("int", "I");
+ m.put("boolean", "Z");
+ m.put("float", "F");
+ m.put("long", "J");
+ m.put("short", "S");
+ m.put("byte", "B");
+ m.put("double", "D");
+ m.put("char", "C");
+ final Map r = new HashMap();
+ for (final Map.Entry e : m.entrySet()) {
+ r.put(e.getValue(), e.getKey());
+ }
+ abbreviationMap = Collections.unmodifiableMap(m);
+ reverseAbbreviationMap = Collections.unmodifiableMap(r);
+ }
+
+ /**
+ * ClassUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as
+ * {@code ClassUtils.getShortClassName(cls)}.
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public ClassUtils() {
+ super();
+ }
+
+ // Short class name
+ // ----------------------------------------------------------------------
+ /**
+ * Gets the class name minus the package name for an {@code Object}.
+ *
+ * @param object the class to get the short name for, may be null
+ * @param valueIfNull the value to return if null
+ * @return the class name of the object without the package name, or the null value
+ */
+ public static String getShortClassName(final Object object, final String valueIfNull) {
+ if (object == null) {
+ return valueIfNull;
+ }
+ return getShortClassName(object.getClass());
+ }
+
+ /**
+ * Gets the class name minus the package name from a {@code Class}.
+ *
+ * Consider using the Java 5 API {@link Class#getSimpleName()} instead.
+ * The one known difference is that this code will return {@code "Map.Entry"} while
+ * the {@code java.lang.Class} variant will simply return {@code "Entry"}.
+ *
+ * @param cls the class to get the short name for.
+ * @return the class name without the package name or an empty string
+ */
+ public static String getShortClassName(final Class> cls) {
+ if (cls == null) {
+ return StringUtils.EMPTY;
+ }
+ return getShortClassName(cls.getName());
+ }
+
+ /**
+ * Gets the class name minus the package name from a String.
+ *
+ * The string passed in is assumed to be a class name - it is not checked.
+
+ * Note that this method differs from Class.getSimpleName() in that this will
+ * return {@code "Map.Entry"} whilst the {@code java.lang.Class} variant will simply
+ * return {@code "Entry"}.
+ *
+ * @param className the className to get the short name for
+ * @return the class name of the class without the package name or an empty string
+ */
+ public static String getShortClassName(String className) {
+ if (StringUtils.isEmpty(className)) {
+ return StringUtils.EMPTY;
+ }
+
+ final StringBuilder arrayPrefix = new StringBuilder();
+
+ // Handle array encoding
+ if (className.startsWith("[")) {
+ while (className.charAt(0) == '[') {
+ className = className.substring(1);
+ arrayPrefix.append("[]");
+ }
+ // Strip Object type encoding
+ if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
+ className = className.substring(1, className.length() - 1);
+ }
+
+ if (reverseAbbreviationMap.containsKey(className)) {
+ className = reverseAbbreviationMap.get(className);
+ }
+ }
+
+ final int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
+ final int innerIdx = className.indexOf(
+ INNER_CLASS_SEPARATOR_CHAR, lastDotIdx == -1 ? 0 : lastDotIdx + 1);
+ String out = className.substring(lastDotIdx + 1);
+ if (innerIdx != -1) {
+ out = out.replace(INNER_CLASS_SEPARATOR_CHAR, PACKAGE_SEPARATOR_CHAR);
+ }
+ return out + arrayPrefix;
+ }
+
+ /**
+ * Null-safe version of aClass.getSimpleName()
+ *
+ * @param cls the class for which to get the simple name.
+ * @return the simple class name.
+ * @since 3.0
+ * @see Class#getSimpleName()
+ */
+ public static String getSimpleName(final Class> cls) {
+ if (cls == null) {
+ return StringUtils.EMPTY;
+ }
+ return cls.getSimpleName();
+ }
+
+ /**
+ * Null-safe version of aClass.getSimpleName()
+ *
+ * @param object the object for which to get the simple class name.
+ * @param valueIfNull the value to return if object
is null
+ * @return the simple class name.
+ * @since 3.0
+ * @see Class#getSimpleName()
+ */
+ public static String getSimpleName(final Object object, final String valueIfNull) {
+ if (object == null) {
+ return valueIfNull;
+ }
+ return getSimpleName(object.getClass());
+ }
+
+ // Package name
+ // ----------------------------------------------------------------------
+ /**
+ * Gets the package name of an {@code Object}.
+ *
+ * @param object the class to get the package name for, may be null
+ * @param valueIfNull the value to return if null
+ * @return the package name of the object, or the null value
+ */
+ public static String getPackageName(final Object object, final String valueIfNull) {
+ if (object == null) {
+ return valueIfNull;
+ }
+ return getPackageName(object.getClass());
+ }
+
+ /**
+ * Gets the package name of a {@code Class}.
+ *
+ * @param cls the class to get the package name for, may be {@code null}.
+ * @return the package name or an empty string
+ */
+ public static String getPackageName(final Class> cls) {
+ if (cls == null) {
+ return StringUtils.EMPTY;
+ }
+ return getPackageName(cls.getName());
+ }
+
+ /**
+ * Gets the package name from a {@code String}.
+ *
+ * The string passed in is assumed to be a class name - it is not checked.
+ * If the class is unpackaged, return an empty string.
+ *
+ * @param className the className to get the package name for, may be {@code null}
+ * @return the package name or an empty string
+ */
+ public static String getPackageName(String className) {
+ if (StringUtils.isEmpty(className)) {
+ return StringUtils.EMPTY;
+ }
+
+ // Strip array encoding
+ while (className.charAt(0) == '[') {
+ className = className.substring(1);
+ }
+ // Strip Object type encoding
+ if (className.charAt(0) == 'L' && className.charAt(className.length() - 1) == ';') {
+ className = className.substring(1);
+ }
+
+ final int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
+ if (i == -1) {
+ return StringUtils.EMPTY;
+ }
+ return className.substring(0, i);
+ }
+
+ // Abbreviated name
+ // ----------------------------------------------------------------------
+ /**
+ * Gets the abbreviated name of a {@code Class}.
+ *
+ * @param cls the class to get the abbreviated name for, may be {@code null}
+ * @param len the desired length of the abbreviated name
+ * @return the abbreviated name or an empty string
+ * @throws IllegalArgumentException if len <= 0
+ * @see #getAbbreviatedName(String, int)
+ * @since 3.4
+ */
+ public static String getAbbreviatedName(final Class> cls, int len) {
+ if (cls == null) {
+ return StringUtils.EMPTY;
+ }
+ return getAbbreviatedName(cls.getName(), len);
+ }
+
+ /**
+ * Gets the abbreviated class name from a {@code String}.
+ *
+ * The string passed in is assumed to be a class name - it is not checked.
+ *
+ * The abbreviation algorithm will shorten the class name, usually without
+ * significant loss of meaning.
+ * The abbreviated class name will always include the complete package hierarchy.
+ * If enough space is available, rightmost sub-packages will be displayed in full
+ * length.
+ *
+ * The following table illustrates the algorithm:
+ *
+ * className len return
+ * null 1 ""
+ * "java.lang.String" 5 "j.l.String"
+ * "java.lang.String" 15 "j.lang.String"
+ * "java.lang.String" 30 "java.lang.String"
+ *
+ * @param className the className to get the abbreviated name for, may be {@code null}
+ * @param len the desired length of the abbreviated name
+ * @return the abbreviated name or an empty string
+ * @throws IllegalArgumentException if len <= 0
+ * @since 3.4
+ */
+ public static String getAbbreviatedName(String className, int len) {
+ if (len <= 0) {
+ throw new IllegalArgumentException("len must be > 0");
+ }
+ if (className == null) {
+ return StringUtils.EMPTY;
+ }
+
+ int availableSpace = len;
+ int packageLevels = StringUtils.countMatches(className, '.');
+ String[] output = new String[packageLevels + 1];
+ int endIndex = className.length() - 1;
+ for (int level = packageLevels; level >= 0; level--) {
+ int startIndex = className.lastIndexOf('.', endIndex);
+ String part = className.substring(startIndex + 1, endIndex + 1);
+ availableSpace -= part.length();
+ if (level > 0) {
+ // all elements except top level require an additional char space
+ availableSpace--;
+ }
+ if (level == packageLevels) {
+ // ClassName is always complete
+ output[level] = part;
+ } else {
+ if (availableSpace > 0) {
+ output[level] = part;
+ } else {
+ // if no space is left still the first char is used
+ output[level] = part.substring(0, 1);
+ }
+ }
+ endIndex = startIndex - 1;
+ }
+
+ return StringUtils.join(output, '.');
+ }
+
+ // Superclasses/Superinterfaces
+ // ----------------------------------------------------------------------
+ /**
+ * Gets a {@code List} of superclasses for the given class.
+ *
+ * @param cls the class to look up, may be {@code null}
+ * @return the {@code List} of superclasses in order going up from this one
+ * {@code null} if null input
+ */
+ public static List> getAllSuperclasses(final Class> cls) {
+ if (cls == null) {
+ return null;
+ }
+ final List> classes = new ArrayList>();
+ Class> superclass = cls.getSuperclass();
+ while (superclass != null) {
+ classes.add(superclass);
+ superclass = superclass.getSuperclass();
+ }
+ return classes;
+ }
+
+ /**
+ * Gets a {@code List} of all interfaces implemented by the given
+ * class and its superclasses.
+ *
+ * The order is determined by looking through each interface in turn as
+ * declared in the source file and following its hierarchy up. Then each
+ * superclass is considered in the same way. Later duplicates are ignored,
+ * so the order is maintained.
+ *
+ * @param cls the class to look up, may be {@code null}
+ * @return the {@code List} of interfaces in order,
+ * {@code null} if null input
+ */
+ public static List> getAllInterfaces(final Class> cls) {
+ if (cls == null) {
+ return null;
+ }
+
+ final LinkedHashSet> interfacesFound = new LinkedHashSet>();
+ getAllInterfaces(cls, interfacesFound);
+
+ return new ArrayList>(interfacesFound);
+ }
+
+ /**
+ * Get the interfaces for the specified class.
+ *
+ * @param cls the class to look up, may be {@code null}
+ * @param interfacesFound the {@code Set} of interfaces for the class
+ */
+ private static void getAllInterfaces(Class> cls, final HashSet> interfacesFound) {
+ while (cls != null) {
+ final Class>[] interfaces = cls.getInterfaces();
+
+ for (final Class> i : interfaces) {
+ if (interfacesFound.add(i)) {
+ getAllInterfaces(i, interfacesFound);
+ }
+ }
+
+ cls = cls.getSuperclass();
+ }
+ }
+
+ // Convert list
+ // ----------------------------------------------------------------------
+ /**
+ * Given a {@code List} of class names, this method converts them into classes.
+ *
+ * A new {@code List} is returned. If the class name cannot be found, {@code null}
+ * is stored in the {@code List}. If the class name in the {@code List} is
+ * {@code null}, {@code null} is stored in the output {@code List}.
+ *
+ * @param classNames the classNames to change
+ * @return a {@code List} of Class objects corresponding to the class names,
+ * {@code null} if null input
+ * @throws ClassCastException if classNames contains a non String entry
+ */
+ public static List> convertClassNamesToClasses(final List classNames) {
+ if (classNames == null) {
+ return null;
+ }
+ final List> classes = new ArrayList>(classNames.size());
+ for (final String className : classNames) {
+ try {
+ classes.add(Class.forName(className));
+ } catch (final Exception ex) {
+ classes.add(null);
+ }
+ }
+ return classes;
+ }
+
+ /**
+ * Given a {@code List} of {@code Class} objects, this method converts
+ * them into class names.
+ *
+ * A new {@code List} is returned. {@code null} objects will be copied into
+ * the returned list as {@code null}.
+ *
+ * @param classes the classes to change
+ * @return a {@code List} of class names corresponding to the Class objects,
+ * {@code null} if null input
+ * @throws ClassCastException if {@code classes} contains a non-{@code Class} entry
+ */
+ public static List convertClassesToClassNames(final List> classes) {
+ if (classes == null) {
+ return null;
+ }
+ final List classNames = new ArrayList(classes.size());
+ for (final Class> cls : classes) {
+ if (cls == null) {
+ classNames.add(null);
+ } else {
+ classNames.add(cls.getName());
+ }
+ }
+ return classNames;
+ }
+
+ // Is assignable
+ // ----------------------------------------------------------------------
+ /**
+ * Checks if an array of Classes can be assigned to another array of Classes.
+ *
+ * This method calls {@link #isAssignable(Class, Class) isAssignable} for each
+ * Class pair in the input arrays. It can be used to check if a set of arguments
+ * (the first parameter) are suitably compatible with a set of method parameter types
+ * (the second parameter).
+ *
+ * Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
+ * method takes into account widenings of primitive classes and
+ * {@code null}s.
+ *
+ * Primitive widenings allow an int to be assigned to a {@code long},
+ * {@code float} or {@code double}. This method returns the correct
+ * result for these cases.
+ *
+ * {@code Null} may be assigned to any reference type. This method will
+ * return {@code true} if {@code null} is passed in and the toClass is
+ * non-primitive.
+ *
+ * Specifically, this method tests whether the type represented by the
+ * specified {@code Class} parameter can be converted to the type
+ * represented by this {@code Class} object via an identity conversion
+ * widening primitive or widening reference conversion. See
+ * The Java Language Specification ,
+ * sections 5.1.1, 5.1.2 and 5.1.4 for details.
+ *
+ * Since Lang 3.0, this method will default behavior for
+ * calculating assignability between primitive and wrapper types corresponding
+ * to the running Java version ; i.e. autoboxing will be the default
+ * behavior in VMs running Java versions > 1.5.
+ *
+ * @param classArray the array of Classes to check, may be {@code null}
+ * @param toClassArray the array of Classes to try to assign into, may be {@code null}
+ * @return {@code true} if assignment possible
+ */
+ public static boolean isAssignable(final Class>[] classArray, final Class>... toClassArray) {
+ return isAssignable(classArray, toClassArray, SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_5));
+ }
+
+ /**
+ * Checks if an array of Classes can be assigned to another array of Classes.
+ *
+ * This method calls {@link #isAssignable(Class, Class) isAssignable} for each
+ * Class pair in the input arrays. It can be used to check if a set of arguments
+ * (the first parameter) are suitably compatible with a set of method parameter types
+ * (the second parameter).
+ *
+ * Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
+ * method takes into account widenings of primitive classes and
+ * {@code null}s.
+ *
+ * Primitive widenings allow an int to be assigned to a {@code long},
+ * {@code float} or {@code double}. This method returns the correct
+ * result for these cases.
+ *
+ * {@code Null} may be assigned to any reference type. This method will
+ * return {@code true} if {@code null} is passed in and the toClass is
+ * non-primitive.
+ *
+ * Specifically, this method tests whether the type represented by the
+ * specified {@code Class} parameter can be converted to the type
+ * represented by this {@code Class} object via an identity conversion
+ * widening primitive or widening reference conversion. See
+ * The Java Language Specification ,
+ * sections 5.1.1, 5.1.2 and 5.1.4 for details.
+ *
+ * @param classArray the array of Classes to check, may be {@code null}
+ * @param toClassArray the array of Classes to try to assign into, may be {@code null}
+ * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers
+ * @return {@code true} if assignment possible
+ */
+ public static boolean isAssignable(Class>[] classArray, Class>[] toClassArray, final boolean autoboxing) {
+ if (ArrayUtils.isSameLength(classArray, toClassArray) == false) {
+ return false;
+ }
+ if (classArray == null) {
+ classArray = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ if (toClassArray == null) {
+ toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ for (int i = 0; i < classArray.length; i++) {
+ if (isAssignable(classArray[i], toClassArray[i], autoboxing) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the given {@code type} is a primitive or primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character},
+ * {@link Short}, {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
+ *
+ * @param type
+ * The class to query or null.
+ * @return true if the given {@code type} is a primitive or primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character},
+ * {@link Short}, {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
+ * @since 3.1
+ */
+ public static boolean isPrimitiveOrWrapper(final Class> type) {
+ if (type == null) {
+ return false;
+ }
+ return type.isPrimitive() || isPrimitiveWrapper(type);
+ }
+
+ /**
+ * Returns whether the given {@code type} is a primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, {@link Short},
+ * {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
+ *
+ * @param type
+ * The class to query or null.
+ * @return true if the given {@code type} is a primitive wrapper ({@link Boolean}, {@link Byte}, {@link Character}, {@link Short},
+ * {@link Integer}, {@link Long}, {@link Double}, {@link Float}).
+ * @since 3.1
+ */
+ public static boolean isPrimitiveWrapper(final Class> type) {
+ return wrapperPrimitiveMap.containsKey(type);
+ }
+
+ /**
+ * Checks if one {@code Class} can be assigned to a variable of
+ * another {@code Class}.
+ *
+ * Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
+ * this method takes into account widenings of primitive classes and
+ * {@code null}s.
+ *
+ * Primitive widenings allow an int to be assigned to a long, float or
+ * double. This method returns the correct result for these cases.
+ *
+ * {@code Null} may be assigned to any reference type. This method
+ * will return {@code true} if {@code null} is passed in and the
+ * toClass is non-primitive.
+ *
+ * Specifically, this method tests whether the type represented by the
+ * specified {@code Class} parameter can be converted to the type
+ * represented by this {@code Class} object via an identity conversion
+ * widening primitive or widening reference conversion. See
+ * The Java Language Specification ,
+ * sections 5.1.1, 5.1.2 and 5.1.4 for details.
+ *
+ * Since Lang 3.0, this method will default behavior for
+ * calculating assignability between primitive and wrapper types corresponding
+ * to the running Java version ; i.e. autoboxing will be the default
+ * behavior in VMs running Java versions > 1.5.
+ *
+ * @param cls the Class to check, may be null
+ * @param toClass the Class to try to assign into, returns false if null
+ * @return {@code true} if assignment possible
+ */
+ public static boolean isAssignable(final Class> cls, final Class> toClass) {
+ return isAssignable(cls, toClass, SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_5));
+ }
+
+ /**
+ * Checks if one {@code Class} can be assigned to a variable of
+ * another {@code Class}.
+ *
+ * Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
+ * this method takes into account widenings of primitive classes and
+ * {@code null}s.
+ *
+ * Primitive widenings allow an int to be assigned to a long, float or
+ * double. This method returns the correct result for these cases.
+ *
+ * {@code Null} may be assigned to any reference type. This method
+ * will return {@code true} if {@code null} is passed in and the
+ * toClass is non-primitive.
+ *
+ * Specifically, this method tests whether the type represented by the
+ * specified {@code Class} parameter can be converted to the type
+ * represented by this {@code Class} object via an identity conversion
+ * widening primitive or widening reference conversion. See
+ * The Java Language Specification ,
+ * sections 5.1.1, 5.1.2 and 5.1.4 for details.
+ *
+ * @param cls the Class to check, may be null
+ * @param toClass the Class to try to assign into, returns false if null
+ * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers
+ * @return {@code true} if assignment possible
+ */
+ public static boolean isAssignable(Class> cls, final Class> toClass, final boolean autoboxing) {
+ if (toClass == null) {
+ return false;
+ }
+ // have to check for null, as isAssignableFrom doesn't
+ if (cls == null) {
+ return !toClass.isPrimitive();
+ }
+ //autoboxing:
+ if (autoboxing) {
+ if (cls.isPrimitive() && !toClass.isPrimitive()) {
+ cls = primitiveToWrapper(cls);
+ if (cls == null) {
+ return false;
+ }
+ }
+ if (toClass.isPrimitive() && !cls.isPrimitive()) {
+ cls = wrapperToPrimitive(cls);
+ if (cls == null) {
+ return false;
+ }
+ }
+ }
+ if (cls.equals(toClass)) {
+ return true;
+ }
+ if (cls.isPrimitive()) {
+ if (toClass.isPrimitive() == false) {
+ return false;
+ }
+ if (Integer.TYPE.equals(cls)) {
+ return Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ if (Long.TYPE.equals(cls)) {
+ return Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ if (Boolean.TYPE.equals(cls)) {
+ return false;
+ }
+ if (Double.TYPE.equals(cls)) {
+ return false;
+ }
+ if (Float.TYPE.equals(cls)) {
+ return Double.TYPE.equals(toClass);
+ }
+ if (Character.TYPE.equals(cls)) {
+ return Integer.TYPE.equals(toClass)
+ || Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ if (Short.TYPE.equals(cls)) {
+ return Integer.TYPE.equals(toClass)
+ || Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ if (Byte.TYPE.equals(cls)) {
+ return Short.TYPE.equals(toClass)
+ || Integer.TYPE.equals(toClass)
+ || Long.TYPE.equals(toClass)
+ || Float.TYPE.equals(toClass)
+ || Double.TYPE.equals(toClass);
+ }
+ // should never get here
+ return false;
+ }
+ return toClass.isAssignableFrom(cls);
+ }
+
+ /**
+ * Converts the specified primitive Class object to its corresponding
+ * wrapper Class object.
+ *
+ * NOTE: From v2.2, this method handles {@code Void.TYPE},
+ * returning {@code Void.TYPE}.
+ *
+ * @param cls the class to convert, may be null
+ * @return the wrapper class for {@code cls} or {@code cls} if
+ * {@code cls} is not a primitive. {@code null} if null input.
+ * @since 2.1
+ */
+ public static Class> primitiveToWrapper(final Class> cls) {
+ Class> convertedClass = cls;
+ if (cls != null && cls.isPrimitive()) {
+ convertedClass = primitiveWrapperMap.get(cls);
+ }
+ return convertedClass;
+ }
+
+ /**
+ * Converts the specified array of primitive Class objects to an array of
+ * its corresponding wrapper Class objects.
+ *
+ * @param classes the class array to convert, may be null or empty
+ * @return an array which contains for each given class, the wrapper class or
+ * the original class if class is not a primitive. {@code null} if null input.
+ * Empty array if an empty array passed in.
+ * @since 2.1
+ */
+ public static Class>[] primitivesToWrappers(final Class>... classes) {
+ if (classes == null) {
+ return null;
+ }
+
+ if (classes.length == 0) {
+ return classes;
+ }
+
+ final Class>[] convertedClasses = new Class[classes.length];
+ for (int i = 0; i < classes.length; i++) {
+ convertedClasses[i] = primitiveToWrapper(classes[i]);
+ }
+ return convertedClasses;
+ }
+
+ /**
+ * Converts the specified wrapper class to its corresponding primitive
+ * class.
+ *
+ * This method is the counter part of {@code primitiveToWrapper()}.
+ * If the passed in class is a wrapper class for a primitive type, this
+ * primitive type will be returned (e.g. {@code Integer.TYPE} for
+ * {@code Integer.class}). For other classes, or if the parameter is
+ * null , the return value is null .
+ *
+ * @param cls the class to convert, may be null
+ * @return the corresponding primitive type if {@code cls} is a
+ * wrapper class, null otherwise
+ * @see #primitiveToWrapper(Class)
+ * @since 2.4
+ */
+ public static Class> wrapperToPrimitive(final Class> cls) {
+ return wrapperPrimitiveMap.get(cls);
+ }
+
+ /**
+ * Converts the specified array of wrapper Class objects to an array of
+ * its corresponding primitive Class objects.
+ *
+ * This method invokes {@code wrapperToPrimitive()} for each element
+ * of the passed in array.
+ *
+ * @param classes the class array to convert, may be null or empty
+ * @return an array which contains for each given class, the primitive class or
+ * null if the original class is not a wrapper class. {@code null} if null input.
+ * Empty array if an empty array passed in.
+ * @see #wrapperToPrimitive(Class)
+ * @since 2.4
+ */
+ public static Class>[] wrappersToPrimitives(final Class>... classes) {
+ if (classes == null) {
+ return null;
+ }
+
+ if (classes.length == 0) {
+ return classes;
+ }
+
+ final Class>[] convertedClasses = new Class[classes.length];
+ for (int i = 0; i < classes.length; i++) {
+ convertedClasses[i] = wrapperToPrimitive(classes[i]);
+ }
+ return convertedClasses;
+ }
+
+ // Inner class
+ // ----------------------------------------------------------------------
+ /**
+ * Is the specified class an inner class or static nested class.
+ *
+ * @param cls the class to check, may be null
+ * @return {@code true} if the class is an inner or static nested class,
+ * false if not or {@code null}
+ */
+ public static boolean isInnerClass(final Class> cls) {
+ return cls != null && cls.getEnclosingClass() != null;
+ }
+
+ // Class loading
+ // ----------------------------------------------------------------------
+ /**
+ * Returns the class represented by {@code className} using the
+ * {@code classLoader}. This implementation supports the syntaxes
+ * "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}",
+ * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}".
+ *
+ * @param classLoader the class loader to use to load the class
+ * @param className the class name
+ * @param initialize whether the class must be initialized
+ * @return the class represented by {@code className} using the {@code classLoader}
+ * @throws ClassNotFoundException if the class is not found
+ */
+ public static Class> getClass(
+ final ClassLoader classLoader, final String className, final boolean initialize) throws ClassNotFoundException {
+ try {
+ Class> clazz;
+ if (namePrimitiveMap.containsKey(className)) {
+ clazz = namePrimitiveMap.get(className);
+ } else {
+ clazz = Class.forName(toCanonicalName(className), initialize, classLoader);
+ }
+ return clazz;
+ } catch (final ClassNotFoundException ex) {
+ // allow path separators (.) as inner class name separators
+ final int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
+
+ if (lastDotIndex != -1) {
+ try {
+ return getClass(classLoader, className.substring(0, lastDotIndex) +
+ INNER_CLASS_SEPARATOR_CHAR + className.substring(lastDotIndex + 1),
+ initialize);
+ } catch (final ClassNotFoundException ex2) { // NOPMD
+ // ignore exception
+ }
+ }
+
+ throw ex;
+ }
+ }
+
+ /**
+ * Returns the (initialized) class represented by {@code className}
+ * using the {@code classLoader}. This implementation supports
+ * the syntaxes "{@code java.util.Map.Entry[]}",
+ * "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}",
+ * and "{@code [Ljava.util.Map$Entry;}".
+ *
+ * @param classLoader the class loader to use to load the class
+ * @param className the class name
+ * @return the class represented by {@code className} using the {@code classLoader}
+ * @throws ClassNotFoundException if the class is not found
+ */
+ public static Class> getClass(final ClassLoader classLoader, final String className) throws ClassNotFoundException {
+ return getClass(classLoader, className, true);
+ }
+
+ /**
+ * Returns the (initialized) class represented by {@code className}
+ * using the current thread's context class loader. This implementation
+ * supports the syntaxes "{@code java.util.Map.Entry[]}",
+ * "{@code java.util.Map$Entry[]}", "{@code [Ljava.util.Map.Entry;}",
+ * and "{@code [Ljava.util.Map$Entry;}".
+ *
+ * @param className the class name
+ * @return the class represented by {@code className} using the current thread's context class loader
+ * @throws ClassNotFoundException if the class is not found
+ */
+ public static Class> getClass(final String className) throws ClassNotFoundException {
+ return getClass(className, true);
+ }
+
+ /**
+ * Returns the class represented by {@code className} using the
+ * current thread's context class loader. This implementation supports the
+ * syntaxes "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}",
+ * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}".
+ *
+ * @param className the class name
+ * @param initialize whether the class must be initialized
+ * @return the class represented by {@code className} using the current thread's context class loader
+ * @throws ClassNotFoundException if the class is not found
+ */
+ public static Class> getClass(final String className, final boolean initialize) throws ClassNotFoundException {
+ final ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+ final ClassLoader loader = contextCL == null ? ClassUtils.class.getClassLoader() : contextCL;
+ return getClass(loader, className, initialize);
+ }
+
+ // Public method
+ // ----------------------------------------------------------------------
+ /**
+ * Returns the desired Method much like {@code Class.getMethod}, however
+ * it ensures that the returned Method is from a public class or interface and not
+ * from an anonymous inner class. This means that the Method is invokable and
+ * doesn't fall foul of Java bug
+ * 4071957 ).
+ *
+ *
+ * Set set = Collections.unmodifiableSet(...);
+ * Method method = ClassUtils.getPublicMethod(set.getClass(), "isEmpty", new Class[0]);
+ * Object result = method.invoke(set, new Object[]);
+ *
+ *
+ * @param cls the class to check, not null
+ * @param methodName the name of the method
+ * @param parameterTypes the list of parameters
+ * @return the method
+ * @throws NullPointerException if the class is null
+ * @throws SecurityException if a security violation occurred
+ * @throws NoSuchMethodException if the method is not found in the given class
+ * or if the method doesn't conform with the requirements
+ */
+ public static Method getPublicMethod(final Class> cls, final String methodName, final Class>... parameterTypes)
+ throws SecurityException, NoSuchMethodException {
+
+ final Method declaredMethod = cls.getMethod(methodName, parameterTypes);
+ if (Modifier.isPublic(declaredMethod.getDeclaringClass().getModifiers())) {
+ return declaredMethod;
+ }
+
+ final List> candidateClasses = new ArrayList>();
+ candidateClasses.addAll(getAllInterfaces(cls));
+ candidateClasses.addAll(getAllSuperclasses(cls));
+
+ for (final Class> candidateClass : candidateClasses) {
+ if (!Modifier.isPublic(candidateClass.getModifiers())) {
+ continue;
+ }
+ Method candidateMethod;
+ try {
+ candidateMethod = candidateClass.getMethod(methodName, parameterTypes);
+ } catch (final NoSuchMethodException ex) {
+ continue;
+ }
+ if (Modifier.isPublic(candidateMethod.getDeclaringClass().getModifiers())) {
+ return candidateMethod;
+ }
+ }
+
+ throw new NoSuchMethodException("Can't find a public method for " +
+ methodName + " " + ArrayUtils.toString(parameterTypes));
+ }
+
+ // ----------------------------------------------------------------------
+ /**
+ * Converts a class name to a JLS style class name.
+ *
+ * @param className the class name
+ * @return the converted name
+ */
+ private static String toCanonicalName(String className) {
+ className = StringUtils.deleteWhitespace(className);
+ if (className == null) {
+ throw new NullPointerException("className must not be null.");
+ } else if (className.endsWith("[]")) {
+ final StringBuilder classNameBuffer = new StringBuilder();
+ while (className.endsWith("[]")) {
+ className = className.substring(0, className.length() - 2);
+ classNameBuffer.append("[");
+ }
+ final String abbreviation = abbreviationMap.get(className);
+ if (abbreviation != null) {
+ classNameBuffer.append(abbreviation);
+ } else {
+ classNameBuffer.append("L").append(className).append(";");
+ }
+ className = classNameBuffer.toString();
+ }
+ return className;
+ }
+
+ /**
+ * Converts an array of {@code Object} in to an array of {@code Class} objects.
+ * If any of these objects is null, a null element will be inserted into the array.
+ *
+ * This method returns {@code null} for a {@code null} input array.
+ *
+ * @param array an {@code Object} array
+ * @return a {@code Class} array, {@code null} if null array input
+ * @since 2.4
+ */
+ public static Class>[] toClass(final Object... array) {
+ if (array == null) {
+ return null;
+ } else if (array.length == 0) {
+ return ArrayUtils.EMPTY_CLASS_ARRAY;
+ }
+ final Class>[] classes = new Class[array.length];
+ for (int i = 0; i < array.length; i++) {
+ classes[i] = array[i] == null ? null : array[i].getClass();
+ }
+ return classes;
+ }
+
+ // Short canonical name
+ // ----------------------------------------------------------------------
+ /**
+ * Gets the canonical name minus the package name for an {@code Object}.
+ *
+ * @param object the class to get the short name for, may be null
+ * @param valueIfNull the value to return if null
+ * @return the canonical name of the object without the package name, or the null value
+ * @since 2.4
+ */
+ public static String getShortCanonicalName(final Object object, final String valueIfNull) {
+ if (object == null) {
+ return valueIfNull;
+ }
+ return getShortCanonicalName(object.getClass().getName());
+ }
+
+ /**
+ * Gets the canonical name minus the package name from a {@code Class}.
+ *
+ * @param cls the class to get the short name for.
+ * @return the canonical name without the package name or an empty string
+ * @since 2.4
+ */
+ public static String getShortCanonicalName(final Class> cls) {
+ if (cls == null) {
+ return StringUtils.EMPTY;
+ }
+ return getShortCanonicalName(cls.getName());
+ }
+
+ /**
+ * Gets the canonical name minus the package name from a String.
+ *
+ * The string passed in is assumed to be a canonical name - it is not checked.
+ *
+ * @param canonicalName the class name to get the short name for
+ * @return the canonical name of the class without the package name or an empty string
+ * @since 2.4
+ */
+ public static String getShortCanonicalName(final String canonicalName) {
+ return ClassUtils.getShortClassName(getCanonicalName(canonicalName));
+ }
+
+ // Package name
+ // ----------------------------------------------------------------------
+ /**
+ * Gets the package name from the canonical name of an {@code Object}.
+ *
+ * @param object the class to get the package name for, may be null
+ * @param valueIfNull the value to return if null
+ * @return the package name of the object, or the null value
+ * @since 2.4
+ */
+ public static String getPackageCanonicalName(final Object object, final String valueIfNull) {
+ if (object == null) {
+ return valueIfNull;
+ }
+ return getPackageCanonicalName(object.getClass().getName());
+ }
+
+ /**
+ * Gets the package name from the canonical name of a {@code Class}.
+ *
+ * @param cls the class to get the package name for, may be {@code null}.
+ * @return the package name or an empty string
+ * @since 2.4
+ */
+ public static String getPackageCanonicalName(final Class> cls) {
+ if (cls == null) {
+ return StringUtils.EMPTY;
+ }
+ return getPackageCanonicalName(cls.getName());
+ }
+
+ /**
+ * Gets the package name from the canonical name.
+ *
+ * The string passed in is assumed to be a canonical name - it is not checked.
+ * If the class is unpackaged, return an empty string.
+ *
+ * @param canonicalName the canonical name to get the package name for, may be {@code null}
+ * @return the package name or an empty string
+ * @since 2.4
+ */
+ public static String getPackageCanonicalName(final String canonicalName) {
+ return ClassUtils.getPackageName(getCanonicalName(canonicalName));
+ }
+
+ /**
+ * Converts a given name of class into canonical format.
+ * If name of class is not a name of array class it returns
+ * unchanged name.
+ * Example:
+ *
+ * {@code getCanonicalName("[I") = "int[]"}
+ * {@code getCanonicalName("[Ljava.lang.String;") = "java.lang.String[]"}
+ * {@code getCanonicalName("java.lang.String") = "java.lang.String"}
+ *
+ *
+ *
+ * @param className the name of class
+ * @return canonical form of class name
+ * @since 2.4
+ */
+ private static String getCanonicalName(String className) {
+ className = StringUtils.deleteWhitespace(className);
+ if (className == null) {
+ return null;
+ }
+ int dim = 0;
+ while (className.startsWith("[")) {
+ dim++;
+ className = className.substring(1);
+ }
+ if (dim < 1) {
+ return className;
+ }
+ if (className.startsWith("L")) {
+ className = className.substring(
+ 1,
+ className.endsWith(";")
+ ? className.length() - 1
+ : className.length());
+ } else {
+ if (className.length() > 0) {
+ className = reverseAbbreviationMap.get(className.substring(0, 1));
+ }
+ }
+ final StringBuilder canonicalClassNameBuffer = new StringBuilder(className);
+ for (int i = 0; i < dim; i++) {
+ canonicalClassNameBuffer.append("[]");
+ }
+ return canonicalClassNameBuffer.toString();
+ }
+
+ /**
+ * Get an {@link Iterable} that can iterate over a class hierarchy in ascending (subclass to superclass) order,
+ * excluding interfaces.
+ *
+ * @param type the type to get the class hierarchy from
+ * @return Iterable an Iterable over the class hierarchy of the given class
+ * @since 3.2
+ */
+ public static Iterable> hierarchy(final Class> type) {
+ return hierarchy(type, Interfaces.EXCLUDE);
+ }
+
+ /**
+ * Get an {@link Iterable} that can iterate over a class hierarchy in ascending (subclass to superclass) order.
+ *
+ * @param type the type to get the class hierarchy from
+ * @param interfacesBehavior switch indicating whether to include or exclude interfaces
+ * @return Iterable an Iterable over the class hierarchy of the given class
+ * @since 3.2
+ */
+ public static Iterable> hierarchy(final Class> type, final Interfaces interfacesBehavior) {
+ final Iterable> classes = new Iterable>() {
+
+ @Override
+ public Iterator> iterator() {
+ final MutableObject> next = new MutableObject>(type);
+ return new Iterator>() {
+
+ @Override
+ public boolean hasNext() {
+ return next.getValue() != null;
+ }
+
+ @Override
+ public Class> next() {
+ final Class> result = next.getValue();
+ next.setValue(result.getSuperclass());
+ return result;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ };
+ }
+
+ };
+ if (interfacesBehavior != Interfaces.INCLUDE) {
+ return classes;
+ }
+ return new Iterable>() {
+
+ @Override
+ public Iterator> iterator() {
+ final Set> seenInterfaces = new HashSet>();
+ final Iterator> wrapped = classes.iterator();
+
+ return new Iterator>() {
+ Iterator> interfaces = Collections.> emptySet().iterator();
+
+ @Override
+ public boolean hasNext() {
+ return interfaces.hasNext() || wrapped.hasNext();
+ }
+
+ @Override
+ public Class> next() {
+ if (interfaces.hasNext()) {
+ final Class> nextInterface = interfaces.next();
+ seenInterfaces.add(nextInterface);
+ return nextInterface;
+ }
+ final Class> nextSuperclass = wrapped.next();
+ final Set> currentInterfaces = new LinkedHashSet>();
+ walkInterfaces(currentInterfaces, nextSuperclass);
+ interfaces = currentInterfaces.iterator();
+ return nextSuperclass;
+ }
+
+ private void walkInterfaces(final Set> addTo, final Class> c) {
+ for (final Class> iface : c.getInterfaces()) {
+ if (!seenInterfaces.contains(iface)) {
+ addTo.add(iface);
+ }
+ walkInterfaces(addTo, iface);
+ }
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ };
+ }
+ };
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Conversion.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Conversion.java
new file mode 100644
index 000000000..05df59430
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Conversion.java
@@ -0,0 +1,1565 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ *******************************************************************************/
+package org.apache.commons.lang3;
+
+import java.util.UUID;
+
+
+/**
+ *
+ * Static methods to convert a type into another, with endianness and bit ordering awareness.
+ *
+ *
+ * The methods names follow a naming rule:
+ * {@code [source endianness][source bit ordering]To[destination endianness][destination bit ordering]}
+ *
+ *
+ * Source/destination type fields is one of the following:
+ *
+ *
+ * binary: an array of booleans
+ * byte or byteArray
+ * int or intArray
+ * long or longArray
+ * hex: a String containing hexadecimal digits (lowercase in destination)
+ * hexDigit: a Char containing a hexadecimal digit (lowercase in destination)
+ * uuid
+ *
+ *
+ * Endianness field: little endian is the default, in this case the field is absent. In case of
+ * big endian, the field is "Be". Bit ordering: Lsb0 is the default, in this case the field
+ * is absent. In case of Msb0, the field is "Msb0".
+ *
+ *
+ * Example: intBeMsb0ToHex convert an int with big endian byte order and Msb0 bit order into its
+ * hexadecimal string representation
+ *
+ *
+ * Most of the methods provide only default encoding for destination, this limits the number of
+ * ways to do one thing. Unless you are dealing with data from/to outside of the JVM platform,
+ * you should not need to use "Be" and "Msb0" methods.
+ *
+ *
+ * Development status: work on going, only a part of the little endian, Lsb0 methods implemented
+ * so far.
+ *
+ *
+ * @since Lang 3.2
+ */
+
+public class Conversion {
+
+ private static final boolean[] TTTT = new boolean[] { true, true, true, true };
+ private static final boolean[] FTTT = new boolean[] { false, true, true, true };
+ private static final boolean[] TFTT = new boolean[] { true, false, true, true };
+ private static final boolean[] FFTT = new boolean[] { false, false, true, true };
+ private static final boolean[] TTFT = new boolean[] { true, true, false, true };
+ private static final boolean[] FTFT = new boolean[] { false, true, false, true };
+ private static final boolean[] TFFT = new boolean[] { true, false, false, true };
+ private static final boolean[] FFFT = new boolean[] { false, false, false, true };
+ private static final boolean[] TTTF = new boolean[] { true, true, true, false };
+ private static final boolean[] FTTF = new boolean[] { false, true, true, false };
+ private static final boolean[] TFTF = new boolean[] { true, false, true, false };
+ private static final boolean[] FFTF = new boolean[] { false, false, true, false };
+ private static final boolean[] TTFF = new boolean[] { true, true, false, false };
+ private static final boolean[] FTFF = new boolean[] { false, true, false, false };
+ private static final boolean[] TFFF = new boolean[] { true, false, false, false };
+ private static final boolean[] FFFF = new boolean[] { false, false, false, false };
+
+ /**
+ *
+ * Converts a hexadecimal digit into an int using the default (Lsb0) bit ordering.
+ *
+ *
+ * '1' is converted to 1
+ *
+ *
+ * @param hexDigit the hexadecimal digit to convert
+ * @return an int equals to {@code hexDigit}
+ * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
+ */
+ public static int hexDigitToInt(final char hexDigit) {
+ final int digit = Character.digit(hexDigit, 16);
+ if (digit < 0) {
+ throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
+ }
+ return digit;
+ }
+
+ /**
+ *
+ * Converts a hexadecimal digit into an int using the Msb0 bit ordering.
+ *
+ *
+ * '1' is converted to 8
+ *
+ *
+ * @param hexDigit the hexadecimal digit to convert
+ * @return an int equals to {@code hexDigit}
+ * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
+ */
+ public static int hexDigitMsb0ToInt(final char hexDigit) {
+ switch (hexDigit) {
+ case '0':
+ return 0x0;
+ case '1':
+ return 0x8;
+ case '2':
+ return 0x4;
+ case '3':
+ return 0xC;
+ case '4':
+ return 0x2;
+ case '5':
+ return 0xA;
+ case '6':
+ return 0x6;
+ case '7':
+ return 0xE;
+ case '8':
+ return 0x1;
+ case '9':
+ return 0x9;
+ case 'a':// fall through
+ case 'A':
+ return 0x5;
+ case 'b':// fall through
+ case 'B':
+ return 0xD;
+ case 'c':// fall through
+ case 'C':
+ return 0x3;
+ case 'd':// fall through
+ case 'D':
+ return 0xB;
+ case 'e':// fall through
+ case 'E':
+ return 0x7;
+ case 'f':// fall through
+ case 'F':
+ return 0xF;
+ default:
+ throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
+ }
+ }
+
+ /**
+ *
+ * Converts a hexadecimal digit into binary (represented as boolean array) using the default
+ * (Lsb0) bit ordering.
+ *
+ *
+ * '1' is converted as follow: (1, 0, 0, 0)
+ *
+ *
+ * @param hexDigit the hexadecimal digit to convert
+ * @return a boolean array with the binary representation of {@code hexDigit}
+ * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
+ */
+ public static boolean[] hexDigitToBinary(final char hexDigit) {
+ switch (hexDigit) {
+ case '0':
+ return FFFF.clone();
+ case '1':
+ return TFFF.clone();
+ case '2':
+ return FTFF.clone();
+ case '3':
+ return TTFF.clone();
+ case '4':
+ return FFTF.clone();
+ case '5':
+ return TFTF.clone();
+ case '6':
+ return FTTF.clone();
+ case '7':
+ return TTTF.clone();
+ case '8':
+ return FFFT.clone();
+ case '9':
+ return TFFT.clone();
+ case 'a':// fall through
+ case 'A':
+ return FTFT.clone();
+ case 'b':// fall through
+ case 'B':
+ return TTFT.clone();
+ case 'c':// fall through
+ case 'C':
+ return FFTT.clone();
+ case 'd':// fall through
+ case 'D':
+ return TFTT.clone();
+ case 'e':// fall through
+ case 'E':
+ return FTTT.clone();
+ case 'f':// fall through
+ case 'F':
+ return TTTT.clone();
+ default:
+ throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
+ }
+ }
+
+ /**
+ *
+ * Converts a hexadecimal digit into binary (represented as boolean array) using the Msb0
+ * bit ordering.
+ *
+ *
+ * '1' is converted as follow: (0, 0, 0, 1)
+ *
+ *
+ * @param hexDigit the hexadecimal digit to convert
+ * @return a boolean array with the binary representation of {@code hexDigit}
+ * @throws IllegalArgumentException if {@code hexDigit} is not a hexadecimal digit
+ */
+ public static boolean[] hexDigitMsb0ToBinary(final char hexDigit) {
+ switch (hexDigit) {
+ case '0':
+ return FFFF.clone();
+ case '1':
+ return FFFT.clone();
+ case '2':
+ return FFTF.clone();
+ case '3':
+ return FFTT.clone();
+ case '4':
+ return FTFF.clone();
+ case '5':
+ return FTFT.clone();
+ case '6':
+ return FTTF.clone();
+ case '7':
+ return FTTT.clone();
+ case '8':
+ return TFFF.clone();
+ case '9':
+ return TFFT.clone();
+ case 'a':// fall through
+ case 'A':
+ return TFTF.clone();
+ case 'b':// fall through
+ case 'B':
+ return TFTT.clone();
+ case 'c':// fall through
+ case 'C':
+ return TTFF.clone();
+ case 'd':// fall through
+ case 'D':
+ return TTFT.clone();
+ case 'e':// fall through
+ case 'E':
+ return TTTF.clone();
+ case 'f':// fall through
+ case 'F':
+ return TTTT.clone();
+ default:
+ throw new IllegalArgumentException("Cannot interpret '" + hexDigit + "' as a hexadecimal digit");
+ }
+ }
+
+ /**
+ *
+ * Converts binary (represented as boolean array) to a hexadecimal digit using the default
+ * (Lsb0) bit ordering.
+ *
+ *
+ * (1, 0, 0, 0) is converted as follow: '1'
+ *
+ *
+ * @param src the binary to convert
+ * @return a hexadecimal digit representing the selected bits
+ * @throws IllegalArgumentException if {@code src} is empty
+ * @throws NullPointerException if {@code src} is {@code null}
+ */
+ public static char binaryToHexDigit(final boolean[] src) {
+ return binaryToHexDigit(src, 0);
+ }
+
+ /**
+ *
+ * Converts binary (represented as boolean array) to a hexadecimal digit using the default
+ * (Lsb0) bit ordering.
+ *
+ *
+ * (1, 0, 0, 0) is converted as follow: '1'
+ *
+ *
+ * @param src the binary to convert
+ * @param srcPos the position of the lsb to start the conversion
+ * @return a hexadecimal digit representing the selected bits
+ * @throws IllegalArgumentException if {@code src} is empty
+ * @throws NullPointerException if {@code src} is {@code null}
+ */
+ public static char binaryToHexDigit(final boolean[] src, final int srcPos) {
+ if (src.length == 0) {
+ throw new IllegalArgumentException("Cannot convert an empty array.");
+ }
+ if (src.length > srcPos + 3 && src[srcPos + 3]) {
+ if (src.length > srcPos + 2 && src[srcPos + 2]) {
+ if (src.length > srcPos + 1 && src[srcPos + 1]) {
+ return src[srcPos] ? 'f' : 'e';
+ }
+ return src[srcPos] ? 'd' : 'c';
+ }
+ if (src.length > srcPos + 1 && src[srcPos + 1]) {
+ return src[srcPos] ? 'b' : 'a';
+ }
+ return src[srcPos] ? '9' : '8';
+ }
+ if (src.length > srcPos + 2 && src[srcPos + 2]) {
+ if (src.length > srcPos + 1 && src[srcPos + 1]) {
+ return src[srcPos] ? '7' : '6';
+ }
+ return src[srcPos] ? '5' : '4';
+ }
+ if (src.length > srcPos + 1 && src[srcPos + 1]) {
+ return src[srcPos] ? '3' : '2';
+ }
+ return src[srcPos] ? '1' : '0';
+ }
+
+ /**
+ *
+ * Converts binary (represented as boolean array) to a hexadecimal digit using the Msb0 bit
+ * ordering.
+ *
+ *
+ * (1, 0, 0, 0) is converted as follow: '8'
+ *
+ *
+ * @param src the binary to convert
+ * @return a hexadecimal digit representing the selected bits
+ * @throws IllegalArgumentException if {@code src} is empty, {@code src.length < 4} or
+ * {@code src.length > 8}
+ * @throws NullPointerException if {@code src} is {@code null}
+ */
+ public static char binaryToHexDigitMsb0_4bits(final boolean[] src) {
+ return binaryToHexDigitMsb0_4bits(src, 0);
+ }
+
+ /**
+ *
+ * Converts binary (represented as boolean array) to a hexadecimal digit using the Msb0 bit
+ * ordering.
+ *
+ *
+ * (1, 0, 0, 0) is converted as follow: '8' (1,0,0,1,1,0,1,0) with srcPos = 3 is converted
+ * to 'D'
+ *
+ *
+ * @param src the binary to convert
+ * @param srcPos the position of the lsb to start the conversion
+ * @return a hexadecimal digit representing the selected bits
+ * @throws IllegalArgumentException if {@code src} is empty, {@code src.length > 8} or
+ * {@code src.length - srcPos < 4}
+ * @throws NullPointerException if {@code src} is {@code null}
+ */
+ public static char binaryToHexDigitMsb0_4bits(final boolean[] src, final int srcPos) {
+ if (src.length > 8) {
+ throw new IllegalArgumentException("src.length>8: src.length=" + src.length);
+ }
+ if (src.length - srcPos < 4) {
+ throw new IllegalArgumentException("src.length-srcPos<4: src.length=" + src.length + ", srcPos=" + srcPos);
+ }
+ if (src[srcPos + 3]) {
+ if (src[srcPos + 2]) {
+ if (src[srcPos + 1]) {
+ return src[srcPos] ? 'f' : '7';
+ }
+ return src[srcPos] ? 'b' : '3';
+ }
+ if (src[srcPos + 1]) {
+ return src[srcPos] ? 'd' : '5';
+ }
+ return src[srcPos] ? '9' : '1';
+ }
+ if (src[srcPos + 2]) {
+ if (src[srcPos + 1]) {
+ return src[srcPos] ? 'e' : '6';
+ }
+ return src[srcPos] ? 'a' : '2';
+ }
+ if (src[srcPos + 1]) {
+ return src[srcPos] ? 'c' : '4';
+ }
+ return src[srcPos] ? '8' : '0';
+ }
+
+ /**
+ *
+ * Converts the first 4 bits of a binary (represented as boolean array) in big endian Msb0
+ * bit ordering to a hexadecimal digit.
+ *
+ *
+ * (1, 0, 0, 0) is converted as follow: '8' (1,0,0,0,0,0,0,0, 0,0,0,0,0,1,0,0) is converted
+ * to '4'
+ *
+ *
+ * @param src the binary to convert
+ * @return a hexadecimal digit representing the selected bits
+ * @throws IllegalArgumentException if {@code src} is empty
+ * @throws NullPointerException if {@code src} is {@code null}
+ */
+ public static char binaryBeMsb0ToHexDigit(final boolean[] src) {
+ return binaryBeMsb0ToHexDigit(src, 0);
+ }
+
+ /**
+ *
+ * Converts a binary (represented as boolean array) in big endian Msb0 bit ordering to a
+ * hexadecimal digit.
+ *
+ *
+ * (1, 0, 0, 0) with srcPos = 0 is converted as follow: '8' (1,0,0,0,0,0,0,0,
+ * 0,0,0,1,0,1,0,0) with srcPos = 2 is converted to '5'
+ *
+ *
+ * @param src the binary to convert
+ * @param srcPos the position of the lsb to start the conversion
+ * @return a hexadecimal digit representing the selected bits
+ * @throws IllegalArgumentException if {@code src} is empty
+ * @throws NullPointerException if {@code src} is {@code null}
+ */
+ public static char binaryBeMsb0ToHexDigit(boolean[] src, int srcPos) {
+ if (src.length == 0) {
+ throw new IllegalArgumentException("Cannot convert an empty array.");
+ }
+ final int beSrcPos = src.length - 1 - srcPos;
+ final int srcLen = Math.min(4, beSrcPos + 1);
+ final boolean[] paddedSrc = new boolean[4];
+ System.arraycopy(src, beSrcPos + 1 - srcLen, paddedSrc, 4 - srcLen, srcLen);
+ src = paddedSrc;
+ srcPos = 0;
+ if (src[srcPos]) {
+ if (src.length > srcPos + 1 && src[srcPos + 1]) {
+ if (src.length > srcPos + 2 && src[srcPos + 2]) {
+ return src.length > srcPos + 3 && src[srcPos + 3] ? 'f' : 'e';
+ }
+ return src.length > srcPos + 3 && src[srcPos + 3] ? 'd' : 'c';
+ }
+ if (src.length > srcPos + 2 && src[srcPos + 2]) {
+ return src.length > srcPos + 3 && src[srcPos + 3] ? 'b' : 'a';
+ }
+ return src.length > srcPos + 3 && src[srcPos + 3] ? '9' : '8';
+ }
+ if (src.length > srcPos + 1 && src[srcPos + 1]) {
+ if (src.length > srcPos + 2 && src[srcPos + 2]) {
+ return src.length > srcPos + 3 && src[srcPos + 3] ? '7' : '6';
+ }
+ return src.length > srcPos + 3 && src[srcPos + 3] ? '5' : '4';
+ }
+ if (src.length > srcPos + 2 && src[srcPos + 2]) {
+ return src.length > srcPos + 3 && src[srcPos + 3] ? '3' : '2';
+ }
+ return src.length > srcPos + 3 && src[srcPos + 3] ? '1' : '0';
+ }
+
+ /**
+ *
+ * Converts the 4 lsb of an int to a hexadecimal digit.
+ *
+ *
+ * 0 returns '0'
+ *
+ *
+ * 1 returns '1'
+ *
+ *
+ * 10 returns 'A' and so on...
+ *
+ *
+ * @param nibble the 4 bits to convert
+ * @return a hexadecimal digit representing the 4 lsb of {@code nibble}
+ * @throws IllegalArgumentException if {@code nibble < 0} or {@code nibble > 15}
+ */
+ public static char intToHexDigit(final int nibble) {
+ final char c = Character.forDigit(nibble, 16);
+ if (c == Character.MIN_VALUE) {
+ throw new IllegalArgumentException("nibble value not between 0 and 15: " + nibble);
+ }
+ return c;
+ }
+
+ /**
+ *
+ * Converts the 4 lsb of an int to a hexadecimal digit encoded using the Msb0 bit ordering.
+ *
+ *
+ * 0 returns '0'
+ *
+ *
+ * 1 returns '8'
+ *
+ *
+ * 10 returns '5' and so on...
+ *
+ *
+ * @param nibble the 4 bits to convert
+ * @return a hexadecimal digit representing the 4 lsb of {@code nibble}
+ * @throws IllegalArgumentException if {@code nibble < 0} or {@code nibble > 15}
+ */
+ public static char intToHexDigitMsb0(final int nibble) {
+ switch (nibble) {
+ case 0x0:
+ return '0';
+ case 0x1:
+ return '8';
+ case 0x2:
+ return '4';
+ case 0x3:
+ return 'c';
+ case 0x4:
+ return '2';
+ case 0x5:
+ return 'a';
+ case 0x6:
+ return '6';
+ case 0x7:
+ return 'e';
+ case 0x8:
+ return '1';
+ case 0x9:
+ return '9';
+ case 0xA:
+ return '5';
+ case 0xB:
+ return 'd';
+ case 0xC:
+ return '3';
+ case 0xD:
+ return 'b';
+ case 0xE:
+ return '7';
+ case 0xF:
+ return 'f';
+ default:
+ throw new IllegalArgumentException("nibble value not between 0 and 15: " + nibble);
+ }
+ }
+
+ /**
+ *
+ * Converts an array of int into a long using the default (little endian, Lsb0) byte and bit
+ * ordering.
+ *
+ *
+ * @param src the int array to convert
+ * @param srcPos the position in {@code src}, in int unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination long
+ * @param dstPos the position of the lsb, in bits, in the result long
+ * @param nInts the number of ints to convert
+ * @return a long containing the selected bits
+ * @throws IllegalArgumentException if {@code (nInts-1)*32+dstPos >= 64}
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nInts > src.length}
+ */
+ public static long intArrayToLong(final int[] src, final int srcPos, final long dstInit, final int dstPos,
+ final int nInts) {
+ if (src.length == 0 && srcPos == 0 || 0 == nInts) {
+ return dstInit;
+ }
+ if ((nInts - 1) * 32 + dstPos >= 64) {
+ throw new IllegalArgumentException("(nInts-1)*32+dstPos is greather or equal to than 64");
+ }
+ long out = dstInit;
+ for (int i = 0; i < nInts; i++) {
+ final int shift = i * 32 + dstPos;
+ final long bits = (0xffffffffL & src[i + srcPos]) << shift;
+ final long mask = 0xffffffffL << shift;
+ out = (out & ~mask) | bits;
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts an array of short into a long using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the short array to convert
+ * @param srcPos the position in {@code src}, in short unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination long
+ * @param dstPos the position of the lsb, in bits, in the result long
+ * @param nShorts the number of shorts to convert
+ * @return a long containing the selected bits
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws IllegalArgumentException if {@code (nShorts-1)*16+dstPos >= 64}
+ * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nShorts > src.length}
+ */
+ public static long shortArrayToLong(final short[] src, final int srcPos, final long dstInit, final int dstPos,
+ final int nShorts) {
+ if (src.length == 0 && srcPos == 0 || 0 == nShorts) {
+ return dstInit;
+ }
+ if ((nShorts - 1) * 16 + dstPos >= 64) {
+ throw new IllegalArgumentException("(nShorts-1)*16+dstPos is greather or equal to than 64");
+ }
+ long out = dstInit;
+ for (int i = 0; i < nShorts; i++) {
+ final int shift = i * 16 + dstPos;
+ final long bits = (0xffffL & src[i + srcPos]) << shift;
+ final long mask = 0xffffL << shift;
+ out = (out & ~mask) | bits;
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts an array of short into a int using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the short array to convert
+ * @param srcPos the position in {@code src}, in short unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination int
+ * @param dstPos the position of the lsb, in bits, in the result int
+ * @param nShorts the number of shorts to convert
+ * @return a int containing the selected bits
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws IllegalArgumentException if {@code (nShorts-1)*16+dstPos >= 32}
+ * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nShorts > src.length}
+ */
+ public static int shortArrayToInt(final short[] src, final int srcPos, final int dstInit, final int dstPos,
+ final int nShorts) {
+ if (src.length == 0 && srcPos == 0 || 0 == nShorts) {
+ return dstInit;
+ }
+ if ((nShorts - 1) * 16 + dstPos >= 32) {
+ throw new IllegalArgumentException("(nShorts-1)*16+dstPos is greather or equal to than 32");
+ }
+ int out = dstInit;
+ for (int i = 0; i < nShorts; i++) {
+ final int shift = i * 16 + dstPos;
+ final int bits = (0xffff & src[i + srcPos]) << shift;
+ final int mask = 0xffff << shift;
+ out = (out & ~mask) | bits;
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts an array of byte into a long using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the byte array to convert
+ * @param srcPos the position in {@code src}, in byte unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination long
+ * @param dstPos the position of the lsb, in bits, in the result long
+ * @param nBytes the number of bytes to convert
+ * @return a long containing the selected bits
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws IllegalArgumentException if {@code (nBytes-1)*8+dstPos >= 64}
+ * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBytes > src.length}
+ */
+ public static long byteArrayToLong(final byte[] src, final int srcPos, final long dstInit, final int dstPos,
+ final int nBytes) {
+ if (src.length == 0 && srcPos == 0 || 0 == nBytes) {
+ return dstInit;
+ }
+ if ((nBytes - 1) * 8 + dstPos >= 64) {
+ throw new IllegalArgumentException("(nBytes-1)*8+dstPos is greather or equal to than 64");
+ }
+ long out = dstInit;
+ for (int i = 0; i < nBytes; i++) {
+ final int shift = i * 8 + dstPos;
+ final long bits = (0xffL & src[i + srcPos]) << shift;
+ final long mask = 0xffL << shift;
+ out = (out & ~mask) | bits;
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts an array of byte into a int using the default (little endian, Lsb0) byte and bit
+ * ordering.
+ *
+ *
+ * @param src the byte array to convert
+ * @param srcPos the position in {@code src}, in byte unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination int
+ * @param dstPos the position of the lsb, in bits, in the result int
+ * @param nBytes the number of bytes to convert
+ * @return a int containing the selected bits
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws IllegalArgumentException if {@code (nBytes-1)*8+dstPos >= 32}
+ * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBytes > src.length}
+ */
+ public static int byteArrayToInt(final byte[] src, final int srcPos, final int dstInit, final int dstPos,
+ final int nBytes) {
+ if (src.length == 0 && srcPos == 0 || 0 == nBytes) {
+ return dstInit;
+ }
+ if ((nBytes - 1) * 8 + dstPos >= 32) {
+ throw new IllegalArgumentException("(nBytes-1)*8+dstPos is greather or equal to than 32");
+ }
+ int out = dstInit;
+ for (int i = 0; i < nBytes; i++) {
+ final int shift = i * 8 + dstPos;
+ final int bits = (0xff & src[i + srcPos]) << shift;
+ final int mask = 0xff << shift;
+ out = (out & ~mask) | bits;
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts an array of byte into a short using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the byte array to convert
+ * @param srcPos the position in {@code src}, in byte unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination short
+ * @param dstPos the position of the lsb, in bits, in the result short
+ * @param nBytes the number of bytes to convert
+ * @return a short containing the selected bits
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws IllegalArgumentException if {@code (nBytes-1)*8+dstPos >= 16}
+ * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBytes > src.length}
+ */
+ public static short byteArrayToShort(final byte[] src, final int srcPos, final short dstInit, final int dstPos,
+ final int nBytes) {
+ if (src.length == 0 && srcPos == 0 || 0 == nBytes) {
+ return dstInit;
+ }
+ if ((nBytes - 1) * 8 + dstPos >= 16) {
+ throw new IllegalArgumentException("(nBytes-1)*8+dstPos is greather or equal to than 16");
+ }
+ short out = dstInit;
+ for (int i = 0; i < nBytes; i++) {
+ final int shift = i * 8 + dstPos;
+ final int bits = (0xff & src[i + srcPos]) << shift;
+ final int mask = 0xff << shift;
+ out = (short) ((out & ~mask) | bits);
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts an array of Char into a long using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the hex string to convert
+ * @param srcPos the position in {@code src}, in Char unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination long
+ * @param dstPos the position of the lsb, in bits, in the result long
+ * @param nHex the number of Chars to convert
+ * @return a long containing the selected bits
+ * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 64}
+ */
+ public static long hexToLong(final String src, final int srcPos, final long dstInit, final int dstPos,
+ final int nHex) {
+ if (0 == nHex) {
+ return dstInit;
+ }
+ if ((nHex - 1) * 4 + dstPos >= 64) {
+ throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greather or equal to than 64");
+ }
+ long out = dstInit;
+ for (int i = 0; i < nHex; i++) {
+ final int shift = i * 4 + dstPos;
+ final long bits = (0xfL & hexDigitToInt(src.charAt(i + srcPos))) << shift;
+ final long mask = 0xfL << shift;
+ out = (out & ~mask) | bits;
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts an array of Char into a int using the default (little endian, Lsb0) byte and bit
+ * ordering.
+ *
+ *
+ * @param src the hex string to convert
+ * @param srcPos the position in {@code src}, in Char unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination int
+ * @param dstPos the position of the lsb, in bits, in the result int
+ * @param nHex the number of Chars to convert
+ * @return a int containing the selected bits
+ * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 32}
+ */
+ public static int hexToInt(final String src, final int srcPos, final int dstInit, final int dstPos, final int nHex) {
+ if (0 == nHex) {
+ return dstInit;
+ }
+ if ((nHex - 1) * 4 + dstPos >= 32) {
+ throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greather or equal to than 32");
+ }
+ int out = dstInit;
+ for (int i = 0; i < nHex; i++) {
+ final int shift = i * 4 + dstPos;
+ final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift;
+ final int mask = 0xf << shift;
+ out = (out & ~mask) | bits;
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts an array of Char into a short using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the hex string to convert
+ * @param srcPos the position in {@code src}, in Char unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination short
+ * @param dstPos the position of the lsb, in bits, in the result short
+ * @param nHex the number of Chars to convert
+ * @return a short containing the selected bits
+ * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 16}
+ */
+ public static short hexToShort(final String src, final int srcPos, final short dstInit, final int dstPos,
+ final int nHex) {
+ if (0 == nHex) {
+ return dstInit;
+ }
+ if ((nHex - 1) * 4 + dstPos >= 16) {
+ throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greather or equal to than 16");
+ }
+ short out = dstInit;
+ for (int i = 0; i < nHex; i++) {
+ final int shift = i * 4 + dstPos;
+ final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift;
+ final int mask = 0xf << shift;
+ out = (short) ((out & ~mask) | bits);
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts an array of Char into a byte using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the hex string to convert
+ * @param srcPos the position in {@code src}, in Char unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination byte
+ * @param dstPos the position of the lsb, in bits, in the result byte
+ * @param nHex the number of Chars to convert
+ * @return a byte containing the selected bits
+ * @throws IllegalArgumentException if {@code (nHexs-1)*4+dstPos >= 8}
+ */
+ public static byte hexToByte(final String src, final int srcPos, final byte dstInit, final int dstPos,
+ final int nHex) {
+ if (0 == nHex) {
+ return dstInit;
+ }
+ if ((nHex - 1) * 4 + dstPos >= 8) {
+ throw new IllegalArgumentException("(nHexs-1)*4+dstPos is greather or equal to than 8");
+ }
+ byte out = dstInit;
+ for (int i = 0; i < nHex; i++) {
+ final int shift = i * 4 + dstPos;
+ final int bits = (0xf & hexDigitToInt(src.charAt(i + srcPos))) << shift;
+ final int mask = 0xf << shift;
+ out = (byte) ((out & ~mask) | bits);
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts binary (represented as boolean array) into a long using the default (little
+ * endian, Lsb0) byte and bit ordering.
+ *
+ *
+ * @param src the binary to convert
+ * @param srcPos the position in {@code src}, in boolean unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination long
+ * @param dstPos the position of the lsb, in bits, in the result long
+ * @param nBools the number of booleans to convert
+ * @return a long containing the selected bits
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 64}
+ * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
+ */
+ public static long binaryToLong(final boolean[] src, final int srcPos, final long dstInit, final int dstPos,
+ final int nBools) {
+ if (src.length == 0 && srcPos == 0 || 0 == nBools) {
+ return dstInit;
+ }
+ if (nBools - 1 + dstPos >= 64) {
+ throw new IllegalArgumentException("nBools-1+dstPos is greather or equal to than 64");
+ }
+ long out = dstInit;
+ for (int i = 0; i < nBools; i++) {
+ final int shift = i + dstPos;
+ final long bits = (src[i + srcPos] ? 1L : 0) << shift;
+ final long mask = 0x1L << shift;
+ out = (out & ~mask) | bits;
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts binary (represented as boolean array) into a int using the default (little
+ * endian, Lsb0) byte and bit ordering.
+ *
+ *
+ * @param src the binary to convert
+ * @param srcPos the position in {@code src}, in boolean unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination int
+ * @param dstPos the position of the lsb, in bits, in the result int
+ * @param nBools the number of booleans to convert
+ * @return a int containing the selected bits
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 32}
+ * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
+ */
+ public static int binaryToInt(final boolean[] src, final int srcPos, final int dstInit, final int dstPos,
+ final int nBools) {
+ if (src.length == 0 && srcPos == 0 || 0 == nBools) {
+ return dstInit;
+ }
+ if (nBools - 1 + dstPos >= 32) {
+ throw new IllegalArgumentException("nBools-1+dstPos is greather or equal to than 32");
+ }
+ int out = dstInit;
+ for (int i = 0; i < nBools; i++) {
+ final int shift = i + dstPos;
+ final int bits = (src[i + srcPos] ? 1 : 0) << shift;
+ final int mask = 0x1 << shift;
+ out = (out & ~mask) | bits;
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts binary (represented as boolean array) into a short using the default (little
+ * endian, Lsb0) byte and bit ordering.
+ *
+ *
+ * @param src the binary to convert
+ * @param srcPos the position in {@code src}, in boolean unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination short
+ * @param dstPos the position of the lsb, in bits, in the result short
+ * @param nBools the number of booleans to convert
+ * @return a short containing the selected bits
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 16}
+ * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
+ */
+ public static short binaryToShort(final boolean[] src, final int srcPos, final short dstInit, final int dstPos,
+ final int nBools) {
+ if (src.length == 0 && srcPos == 0 || 0 == nBools) {
+ return dstInit;
+ }
+ if (nBools - 1 + dstPos >= 16) {
+ throw new IllegalArgumentException("nBools-1+dstPos is greather or equal to than 16");
+ }
+ short out = dstInit;
+ for (int i = 0; i < nBools; i++) {
+ final int shift = i + dstPos;
+ final int bits = (src[i + srcPos] ? 1 : 0) << shift;
+ final int mask = 0x1 << shift;
+ out = (short) ((out & ~mask) | bits);
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts binary (represented as boolean array) into a byte using the default (little
+ * endian, Lsb0) byte and bit ordering.
+ *
+ *
+ * @param src the binary to convert
+ * @param srcPos the position in {@code src}, in boolean unit, from where to start the
+ * conversion
+ * @param dstInit initial value of the destination byte
+ * @param dstPos the position of the lsb, in bits, in the result byte
+ * @param nBools the number of booleans to convert
+ * @return a byte containing the selected bits
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws IllegalArgumentException if {@code nBools-1+dstPos >= 8}
+ * @throws ArrayIndexOutOfBoundsException if {@code srcPos + nBools > src.length}
+ */
+ public static byte binaryToByte(final boolean[] src, final int srcPos, final byte dstInit, final int dstPos,
+ final int nBools) {
+ if (src.length == 0 && srcPos == 0 || 0 == nBools) {
+ return dstInit;
+ }
+ if (nBools - 1 + dstPos >= 8) {
+ throw new IllegalArgumentException("nBools-1+dstPos is greather or equal to than 8");
+ }
+ byte out = dstInit;
+ for (int i = 0; i < nBools; i++) {
+ final int shift = i + dstPos;
+ final int bits = (src[i + srcPos] ? 1 : 0) << shift;
+ final int mask = 0x1 << shift;
+ out = (byte) ((out & ~mask) | bits);
+ }
+ return out;
+ }
+
+ /**
+ *
+ * Converts a long into an array of int using the default (little endian, Lsb0) byte and bit
+ * ordering.
+ *
+ *
+ * @param src the long to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nInts the number of ints to copy to {@code dst}, must be smaller or equal to the
+ * width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null} and {@code nInts > 0}
+ * @throws IllegalArgumentException if {@code (nInts-1)*32+srcPos >= 64}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nInts > dst.length}
+ */
+ public static int[] longToIntArray(final long src, final int srcPos, final int[] dst, final int dstPos,
+ final int nInts) {
+ if (0 == nInts) {
+ return dst;
+ }
+ if ((nInts - 1) * 32 + srcPos >= 64) {
+ throw new IllegalArgumentException("(nInts-1)*32+srcPos is greather or equal to than 64");
+ }
+ for (int i = 0; i < nInts; i++) {
+ final int shift = i * 32 + srcPos;
+ dst[dstPos + i] = (int) (0xffffffff & (src >> shift));
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts a long into an array of short using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the long to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nShorts the number of shorts to copy to {@code dst}, must be smaller or equal to
+ * the width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null}
+ * @throws IllegalArgumentException if {@code (nShorts-1)*16+srcPos >= 64}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nShorts > dst.length}
+ */
+ public static short[] longToShortArray(final long src, final int srcPos, final short[] dst, final int dstPos,
+ final int nShorts) {
+ if (0 == nShorts) {
+ return dst;
+ }
+ if ((nShorts - 1) * 16 + srcPos >= 64) {
+ throw new IllegalArgumentException("(nShorts-1)*16+srcPos is greather or equal to than 64");
+ }
+ for (int i = 0; i < nShorts; i++) {
+ final int shift = i * 16 + srcPos;
+ dst[dstPos + i] = (short) (0xffff & (src >> shift));
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts a int into an array of short using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the int to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nShorts the number of shorts to copy to {@code dst}, must be smaller or equal to
+ * the width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null}
+ * @throws IllegalArgumentException if {@code (nShorts-1)*16+srcPos >= 32}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nShorts > dst.length}
+ */
+ public static short[] intToShortArray(final int src, final int srcPos, final short[] dst, final int dstPos,
+ final int nShorts) {
+ if (0 == nShorts) {
+ return dst;
+ }
+ if ((nShorts - 1) * 16 + srcPos >= 32) {
+ throw new IllegalArgumentException("(nShorts-1)*16+srcPos is greather or equal to than 32");
+ }
+ for (int i = 0; i < nShorts; i++) {
+ final int shift = i * 16 + srcPos;
+ dst[dstPos + i] = (short) (0xffff & (src >> shift));
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts a long into an array of byte using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the long to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
+ * width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null}
+ * @throws IllegalArgumentException if {@code (nBytes-1)*8+srcPos >= 64}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
+ */
+ public static byte[] longToByteArray(final long src, final int srcPos, final byte[] dst, final int dstPos,
+ final int nBytes) {
+ if (0 == nBytes) {
+ return dst;
+ }
+ if ((nBytes - 1) * 8 + srcPos >= 64) {
+ throw new IllegalArgumentException("(nBytes-1)*8+srcPos is greather or equal to than 64");
+ }
+ for (int i = 0; i < nBytes; i++) {
+ final int shift = i * 8 + srcPos;
+ dst[dstPos + i] = (byte) (0xff & (src >> shift));
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts a int into an array of byte using the default (little endian, Lsb0) byte and bit
+ * ordering.
+ *
+ *
+ * @param src the int to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
+ * width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null}
+ * @throws IllegalArgumentException if {@code (nBytes-1)*8+srcPos >= 32}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
+ */
+ public static byte[] intToByteArray(final int src, final int srcPos, final byte[] dst, final int dstPos,
+ final int nBytes) {
+ if (0 == nBytes) {
+ return dst;
+ }
+ if ((nBytes - 1) * 8 + srcPos >= 32) {
+ throw new IllegalArgumentException("(nBytes-1)*8+srcPos is greather or equal to than 32");
+ }
+ for (int i = 0; i < nBytes; i++) {
+ final int shift = i * 8 + srcPos;
+ dst[dstPos + i] = (byte) (0xff & (src >> shift));
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts a short into an array of byte using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the short to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
+ * width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null}
+ * @throws IllegalArgumentException if {@code (nBytes-1)*8+srcPos >= 16}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
+ */
+ public static byte[] shortToByteArray(final short src, final int srcPos, final byte[] dst, final int dstPos,
+ final int nBytes) {
+ if (0 == nBytes) {
+ return dst;
+ }
+ if ((nBytes - 1) * 8 + srcPos >= 16) {
+ throw new IllegalArgumentException("(nBytes-1)*8+srcPos is greather or equal to than 16");
+ }
+ for (int i = 0; i < nBytes; i++) {
+ final int shift = i * 8 + srcPos;
+ dst[dstPos + i] = (byte) (0xff & (src >> shift));
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts a long into an array of Char using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the long to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dstInit the initial value for the result String
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
+ * width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 64}
+ * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
+ */
+ public static String longToHex(final long src, final int srcPos, final String dstInit, final int dstPos,
+ final int nHexs) {
+ if (0 == nHexs) {
+ return dstInit;
+ }
+ if ((nHexs - 1) * 4 + srcPos >= 64) {
+ throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greather or equal to than 64");
+ }
+ final StringBuilder sb = new StringBuilder(dstInit);
+ int append = sb.length();
+ for (int i = 0; i < nHexs; i++) {
+ final int shift = i * 4 + srcPos;
+ final int bits = (int) (0xF & (src >> shift));
+ if (dstPos + i == append) {
+ ++append;
+ sb.append(intToHexDigit(bits));
+ } else {
+ sb.setCharAt(dstPos + i, intToHexDigit(bits));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ *
+ * Converts a int into an array of Char using the default (little endian, Lsb0) byte and bit
+ * ordering.
+ *
+ *
+ * @param src the int to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dstInit the initial value for the result String
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
+ * width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 32}
+ * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
+ */
+ public static String intToHex(final int src, final int srcPos, final String dstInit, final int dstPos,
+ final int nHexs) {
+ if (0 == nHexs) {
+ return dstInit;
+ }
+ if ((nHexs - 1) * 4 + srcPos >= 32) {
+ throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greather or equal to than 32");
+ }
+ final StringBuilder sb = new StringBuilder(dstInit);
+ int append = sb.length();
+ for (int i = 0; i < nHexs; i++) {
+ final int shift = i * 4 + srcPos;
+ final int bits = 0xF & (src >> shift);
+ if (dstPos + i == append) {
+ ++append;
+ sb.append(intToHexDigit(bits));
+ } else {
+ sb.setCharAt(dstPos + i, intToHexDigit(bits));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ *
+ * Converts a short into an array of Char using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the short to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dstInit the initial value for the result String
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
+ * width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 16}
+ * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
+ */
+ public static String shortToHex(final short src, final int srcPos, final String dstInit, final int dstPos,
+ final int nHexs) {
+ if (0 == nHexs) {
+ return dstInit;
+ }
+ if ((nHexs - 1) * 4 + srcPos >= 16) {
+ throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greather or equal to than 16");
+ }
+ final StringBuilder sb = new StringBuilder(dstInit);
+ int append = sb.length();
+ for (int i = 0; i < nHexs; i++) {
+ final int shift = i * 4 + srcPos;
+ final int bits = 0xF & (src >> shift);
+ if (dstPos + i == append) {
+ ++append;
+ sb.append(intToHexDigit(bits));
+ } else {
+ sb.setCharAt(dstPos + i, intToHexDigit(bits));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ *
+ * Converts a byte into an array of Char using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the byte to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dstInit the initial value for the result String
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nHexs the number of Chars to copy to {@code dst}, must be smaller or equal to the
+ * width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws IllegalArgumentException if {@code (nHexs-1)*4+srcPos >= 8}
+ * @throws StringIndexOutOfBoundsException if {@code dst.init.length() < dstPos}
+ */
+ public static String byteToHex(final byte src, final int srcPos, final String dstInit, final int dstPos,
+ final int nHexs) {
+ if (0 == nHexs) {
+ return dstInit;
+ }
+ if ((nHexs - 1) * 4 + srcPos >= 8) {
+ throw new IllegalArgumentException("(nHexs-1)*4+srcPos is greather or equal to than 8");
+ }
+ final StringBuilder sb = new StringBuilder(dstInit);
+ int append = sb.length();
+ for (int i = 0; i < nHexs; i++) {
+ final int shift = i * 4 + srcPos;
+ final int bits = 0xF & (src >> shift);
+ if (dstPos + i == append) {
+ ++append;
+ sb.append(intToHexDigit(bits));
+ } else {
+ sb.setCharAt(dstPos + i, intToHexDigit(bits));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ *
+ * Converts a long into an array of boolean using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the long to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
+ * the width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null}
+ * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 64}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
+ */
+ public static boolean[] longToBinary(final long src, final int srcPos, final boolean[] dst, final int dstPos,
+ final int nBools) {
+ if (0 == nBools) {
+ return dst;
+ }
+ if (nBools - 1 + srcPos >= 64) {
+ throw new IllegalArgumentException("nBools-1+srcPos is greather or equal to than 64");
+ }
+ for (int i = 0; i < nBools; i++) {
+ final int shift = i + srcPos;
+ dst[dstPos + i] = (0x1 & (src >> shift)) != 0;
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts a int into an array of boolean using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the int to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
+ * the width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null}
+ * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 32}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
+ */
+ public static boolean[] intToBinary(final int src, final int srcPos, final boolean[] dst, final int dstPos,
+ final int nBools) {
+ if (0 == nBools) {
+ return dst;
+ }
+ if (nBools - 1 + srcPos >= 32) {
+ throw new IllegalArgumentException("nBools-1+srcPos is greather or equal to than 32");
+ }
+ for (int i = 0; i < nBools; i++) {
+ final int shift = i + srcPos;
+ dst[dstPos + i] = (0x1 & (src >> shift)) != 0;
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts a short into an array of boolean using the default (little endian, Lsb0) byte
+ * and bit ordering.
+ *
+ *
+ * @param src the short to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
+ * the width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null}
+ * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 16}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
+ */
+ public static boolean[] shortToBinary(final short src, final int srcPos, final boolean[] dst, final int dstPos,
+ final int nBools) {
+ if (0 == nBools) {
+ return dst;
+ }
+ if (nBools - 1 + srcPos >= 16) {
+ throw new IllegalArgumentException("nBools-1+srcPos is greather or equal to than 16");
+ }
+ assert (nBools - 1) < 16 - srcPos;
+ for (int i = 0; i < nBools; i++) {
+ final int shift = i + srcPos;
+ dst[dstPos + i] = (0x1 & (src >> shift)) != 0;
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts a byte into an array of boolean using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the byte to convert
+ * @param srcPos the position in {@code src}, in bits, from where to start the conversion
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nBools the number of booleans to copy to {@code dst}, must be smaller or equal to
+ * the width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null}
+ * @throws IllegalArgumentException if {@code nBools-1+srcPos >= 8}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBools > dst.length}
+ */
+ public static boolean[] byteToBinary(final byte src, final int srcPos, final boolean[] dst, final int dstPos,
+ final int nBools) {
+ if (0 == nBools) {
+ return dst;
+ }
+ if (nBools - 1 + srcPos >= 8) {
+ throw new IllegalArgumentException("nBools-1+srcPos is greather or equal to than 8");
+ }
+ for (int i = 0; i < nBools; i++) {
+ final int shift = i + srcPos;
+ dst[dstPos + i] = (0x1 & (src >> shift)) != 0;
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts UUID into an array of byte using the default (little endian, Lsb0) byte and bit
+ * ordering.
+ *
+ *
+ * @param src the UUID to convert
+ * @param dst the destination array
+ * @param dstPos the position in {@code dst} where to copy the result
+ * @param nBytes the number of bytes to copy to {@code dst}, must be smaller or equal to the
+ * width of the input (from srcPos to msb)
+ * @return {@code dst}
+ * @throws NullPointerException if {@code dst} is {@code null}
+ * @throws IllegalArgumentException if {@code nBytes > 16}
+ * @throws ArrayIndexOutOfBoundsException if {@code dstPos + nBytes > dst.length}
+ */
+ public static byte[] uuidToByteArray(final UUID src, final byte[] dst, final int dstPos, final int nBytes) {
+ if (0 == nBytes) {
+ return dst;
+ }
+ if (nBytes > 16) {
+ throw new IllegalArgumentException("nBytes is greather than 16");
+ }
+ longToByteArray(src.getMostSignificantBits(), 0, dst, dstPos, nBytes > 8 ? 8 : nBytes);
+ if (nBytes >= 8) {
+ longToByteArray(src.getLeastSignificantBits(), 0, dst, dstPos + 8, nBytes - 8);
+ }
+ return dst;
+ }
+
+ /**
+ *
+ * Converts bytes from an array into a UUID using the default (little endian, Lsb0) byte and
+ * bit ordering.
+ *
+ *
+ * @param src the byte array to convert
+ * @param srcPos the position in {@code src} where to copy the result from
+ * @return a UUID
+ * @throws NullPointerException if {@code src} is {@code null}
+ * @throws IllegalArgumentException if array does not contain at least 16 bytes beginning
+ * with {@code srcPos}
+ */
+ public static UUID byteArrayToUuid(final byte[] src, final int srcPos) {
+ if (src.length - srcPos < 16) {
+ throw new IllegalArgumentException("Need at least 16 bytes for UUID");
+ }
+ return new UUID(byteArrayToLong(src, srcPos, 0, 0, 8), byteArrayToLong(src, srcPos + 8, 0, 0, 8));
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/EnumUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/EnumUtils.java
new file mode 100644
index 000000000..699a21539
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/EnumUtils.java
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Utility library to provide helper methods for Java enums.
+ *
+ * #ThreadSafe#
+ *
+ * @since 3.0
+ */
+public class EnumUtils {
+
+ private static final String NULL_ELEMENTS_NOT_PERMITTED = "null elements not permitted";
+ private static final String CANNOT_STORE_S_S_VALUES_IN_S_BITS = "Cannot store %s %s values in %s bits";
+ private static final String S_DOES_NOT_SEEM_TO_BE_AN_ENUM_TYPE = "%s does not seem to be an Enum type";
+ private static final String ENUM_CLASS_MUST_BE_DEFINED = "EnumClass must be defined.";
+
+ /**
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public EnumUtils() {
+ }
+
+ /**
+ * Gets the {@code Map} of enums by name.
+ *
+ * This method is useful when you need a map of enums by name.
+ *
+ * @param the type of the enumeration
+ * @param enumClass the class of the enum to query, not null
+ * @return the modifiable map of enum names to enums, never null
+ */
+ public static > Map getEnumMap(final Class enumClass) {
+ final Map map = new LinkedHashMap();
+ for (final E e: enumClass.getEnumConstants()) {
+ map.put(e.name(), e);
+ }
+ return map;
+ }
+
+ /**
+ * Gets the {@code List} of enums.
+ *
+ * This method is useful when you need a list of enums rather than an array.
+ *
+ * @param the type of the enumeration
+ * @param enumClass the class of the enum to query, not null
+ * @return the modifiable list of enums, never null
+ */
+ public static > List getEnumList(final Class enumClass) {
+ return new ArrayList(Arrays.asList(enumClass.getEnumConstants()));
+ }
+
+ /**
+ * Checks if the specified name is a valid enum for the class.
+ *
+ * This method differs from {@link Enum#valueOf} in that checks if the name is
+ * a valid enum without needing to catch the exception.
+ *
+ * @param the type of the enumeration
+ * @param enumClass the class of the enum to query, not null
+ * @param enumName the enum name, null returns false
+ * @return true if the enum name is valid, otherwise false
+ */
+ public static > boolean isValidEnum(final Class enumClass, final String enumName) {
+ if (enumName == null) {
+ return false;
+ }
+ try {
+ Enum.valueOf(enumClass, enumName);
+ return true;
+ } catch (final IllegalArgumentException ex) {
+ return false;
+ }
+ }
+
+ /**
+ * Gets the enum for the class, returning {@code null} if not found.
+ *
+ * This method differs from {@link Enum#valueOf} in that it does not throw an exception
+ * for an invalid enum name.
+ *
+ * @param the type of the enumeration
+ * @param enumClass the class of the enum to query, not null
+ * @param enumName the enum name, null returns null
+ * @return the enum, null if not found
+ */
+ public static > E getEnum(final Class enumClass, final String enumName) {
+ if (enumName == null) {
+ return null;
+ }
+ try {
+ return Enum.valueOf(enumClass, enumName);
+ } catch (final IllegalArgumentException ex) {
+ return null;
+ }
+ }
+
+ /**
+ * Creates a long bit vector representation of the given subset of an Enum.
+ *
+ * This generates a value that is usable by {@link EnumUtils#processBitVector}.
+ *
+ * Do not use this method if you have more than 64 values in your Enum, as this
+ * would create a value greater than a long can hold.
+ *
+ * @param enumClass the class of the enum we are working with, not {@code null}
+ * @param values the values we want to convert, not {@code null}, neither containing {@code null}
+ * @param the type of the enumeration
+ * @return a long whose value provides a binary representation of the given set of enum values.
+ * @throws NullPointerException if {@code enumClass} or {@code values} is {@code null}
+ * @throws IllegalArgumentException if {@code enumClass} is not an enum class or has more than 64 values,
+ * or if any {@code values} {@code null}
+ * @since 3.0.1
+ * @see #generateBitVectors(Class, Iterable)
+ */
+ public static > long generateBitVector(final Class enumClass, final Iterable extends E> values) {
+ checkBitVectorable(enumClass);
+ Validate.notNull(values);
+ long total = 0;
+ for (final E constant : values) {
+ Validate.isTrue(constant != null, NULL_ELEMENTS_NOT_PERMITTED);
+ total |= 1L << constant.ordinal();
+ }
+ return total;
+ }
+
+ /**
+ * Creates a bit vector representation of the given subset of an Enum using as many {@code long}s as needed.
+ *
+ * This generates a value that is usable by {@link EnumUtils#processBitVectors}.
+ *
+ * Use this method if you have more than 64 values in your Enum.
+ *
+ * @param enumClass the class of the enum we are working with, not {@code null}
+ * @param values the values we want to convert, not {@code null}, neither containing {@code null}
+ * @param the type of the enumeration
+ * @return a long[] whose values provide a binary representation of the given set of enum values
+ * with least significant digits rightmost.
+ * @throws NullPointerException if {@code enumClass} or {@code values} is {@code null}
+ * @throws IllegalArgumentException if {@code enumClass} is not an enum class, or if any {@code values} {@code null}
+ * @since 3.2
+ */
+ public static > long[] generateBitVectors(final Class enumClass, final Iterable extends E> values) {
+ asEnum(enumClass);
+ Validate.notNull(values);
+ final EnumSet condensed = EnumSet.noneOf(enumClass);
+ for (final E constant : values) {
+ Validate.isTrue(constant != null, NULL_ELEMENTS_NOT_PERMITTED);
+ condensed.add(constant);
+ }
+ final long[] result = new long[(enumClass.getEnumConstants().length - 1) / Long.SIZE + 1];
+ for (final E value : condensed) {
+ result[value.ordinal() / Long.SIZE] |= 1L << (value.ordinal() % Long.SIZE);
+ }
+ ArrayUtils.reverse(result);
+ return result;
+ }
+
+ /**
+ * Creates a long bit vector representation of the given array of Enum values.
+ *
+ * This generates a value that is usable by {@link EnumUtils#processBitVector}.
+ *
+ * Do not use this method if you have more than 64 values in your Enum, as this
+ * would create a value greater than a long can hold.
+ *
+ * @param enumClass the class of the enum we are working with, not {@code null}
+ * @param values the values we want to convert, not {@code null}
+ * @param the type of the enumeration
+ * @return a long whose value provides a binary representation of the given set of enum values.
+ * @throws NullPointerException if {@code enumClass} or {@code values} is {@code null}
+ * @throws IllegalArgumentException if {@code enumClass} is not an enum class or has more than 64 values
+ * @since 3.0.1
+ * @see #generateBitVectors(Class, Iterable)
+ */
+ public static > long generateBitVector(final Class enumClass, final E... values) {
+ Validate.noNullElements(values);
+ return generateBitVector(enumClass, Arrays. asList(values));
+ }
+
+ /**
+ * Creates a bit vector representation of the given subset of an Enum using as many {@code long}s as needed.
+ *
+ * This generates a value that is usable by {@link EnumUtils#processBitVectors}.
+ *
+ * Use this method if you have more than 64 values in your Enum.
+ *
+ * @param enumClass the class of the enum we are working with, not {@code null}
+ * @param values the values we want to convert, not {@code null}, neither containing {@code null}
+ * @param the type of the enumeration
+ * @return a long[] whose values provide a binary representation of the given set of enum values
+ * with least significant digits rightmost.
+ * @throws NullPointerException if {@code enumClass} or {@code values} is {@code null}
+ * @throws IllegalArgumentException if {@code enumClass} is not an enum class, or if any {@code values} {@code null}
+ * @since 3.2
+ */
+ public static > long[] generateBitVectors(final Class enumClass, final E... values) {
+ asEnum(enumClass);
+ Validate.noNullElements(values);
+ final EnumSet condensed = EnumSet.noneOf(enumClass);
+ Collections.addAll(condensed, values);
+ final long[] result = new long[(enumClass.getEnumConstants().length - 1) / Long.SIZE + 1];
+ for (final E value : condensed) {
+ result[value.ordinal() / Long.SIZE] |= 1L << (value.ordinal() % Long.SIZE);
+ }
+ ArrayUtils.reverse(result);
+ return result;
+ }
+
+ /**
+ * Convert a long value created by {@link EnumUtils#generateBitVector} into the set of
+ * enum values that it represents.
+ *
+ * If you store this value, beware any changes to the enum that would affect ordinal values.
+ * @param enumClass the class of the enum we are working with, not {@code null}
+ * @param value the long value representation of a set of enum values
+ * @param the type of the enumeration
+ * @return a set of enum values
+ * @throws NullPointerException if {@code enumClass} is {@code null}
+ * @throws IllegalArgumentException if {@code enumClass} is not an enum class or has more than 64 values
+ * @since 3.0.1
+ */
+ public static > EnumSet processBitVector(final Class enumClass, final long value) {
+ checkBitVectorable(enumClass).getEnumConstants();
+ return processBitVectors(enumClass, value);
+ }
+
+ /**
+ * Convert a {@code long[]} created by {@link EnumUtils#generateBitVectors} into the set of
+ * enum values that it represents.
+ *
+ * If you store this value, beware any changes to the enum that would affect ordinal values.
+ * @param enumClass the class of the enum we are working with, not {@code null}
+ * @param values the long[] bearing the representation of a set of enum values, least significant digits rightmost, not {@code null}
+ * @param the type of the enumeration
+ * @return a set of enum values
+ * @throws NullPointerException if {@code enumClass} is {@code null}
+ * @throws IllegalArgumentException if {@code enumClass} is not an enum class
+ * @since 3.2
+ */
+ public static > EnumSet processBitVectors(final Class enumClass, final long... values) {
+ final EnumSet results = EnumSet.noneOf(asEnum(enumClass));
+ final long[] lvalues = ArrayUtils.clone(Validate.notNull(values));
+ ArrayUtils.reverse(lvalues);
+ for (final E constant : enumClass.getEnumConstants()) {
+ final int block = constant.ordinal() / Long.SIZE;
+ if (block < lvalues.length && (lvalues[block] & 1L << (constant.ordinal() % Long.SIZE)) != 0) {
+ results.add(constant);
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Validate that {@code enumClass} is compatible with representation in a {@code long}.
+ * @param the type of the enumeration
+ * @param enumClass to check
+ * @return {@code enumClass}
+ * @throws NullPointerException if {@code enumClass} is {@code null}
+ * @throws IllegalArgumentException if {@code enumClass} is not an enum class or has more than 64 values
+ * @since 3.0.1
+ */
+ private static > Class checkBitVectorable(final Class enumClass) {
+ final E[] constants = asEnum(enumClass).getEnumConstants();
+ Validate.isTrue(constants.length <= Long.SIZE, CANNOT_STORE_S_S_VALUES_IN_S_BITS,
+ Integer.valueOf(constants.length), enumClass.getSimpleName(), Integer.valueOf(Long.SIZE));
+
+ return enumClass;
+ }
+
+ /**
+ * Validate {@code enumClass}.
+ * @param the type of the enumeration
+ * @param enumClass to check
+ * @return {@code enumClass}
+ * @throws NullPointerException if {@code enumClass} is {@code null}
+ * @throws IllegalArgumentException if {@code enumClass} is not an enum class
+ * @since 3.2
+ */
+ private static > Class asEnum(final Class enumClass) {
+ Validate.notNull(enumClass, ENUM_CLASS_MUST_BE_DEFINED);
+ Validate.isTrue(enumClass.isEnum(), S_DOES_NOT_SEEM_TO_BE_AN_ENUM_TYPE, enumClass);
+ return enumClass;
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/JavaVersion.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/JavaVersion.java
new file mode 100644
index 000000000..4dd7e46af
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/JavaVersion.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import org.apache.commons.lang3.math.NumberUtils;
+
+/**
+ * An enum representing all the versions of the Java specification.
+ * This is intended to mirror available values from the
+ * java.specification.version System property.
+ *
+ * @since 3.0
+ */
+public enum JavaVersion {
+
+ /**
+ * The Java version reported by Android. This is not an official Java version number.
+ */
+ JAVA_0_9(1.5f, "0.9"),
+
+ /**
+ * Java 1.1.
+ */
+ JAVA_1_1(1.1f, "1.1"),
+
+ /**
+ * Java 1.2.
+ */
+ JAVA_1_2(1.2f, "1.2"),
+
+ /**
+ * Java 1.3.
+ */
+ JAVA_1_3(1.3f, "1.3"),
+
+ /**
+ * Java 1.4.
+ */
+ JAVA_1_4(1.4f, "1.4"),
+
+ /**
+ * Java 1.5.
+ */
+ JAVA_1_5(1.5f, "1.5"),
+
+ /**
+ * Java 1.6.
+ */
+ JAVA_1_6(1.6f, "1.6"),
+
+ /**
+ * Java 1.7.
+ */
+ JAVA_1_7(1.7f, "1.7"),
+
+ /**
+ * Java 1.8.
+ */
+ JAVA_1_8(1.8f, "1.8"),
+
+ /**
+ * Java 1.9.
+ *
+ * @deprecated As of release 3.5, replaced by {@link #JAVA_9}
+ */
+ JAVA_1_9(9.0f, "9"),
+
+ /**
+ * Java 9
+ */
+ JAVA_9(9.0f, "9"),
+
+ /**
+ * The most recent java version. Mainly introduced to avoid to break when a new version of Java is used.
+ */
+ JAVA_RECENT(maxVersion(), Float.toString(maxVersion()));
+
+ /**
+ * The float value.
+ */
+ private final float value;
+ /**
+ * The standard name.
+ */
+ private final String name;
+
+ /**
+ * Constructor.
+ *
+ * @param value the float value
+ * @param name the standard name, not null
+ */
+ JavaVersion(final float value, final String name) {
+ this.value = value;
+ this.name = name;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Whether this version of Java is at least the version of Java passed in.
+ *
+ * For example:
+ * {@code myVersion.atLeast(JavaVersion.JAVA_1_4)}
+ *
+ * @param requiredVersion the version to check against, not null
+ * @return true if this version is equal to or greater than the specified version
+ */
+ public boolean atLeast(final JavaVersion requiredVersion) {
+ return this.value >= requiredVersion.value;
+ }
+
+ /**
+ * Transforms the given string with a Java version number to the
+ * corresponding constant of this enumeration class. This method is used
+ * internally.
+ *
+ * @param nom the Java version as string
+ * @return the corresponding enumeration constant or null if the
+ * version is unknown
+ */
+ // helper for static importing
+ static JavaVersion getJavaVersion(final String nom) {
+ return get(nom);
+ }
+
+ /**
+ * Transforms the given string with a Java version number to the
+ * corresponding constant of this enumeration class. This method is used
+ * internally.
+ *
+ * @param nom the Java version as string
+ * @return the corresponding enumeration constant or null if the
+ * version is unknown
+ */
+ static JavaVersion get(final String nom) {
+ if ("0.9".equals(nom)) {
+ return JAVA_0_9;
+ } else if ("1.1".equals(nom)) {
+ return JAVA_1_1;
+ } else if ("1.2".equals(nom)) {
+ return JAVA_1_2;
+ } else if ("1.3".equals(nom)) {
+ return JAVA_1_3;
+ } else if ("1.4".equals(nom)) {
+ return JAVA_1_4;
+ } else if ("1.5".equals(nom)) {
+ return JAVA_1_5;
+ } else if ("1.6".equals(nom)) {
+ return JAVA_1_6;
+ } else if ("1.7".equals(nom)) {
+ return JAVA_1_7;
+ } else if ("1.8".equals(nom)) {
+ return JAVA_1_8;
+ } else if ("9".equals(nom)) {
+ return JAVA_9;
+ }
+ if (nom == null) {
+ return null;
+ }
+ final float v = toFloatVersion(nom);
+ if ((v - 1.) < 1.) { // then we need to check decimals > .9
+ final int firstComma = Math.max(nom.indexOf('.'), nom.indexOf(','));
+ final int end = Math.max(nom.length(), nom.indexOf(',', firstComma));
+ if (Float.parseFloat(nom.substring(firstComma + 1, end)) > .9f) {
+ return JAVA_RECENT;
+ }
+ }
+ return null;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ *
The string value is overridden to return the standard name.
+ *
+ * For example, "1.5"
.
+ *
+ * @return the name, not null
+ */
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * Gets the Java Version from the system or 99.0 if the {@code java.specification.version} system property is not set.
+ *
+ * @return the value of {@code java.specification.version} system property or 99.0 if it is not set.
+ */
+ private static float maxVersion() {
+ final float v = toFloatVersion(System.getProperty("java.specification.version", "99.0"));
+ if (v > 0) {
+ return v;
+ }
+ return 99f;
+ }
+
+ /**
+ * Parses a float value from a String.
+ *
+ * @param value the String to parse.
+ * @return the float value represented by the string or -1 if the given String can not be parsed.
+ */
+ private static float toFloatVersion(final String value) {
+ final int defaultReturnValue = -1;
+ if (value.contains(".")) {
+ final String[] toParse = value.split("\\.");
+ if (toParse.length >= 2) {
+ return NumberUtils.toFloat(toParse[0] + '.' + toParse[1], defaultReturnValue);
+ }
+ } else {
+ return NumberUtils.toFloat(value, defaultReturnValue);
+ }
+ return defaultReturnValue;
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/LocaleUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/LocaleUtils.java
new file mode 100644
index 000000000..418537394
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/LocaleUtils.java
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Operations to assist when working with a {@link Locale}.
+ *
+ * This class tries to handle {@code null} input gracefully.
+ * An exception will not be thrown for a {@code null} input.
+ * Each method documents its behaviour in more detail.
+ *
+ * @since 2.2
+ */
+public class LocaleUtils {
+
+ /** Concurrent map of language locales by country. */
+ private static final ConcurrentMap> cLanguagesByCountry =
+ new ConcurrentHashMap>();
+
+ /** Concurrent map of country locales by language. */
+ private static final ConcurrentMap> cCountriesByLanguage =
+ new ConcurrentHashMap>();
+
+ /**
+ * {@code LocaleUtils} instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as {@code LocaleUtils.toLocale("en_GB");}.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public LocaleUtils() {
+ super();
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Converts a String to a Locale.
+ *
+ * This method takes the string format of a locale and creates the
+ * locale object from it.
+ *
+ *
+ * LocaleUtils.toLocale("") = new Locale("", "")
+ * LocaleUtils.toLocale("en") = new Locale("en", "")
+ * LocaleUtils.toLocale("en_GB") = new Locale("en", "GB")
+ * LocaleUtils.toLocale("en_GB_xxx") = new Locale("en", "GB", "xxx") (#)
+ *
+ *
+ * (#) The behaviour of the JDK variant constructor changed between JDK1.3 and JDK1.4.
+ * In JDK1.3, the constructor upper cases the variant, in JDK1.4, it doesn't.
+ * Thus, the result from getVariant() may vary depending on your JDK.
+ *
+ * This method validates the input strictly.
+ * The language code must be lowercase.
+ * The country code must be uppercase.
+ * The separator must be an underscore.
+ * The length must be correct.
+ *
+ *
+ * @param str the locale String to convert, null returns null
+ * @return a Locale, null if null input
+ * @throws IllegalArgumentException if the string is an invalid format
+ * @see Locale#forLanguageTag(String)
+ */
+ public static Locale toLocale(final String str) {
+ if (str == null) {
+ return null;
+ }
+ if (str.isEmpty()) { // LANG-941 - JDK 8 introduced an empty locale where all fields are blank
+ return new Locale(StringUtils.EMPTY, StringUtils.EMPTY);
+ }
+ if (str.contains("#")) { // LANG-879 - Cannot handle Java 7 script & extensions
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ final int len = str.length();
+ if (len < 2) {
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ final char ch0 = str.charAt(0);
+ if (ch0 == '_') {
+ if (len < 3) {
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ final char ch1 = str.charAt(1);
+ final char ch2 = str.charAt(2);
+ if (!Character.isUpperCase(ch1) || !Character.isUpperCase(ch2)) {
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ if (len == 3) {
+ return new Locale(StringUtils.EMPTY, str.substring(1, 3));
+ }
+ if (len < 5) {
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ if (str.charAt(3) != '_') {
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ return new Locale(StringUtils.EMPTY, str.substring(1, 3), str.substring(4));
+ }
+
+ final String[] split = str.split("_", -1);
+ final int occurrences = split.length -1;
+ switch (occurrences) {
+ case 0:
+ if (StringUtils.isAllLowerCase(str) && (len == 2 || len == 3)) {
+ return new Locale(str);
+ }
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+
+ case 1:
+ if (StringUtils.isAllLowerCase(split[0]) &&
+ (split[0].length() == 2 || split[0].length() == 3) &&
+ split[1].length() == 2 && StringUtils.isAllUpperCase(split[1])) {
+ return new Locale(split[0], split[1]);
+ }
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+
+ case 2:
+ if (StringUtils.isAllLowerCase(split[0]) &&
+ (split[0].length() == 2 || split[0].length() == 3) &&
+ (split[1].length() == 0 || split[1].length() == 2 && StringUtils.isAllUpperCase(split[1])) &&
+ split[2].length() > 0) {
+ return new Locale(split[0], split[1], split[2]);
+ }
+
+ //$FALL-THROUGH$
+ default:
+ throw new IllegalArgumentException("Invalid locale format: " + str);
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains the list of locales to search through when performing
+ * a locale search.
+ *
+ *
+ * localeLookupList(Locale("fr","CA","xxx"))
+ * = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr")]
+ *
+ *
+ * @param locale the locale to start from
+ * @return the unmodifiable list of Locale objects, 0 being locale, not null
+ */
+ public static List localeLookupList(final Locale locale) {
+ return localeLookupList(locale, locale);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains the list of locales to search through when performing
+ * a locale search.
+ *
+ *
+ * localeLookupList(Locale("fr", "CA", "xxx"), Locale("en"))
+ * = [Locale("fr","CA","xxx"), Locale("fr","CA"), Locale("fr"), Locale("en"]
+ *
+ *
+ * The result list begins with the most specific locale, then the
+ * next more general and so on, finishing with the default locale.
+ * The list will never contain the same locale twice.
+ *
+ * @param locale the locale to start from, null returns empty list
+ * @param defaultLocale the default locale to use if no other is found
+ * @return the unmodifiable list of Locale objects, 0 being locale, not null
+ */
+ public static List localeLookupList(final Locale locale, final Locale defaultLocale) {
+ final List list = new ArrayList(4);
+ if (locale != null) {
+ list.add(locale);
+ if (locale.getVariant().length() > 0) {
+ list.add(new Locale(locale.getLanguage(), locale.getCountry()));
+ }
+ if (locale.getCountry().length() > 0) {
+ list.add(new Locale(locale.getLanguage(), StringUtils.EMPTY));
+ }
+ if (list.contains(defaultLocale) == false) {
+ list.add(defaultLocale);
+ }
+ }
+ return Collections.unmodifiableList(list);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains an unmodifiable list of installed locales.
+ *
+ * This method is a wrapper around {@link Locale#getAvailableLocales()}.
+ * It is more efficient, as the JDK method must create a new array each
+ * time it is called.
+ *
+ * @return the unmodifiable list of available locales
+ */
+ public static List availableLocaleList() {
+ return SyncAvoid.AVAILABLE_LOCALE_LIST;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains an unmodifiable set of installed locales.
+ *
+ * This method is a wrapper around {@link Locale#getAvailableLocales()}.
+ * It is more efficient, as the JDK method must create a new array each
+ * time it is called.
+ *
+ * @return the unmodifiable set of available locales
+ */
+ public static Set availableLocaleSet() {
+ return SyncAvoid.AVAILABLE_LOCALE_SET;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if the locale specified is in the list of available locales.
+ *
+ * @param locale the Locale object to check if it is available
+ * @return true if the locale is a known locale
+ */
+ public static boolean isAvailableLocale(final Locale locale) {
+ return availableLocaleList().contains(locale);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains the list of languages supported for a given country.
+ *
+ * This method takes a country code and searches to find the
+ * languages available for that country. Variant locales are removed.
+ *
+ * @param countryCode the 2 letter country code, null returns empty
+ * @return an unmodifiable List of Locale objects, not null
+ */
+ public static List languagesByCountry(final String countryCode) {
+ if (countryCode == null) {
+ return Collections.emptyList();
+ }
+ List langs = cLanguagesByCountry.get(countryCode);
+ if (langs == null) {
+ langs = new ArrayList();
+ final List locales = availableLocaleList();
+ for (int i = 0; i < locales.size(); i++) {
+ final Locale locale = locales.get(i);
+ if (countryCode.equals(locale.getCountry()) &&
+ locale.getVariant().isEmpty()) {
+ langs.add(locale);
+ }
+ }
+ langs = Collections.unmodifiableList(langs);
+ cLanguagesByCountry.putIfAbsent(countryCode, langs);
+ langs = cLanguagesByCountry.get(countryCode);
+ }
+ return langs;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Obtains the list of countries supported for a given language.
+ *
+ * This method takes a language code and searches to find the
+ * countries available for that language. Variant locales are removed.
+ *
+ * @param languageCode the 2 letter language code, null returns empty
+ * @return an unmodifiable List of Locale objects, not null
+ */
+ public static List countriesByLanguage(final String languageCode) {
+ if (languageCode == null) {
+ return Collections.emptyList();
+ }
+ List countries = cCountriesByLanguage.get(languageCode);
+ if (countries == null) {
+ countries = new ArrayList();
+ final List locales = availableLocaleList();
+ for (int i = 0; i < locales.size(); i++) {
+ final Locale locale = locales.get(i);
+ if (languageCode.equals(locale.getLanguage()) &&
+ locale.getCountry().length() != 0 &&
+ locale.getVariant().isEmpty()) {
+ countries.add(locale);
+ }
+ }
+ countries = Collections.unmodifiableList(countries);
+ cCountriesByLanguage.putIfAbsent(languageCode, countries);
+ countries = cCountriesByLanguage.get(languageCode);
+ }
+ return countries;
+ }
+
+ //-----------------------------------------------------------------------
+ // class to avoid synchronization (Init on demand)
+ static class SyncAvoid {
+ /** Unmodifiable list of available locales. */
+ private static final List AVAILABLE_LOCALE_LIST;
+ /** Unmodifiable set of available locales. */
+ private static final Set AVAILABLE_LOCALE_SET;
+
+ static {
+ final List list = new ArrayList(Arrays.asList(Locale.getAvailableLocales())); // extra safe
+ AVAILABLE_LOCALE_LIST = Collections.unmodifiableList(list);
+ AVAILABLE_LOCALE_SET = Collections.unmodifiableSet(new HashSet(list));
+ }
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/NotImplementedException.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/NotImplementedException.java
new file mode 100644
index 000000000..82e3784e8
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/NotImplementedException.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+/**
+ * Thrown to indicate that a block of code has not been implemented.
+ * This exception supplements UnsupportedOperationException
+ * by providing a more semantically rich description of the problem.
+ *
+ * NotImplementedException
represents the case where the
+ * author has yet to implement the logic at this point in the program.
+ * This can act as an exception based TODO tag.
+ *
+ *
+ * public void foo() {
+ * try {
+ * // do something that throws an Exception
+ * } catch (Exception ex) {
+ * // don't know what to do here yet
+ * throw new NotImplementedException("TODO", ex);
+ * }
+ * }
+ *
+ *
+ * This class was originally added in Lang 2.0, but removed in 3.0.
+ *
+ * @since 3.2
+ */
+public class NotImplementedException extends UnsupportedOperationException {
+
+ private static final long serialVersionUID = 20131021L;
+
+ private final String code;
+
+ /**
+ * Constructs a NotImplementedException.
+ *
+ * @param message description of the exception
+ * @since 3.2
+ */
+ public NotImplementedException(final String message) {
+ this(message, (String) null);
+ }
+
+ /**
+ * Constructs a NotImplementedException.
+ *
+ * @param cause cause of the exception
+ * @since 3.2
+ */
+ public NotImplementedException(final Throwable cause) {
+ this(cause, null);
+ }
+
+ /**
+ * Constructs a NotImplementedException.
+ *
+ * @param message description of the exception
+ * @param cause cause of the exception
+ * @since 3.2
+ */
+ public NotImplementedException(final String message, final Throwable cause) {
+ this(message, cause, null);
+ }
+
+ /**
+ * Constructs a NotImplementedException.
+ *
+ * @param message description of the exception
+ * @param code code indicating a resource for more information regarding the lack of implementation
+ * @since 3.2
+ */
+ public NotImplementedException(final String message, final String code) {
+ super(message);
+ this.code = code;
+ }
+
+ /**
+ * Constructs a NotImplementedException.
+ *
+ * @param cause cause of the exception
+ * @param code code indicating a resource for more information regarding the lack of implementation
+ * @since 3.2
+ */
+ public NotImplementedException(final Throwable cause, final String code) {
+ super(cause);
+ this.code = code;
+ }
+
+ /**
+ * Constructs a NotImplementedException.
+ *
+ * @param message description of the exception
+ * @param cause cause of the exception
+ * @param code code indicating a resource for more information regarding the lack of implementation
+ * @since 3.2
+ */
+ public NotImplementedException(final String message, final Throwable cause, final String code) {
+ super(message, cause);
+ this.code = code;
+ }
+
+ /**
+ * Obtain the not implemented code. This is an unformatted piece of text intended to point to
+ * further information regarding the lack of implementation. It might, for example, be an issue
+ * tracker ID or a URL.
+ *
+ * @return a code indicating a resource for more information regarding the lack of implementation
+ */
+ public String getCode() {
+ return this.code;
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ObjectUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ObjectUtils.java
new file mode 100644
index 000000000..d328105e0
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ObjectUtils.java
@@ -0,0 +1,1016 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.apache.commons.lang3.exception.CloneFailedException;
+import org.apache.commons.lang3.mutable.MutableInt;
+import org.apache.commons.lang3.text.StrBuilder;
+
+/**
+ * Operations on {@code Object}.
+ *
+ * This class tries to handle {@code null} input gracefully.
+ * An exception will generally not be thrown for a {@code null} input.
+ * Each method documents its behaviour in more detail.
+ *
+ * #ThreadSafe#
+ * @since 1.0
+ */
+//@Immutable
+public class ObjectUtils {
+
+ /**
+ * Singleton used as a {@code null} placeholder where
+ * {@code null} has another meaning.
+ *
+ * For example, in a {@code HashMap} the
+ * {@link java.util.HashMap#get(java.lang.Object)} method returns
+ * {@code null} if the {@code Map} contains {@code null} or if there
+ * is no matching key. The {@code Null} placeholder can be used to
+ * distinguish between these two cases.
+ *
+ * Another example is {@code Hashtable}, where {@code null}
+ * cannot be stored.
+ *
+ * This instance is Serializable.
+ */
+ public static final Null NULL = new Null();
+
+ /**
+ * {@code ObjectUtils} instances should NOT be constructed in
+ * standard programming. Instead, the static methods on the class should
+ * be used, such as {@code ObjectUtils.defaultIfNull("a","b");}.
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public ObjectUtils() {
+ super();
+ }
+
+ // Defaulting
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a default value if the object passed is {@code null}.
+ *
+ *
+ * ObjectUtils.defaultIfNull(null, null) = null
+ * ObjectUtils.defaultIfNull(null, "") = ""
+ * ObjectUtils.defaultIfNull(null, "zz") = "zz"
+ * ObjectUtils.defaultIfNull("abc", *) = "abc"
+ * ObjectUtils.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
+ *
+ *
+ * @param the type of the object
+ * @param object the {@code Object} to test, may be {@code null}
+ * @param defaultValue the default value to return, may be {@code null}
+ * @return {@code object} if it is not {@code null}, defaultValue otherwise
+ */
+ public static T defaultIfNull(final T object, final T defaultValue) {
+ return object != null ? object : defaultValue;
+ }
+
+ /**
+ * Returns the first value in the array which is not {@code null}.
+ * If all the values are {@code null} or the array is {@code null}
+ * or empty then {@code null} is returned.
+ *
+ *
+ * ObjectUtils.firstNonNull(null, null) = null
+ * ObjectUtils.firstNonNull(null, "") = ""
+ * ObjectUtils.firstNonNull(null, null, "") = ""
+ * ObjectUtils.firstNonNull(null, "zz") = "zz"
+ * ObjectUtils.firstNonNull("abc", *) = "abc"
+ * ObjectUtils.firstNonNull(null, "xyz", *) = "xyz"
+ * ObjectUtils.firstNonNull(Boolean.TRUE, *) = Boolean.TRUE
+ * ObjectUtils.firstNonNull() = null
+ *
+ *
+ * @param the component type of the array
+ * @param values the values to test, may be {@code null} or empty
+ * @return the first value from {@code values} which is not {@code null},
+ * or {@code null} if there are no non-null values
+ * @since 3.0
+ */
+ public static T firstNonNull(final T... values) {
+ if (values != null) {
+ for (final T val : values) {
+ if (val != null) {
+ return val;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Checks if any value in the given array is not {@code null}.
+ *
+ *
+ * If all the values are {@code null} or the array is {@code null}
+ * or empty then {@code false} is returned. Otherwise {@code true} is returned.
+ *
+ *
+ *
+ * ObjectUtils.anyNotNull(*) = true
+ * ObjectUtils.anyNotNull(*, null) = true
+ * ObjectUtils.anyNotNull(null, *) = true
+ * ObjectUtils.anyNotNull(null, null, *, *) = true
+ * ObjectUtils.anyNotNull(null) = false
+ * ObjectUtils.anyNotNull(null, null) = false
+ *
+ *
+ * @param values the values to test, may be {@code null} or empty
+ * @return {@code true} if there is at least one non-null value in the array,
+ * {@code false} if all values in the array are {@code null}s.
+ * If the array is {@code null} or empty {@code false} is also returned.
+ * @since 3.5
+ */
+ public static boolean anyNotNull(final Object... values) {
+ return firstNonNull(values) != null;
+ }
+
+ /**
+ * Checks if all values in the array are not {@code nulls}.
+ *
+ *
+ * If any value is {@code null} or the array is {@code null} then
+ * {@code false} is returned. If all elements in array are not
+ * {@code null} or the array is empty (contains no elements) {@code true}
+ * is returned.
+ *
+ *
+ *
+ * ObjectUtils.allNotNull(*) = true
+ * ObjectUtils.allNotNull(*, *) = true
+ * ObjectUtils.allNotNull(null) = false
+ * ObjectUtils.allNotNull(null, null) = false
+ * ObjectUtils.allNotNull(null, *) = false
+ * ObjectUtils.allNotNull(*, null) = false
+ * ObjectUtils.allNotNull(*, *, null, *) = false
+ *
+ *
+ * @param values the values to test, may be {@code null} or empty
+ * @return {@code false} if there is at least one {@code null} value in the array or the array is {@code null},
+ * {@code true} if all values in the array are not {@code null}s or array contains no elements.
+ * @since 3.5
+ */
+ public static boolean allNotNull(final Object... values) {
+ if (values == null) {
+ return false;
+ }
+
+ for (final Object val : values) {
+ if (val == null) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // Null-safe equals/hashCode
+ //-----------------------------------------------------------------------
+ /**
+ * Compares two objects for equality, where either one or both
+ * objects may be {@code null}.
+ *
+ *
+ * ObjectUtils.equals(null, null) = true
+ * ObjectUtils.equals(null, "") = false
+ * ObjectUtils.equals("", null) = false
+ * ObjectUtils.equals("", "") = true
+ * ObjectUtils.equals(Boolean.TRUE, null) = false
+ * ObjectUtils.equals(Boolean.TRUE, "true") = false
+ * ObjectUtils.equals(Boolean.TRUE, Boolean.TRUE) = true
+ * ObjectUtils.equals(Boolean.TRUE, Boolean.FALSE) = false
+ *
+ *
+ * @param object1 the first object, may be {@code null}
+ * @param object2 the second object, may be {@code null}
+ * @return {@code true} if the values of both objects are the same
+ * @deprecated this method has been replaced by {@code java.util.Objects.equals(Object, Object)} in Java 7 and will
+ * be removed from future releases.
+ */
+ @Deprecated
+ public static boolean equals(final Object object1, final Object object2) {
+ if (object1 == object2) {
+ return true;
+ }
+ if (object1 == null || object2 == null) {
+ return false;
+ }
+ return object1.equals(object2);
+ }
+
+ /**
+ * Compares two objects for inequality, where either one or both
+ * objects may be {@code null}.
+ *
+ *
+ * ObjectUtils.notEqual(null, null) = false
+ * ObjectUtils.notEqual(null, "") = true
+ * ObjectUtils.notEqual("", null) = true
+ * ObjectUtils.notEqual("", "") = false
+ * ObjectUtils.notEqual(Boolean.TRUE, null) = true
+ * ObjectUtils.notEqual(Boolean.TRUE, "true") = true
+ * ObjectUtils.notEqual(Boolean.TRUE, Boolean.TRUE) = false
+ * ObjectUtils.notEqual(Boolean.TRUE, Boolean.FALSE) = true
+ *
+ *
+ * @param object1 the first object, may be {@code null}
+ * @param object2 the second object, may be {@code null}
+ * @return {@code false} if the values of both objects are the same
+ */
+ public static boolean notEqual(final Object object1, final Object object2) {
+ return ObjectUtils.equals(object1, object2) == false;
+ }
+
+ /**
+ * Gets the hash code of an object returning zero when the
+ * object is {@code null}.
+ *
+ *
+ * ObjectUtils.hashCode(null) = 0
+ * ObjectUtils.hashCode(obj) = obj.hashCode()
+ *
+ *
+ * @param obj the object to obtain the hash code of, may be {@code null}
+ * @return the hash code of the object, or zero if null
+ * @since 2.1
+ * @deprecated this method has been replaced by {@code java.util.Objects.hashCode(Object)} in Java 7 and will be
+ * removed in future releases
+ */
+ @Deprecated
+ public static int hashCode(final Object obj) {
+ // hashCode(Object) retained for performance, as hash code is often critical
+ return obj == null ? 0 : obj.hashCode();
+ }
+
+ /**
+ * Gets the hash code for multiple objects.
+ *
+ * This allows a hash code to be rapidly calculated for a number of objects.
+ * The hash code for a single object is the not same as {@link #hashCode(Object)}.
+ * The hash code for multiple objects is the same as that calculated by an
+ * {@code ArrayList} containing the specified objects.
+ *
+ *
+ * ObjectUtils.hashCodeMulti() = 1
+ * ObjectUtils.hashCodeMulti((Object[]) null) = 1
+ * ObjectUtils.hashCodeMulti(a) = 31 + a.hashCode()
+ * ObjectUtils.hashCodeMulti(a,b) = (31 + a.hashCode()) * 31 + b.hashCode()
+ * ObjectUtils.hashCodeMulti(a,b,c) = ((31 + a.hashCode()) * 31 + b.hashCode()) * 31 + c.hashCode()
+ *
+ *
+ * @param objects the objects to obtain the hash code of, may be {@code null}
+ * @return the hash code of the objects, or zero if null
+ * @since 3.0
+ * @deprecated this method has been replaced by {@code java.util.Objects.hash(Object...)} in Java 7 and will be
+ * removed in future releases.
+ */
+ @Deprecated
+ public static int hashCodeMulti(final Object... objects) {
+ int hash = 1;
+ if (objects != null) {
+ for (final Object object : objects) {
+ final int tmpHash = ObjectUtils.hashCode(object);
+ hash = hash * 31 + tmpHash;
+ }
+ }
+ return hash;
+ }
+
+ // Identity ToString
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the toString that would be produced by {@code Object}
+ * if a class did not override toString itself. {@code null}
+ * will return {@code null}.
+ *
+ *
+ * ObjectUtils.identityToString(null) = null
+ * ObjectUtils.identityToString("") = "java.lang.String@1e23"
+ * ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
+ *
+ *
+ * @param object the object to create a toString for, may be
+ * {@code null}
+ * @return the default toString text, or {@code null} if
+ * {@code null} passed in
+ */
+ public static String identityToString(final Object object) {
+ if (object == null) {
+ return null;
+ }
+ final StringBuilder builder = new StringBuilder();
+ identityToString(builder, object);
+ return builder.toString();
+ }
+
+ /**
+ * Appends the toString that would be produced by {@code Object}
+ * if a class did not override toString itself. {@code null}
+ * will throw a NullPointerException for either of the two parameters.
+ *
+ *
+ * ObjectUtils.identityToString(appendable, "") = appendable.append("java.lang.String@1e23"
+ * ObjectUtils.identityToString(appendable, Boolean.TRUE) = appendable.append("java.lang.Boolean@7fa"
+ * ObjectUtils.identityToString(appendable, Boolean.TRUE) = appendable.append("java.lang.Boolean@7fa")
+ *
+ *
+ * @param appendable the appendable to append to
+ * @param object the object to create a toString for
+ * @throws IOException if an I/O error occurs
+ * @since 3.2
+ */
+ public static void identityToString(final Appendable appendable, final Object object) throws IOException {
+ if (object == null) {
+ throw new NullPointerException("Cannot get the toString of a null identity");
+ }
+ appendable.append(object.getClass().getName())
+ .append('@')
+ .append(Integer.toHexString(System.identityHashCode(object)));
+ }
+
+ /**
+ * Appends the toString that would be produced by {@code Object}
+ * if a class did not override toString itself. {@code null}
+ * will throw a NullPointerException for either of the two parameters.
+ *
+ *
+ * ObjectUtils.identityToString(builder, "") = builder.append("java.lang.String@1e23"
+ * ObjectUtils.identityToString(builder, Boolean.TRUE) = builder.append("java.lang.Boolean@7fa"
+ * ObjectUtils.identityToString(builder, Boolean.TRUE) = builder.append("java.lang.Boolean@7fa")
+ *
+ *
+ * @param builder the builder to append to
+ * @param object the object to create a toString for
+ * @since 3.2
+ */
+ public static void identityToString(final StrBuilder builder, final Object object) {
+ if (object == null) {
+ throw new NullPointerException("Cannot get the toString of a null identity");
+ }
+ builder.append(object.getClass().getName())
+ .append('@')
+ .append(Integer.toHexString(System.identityHashCode(object)));
+ }
+
+ /**
+ * Appends the toString that would be produced by {@code Object}
+ * if a class did not override toString itself. {@code null}
+ * will throw a NullPointerException for either of the two parameters.
+ *
+ *
+ * ObjectUtils.identityToString(buf, "") = buf.append("java.lang.String@1e23"
+ * ObjectUtils.identityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa"
+ * ObjectUtils.identityToString(buf, Boolean.TRUE) = buf.append("java.lang.Boolean@7fa")
+ *
+ *
+ * @param buffer the buffer to append to
+ * @param object the object to create a toString for
+ * @since 2.4
+ */
+ public static void identityToString(final StringBuffer buffer, final Object object) {
+ if (object == null) {
+ throw new NullPointerException("Cannot get the toString of a null identity");
+ }
+ buffer.append(object.getClass().getName())
+ .append('@')
+ .append(Integer.toHexString(System.identityHashCode(object)));
+ }
+
+ /**
+ * Appends the toString that would be produced by {@code Object}
+ * if a class did not override toString itself. {@code null}
+ * will throw a NullPointerException for either of the two parameters.
+ *
+ *
+ * ObjectUtils.identityToString(builder, "") = builder.append("java.lang.String@1e23"
+ * ObjectUtils.identityToString(builder, Boolean.TRUE) = builder.append("java.lang.Boolean@7fa"
+ * ObjectUtils.identityToString(builder, Boolean.TRUE) = builder.append("java.lang.Boolean@7fa")
+ *
+ *
+ * @param builder the builder to append to
+ * @param object the object to create a toString for
+ * @since 3.2
+ */
+ public static void identityToString(final StringBuilder builder, final Object object) {
+ if (object == null) {
+ throw new NullPointerException("Cannot get the toString of a null identity");
+ }
+ builder.append(object.getClass().getName())
+ .append('@')
+ .append(Integer.toHexString(System.identityHashCode(object)));
+ }
+
+ // ToString
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the {@code toString} of an {@code Object} returning
+ * an empty string ("") if {@code null} input.
+ *
+ *
+ * ObjectUtils.toString(null) = ""
+ * ObjectUtils.toString("") = ""
+ * ObjectUtils.toString("bat") = "bat"
+ * ObjectUtils.toString(Boolean.TRUE) = "true"
+ *
+ *
+ * @see StringUtils#defaultString(String)
+ * @see String#valueOf(Object)
+ * @param obj the Object to {@code toString}, may be null
+ * @return the passed in Object's toString, or {@code ""} if {@code null} input
+ * @since 2.0
+ * @deprecated this method has been replaced by {@code java.util.Objects.toString(Object)} in Java 7 and will be
+ * removed in future releases. Note however that said method will return "null" for null references, while this
+ * method returns and empty String. To preserve behavior use {@code java.util.Objects.toString(myObject, "")}
+ */
+ @Deprecated
+ public static String toString(final Object obj) {
+ return obj == null ? StringUtils.EMPTY : obj.toString();
+ }
+
+ /**
+ * Gets the {@code toString} of an {@code Object} returning
+ * a specified text if {@code null} input.
+ *
+ *
+ * ObjectUtils.toString(null, null) = null
+ * ObjectUtils.toString(null, "null") = "null"
+ * ObjectUtils.toString("", "null") = ""
+ * ObjectUtils.toString("bat", "null") = "bat"
+ * ObjectUtils.toString(Boolean.TRUE, "null") = "true"
+ *
+ *
+ * @see StringUtils#defaultString(String,String)
+ * @see String#valueOf(Object)
+ * @param obj the Object to {@code toString}, may be null
+ * @param nullStr the String to return if {@code null} input, may be null
+ * @return the passed in Object's toString, or {@code nullStr} if {@code null} input
+ * @since 2.0
+ * @deprecated this method has been replaced by {@code java.util.Objects.toString(Object, String)} in Java 7 and
+ * will be removed in future releases.
+ */
+ @Deprecated
+ public static String toString(final Object obj, final String nullStr) {
+ return obj == null ? nullStr : obj.toString();
+ }
+
+ // Comparable
+ //-----------------------------------------------------------------------
+ /**
+ * Null safe comparison of Comparables.
+ *
+ * @param type of the values processed by this method
+ * @param values the set of comparable values, may be null
+ * @return
+ *
+ * If any objects are non-null and unequal, the lesser object.
+ * If all objects are non-null and equal, the first.
+ * If any of the comparables are null, the lesser of the non-null objects.
+ * If all the comparables are null, null is returned.
+ *
+ */
+ public static > T min(final T... values) {
+ T result = null;
+ if (values != null) {
+ for (final T value : values) {
+ if (compare(value, result, true) < 0) {
+ result = value;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Null safe comparison of Comparables.
+ *
+ * @param type of the values processed by this method
+ * @param values the set of comparable values, may be null
+ * @return
+ *
+ * If any objects are non-null and unequal, the greater object.
+ * If all objects are non-null and equal, the first.
+ * If any of the comparables are null, the greater of the non-null objects.
+ * If all the comparables are null, null is returned.
+ *
+ */
+ public static > T max(final T... values) {
+ T result = null;
+ if (values != null) {
+ for (final T value : values) {
+ if (compare(value, result, false) > 0) {
+ result = value;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Null safe comparison of Comparables.
+ * {@code null} is assumed to be less than a non-{@code null} value.
+ *
+ * @param type of the values processed by this method
+ * @param c1 the first comparable, may be null
+ * @param c2 the second comparable, may be null
+ * @return a negative value if c1 < c2, zero if c1 = c2
+ * and a positive value if c1 > c2
+ */
+ public static > int compare(final T c1, final T c2) {
+ return compare(c1, c2, false);
+ }
+
+ /**
+ * Null safe comparison of Comparables.
+ *
+ * @param type of the values processed by this method
+ * @param c1 the first comparable, may be null
+ * @param c2 the second comparable, may be null
+ * @param nullGreater if true {@code null} is considered greater
+ * than a non-{@code null} value or if false {@code null} is
+ * considered less than a Non-{@code null} value
+ * @return a negative value if c1 < c2, zero if c1 = c2
+ * and a positive value if c1 > c2
+ * @see java.util.Comparator#compare(Object, Object)
+ */
+ public static > int compare(final T c1, final T c2, final boolean nullGreater) {
+ if (c1 == c2) {
+ return 0;
+ } else if (c1 == null) {
+ return nullGreater ? 1 : -1;
+ } else if (c2 == null) {
+ return nullGreater ? -1 : 1;
+ }
+ return c1.compareTo(c2);
+ }
+
+ /**
+ * Find the "best guess" middle value among comparables. If there is an even
+ * number of total values, the lower of the two middle values will be returned.
+ * @param type of values processed by this method
+ * @param items to compare
+ * @return T at middle position
+ * @throws NullPointerException if items is {@code null}
+ * @throws IllegalArgumentException if items is empty or contains {@code null} values
+ * @since 3.0.1
+ */
+ public static > T median(final T... items) {
+ Validate.notEmpty(items);
+ Validate.noNullElements(items);
+ final TreeSet sort = new TreeSet();
+ Collections.addAll(sort, items);
+ @SuppressWarnings("unchecked") //we know all items added were T instances
+ final
+ T result = (T) sort.toArray()[(sort.size() - 1) / 2];
+ return result;
+ }
+
+ /**
+ * Find the "best guess" middle value among comparables. If there is an even
+ * number of total values, the lower of the two middle values will be returned.
+ * @param type of values processed by this method
+ * @param comparator to use for comparisons
+ * @param items to compare
+ * @return T at middle position
+ * @throws NullPointerException if items or comparator is {@code null}
+ * @throws IllegalArgumentException if items is empty or contains {@code null} values
+ * @since 3.0.1
+ */
+ public static T median(final Comparator comparator, final T... items) {
+ Validate.notEmpty(items, "null/empty items");
+ Validate.noNullElements(items);
+ Validate.notNull(comparator, "null comparator");
+ final TreeSet sort = new TreeSet(comparator);
+ Collections.addAll(sort, items);
+ @SuppressWarnings("unchecked") //we know all items added were T instances
+ final
+ T result = (T) sort.toArray()[(sort.size() - 1) / 2];
+ return result;
+ }
+
+ // Mode
+ //-----------------------------------------------------------------------
+ /**
+ * Find the most frequently occurring item.
+ *
+ * @param type of values processed by this method
+ * @param items to check
+ * @return most populous T, {@code null} if non-unique or no items supplied
+ * @since 3.0.1
+ */
+ public static T mode(final T... items) {
+ if (ArrayUtils.isNotEmpty(items)) {
+ final HashMap occurrences = new HashMap(items.length);
+ for (final T t : items) {
+ final MutableInt count = occurrences.get(t);
+ if (count == null) {
+ occurrences.put(t, new MutableInt(1));
+ } else {
+ count.increment();
+ }
+ }
+ T result = null;
+ int max = 0;
+ for (final Map.Entry e : occurrences.entrySet()) {
+ final int cmp = e.getValue().intValue();
+ if (cmp == max) {
+ result = null;
+ } else if (cmp > max) {
+ max = cmp;
+ result = e.getKey();
+ }
+ }
+ return result;
+ }
+ return null;
+ }
+
+ // cloning
+ //-----------------------------------------------------------------------
+ /**
+ * Clone an object.
+ *
+ * @param the type of the object
+ * @param obj the object to clone, null returns null
+ * @return the clone if the object implements {@link Cloneable} otherwise {@code null}
+ * @throws CloneFailedException if the object is cloneable and the clone operation fails
+ * @since 3.0
+ */
+ public static T clone(final T obj) {
+ if (obj instanceof Cloneable) {
+ final Object result;
+ if (obj.getClass().isArray()) {
+ final Class> componentType = obj.getClass().getComponentType();
+ if (!componentType.isPrimitive()) {
+ result = ((Object[]) obj).clone();
+ } else {
+ int length = Array.getLength(obj);
+ result = Array.newInstance(componentType, length);
+ while (length-- > 0) {
+ Array.set(result, length, Array.get(obj, length));
+ }
+ }
+ } else {
+ try {
+ final Method clone = obj.getClass().getMethod("clone");
+ result = clone.invoke(obj);
+ } catch (final NoSuchMethodException e) {
+ throw new CloneFailedException("Cloneable type "
+ + obj.getClass().getName()
+ + " has no clone method", e);
+ } catch (final IllegalAccessException e) {
+ throw new CloneFailedException("Cannot clone Cloneable type "
+ + obj.getClass().getName(), e);
+ } catch (final InvocationTargetException e) {
+ throw new CloneFailedException("Exception cloning Cloneable type "
+ + obj.getClass().getName(), e.getCause());
+ }
+ }
+ @SuppressWarnings("unchecked") // OK because input is of type T
+ final T checked = (T) result;
+ return checked;
+ }
+
+ return null;
+ }
+
+ /**
+ * Clone an object if possible.
+ *
+ * This method is similar to {@link #clone(Object)}, but will return the provided
+ * instance as the return value instead of {@code null} if the instance
+ * is not cloneable. This is more convenient if the caller uses different
+ * implementations (e.g. of a service) and some of the implementations do not allow concurrent
+ * processing or have state. In such cases the implementation can simply provide a proper
+ * clone implementation and the caller's code does not have to change.
+ *
+ * @param the type of the object
+ * @param obj the object to clone, null returns null
+ * @return the clone if the object implements {@link Cloneable} otherwise the object itself
+ * @throws CloneFailedException if the object is cloneable and the clone operation fails
+ * @since 3.0
+ */
+ public static T cloneIfPossible(final T obj) {
+ final T clone = clone(obj);
+ return clone == null ? obj : clone;
+ }
+
+ // Null
+ //-----------------------------------------------------------------------
+ /**
+ * Class used as a null placeholder where {@code null}
+ * has another meaning.
+ *
+ * For example, in a {@code HashMap} the
+ * {@link java.util.HashMap#get(java.lang.Object)} method returns
+ * {@code null} if the {@code Map} contains {@code null} or if there is
+ * no matching key. The {@code Null} placeholder can be used to distinguish
+ * between these two cases.
+ *
+ * Another example is {@code Hashtable}, where {@code null}
+ * cannot be stored.
+ */
+ public static class Null implements Serializable {
+ /**
+ * Required for serialization support. Declare serialization compatibility with Commons Lang 1.0
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 7092611880189329093L;
+
+ /**
+ * Restricted constructor - singleton.
+ */
+ Null() {
+ super();
+ }
+
+ /**
+ * Ensure singleton.
+ *
+ * @return the singleton value
+ */
+ private Object readResolve() {
+ return ObjectUtils.NULL;
+ }
+ }
+
+
+ // Constants (LANG-816):
+ /*
+ These methods ensure constants are not inlined by javac.
+ For example, typically a developer might declare a constant like so:
+
+ public final static int MAGIC_NUMBER = 5;
+
+ Should a different jar file refer to this, and the MAGIC_NUMBER
+ is changed a later date (e.g., MAGIC_NUMBER = 6), the different jar
+ file will need to recompile itself. This is because javac
+ typically inlines the primitive or String constant directly into
+ the bytecode, and removes the reference to the MAGIC_NUMBER field.
+
+ To help the other jar (so that it does not need to recompile
+ when constants are changed) the original developer can declare
+ their constant using one of the CONST() utility methods, instead:
+
+ public final static int MAGIC_NUMBER = CONST(5);
+ */
+
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static boolean MAGIC_FLAG = ObjectUtils.CONST(true);
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param v the boolean value to return
+ * @return the boolean v, unchanged
+ * @since 3.2
+ */
+ public static boolean CONST(final boolean v) { return v; }
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static byte MAGIC_BYTE = ObjectUtils.CONST((byte) 127);
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param v the byte value to return
+ * @return the byte v, unchanged
+ * @since 3.2
+ */
+ public static byte CONST(final byte v) { return v; }
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static byte MAGIC_BYTE = ObjectUtils.CONST_BYTE(127);
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param v the byte literal (as an int) value to return
+ * @throws IllegalArgumentException if the value passed to v
+ * is larger than a byte, that is, smaller than -128 or
+ * larger than 127.
+ * @return the byte v, unchanged
+ * @since 3.2
+ */
+ public static byte CONST_BYTE(final int v) throws IllegalArgumentException {
+ if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) {
+ throw new IllegalArgumentException("Supplied value must be a valid byte literal between -128 and 127: [" + v + "]");
+ }
+ return (byte) v;
+ }
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static char MAGIC_CHAR = ObjectUtils.CONST('a');
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param v the char value to return
+ * @return the char v, unchanged
+ * @since 3.2
+ */
+ public static char CONST(final char v) { return v; }
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static short MAGIC_SHORT = ObjectUtils.CONST((short) 123);
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param v the short value to return
+ * @return the short v, unchanged
+ * @since 3.2
+ */
+ public static short CONST(final short v) { return v; }
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static short MAGIC_SHORT = ObjectUtils.CONST_SHORT(127);
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param v the short literal (as an int) value to return
+ * @throws IllegalArgumentException if the value passed to v
+ * is larger than a short, that is, smaller than -32768 or
+ * larger than 32767.
+ * @return the byte v, unchanged
+ * @since 3.2
+ */
+ public static short CONST_SHORT(final int v) throws IllegalArgumentException {
+ if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
+ throw new IllegalArgumentException("Supplied value must be a valid byte literal between -32768 and 32767: [" + v + "]");
+ }
+ return (short) v;
+ }
+
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static int MAGIC_INT = ObjectUtils.CONST(123);
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param v the int value to return
+ * @return the int v, unchanged
+ * @since 3.2
+ */
+ public static int CONST(final int v) { return v; }
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static long MAGIC_LONG = ObjectUtils.CONST(123L);
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param v the long value to return
+ * @return the long v, unchanged
+ * @since 3.2
+ */
+ public static long CONST(final long v) { return v; }
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static float MAGIC_FLOAT = ObjectUtils.CONST(1.0f);
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param v the float value to return
+ * @return the float v, unchanged
+ * @since 3.2
+ */
+ public static float CONST(final float v) { return v; }
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static double MAGIC_DOUBLE = ObjectUtils.CONST(1.0);
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param v the double value to return
+ * @return the double v, unchanged
+ * @since 3.2
+ */
+ public static double CONST(final double v) { return v; }
+
+ /**
+ * This method returns the provided value unchanged.
+ * This can prevent javac from inlining a constant
+ * field, e.g.,
+ *
+ *
+ * public final static String MAGIC_STRING = ObjectUtils.CONST("abc");
+ *
+ *
+ * This way any jars that refer to this field do not
+ * have to recompile themselves if the field's value
+ * changes at some future date.
+ *
+ * @param the Object type
+ * @param v the genericized Object value to return (typically a String).
+ * @return the genericized Object v, unchanged (typically a String).
+ * @since 3.2
+ */
+ public static T CONST(final T v) { return v; }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/RandomStringUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/RandomStringUtils.java
new file mode 100644
index 000000000..84b30fd64
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/RandomStringUtils.java
@@ -0,0 +1,455 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.util.Random;
+
+/**
+ * Operations for random {@code String}s.
+ * Currently private high surrogate characters are ignored.
+ * These are Unicode characters that fall between the values 56192 (db80)
+ * and 56319 (dbff) as we don't know how to handle them.
+ * High and low surrogates are correctly dealt with - that is if a
+ * high surrogate is randomly chosen, 55296 (d800) to 56191 (db7f)
+ * then it is followed by a low surrogate. If a low surrogate is chosen,
+ * 56320 (dc00) to 57343 (dfff) then it is placed after a randomly
+ * chosen high surrogate.
+ *
+ * #ThreadSafe#
+ * @since 1.0
+ */
+public class RandomStringUtils {
+
+ /**
+ * Random object used by random method. This has to be not local
+ * to the random method so as to not return the same value in the
+ * same millisecond.
+ */
+ private static final Random RANDOM = new Random();
+
+ /**
+ * {@code RandomStringUtils} instances should NOT be constructed in
+ * standard programming. Instead, the class should be used as
+ * {@code RandomStringUtils.random(5);}.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ */
+ public RandomStringUtils() {
+ super();
+ }
+
+ // Random
+ //-----------------------------------------------------------------------
+ /**
+ * Creates a random string whose length is the number of characters
+ * specified.
+ *
+ * Characters will be chosen from the set of all characters.
+ *
+ * @param count the length of random string to create
+ * @return the random string
+ */
+ public static String random(final int count) {
+ return random(count, false, false);
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters
+ * specified.
+ *
+ * Characters will be chosen from the set of characters whose
+ * ASCII value is between {@code 32} and {@code 126} (inclusive).
+ *
+ * @param count the length of random string to create
+ * @return the random string
+ */
+ public static String randomAscii(final int count) {
+ return random(count, 32, 127, false, false);
+ }
+
+ /**
+ * Creates a random string whose length is between the inclusive minimum and
+ * the exclusive maximum.
+ *
+ * Characters will be chosen from the set of characters whose
+ * ASCII value is between {@code 32} and {@code 126} (inclusive).
+ *
+ * @param minLengthInclusive the inclusive minimum length of the string to generate
+ * @param maxLengthExclusive the exclusive maximum length of the string to generate
+ * @return the random string
+ * @since 3.5
+ */
+ public static String randomAscii(final int minLengthInclusive, final int maxLengthExclusive) {
+ return randomAscii(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters
+ * specified.
+ *
+ * Characters will be chosen from the set of alphabetic
+ * characters.
+ *
+ * @param count the length of random string to create
+ * @return the random string
+ */
+ public static String randomAlphabetic(final int count) {
+ return random(count, true, false);
+ }
+
+ /**
+ * Creates a random string whose length is between the inclusive minimum and
+ * the exclusive maximum.
+ *
+ * Characters will be chosen from the set of alphabetic characters.
+ *
+ * @param minLengthInclusive the inclusive minimum length of the string to generate
+ * @param maxLengthExclusive the exclusive maximum length of the string to generate
+ * @return the random string
+ * @since 3.5
+ */
+ public static String randomAlphabetic(final int minLengthInclusive, final int maxLengthExclusive) {
+ return randomAlphabetic(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters
+ * specified.
+ *
+ * Characters will be chosen from the set of alpha-numeric
+ * characters.
+ *
+ * @param count the length of random string to create
+ * @return the random string
+ */
+ public static String randomAlphanumeric(final int count) {
+ return random(count, true, true);
+ }
+
+ /**
+ * Creates a random string whose length is between the inclusive minimum and
+ * the exclusive maximum.
+ *
+ * Characters will be chosen from the set of alpha-numeric characters.
+ *
+ * @param minLengthInclusive the inclusive minimum length of the string to generate
+ * @param maxLengthExclusive the exclusive maximum length of the string to generate
+ * @return the random string
+ * @since 3.5
+ */
+ public static String randomAlphanumeric(final int minLengthInclusive, final int maxLengthExclusive) {
+ return randomAlphanumeric(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters specified.
+ *
+ * Characters will be chosen from the set of characters which match the POSIX [:graph:]
+ * regular expression character class. This class contains all visible ASCII characters
+ * (i.e. anything except spaces and control characters).
+ *
+ * @param count the length of random string to create
+ * @return the random string
+ * @since 3.5
+ */
+ public static String randomGraph(final int count) {
+ return random(count, 33, 126, false, false);
+ }
+
+ /**
+ * Creates a random string whose length is between the inclusive minimum and
+ * the exclusive maximum.
+ *
+ * Characters will be chosen from the set of \p{Graph} characters.
+ *
+ * @param minLengthInclusive the inclusive minimum length of the string to generate
+ * @param maxLengthExclusive the exclusive maximum length of the string to generate
+ * @return the random string
+ * @since 3.5
+ */
+ public static String randomGraph(final int minLengthInclusive, final int maxLengthExclusive) {
+ return randomGraph(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters
+ * specified.
+ *
+ * Characters will be chosen from the set of numeric
+ * characters.
+ *
+ * @param count the length of random string to create
+ * @return the random string
+ */
+ public static String randomNumeric(final int count) {
+ return random(count, false, true);
+ }
+
+ /**
+ * Creates a random string whose length is between the inclusive minimum and
+ * the exclusive maximum.
+ *
+ * Characters will be chosen from the set of \p{Digit} characters.
+ *
+ * @param minLengthInclusive the inclusive minimum length of the string to generate
+ * @param maxLengthExclusive the exclusive maximum length of the string to generate
+ * @return the random string
+ * @since 3.5
+ */
+ public static String randomNumeric(final int minLengthInclusive, final int maxLengthExclusive) {
+ return randomNumeric(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters specified.
+ *
+ * Characters will be chosen from the set of characters which match the POSIX [:print:]
+ * regular expression character class. This class includes all visible ASCII characters and spaces
+ * (i.e. anything except control characters).
+ *
+ * @param count the length of random string to create
+ * @return the random string
+ * @since 3.5
+ */
+ public static String randomPrint(final int count) {
+ return random(count, 32, 126, false, false);
+ }
+
+ /**
+ * Creates a random string whose length is between the inclusive minimum and
+ * the exclusive maximum.
+ *
+ * Characters will be chosen from the set of \p{Print} characters.
+ *
+ * @param minLengthInclusive the inclusive minimum length of the string to generate
+ * @param maxLengthExclusive the exclusive maximum length of the string to generate
+ * @return the random string
+ * @since 3.5
+ */
+ public static String randomPrint(final int minLengthInclusive, final int maxLengthExclusive) {
+ return randomPrint(RandomUtils.nextInt(minLengthInclusive, maxLengthExclusive));
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters
+ * specified.
+ *
+ * Characters will be chosen from the set of alpha-numeric
+ * characters as indicated by the arguments.
+ *
+ * @param count the length of random string to create
+ * @param letters if {@code true}, generated string may include
+ * alphabetic characters
+ * @param numbers if {@code true}, generated string may include
+ * numeric characters
+ * @return the random string
+ */
+ public static String random(final int count, final boolean letters, final boolean numbers) {
+ return random(count, 0, 0, letters, numbers);
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters
+ * specified.
+ *
+ * Characters will be chosen from the set of alpha-numeric
+ * characters as indicated by the arguments.
+ *
+ * @param count the length of random string to create
+ * @param start the position in set of chars to start at
+ * @param end the position in set of chars to end before
+ * @param letters if {@code true}, generated string may include
+ * alphabetic characters
+ * @param numbers if {@code true}, generated string may include
+ * numeric characters
+ * @return the random string
+ */
+ public static String random(final int count, final int start, final int end, final boolean letters, final boolean numbers) {
+ return random(count, start, end, letters, numbers, null, RANDOM);
+ }
+
+ /**
+ * Creates a random string based on a variety of options, using
+ * default source of randomness.
+ *
+ * This method has exactly the same semantics as
+ * {@link #random(int,int,int,boolean,boolean,char[],Random)}, but
+ * instead of using an externally supplied source of randomness, it uses
+ * the internal static {@link Random} instance.
+ *
+ * @param count the length of random string to create
+ * @param start the position in set of chars to start at
+ * @param end the position in set of chars to end before
+ * @param letters only allow letters?
+ * @param numbers only allow numbers?
+ * @param chars the set of chars to choose randoms from.
+ * If {@code null}, then it will use the set of all chars.
+ * @return the random string
+ * @throws ArrayIndexOutOfBoundsException if there are not
+ * {@code (end - start) + 1} characters in the set array.
+ */
+ public static String random(final int count, final int start, final int end, final boolean letters, final boolean numbers, final char... chars) {
+ return random(count, start, end, letters, numbers, chars, RANDOM);
+ }
+
+ /**
+ * Creates a random string based on a variety of options, using
+ * supplied source of randomness.
+ *
+ * If start and end are both {@code 0}, start and end are set
+ * to {@code ' '} and {@code 'z'}, the ASCII printable
+ * characters, will be used, unless letters and numbers are both
+ * {@code false}, in which case, start and end are set to
+ * {@code 0} and {@code Integer.MAX_VALUE}.
+ *
+ *
If set is not {@code null}, characters between start and
+ * end are chosen.
+ *
+ * This method accepts a user-supplied {@link Random}
+ * instance to use as a source of randomness. By seeding a single
+ * {@link Random} instance with a fixed seed and using it for each call,
+ * the same random sequence of strings can be generated repeatedly
+ * and predictably.
+ *
+ * @param count the length of random string to create
+ * @param start the position in set of chars to start at
+ * @param end the position in set of chars to end before
+ * @param letters only allow letters?
+ * @param numbers only allow numbers?
+ * @param chars the set of chars to choose randoms from, must not be empty.
+ * If {@code null}, then it will use the set of all chars.
+ * @param random a source of randomness.
+ * @return the random string
+ * @throws ArrayIndexOutOfBoundsException if there are not
+ * {@code (end - start) + 1} characters in the set array.
+ * @throws IllegalArgumentException if {@code count} < 0 or the provided chars array is empty.
+ * @since 2.0
+ */
+ public static String random(int count, int start, int end, final boolean letters, final boolean numbers,
+ final char[] chars, final Random random) {
+ if (count == 0) {
+ return StringUtils.EMPTY;
+ } else if (count < 0) {
+ throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
+ }
+ if (chars != null && chars.length == 0) {
+ throw new IllegalArgumentException("The chars array must not be empty");
+ }
+
+ if (start == 0 && end == 0) {
+ if (chars != null) {
+ end = chars.length;
+ } else {
+ if (!letters && !numbers) {
+ end = Integer.MAX_VALUE;
+ } else {
+ end = 'z' + 1;
+ start = ' ';
+ }
+ }
+ } else {
+ if (end <= start) {
+ throw new IllegalArgumentException("Parameter end (" + end + ") must be greater than start (" + start + ")");
+ }
+ }
+
+ final char[] buffer = new char[count];
+ final int gap = end - start;
+
+ while (count-- != 0) {
+ char ch;
+ if (chars == null) {
+ ch = (char) (random.nextInt(gap) + start);
+ } else {
+ ch = chars[random.nextInt(gap) + start];
+ }
+ if (letters && Character.isLetter(ch)
+ || numbers && Character.isDigit(ch)
+ || !letters && !numbers) {
+ if(ch >= 56320 && ch <= 57343) {
+ if(count == 0) {
+ count++;
+ } else {
+ // low surrogate, insert high surrogate after putting it in
+ buffer[count] = ch;
+ count--;
+ buffer[count] = (char) (55296 + random.nextInt(128));
+ }
+ } else if(ch >= 55296 && ch <= 56191) {
+ if(count == 0) {
+ count++;
+ } else {
+ // high surrogate, insert low surrogate before putting it in
+ buffer[count] = (char) (56320 + random.nextInt(128));
+ count--;
+ buffer[count] = ch;
+ }
+ } else if(ch >= 56192 && ch <= 56319) {
+ // private high surrogate, no effing clue, so skip it
+ count++;
+ } else {
+ buffer[count] = ch;
+ }
+ } else {
+ count++;
+ }
+ }
+ return new String(buffer);
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters
+ * specified.
+ *
+ * Characters will be chosen from the set of characters
+ * specified by the string, must not be empty.
+ * If null, the set of all characters is used.
+ *
+ * @param count the length of random string to create
+ * @param chars the String containing the set of characters to use,
+ * may be null, but must not be empty
+ * @return the random string
+ * @throws IllegalArgumentException if {@code count} < 0 or the string is empty.
+ */
+ public static String random(final int count, final String chars) {
+ if (chars == null) {
+ return random(count, 0, 0, false, false, null, RANDOM);
+ }
+ return random(count, chars.toCharArray());
+ }
+
+ /**
+ * Creates a random string whose length is the number of characters
+ * specified.
+ *
+ * Characters will be chosen from the set of characters specified.
+ *
+ * @param count the length of random string to create
+ * @param chars the character array containing the set of characters to use,
+ * may be null
+ * @return the random string
+ * @throws IllegalArgumentException if {@code count} < 0.
+ */
+ public static String random(final int count, final char... chars) {
+ if (chars == null) {
+ return random(count, 0, 0, false, false, null, RANDOM);
+ }
+ return random(count, 0, chars.length, false, false, chars, RANDOM);
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/RandomUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/RandomUtils.java
new file mode 100644
index 000000000..3ea44938a
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/RandomUtils.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.util.Random;
+
+/**
+ * Utility library that supplements the standard {@link Random} class.
+ *
+ * @since 3.3
+ */
+public class RandomUtils {
+
+ /**
+ * Random object used by random method. This has to be not local to the
+ * random method so as to not return the same value in the same millisecond.
+ */
+ private static final Random RANDOM = new Random();
+
+ /**
+ *
+ * {@code RandomUtils} instances should NOT be constructed in standard
+ * programming. Instead, the class should be used as
+ * {@code RandomUtils.nextBytes(5);}.
+ *
+ *
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ *
+ */
+ public RandomUtils() {
+ super();
+ }
+
+ /**
+ *
+ * Returns a random boolean value
+ *
+ *
+ * @return the random boolean
+ * @since 3.5
+ */
+ public static boolean nextBoolean() {
+ return RANDOM.nextBoolean();
+ }
+
+ /**
+ *
+ * Creates an array of random bytes.
+ *
+ *
+ * @param count
+ * the size of the returned array
+ * @return the random byte array
+ * @throws IllegalArgumentException if {@code count} is negative
+ */
+ public static byte[] nextBytes(final int count) {
+ Validate.isTrue(count >= 0, "Count cannot be negative.");
+
+ final byte[] result = new byte[count];
+ RANDOM.nextBytes(result);
+ return result;
+ }
+
+ /**
+ *
+ * Returns a random integer within the specified range.
+ *
+ *
+ * @param startInclusive
+ * the smallest value that can be returned, must be non-negative
+ * @param endExclusive
+ * the upper bound (not included)
+ * @throws IllegalArgumentException
+ * if {@code startInclusive > endExclusive} or if
+ * {@code startInclusive} is negative
+ * @return the random integer
+ */
+ public static int nextInt(final int startInclusive, final int endExclusive) {
+ Validate.isTrue(endExclusive >= startInclusive,
+ "Start value must be smaller or equal to end value.");
+ Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
+
+ if (startInclusive == endExclusive) {
+ return startInclusive;
+ }
+
+ return startInclusive + RANDOM.nextInt(endExclusive - startInclusive);
+ }
+
+ /**
+ * Returns a random int within 0 - Integer.MAX_VALUE
+ *
+ * @return the random integer
+ * @see #nextInt(int, int)
+ * @since 3.5
+ */
+ public static int nextInt() {
+ return nextInt(0, Integer.MAX_VALUE);
+ }
+
+ /**
+ *
+ * Returns a random long within the specified range.
+ *
+ *
+ * @param startInclusive
+ * the smallest value that can be returned, must be non-negative
+ * @param endExclusive
+ * the upper bound (not included)
+ * @throws IllegalArgumentException
+ * if {@code startInclusive > endExclusive} or if
+ * {@code startInclusive} is negative
+ * @return the random long
+ */
+ public static long nextLong(final long startInclusive, final long endExclusive) {
+ Validate.isTrue(endExclusive >= startInclusive,
+ "Start value must be smaller or equal to end value.");
+ Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
+
+ if (startInclusive == endExclusive) {
+ return startInclusive;
+ }
+
+ return (long) nextDouble(startInclusive, endExclusive);
+ }
+
+ /**
+ * Returns a random long within 0 - Long.MAX_VALUE
+ *
+ * @return the random long
+ * @see #nextLong(long, long)
+ * @since 3.5
+ */
+ public static long nextLong() {
+ return nextLong(0, Long.MAX_VALUE);
+ }
+
+ /**
+ *
+ * Returns a random double within the specified range.
+ *
+ *
+ * @param startInclusive
+ * the smallest value that can be returned, must be non-negative
+ * @param endInclusive
+ * the upper bound (included)
+ * @throws IllegalArgumentException
+ * if {@code startInclusive > endInclusive} or if
+ * {@code startInclusive} is negative
+ * @return the random double
+ */
+ public static double nextDouble(final double startInclusive, final double endInclusive) {
+ Validate.isTrue(endInclusive >= startInclusive,
+ "Start value must be smaller or equal to end value.");
+ Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
+
+ if (startInclusive == endInclusive) {
+ return startInclusive;
+ }
+
+ return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextDouble());
+ }
+
+ /**
+ * Returns a random double within 0 - Double.MAX_VALUE
+ *
+ * @return the random double
+ * @see #nextDouble(double, double)
+ * @since 3.5
+ */
+ public static double nextDouble() {
+ return nextDouble(0, Double.MAX_VALUE);
+ }
+
+ /**
+ *
+ * Returns a random float within the specified range.
+ *
+ *
+ * @param startInclusive
+ * the smallest value that can be returned, must be non-negative
+ * @param endInclusive
+ * the upper bound (included)
+ * @throws IllegalArgumentException
+ * if {@code startInclusive > endInclusive} or if
+ * {@code startInclusive} is negative
+ * @return the random float
+ */
+ public static float nextFloat(final float startInclusive, final float endInclusive) {
+ Validate.isTrue(endInclusive >= startInclusive,
+ "Start value must be smaller or equal to end value.");
+ Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
+
+ if (startInclusive == endInclusive) {
+ return startInclusive;
+ }
+
+ return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextFloat());
+ }
+
+ /**
+ * Returns a random float within 0 - Float.MAX_VALUE
+ *
+ * @return the random float
+ * @see #nextFloat()
+ * @since 3.5
+ */
+ public static float nextFloat() {
+ return nextFloat(0, Float.MAX_VALUE);
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Range.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Range.java
new file mode 100644
index 000000000..40afba8c9
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Range.java
@@ -0,0 +1,487 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * An immutable range of objects from a minimum to maximum point inclusive.
+ *
+ * The objects need to either be implementations of {@code Comparable}
+ * or you need to supply a {@code Comparator}.
+ *
+ * #ThreadSafe# if the objects and comparator are thread-safe
+ *
+ * @since 3.0
+ */
+public final class Range implements Serializable {
+
+ /**
+ * Serialization version.
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The ordering scheme used in this range.
+ */
+ private final Comparator comparator;
+ /**
+ * The minimum value in this range (inclusive).
+ */
+ private final T minimum;
+ /**
+ * The maximum value in this range (inclusive).
+ */
+ private final T maximum;
+ /**
+ * Cached output hashCode (class is immutable).
+ */
+ private transient int hashCode;
+ /**
+ * Cached output toString (class is immutable).
+ */
+ private transient String toString;
+
+ /**
+ * Obtains a range using the specified element as both the minimum
+ * and maximum in this range.
+ *
+ * The range uses the natural ordering of the elements to determine where
+ * values lie in the range.
+ *
+ * @param the type of the elements in this range
+ * @param element the value to use for this range, not null
+ * @return the range object, not null
+ * @throws IllegalArgumentException if the element is null
+ * @throws ClassCastException if the element is not {@code Comparable}
+ */
+ public static > Range is(final T element) {
+ return between(element, element, null);
+ }
+
+ /**
+ * Obtains a range using the specified element as both the minimum
+ * and maximum in this range.
+ *
+ * The range uses the specified {@code Comparator} to determine where
+ * values lie in the range.
+ *
+ * @param the type of the elements in this range
+ * @param element the value to use for this range, must not be {@code null}
+ * @param comparator the comparator to be used, null for natural ordering
+ * @return the range object, not null
+ * @throws IllegalArgumentException if the element is null
+ * @throws ClassCastException if using natural ordering and the elements are not {@code Comparable}
+ */
+ public static Range is(final T element, final Comparator comparator) {
+ return between(element, element, comparator);
+ }
+
+ /**
+ * Obtains a range with the specified minimum and maximum values (both inclusive).
+ *
+ * The range uses the natural ordering of the elements to determine where
+ * values lie in the range.
+ *
+ * The arguments may be passed in the order (min,max) or (max,min).
+ * The getMinimum and getMaximum methods will return the correct values.
+ *
+ * @param the type of the elements in this range
+ * @param fromInclusive the first value that defines the edge of the range, inclusive
+ * @param toInclusive the second value that defines the edge of the range, inclusive
+ * @return the range object, not null
+ * @throws IllegalArgumentException if either element is null
+ * @throws ClassCastException if the elements are not {@code Comparable}
+ */
+ public static > Range between(final T fromInclusive, final T toInclusive) {
+ return between(fromInclusive, toInclusive, null);
+ }
+
+ /**
+ * Obtains a range with the specified minimum and maximum values (both inclusive).
+ *
+ * The range uses the specified {@code Comparator} to determine where
+ * values lie in the range.
+ *
+ * The arguments may be passed in the order (min,max) or (max,min).
+ * The getMinimum and getMaximum methods will return the correct values.
+ *
+ * @param the type of the elements in this range
+ * @param fromInclusive the first value that defines the edge of the range, inclusive
+ * @param toInclusive the second value that defines the edge of the range, inclusive
+ * @param comparator the comparator to be used, null for natural ordering
+ * @return the range object, not null
+ * @throws IllegalArgumentException if either element is null
+ * @throws ClassCastException if using natural ordering and the elements are not {@code Comparable}
+ */
+ public static Range between(final T fromInclusive, final T toInclusive, final Comparator comparator) {
+ return new Range(fromInclusive, toInclusive, comparator);
+ }
+
+ /**
+ * Creates an instance.
+ *
+ * @param element1 the first element, not null
+ * @param element2 the second element, not null
+ * @param comp the comparator to be used, null for natural ordering
+ */
+ @SuppressWarnings("unchecked")
+ private Range(final T element1, final T element2, final Comparator comp) {
+ if (element1 == null || element2 == null) {
+ throw new IllegalArgumentException("Elements in a range must not be null: element1=" +
+ element1 + ", element2=" + element2);
+ }
+ if (comp == null) {
+ this.comparator = ComparableComparator.INSTANCE;
+ } else {
+ this.comparator = comp;
+ }
+ if (this.comparator.compare(element1, element2) < 1) {
+ this.minimum = element1;
+ this.maximum = element2;
+ } else {
+ this.minimum = element2;
+ this.maximum = element1;
+ }
+ }
+
+ // Accessors
+ //--------------------------------------------------------------------
+
+ /**
+ * Gets the minimum value in this range.
+ *
+ * @return the minimum value in this range, not null
+ */
+ public T getMinimum() {
+ return minimum;
+ }
+
+ /**
+ * Gets the maximum value in this range.
+ *
+ * @return the maximum value in this range, not null
+ */
+ public T getMaximum() {
+ return maximum;
+ }
+
+ /**
+ * Gets the comparator being used to determine if objects are within the range.
+ *
+ * Natural ordering uses an internal comparator implementation, thus this
+ * method never returns null. See {@link #isNaturalOrdering()}.
+ *
+ * @return the comparator being used, not null
+ */
+ public Comparator getComparator() {
+ return comparator;
+ }
+
+ /**
+ * Whether or not the Range is using the natural ordering of the elements.
+ *
+ * Natural ordering uses an internal comparator implementation, thus this
+ * method is the only way to check if a null comparator was specified.
+ *
+ * @return true if using natural ordering
+ */
+ public boolean isNaturalOrdering() {
+ return comparator == ComparableComparator.INSTANCE;
+ }
+
+ // Element tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Checks whether the specified element occurs within this range.
+ *
+ * @param element the element to check for, null returns false
+ * @return true if the specified element occurs within this range
+ */
+ public boolean contains(final T element) {
+ if (element == null) {
+ return false;
+ }
+ return comparator.compare(element, minimum) > -1 && comparator.compare(element, maximum) < 1;
+ }
+
+ /**
+ * Checks whether this range is after the specified element.
+ *
+ * @param element the element to check for, null returns false
+ * @return true if this range is entirely after the specified element
+ */
+ public boolean isAfter(final T element) {
+ if (element == null) {
+ return false;
+ }
+ return comparator.compare(element, minimum) < 0;
+ }
+
+ /**
+ * Checks whether this range starts with the specified element.
+ *
+ * @param element the element to check for, null returns false
+ * @return true if the specified element occurs within this range
+ */
+ public boolean isStartedBy(final T element) {
+ if (element == null) {
+ return false;
+ }
+ return comparator.compare(element, minimum) == 0;
+ }
+
+ /**
+ * Checks whether this range ends with the specified element.
+ *
+ * @param element the element to check for, null returns false
+ * @return true if the specified element occurs within this range
+ */
+ public boolean isEndedBy(final T element) {
+ if (element == null) {
+ return false;
+ }
+ return comparator.compare(element, maximum) == 0;
+ }
+
+ /**
+ * Checks whether this range is before the specified element.
+ *
+ * @param element the element to check for, null returns false
+ * @return true if this range is entirely before the specified element
+ */
+ public boolean isBefore(final T element) {
+ if (element == null) {
+ return false;
+ }
+ return comparator.compare(element, maximum) > 0;
+ }
+
+ /**
+ * Checks where the specified element occurs relative to this range.
+ *
+ * The API is reminiscent of the Comparable interface returning {@code -1} if
+ * the element is before the range, {@code 0} if contained within the range and
+ * {@code 1} if the element is after the range.
+ *
+ * @param element the element to check for, not null
+ * @return -1, 0 or +1 depending on the element's location relative to the range
+ */
+ public int elementCompareTo(final T element) {
+ if (element == null) {
+ // Comparable API says throw NPE on null
+ throw new NullPointerException("Element is null");
+ }
+ if (isAfter(element)) {
+ return -1;
+ } else if (isBefore(element)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ // Range tests
+ //--------------------------------------------------------------------
+
+ /**
+ * Checks whether this range contains all the elements of the specified range.
+ *
+ * This method may fail if the ranges have two different comparators or element types.
+ *
+ * @param otherRange the range to check, null returns false
+ * @return true if this range contains the specified range
+ * @throws RuntimeException if ranges cannot be compared
+ */
+ public boolean containsRange(final Range otherRange) {
+ if (otherRange == null) {
+ return false;
+ }
+ return contains(otherRange.minimum)
+ && contains(otherRange.maximum);
+ }
+
+ /**
+ * Checks whether this range is completely after the specified range.
+ *
+ * This method may fail if the ranges have two different comparators or element types.
+ *
+ * @param otherRange the range to check, null returns false
+ * @return true if this range is completely after the specified range
+ * @throws RuntimeException if ranges cannot be compared
+ */
+ public boolean isAfterRange(final Range otherRange) {
+ if (otherRange == null) {
+ return false;
+ }
+ return isAfter(otherRange.maximum);
+ }
+
+ /**
+ * Checks whether this range is overlapped by the specified range.
+ *
+ * Two ranges overlap if there is at least one element in common.
+ *
+ * This method may fail if the ranges have two different comparators or element types.
+ *
+ * @param otherRange the range to test, null returns false
+ * @return true if the specified range overlaps with this
+ * range; otherwise, {@code false}
+ * @throws RuntimeException if ranges cannot be compared
+ */
+ public boolean isOverlappedBy(final Range otherRange) {
+ if (otherRange == null) {
+ return false;
+ }
+ return otherRange.contains(minimum)
+ || otherRange.contains(maximum)
+ || contains(otherRange.minimum);
+ }
+
+ /**
+ * Checks whether this range is completely before the specified range.
+ *
+ * This method may fail if the ranges have two different comparators or element types.
+ *
+ * @param otherRange the range to check, null returns false
+ * @return true if this range is completely before the specified range
+ * @throws RuntimeException if ranges cannot be compared
+ */
+ public boolean isBeforeRange(final Range otherRange) {
+ if (otherRange == null) {
+ return false;
+ }
+ return isBefore(otherRange.minimum);
+ }
+
+ /**
+ * Calculate the intersection of {@code this} and an overlapping Range.
+ * @param other overlapping Range
+ * @return range representing the intersection of {@code this} and {@code other} ({@code this} if equal)
+ * @throws IllegalArgumentException if {@code other} does not overlap {@code this}
+ * @since 3.0.1
+ */
+ public Range intersectionWith(final Range other) {
+ if (!this.isOverlappedBy(other)) {
+ throw new IllegalArgumentException(String.format(
+ "Cannot calculate intersection with non-overlapping range %s", other));
+ }
+ if (this.equals(other)) {
+ return this;
+ }
+ final T min = getComparator().compare(minimum, other.minimum) < 0 ? other.minimum : minimum;
+ final T max = getComparator().compare(maximum, other.maximum) < 0 ? maximum : other.maximum;
+ return between(min, max, getComparator());
+ }
+
+ // Basics
+ //--------------------------------------------------------------------
+
+ /**
+ * Compares this range to another object to test if they are equal.
.
+ *
+ * To be equal, the minimum and maximum values must be equal, which
+ * ignores any differences in the comparator.
+ *
+ * @param obj the reference object with which to compare
+ * @return true if this object is equal
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ } else if (obj == null || obj.getClass() != getClass()) {
+ return false;
+ } else {
+ @SuppressWarnings("unchecked") // OK because we checked the class above
+ final
+ Range range = (Range) obj;
+ return minimum.equals(range.minimum) &&
+ maximum.equals(range.maximum);
+ }
+ }
+
+ /**
+ * Gets a suitable hash code for the range.
+ *
+ * @return a hash code value for this object
+ */
+ @Override
+ public int hashCode() {
+ int result = hashCode;
+ if (hashCode == 0) {
+ result = 17;
+ result = 37 * result + getClass().hashCode();
+ result = 37 * result + minimum.hashCode();
+ result = 37 * result + maximum.hashCode();
+ hashCode = result;
+ }
+ return result;
+ }
+
+ /**
+ * Gets the range as a {@code String}.
+ *
+ * The format of the String is '[min ..max ]'.
+ *
+ * @return the {@code String} representation of this range
+ */
+ @Override
+ public String toString() {
+ if (toString == null) {
+ toString = "[" + minimum + ".." + maximum + "]";
+ }
+ return toString;
+ }
+
+ /**
+ * Formats the receiver using the given format.
+ *
+ * This uses {@link java.util.Formattable} to perform the formatting. Three variables may
+ * be used to embed the minimum, maximum and comparator.
+ * Use {@code %1$s} for the minimum element, {@code %2$s} for the maximum element
+ * and {@code %3$s} for the comparator.
+ * The default format used by {@code toString()} is {@code [%1$s..%2$s]}.
+ *
+ * @param format the format string, optionally containing {@code %1$s}, {@code %2$s} and {@code %3$s}, not null
+ * @return the formatted string, not null
+ */
+ public String toString(final String format) {
+ return String.format(format, minimum, maximum, comparator);
+ }
+
+ //-----------------------------------------------------------------------
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private enum ComparableComparator implements Comparator {
+ INSTANCE;
+ /**
+ * Comparable based compare implementation.
+ *
+ * @param obj1 left hand side of comparison
+ * @param obj2 right hand side of comparison
+ * @return negative, 0, positive comparison value
+ */
+ @Override
+ public int compare(final Object obj1, final Object obj2) {
+ return ((Comparable) obj1).compareTo(obj2);
+ }
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SerializationException.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SerializationException.java
new file mode 100644
index 000000000..588eff05a
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SerializationException.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+/**
+ * Exception thrown when the Serialization process fails.
+ *
+ * The original error is wrapped within this one.
+ *
+ * #NotThreadSafe# because Throwable is not thread-safe
+ * @since 1.0
+ */
+public class SerializationException extends RuntimeException {
+
+ /**
+ * Required for serialization support.
+ *
+ * @see java.io.Serializable
+ */
+ private static final long serialVersionUID = 4029025366392702726L;
+
+ /**
+ * Constructs a new {@code SerializationException} without specified
+ * detail message.
+ */
+ public SerializationException() {
+ super();
+ }
+
+ /**
+ * Constructs a new {@code SerializationException} with specified
+ * detail message.
+ *
+ * @param msg The error message.
+ */
+ public SerializationException(final String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs a new {@code SerializationException} with specified
+ * nested {@code Throwable}.
+ *
+ * @param cause The {@code Exception} or {@code Error}
+ * that caused this exception to be thrown.
+ */
+ public SerializationException(final Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new {@code SerializationException} with specified
+ * detail message and nested {@code Throwable}.
+ *
+ * @param msg The error message.
+ * @param cause The {@code Exception} or {@code Error}
+ * that caused this exception to be thrown.
+ */
+ public SerializationException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SerializationUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SerializationUtils.java
new file mode 100644
index 000000000..a5a7b49be
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SerializationUtils.java
@@ -0,0 +1,339 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Assists with the serialization process and performs additional functionality based
+ * on serialization.
+ *
+ *
+ * Deep clone using serialization
+ * Serialize managing finally and IOException
+ * Deserialize managing finally and IOException
+ *
+ *
+ * This class throws exceptions for invalid {@code null} inputs.
+ * Each method documents its behaviour in more detail.
+ *
+ * #ThreadSafe#
+ * @since 1.0
+ */
+public class SerializationUtils {
+
+ /**
+ * SerializationUtils instances should NOT be constructed in standard programming.
+ * Instead, the class should be used as {@code SerializationUtils.clone(object)}.
+ *
+ * This constructor is public to permit tools that require a JavaBean instance
+ * to operate.
+ * @since 2.0
+ */
+ public SerializationUtils() {
+ super();
+ }
+
+ // Clone
+ //-----------------------------------------------------------------------
+ /**
+ * Deep clone an {@code Object} using serialization.
+ *
+ * This is many times slower than writing clone methods by hand
+ * on all objects in your object graph. However, for complex object
+ * graphs, or for those that don't support deep cloning this can
+ * be a simple alternative implementation. Of course all the objects
+ * must be {@code Serializable}.
+ *
+ * @param the type of the object involved
+ * @param object the {@code Serializable} object to clone
+ * @return the cloned object
+ * @throws SerializationException (runtime) if the serialization fails
+ */
+ public static T clone(final T object) {
+ if (object == null) {
+ return null;
+ }
+ final byte[] objectData = serialize(object);
+ final ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
+
+ ClassLoaderAwareObjectInputStream in = null;
+ try {
+ // stream closed in the finally
+ in = new ClassLoaderAwareObjectInputStream(bais, object.getClass().getClassLoader());
+ /*
+ * when we serialize and deserialize an object,
+ * it is reasonable to assume the deserialized object
+ * is of the same type as the original serialized object
+ */
+ @SuppressWarnings("unchecked") // see above
+ final T readObject = (T) in.readObject();
+ return readObject;
+
+ } catch (final ClassNotFoundException ex) {
+ throw new SerializationException("ClassNotFoundException while reading cloned object data", ex);
+ } catch (final IOException ex) {
+ throw new SerializationException("IOException while reading cloned object data", ex);
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (final IOException ex) {
+ throw new SerializationException("IOException on closing cloned object data InputStream.", ex);
+ }
+ }
+ }
+
+ /**
+ * Performs a serialization roundtrip. Serializes and deserializes the given object, great for testing objects that
+ * implement {@link Serializable}.
+ *
+ * @param
+ * the type of the object involved
+ * @param msg
+ * the object to roundtrip
+ * @return the serialized and deseralized object
+ * @since 3.3
+ */
+ @SuppressWarnings("unchecked") // OK, because we serialized a type `T`
+ public static T roundtrip(final T msg) {
+ return (T) SerializationUtils.deserialize(SerializationUtils.serialize(msg));
+ }
+
+ // Serialize
+ //-----------------------------------------------------------------------
+ /**
+ * Serializes an {@code Object} to the specified stream.
+ *
+ * The stream will be closed once the object is written.
+ * This avoids the need for a finally clause, and maybe also exception
+ * handling, in the application code.
+ *
+ * The stream passed in is not buffered internally within this method.
+ * This is the responsibility of your application if desired.
+ *
+ * @param obj the object to serialize to bytes, may be null
+ * @param outputStream the stream to write to, must not be null
+ * @throws IllegalArgumentException if {@code outputStream} is {@code null}
+ * @throws SerializationException (runtime) if the serialization fails
+ */
+ public static void serialize(final Serializable obj, final OutputStream outputStream) {
+ if (outputStream == null) {
+ throw new IllegalArgumentException("The OutputStream must not be null");
+ }
+ ObjectOutputStream out = null;
+ try {
+ // stream closed in the finally
+ out = new ObjectOutputStream(outputStream);
+ out.writeObject(obj);
+
+ } catch (final IOException ex) {
+ throw new SerializationException(ex);
+ } finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ } catch (final IOException ex) { // NOPMD
+ // ignore close exception
+ }
+ }
+ }
+
+ /**
+ * Serializes an {@code Object} to a byte array for
+ * storage/serialization.
+ *
+ * @param obj the object to serialize to bytes
+ * @return a byte[] with the converted Serializable
+ * @throws SerializationException (runtime) if the serialization fails
+ */
+ public static byte[] serialize(final Serializable obj) {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
+ serialize(obj, baos);
+ return baos.toByteArray();
+ }
+
+ // Deserialize
+ //-----------------------------------------------------------------------
+ /**
+ *
+ * Deserializes an {@code Object} from the specified stream.
+ *
+ *
+ *
+ * The stream will be closed once the object is written. This avoids the need for a finally clause, and maybe also
+ * exception handling, in the application code.
+ *
+ *
+ *
+ * The stream passed in is not buffered internally within this method. This is the responsibility of your
+ * application if desired.
+ *
+ *
+ *
+ * If the call site incorrectly types the return value, a {@link ClassCastException} is thrown from the call site.
+ * Without Generics in this declaration, the call site must type cast and can cause the same ClassCastException.
+ * Note that in both cases, the ClassCastException is in the call site, not in this method.
+ *
+ *
+ * @param the object type to be deserialized
+ * @param inputStream
+ * the serialized object input stream, must not be null
+ * @return the deserialized object
+ * @throws IllegalArgumentException
+ * if {@code inputStream} is {@code null}
+ * @throws SerializationException
+ * (runtime) if the serialization fails
+ */
+ public static T deserialize(final InputStream inputStream) {
+ if (inputStream == null) {
+ throw new IllegalArgumentException("The InputStream must not be null");
+ }
+ ObjectInputStream in = null;
+ try {
+ // stream closed in the finally
+ in = new ObjectInputStream(inputStream);
+ @SuppressWarnings("unchecked")
+ final T obj = (T) in.readObject();
+ return obj;
+
+ } catch (final ClassNotFoundException ex) {
+ throw new SerializationException(ex);
+ } catch (final IOException ex) {
+ throw new SerializationException(ex);
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (final IOException ex) { // NOPMD
+ // ignore close exception
+ }
+ }
+ }
+
+ /**
+ *
+ * Deserializes a single {@code Object} from an array of bytes.
+ *
+ *
+ *
+ * If the call site incorrectly types the return value, a {@link ClassCastException} is thrown from the call site.
+ * Without Generics in this declaration, the call site must type cast and can cause the same ClassCastException.
+ * Note that in both cases, the ClassCastException is in the call site, not in this method.
+ *
+ *
+ * @param the object type to be deserialized
+ * @param objectData
+ * the serialized object, must not be null
+ * @return the deserialized object
+ * @throws IllegalArgumentException
+ * if {@code objectData} is {@code null}
+ * @throws SerializationException
+ * (runtime) if the serialization fails
+ */
+ public static T deserialize(final byte[] objectData) {
+ if (objectData == null) {
+ throw new IllegalArgumentException("The byte[] must not be null");
+ }
+ return SerializationUtils.deserialize(new ByteArrayInputStream(objectData));
+ }
+
+ /**
+ * Custom specialization of the standard JDK {@link java.io.ObjectInputStream}
+ * that uses a custom ClassLoader
to resolve a class.
+ * If the specified ClassLoader
is not able to resolve the class,
+ * the context classloader of the current thread will be used.
+ * This way, the standard deserialization work also in web-application
+ * containers and application servers, no matter in which of the
+ * ClassLoader
the particular class that encapsulates
+ * serialization/deserialization lives.
+ *
+ * For more in-depth information about the problem for which this
+ * class here is a workaround, see the JIRA issue LANG-626.
+ */
+ static class ClassLoaderAwareObjectInputStream extends ObjectInputStream {
+ private static final Map> primitiveTypes =
+ new HashMap>();
+
+ static {
+ primitiveTypes.put("byte", byte.class);
+ primitiveTypes.put("short", short.class);
+ primitiveTypes.put("int", int.class);
+ primitiveTypes.put("long", long.class);
+ primitiveTypes.put("float", float.class);
+ primitiveTypes.put("double", double.class);
+ primitiveTypes.put("boolean", boolean.class);
+ primitiveTypes.put("char", char.class);
+ primitiveTypes.put("void", void.class);
+ }
+
+ private final ClassLoader classLoader;
+
+ /**
+ * Constructor.
+ * @param in The InputStream
.
+ * @param classLoader classloader to use
+ * @throws IOException if an I/O error occurs while reading stream header.
+ * @see java.io.ObjectInputStream
+ */
+ public ClassLoaderAwareObjectInputStream(final InputStream in, final ClassLoader classLoader) throws IOException {
+ super(in);
+ this.classLoader = classLoader;
+ }
+
+ /**
+ * Overriden version that uses the parametrized ClassLoader
or the ClassLoader
+ * of the current Thread
to resolve the class.
+ * @param desc An instance of class ObjectStreamClass
.
+ * @return A Class
object corresponding to desc
.
+ * @throws IOException Any of the usual Input/Output exceptions.
+ * @throws ClassNotFoundException If class of a serialized object cannot be found.
+ */
+ @Override
+ protected Class> resolveClass(final ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ final String name = desc.getName();
+ try {
+ return Class.forName(name, false, classLoader);
+ } catch (final ClassNotFoundException ex) {
+ try {
+ return Class.forName(name, false, Thread.currentThread().getContextClassLoader());
+ } catch (final ClassNotFoundException cnfe) {
+ final Class> cls = primitiveTypes.get(name);
+ if (cls != null) {
+ return cls;
+ }
+ throw cnfe;
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/StringEscapeUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/StringEscapeUtils.java
new file mode 100644
index 000000000..a244847f4
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/StringEscapeUtils.java
@@ -0,0 +1,804 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.commons.lang3.text.translate.AggregateTranslator;
+import org.apache.commons.lang3.text.translate.CharSequenceTranslator;
+import org.apache.commons.lang3.text.translate.EntityArrays;
+import org.apache.commons.lang3.text.translate.JavaUnicodeEscaper;
+import org.apache.commons.lang3.text.translate.LookupTranslator;
+import org.apache.commons.lang3.text.translate.NumericEntityEscaper;
+import org.apache.commons.lang3.text.translate.NumericEntityUnescaper;
+import org.apache.commons.lang3.text.translate.OctalUnescaper;
+import org.apache.commons.lang3.text.translate.UnicodeUnescaper;
+import org.apache.commons.lang3.text.translate.UnicodeUnpairedSurrogateRemover;
+
+/**
+ * Escapes and unescapes {@code String}s for
+ * Java, Java Script, HTML and XML.
+ *
+ * #ThreadSafe#
+ * @since 2.0
+ */
+public class StringEscapeUtils {
+
+ /* ESCAPE TRANSLATORS */
+
+ /**
+ * Translator object for escaping Java.
+ *
+ * While {@link #escapeJava(String)} is the expected method of use, this
+ * object allows the Java escaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ public static final CharSequenceTranslator ESCAPE_JAVA =
+ new LookupTranslator(
+ new String[][] {
+ {"\"", "\\\""},
+ {"\\", "\\\\"},
+ }).with(
+ new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE())
+ ).with(
+ JavaUnicodeEscaper.outsideOf(32, 0x7f)
+ );
+
+ /**
+ * Translator object for escaping EcmaScript/JavaScript.
+ *
+ * While {@link #escapeEcmaScript(String)} is the expected method of use, this
+ * object allows the EcmaScript escaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ public static final CharSequenceTranslator ESCAPE_ECMASCRIPT =
+ new AggregateTranslator(
+ new LookupTranslator(
+ new String[][] {
+ {"'", "\\'"},
+ {"\"", "\\\""},
+ {"\\", "\\\\"},
+ {"/", "\\/"}
+ }),
+ new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE()),
+ JavaUnicodeEscaper.outsideOf(32, 0x7f)
+ );
+
+ /**
+ * Translator object for escaping Json.
+ *
+ * While {@link #escapeJson(String)} is the expected method of use, this
+ * object allows the Json escaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.2
+ */
+ public static final CharSequenceTranslator ESCAPE_JSON =
+ new AggregateTranslator(
+ new LookupTranslator(
+ new String[][] {
+ {"\"", "\\\""},
+ {"\\", "\\\\"},
+ {"/", "\\/"}
+ }),
+ new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE()),
+ JavaUnicodeEscaper.outsideOf(32, 0x7f)
+ );
+
+ /**
+ * Translator object for escaping XML.
+ *
+ * While {@link #escapeXml(String)} is the expected method of use, this
+ * object allows the XML escaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ * @deprecated use {@link #ESCAPE_XML10} or {@link #ESCAPE_XML11} instead.
+ */
+ @Deprecated
+ public static final CharSequenceTranslator ESCAPE_XML =
+ new AggregateTranslator(
+ new LookupTranslator(EntityArrays.BASIC_ESCAPE()),
+ new LookupTranslator(EntityArrays.APOS_ESCAPE())
+ );
+
+ /**
+ * Translator object for escaping XML 1.0.
+ *
+ * While {@link #escapeXml10(String)} is the expected method of use, this
+ * object allows the XML escaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.3
+ */
+ public static final CharSequenceTranslator ESCAPE_XML10 =
+ new AggregateTranslator(
+ new LookupTranslator(EntityArrays.BASIC_ESCAPE()),
+ new LookupTranslator(EntityArrays.APOS_ESCAPE()),
+ new LookupTranslator(
+ new String[][] {
+ { "\u0000", StringUtils.EMPTY },
+ { "\u0001", StringUtils.EMPTY },
+ { "\u0002", StringUtils.EMPTY },
+ { "\u0003", StringUtils.EMPTY },
+ { "\u0004", StringUtils.EMPTY },
+ { "\u0005", StringUtils.EMPTY },
+ { "\u0006", StringUtils.EMPTY },
+ { "\u0007", StringUtils.EMPTY },
+ { "\u0008", StringUtils.EMPTY },
+ { "\u000b", StringUtils.EMPTY },
+ { "\u000c", StringUtils.EMPTY },
+ { "\u000e", StringUtils.EMPTY },
+ { "\u000f", StringUtils.EMPTY },
+ { "\u0010", StringUtils.EMPTY },
+ { "\u0011", StringUtils.EMPTY },
+ { "\u0012", StringUtils.EMPTY },
+ { "\u0013", StringUtils.EMPTY },
+ { "\u0014", StringUtils.EMPTY },
+ { "\u0015", StringUtils.EMPTY },
+ { "\u0016", StringUtils.EMPTY },
+ { "\u0017", StringUtils.EMPTY },
+ { "\u0018", StringUtils.EMPTY },
+ { "\u0019", StringUtils.EMPTY },
+ { "\u001a", StringUtils.EMPTY },
+ { "\u001b", StringUtils.EMPTY },
+ { "\u001c", StringUtils.EMPTY },
+ { "\u001d", StringUtils.EMPTY },
+ { "\u001e", StringUtils.EMPTY },
+ { "\u001f", StringUtils.EMPTY },
+ { "\ufffe", StringUtils.EMPTY },
+ { "\uffff", StringUtils.EMPTY }
+ }),
+ NumericEntityEscaper.between(0x7f, 0x84),
+ NumericEntityEscaper.between(0x86, 0x9f),
+ new UnicodeUnpairedSurrogateRemover()
+ );
+
+ /**
+ * Translator object for escaping XML 1.1.
+ *
+ * While {@link #escapeXml11(String)} is the expected method of use, this
+ * object allows the XML escaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.3
+ */
+ public static final CharSequenceTranslator ESCAPE_XML11 =
+ new AggregateTranslator(
+ new LookupTranslator(EntityArrays.BASIC_ESCAPE()),
+ new LookupTranslator(EntityArrays.APOS_ESCAPE()),
+ new LookupTranslator(
+ new String[][] {
+ { "\u0000", StringUtils.EMPTY },
+ { "\u000b", "" },
+ { "\u000c", "" },
+ { "\ufffe", StringUtils.EMPTY },
+ { "\uffff", StringUtils.EMPTY }
+ }),
+ NumericEntityEscaper.between(0x1, 0x8),
+ NumericEntityEscaper.between(0xe, 0x1f),
+ NumericEntityEscaper.between(0x7f, 0x84),
+ NumericEntityEscaper.between(0x86, 0x9f),
+ new UnicodeUnpairedSurrogateRemover()
+ );
+
+ /**
+ * Translator object for escaping HTML version 3.0.
+ *
+ * While {@link #escapeHtml3(String)} is the expected method of use, this
+ * object allows the HTML escaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ public static final CharSequenceTranslator ESCAPE_HTML3 =
+ new AggregateTranslator(
+ new LookupTranslator(EntityArrays.BASIC_ESCAPE()),
+ new LookupTranslator(EntityArrays.ISO8859_1_ESCAPE())
+ );
+
+ /**
+ * Translator object for escaping HTML version 4.0.
+ *
+ * While {@link #escapeHtml4(String)} is the expected method of use, this
+ * object allows the HTML escaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ public static final CharSequenceTranslator ESCAPE_HTML4 =
+ new AggregateTranslator(
+ new LookupTranslator(EntityArrays.BASIC_ESCAPE()),
+ new LookupTranslator(EntityArrays.ISO8859_1_ESCAPE()),
+ new LookupTranslator(EntityArrays.HTML40_EXTENDED_ESCAPE())
+ );
+
+ /**
+ * Translator object for escaping individual Comma Separated Values.
+ *
+ * While {@link #escapeCsv(String)} is the expected method of use, this
+ * object allows the CSV escaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ public static final CharSequenceTranslator ESCAPE_CSV = new CsvEscaper();
+
+ // TODO: Create a parent class - 'SinglePassTranslator' ?
+ // It would handle the index checking + length returning,
+ // and could also have an optimization check method.
+ static class CsvEscaper extends CharSequenceTranslator {
+
+ private static final char CSV_DELIMITER = ',';
+ private static final char CSV_QUOTE = '"';
+ private static final String CSV_QUOTE_STR = String.valueOf(CSV_QUOTE);
+ private static final char[] CSV_SEARCH_CHARS =
+ new char[] {CSV_DELIMITER, CSV_QUOTE, CharUtils.CR, CharUtils.LF};
+
+ @Override
+ public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
+
+ if(index != 0) {
+ throw new IllegalStateException("CsvEscaper should never reach the [1] index");
+ }
+
+ if (StringUtils.containsNone(input.toString(), CSV_SEARCH_CHARS)) {
+ out.write(input.toString());
+ } else {
+ out.write(CSV_QUOTE);
+ out.write(StringUtils.replace(input.toString(), CSV_QUOTE_STR, CSV_QUOTE_STR + CSV_QUOTE_STR));
+ out.write(CSV_QUOTE);
+ }
+ return Character.codePointCount(input, 0, input.length());
+ }
+ }
+
+ /* UNESCAPE TRANSLATORS */
+
+ /**
+ * Translator object for unescaping escaped Java.
+ *
+ * While {@link #unescapeJava(String)} is the expected method of use, this
+ * object allows the Java unescaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ // TODO: throw "illegal character: \92" as an Exception if a \ on the end of the Java (as per the compiler)?
+ public static final CharSequenceTranslator UNESCAPE_JAVA =
+ new AggregateTranslator(
+ new OctalUnescaper(), // .between('\1', '\377'),
+ new UnicodeUnescaper(),
+ new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_UNESCAPE()),
+ new LookupTranslator(
+ new String[][] {
+ {"\\\\", "\\"},
+ {"\\\"", "\""},
+ {"\\'", "'"},
+ {"\\", ""}
+ })
+ );
+
+ /**
+ * Translator object for unescaping escaped EcmaScript.
+ *
+ * While {@link #unescapeEcmaScript(String)} is the expected method of use, this
+ * object allows the EcmaScript unescaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ public static final CharSequenceTranslator UNESCAPE_ECMASCRIPT = UNESCAPE_JAVA;
+
+ /**
+ * Translator object for unescaping escaped Json.
+ *
+ * While {@link #unescapeJson(String)} is the expected method of use, this
+ * object allows the Json unescaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.2
+ */
+ public static final CharSequenceTranslator UNESCAPE_JSON = UNESCAPE_JAVA;
+
+ /**
+ * Translator object for unescaping escaped HTML 3.0.
+ *
+ * While {@link #unescapeHtml3(String)} is the expected method of use, this
+ * object allows the HTML unescaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ public static final CharSequenceTranslator UNESCAPE_HTML3 =
+ new AggregateTranslator(
+ new LookupTranslator(EntityArrays.BASIC_UNESCAPE()),
+ new LookupTranslator(EntityArrays.ISO8859_1_UNESCAPE()),
+ new NumericEntityUnescaper()
+ );
+
+ /**
+ * Translator object for unescaping escaped HTML 4.0.
+ *
+ * While {@link #unescapeHtml4(String)} is the expected method of use, this
+ * object allows the HTML unescaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ public static final CharSequenceTranslator UNESCAPE_HTML4 =
+ new AggregateTranslator(
+ new LookupTranslator(EntityArrays.BASIC_UNESCAPE()),
+ new LookupTranslator(EntityArrays.ISO8859_1_UNESCAPE()),
+ new LookupTranslator(EntityArrays.HTML40_EXTENDED_UNESCAPE()),
+ new NumericEntityUnescaper()
+ );
+
+ /**
+ * Translator object for unescaping escaped XML.
+ *
+ * While {@link #unescapeXml(String)} is the expected method of use, this
+ * object allows the XML unescaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ public static final CharSequenceTranslator UNESCAPE_XML =
+ new AggregateTranslator(
+ new LookupTranslator(EntityArrays.BASIC_UNESCAPE()),
+ new LookupTranslator(EntityArrays.APOS_UNESCAPE()),
+ new NumericEntityUnescaper()
+ );
+
+ /**
+ * Translator object for unescaping escaped Comma Separated Value entries.
+ *
+ * While {@link #unescapeCsv(String)} is the expected method of use, this
+ * object allows the CSV unescaping functionality to be used
+ * as the foundation for a custom translator.
+ *
+ * @since 3.0
+ */
+ public static final CharSequenceTranslator UNESCAPE_CSV = new CsvUnescaper();
+
+ static class CsvUnescaper extends CharSequenceTranslator {
+
+ private static final char CSV_DELIMITER = ',';
+ private static final char CSV_QUOTE = '"';
+ private static final String CSV_QUOTE_STR = String.valueOf(CSV_QUOTE);
+ private static final char[] CSV_SEARCH_CHARS =
+ new char[] {CSV_DELIMITER, CSV_QUOTE, CharUtils.CR, CharUtils.LF};
+
+ @Override
+ public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
+
+ if(index != 0) {
+ throw new IllegalStateException("CsvUnescaper should never reach the [1] index");
+ }
+
+ if ( input.charAt(0) != CSV_QUOTE || input.charAt(input.length() - 1) != CSV_QUOTE ) {
+ out.write(input.toString());
+ return Character.codePointCount(input, 0, input.length());
+ }
+
+ // strip quotes
+ final String quoteless = input.subSequence(1, input.length() - 1).toString();
+
+ if ( StringUtils.containsAny(quoteless, CSV_SEARCH_CHARS) ) {
+ // deal with escaped quotes; ie) ""
+ out.write(StringUtils.replace(quoteless, CSV_QUOTE_STR + CSV_QUOTE_STR, CSV_QUOTE_STR));
+ } else {
+ out.write(input.toString());
+ }
+ return Character.codePointCount(input, 0, input.length());
+ }
+ }
+
+ /* Helper functions */
+
+ /**
+ * {@code StringEscapeUtils} instances should NOT be constructed in
+ * standard programming.
+ *
+ * Instead, the class should be used as:
+ * StringEscapeUtils.escapeJava("foo");
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public StringEscapeUtils() {
+ super();
+ }
+
+ // Java and JavaScript
+ //--------------------------------------------------------------------------
+ /**
+ * Escapes the characters in a {@code String} using Java String rules.
+ *
+ * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)
+ *
+ * So a tab becomes the characters {@code '\\'} and
+ * {@code 't'}.
+ *
+ * The only difference between Java strings and JavaScript strings
+ * is that in JavaScript, a single quote and forward-slash (/) are escaped.
+ *
+ * Example:
+ *
+ * input string: He didn't say, "Stop!"
+ * output string: He didn't say, \"Stop!\"
+ *
+ *
+ * @param input String to escape values in, may be null
+ * @return String with escaped values, {@code null} if null string input
+ */
+ public static final String escapeJava(final String input) {
+ return ESCAPE_JAVA.translate(input);
+ }
+
+ /**
+ * Escapes the characters in a {@code String} using EcmaScript String rules.
+ * Escapes any values it finds into their EcmaScript String form.
+ * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)
+ *
+ * So a tab becomes the characters {@code '\\'} and
+ * {@code 't'}.
+ *
+ * The only difference between Java strings and EcmaScript strings
+ * is that in EcmaScript, a single quote and forward-slash (/) are escaped.
+ *
+ * Note that EcmaScript is best known by the JavaScript and ActionScript dialects.
+ *
+ * Example:
+ *
+ * input string: He didn't say, "Stop!"
+ * output string: He didn\'t say, \"Stop!\"
+ *
+ *
+ * @param input String to escape values in, may be null
+ * @return String with escaped values, {@code null} if null string input
+ *
+ * @since 3.0
+ */
+ public static final String escapeEcmaScript(final String input) {
+ return ESCAPE_ECMASCRIPT.translate(input);
+ }
+
+ /**
+ * Escapes the characters in a {@code String} using Json String rules.
+ * Escapes any values it finds into their Json String form.
+ * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.)
+ *
+ * So a tab becomes the characters {@code '\\'} and
+ * {@code 't'}.
+ *
+ * The only difference between Java strings and Json strings
+ * is that in Json, forward-slash (/) is escaped.
+ *
+ * See http://www.ietf.org/rfc/rfc4627.txt for further details.
+ *
+ * Example:
+ *
+ * input string: He didn't say, "Stop!"
+ * output string: He didn't say, \"Stop!\"
+ *
+ *
+ * @param input String to escape values in, may be null
+ * @return String with escaped values, {@code null} if null string input
+ *
+ * @since 3.2
+ */
+ public static final String escapeJson(final String input) {
+ return ESCAPE_JSON.translate(input);
+ }
+
+ /**
+ * Unescapes any Java literals found in the {@code String}.
+ * For example, it will turn a sequence of {@code '\'} and
+ * {@code 'n'} into a newline character, unless the {@code '\'}
+ * is preceded by another {@code '\'}.
+ *
+ * @param input the {@code String} to unescape, may be null
+ * @return a new unescaped {@code String}, {@code null} if null string input
+ */
+ public static final String unescapeJava(final String input) {
+ return UNESCAPE_JAVA.translate(input);
+ }
+
+ /**
+ * Unescapes any EcmaScript literals found in the {@code String}.
+ *
+ * For example, it will turn a sequence of {@code '\'} and {@code 'n'}
+ * into a newline character, unless the {@code '\'} is preceded by another
+ * {@code '\'}.
+ *
+ * @see #unescapeJava(String)
+ * @param input the {@code String} to unescape, may be null
+ * @return A new unescaped {@code String}, {@code null} if null string input
+ *
+ * @since 3.0
+ */
+ public static final String unescapeEcmaScript(final String input) {
+ return UNESCAPE_ECMASCRIPT.translate(input);
+ }
+
+ /**
+ * Unescapes any Json literals found in the {@code String}.
+ *
+ * For example, it will turn a sequence of {@code '\'} and {@code 'n'}
+ * into a newline character, unless the {@code '\'} is preceded by another
+ * {@code '\'}.
+ *
+ * @see #unescapeJava(String)
+ * @param input the {@code String} to unescape, may be null
+ * @return A new unescaped {@code String}, {@code null} if null string input
+ *
+ * @since 3.2
+ */
+ public static final String unescapeJson(final String input) {
+ return UNESCAPE_JSON.translate(input);
+ }
+
+ // HTML and XML
+ //--------------------------------------------------------------------------
+ /**
+ * Escapes the characters in a {@code String} using HTML entities.
+ *
+ *
+ * For example:
+ *
+ * "bread" & "butter"
+ * becomes:
+ *
+ * "bread" & "butter"
.
+ *
+ *
+ * Supports all known HTML 4.0 entities, including funky accents.
+ * Note that the commonly used apostrophe escape character (')
+ * is not a legal entity and so is not supported).
+ *
+ * @param input the {@code String} to escape, may be null
+ * @return a new escaped {@code String}, {@code null} if null string input
+ *
+ * @see ISO Entities
+ * @see HTML 3.2 Character Entities for ISO Latin-1
+ * @see HTML 4.0 Character entity references
+ * @see HTML 4.01 Character References
+ * @see HTML 4.01 Code positions
+ *
+ * @since 3.0
+ */
+ public static final String escapeHtml4(final String input) {
+ return ESCAPE_HTML4.translate(input);
+ }
+
+ /**
+ * Escapes the characters in a {@code String} using HTML entities.
+ * Supports only the HTML 3.0 entities.
+ *
+ * @param input the {@code String} to escape, may be null
+ * @return a new escaped {@code String}, {@code null} if null string input
+ *
+ * @since 3.0
+ */
+ public static final String escapeHtml3(final String input) {
+ return ESCAPE_HTML3.translate(input);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Unescapes a string containing entity escapes to a string
+ * containing the actual Unicode characters corresponding to the
+ * escapes. Supports HTML 4.0 entities.
+ *
+ * For example, the string {@code "<Français>"}
+ * will become {@code ""}
+ *
+ * If an entity is unrecognized, it is left alone, and inserted
+ * verbatim into the result string. e.g. {@code ">&zzzz;x"} will
+ * become {@code ">&zzzz;x"}.
+ *
+ * @param input the {@code String} to unescape, may be null
+ * @return a new unescaped {@code String}, {@code null} if null string input
+ *
+ * @since 3.0
+ */
+ public static final String unescapeHtml4(final String input) {
+ return UNESCAPE_HTML4.translate(input);
+ }
+
+ /**
+ * Unescapes a string containing entity escapes to a string
+ * containing the actual Unicode characters corresponding to the
+ * escapes. Supports only HTML 3.0 entities.
+ *
+ * @param input the {@code String} to unescape, may be null
+ * @return a new unescaped {@code String}, {@code null} if null string input
+ *
+ * @since 3.0
+ */
+ public static final String unescapeHtml3(final String input) {
+ return UNESCAPE_HTML3.translate(input);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Escapes the characters in a {@code String} using XML entities.
+ *
+ * For example: {@code "bread" & "butter"} =>
+ * {@code "bread" & "butter"}.
+ *
+ *
+ * Supports only the five basic XML entities (gt, lt, quot, amp, apos).
+ * Does not support DTDs or external entities.
+ *
+ * Note that Unicode characters greater than 0x7f are as of 3.0, no longer
+ * escaped. If you still wish this functionality, you can achieve it
+ * via the following:
+ * {@code StringEscapeUtils.ESCAPE_XML.with( NumericEntityEscaper.between(0x7f, Integer.MAX_VALUE) );}
+ *
+ * @param input the {@code String} to escape, may be null
+ * @return a new escaped {@code String}, {@code null} if null string input
+ * @see #unescapeXml(java.lang.String)
+ * @deprecated use {@link #escapeXml10(java.lang.String)} or {@link #escapeXml11(java.lang.String)} instead.
+ */
+ @Deprecated
+ public static final String escapeXml(final String input) {
+ return ESCAPE_XML.translate(input);
+ }
+
+ /**
+ * Escapes the characters in a {@code String} using XML entities.
+ *
+ * For example: {@code "bread" & "butter"} =>
+ * {@code "bread" & "butter"}.
+ *
+ *
+ * Note that XML 1.0 is a text-only format: it cannot represent control
+ * characters or unpaired Unicode surrogate codepoints, even after escaping.
+ * {@code escapeXml10} will remove characters that do not fit in the
+ * following ranges:
+ *
+ * {@code #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]}
+ *
+ * Though not strictly necessary, {@code escapeXml10} will escape
+ * characters in the following ranges:
+ *
+ * {@code [#x7F-#x84] | [#x86-#x9F]}
+ *
+ * The returned string can be inserted into a valid XML 1.0 or XML 1.1
+ * document. If you want to allow more non-text characters in an XML 1.1
+ * document, use {@link #escapeXml11(String)}.
+ *
+ * @param input the {@code String} to escape, may be null
+ * @return a new escaped {@code String}, {@code null} if null string input
+ * @see #unescapeXml(java.lang.String)
+ * @since 3.3
+ */
+ public static String escapeXml10(final String input) {
+ return ESCAPE_XML10.translate(input);
+ }
+
+ /**
+ * Escapes the characters in a {@code String} using XML entities.
+ *
+ * For example: {@code "bread" & "butter"} =>
+ * {@code "bread" & "butter"}.
+ *
+ *
+ * XML 1.1 can represent certain control characters, but it cannot represent
+ * the null byte or unpaired Unicode surrogate codepoints, even after escaping.
+ * {@code escapeXml11} will remove characters that do not fit in the following
+ * ranges:
+ *
+ * {@code [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]}
+ *
+ * {@code escapeXml11} will escape characters in the following ranges:
+ *
+ * {@code [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]}
+ *
+ * The returned string can be inserted into a valid XML 1.1 document. Do not
+ * use it for XML 1.0 documents.
+ *
+ * @param input the {@code String} to escape, may be null
+ * @return a new escaped {@code String}, {@code null} if null string input
+ * @see #unescapeXml(java.lang.String)
+ * @since 3.3
+ */
+ public static String escapeXml11(final String input) {
+ return ESCAPE_XML11.translate(input);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Unescapes a string containing XML entity escapes to a string
+ * containing the actual Unicode characters corresponding to the
+ * escapes.
+ *
+ * Supports only the five basic XML entities (gt, lt, quot, amp, apos).
+ * Does not support DTDs or external entities.
+ *
+ * Note that numerical \\u Unicode codes are unescaped to their respective
+ * Unicode characters. This may change in future releases.
+ *
+ * @param input the {@code String} to unescape, may be null
+ * @return a new unescaped {@code String}, {@code null} if null string input
+ * @see #escapeXml(String)
+ * @see #escapeXml10(String)
+ * @see #escapeXml11(String)
+ */
+ public static final String unescapeXml(final String input) {
+ return UNESCAPE_XML.translate(input);
+ }
+
+ //-----------------------------------------------------------------------
+
+ /**
+ * Returns a {@code String} value for a CSV column enclosed in double quotes,
+ * if required.
+ *
+ * If the value contains a comma, newline or double quote, then the
+ * String value is returned enclosed in double quotes.
+ *
+ * Any double quote characters in the value are escaped with another double quote.
+ *
+ * If the value does not contain a comma, newline or double quote, then the
+ * String value is returned unchanged.
+ *
+ * see Wikipedia and
+ * RFC 4180 .
+ *
+ * @param input the input CSV column String, may be null
+ * @return the input String, enclosed in double quotes if the value contains a comma,
+ * newline or double quote, {@code null} if null string input
+ * @since 2.4
+ */
+ public static final String escapeCsv(final String input) {
+ return ESCAPE_CSV.translate(input);
+ }
+
+ /**
+ * Returns a {@code String} value for an unescaped CSV column.
+ *
+ * If the value is enclosed in double quotes, and contains a comma, newline
+ * or double quote, then quotes are removed.
+ *
+ *
+ * Any double quote escaped characters (a pair of double quotes) are unescaped
+ * to just one double quote.
+ *
+ * If the value is not enclosed in double quotes, or is and does not contain a
+ * comma, newline or double quote, then the String value is returned unchanged.
+ *
+ * see Wikipedia and
+ * RFC 4180 .
+ *
+ * @param input the input CSV column String, may be null
+ * @return the input String, with enclosing double quotes removed and embedded double
+ * quotes unescaped, {@code null} if null string input
+ * @since 2.4
+ */
+ public static final String unescapeCsv(final String input) {
+ return UNESCAPE_CSV.translate(input);
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/StringUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/StringUtils.java
new file mode 100644
index 000000000..879139423
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/StringUtils.java
@@ -0,0 +1,8822 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.text.Normalizer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.regex.Pattern;
+
+/**
+ * Operations on {@link java.lang.String} that are
+ * {@code null} safe.
+ *
+ *
+ * IsEmpty/IsBlank
+ * - checks if a String contains text
+ * Trim/Strip
+ * - removes leading and trailing whitespace
+ * Equals/Compare
+ * - compares two strings null-safe
+ * startsWith
+ * - check if a String starts with a prefix null-safe
+ * endsWith
+ * - check if a String ends with a suffix null-safe
+ * IndexOf/LastIndexOf/Contains
+ * - null-safe index-of checks
+ * IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut
+ * - index-of any of a set of Strings
+ * ContainsOnly/ContainsNone/ContainsAny
+ * - does String contains only/none/any of these characters
+ * Substring/Left/Right/Mid
+ * - null-safe substring extractions
+ * SubstringBefore/SubstringAfter/SubstringBetween
+ * - substring extraction relative to other strings
+ * Split/Join
+ * - splits a String into an array of substrings and vice versa
+ * Remove/Delete
+ * - removes part of a String
+ * Replace/Overlay
+ * - Searches a String and replaces one String with another
+ * Chomp/Chop
+ * - removes the last part of a String
+ * AppendIfMissing
+ * - appends a suffix to the end of the String if not present
+ * PrependIfMissing
+ * - prepends a prefix to the start of the String if not present
+ * LeftPad/RightPad/Center/Repeat
+ * - pads a String
+ * UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize
+ * - changes the case of a String
+ * CountMatches
+ * - counts the number of occurrences of one String in another
+ * IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable
+ * - checks the characters in a String
+ * DefaultString
+ * - protects against a null input String
+ * Rotate
+ * - rotate (circular shift) a String
+ * Reverse/ReverseDelimited
+ * - reverses a String
+ * Abbreviate
+ * - abbreviates a string using ellipsis
+ * Difference
+ * - compares Strings and reports on their differences
+ * LevenshteinDistance
+ * - the number of changes needed to change one String into another
+ *
+ *
+ * The {@code StringUtils} class defines certain words related to
+ * String handling.
+ *
+ *
+ * null - {@code null}
+ * empty - a zero-length string ({@code ""})
+ * space - the space character ({@code ' '}, char 32)
+ * whitespace - the characters defined by {@link Character#isWhitespace(char)}
+ * trim - the characters <= 32 as in {@link String#trim()}
+ *
+ *
+ * {@code StringUtils} handles {@code null} input Strings quietly.
+ * That is to say that a {@code null} input will return {@code null}.
+ * Where a {@code boolean} or {@code int} is being returned
+ * details vary by method.
+ *
+ * A side effect of the {@code null} handling is that a
+ * {@code NullPointerException} should be considered a bug in
+ * {@code StringUtils}.
+ *
+ * Methods in this class give sample code to explain their operation.
+ * The symbol {@code *} is used to indicate any input including {@code null}.
+ *
+ * #ThreadSafe#
+ * @see java.lang.String
+ * @since 1.0
+ */
+//@Immutable
+public class StringUtils {
+ // Performance testing notes (JDK 1.4, Jul03, scolebourne)
+ // Whitespace:
+ // Character.isWhitespace() is faster than WHITESPACE.indexOf()
+ // where WHITESPACE is a string of all whitespace characters
+ //
+ // Character access:
+ // String.charAt(n) versus toCharArray(), then array[n]
+ // String.charAt(n) is about 15% worse for a 10K string
+ // They are about equal for a length 50 string
+ // String.charAt(n) is about 4 times better for a length 3 string
+ // String.charAt(n) is best bet overall
+ //
+ // Append:
+ // String.concat about twice as fast as StringBuffer.append
+ // (not sure who tested this)
+
+ /**
+ * A String for a space character.
+ *
+ * @since 3.2
+ */
+ public static final String SPACE = " ";
+
+ /**
+ * The empty String {@code ""}.
+ * @since 2.0
+ */
+ public static final String EMPTY = "";
+
+ /**
+ * A String for linefeed LF ("\n").
+ *
+ * @see JLF: Escape Sequences
+ * for Character and String Literals
+ * @since 3.2
+ */
+ public static final String LF = "\n";
+
+ /**
+ * A String for carriage return CR ("\r").
+ *
+ * @see JLF: Escape Sequences
+ * for Character and String Literals
+ * @since 3.2
+ */
+ public static final String CR = "\r";
+
+ /**
+ * Represents a failed index search.
+ * @since 2.1
+ */
+ public static final int INDEX_NOT_FOUND = -1;
+
+ /**
+ * The maximum size to which the padding constant(s) can expand.
+ */
+ private static final int PAD_LIMIT = 8192;
+
+ /**
+ * {@code StringUtils} instances should NOT be constructed in
+ * standard programming. Instead, the class should be used as
+ * {@code StringUtils.trim(" foo ");}.
+ *
+ * This constructor is public to permit tools that require a JavaBean
+ * instance to operate.
+ */
+ public StringUtils() {
+ super();
+ }
+
+ // Empty checks
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if a CharSequence is empty ("") or null.
+ *
+ *
+ * StringUtils.isEmpty(null) = true
+ * StringUtils.isEmpty("") = true
+ * StringUtils.isEmpty(" ") = false
+ * StringUtils.isEmpty("bob") = false
+ * StringUtils.isEmpty(" bob ") = false
+ *
+ *
+ * NOTE: This method changed in Lang version 2.0.
+ * It no longer trims the CharSequence.
+ * That functionality is available in isBlank().
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if the CharSequence is empty or null
+ * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
+ */
+ public static boolean isEmpty(final CharSequence cs) {
+ return cs == null || cs.length() == 0;
+ }
+
+ /**
+ * Checks if a CharSequence is not empty ("") and not null.
+ *
+ *
+ * StringUtils.isNotEmpty(null) = false
+ * StringUtils.isNotEmpty("") = false
+ * StringUtils.isNotEmpty(" ") = true
+ * StringUtils.isNotEmpty("bob") = true
+ * StringUtils.isNotEmpty(" bob ") = true
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if the CharSequence is not empty and not null
+ * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
+ */
+ public static boolean isNotEmpty(final CharSequence cs) {
+ return !isEmpty(cs);
+ }
+
+ /**
+ * Checks if any one of the CharSequences are empty ("") or null.
+ *
+ *
+ * StringUtils.isAnyEmpty(null) = true
+ * StringUtils.isAnyEmpty(null, "foo") = true
+ * StringUtils.isAnyEmpty("", "bar") = true
+ * StringUtils.isAnyEmpty("bob", "") = true
+ * StringUtils.isAnyEmpty(" bob ", null) = true
+ * StringUtils.isAnyEmpty(" ", "bar") = false
+ * StringUtils.isAnyEmpty("foo", "bar") = false
+ *
+ *
+ * @param css the CharSequences to check, may be null or empty
+ * @return {@code true} if any of the CharSequences are empty or null
+ * @since 3.2
+ */
+ public static boolean isAnyEmpty(final CharSequence... css) {
+ if (ArrayUtils.isEmpty(css)) {
+ return true;
+ }
+ for (final CharSequence cs : css){
+ if (isEmpty(cs)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if none of the CharSequences are empty ("") or null.
+ *
+ *
+ * StringUtils.isNoneEmpty(null) = false
+ * StringUtils.isNoneEmpty(null, "foo") = false
+ * StringUtils.isNoneEmpty("", "bar") = false
+ * StringUtils.isNoneEmpty("bob", "") = false
+ * StringUtils.isNoneEmpty(" bob ", null) = false
+ * StringUtils.isNoneEmpty(" ", "bar") = true
+ * StringUtils.isNoneEmpty("foo", "bar") = true
+ *
+ *
+ * @param css the CharSequences to check, may be null or empty
+ * @return {@code true} if none of the CharSequences are empty or null
+ * @since 3.2
+ */
+ public static boolean isNoneEmpty(final CharSequence... css) {
+ return !isAnyEmpty(css);
+ }
+ /**
+ * Checks if a CharSequence is whitespace, empty ("") or null.
+ *
+ *
+ * StringUtils.isBlank(null) = true
+ * StringUtils.isBlank("") = true
+ * StringUtils.isBlank(" ") = true
+ * StringUtils.isBlank("bob") = false
+ * StringUtils.isBlank(" bob ") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if the CharSequence is null, empty or whitespace
+ * @since 2.0
+ * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
+ */
+ public static boolean isBlank(final CharSequence cs) {
+ int strLen;
+ if (cs == null || (strLen = cs.length()) == 0) {
+ return true;
+ }
+ for (int i = 0; i < strLen; i++) {
+ if (Character.isWhitespace(cs.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if a CharSequence is not empty (""), not null and not whitespace only.
+ *
+ *
+ * StringUtils.isNotBlank(null) = false
+ * StringUtils.isNotBlank("") = false
+ * StringUtils.isNotBlank(" ") = false
+ * StringUtils.isNotBlank("bob") = true
+ * StringUtils.isNotBlank(" bob ") = true
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if the CharSequence is
+ * not empty and not null and not whitespace
+ * @since 2.0
+ * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
+ */
+ public static boolean isNotBlank(final CharSequence cs) {
+ return !isBlank(cs);
+ }
+
+ /**
+ * Checks if any one of the CharSequences are blank ("") or null and not whitespace only..
+ *
+ *
+ * StringUtils.isAnyBlank(null) = true
+ * StringUtils.isAnyBlank(null, "foo") = true
+ * StringUtils.isAnyBlank(null, null) = true
+ * StringUtils.isAnyBlank("", "bar") = true
+ * StringUtils.isAnyBlank("bob", "") = true
+ * StringUtils.isAnyBlank(" bob ", null) = true
+ * StringUtils.isAnyBlank(" ", "bar") = true
+ * StringUtils.isAnyBlank("foo", "bar") = false
+ *
+ *
+ * @param css the CharSequences to check, may be null or empty
+ * @return {@code true} if any of the CharSequences are blank or null or whitespace only
+ * @since 3.2
+ */
+ public static boolean isAnyBlank(final CharSequence... css) {
+ if (ArrayUtils.isEmpty(css)) {
+ return true;
+ }
+ for (final CharSequence cs : css){
+ if (isBlank(cs)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if none of the CharSequences are blank ("") or null and whitespace only..
+ *
+ *
+ * StringUtils.isNoneBlank(null) = false
+ * StringUtils.isNoneBlank(null, "foo") = false
+ * StringUtils.isNoneBlank(null, null) = false
+ * StringUtils.isNoneBlank("", "bar") = false
+ * StringUtils.isNoneBlank("bob", "") = false
+ * StringUtils.isNoneBlank(" bob ", null) = false
+ * StringUtils.isNoneBlank(" ", "bar") = false
+ * StringUtils.isNoneBlank("foo", "bar") = true
+ *
+ *
+ * @param css the CharSequences to check, may be null or empty
+ * @return {@code true} if none of the CharSequences are blank or null or whitespace only
+ * @since 3.2
+ */
+ public static boolean isNoneBlank(final CharSequence... css) {
+ return !isAnyBlank(css);
+ }
+
+ // Trim
+ //-----------------------------------------------------------------------
+ /**
+ * Removes control characters (char <= 32) from both
+ * ends of this String, handling {@code null} by returning
+ * {@code null}.
+ *
+ * The String is trimmed using {@link String#trim()}.
+ * Trim removes start and end characters <= 32.
+ * To strip whitespace use {@link #strip(String)}.
+ *
+ * To trim your choice of characters, use the
+ * {@link #strip(String, String)} methods.
+ *
+ *
+ * StringUtils.trim(null) = null
+ * StringUtils.trim("") = ""
+ * StringUtils.trim(" ") = ""
+ * StringUtils.trim("abc") = "abc"
+ * StringUtils.trim(" abc ") = "abc"
+ *
+ *
+ * @param str the String to be trimmed, may be null
+ * @return the trimmed string, {@code null} if null String input
+ */
+ public static String trim(final String str) {
+ return str == null ? null : str.trim();
+ }
+
+ /**
+ * Removes control characters (char <= 32) from both
+ * ends of this String returning {@code null} if the String is
+ * empty ("") after the trim or if it is {@code null}.
+ *
+ *
The String is trimmed using {@link String#trim()}.
+ * Trim removes start and end characters <= 32.
+ * To strip whitespace use {@link #stripToNull(String)}.
+ *
+ *
+ * StringUtils.trimToNull(null) = null
+ * StringUtils.trimToNull("") = null
+ * StringUtils.trimToNull(" ") = null
+ * StringUtils.trimToNull("abc") = "abc"
+ * StringUtils.trimToNull(" abc ") = "abc"
+ *
+ *
+ * @param str the String to be trimmed, may be null
+ * @return the trimmed String,
+ * {@code null} if only chars <= 32, empty or null String input
+ * @since 2.0
+ */
+ public static String trimToNull(final String str) {
+ final String ts = trim(str);
+ return isEmpty(ts) ? null : ts;
+ }
+
+ /**
+ * Removes control characters (char <= 32) from both
+ * ends of this String returning an empty String ("") if the String
+ * is empty ("") after the trim or if it is {@code null}.
+ *
+ *
The String is trimmed using {@link String#trim()}.
+ * Trim removes start and end characters <= 32.
+ * To strip whitespace use {@link #stripToEmpty(String)}.
+ *
+ *
+ * StringUtils.trimToEmpty(null) = ""
+ * StringUtils.trimToEmpty("") = ""
+ * StringUtils.trimToEmpty(" ") = ""
+ * StringUtils.trimToEmpty("abc") = "abc"
+ * StringUtils.trimToEmpty(" abc ") = "abc"
+ *
+ *
+ * @param str the String to be trimmed, may be null
+ * @return the trimmed String, or an empty String if {@code null} input
+ * @since 2.0
+ */
+ public static String trimToEmpty(final String str) {
+ return str == null ? EMPTY : str.trim();
+ }
+
+ /**
+ * Truncates a String. This will turn
+ * "Now is the time for all good men" into "Now is the time for".
+ *
+ * Specifically:
+ *
+ * If {@code str} is less than {@code maxWidth} characters
+ * long, return it.
+ * Else truncate it to {@code substring(str, 0, maxWidth)}.
+ * If {@code maxWidth} is less than {@code 0}, throw an
+ * {@code IllegalArgumentException}.
+ * In no case will it return a String of length greater than
+ * {@code maxWidth}.
+ *
+ *
+ *
+ * StringUtils.truncate(null, 0) = null
+ * StringUtils.truncate(null, 2) = null
+ * StringUtils.truncate("", 4) = ""
+ * StringUtils.truncate("abcdefg", 4) = "abcd"
+ * StringUtils.truncate("abcdefg", 6) = "abcdef"
+ * StringUtils.truncate("abcdefg", 7) = "abcdefg"
+ * StringUtils.truncate("abcdefg", 8) = "abcdefg"
+ * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException
+ *
+ *
+ * @param str the String to truncate, may be null
+ * @param maxWidth maximum length of result String, must be positive
+ * @return truncated String, {@code null} if null String input
+ * @since 3.5
+ */
+ public static String truncate(final String str, int maxWidth) {
+ return truncate(str, 0, maxWidth);
+ }
+
+ /**
+ * Truncates a String. This will turn
+ * "Now is the time for all good men" into "is the time for all".
+ *
+ * Works like {@code truncate(String, int)}, but allows you to specify
+ * a "left edge" offset.
+ *
+ *
Specifically:
+ *
+ * If {@code str} is less than {@code maxWidth} characters
+ * long, return it.
+ * Else truncate it to {@code substring(str, offset, maxWidth)}.
+ * If {@code maxWidth} is less than {@code 0}, throw an
+ * {@code IllegalArgumentException}.
+ * If {@code offset} is less than {@code 0}, throw an
+ * {@code IllegalArgumentException}.
+ * In no case will it return a String of length greater than
+ * {@code maxWidth}.
+ *
+ *
+ *
+ * StringUtils.truncate(null, 0, 0) = null
+ * StringUtils.truncate(null, 2, 4) = null
+ * StringUtils.truncate("", 0, 10) = ""
+ * StringUtils.truncate("", 2, 10) = ""
+ * StringUtils.truncate("abcdefghij", 0, 3) = "abc"
+ * StringUtils.truncate("abcdefghij", 5, 6) = "fghij"
+ * StringUtils.truncate("raspberry peach", 10, 15) = "peach"
+ * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij"
+ * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException
+ * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = "abcdefghij"
+ * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = "abcdefghijklmno"
+ * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno"
+ * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk"
+ * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl"
+ * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm"
+ * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn"
+ * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno"
+ * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij"
+ * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh"
+ * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm"
+ * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno"
+ * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n"
+ * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no"
+ * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o"
+ * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o"
+ * StringUtils.truncate("abcdefghijklmno", 15, 1) = ""
+ * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = ""
+ * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = ""
+ * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException
+ * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException
+ *
+ *
+ * @param str the String to check, may be null
+ * @param offset left edge of source String
+ * @param maxWidth maximum length of result String, must be positive
+ * @return truncated String, {@code null} if null String input
+ * @since 3.5
+ */
+ public static String truncate(final String str, int offset, int maxWidth) {
+ if (offset < 0) {
+ throw new IllegalArgumentException("offset cannot be negative");
+ }
+ if (maxWidth < 0) {
+ throw new IllegalArgumentException("maxWith cannot be negative");
+ }
+ if (str == null) {
+ return null;
+ }
+ if (offset > str.length()) {
+ return EMPTY;
+ }
+ if (str.length() > maxWidth) {
+ int ix = offset + maxWidth > str.length() ? str.length() : offset + maxWidth;
+ return str.substring(offset, ix);
+ }
+ return str.substring(offset);
+ }
+
+ // Stripping
+ //-----------------------------------------------------------------------
+ /**
+ * Strips whitespace from the start and end of a String.
+ *
+ * This is similar to {@link #trim(String)} but removes whitespace.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ *
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.strip(null) = null
+ * StringUtils.strip("") = ""
+ * StringUtils.strip(" ") = ""
+ * StringUtils.strip("abc") = "abc"
+ * StringUtils.strip(" abc") = "abc"
+ * StringUtils.strip("abc ") = "abc"
+ * StringUtils.strip(" abc ") = "abc"
+ * StringUtils.strip(" ab c ") = "ab c"
+ *
+ *
+ * @param str the String to remove whitespace from, may be null
+ * @return the stripped String, {@code null} if null String input
+ */
+ public static String strip(final String str) {
+ return strip(str, null);
+ }
+
+ /**
+ * Strips whitespace from the start and end of a String returning
+ * {@code null} if the String is empty ("") after the strip.
+ *
+ * This is similar to {@link #trimToNull(String)} but removes whitespace.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ *
+ *
+ * StringUtils.stripToNull(null) = null
+ * StringUtils.stripToNull("") = null
+ * StringUtils.stripToNull(" ") = null
+ * StringUtils.stripToNull("abc") = "abc"
+ * StringUtils.stripToNull(" abc") = "abc"
+ * StringUtils.stripToNull("abc ") = "abc"
+ * StringUtils.stripToNull(" abc ") = "abc"
+ * StringUtils.stripToNull(" ab c ") = "ab c"
+ *
+ *
+ * @param str the String to be stripped, may be null
+ * @return the stripped String,
+ * {@code null} if whitespace, empty or null String input
+ * @since 2.0
+ */
+ public static String stripToNull(String str) {
+ if (str == null) {
+ return null;
+ }
+ str = strip(str, null);
+ return str.isEmpty() ? null : str;
+ }
+
+ /**
+ * Strips whitespace from the start and end of a String returning
+ * an empty String if {@code null} input.
+ *
+ * This is similar to {@link #trimToEmpty(String)} but removes whitespace.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ *
+ *
+ * StringUtils.stripToEmpty(null) = ""
+ * StringUtils.stripToEmpty("") = ""
+ * StringUtils.stripToEmpty(" ") = ""
+ * StringUtils.stripToEmpty("abc") = "abc"
+ * StringUtils.stripToEmpty(" abc") = "abc"
+ * StringUtils.stripToEmpty("abc ") = "abc"
+ * StringUtils.stripToEmpty(" abc ") = "abc"
+ * StringUtils.stripToEmpty(" ab c ") = "ab c"
+ *
+ *
+ * @param str the String to be stripped, may be null
+ * @return the trimmed String, or an empty String if {@code null} input
+ * @since 2.0
+ */
+ public static String stripToEmpty(final String str) {
+ return str == null ? EMPTY : strip(str, null);
+ }
+
+ /**
+ * Strips any of a set of characters from the start and end of a String.
+ * This is similar to {@link String#trim()} but allows the characters
+ * to be stripped to be controlled.
+ *
+ * A {@code null} input String returns {@code null}.
+ * An empty string ("") input returns the empty string.
+ *
+ * If the stripChars String is {@code null}, whitespace is
+ * stripped as defined by {@link Character#isWhitespace(char)}.
+ * Alternatively use {@link #strip(String)}.
+ *
+ *
+ * StringUtils.strip(null, *) = null
+ * StringUtils.strip("", *) = ""
+ * StringUtils.strip("abc", null) = "abc"
+ * StringUtils.strip(" abc", null) = "abc"
+ * StringUtils.strip("abc ", null) = "abc"
+ * StringUtils.strip(" abc ", null) = "abc"
+ * StringUtils.strip(" abcyx", "xyz") = " abc"
+ *
+ *
+ * @param str the String to remove characters from, may be null
+ * @param stripChars the characters to remove, null treated as whitespace
+ * @return the stripped String, {@code null} if null String input
+ */
+ public static String strip(String str, final String stripChars) {
+ if (isEmpty(str)) {
+ return str;
+ }
+ str = stripStart(str, stripChars);
+ return stripEnd(str, stripChars);
+ }
+
+ /**
+ * Strips any of a set of characters from the start of a String.
+ *
+ * A {@code null} input String returns {@code null}.
+ * An empty string ("") input returns the empty string.
+ *
+ * If the stripChars String is {@code null}, whitespace is
+ * stripped as defined by {@link Character#isWhitespace(char)}.
+ *
+ *
+ * StringUtils.stripStart(null, *) = null
+ * StringUtils.stripStart("", *) = ""
+ * StringUtils.stripStart("abc", "") = "abc"
+ * StringUtils.stripStart("abc", null) = "abc"
+ * StringUtils.stripStart(" abc", null) = "abc"
+ * StringUtils.stripStart("abc ", null) = "abc "
+ * StringUtils.stripStart(" abc ", null) = "abc "
+ * StringUtils.stripStart("yxabc ", "xyz") = "abc "
+ *
+ *
+ * @param str the String to remove characters from, may be null
+ * @param stripChars the characters to remove, null treated as whitespace
+ * @return the stripped String, {@code null} if null String input
+ */
+ public static String stripStart(final String str, final String stripChars) {
+ int strLen;
+ if (str == null || (strLen = str.length()) == 0) {
+ return str;
+ }
+ int start = 0;
+ if (stripChars == null) {
+ while (start != strLen && Character.isWhitespace(str.charAt(start))) {
+ start++;
+ }
+ } else if (stripChars.isEmpty()) {
+ return str;
+ } else {
+ while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {
+ start++;
+ }
+ }
+ return str.substring(start);
+ }
+
+ /**
+ * Strips any of a set of characters from the end of a String.
+ *
+ * A {@code null} input String returns {@code null}.
+ * An empty string ("") input returns the empty string.
+ *
+ * If the stripChars String is {@code null}, whitespace is
+ * stripped as defined by {@link Character#isWhitespace(char)}.
+ *
+ *
+ * StringUtils.stripEnd(null, *) = null
+ * StringUtils.stripEnd("", *) = ""
+ * StringUtils.stripEnd("abc", "") = "abc"
+ * StringUtils.stripEnd("abc", null) = "abc"
+ * StringUtils.stripEnd(" abc", null) = " abc"
+ * StringUtils.stripEnd("abc ", null) = "abc"
+ * StringUtils.stripEnd(" abc ", null) = " abc"
+ * StringUtils.stripEnd(" abcyx", "xyz") = " abc"
+ * StringUtils.stripEnd("120.00", ".0") = "12"
+ *
+ *
+ * @param str the String to remove characters from, may be null
+ * @param stripChars the set of characters to remove, null treated as whitespace
+ * @return the stripped String, {@code null} if null String input
+ */
+ public static String stripEnd(final String str, final String stripChars) {
+ int end;
+ if (str == null || (end = str.length()) == 0) {
+ return str;
+ }
+
+ if (stripChars == null) {
+ while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
+ end--;
+ }
+ } else if (stripChars.isEmpty()) {
+ return str;
+ } else {
+ while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {
+ end--;
+ }
+ }
+ return str.substring(0, end);
+ }
+
+ // StripAll
+ //-----------------------------------------------------------------------
+ /**
+ * Strips whitespace from the start and end of every String in an array.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ *
+ * A new array is returned each time, except for length zero.
+ * A {@code null} array will return {@code null}.
+ * An empty array will return itself.
+ * A {@code null} array entry will be ignored.
+ *
+ *
+ * StringUtils.stripAll(null) = null
+ * StringUtils.stripAll([]) = []
+ * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"]
+ * StringUtils.stripAll(["abc ", null]) = ["abc", null]
+ *
+ *
+ * @param strs the array to remove whitespace from, may be null
+ * @return the stripped Strings, {@code null} if null array input
+ */
+ public static String[] stripAll(final String... strs) {
+ return stripAll(strs, null);
+ }
+
+ /**
+ * Strips any of a set of characters from the start and end of every
+ * String in an array.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ *
+ * A new array is returned each time, except for length zero.
+ * A {@code null} array will return {@code null}.
+ * An empty array will return itself.
+ * A {@code null} array entry will be ignored.
+ * A {@code null} stripChars will strip whitespace as defined by
+ * {@link Character#isWhitespace(char)}.
+ *
+ *
+ * StringUtils.stripAll(null, *) = null
+ * StringUtils.stripAll([], *) = []
+ * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"]
+ * StringUtils.stripAll(["abc ", null], null) = ["abc", null]
+ * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null]
+ * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null]
+ *
+ *
+ * @param strs the array to remove characters from, may be null
+ * @param stripChars the characters to remove, null treated as whitespace
+ * @return the stripped Strings, {@code null} if null array input
+ */
+ public static String[] stripAll(final String[] strs, final String stripChars) {
+ int strsLen;
+ if (strs == null || (strsLen = strs.length) == 0) {
+ return strs;
+ }
+ final String[] newArr = new String[strsLen];
+ for (int i = 0; i < strsLen; i++) {
+ newArr[i] = strip(strs[i], stripChars);
+ }
+ return newArr;
+ }
+
+ /**
+ * Removes diacritics (~= accents) from a string. The case will not be altered.
+ * For instance, 'à' will be replaced by 'a'.
+ * Note that ligatures will be left as is.
+ *
+ *
+ * StringUtils.stripAccents(null) = null
+ * StringUtils.stripAccents("") = ""
+ * StringUtils.stripAccents("control") = "control"
+ * StringUtils.stripAccents("éclair") = "eclair"
+ *
+ *
+ * @param input String to be stripped
+ * @return input text with diacritics removed
+ *
+ * @since 3.0
+ */
+ // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907).
+ public static String stripAccents(final String input) {
+ if(input == null) {
+ return null;
+ }
+ final Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");//$NON-NLS-1$
+ final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFD));
+ convertRemainingAccentCharacters(decomposed);
+ // Note that this doesn't correctly remove ligatures...
+ return pattern.matcher(decomposed).replaceAll(StringUtils.EMPTY);
+ }
+
+ private static void convertRemainingAccentCharacters(StringBuilder decomposed) {
+ for (int i = 0; i < decomposed.length(); i++) {
+ if (decomposed.charAt(i) == '\u0141') {
+ decomposed.deleteCharAt(i);
+ decomposed.insert(i, 'L');
+ } else if (decomposed.charAt(i) == '\u0142') {
+ decomposed.deleteCharAt(i);
+ decomposed.insert(i, 'l');
+ }
+ }
+ }
+
+ // Equals
+ //-----------------------------------------------------------------------
+ /**
+ * Compares two CharSequences, returning {@code true} if they represent
+ * equal sequences of characters.
+ *
+ * {@code null}s are handled without exceptions. Two {@code null}
+ * references are considered to be equal. The comparison is case sensitive.
+ *
+ *
+ * StringUtils.equals(null, null) = true
+ * StringUtils.equals(null, "abc") = false
+ * StringUtils.equals("abc", null) = false
+ * StringUtils.equals("abc", "abc") = true
+ * StringUtils.equals("abc", "ABC") = false
+ *
+ *
+ * @see Object#equals(Object)
+ * @param cs1 the first CharSequence, may be {@code null}
+ * @param cs2 the second CharSequence, may be {@code null}
+ * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
+ * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
+ */
+ public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
+ if (cs1 == cs2) {
+ return true;
+ }
+ if (cs1 == null || cs2 == null) {
+ return false;
+ }
+ if (cs1.length() != cs2.length()) {
+ return false;
+ }
+ if (cs1 instanceof String && cs2 instanceof String) {
+ return cs1.equals(cs2);
+ }
+ return CharSequenceUtils.regionMatches(cs1, false, 0, cs2, 0, cs1.length());
+ }
+
+ /**
+ * Compares two CharSequences, returning {@code true} if they represent
+ * equal sequences of characters, ignoring case.
+ *
+ * {@code null}s are handled without exceptions. Two {@code null}
+ * references are considered equal. Comparison is case insensitive.
+ *
+ *
+ * StringUtils.equalsIgnoreCase(null, null) = true
+ * StringUtils.equalsIgnoreCase(null, "abc") = false
+ * StringUtils.equalsIgnoreCase("abc", null) = false
+ * StringUtils.equalsIgnoreCase("abc", "abc") = true
+ * StringUtils.equalsIgnoreCase("abc", "ABC") = true
+ *
+ *
+ * @param str1 the first CharSequence, may be null
+ * @param str2 the second CharSequence, may be null
+ * @return {@code true} if the CharSequence are equal, case insensitive, or
+ * both {@code null}
+ * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence)
+ */
+ public static boolean equalsIgnoreCase(final CharSequence str1, final CharSequence str2) {
+ if (str1 == null || str2 == null) {
+ return str1 == str2;
+ } else if (str1 == str2) {
+ return true;
+ } else if (str1.length() != str2.length()) {
+ return false;
+ } else {
+ return CharSequenceUtils.regionMatches(str1, true, 0, str2, 0, str1.length());
+ }
+ }
+
+ // Compare
+ //-----------------------------------------------------------------------
+ /**
+ * Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
+ *
+ * {@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})
+ * {@code int < 0}, if {@code str1} is less than {@code str2}
+ * {@code int > 0}, if {@code str1} is greater than {@code str2}
+ *
+ *
+ * This is a {@code null} safe version of :
+ * str1.compareTo(str2)
+ *
+ * {@code null} value is considered less than non-{@code null} value.
+ * Two {@code null} references are considered equal.
+ *
+ *
+ * StringUtils.compare(null, null) = 0
+ * StringUtils.compare(null , "a") < 0
+ * StringUtils.compare("a", null) > 0
+ * StringUtils.compare("abc", "abc") = 0
+ * StringUtils.compare("a", "b") < 0
+ * StringUtils.compare("b", "a") > 0
+ * StringUtils.compare("a", "B") > 0
+ * StringUtils.compare("ab", "abc") < 0
+ *
+ *
+ * @see #compare(String, String, boolean)
+ * @see String#compareTo(String)
+ * @param str1 the String to compare from
+ * @param str2 the String to compare to
+ * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}
+ * @since 3.5
+ */
+ public static int compare(final String str1, final String str2) {
+ return compare(str1, str2, true);
+ }
+
+ /**
+ * Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
+ *
+ * {@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})
+ * {@code int < 0}, if {@code str1} is less than {@code str2}
+ * {@code int > 0}, if {@code str1} is greater than {@code str2}
+ *
+ *
+ * This is a {@code null} safe version of :
+ * str1.compareTo(str2)
+ *
+ * {@code null} inputs are handled according to the {@code nullIsLess} parameter.
+ * Two {@code null} references are considered equal.
+ *
+ *
+ * StringUtils.compare(null, null, *) = 0
+ * StringUtils.compare(null , "a", true) < 0
+ * StringUtils.compare(null , "a", false) > 0
+ * StringUtils.compare("a", null, true) > 0
+ * StringUtils.compare("a", null, false) < 0
+ * StringUtils.compare("abc", "abc", *) = 0
+ * StringUtils.compare("a", "b", *) < 0
+ * StringUtils.compare("b", "a", *) > 0
+ * StringUtils.compare("a", "B", *) > 0
+ * StringUtils.compare("ab", "abc", *) < 0
+ *
+ *
+ * @see String#compareTo(String)
+ * @param str1 the String to compare from
+ * @param str2 the String to compare to
+ * @param nullIsLess whether consider {@code null} value less than non-{@code null} value
+ * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}
+ * @since 3.5
+ */
+ public static int compare(final String str1, final String str2, final boolean nullIsLess) {
+ if (str1 == str2) {
+ return 0;
+ }
+ if (str1 == null) {
+ return nullIsLess ? -1 : 1;
+ }
+ if (str2 == null) {
+ return nullIsLess ? 1 : - 1;
+ }
+ return str1.compareTo(str2);
+ }
+
+ /**
+ * Compare two Strings lexicographically, ignoring case differences,
+ * as per {@link String#compareToIgnoreCase(String)}, returning :
+ *
+ * {@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})
+ * {@code int < 0}, if {@code str1} is less than {@code str2}
+ * {@code int > 0}, if {@code str1} is greater than {@code str2}
+ *
+ *
+ * This is a {@code null} safe version of :
+ * str1.compareToIgnoreCase(str2)
+ *
+ * {@code null} value is considered less than non-{@code null} value.
+ * Two {@code null} references are considered equal.
+ * Comparison is case insensitive.
+ *
+ *
+ * StringUtils.compareIgnoreCase(null, null) = 0
+ * StringUtils.compareIgnoreCase(null , "a") < 0
+ * StringUtils.compareIgnoreCase("a", null) > 0
+ * StringUtils.compareIgnoreCase("abc", "abc") = 0
+ * StringUtils.compareIgnoreCase("abc", "ABC") = 0
+ * StringUtils.compareIgnoreCase("a", "b") < 0
+ * StringUtils.compareIgnoreCase("b", "a") > 0
+ * StringUtils.compareIgnoreCase("a", "B") < 0
+ * StringUtils.compareIgnoreCase("A", "b") < 0
+ * StringUtils.compareIgnoreCase("ab", "ABC") < 0
+ *
+ *
+ * @see #compareIgnoreCase(String, String, boolean)
+ * @see String#compareToIgnoreCase(String)
+ * @param str1 the String to compare from
+ * @param str2 the String to compare to
+ * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
+ * ignoring case differences.
+ * @since 3.5
+ */
+ public static int compareIgnoreCase(final String str1, final String str2) {
+ return compareIgnoreCase(str1, str2, true);
+ }
+
+ /**
+ * Compare two Strings lexicographically, ignoring case differences,
+ * as per {@link String#compareToIgnoreCase(String)}, returning :
+ *
+ * {@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})
+ * {@code int < 0}, if {@code str1} is less than {@code str2}
+ * {@code int > 0}, if {@code str1} is greater than {@code str2}
+ *
+ *
+ * This is a {@code null} safe version of :
+ * str1.compareToIgnoreCase(str2)
+ *
+ * {@code null} inputs are handled according to the {@code nullIsLess} parameter.
+ * Two {@code null} references are considered equal.
+ * Comparison is case insensitive.
+ *
+ *
+ * StringUtils.compareIgnoreCase(null, null, *) = 0
+ * StringUtils.compareIgnoreCase(null , "a", true) < 0
+ * StringUtils.compareIgnoreCase(null , "a", false) > 0
+ * StringUtils.compareIgnoreCase("a", null, true) > 0
+ * StringUtils.compareIgnoreCase("a", null, false) < 0
+ * StringUtils.compareIgnoreCase("abc", "abc", *) = 0
+ * StringUtils.compareIgnoreCase("abc", "ABC", *) = 0
+ * StringUtils.compareIgnoreCase("a", "b", *) < 0
+ * StringUtils.compareIgnoreCase("b", "a", *) > 0
+ * StringUtils.compareIgnoreCase("a", "B", *) < 0
+ * StringUtils.compareIgnoreCase("A", "b", *) < 0
+ * StringUtils.compareIgnoreCase("ab", "abc", *) < 0
+ *
+ *
+ * @see String#compareToIgnoreCase(String)
+ * @param str1 the String to compare from
+ * @param str2 the String to compare to
+ * @param nullIsLess whether consider {@code null} value less than non-{@code null} value
+ * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
+ * ignoring case differences.
+ * @since 3.5
+ */
+ public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) {
+ if (str1 == str2) {
+ return 0;
+ }
+ if (str1 == null) {
+ return nullIsLess ? -1 : 1;
+ }
+ if (str2 == null) {
+ return nullIsLess ? 1 : - 1;
+ }
+ return str1.compareToIgnoreCase(str2);
+ }
+
+ /**
+ * Compares given string
to a CharSequences vararg of searchStrings
,
+ * returning {@code true} if the string
is equal to any of the searchStrings
.
+ *
+ *
+ * StringUtils.equalsAny(null, (CharSequence[]) null) = false
+ * StringUtils.equalsAny(null, null, null) = true
+ * StringUtils.equalsAny(null, "abc", "def") = false
+ * StringUtils.equalsAny("abc", null, "def") = false
+ * StringUtils.equalsAny("abc", "abc", "def") = true
+ * StringUtils.equalsAny("abc", "ABC", "DEF") = false
+ *
+ *
+ * @param string to compare, may be {@code null}.
+ * @param searchStrings a vararg of strings, may be {@code null}.
+ * @return {@code true} if the string is equal (case-sensitive) to any other element of searchStrings
;
+ * {@code false} if searchStrings
is null or contains no matches.
+ * @since 3.5
+ */
+ public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) {
+ if (ArrayUtils.isNotEmpty(searchStrings)) {
+ for (CharSequence next : searchStrings) {
+ if (equals(string, next)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Compares given string
to a CharSequences vararg of searchStrings
,
+ * returning {@code true} if the string
is equal to any of the searchStrings
, ignoring case.
+ *
+ *
+ * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
+ * StringUtils.equalsAnyIgnoreCase(null, null, null) = true
+ * StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false
+ * StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false
+ * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
+ * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true
+ *
+ *
+ * @param string to compare, may be {@code null}.
+ * @param searchStrings a vararg of strings, may be {@code null}.
+ * @return {@code true} if the string is equal (case-insensitive) to any other element of searchStrings
;
+ * {@code false} if searchStrings
is null or contains no matches.
+ * @since 3.5
+ */
+ public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence...searchStrings) {
+ if (ArrayUtils.isNotEmpty(searchStrings)) {
+ for (CharSequence next : searchStrings) {
+ if (equalsIgnoreCase(string, next)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ // IndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * Finds the first index within a CharSequence, handling {@code null}.
+ * This method uses {@link String#indexOf(int, int)} if possible.
+ *
+ * A {@code null} or empty ("") CharSequence will return {@code INDEX_NOT_FOUND (-1)}.
+ *
+ *
+ * StringUtils.indexOf(null, *) = -1
+ * StringUtils.indexOf("", *) = -1
+ * StringUtils.indexOf("aabaabaa", 'a') = 0
+ * StringUtils.indexOf("aabaabaa", 'b') = 2
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchChar the character to find
+ * @return the first index of the search character,
+ * -1 if no match or {@code null} string input
+ * @since 2.0
+ * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int)
+ */
+ public static int indexOf(final CharSequence seq, final int searchChar) {
+ if (isEmpty(seq)) {
+ return INDEX_NOT_FOUND;
+ }
+ return CharSequenceUtils.indexOf(seq, searchChar, 0);
+ }
+
+ /**
+ * Finds the first index within a CharSequence from a start position,
+ * handling {@code null}.
+ * This method uses {@link String#indexOf(int, int)} if possible.
+ *
+ * A {@code null} or empty ("") CharSequence will return {@code (INDEX_NOT_FOUND) -1}.
+ * A negative start position is treated as zero.
+ * A start position greater than the string length returns {@code -1}.
+ *
+ *
+ * StringUtils.indexOf(null, *, *) = -1
+ * StringUtils.indexOf("", *, *) = -1
+ * StringUtils.indexOf("aabaabaa", 'b', 0) = 2
+ * StringUtils.indexOf("aabaabaa", 'b', 3) = 5
+ * StringUtils.indexOf("aabaabaa", 'b', 9) = -1
+ * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchChar the character to find
+ * @param startPos the start position, negative treated as zero
+ * @return the first index of the search character (always ≥ startPos),
+ * -1 if no match or {@code null} string input
+ * @since 2.0
+ * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int)
+ */
+ public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) {
+ if (isEmpty(seq)) {
+ return INDEX_NOT_FOUND;
+ }
+ return CharSequenceUtils.indexOf(seq, searchChar, startPos);
+ }
+
+ /**
+ * Finds the first index within a CharSequence, handling {@code null}.
+ * This method uses {@link String#indexOf(String, int)} if possible.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ *
+ *
+ * StringUtils.indexOf(null, *) = -1
+ * StringUtils.indexOf(*, null) = -1
+ * StringUtils.indexOf("", "") = 0
+ * StringUtils.indexOf("", *) = -1 (except when * = "")
+ * StringUtils.indexOf("aabaabaa", "a") = 0
+ * StringUtils.indexOf("aabaabaa", "b") = 2
+ * StringUtils.indexOf("aabaabaa", "ab") = 1
+ * StringUtils.indexOf("aabaabaa", "") = 0
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchSeq the CharSequence to find, may be null
+ * @return the first index of the search CharSequence,
+ * -1 if no match or {@code null} string input
+ * @since 2.0
+ * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence)
+ */
+ public static int indexOf(final CharSequence seq, final CharSequence searchSeq) {
+ if (seq == null || searchSeq == null) {
+ return INDEX_NOT_FOUND;
+ }
+ return CharSequenceUtils.indexOf(seq, searchSeq, 0);
+ }
+
+ /**
+ * Finds the first index within a CharSequence, handling {@code null}.
+ * This method uses {@link String#indexOf(String, int)} if possible.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ * A negative start position is treated as zero.
+ * An empty ("") search CharSequence always matches.
+ * A start position greater than the string length only matches
+ * an empty search CharSequence.
+ *
+ *
+ * StringUtils.indexOf(null, *, *) = -1
+ * StringUtils.indexOf(*, null, *) = -1
+ * StringUtils.indexOf("", "", 0) = 0
+ * StringUtils.indexOf("", *, 0) = -1 (except when * = "")
+ * StringUtils.indexOf("aabaabaa", "a", 0) = 0
+ * StringUtils.indexOf("aabaabaa", "b", 0) = 2
+ * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
+ * StringUtils.indexOf("aabaabaa", "b", 3) = 5
+ * StringUtils.indexOf("aabaabaa", "b", 9) = -1
+ * StringUtils.indexOf("aabaabaa", "b", -1) = 2
+ * StringUtils.indexOf("aabaabaa", "", 2) = 2
+ * StringUtils.indexOf("abc", "", 9) = 3
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchSeq the CharSequence to find, may be null
+ * @param startPos the start position, negative treated as zero
+ * @return the first index of the search CharSequence (always ≥ startPos),
+ * -1 if no match or {@code null} string input
+ * @since 2.0
+ * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int)
+ */
+ public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
+ if (seq == null || searchSeq == null) {
+ return INDEX_NOT_FOUND;
+ }
+ return CharSequenceUtils.indexOf(seq, searchSeq, startPos);
+ }
+
+ /**
+ * Finds the n-th index within a CharSequence, handling {@code null}.
+ * This method uses {@link String#indexOf(String)} if possible.
+ * Note: The code starts looking for a match at the start of the target,
+ * incrementing the starting index by one after each successful match.
+ * The code increments the starting index by one,
+ * rather than by the length of the match string,
+ * so matches may overlap.
+ * A {@code null} CharSequence will return {@code -1}.
+ *
+ *
+ * StringUtils.ordinalIndexOf(null, *, *) = -1
+ * StringUtils.ordinalIndexOf(*, null, *) = -1
+ * StringUtils.ordinalIndexOf("", "", *) = 0
+ * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0
+ * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1
+ * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2
+ * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5
+ * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
+ * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
+ * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0
+ * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0
+ *
+ *
+ * Matches may overlap:
+ *
+ * StringUtils.ordinalIndexOf("ababab","aba", 1) = 0
+ * StringUtils.ordinalIndexOf("ababab","aba", 2) = 2
+ * StringUtils.ordinalIndexOf("ababab","aba", 3) = -1
+ *
+ * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0
+ * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2
+ * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4
+ * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1
+ *
+ *
+ * Note that 'head(CharSequence str, int n)' may be implemented as:
+ *
+ *
+ * str.substring(0, lastOrdinalIndexOf(str, "\n", n))
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param searchStr the CharSequence to find, may be null
+ * @param ordinal the n-th {@code searchStr} to find
+ * @return the n-th index of the search CharSequence,
+ * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
+ * @since 2.1
+ * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int)
+ */
+ public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
+ return ordinalIndexOf(str, searchStr, ordinal, false);
+ }
+
+ /**
+ * Finds the n-th index within a String, handling {@code null}.
+ * This method uses {@link String#indexOf(String)} if possible.
+ * Note that matches may overlap
+ *
+ *
A {@code null} CharSequence will return {@code -1}.
+ *
+ * @param str the CharSequence to check, may be null
+ * @param searchStr the CharSequence to find, may be null
+ * @param ordinal the n-th {@code searchStr} to find, overlapping matches are allowed.
+ * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
+ * @return the n-th index of the search CharSequence,
+ * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
+ */
+ // Shared code between ordinalIndexOf(String,String,int) and lastOrdinalIndexOf(String,String,int)
+ private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) {
+ if (str == null || searchStr == null || ordinal <= 0) {
+ return INDEX_NOT_FOUND;
+ }
+ if (searchStr.length() == 0) {
+ return lastIndex ? str.length() : 0;
+ }
+ int found = 0;
+ // set the initial index beyond the end of the string
+ // this is to allow for the initial index decrement/increment
+ int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
+ do {
+ if (lastIndex) {
+ index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards thru string
+ } else {
+ index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string
+ }
+ if (index < 0) {
+ return index;
+ }
+ found++;
+ } while (found < ordinal);
+ return index;
+ }
+
+ /**
+ * Case in-sensitive find of the first index within a CharSequence.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ * A negative start position is treated as zero.
+ * An empty ("") search CharSequence always matches.
+ * A start position greater than the string length only matches
+ * an empty search CharSequence.
+ *
+ *
+ * StringUtils.indexOfIgnoreCase(null, *) = -1
+ * StringUtils.indexOfIgnoreCase(*, null) = -1
+ * StringUtils.indexOfIgnoreCase("", "") = 0
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param searchStr the CharSequence to find, may be null
+ * @return the first index of the search CharSequence,
+ * -1 if no match or {@code null} string input
+ * @since 2.5
+ * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence)
+ */
+ public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
+ return indexOfIgnoreCase(str, searchStr, 0);
+ }
+
+ /**
+ * Case in-sensitive find of the first index within a CharSequence
+ * from the specified position.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ * A negative start position is treated as zero.
+ * An empty ("") search CharSequence always matches.
+ * A start position greater than the string length only matches
+ * an empty search CharSequence.
+ *
+ *
+ * StringUtils.indexOfIgnoreCase(null, *, *) = -1
+ * StringUtils.indexOfIgnoreCase(*, null, *) = -1
+ * StringUtils.indexOfIgnoreCase("", "", 0) = 0
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
+ * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2
+ * StringUtils.indexOfIgnoreCase("abc", "", 9) = -1
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param searchStr the CharSequence to find, may be null
+ * @param startPos the start position, negative treated as zero
+ * @return the first index of the search CharSequence (always ≥ startPos),
+ * -1 if no match or {@code null} string input
+ * @since 2.5
+ * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int)
+ */
+ public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) {
+ if (str == null || searchStr == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startPos < 0) {
+ startPos = 0;
+ }
+ final int endLimit = str.length() - searchStr.length() + 1;
+ if (startPos > endLimit) {
+ return INDEX_NOT_FOUND;
+ }
+ if (searchStr.length() == 0) {
+ return startPos;
+ }
+ for (int i = startPos; i < endLimit; i++) {
+ if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ // LastIndexOf
+ //-----------------------------------------------------------------------
+ /**
+ * Finds the last index within a CharSequence, handling {@code null}.
+ * This method uses {@link String#lastIndexOf(int)} if possible.
+ *
+ * A {@code null} or empty ("") CharSequence will return {@code -1}.
+ *
+ *
+ * StringUtils.lastIndexOf(null, *) = -1
+ * StringUtils.lastIndexOf("", *) = -1
+ * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
+ * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchChar the character to find
+ * @return the last index of the search character,
+ * -1 if no match or {@code null} string input
+ * @since 2.0
+ * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int)
+ */
+ public static int lastIndexOf(final CharSequence seq, final int searchChar) {
+ if (isEmpty(seq)) {
+ return INDEX_NOT_FOUND;
+ }
+ return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length());
+ }
+
+ /**
+ * Finds the last index within a CharSequence from a start position,
+ * handling {@code null}.
+ * This method uses {@link String#lastIndexOf(int, int)} if possible.
+ *
+ * A {@code null} or empty ("") CharSequence will return {@code -1}.
+ * A negative start position returns {@code -1}.
+ * A start position greater than the string length searches the whole string.
+ * The search starts at the startPos and works backwards; matches starting after the start
+ * position are ignored.
+ *
+ *
+ *
+ * StringUtils.lastIndexOf(null, *, *) = -1
+ * StringUtils.lastIndexOf("", *, *) = -1
+ * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5
+ * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2
+ * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1
+ * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5
+ * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
+ * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchChar the character to find
+ * @param startPos the start position
+ * @return the last index of the search character (always ≤ startPos),
+ * -1 if no match or {@code null} string input
+ * @since 2.0
+ * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int)
+ */
+ public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) {
+ if (isEmpty(seq)) {
+ return INDEX_NOT_FOUND;
+ }
+ return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos);
+ }
+
+ /**
+ * Finds the last index within a CharSequence, handling {@code null}.
+ * This method uses {@link String#lastIndexOf(String)} if possible.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ *
+ *
+ * StringUtils.lastIndexOf(null, *) = -1
+ * StringUtils.lastIndexOf(*, null) = -1
+ * StringUtils.lastIndexOf("", "") = 0
+ * StringUtils.lastIndexOf("aabaabaa", "a") = 7
+ * StringUtils.lastIndexOf("aabaabaa", "b") = 5
+ * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
+ * StringUtils.lastIndexOf("aabaabaa", "") = 8
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchSeq the CharSequence to find, may be null
+ * @return the last index of the search String,
+ * -1 if no match or {@code null} string input
+ * @since 2.0
+ * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence)
+ */
+ public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) {
+ if (seq == null || searchSeq == null) {
+ return INDEX_NOT_FOUND;
+ }
+ return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length());
+ }
+
+ /**
+ * Finds the n-th last index within a String, handling {@code null}.
+ * This method uses {@link String#lastIndexOf(String)}.
+ *
+ * A {@code null} String will return {@code -1}.
+ *
+ *
+ * StringUtils.lastOrdinalIndexOf(null, *, *) = -1
+ * StringUtils.lastOrdinalIndexOf(*, null, *) = -1
+ * StringUtils.lastOrdinalIndexOf("", "", *) = 0
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8
+ * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8
+ *
+ *
+ * Note that 'tail(CharSequence str, int n)' may be implemented as:
+ *
+ *
+ * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param searchStr the CharSequence to find, may be null
+ * @param ordinal the n-th last {@code searchStr} to find
+ * @return the n-th last index of the search CharSequence,
+ * {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
+ * @since 2.5
+ * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int)
+ */
+ public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
+ return ordinalIndexOf(str, searchStr, ordinal, true);
+ }
+
+ /**
+ * Finds the last index within a CharSequence, handling {@code null}.
+ * This method uses {@link String#lastIndexOf(String, int)} if possible.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ * A negative start position returns {@code -1}.
+ * An empty ("") search CharSequence always matches unless the start position is negative.
+ * A start position greater than the string length searches the whole string.
+ * The search starts at the startPos and works backwards; matches starting after the start
+ * position are ignored.
+ *
+ *
+ *
+ * StringUtils.lastIndexOf(null, *, *) = -1
+ * StringUtils.lastIndexOf(*, null, *) = -1
+ * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7
+ * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5
+ * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
+ * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5
+ * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
+ * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0
+ * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1
+ * StringUtils.lastIndexOf("aabaabaa", "b", 1) = -1
+ * StringUtils.lastIndexOf("aabaabaa", "b", 2) = 2
+ * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = -1
+ * StringUtils.lastIndexOf("aabaabaa", "ba", 2) = 2
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchSeq the CharSequence to find, may be null
+ * @param startPos the start position, negative treated as zero
+ * @return the last index of the search CharSequence (always ≤ startPos),
+ * -1 if no match or {@code null} string input
+ * @since 2.0
+ * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int)
+ */
+ public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
+ if (seq == null || searchSeq == null) {
+ return INDEX_NOT_FOUND;
+ }
+ return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos);
+ }
+
+ /**
+ * Case in-sensitive find of the last index within a CharSequence.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ * A negative start position returns {@code -1}.
+ * An empty ("") search CharSequence always matches unless the start position is negative.
+ * A start position greater than the string length searches the whole string.
+ *
+ *
+ * StringUtils.lastIndexOfIgnoreCase(null, *) = -1
+ * StringUtils.lastIndexOfIgnoreCase(*, null) = -1
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param searchStr the CharSequence to find, may be null
+ * @return the first index of the search CharSequence,
+ * -1 if no match or {@code null} string input
+ * @since 2.5
+ * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence)
+ */
+ public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
+ if (str == null || searchStr == null) {
+ return INDEX_NOT_FOUND;
+ }
+ return lastIndexOfIgnoreCase(str, searchStr, str.length());
+ }
+
+ /**
+ * Case in-sensitive find of the last index within a CharSequence
+ * from the specified position.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ * A negative start position returns {@code -1}.
+ * An empty ("") search CharSequence always matches unless the start position is negative.
+ * A start position greater than the string length searches the whole string.
+ * The search starts at the startPos and works backwards; matches starting after the start
+ * position are ignored.
+ *
+ *
+ *
+ * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1
+ * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0
+ * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param searchStr the CharSequence to find, may be null
+ * @param startPos the start position
+ * @return the last index of the search CharSequence (always ≤ startPos),
+ * -1 if no match or {@code null} input
+ * @since 2.5
+ * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int)
+ */
+ public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) {
+ if (str == null || searchStr == null) {
+ return INDEX_NOT_FOUND;
+ }
+ if (startPos > str.length() - searchStr.length()) {
+ startPos = str.length() - searchStr.length();
+ }
+ if (startPos < 0) {
+ return INDEX_NOT_FOUND;
+ }
+ if (searchStr.length() == 0) {
+ return startPos;
+ }
+
+ for (int i = startPos; i >= 0; i--) {
+ if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) {
+ return i;
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ // Contains
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if CharSequence contains a search character, handling {@code null}.
+ * This method uses {@link String#indexOf(int)} if possible.
+ *
+ * A {@code null} or empty ("") CharSequence will return {@code false}.
+ *
+ *
+ * StringUtils.contains(null, *) = false
+ * StringUtils.contains("", *) = false
+ * StringUtils.contains("abc", 'a') = true
+ * StringUtils.contains("abc", 'z') = false
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchChar the character to find
+ * @return true if the CharSequence contains the search character,
+ * false if not or {@code null} string input
+ * @since 2.0
+ * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int)
+ */
+ public static boolean contains(final CharSequence seq, final int searchChar) {
+ if (isEmpty(seq)) {
+ return false;
+ }
+ return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0;
+ }
+
+ /**
+ * Checks if CharSequence contains a search CharSequence, handling {@code null}.
+ * This method uses {@link String#indexOf(String)} if possible.
+ *
+ * A {@code null} CharSequence will return {@code false}.
+ *
+ *
+ * StringUtils.contains(null, *) = false
+ * StringUtils.contains(*, null) = false
+ * StringUtils.contains("", "") = true
+ * StringUtils.contains("abc", "") = true
+ * StringUtils.contains("abc", "a") = true
+ * StringUtils.contains("abc", "z") = false
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchSeq the CharSequence to find, may be null
+ * @return true if the CharSequence contains the search CharSequence,
+ * false if not or {@code null} string input
+ * @since 2.0
+ * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence)
+ */
+ public static boolean contains(final CharSequence seq, final CharSequence searchSeq) {
+ if (seq == null || searchSeq == null) {
+ return false;
+ }
+ return CharSequenceUtils.indexOf(seq, searchSeq, 0) >= 0;
+ }
+
+ /**
+ * Checks if CharSequence contains a search CharSequence irrespective of case,
+ * handling {@code null}. Case-insensitivity is defined as by
+ * {@link String#equalsIgnoreCase(String)}.
+ *
+ *
A {@code null} CharSequence will return {@code false}.
+ *
+ *
+ * StringUtils.containsIgnoreCase(null, *) = false
+ * StringUtils.containsIgnoreCase(*, null) = false
+ * StringUtils.containsIgnoreCase("", "") = true
+ * StringUtils.containsIgnoreCase("abc", "") = true
+ * StringUtils.containsIgnoreCase("abc", "a") = true
+ * StringUtils.containsIgnoreCase("abc", "z") = false
+ * StringUtils.containsIgnoreCase("abc", "A") = true
+ * StringUtils.containsIgnoreCase("abc", "Z") = false
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param searchStr the CharSequence to find, may be null
+ * @return true if the CharSequence contains the search CharSequence irrespective of
+ * case or false if not or {@code null} string input
+ * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence)
+ */
+ public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {
+ if (str == null || searchStr == null) {
+ return false;
+ }
+ final int len = searchStr.length();
+ final int max = str.length() - len;
+ for (int i = 0; i <= max; i++) {
+ if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check whether the given CharSequence contains any whitespace characters.
+ * @param seq the CharSequence to check (may be {@code null})
+ * @return {@code true} if the CharSequence is not empty and
+ * contains at least 1 whitespace character
+ * @see java.lang.Character#isWhitespace
+ * @since 3.0
+ */
+ // From org.springframework.util.StringUtils, under Apache License 2.0
+ public static boolean containsWhitespace(final CharSequence seq) {
+ if (isEmpty(seq)) {
+ return false;
+ }
+ final int strLen = seq.length();
+ for (int i = 0; i < strLen; i++) {
+ if (Character.isWhitespace(seq.charAt(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // IndexOfAny chars
+ //-----------------------------------------------------------------------
+ /**
+ * Search a CharSequence to find the first index of any
+ * character in the given set of characters.
+ *
+ * A {@code null} String will return {@code -1}.
+ * A {@code null} or zero length search array will return {@code -1}.
+ *
+ *
+ * StringUtils.indexOfAny(null, *) = -1
+ * StringUtils.indexOfAny("", *) = -1
+ * StringUtils.indexOfAny(*, null) = -1
+ * StringUtils.indexOfAny(*, []) = -1
+ * StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0
+ * StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3
+ * StringUtils.indexOfAny("aba", ['z']) = -1
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the index of any of the chars, -1 if no match or null input
+ * @since 2.0
+ * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)
+ */
+ public static int indexOfAny(final CharSequence cs, final char... searchChars) {
+ if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
+ return INDEX_NOT_FOUND;
+ }
+ final int csLen = cs.length();
+ final int csLast = csLen - 1;
+ final int searchLen = searchChars.length;
+ final int searchLast = searchLen - 1;
+ for (int i = 0; i < csLen; i++) {
+ final char ch = cs.charAt(i);
+ for (int j = 0; j < searchLen; j++) {
+ if (searchChars[j] == ch) {
+ if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) {
+ // ch is a supplementary character
+ if (searchChars[j + 1] == cs.charAt(i + 1)) {
+ return i;
+ }
+ } else {
+ return i;
+ }
+ }
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ * Search a CharSequence to find the first index of any
+ * character in the given set of characters.
+ *
+ * A {@code null} String will return {@code -1}.
+ * A {@code null} search string will return {@code -1}.
+ *
+ *
+ * StringUtils.indexOfAny(null, *) = -1
+ * StringUtils.indexOfAny("", *) = -1
+ * StringUtils.indexOfAny(*, null) = -1
+ * StringUtils.indexOfAny(*, "") = -1
+ * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
+ * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
+ * StringUtils.indexOfAny("aba","z") = -1
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the index of any of the chars, -1 if no match or null input
+ * @since 2.0
+ * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String)
+ */
+ public static int indexOfAny(final CharSequence cs, final String searchChars) {
+ if (isEmpty(cs) || isEmpty(searchChars)) {
+ return INDEX_NOT_FOUND;
+ }
+ return indexOfAny(cs, searchChars.toCharArray());
+ }
+
+ // ContainsAny
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if the CharSequence contains any character in the given
+ * set of characters.
+ *
+ * A {@code null} CharSequence will return {@code false}.
+ * A {@code null} or zero length search array will return {@code false}.
+ *
+ *
+ * StringUtils.containsAny(null, *) = false
+ * StringUtils.containsAny("", *) = false
+ * StringUtils.containsAny(*, null) = false
+ * StringUtils.containsAny(*, []) = false
+ * StringUtils.containsAny("zzabyycdxx",['z','a']) = true
+ * StringUtils.containsAny("zzabyycdxx",['b','y']) = true
+ * StringUtils.containsAny("zzabyycdxx",['z','y']) = true
+ * StringUtils.containsAny("aba", ['z']) = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the {@code true} if any of the chars are found,
+ * {@code false} if no match or null input
+ * @since 2.4
+ * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...)
+ */
+ public static boolean containsAny(final CharSequence cs, final char... searchChars) {
+ if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
+ return false;
+ }
+ final int csLength = cs.length();
+ final int searchLength = searchChars.length;
+ final int csLast = csLength - 1;
+ final int searchLast = searchLength - 1;
+ for (int i = 0; i < csLength; i++) {
+ final char ch = cs.charAt(i);
+ for (int j = 0; j < searchLength; j++) {
+ if (searchChars[j] == ch) {
+ if (Character.isHighSurrogate(ch)) {
+ if (j == searchLast) {
+ // missing low surrogate, fine, like String.indexOf(String)
+ return true;
+ }
+ if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
+ return true;
+ }
+ } else {
+ // ch is in the Basic Multilingual Plane
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ *
+ * Checks if the CharSequence contains any character in the given set of characters.
+ *
+ *
+ *
+ * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return
+ * {@code false}.
+ *
+ *
+ *
+ * StringUtils.containsAny(null, *) = false
+ * StringUtils.containsAny("", *) = false
+ * StringUtils.containsAny(*, null) = false
+ * StringUtils.containsAny(*, "") = false
+ * StringUtils.containsAny("zzabyycdxx", "za") = true
+ * StringUtils.containsAny("zzabyycdxx", "by") = true
+ * StringUtils.containsAny("zzabyycdxx", "zy") = true
+ * StringUtils.containsAny("zzabyycdxx", "\tx") = true
+ * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true
+ * StringUtils.containsAny("aba","z") = false
+ *
+ *
+ * @param cs
+ * the CharSequence to check, may be null
+ * @param searchChars
+ * the chars to search for, may be null
+ * @return the {@code true} if any of the chars are found, {@code false} if no match or null input
+ * @since 2.4
+ * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence)
+ */
+ public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) {
+ if (searchChars == null) {
+ return false;
+ }
+ return containsAny(cs, CharSequenceUtils.toCharArray(searchChars));
+ }
+
+ /**
+ * Checks if the CharSequence contains any of the CharSequences in the given array.
+ *
+ *
+ * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero
+ * length search array will return {@code false}.
+ *
+ *
+ *
+ * StringUtils.containsAny(null, *) = false
+ * StringUtils.containsAny("", *) = false
+ * StringUtils.containsAny(*, null) = false
+ * StringUtils.containsAny(*, []) = false
+ * StringUtils.containsAny("abcd", "ab", null) = true
+ * StringUtils.containsAny("abcd", "ab", "cd") = true
+ * StringUtils.containsAny("abc", "d", "abc") = true
+ *
+ *
+ *
+ * @param cs The CharSequence to check, may be null
+ * @param searchCharSequences The array of CharSequences to search for, may be null.
+ * Individual CharSequences may be null as well.
+ * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
+ * @since 3.4
+ */
+ public static boolean containsAny(CharSequence cs, CharSequence... searchCharSequences) {
+ if (isEmpty(cs) || ArrayUtils.isEmpty(searchCharSequences)) {
+ return false;
+ }
+ for (CharSequence searchCharSequence : searchCharSequences) {
+ if (contains(cs, searchCharSequence)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // IndexOfAnyBut chars
+ //-----------------------------------------------------------------------
+ /**
+ * Searches a CharSequence to find the first index of any
+ * character not in the given set of characters.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ * A {@code null} or zero length search array will return {@code -1}.
+ *
+ *
+ * StringUtils.indexOfAnyBut(null, *) = -1
+ * StringUtils.indexOfAnyBut("", *) = -1
+ * StringUtils.indexOfAnyBut(*, null) = -1
+ * StringUtils.indexOfAnyBut(*, []) = -1
+ * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
+ * StringUtils.indexOfAnyBut("aba", new char[] {'z'} ) = 0
+ * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} ) = -1
+
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the index of any of the chars, -1 if no match or null input
+ * @since 2.0
+ * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...)
+ */
+ public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) {
+ if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
+ return INDEX_NOT_FOUND;
+ }
+ final int csLen = cs.length();
+ final int csLast = csLen - 1;
+ final int searchLen = searchChars.length;
+ final int searchLast = searchLen - 1;
+ outer:
+ for (int i = 0; i < csLen; i++) {
+ final char ch = cs.charAt(i);
+ for (int j = 0; j < searchLen; j++) {
+ if (searchChars[j] == ch) {
+ if (i < csLast && j < searchLast && Character.isHighSurrogate(ch)) {
+ if (searchChars[j + 1] == cs.charAt(i + 1)) {
+ continue outer;
+ }
+ } else {
+ continue outer;
+ }
+ }
+ }
+ return i;
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ * Search a CharSequence to find the first index of any
+ * character not in the given set of characters.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ * A {@code null} or empty search string will return {@code -1}.
+ *
+ *
+ * StringUtils.indexOfAnyBut(null, *) = -1
+ * StringUtils.indexOfAnyBut("", *) = -1
+ * StringUtils.indexOfAnyBut(*, null) = -1
+ * StringUtils.indexOfAnyBut(*, "") = -1
+ * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
+ * StringUtils.indexOfAnyBut("zzabyycdxx", "") = -1
+ * StringUtils.indexOfAnyBut("aba","ab") = -1
+ *
+ *
+ * @param seq the CharSequence to check, may be null
+ * @param searchChars the chars to search for, may be null
+ * @return the index of any of the chars, -1 if no match or null input
+ * @since 2.0
+ * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence)
+ */
+ public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) {
+ if (isEmpty(seq) || isEmpty(searchChars)) {
+ return INDEX_NOT_FOUND;
+ }
+ final int strLen = seq.length();
+ for (int i = 0; i < strLen; i++) {
+ final char ch = seq.charAt(i);
+ final boolean chFound = CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0;
+ if (i + 1 < strLen && Character.isHighSurrogate(ch)) {
+ final char ch2 = seq.charAt(i + 1);
+ if (chFound && CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) {
+ return i;
+ }
+ } else {
+ if (!chFound) {
+ return i;
+ }
+ }
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ // ContainsOnly
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if the CharSequence contains only certain characters.
+ *
+ * A {@code null} CharSequence will return {@code false}.
+ * A {@code null} valid character array will return {@code false}.
+ * An empty CharSequence (length()=0) always returns {@code true}.
+ *
+ *
+ * StringUtils.containsOnly(null, *) = false
+ * StringUtils.containsOnly(*, null) = false
+ * StringUtils.containsOnly("", *) = true
+ * StringUtils.containsOnly("ab", '') = false
+ * StringUtils.containsOnly("abab", 'abc') = true
+ * StringUtils.containsOnly("ab1", 'abc') = false
+ * StringUtils.containsOnly("abz", 'abc') = false
+ *
+ *
+ * @param cs the String to check, may be null
+ * @param valid an array of valid chars, may be null
+ * @return true if it only contains valid chars and is non-null
+ * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...)
+ */
+ public static boolean containsOnly(final CharSequence cs, final char... valid) {
+ // All these pre-checks are to maintain API with an older version
+ if (valid == null || cs == null) {
+ return false;
+ }
+ if (cs.length() == 0) {
+ return true;
+ }
+ if (valid.length == 0) {
+ return false;
+ }
+ return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND;
+ }
+
+ /**
+ * Checks if the CharSequence contains only certain characters.
+ *
+ * A {@code null} CharSequence will return {@code false}.
+ * A {@code null} valid character String will return {@code false}.
+ * An empty String (length()=0) always returns {@code true}.
+ *
+ *
+ * StringUtils.containsOnly(null, *) = false
+ * StringUtils.containsOnly(*, null) = false
+ * StringUtils.containsOnly("", *) = true
+ * StringUtils.containsOnly("ab", "") = false
+ * StringUtils.containsOnly("abab", "abc") = true
+ * StringUtils.containsOnly("ab1", "abc") = false
+ * StringUtils.containsOnly("abz", "abc") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @param validChars a String of valid chars, may be null
+ * @return true if it only contains valid chars and is non-null
+ * @since 2.0
+ * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String)
+ */
+ public static boolean containsOnly(final CharSequence cs, final String validChars) {
+ if (cs == null || validChars == null) {
+ return false;
+ }
+ return containsOnly(cs, validChars.toCharArray());
+ }
+
+ // ContainsNone
+ //-----------------------------------------------------------------------
+ /**
+ * Checks that the CharSequence does not contain certain characters.
+ *
+ * A {@code null} CharSequence will return {@code true}.
+ * A {@code null} invalid character array will return {@code true}.
+ * An empty CharSequence (length()=0) always returns true.
+ *
+ *
+ * StringUtils.containsNone(null, *) = true
+ * StringUtils.containsNone(*, null) = true
+ * StringUtils.containsNone("", *) = true
+ * StringUtils.containsNone("ab", '') = true
+ * StringUtils.containsNone("abab", 'xyz') = true
+ * StringUtils.containsNone("ab1", 'xyz') = true
+ * StringUtils.containsNone("abz", 'xyz') = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @param searchChars an array of invalid chars, may be null
+ * @return true if it contains none of the invalid chars, or is null
+ * @since 2.0
+ * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...)
+ */
+ public static boolean containsNone(final CharSequence cs, final char... searchChars) {
+ if (cs == null || searchChars == null) {
+ return true;
+ }
+ final int csLen = cs.length();
+ final int csLast = csLen - 1;
+ final int searchLen = searchChars.length;
+ final int searchLast = searchLen - 1;
+ for (int i = 0; i < csLen; i++) {
+ final char ch = cs.charAt(i);
+ for (int j = 0; j < searchLen; j++) {
+ if (searchChars[j] == ch) {
+ if (Character.isHighSurrogate(ch)) {
+ if (j == searchLast) {
+ // missing low surrogate, fine, like String.indexOf(String)
+ return false;
+ }
+ if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
+ return false;
+ }
+ } else {
+ // ch is in the Basic Multilingual Plane
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks that the CharSequence does not contain certain characters.
+ *
+ * A {@code null} CharSequence will return {@code true}.
+ * A {@code null} invalid character array will return {@code true}.
+ * An empty String ("") always returns true.
+ *
+ *
+ * StringUtils.containsNone(null, *) = true
+ * StringUtils.containsNone(*, null) = true
+ * StringUtils.containsNone("", *) = true
+ * StringUtils.containsNone("ab", "") = true
+ * StringUtils.containsNone("abab", "xyz") = true
+ * StringUtils.containsNone("ab1", "xyz") = true
+ * StringUtils.containsNone("abz", "xyz") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @param invalidChars a String of invalid chars, may be null
+ * @return true if it contains none of the invalid chars, or is null
+ * @since 2.0
+ * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String)
+ */
+ public static boolean containsNone(final CharSequence cs, final String invalidChars) {
+ if (cs == null || invalidChars == null) {
+ return true;
+ }
+ return containsNone(cs, invalidChars.toCharArray());
+ }
+
+ // IndexOfAny strings
+ //-----------------------------------------------------------------------
+ /**
+ * Find the first index of any of a set of potential substrings.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ * A {@code null} or zero length search array will return {@code -1}.
+ * A {@code null} search array entry will be ignored, but a search
+ * array containing "" will return {@code 0} if {@code str} is not
+ * null. This method uses {@link String#indexOf(String)} if possible.
+ *
+ *
+ * StringUtils.indexOfAny(null, *) = -1
+ * StringUtils.indexOfAny(*, null) = -1
+ * StringUtils.indexOfAny(*, []) = -1
+ * StringUtils.indexOfAny("zzabyycdxx", ["ab","cd"]) = 2
+ * StringUtils.indexOfAny("zzabyycdxx", ["cd","ab"]) = 2
+ * StringUtils.indexOfAny("zzabyycdxx", ["mn","op"]) = -1
+ * StringUtils.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1
+ * StringUtils.indexOfAny("zzabyycdxx", [""]) = 0
+ * StringUtils.indexOfAny("", [""]) = 0
+ * StringUtils.indexOfAny("", ["a"]) = -1
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param searchStrs the CharSequences to search for, may be null
+ * @return the first index of any of the searchStrs in str, -1 if no match
+ * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...)
+ */
+ public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) {
+ if (str == null || searchStrs == null) {
+ return INDEX_NOT_FOUND;
+ }
+ final int sz = searchStrs.length;
+
+ // String's can't have a MAX_VALUEth index.
+ int ret = Integer.MAX_VALUE;
+
+ int tmp = 0;
+ for (int i = 0; i < sz; i++) {
+ final CharSequence search = searchStrs[i];
+ if (search == null) {
+ continue;
+ }
+ tmp = CharSequenceUtils.indexOf(str, search, 0);
+ if (tmp == INDEX_NOT_FOUND) {
+ continue;
+ }
+
+ if (tmp < ret) {
+ ret = tmp;
+ }
+ }
+
+ return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret;
+ }
+
+ /**
+ * Find the latest index of any of a set of potential substrings.
+ *
+ * A {@code null} CharSequence will return {@code -1}.
+ * A {@code null} search array will return {@code -1}.
+ * A {@code null} or zero length search array entry will be ignored,
+ * but a search array containing "" will return the length of {@code str}
+ * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible
+ *
+ *
+ * StringUtils.lastIndexOfAny(null, *) = -1
+ * StringUtils.lastIndexOfAny(*, null) = -1
+ * StringUtils.lastIndexOfAny(*, []) = -1
+ * StringUtils.lastIndexOfAny(*, [null]) = -1
+ * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6
+ * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6
+ * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
+ * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
+ * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn",""]) = 10
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param searchStrs the CharSequences to search for, may be null
+ * @return the last index of any of the CharSequences, -1 if no match
+ * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence)
+ */
+ public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) {
+ if (str == null || searchStrs == null) {
+ return INDEX_NOT_FOUND;
+ }
+ final int sz = searchStrs.length;
+ int ret = INDEX_NOT_FOUND;
+ int tmp = 0;
+ for (int i = 0; i < sz; i++) {
+ final CharSequence search = searchStrs[i];
+ if (search == null) {
+ continue;
+ }
+ tmp = CharSequenceUtils.lastIndexOf(str, search, str.length());
+ if (tmp > ret) {
+ ret = tmp;
+ }
+ }
+ return ret;
+ }
+
+ // Substring
+ //-----------------------------------------------------------------------
+ /**
+ * Gets a substring from the specified String avoiding exceptions.
+ *
+ * A negative start position can be used to start {@code n}
+ * characters from the end of the String.
+ *
+ * A {@code null} String will return {@code null}.
+ * An empty ("") String will return "".
+ *
+ *
+ * StringUtils.substring(null, *) = null
+ * StringUtils.substring("", *) = ""
+ * StringUtils.substring("abc", 0) = "abc"
+ * StringUtils.substring("abc", 2) = "c"
+ * StringUtils.substring("abc", 4) = ""
+ * StringUtils.substring("abc", -2) = "bc"
+ * StringUtils.substring("abc", -4) = "abc"
+ *
+ *
+ * @param str the String to get the substring from, may be null
+ * @param start the position to start from, negative means
+ * count back from the end of the String by this many characters
+ * @return substring from start position, {@code null} if null String input
+ */
+ public static String substring(final String str, int start) {
+ if (str == null) {
+ return null;
+ }
+
+ // handle negatives, which means last n characters
+ if (start < 0) {
+ start = str.length() + start; // remember start is negative
+ }
+
+ if (start < 0) {
+ start = 0;
+ }
+ if (start > str.length()) {
+ return EMPTY;
+ }
+
+ return str.substring(start);
+ }
+
+ /**
+ * Gets a substring from the specified String avoiding exceptions.
+ *
+ * A negative start position can be used to start/end {@code n}
+ * characters from the end of the String.
+ *
+ * The returned substring starts with the character in the {@code start}
+ * position and ends before the {@code end} position. All position counting is
+ * zero-based -- i.e., to start at the beginning of the string use
+ * {@code start = 0}. Negative start and end positions can be used to
+ * specify offsets relative to the end of the String.
+ *
+ * If {@code start} is not strictly to the left of {@code end}, ""
+ * is returned.
+ *
+ *
+ * StringUtils.substring(null, *, *) = null
+ * StringUtils.substring("", * , *) = "";
+ * StringUtils.substring("abc", 0, 2) = "ab"
+ * StringUtils.substring("abc", 2, 0) = ""
+ * StringUtils.substring("abc", 2, 4) = "c"
+ * StringUtils.substring("abc", 4, 6) = ""
+ * StringUtils.substring("abc", 2, 2) = ""
+ * StringUtils.substring("abc", -2, -1) = "b"
+ * StringUtils.substring("abc", -4, 2) = "ab"
+ *
+ *
+ * @param str the String to get the substring from, may be null
+ * @param start the position to start from, negative means
+ * count back from the end of the String by this many characters
+ * @param end the position to end at (exclusive), negative means
+ * count back from the end of the String by this many characters
+ * @return substring from start position to end position,
+ * {@code null} if null String input
+ */
+ public static String substring(final String str, int start, int end) {
+ if (str == null) {
+ return null;
+ }
+
+ // handle negatives
+ if (end < 0) {
+ end = str.length() + end; // remember end is negative
+ }
+ if (start < 0) {
+ start = str.length() + start; // remember start is negative
+ }
+
+ // check length next
+ if (end > str.length()) {
+ end = str.length();
+ }
+
+ // if start is greater than end, return ""
+ if (start > end) {
+ return EMPTY;
+ }
+
+ if (start < 0) {
+ start = 0;
+ }
+ if (end < 0) {
+ end = 0;
+ }
+
+ return str.substring(start, end);
+ }
+
+ // Left/Right/Mid
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the leftmost {@code len} characters of a String.
+ *
+ * If {@code len} characters are not available, or the
+ * String is {@code null}, the String will be returned without
+ * an exception. An empty String is returned if len is negative.
+ *
+ *
+ * StringUtils.left(null, *) = null
+ * StringUtils.left(*, -ve) = ""
+ * StringUtils.left("", *) = ""
+ * StringUtils.left("abc", 0) = ""
+ * StringUtils.left("abc", 2) = "ab"
+ * StringUtils.left("abc", 4) = "abc"
+ *
+ *
+ * @param str the String to get the leftmost characters from, may be null
+ * @param len the length of the required String
+ * @return the leftmost characters, {@code null} if null String input
+ */
+ public static String left(final String str, final int len) {
+ if (str == null) {
+ return null;
+ }
+ if (len < 0) {
+ return EMPTY;
+ }
+ if (str.length() <= len) {
+ return str;
+ }
+ return str.substring(0, len);
+ }
+
+ /**
+ * Gets the rightmost {@code len} characters of a String.
+ *
+ * If {@code len} characters are not available, or the String
+ * is {@code null}, the String will be returned without an
+ * an exception. An empty String is returned if len is negative.
+ *
+ *
+ * StringUtils.right(null, *) = null
+ * StringUtils.right(*, -ve) = ""
+ * StringUtils.right("", *) = ""
+ * StringUtils.right("abc", 0) = ""
+ * StringUtils.right("abc", 2) = "bc"
+ * StringUtils.right("abc", 4) = "abc"
+ *
+ *
+ * @param str the String to get the rightmost characters from, may be null
+ * @param len the length of the required String
+ * @return the rightmost characters, {@code null} if null String input
+ */
+ public static String right(final String str, final int len) {
+ if (str == null) {
+ return null;
+ }
+ if (len < 0) {
+ return EMPTY;
+ }
+ if (str.length() <= len) {
+ return str;
+ }
+ return str.substring(str.length() - len);
+ }
+
+ /**
+ * Gets {@code len} characters from the middle of a String.
+ *
+ * If {@code len} characters are not available, the remainder
+ * of the String will be returned without an exception. If the
+ * String is {@code null}, {@code null} will be returned.
+ * An empty String is returned if len is negative or exceeds the
+ * length of {@code str}.
+ *
+ *
+ * StringUtils.mid(null, *, *) = null
+ * StringUtils.mid(*, *, -ve) = ""
+ * StringUtils.mid("", 0, *) = ""
+ * StringUtils.mid("abc", 0, 2) = "ab"
+ * StringUtils.mid("abc", 0, 4) = "abc"
+ * StringUtils.mid("abc", 2, 4) = "c"
+ * StringUtils.mid("abc", 4, 2) = ""
+ * StringUtils.mid("abc", -2, 2) = "ab"
+ *
+ *
+ * @param str the String to get the characters from, may be null
+ * @param pos the position to start from, negative treated as zero
+ * @param len the length of the required String
+ * @return the middle characters, {@code null} if null String input
+ */
+ public static String mid(final String str, int pos, final int len) {
+ if (str == null) {
+ return null;
+ }
+ if (len < 0 || pos > str.length()) {
+ return EMPTY;
+ }
+ if (pos < 0) {
+ pos = 0;
+ }
+ if (str.length() <= pos + len) {
+ return str.substring(pos);
+ }
+ return str.substring(pos, pos + len);
+ }
+
+ // SubStringAfter/SubStringBefore
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the substring before the first occurrence of a separator.
+ * The separator is not returned.
+ *
+ * A {@code null} string input will return {@code null}.
+ * An empty ("") string input will return the empty string.
+ * A {@code null} separator will return the input string.
+ *
+ * If nothing is found, the string input is returned.
+ *
+ *
+ * StringUtils.substringBefore(null, *) = null
+ * StringUtils.substringBefore("", *) = ""
+ * StringUtils.substringBefore("abc", "a") = ""
+ * StringUtils.substringBefore("abcba", "b") = "a"
+ * StringUtils.substringBefore("abc", "c") = "ab"
+ * StringUtils.substringBefore("abc", "d") = "abc"
+ * StringUtils.substringBefore("abc", "") = ""
+ * StringUtils.substringBefore("abc", null) = "abc"
+ *
+ *
+ * @param str the String to get a substring from, may be null
+ * @param separator the String to search for, may be null
+ * @return the substring before the first occurrence of the separator,
+ * {@code null} if null String input
+ * @since 2.0
+ */
+ public static String substringBefore(final String str, final String separator) {
+ if (isEmpty(str) || separator == null) {
+ return str;
+ }
+ if (separator.isEmpty()) {
+ return EMPTY;
+ }
+ final int pos = str.indexOf(separator);
+ if (pos == INDEX_NOT_FOUND) {
+ return str;
+ }
+ return str.substring(0, pos);
+ }
+
+ /**
+ * Gets the substring after the first occurrence of a separator.
+ * The separator is not returned.
+ *
+ * A {@code null} string input will return {@code null}.
+ * An empty ("") string input will return the empty string.
+ * A {@code null} separator will return the empty string if the
+ * input string is not {@code null}.
+ *
+ * If nothing is found, the empty string is returned.
+ *
+ *
+ * StringUtils.substringAfter(null, *) = null
+ * StringUtils.substringAfter("", *) = ""
+ * StringUtils.substringAfter(*, null) = ""
+ * StringUtils.substringAfter("abc", "a") = "bc"
+ * StringUtils.substringAfter("abcba", "b") = "cba"
+ * StringUtils.substringAfter("abc", "c") = ""
+ * StringUtils.substringAfter("abc", "d") = ""
+ * StringUtils.substringAfter("abc", "") = "abc"
+ *
+ *
+ * @param str the String to get a substring from, may be null
+ * @param separator the String to search for, may be null
+ * @return the substring after the first occurrence of the separator,
+ * {@code null} if null String input
+ * @since 2.0
+ */
+ public static String substringAfter(final String str, final String separator) {
+ if (isEmpty(str)) {
+ return str;
+ }
+ if (separator == null) {
+ return EMPTY;
+ }
+ final int pos = str.indexOf(separator);
+ if (pos == INDEX_NOT_FOUND) {
+ return EMPTY;
+ }
+ return str.substring(pos + separator.length());
+ }
+
+ /**
+ * Gets the substring before the last occurrence of a separator.
+ * The separator is not returned.
+ *
+ * A {@code null} string input will return {@code null}.
+ * An empty ("") string input will return the empty string.
+ * An empty or {@code null} separator will return the input string.
+ *
+ * If nothing is found, the string input is returned.
+ *
+ *
+ * StringUtils.substringBeforeLast(null, *) = null
+ * StringUtils.substringBeforeLast("", *) = ""
+ * StringUtils.substringBeforeLast("abcba", "b") = "abc"
+ * StringUtils.substringBeforeLast("abc", "c") = "ab"
+ * StringUtils.substringBeforeLast("a", "a") = ""
+ * StringUtils.substringBeforeLast("a", "z") = "a"
+ * StringUtils.substringBeforeLast("a", null) = "a"
+ * StringUtils.substringBeforeLast("a", "") = "a"
+ *
+ *
+ * @param str the String to get a substring from, may be null
+ * @param separator the String to search for, may be null
+ * @return the substring before the last occurrence of the separator,
+ * {@code null} if null String input
+ * @since 2.0
+ */
+ public static String substringBeforeLast(final String str, final String separator) {
+ if (isEmpty(str) || isEmpty(separator)) {
+ return str;
+ }
+ final int pos = str.lastIndexOf(separator);
+ if (pos == INDEX_NOT_FOUND) {
+ return str;
+ }
+ return str.substring(0, pos);
+ }
+
+ /**
+ * Gets the substring after the last occurrence of a separator.
+ * The separator is not returned.
+ *
+ * A {@code null} string input will return {@code null}.
+ * An empty ("") string input will return the empty string.
+ * An empty or {@code null} separator will return the empty string if
+ * the input string is not {@code null}.
+ *
+ * If nothing is found, the empty string is returned.
+ *
+ *
+ * StringUtils.substringAfterLast(null, *) = null
+ * StringUtils.substringAfterLast("", *) = ""
+ * StringUtils.substringAfterLast(*, "") = ""
+ * StringUtils.substringAfterLast(*, null) = ""
+ * StringUtils.substringAfterLast("abc", "a") = "bc"
+ * StringUtils.substringAfterLast("abcba", "b") = "a"
+ * StringUtils.substringAfterLast("abc", "c") = ""
+ * StringUtils.substringAfterLast("a", "a") = ""
+ * StringUtils.substringAfterLast("a", "z") = ""
+ *
+ *
+ * @param str the String to get a substring from, may be null
+ * @param separator the String to search for, may be null
+ * @return the substring after the last occurrence of the separator,
+ * {@code null} if null String input
+ * @since 2.0
+ */
+ public static String substringAfterLast(final String str, final String separator) {
+ if (isEmpty(str)) {
+ return str;
+ }
+ if (isEmpty(separator)) {
+ return EMPTY;
+ }
+ final int pos = str.lastIndexOf(separator);
+ if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) {
+ return EMPTY;
+ }
+ return str.substring(pos + separator.length());
+ }
+
+ // Substring between
+ //-----------------------------------------------------------------------
+ /**
+ * Gets the String that is nested in between two instances of the
+ * same String.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} tag returns {@code null}.
+ *
+ *
+ * StringUtils.substringBetween(null, *) = null
+ * StringUtils.substringBetween("", "") = ""
+ * StringUtils.substringBetween("", "tag") = null
+ * StringUtils.substringBetween("tagabctag", null) = null
+ * StringUtils.substringBetween("tagabctag", "") = ""
+ * StringUtils.substringBetween("tagabctag", "tag") = "abc"
+ *
+ *
+ * @param str the String containing the substring, may be null
+ * @param tag the String before and after the substring, may be null
+ * @return the substring, {@code null} if no match
+ * @since 2.0
+ */
+ public static String substringBetween(final String str, final String tag) {
+ return substringBetween(str, tag, tag);
+ }
+
+ /**
+ * Gets the String that is nested in between two Strings.
+ * Only the first match is returned.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} open/close returns {@code null} (no match).
+ * An empty ("") open and close returns an empty string.
+ *
+ *
+ * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
+ * StringUtils.substringBetween(null, *, *) = null
+ * StringUtils.substringBetween(*, null, *) = null
+ * StringUtils.substringBetween(*, *, null) = null
+ * StringUtils.substringBetween("", "", "") = ""
+ * StringUtils.substringBetween("", "", "]") = null
+ * StringUtils.substringBetween("", "[", "]") = null
+ * StringUtils.substringBetween("yabcz", "", "") = ""
+ * StringUtils.substringBetween("yabcz", "y", "z") = "abc"
+ * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc"
+ *
+ *
+ * @param str the String containing the substring, may be null
+ * @param open the String before the substring, may be null
+ * @param close the String after the substring, may be null
+ * @return the substring, {@code null} if no match
+ * @since 2.0
+ */
+ public static String substringBetween(final String str, final String open, final String close) {
+ if (str == null || open == null || close == null) {
+ return null;
+ }
+ final int start = str.indexOf(open);
+ if (start != INDEX_NOT_FOUND) {
+ final int end = str.indexOf(close, start + open.length());
+ if (end != INDEX_NOT_FOUND) {
+ return str.substring(start + open.length(), end);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Searches a String for substrings delimited by a start and end tag,
+ * returning all matching substrings in an array.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} open/close returns {@code null} (no match).
+ * An empty ("") open/close returns {@code null} (no match).
+ *
+ *
+ * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
+ * StringUtils.substringsBetween(null, *, *) = null
+ * StringUtils.substringsBetween(*, null, *) = null
+ * StringUtils.substringsBetween(*, *, null) = null
+ * StringUtils.substringsBetween("", "[", "]") = []
+ *
+ *
+ * @param str the String containing the substrings, null returns null, empty returns empty
+ * @param open the String identifying the start of the substring, empty returns null
+ * @param close the String identifying the end of the substring, empty returns null
+ * @return a String Array of substrings, or {@code null} if no match
+ * @since 2.3
+ */
+ public static String[] substringsBetween(final String str, final String open, final String close) {
+ if (str == null || isEmpty(open) || isEmpty(close)) {
+ return null;
+ }
+ final int strLen = str.length();
+ if (strLen == 0) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ final int closeLen = close.length();
+ final int openLen = open.length();
+ final List list = new ArrayList();
+ int pos = 0;
+ while (pos < strLen - closeLen) {
+ int start = str.indexOf(open, pos);
+ if (start < 0) {
+ break;
+ }
+ start += openLen;
+ final int end = str.indexOf(close, start);
+ if (end < 0) {
+ break;
+ }
+ list.add(str.substring(start, end));
+ pos = end + closeLen;
+ }
+ if (list.isEmpty()) {
+ return null;
+ }
+ return list.toArray(new String [list.size()]);
+ }
+
+ // Nested extraction
+ //-----------------------------------------------------------------------
+
+ // Splitting
+ //-----------------------------------------------------------------------
+ /**
+ * Splits the provided text into an array, using whitespace as the
+ * separator.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.split(null) = null
+ * StringUtils.split("") = []
+ * StringUtils.split("abc def") = ["abc", "def"]
+ * StringUtils.split("abc def") = ["abc", "def"]
+ * StringUtils.split(" abc ") = ["abc"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @return an array of parsed Strings, {@code null} if null String input
+ */
+ public static String[] split(final String str) {
+ return split(str, null, -1);
+ }
+
+ /**
+ * Splits the provided text into an array, separator specified.
+ * This is an alternative to using StringTokenizer.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.split(null, *) = null
+ * StringUtils.split("", *) = []
+ * StringUtils.split("a.b.c", '.') = ["a", "b", "c"]
+ * StringUtils.split("a..b.c", '.') = ["a", "b", "c"]
+ * StringUtils.split("a:b:c", '.') = ["a:b:c"]
+ * StringUtils.split("a b c", ' ') = ["a", "b", "c"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separatorChar the character used as the delimiter
+ * @return an array of parsed Strings, {@code null} if null String input
+ * @since 2.0
+ */
+ public static String[] split(final String str, final char separatorChar) {
+ return splitWorker(str, separatorChar, false);
+ }
+
+ /**
+ * Splits the provided text into an array, separators specified.
+ * This is an alternative to using StringTokenizer.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} separatorChars splits on whitespace.
+ *
+ *
+ * StringUtils.split(null, *) = null
+ * StringUtils.split("", *) = []
+ * StringUtils.split("abc def", null) = ["abc", "def"]
+ * StringUtils.split("abc def", " ") = ["abc", "def"]
+ * StringUtils.split("abc def", " ") = ["abc", "def"]
+ * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separatorChars the characters used as the delimiters,
+ * {@code null} splits on whitespace
+ * @return an array of parsed Strings, {@code null} if null String input
+ */
+ public static String[] split(final String str, final String separatorChars) {
+ return splitWorker(str, separatorChars, -1, false);
+ }
+
+ /**
+ * Splits the provided text into an array with a maximum length,
+ * separators specified.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} separatorChars splits on whitespace.
+ *
+ * If more than {@code max} delimited substrings are found, the last
+ * returned string includes all characters after the first {@code max - 1}
+ * returned strings (including separator characters).
+ *
+ *
+ * StringUtils.split(null, *, *) = null
+ * StringUtils.split("", *, *) = []
+ * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"]
+ * StringUtils.split("ab cd ef", null, 0) = ["ab", "cd", "ef"]
+ * StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
+ * StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separatorChars the characters used as the delimiters,
+ * {@code null} splits on whitespace
+ * @param max the maximum number of elements to include in the
+ * array. A zero or negative value implies no limit
+ * @return an array of parsed Strings, {@code null} if null String input
+ */
+ public static String[] split(final String str, final String separatorChars, final int max) {
+ return splitWorker(str, separatorChars, max, false);
+ }
+
+ /**
+ * Splits the provided text into an array, separator string specified.
+ *
+ * The separator(s) will not be included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} separator splits on whitespace.
+ *
+ *
+ * StringUtils.splitByWholeSeparator(null, *) = null
+ * StringUtils.splitByWholeSeparator("", *) = []
+ * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparator("ab de fg", null) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparator("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+ * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separator String containing the String to be used as a delimiter,
+ * {@code null} splits on whitespace
+ * @return an array of parsed Strings, {@code null} if null String was input
+ */
+ public static String[] splitByWholeSeparator(final String str, final String separator) {
+ return splitByWholeSeparatorWorker( str, separator, -1, false ) ;
+ }
+
+ /**
+ * Splits the provided text into an array, separator string specified.
+ * Returns a maximum of {@code max} substrings.
+ *
+ * The separator(s) will not be included in the returned String array.
+ * Adjacent separators are treated as one separator.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} separator splits on whitespace.
+ *
+ *
+ * StringUtils.splitByWholeSeparator(null, *, *) = null
+ * StringUtils.splitByWholeSeparator("", *, *) = []
+ * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparator("ab de fg", null, 0) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
+ * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
+ * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separator String containing the String to be used as a delimiter,
+ * {@code null} splits on whitespace
+ * @param max the maximum number of elements to include in the returned
+ * array. A zero or negative value implies no limit.
+ * @return an array of parsed Strings, {@code null} if null String was input
+ */
+ public static String[] splitByWholeSeparator( final String str, final String separator, final int max) {
+ return splitByWholeSeparatorWorker(str, separator, max, false);
+ }
+
+ /**
+ * Splits the provided text into an array, separator string specified.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} separator splits on whitespace.
+ *
+ *
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *) = null
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *) = []
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null) = ["ab", "", "", "de", "fg"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separator String containing the String to be used as a delimiter,
+ * {@code null} splits on whitespace
+ * @return an array of parsed Strings, {@code null} if null String was input
+ * @since 2.4
+ */
+ public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) {
+ return splitByWholeSeparatorWorker(str, separator, -1, true);
+ }
+
+ /**
+ * Splits the provided text into an array, separator string specified.
+ * Returns a maximum of {@code max} substrings.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} separator splits on whitespace.
+ *
+ *
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *) = null
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *) = []
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "de", "fg"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0) = ["ab", "", "", "de", "fg"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
+ * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
+ *
+ *
+ * @param str the String to parse, may be null
+ * @param separator String containing the String to be used as a delimiter,
+ * {@code null} splits on whitespace
+ * @param max the maximum number of elements to include in the returned
+ * array. A zero or negative value implies no limit.
+ * @return an array of parsed Strings, {@code null} if null String was input
+ * @since 2.4
+ */
+ public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) {
+ return splitByWholeSeparatorWorker(str, separator, max, true);
+ }
+
+ /**
+ * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods.
+ *
+ * @param str the String to parse, may be {@code null}
+ * @param separator String containing the String to be used as a delimiter,
+ * {@code null} splits on whitespace
+ * @param max the maximum number of elements to include in the returned
+ * array. A zero or negative value implies no limit.
+ * @param preserveAllTokens if {@code true}, adjacent separators are
+ * treated as empty token separators; if {@code false}, adjacent
+ * separators are treated as one separator.
+ * @return an array of parsed Strings, {@code null} if null String input
+ * @since 2.4
+ */
+ private static String[] splitByWholeSeparatorWorker(
+ final String str, final String separator, final int max, final boolean preserveAllTokens) {
+ if (str == null) {
+ return null;
+ }
+
+ final int len = str.length();
+
+ if (len == 0) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+
+ if (separator == null || EMPTY.equals(separator)) {
+ // Split on whitespace.
+ return splitWorker(str, null, max, preserveAllTokens);
+ }
+
+ final int separatorLength = separator.length();
+
+ final ArrayList substrings = new ArrayList();
+ int numberOfSubstrings = 0;
+ int beg = 0;
+ int end = 0;
+ while (end < len) {
+ end = str.indexOf(separator, beg);
+
+ if (end > -1) {
+ if (end > beg) {
+ numberOfSubstrings += 1;
+
+ if (numberOfSubstrings == max) {
+ end = len;
+ substrings.add(str.substring(beg));
+ } else {
+ // The following is OK, because String.substring( beg, end ) excludes
+ // the character at the position 'end'.
+ substrings.add(str.substring(beg, end));
+
+ // Set the starting point for the next search.
+ // The following is equivalent to beg = end + (separatorLength - 1) + 1,
+ // which is the right calculation:
+ beg = end + separatorLength;
+ }
+ } else {
+ // We found a consecutive occurrence of the separator, so skip it.
+ if (preserveAllTokens) {
+ numberOfSubstrings += 1;
+ if (numberOfSubstrings == max) {
+ end = len;
+ substrings.add(str.substring(beg));
+ } else {
+ substrings.add(EMPTY);
+ }
+ }
+ beg = end + separatorLength;
+ }
+ } else {
+ // String.substring( beg ) goes from 'beg' to the end of the String.
+ substrings.add(str.substring(beg));
+ end = len;
+ }
+ }
+
+ return substrings.toArray(new String[substrings.size()]);
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Splits the provided text into an array, using whitespace as the
+ * separator, preserving all tokens, including empty tokens created by
+ * adjacent separators. This is an alternative to using StringTokenizer.
+ * Whitespace is defined by {@link Character#isWhitespace(char)}.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.splitPreserveAllTokens(null) = null
+ * StringUtils.splitPreserveAllTokens("") = []
+ * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "def"]
+ * StringUtils.splitPreserveAllTokens("abc def") = ["abc", "", "def"]
+ * StringUtils.splitPreserveAllTokens(" abc ") = ["", "abc", ""]
+ *
+ *
+ * @param str the String to parse, may be {@code null}
+ * @return an array of parsed Strings, {@code null} if null String input
+ * @since 2.1
+ */
+ public static String[] splitPreserveAllTokens(final String str) {
+ return splitWorker(str, null, -1, true);
+ }
+
+ /**
+ * Splits the provided text into an array, separator specified,
+ * preserving all tokens, including empty tokens created by adjacent
+ * separators. This is an alternative to using StringTokenizer.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.splitPreserveAllTokens(null, *) = null
+ * StringUtils.splitPreserveAllTokens("", *) = []
+ * StringUtils.splitPreserveAllTokens("a.b.c", '.') = ["a", "b", "c"]
+ * StringUtils.splitPreserveAllTokens("a..b.c", '.') = ["a", "", "b", "c"]
+ * StringUtils.splitPreserveAllTokens("a:b:c", '.') = ["a:b:c"]
+ * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
+ * StringUtils.splitPreserveAllTokens("a b c", ' ') = ["a", "b", "c"]
+ * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", ""]
+ * StringUtils.splitPreserveAllTokens("a b c ", ' ') = ["a", "b", "c", "", ""]
+ * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", a", "b", "c"]
+ * StringUtils.splitPreserveAllTokens(" a b c", ' ') = ["", "", a", "b", "c"]
+ * StringUtils.splitPreserveAllTokens(" a b c ", ' ') = ["", a", "b", "c", ""]
+ *
+ *
+ * @param str the String to parse, may be {@code null}
+ * @param separatorChar the character used as the delimiter,
+ * {@code null} splits on whitespace
+ * @return an array of parsed Strings, {@code null} if null String input
+ * @since 2.1
+ */
+ public static String[] splitPreserveAllTokens(final String str, final char separatorChar) {
+ return splitWorker(str, separatorChar, true);
+ }
+
+ /**
+ * Performs the logic for the {@code split} and
+ * {@code splitPreserveAllTokens} methods that do not return a
+ * maximum array length.
+ *
+ * @param str the String to parse, may be {@code null}
+ * @param separatorChar the separate character
+ * @param preserveAllTokens if {@code true}, adjacent separators are
+ * treated as empty token separators; if {@code false}, adjacent
+ * separators are treated as one separator.
+ * @return an array of parsed Strings, {@code null} if null String input
+ */
+ private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) {
+ // Performance tuned for 2.0 (JDK1.4)
+
+ if (str == null) {
+ return null;
+ }
+ final int len = str.length();
+ if (len == 0) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ final List list = new ArrayList();
+ int i = 0, start = 0;
+ boolean match = false;
+ boolean lastMatch = false;
+ while (i < len) {
+ if (str.charAt(i) == separatorChar) {
+ if (match || preserveAllTokens) {
+ list.add(str.substring(start, i));
+ match = false;
+ lastMatch = true;
+ }
+ start = ++i;
+ continue;
+ }
+ lastMatch = false;
+ match = true;
+ i++;
+ }
+ if (match || preserveAllTokens && lastMatch) {
+ list.add(str.substring(start, i));
+ }
+ return list.toArray(new String[list.size()]);
+ }
+
+ /**
+ * Splits the provided text into an array, separators specified,
+ * preserving all tokens, including empty tokens created by adjacent
+ * separators. This is an alternative to using StringTokenizer.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
+ * For more control over the split use the StrTokenizer class.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} separatorChars splits on whitespace.
+ *
+ *
+ * StringUtils.splitPreserveAllTokens(null, *) = null
+ * StringUtils.splitPreserveAllTokens("", *) = []
+ * StringUtils.splitPreserveAllTokens("abc def", null) = ["abc", "def"]
+ * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "def"]
+ * StringUtils.splitPreserveAllTokens("abc def", " ") = ["abc", "", def"]
+ * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+ * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":") = ["ab", "cd", "ef", ""]
+ * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
+ * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":") = ["ab", "", cd", "ef"]
+ * StringUtils.splitPreserveAllTokens(":cd:ef", ":") = ["", cd", "ef"]
+ * StringUtils.splitPreserveAllTokens("::cd:ef", ":") = ["", "", cd", "ef"]
+ * StringUtils.splitPreserveAllTokens(":cd:ef:", ":") = ["", cd", "ef", ""]
+ *
+ *
+ * @param str the String to parse, may be {@code null}
+ * @param separatorChars the characters used as the delimiters,
+ * {@code null} splits on whitespace
+ * @return an array of parsed Strings, {@code null} if null String input
+ * @since 2.1
+ */
+ public static String[] splitPreserveAllTokens(final String str, final String separatorChars) {
+ return splitWorker(str, separatorChars, -1, true);
+ }
+
+ /**
+ * Splits the provided text into an array with a maximum length,
+ * separators specified, preserving all tokens, including empty tokens
+ * created by adjacent separators.
+ *
+ * The separator is not included in the returned String array.
+ * Adjacent separators are treated as separators for empty tokens.
+ * Adjacent separators are treated as one separator.
+ *
+ * A {@code null} input String returns {@code null}.
+ * A {@code null} separatorChars splits on whitespace.
+ *
+ * If more than {@code max} delimited substrings are found, the last
+ * returned string includes all characters after the first {@code max - 1}
+ * returned strings (including separator characters).
+ *
+ *
+ * StringUtils.splitPreserveAllTokens(null, *, *) = null
+ * StringUtils.splitPreserveAllTokens("", *, *) = []
+ * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "cd", "ef"]
+ * StringUtils.splitPreserveAllTokens("ab de fg", null, 0) = ["ab", "cd", "ef"]
+ * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
+ * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
+ * StringUtils.splitPreserveAllTokens("ab de fg", null, 2) = ["ab", " de fg"]
+ * StringUtils.splitPreserveAllTokens("ab de fg", null, 3) = ["ab", "", " de fg"]
+ * StringUtils.splitPreserveAllTokens("ab de fg", null, 4) = ["ab", "", "", "de fg"]
+ *
+ *
+ * @param str the String to parse, may be {@code null}
+ * @param separatorChars the characters used as the delimiters,
+ * {@code null} splits on whitespace
+ * @param max the maximum number of elements to include in the
+ * array. A zero or negative value implies no limit
+ * @return an array of parsed Strings, {@code null} if null String input
+ * @since 2.1
+ */
+ public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) {
+ return splitWorker(str, separatorChars, max, true);
+ }
+
+ /**
+ * Performs the logic for the {@code split} and
+ * {@code splitPreserveAllTokens} methods that return a maximum array
+ * length.
+ *
+ * @param str the String to parse, may be {@code null}
+ * @param separatorChars the separate character
+ * @param max the maximum number of elements to include in the
+ * array. A zero or negative value implies no limit.
+ * @param preserveAllTokens if {@code true}, adjacent separators are
+ * treated as empty token separators; if {@code false}, adjacent
+ * separators are treated as one separator.
+ * @return an array of parsed Strings, {@code null} if null String input
+ */
+ private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) {
+ // Performance tuned for 2.0 (JDK1.4)
+ // Direct code is quicker than StringTokenizer.
+ // Also, StringTokenizer uses isSpace() not isWhitespace()
+
+ if (str == null) {
+ return null;
+ }
+ final int len = str.length();
+ if (len == 0) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ final List list = new ArrayList();
+ int sizePlus1 = 1;
+ int i = 0, start = 0;
+ boolean match = false;
+ boolean lastMatch = false;
+ if (separatorChars == null) {
+ // Null separator means use whitespace
+ while (i < len) {
+ if (Character.isWhitespace(str.charAt(i))) {
+ if (match || preserveAllTokens) {
+ lastMatch = true;
+ if (sizePlus1++ == max) {
+ i = len;
+ lastMatch = false;
+ }
+ list.add(str.substring(start, i));
+ match = false;
+ }
+ start = ++i;
+ continue;
+ }
+ lastMatch = false;
+ match = true;
+ i++;
+ }
+ } else if (separatorChars.length() == 1) {
+ // Optimise 1 character case
+ final char sep = separatorChars.charAt(0);
+ while (i < len) {
+ if (str.charAt(i) == sep) {
+ if (match || preserveAllTokens) {
+ lastMatch = true;
+ if (sizePlus1++ == max) {
+ i = len;
+ lastMatch = false;
+ }
+ list.add(str.substring(start, i));
+ match = false;
+ }
+ start = ++i;
+ continue;
+ }
+ lastMatch = false;
+ match = true;
+ i++;
+ }
+ } else {
+ // standard case
+ while (i < len) {
+ if (separatorChars.indexOf(str.charAt(i)) >= 0) {
+ if (match || preserveAllTokens) {
+ lastMatch = true;
+ if (sizePlus1++ == max) {
+ i = len;
+ lastMatch = false;
+ }
+ list.add(str.substring(start, i));
+ match = false;
+ }
+ start = ++i;
+ continue;
+ }
+ lastMatch = false;
+ match = true;
+ i++;
+ }
+ }
+ if (match || preserveAllTokens && lastMatch) {
+ list.add(str.substring(start, i));
+ }
+ return list.toArray(new String[list.size()]);
+ }
+
+ /**
+ * Splits a String by Character type as returned by
+ * {@code java.lang.Character.getType(char)}. Groups of contiguous
+ * characters of the same type are returned as complete tokens.
+ *
+ * StringUtils.splitByCharacterType(null) = null
+ * StringUtils.splitByCharacterType("") = []
+ * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"]
+ * StringUtils.splitByCharacterType("ab de fg") = ["ab", " ", "de", " ", "fg"]
+ * StringUtils.splitByCharacterType("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"]
+ * StringUtils.splitByCharacterType("number5") = ["number", "5"]
+ * StringUtils.splitByCharacterType("fooBar") = ["foo", "B", "ar"]
+ * StringUtils.splitByCharacterType("foo200Bar") = ["foo", "200", "B", "ar"]
+ * StringUtils.splitByCharacterType("ASFRules") = ["ASFR", "ules"]
+ *
+ * @param str the String to split, may be {@code null}
+ * @return an array of parsed Strings, {@code null} if null String input
+ * @since 2.4
+ */
+ public static String[] splitByCharacterType(final String str) {
+ return splitByCharacterType(str, false);
+ }
+
+ /**
+ * Splits a String by Character type as returned by
+ * {@code java.lang.Character.getType(char)}. Groups of contiguous
+ * characters of the same type are returned as complete tokens, with the
+ * following exception: the character of type
+ * {@code Character.UPPERCASE_LETTER}, if any, immediately
+ * preceding a token of type {@code Character.LOWERCASE_LETTER}
+ * will belong to the following token rather than to the preceding, if any,
+ * {@code Character.UPPERCASE_LETTER} token.
+ *
+ * StringUtils.splitByCharacterTypeCamelCase(null) = null
+ * StringUtils.splitByCharacterTypeCamelCase("") = []
+ * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"]
+ * StringUtils.splitByCharacterTypeCamelCase("ab de fg") = ["ab", " ", "de", " ", "fg"]
+ * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef") = ["ab", ":", "cd", ":", "ef"]
+ * StringUtils.splitByCharacterTypeCamelCase("number5") = ["number", "5"]
+ * StringUtils.splitByCharacterTypeCamelCase("fooBar") = ["foo", "Bar"]
+ * StringUtils.splitByCharacterTypeCamelCase("foo200Bar") = ["foo", "200", "Bar"]
+ * StringUtils.splitByCharacterTypeCamelCase("ASFRules") = ["ASF", "Rules"]
+ *
+ * @param str the String to split, may be {@code null}
+ * @return an array of parsed Strings, {@code null} if null String input
+ * @since 2.4
+ */
+ public static String[] splitByCharacterTypeCamelCase(final String str) {
+ return splitByCharacterType(str, true);
+ }
+
+ /**
+ * Splits a String by Character type as returned by
+ * {@code java.lang.Character.getType(char)}. Groups of contiguous
+ * characters of the same type are returned as complete tokens, with the
+ * following exception: if {@code camelCase} is {@code true},
+ * the character of type {@code Character.UPPERCASE_LETTER}, if any,
+ * immediately preceding a token of type {@code Character.LOWERCASE_LETTER}
+ * will belong to the following token rather than to the preceding, if any,
+ * {@code Character.UPPERCASE_LETTER} token.
+ * @param str the String to split, may be {@code null}
+ * @param camelCase whether to use so-called "camel-case" for letter types
+ * @return an array of parsed Strings, {@code null} if null String input
+ * @since 2.4
+ */
+ private static String[] splitByCharacterType(final String str, final boolean camelCase) {
+ if (str == null) {
+ return null;
+ }
+ if (str.isEmpty()) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ final char[] c = str.toCharArray();
+ final List list = new ArrayList();
+ int tokenStart = 0;
+ int currentType = Character.getType(c[tokenStart]);
+ for (int pos = tokenStart + 1; pos < c.length; pos++) {
+ final int type = Character.getType(c[pos]);
+ if (type == currentType) {
+ continue;
+ }
+ if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
+ final int newTokenStart = pos - 1;
+ if (newTokenStart != tokenStart) {
+ list.add(new String(c, tokenStart, newTokenStart - tokenStart));
+ tokenStart = newTokenStart;
+ }
+ } else {
+ list.add(new String(c, tokenStart, pos - tokenStart));
+ tokenStart = pos;
+ }
+ currentType = type;
+ }
+ list.add(new String(c, tokenStart, c.length - tokenStart));
+ return list.toArray(new String[list.size()]);
+ }
+
+ // Joining
+ //-----------------------------------------------------------------------
+ /**
+ * Joins the elements of the provided array into a single String
+ * containing the provided list of elements.
+ *
+ * No separator is added to the joined String.
+ * Null objects or empty strings within the array are represented by
+ * empty strings.
+ *
+ *
+ * StringUtils.join(null) = null
+ * StringUtils.join([]) = ""
+ * StringUtils.join([null]) = ""
+ * StringUtils.join(["a", "b", "c"]) = "abc"
+ * StringUtils.join([null, "", "a"]) = "a"
+ *
+ *
+ * @param the specific type of values to join together
+ * @param elements the values to join together, may be null
+ * @return the joined String, {@code null} if null array input
+ * @since 2.0
+ * @since 3.0 Changed signature to use varargs
+ */
+ public static String join(final T... elements) {
+ return join(elements, null);
+ }
+
+ /**
+ * Joins the elements of the provided array into a single String
+ * containing the provided list of elements.
+ *
+ * No delimiter is added before or after the list.
+ * Null objects or empty strings within the array are represented by
+ * empty strings.
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
+ * StringUtils.join(["a", "b", "c"], null) = "abc"
+ * StringUtils.join([null, "", "a"], ';') = ";;a"
+ *
+ *
+ * @param array the array of values to join together, may be null
+ * @param separator the separator character to use
+ * @return the joined String, {@code null} if null array input
+ * @since 2.0
+ */
+ public static String join(final Object[] array, final char separator) {
+ if (array == null) {
+ return null;
+ }
+ return join(array, separator, 0, array.length);
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final long[] array, final char separator) {
+ if (array == null) {
+ return null;
+ }
+ return join(array, separator, 0, array.length);
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final int[] array, final char separator) {
+ if (array == null) {
+ return null;
+ }
+ return join(array, separator, 0, array.length);
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final short[] array, final char separator) {
+ if (array == null) {
+ return null;
+ }
+ return join(array, separator, 0, array.length);
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final byte[] array, final char separator) {
+ if (array == null) {
+ return null;
+ }
+ return join(array, separator, 0, array.length);
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final char[] array, final char separator) {
+ if (array == null) {
+ return null;
+ }
+ return join(array, separator, 0, array.length);
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final float[] array, final char separator) {
+ if (array == null) {
+ return null;
+ }
+ return join(array, separator, 0, array.length);
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final double[] array, final char separator) {
+ if (array == null) {
+ return null;
+ }
+ return join(array, separator, 0, array.length);
+ }
+
+
+ /**
+ * Joins the elements of the provided array into a single String
+ * containing the provided list of elements.
+ *
+ * No delimiter is added before or after the list.
+ * Null objects or empty strings within the array are represented by
+ * empty strings.
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join(["a", "b", "c"], ';') = "a;b;c"
+ * StringUtils.join(["a", "b", "c"], null) = "abc"
+ * StringUtils.join([null, "", "a"], ';') = ";;a"
+ *
+ *
+ * @param array the array of values to join together, may be null
+ * @param separator the separator character to use
+ * @param startIndex the first index to start joining from. It is
+ * an error to pass in an end index past the end of the array
+ * @param endIndex the index to stop joining from (exclusive). It is
+ * an error to pass in an end index past the end of the array
+ * @return the joined String, {@code null} if null array input
+ * @since 2.0
+ */
+ public static String join(final Object[] array, final char separator, final int startIndex, final int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ final int noOfItems = endIndex - startIndex;
+ if (noOfItems <= 0) {
+ return EMPTY;
+ }
+ final StringBuilder buf = new StringBuilder(noOfItems * 16);
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
+ buf.append(separator);
+ }
+ if (array[i] != null) {
+ buf.append(array[i]);
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @param startIndex
+ * the first index to start joining from. It is an error to pass in an end index past the end of the
+ * array
+ * @param endIndex
+ * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
+ * the array
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final long[] array, final char separator, final int startIndex, final int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ final int noOfItems = endIndex - startIndex;
+ if (noOfItems <= 0) {
+ return EMPTY;
+ }
+ final StringBuilder buf = new StringBuilder(noOfItems * 16);
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
+ buf.append(separator);
+ }
+ buf.append(array[i]);
+ }
+ return buf.toString();
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @param startIndex
+ * the first index to start joining from. It is an error to pass in an end index past the end of the
+ * array
+ * @param endIndex
+ * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
+ * the array
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final int[] array, final char separator, final int startIndex, final int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ final int noOfItems = endIndex - startIndex;
+ if (noOfItems <= 0) {
+ return EMPTY;
+ }
+ final StringBuilder buf = new StringBuilder(noOfItems * 16);
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
+ buf.append(separator);
+ }
+ buf.append(array[i]);
+ }
+ return buf.toString();
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @param startIndex
+ * the first index to start joining from. It is an error to pass in an end index past the end of the
+ * array
+ * @param endIndex
+ * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
+ * the array
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final byte[] array, final char separator, final int startIndex, final int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ final int noOfItems = endIndex - startIndex;
+ if (noOfItems <= 0) {
+ return EMPTY;
+ }
+ final StringBuilder buf = new StringBuilder(noOfItems * 16);
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
+ buf.append(separator);
+ }
+ buf.append(array[i]);
+ }
+ return buf.toString();
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @param startIndex
+ * the first index to start joining from. It is an error to pass in an end index past the end of the
+ * array
+ * @param endIndex
+ * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
+ * the array
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final short[] array, final char separator, final int startIndex, final int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ final int noOfItems = endIndex - startIndex;
+ if (noOfItems <= 0) {
+ return EMPTY;
+ }
+ final StringBuilder buf = new StringBuilder(noOfItems * 16);
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
+ buf.append(separator);
+ }
+ buf.append(array[i]);
+ }
+ return buf.toString();
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @param startIndex
+ * the first index to start joining from. It is an error to pass in an end index past the end of the
+ * array
+ * @param endIndex
+ * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
+ * the array
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final char[] array, final char separator, final int startIndex, final int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ final int noOfItems = endIndex - startIndex;
+ if (noOfItems <= 0) {
+ return EMPTY;
+ }
+ final StringBuilder buf = new StringBuilder(noOfItems * 16);
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
+ buf.append(separator);
+ }
+ buf.append(array[i]);
+ }
+ return buf.toString();
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @param startIndex
+ * the first index to start joining from. It is an error to pass in an end index past the end of the
+ * array
+ * @param endIndex
+ * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
+ * the array
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final double[] array, final char separator, final int startIndex, final int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ final int noOfItems = endIndex - startIndex;
+ if (noOfItems <= 0) {
+ return EMPTY;
+ }
+ final StringBuilder buf = new StringBuilder(noOfItems * 16);
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
+ buf.append(separator);
+ }
+ buf.append(array[i]);
+ }
+ return buf.toString();
+ }
+
+ /**
+ *
+ * Joins the elements of the provided array into a single String containing the provided list of elements.
+ *
+ *
+ *
+ * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
+ * by empty strings.
+ *
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join([1, 2, 3], ';') = "1;2;3"
+ * StringUtils.join([1, 2, 3], null) = "123"
+ *
+ *
+ * @param array
+ * the array of values to join together, may be null
+ * @param separator
+ * the separator character to use
+ * @param startIndex
+ * the first index to start joining from. It is an error to pass in an end index past the end of the
+ * array
+ * @param endIndex
+ * the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
+ * the array
+ * @return the joined String, {@code null} if null array input
+ * @since 3.2
+ */
+ public static String join(final float[] array, final char separator, final int startIndex, final int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ final int noOfItems = endIndex - startIndex;
+ if (noOfItems <= 0) {
+ return EMPTY;
+ }
+ final StringBuilder buf = new StringBuilder(noOfItems * 16);
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
+ buf.append(separator);
+ }
+ buf.append(array[i]);
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * Joins the elements of the provided array into a single String
+ * containing the provided list of elements.
+ *
+ * No delimiter is added before or after the list.
+ * A {@code null} separator is the same as an empty String ("").
+ * Null objects or empty strings within the array are represented by
+ * empty strings.
+ *
+ *
+ * StringUtils.join(null, *) = null
+ * StringUtils.join([], *) = ""
+ * StringUtils.join([null], *) = ""
+ * StringUtils.join(["a", "b", "c"], "--") = "a--b--c"
+ * StringUtils.join(["a", "b", "c"], null) = "abc"
+ * StringUtils.join(["a", "b", "c"], "") = "abc"
+ * StringUtils.join([null, "", "a"], ',') = ",,a"
+ *
+ *
+ * @param array the array of values to join together, may be null
+ * @param separator the separator character to use, null treated as ""
+ * @return the joined String, {@code null} if null array input
+ */
+ public static String join(final Object[] array, final String separator) {
+ if (array == null) {
+ return null;
+ }
+ return join(array, separator, 0, array.length);
+ }
+
+ /**
+ * Joins the elements of the provided array into a single String
+ * containing the provided list of elements.
+ *
+ * No delimiter is added before or after the list.
+ * A {@code null} separator is the same as an empty String ("").
+ * Null objects or empty strings within the array are represented by
+ * empty strings.
+ *
+ *
+ * StringUtils.join(null, *, *, *) = null
+ * StringUtils.join([], *, *, *) = ""
+ * StringUtils.join([null], *, *, *) = ""
+ * StringUtils.join(["a", "b", "c"], "--", 0, 3) = "a--b--c"
+ * StringUtils.join(["a", "b", "c"], "--", 1, 3) = "b--c"
+ * StringUtils.join(["a", "b", "c"], "--", 2, 3) = "c"
+ * StringUtils.join(["a", "b", "c"], "--", 2, 2) = ""
+ * StringUtils.join(["a", "b", "c"], null, 0, 3) = "abc"
+ * StringUtils.join(["a", "b", "c"], "", 0, 3) = "abc"
+ * StringUtils.join([null, "", "a"], ',', 0, 3) = ",,a"
+ *
+ *
+ * @param array the array of values to join together, may be null
+ * @param separator the separator character to use, null treated as ""
+ * @param startIndex the first index to start joining from.
+ * @param endIndex the index to stop joining from (exclusive).
+ * @return the joined String, {@code null} if null array input; or the empty string
+ * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by
+ * {@code endIndex - startIndex}
+ * @throws ArrayIndexOutOfBoundsException ife
+ * {@code startIndex < 0} or
+ * {@code startIndex >= array.length()} or
+ * {@code endIndex < 0} or
+ * {@code endIndex > array.length()}
+ */
+ public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) {
+ if (array == null) {
+ return null;
+ }
+ if (separator == null) {
+ separator = EMPTY;
+ }
+
+ // endIndex - startIndex > 0: Len = NofStrings *(len(firstString) + len(separator))
+ // (Assuming that all Strings are roughly equally long)
+ final int noOfItems = endIndex - startIndex;
+ if (noOfItems <= 0) {
+ return EMPTY;
+ }
+
+ final StringBuilder buf = new StringBuilder(noOfItems * 16);
+
+ for (int i = startIndex; i < endIndex; i++) {
+ if (i > startIndex) {
+ buf.append(separator);
+ }
+ if (array[i] != null) {
+ buf.append(array[i]);
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Joins the elements of the provided {@code Iterator} into
+ * a single String containing the provided elements.
+ *
+ * No delimiter is added before or after the list. Null objects or empty
+ * strings within the iteration are represented by empty strings.
+ *
+ * See the examples here: {@link #join(Object[],char)}.
+ *
+ * @param iterator the {@code Iterator} of values to join together, may be null
+ * @param separator the separator character to use
+ * @return the joined String, {@code null} if null iterator input
+ * @since 2.0
+ */
+ public static String join(final Iterator> iterator, final char separator) {
+
+ // handle null, zero and one elements before building a buffer
+ if (iterator == null) {
+ return null;
+ }
+ if (!iterator.hasNext()) {
+ return EMPTY;
+ }
+ final Object first = iterator.next();
+ if (!iterator.hasNext()) {
+ @SuppressWarnings( "deprecation" ) // ObjectUtils.toString(Object) has been deprecated in 3.2
+ final
+ String result = ObjectUtils.toString(first);
+ return result;
+ }
+
+ // two or more elements
+ final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
+ if (first != null) {
+ buf.append(first);
+ }
+
+ while (iterator.hasNext()) {
+ buf.append(separator);
+ final Object obj = iterator.next();
+ if (obj != null) {
+ buf.append(obj);
+ }
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * Joins the elements of the provided {@code Iterator} into
+ * a single String containing the provided elements.
+ *
+ * No delimiter is added before or after the list.
+ * A {@code null} separator is the same as an empty String ("").
+ *
+ * See the examples here: {@link #join(Object[],String)}.
+ *
+ * @param iterator the {@code Iterator} of values to join together, may be null
+ * @param separator the separator character to use, null treated as ""
+ * @return the joined String, {@code null} if null iterator input
+ */
+ public static String join(final Iterator> iterator, final String separator) {
+
+ // handle null, zero and one elements before building a buffer
+ if (iterator == null) {
+ return null;
+ }
+ if (!iterator.hasNext()) {
+ return EMPTY;
+ }
+ final Object first = iterator.next();
+ if (!iterator.hasNext()) {
+ @SuppressWarnings( "deprecation" ) // ObjectUtils.toString(Object) has been deprecated in 3.2
+ final String result = ObjectUtils.toString(first);
+ return result;
+ }
+
+ // two or more elements
+ final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
+ if (first != null) {
+ buf.append(first);
+ }
+
+ while (iterator.hasNext()) {
+ if (separator != null) {
+ buf.append(separator);
+ }
+ final Object obj = iterator.next();
+ if (obj != null) {
+ buf.append(obj);
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Joins the elements of the provided {@code Iterable} into
+ * a single String containing the provided elements.
+ *
+ * No delimiter is added before or after the list. Null objects or empty
+ * strings within the iteration are represented by empty strings.
+ *
+ * See the examples here: {@link #join(Object[],char)}.
+ *
+ * @param iterable the {@code Iterable} providing the values to join together, may be null
+ * @param separator the separator character to use
+ * @return the joined String, {@code null} if null iterator input
+ * @since 2.3
+ */
+ public static String join(final Iterable> iterable, final char separator) {
+ if (iterable == null) {
+ return null;
+ }
+ return join(iterable.iterator(), separator);
+ }
+
+ /**
+ * Joins the elements of the provided {@code Iterable} into
+ * a single String containing the provided elements.
+ *
+ * No delimiter is added before or after the list.
+ * A {@code null} separator is the same as an empty String ("").
+ *
+ * See the examples here: {@link #join(Object[],String)}.
+ *
+ * @param iterable the {@code Iterable} providing the values to join together, may be null
+ * @param separator the separator character to use, null treated as ""
+ * @return the joined String, {@code null} if null iterator input
+ * @since 2.3
+ */
+ public static String join(final Iterable> iterable, final String separator) {
+ if (iterable == null) {
+ return null;
+ }
+ return join(iterable.iterator(), separator);
+ }
+
+ /**
+ * Joins the elements of the provided varargs into a
+ * single String containing the provided elements.
+ *
+ * No delimiter is added before or after the list.
+ * {@code null} elements and separator are treated as empty Strings ("").
+ *
+ *
+ * StringUtils.joinWith(",", {"a", "b"}) = "a,b"
+ * StringUtils.joinWith(",", {"a", "b",""}) = "a,b,"
+ * StringUtils.joinWith(",", {"a", null, "b"}) = "a,,b"
+ * StringUtils.joinWith(null, {"a", "b"}) = "ab"
+ *
+ *
+ * @param separator the separator character to use, null treated as ""
+ * @param objects the varargs providing the values to join together. {@code null} elements are treated as ""
+ * @return the joined String.
+ * @throws java.lang.IllegalArgumentException if a null varargs is provided
+ * @since 3.5
+ */
+ public static String joinWith(final String separator, final Object... objects) {
+ if (objects == null) {
+ throw new IllegalArgumentException("Object varargs must not be null");
+ }
+
+ final String sanitizedSeparator = defaultString(separator, StringUtils.EMPTY);
+
+ final StringBuilder result = new StringBuilder();
+
+ final Iterator iterator = Arrays.asList(objects).iterator();
+ while (iterator.hasNext()) {
+ @SuppressWarnings("deprecation") // o.k. to use as long as we do not require java 7 or greater
+ final String value = ObjectUtils.toString(iterator.next());
+ result.append(value);
+
+ if (iterator.hasNext()) {
+ result.append(sanitizedSeparator);
+ }
+ }
+
+ return result.toString();
+ }
+
+ // Delete
+ //-----------------------------------------------------------------------
+ /**
+ * Deletes all whitespaces from a String as defined by
+ * {@link Character#isWhitespace(char)}.
+ *
+ *
+ * StringUtils.deleteWhitespace(null) = null
+ * StringUtils.deleteWhitespace("") = ""
+ * StringUtils.deleteWhitespace("abc") = "abc"
+ * StringUtils.deleteWhitespace(" ab c ") = "abc"
+ *
+ *
+ * @param str the String to delete whitespace from, may be null
+ * @return the String without whitespaces, {@code null} if null String input
+ */
+ public static String deleteWhitespace(final String str) {
+ if (isEmpty(str)) {
+ return str;
+ }
+ final int sz = str.length();
+ final char[] chs = new char[sz];
+ int count = 0;
+ for (int i = 0; i < sz; i++) {
+ if (!Character.isWhitespace(str.charAt(i))) {
+ chs[count++] = str.charAt(i);
+ }
+ }
+ if (count == sz) {
+ return str;
+ }
+ return new String(chs, 0, count);
+ }
+
+ // Remove
+ //-----------------------------------------------------------------------
+ /**
+ * Removes a substring only if it is at the beginning of a source string,
+ * otherwise returns the source string.
+ *
+ * A {@code null} source string will return {@code null}.
+ * An empty ("") source string will return the empty string.
+ * A {@code null} search string will return the source string.
+ *
+ *
+ * StringUtils.removeStart(null, *) = null
+ * StringUtils.removeStart("", *) = ""
+ * StringUtils.removeStart(*, null) = *
+ * StringUtils.removeStart("www.domain.com", "www.") = "domain.com"
+ * StringUtils.removeStart("domain.com", "www.") = "domain.com"
+ * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
+ * StringUtils.removeStart("abc", "") = "abc"
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the String to search for and remove, may be null
+ * @return the substring with the string removed if found,
+ * {@code null} if null String input
+ * @since 2.1
+ */
+ public static String removeStart(final String str, final String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (str.startsWith(remove)){
+ return str.substring(remove.length());
+ }
+ return str;
+ }
+
+ /**
+ * Case insensitive removal of a substring if it is at the beginning of a source string,
+ * otherwise returns the source string.
+ *
+ * A {@code null} source string will return {@code null}.
+ * An empty ("") source string will return the empty string.
+ * A {@code null} search string will return the source string.
+ *
+ *
+ * StringUtils.removeStartIgnoreCase(null, *) = null
+ * StringUtils.removeStartIgnoreCase("", *) = ""
+ * StringUtils.removeStartIgnoreCase(*, null) = *
+ * StringUtils.removeStartIgnoreCase("www.domain.com", "www.") = "domain.com"
+ * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.") = "domain.com"
+ * StringUtils.removeStartIgnoreCase("domain.com", "www.") = "domain.com"
+ * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
+ * StringUtils.removeStartIgnoreCase("abc", "") = "abc"
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the String to search for (case insensitive) and remove, may be null
+ * @return the substring with the string removed if found,
+ * {@code null} if null String input
+ * @since 2.4
+ */
+ public static String removeStartIgnoreCase(final String str, final String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (startsWithIgnoreCase(str, remove)) {
+ return str.substring(remove.length());
+ }
+ return str;
+ }
+
+ /**
+ * Removes a substring only if it is at the end of a source string,
+ * otherwise returns the source string.
+ *
+ * A {@code null} source string will return {@code null}.
+ * An empty ("") source string will return the empty string.
+ * A {@code null} search string will return the source string.
+ *
+ *
+ * StringUtils.removeEnd(null, *) = null
+ * StringUtils.removeEnd("", *) = ""
+ * StringUtils.removeEnd(*, null) = *
+ * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com"
+ * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain"
+ * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
+ * StringUtils.removeEnd("abc", "") = "abc"
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the String to search for and remove, may be null
+ * @return the substring with the string removed if found,
+ * {@code null} if null String input
+ * @since 2.1
+ */
+ public static String removeEnd(final String str, final String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (str.endsWith(remove)) {
+ return str.substring(0, str.length() - remove.length());
+ }
+ return str;
+ }
+
+ /**
+ * Case insensitive removal of a substring if it is at the end of a source string,
+ * otherwise returns the source string.
+ *
+ * A {@code null} source string will return {@code null}.
+ * An empty ("") source string will return the empty string.
+ * A {@code null} search string will return the source string.
+ *
+ *
+ * StringUtils.removeEndIgnoreCase(null, *) = null
+ * StringUtils.removeEndIgnoreCase("", *) = ""
+ * StringUtils.removeEndIgnoreCase(*, null) = *
+ * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.") = "www.domain.com"
+ * StringUtils.removeEndIgnoreCase("www.domain.com", ".com") = "www.domain"
+ * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
+ * StringUtils.removeEndIgnoreCase("abc", "") = "abc"
+ * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
+ * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the String to search for (case insensitive) and remove, may be null
+ * @return the substring with the string removed if found,
+ * {@code null} if null String input
+ * @since 2.4
+ */
+ public static String removeEndIgnoreCase(final String str, final String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ if (endsWithIgnoreCase(str, remove)) {
+ return str.substring(0, str.length() - remove.length());
+ }
+ return str;
+ }
+
+ /**
+ * Removes all occurrences of a substring from within the source string.
+ *
+ * A {@code null} source string will return {@code null}.
+ * An empty ("") source string will return the empty string.
+ * A {@code null} remove string will return the source string.
+ * An empty ("") remove string will return the source string.
+ *
+ *
+ * StringUtils.remove(null, *) = null
+ * StringUtils.remove("", *) = ""
+ * StringUtils.remove(*, null) = *
+ * StringUtils.remove(*, "") = *
+ * StringUtils.remove("queued", "ue") = "qd"
+ * StringUtils.remove("queued", "zz") = "queued"
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the String to search for and remove, may be null
+ * @return the substring with the string removed if found,
+ * {@code null} if null String input
+ * @since 2.1
+ */
+ public static String remove(final String str, final String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ return replace(str, remove, EMPTY, -1);
+ }
+
+ /**
+ *
+ * Case insensitive removal of all occurrences of a substring from within
+ * the source string.
+ *
+ *
+ *
+ * A {@code null} source string will return {@code null}. An empty ("")
+ * source string will return the empty string. A {@code null} remove string
+ * will return the source string. An empty ("") remove string will return
+ * the source string.
+ *
+ *
+ *
+ * StringUtils.removeIgnoreCase(null, *) = null
+ * StringUtils.removeIgnoreCase("", *) = ""
+ * StringUtils.removeIgnoreCase(*, null) = *
+ * StringUtils.removeIgnoreCase(*, "") = *
+ * StringUtils.removeIgnoreCase("queued", "ue") = "qd"
+ * StringUtils.removeIgnoreCase("queued", "zz") = "queued"
+ * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd"
+ * StringUtils.removeIgnoreCase("queued", "zZ") = "queued"
+ *
+ *
+ * @param str
+ * the source String to search, may be null
+ * @param remove
+ * the String to search for (case insensitive) and remove, may be
+ * null
+ * @return the substring with the string removed if found, {@code null} if
+ * null String input
+ * @since 3.5
+ */
+ public static String removeIgnoreCase(String str, String remove) {
+ if (isEmpty(str) || isEmpty(remove)) {
+ return str;
+ }
+ return replaceIgnoreCase(str, remove, EMPTY, -1);
+ }
+
+ /**
+ * Removes all occurrences of a character from within the source string.
+ *
+ * A {@code null} source string will return {@code null}.
+ * An empty ("") source string will return the empty string.
+ *
+ *
+ * StringUtils.remove(null, *) = null
+ * StringUtils.remove("", *) = ""
+ * StringUtils.remove("queued", 'u') = "qeed"
+ * StringUtils.remove("queued", 'z') = "queued"
+ *
+ *
+ * @param str the source String to search, may be null
+ * @param remove the char to search for and remove, may be null
+ * @return the substring with the char removed if found,
+ * {@code null} if null String input
+ * @since 2.1
+ */
+ public static String remove(final String str, final char remove) {
+ if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
+ return str;
+ }
+ final char[] chars = str.toCharArray();
+ int pos = 0;
+ for (int i = 0; i < chars.length; i++) {
+ if (chars[i] != remove) {
+ chars[pos++] = chars[i];
+ }
+ }
+ return new String(chars, 0, pos);
+ }
+
+ /**
+ * Removes each substring of the text String that matches the given regular expression.
+ *
+ * This method is a {@code null} safe equivalent to:
+ *
+ * {@code text.replaceAll(regex, StringUtils.EMPTY)}
+ * {@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}
+ *
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ * Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option
+ * is NOT automatically added.
+ * To use the DOTALL option prepend "(?s)"
to the regex.
+ * DOTALL is also know as single-line mode in Perl.
+ *
+ *
+ * StringUtils.removeAll(null, *) = null
+ * StringUtils.removeAll("any", null) = "any"
+ * StringUtils.removeAll("any", "") = "any"
+ * StringUtils.removeAll("any", ".*") = ""
+ * StringUtils.removeAll("any", ".+") = ""
+ * StringUtils.removeAll("abc", ".?") = ""
+ * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB"
+ * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB"
+ * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123"
+ *
+ *
+ * @param text text to remove from, may be null
+ * @param regex the regular expression to which this string is to be matched
+ * @return the text with any removes processed,
+ * {@code null} if null String input
+ *
+ * @throws java.util.regex.PatternSyntaxException
+ * if the regular expression's syntax is invalid
+ *
+ * @see #replaceAll(String, String, String)
+ * @see #removePattern(String, String)
+ * @see String#replaceAll(String, String)
+ * @see java.util.regex.Pattern
+ * @see java.util.regex.Pattern#DOTALL
+ * @since 3.5
+ */
+ public static String removeAll(final String text, final String regex) {
+ return replaceAll(text, regex, StringUtils.EMPTY);
+ }
+
+ /**
+ * Removes the first substring of the text string that matches the given regular expression.
+ *
+ * This method is a {@code null} safe equivalent to:
+ *
+ * {@code text.replaceFirst(regex, StringUtils.EMPTY)}
+ * {@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}
+ *
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ * The {@link Pattern#DOTALL} option is NOT automatically added.
+ * To use the DOTALL option prepend "(?s)"
to the regex.
+ * DOTALL is also know as single-line mode in Perl.
+ *
+ *
+ * StringUtils.removeFirst(null, *) = null
+ * StringUtils.removeFirst("any", null) = "any"
+ * StringUtils.removeFirst("any", "") = "any"
+ * StringUtils.removeFirst("any", ".*") = ""
+ * StringUtils.removeFirst("any", ".+") = ""
+ * StringUtils.removeFirst("abc", ".?") = "bc"
+ * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B"
+ * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB"
+ * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123"
+ * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc"
+ *
+ *
+ * @param text text to remove from, may be null
+ * @param regex the regular expression to which this string is to be matched
+ * @return the text with the first replacement processed,
+ * {@code null} if null String input
+ *
+ * @throws java.util.regex.PatternSyntaxException
+ * if the regular expression's syntax is invalid
+ *
+ * @see #replaceFirst(String, String, String)
+ * @see String#replaceFirst(String, String)
+ * @see java.util.regex.Pattern
+ * @see java.util.regex.Pattern#DOTALL
+ * @since 3.5
+ */
+ public static String removeFirst(final String text, final String regex) {
+ return replaceFirst(text, regex, StringUtils.EMPTY);
+ }
+
+ // Replacing
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces a String with another String inside a larger String, once.
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ *
+ * StringUtils.replaceOnce(null, *, *) = null
+ * StringUtils.replaceOnce("", *, *) = ""
+ * StringUtils.replaceOnce("any", null, *) = "any"
+ * StringUtils.replaceOnce("any", *, null) = "any"
+ * StringUtils.replaceOnce("any", "", *) = "any"
+ * StringUtils.replaceOnce("aba", "a", null) = "aba"
+ * StringUtils.replaceOnce("aba", "a", "") = "ba"
+ * StringUtils.replaceOnce("aba", "a", "z") = "zba"
+ *
+ *
+ * @see #replace(String text, String searchString, String replacement, int max)
+ * @param text text to search and replace in, may be null
+ * @param searchString the String to search for, may be null
+ * @param replacement the String to replace with, may be null
+ * @return the text with any replacements processed,
+ * {@code null} if null String input
+ */
+ public static String replaceOnce(final String text, final String searchString, final String replacement) {
+ return replace(text, searchString, replacement, 1);
+ }
+
+ /**
+ * Case insensitively replaces a String with another String inside a larger String, once.
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ *
+ * StringUtils.replaceOnceIgnoreCase(null, *, *) = null
+ * StringUtils.replaceOnceIgnoreCase("", *, *) = ""
+ * StringUtils.replaceOnceIgnoreCase("any", null, *) = "any"
+ * StringUtils.replaceOnceIgnoreCase("any", *, null) = "any"
+ * StringUtils.replaceOnceIgnoreCase("any", "", *) = "any"
+ * StringUtils.replaceOnceIgnoreCase("aba", "a", null) = "aba"
+ * StringUtils.replaceOnceIgnoreCase("aba", "a", "") = "ba"
+ * StringUtils.replaceOnceIgnoreCase("aba", "a", "z") = "zba"
+ * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo"
+ *
+ *
+ * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
+ * @param text text to search and replace in, may be null
+ * @param searchString the String to search for (case insensitive), may be null
+ * @param replacement the String to replace with, may be null
+ * @return the text with any replacements processed,
+ * {@code null} if null String input
+ * @since 3.5
+ */
+ public static String replaceOnceIgnoreCase(String text, String searchString, String replacement) {
+ return replaceIgnoreCase(text, searchString, replacement, 1);
+ }
+
+ /**
+ * Replaces each substring of the source String that matches the given regular expression with the given
+ * replacement using the {@link Pattern#DOTALL} option. DOTALL is also know as single-line mode in Perl.
+ *
+ * This call is a {@code null} safe equivalent to:
+ *
+ * {@code source.replaceAll("(?s)" + regex, replacement)}
+ * {@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}
+ *
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ *
+ * StringUtils.replacePattern(null, *, *) = null
+ * StringUtils.replacePattern("any", null, *) = "any"
+ * StringUtils.replacePattern("any", *, null) = "any"
+ * StringUtils.replacePattern("", "", "zzz") = "zzz"
+ * StringUtils.replacePattern("", ".*", "zzz") = "zzz"
+ * StringUtils.replacePattern("", ".+", "zzz") = ""
+ * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z"
+ * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123"
+ * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
+ * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
+ * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
+ *
+ *
+ * @param source
+ * the source string
+ * @param regex
+ * the regular expression to which this string is to be matched
+ * @param replacement
+ * the string to be substituted for each match
+ * @return The resulting {@code String}
+ * @see #replaceAll(String, String, String)
+ * @see String#replaceAll(String, String)
+ * @see Pattern#DOTALL
+ * @since 3.2
+ * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
+ */
+ public static String replacePattern(final String source, final String regex, final String replacement) {
+ if (source == null || regex == null|| replacement == null ) {
+ return source;
+ }
+ return Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement);
+ }
+
+ /**
+ * Removes each substring of the source String that matches the given regular expression using the DOTALL option.
+ *
+ *
+ * This call is a {@code null} safe equivalent to:
+ *
+ * {@code source.replaceAll("(?s)" + regex, StringUtils.EMPTY)}
+ * {@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}
+ *
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ *
+ * StringUtils.removePattern(null, *) = null
+ * StringUtils.removePattern("any", null) = "any"
+ * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB"
+ * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123"
+ *
+ *
+ * @param source
+ * the source string
+ * @param regex
+ * the regular expression to which this string is to be matched
+ * @return The resulting {@code String}
+ * @see #replacePattern(String, String, String)
+ * @see String#replaceAll(String, String)
+ * @see Pattern#DOTALL
+ * @since 3.2
+ * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
+ */
+ public static String removePattern(final String source, final String regex) {
+ return replacePattern(source, regex, StringUtils.EMPTY);
+ }
+
+ /**
+ * Replaces each substring of the text String that matches the given regular expression
+ * with the given replacement.
+ *
+ * This method is a {@code null} safe equivalent to:
+ *
+ * {@code text.replaceAll(regex, replacement)}
+ * {@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}
+ *
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ * Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option
+ * is NOT automatically added.
+ * To use the DOTALL option prepend "(?s)"
to the regex.
+ * DOTALL is also know as single-line mode in Perl.
+ *
+ *
+ * StringUtils.replaceAll(null, *, *) = null
+ * StringUtils.replaceAll("any", null, *) = "any"
+ * StringUtils.replaceAll("any", *, null) = "any"
+ * StringUtils.replaceAll("", "", "zzz") = "zzz"
+ * StringUtils.replaceAll("", ".*", "zzz") = "zzz"
+ * StringUtils.replaceAll("", ".+", "zzz") = ""
+ * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ"
+ * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz"
+ * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z"
+ * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123"
+ * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
+ * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
+ * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
+ *
+ *
+ * @param text text to search and replace in, may be null
+ * @param regex the regular expression to which this string is to be matched
+ * @param replacement the string to be substituted for each match
+ * @return the text with any replacements processed,
+ * {@code null} if null String input
+ *
+ * @throws java.util.regex.PatternSyntaxException
+ * if the regular expression's syntax is invalid
+ *
+ * @see #replacePattern(String, String, String)
+ * @see String#replaceAll(String, String)
+ * @see java.util.regex.Pattern
+ * @see java.util.regex.Pattern#DOTALL
+ * @since 3.5
+ */
+ public static String replaceAll(final String text, final String regex, final String replacement) {
+ if (text == null || regex == null|| replacement == null ) {
+ return text;
+ }
+ return text.replaceAll(regex, replacement);
+ }
+
+ /**
+ * Replaces the first substring of the text string that matches the given regular expression
+ * with the given replacement.
+ *
+ * This method is a {@code null} safe equivalent to:
+ *
+ * {@code text.replaceFirst(regex, replacement)}
+ * {@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}
+ *
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ * The {@link Pattern#DOTALL} option is NOT automatically added.
+ * To use the DOTALL option prepend "(?s)"
to the regex.
+ * DOTALL is also know as single-line mode in Perl.
+ *
+ *
+ * StringUtils.replaceFirst(null, *, *) = null
+ * StringUtils.replaceFirst("any", null, *) = "any"
+ * StringUtils.replaceFirst("any", *, null) = "any"
+ * StringUtils.replaceFirst("", "", "zzz") = "zzz"
+ * StringUtils.replaceFirst("", ".*", "zzz") = "zzz"
+ * StringUtils.replaceFirst("", ".+", "zzz") = ""
+ * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc"
+ * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>"
+ * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z"
+ * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123"
+ * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc"
+ * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc"
+ * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit"
+ *
+ *
+ * @param text text to search and replace in, may be null
+ * @param regex the regular expression to which this string is to be matched
+ * @param replacement the string to be substituted for the first match
+ * @return the text with the first replacement processed,
+ * {@code null} if null String input
+ *
+ * @throws java.util.regex.PatternSyntaxException
+ * if the regular expression's syntax is invalid
+ *
+ * @see String#replaceFirst(String, String)
+ * @see java.util.regex.Pattern
+ * @see java.util.regex.Pattern#DOTALL
+ * @since 3.5
+ */
+ public static String replaceFirst(final String text, final String regex, final String replacement) {
+ if (text == null || regex == null|| replacement == null ) {
+ return text;
+ }
+ return text.replaceFirst(regex, replacement);
+ }
+
+ /**
+ * Replaces all occurrences of a String within another String.
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ *
+ * StringUtils.replace(null, *, *) = null
+ * StringUtils.replace("", *, *) = ""
+ * StringUtils.replace("any", null, *) = "any"
+ * StringUtils.replace("any", *, null) = "any"
+ * StringUtils.replace("any", "", *) = "any"
+ * StringUtils.replace("aba", "a", null) = "aba"
+ * StringUtils.replace("aba", "a", "") = "b"
+ * StringUtils.replace("aba", "a", "z") = "zbz"
+ *
+ *
+ * @see #replace(String text, String searchString, String replacement, int max)
+ * @param text text to search and replace in, may be null
+ * @param searchString the String to search for, may be null
+ * @param replacement the String to replace it with, may be null
+ * @return the text with any replacements processed,
+ * {@code null} if null String input
+ */
+ public static String replace(final String text, final String searchString, final String replacement) {
+ return replace(text, searchString, replacement, -1);
+ }
+
+ /**
+ * Case insensitively replaces all occurrences of a String within another String.
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ *
+ * StringUtils.replaceIgnoreCase(null, *, *) = null
+ * StringUtils.replaceIgnoreCase("", *, *) = ""
+ * StringUtils.replaceIgnoreCase("any", null, *) = "any"
+ * StringUtils.replaceIgnoreCase("any", *, null) = "any"
+ * StringUtils.replaceIgnoreCase("any", "", *) = "any"
+ * StringUtils.replaceIgnoreCase("aba", "a", null) = "aba"
+ * StringUtils.replaceIgnoreCase("abA", "A", "") = "b"
+ * StringUtils.replaceIgnoreCase("aba", "A", "z") = "zbz"
+ *
+ *
+ * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
+ * @param text text to search and replace in, may be null
+ * @param searchString the String to search for (case insensitive), may be null
+ * @param replacement the String to replace it with, may be null
+ * @return the text with any replacements processed,
+ * {@code null} if null String input
+ * @since 3.5
+ */
+ public static String replaceIgnoreCase(String text, String searchString, String replacement) {
+ return replaceIgnoreCase(text, searchString, replacement, -1);
+ }
+
+ /**
+ * Replaces a String with another String inside a larger String,
+ * for the first {@code max} values of the search String.
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ *
+ * StringUtils.replace(null, *, *, *) = null
+ * StringUtils.replace("", *, *, *) = ""
+ * StringUtils.replace("any", null, *, *) = "any"
+ * StringUtils.replace("any", *, null, *) = "any"
+ * StringUtils.replace("any", "", *, *) = "any"
+ * StringUtils.replace("any", *, *, 0) = "any"
+ * StringUtils.replace("abaa", "a", null, -1) = "abaa"
+ * StringUtils.replace("abaa", "a", "", -1) = "b"
+ * StringUtils.replace("abaa", "a", "z", 0) = "abaa"
+ * StringUtils.replace("abaa", "a", "z", 1) = "zbaa"
+ * StringUtils.replace("abaa", "a", "z", 2) = "zbza"
+ * StringUtils.replace("abaa", "a", "z", -1) = "zbzz"
+ *
+ *
+ * @param text text to search and replace in, may be null
+ * @param searchString the String to search for, may be null
+ * @param replacement the String to replace it with, may be null
+ * @param max maximum number of values to replace, or {@code -1} if no maximum
+ * @return the text with any replacements processed,
+ * {@code null} if null String input
+ */
+ public static String replace(final String text, final String searchString, final String replacement, int max) {
+ return replace(text, searchString, replacement, max, false);
+ }
+
+ /**
+ * Replaces a String with another String inside a larger String,
+ * for the first {@code max} values of the search String,
+ * case sensitively/insensisitively based on {@code ignoreCase} value.
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ *
+ * StringUtils.replace(null, *, *, *, false) = null
+ * StringUtils.replace("", *, *, *, false) = ""
+ * StringUtils.replace("any", null, *, *, false) = "any"
+ * StringUtils.replace("any", *, null, *, false) = "any"
+ * StringUtils.replace("any", "", *, *, false) = "any"
+ * StringUtils.replace("any", *, *, 0, false) = "any"
+ * StringUtils.replace("abaa", "a", null, -1, false) = "abaa"
+ * StringUtils.replace("abaa", "a", "", -1, false) = "b"
+ * StringUtils.replace("abaa", "a", "z", 0, false) = "abaa"
+ * StringUtils.replace("abaa", "A", "z", 1, false) = "abaa"
+ * StringUtils.replace("abaa", "A", "z", 1, true) = "zbaa"
+ * StringUtils.replace("abAa", "a", "z", 2, true) = "zbza"
+ * StringUtils.replace("abAa", "a", "z", -1, true) = "zbzz"
+ *
+ *
+ * @param text text to search and replace in, may be null
+ * @param searchString the String to search for (case insensitive), may be null
+ * @param replacement the String to replace it with, may be null
+ * @param max maximum number of values to replace, or {@code -1} if no maximum
+ * @param ignoreCase if true replace is case insensitive, otherwise case sensitive
+ * @return the text with any replacements processed,
+ * {@code null} if null String input
+ */
+ private static String replace(String text, String searchString, String replacement, int max, boolean ignoreCase) {
+ if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) {
+ return text;
+ }
+ String searchText = text;
+ if (ignoreCase) {
+ searchText = text.toLowerCase();
+ searchString = searchString.toLowerCase();
+ }
+ int start = 0;
+ int end = searchText.indexOf(searchString, start);
+ if (end == INDEX_NOT_FOUND) {
+ return text;
+ }
+ final int replLength = searchString.length();
+ int increase = replacement.length() - replLength;
+ increase = increase < 0 ? 0 : increase;
+ increase *= max < 0 ? 16 : max > 64 ? 64 : max;
+ final StringBuilder buf = new StringBuilder(text.length() + increase);
+ while (end != INDEX_NOT_FOUND) {
+ buf.append(text.substring(start, end)).append(replacement);
+ start = end + replLength;
+ if (--max == 0) {
+ break;
+ }
+ end = searchText.indexOf(searchString, start);
+ }
+ buf.append(text.substring(start));
+ return buf.toString();
+ }
+
+ /**
+ * Case insensitively replaces a String with another String inside a larger String,
+ * for the first {@code max} values of the search String.
+ *
+ * A {@code null} reference passed to this method is a no-op.
+ *
+ *
+ * StringUtils.replaceIgnoreCase(null, *, *, *) = null
+ * StringUtils.replaceIgnoreCase("", *, *, *) = ""
+ * StringUtils.replaceIgnoreCase("any", null, *, *) = "any"
+ * StringUtils.replaceIgnoreCase("any", *, null, *) = "any"
+ * StringUtils.replaceIgnoreCase("any", "", *, *) = "any"
+ * StringUtils.replaceIgnoreCase("any", *, *, 0) = "any"
+ * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa"
+ * StringUtils.replaceIgnoreCase("abaa", "a", "", -1) = "b"
+ * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0) = "abaa"
+ * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1) = "zbaa"
+ * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2) = "zbza"
+ * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1) = "zbzz"
+ *
+ *
+ * @param text text to search and replace in, may be null
+ * @param searchString the String to search for (case insensitive), may be null
+ * @param replacement the String to replace it with, may be null
+ * @param max maximum number of values to replace, or {@code -1} if no maximum
+ * @return the text with any replacements processed,
+ * {@code null} if null String input
+ * @since 3.5
+ */
+ public static String replaceIgnoreCase(String text, String searchString, String replacement, int max) {
+ return replace(text, searchString, replacement, max, true);
+ }
+
+ /**
+ *
+ * Replaces all occurrences of Strings within another String.
+ *
+ *
+ *
+ * A {@code null} reference passed to this method is a no-op, or if
+ * any "search string" or "string to replace" is null, that replace will be
+ * ignored. This will not repeat. For repeating replaces, call the
+ * overloaded method.
+ *
+ *
+ *
+ * StringUtils.replaceEach(null, *, *) = null
+ * StringUtils.replaceEach("", *, *) = ""
+ * StringUtils.replaceEach("aba", null, null) = "aba"
+ * StringUtils.replaceEach("aba", new String[0], null) = "aba"
+ * StringUtils.replaceEach("aba", null, new String[0]) = "aba"
+ * StringUtils.replaceEach("aba", new String[]{"a"}, null) = "aba"
+ * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}) = "b"
+ * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}) = "aba"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
+ * (example of how it does not repeat)
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "dcte"
+ *
+ *
+ * @param text
+ * text to search and replace in, no-op if null
+ * @param searchList
+ * the Strings to search for, no-op if null
+ * @param replacementList
+ * the Strings to replace them with, no-op if null
+ * @return the text with any replacements processed, {@code null} if
+ * null String input
+ * @throws IllegalArgumentException
+ * if the lengths of the arrays are not the same (null is ok,
+ * and/or size 0)
+ * @since 2.4
+ */
+ public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) {
+ return replaceEach(text, searchList, replacementList, false, 0);
+ }
+
+ /**
+ *
+ * Replaces all occurrences of Strings within another String.
+ *
+ *
+ *
+ * A {@code null} reference passed to this method is a no-op, or if
+ * any "search string" or "string to replace" is null, that replace will be
+ * ignored.
+ *
+ *
+ *
+ * StringUtils.replaceEachRepeatedly(null, *, *) = null
+ * StringUtils.replaceEachRepeatedly("", *, *) = ""
+ * StringUtils.replaceEachRepeatedly("aba", null, null) = "aba"
+ * StringUtils.replaceEachRepeatedly("aba", new String[0], null) = "aba"
+ * StringUtils.replaceEachRepeatedly("aba", null, new String[0]) = "aba"
+ * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null) = "aba"
+ * StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""}) = "b"
+ * StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"}) = "aba"
+ * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}) = "wcte"
+ * (example of how it repeats)
+ * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}) = "tcte"
+ * StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = IllegalStateException
+ *
+ *
+ * @param text
+ * text to search and replace in, no-op if null
+ * @param searchList
+ * the Strings to search for, no-op if null
+ * @param replacementList
+ * the Strings to replace them with, no-op if null
+ * @return the text with any replacements processed, {@code null} if
+ * null String input
+ * @throws IllegalStateException
+ * if the search is repeating and there is an endless loop due
+ * to outputs of one being inputs to another
+ * @throws IllegalArgumentException
+ * if the lengths of the arrays are not the same (null is ok,
+ * and/or size 0)
+ * @since 2.4
+ */
+ public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) {
+ // timeToLive should be 0 if not used or nothing to replace, else it's
+ // the length of the replace array
+ final int timeToLive = searchList == null ? 0 : searchList.length;
+ return replaceEach(text, searchList, replacementList, true, timeToLive);
+ }
+
+ /**
+ *
+ * Replace all occurrences of Strings within another String.
+ * This is a private recursive helper method for {@link #replaceEachRepeatedly(String, String[], String[])} and
+ * {@link #replaceEach(String, String[], String[])}
+ *
+ *
+ *
+ * A {@code null} reference passed to this method is a no-op, or if
+ * any "search string" or "string to replace" is null, that replace will be
+ * ignored.
+ *
+ *
+ *
+ * StringUtils.replaceEach(null, *, *, *, *) = null
+ * StringUtils.replaceEach("", *, *, *, *) = ""
+ * StringUtils.replaceEach("aba", null, null, *, *) = "aba"
+ * StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba"
+ * StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba"
+ * StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba"
+ * StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b"
+ * StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte"
+ * (example of how it repeats)
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte"
+ * StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = IllegalStateException
+ *
+ *
+ * @param text
+ * text to search and replace in, no-op if null
+ * @param searchList
+ * the Strings to search for, no-op if null
+ * @param replacementList
+ * the Strings to replace them with, no-op if null
+ * @param repeat if true, then replace repeatedly
+ * until there are no more possible replacements or timeToLive < 0
+ * @param timeToLive
+ * if less than 0 then there is a circular reference and endless
+ * loop
+ * @return the text with any replacements processed, {@code null} if
+ * null String input
+ * @throws IllegalStateException
+ * if the search is repeating and there is an endless loop due
+ * to outputs of one being inputs to another
+ * @throws IllegalArgumentException
+ * if the lengths of the arrays are not the same (null is ok,
+ * and/or size 0)
+ * @since 2.4
+ */
+ private static String replaceEach(
+ final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) {
+
+ // mchyzer Performance note: This creates very few new objects (one major goal)
+ // let me know if there are performance requests, we can create a harness to measure
+
+ if (text == null || text.isEmpty() || searchList == null ||
+ searchList.length == 0 || replacementList == null || replacementList.length == 0) {
+ return text;
+ }
+
+ // if recursing, this shouldn't be less than 0
+ if (timeToLive < 0) {
+ throw new IllegalStateException("Aborting to protect against StackOverflowError - " +
+ "output of one loop is the input of another");
+ }
+
+ final int searchLength = searchList.length;
+ final int replacementLength = replacementList.length;
+
+ // make sure lengths are ok, these need to be equal
+ if (searchLength != replacementLength) {
+ throw new IllegalArgumentException("Search and Replace array lengths don't match: "
+ + searchLength
+ + " vs "
+ + replacementLength);
+ }
+
+ // keep track of which still have matches
+ final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
+
+ // index on index that the match was found
+ int textIndex = -1;
+ int replaceIndex = -1;
+ int tempIndex = -1;
+
+ // index of replace array that will replace the search string found
+ // NOTE: logic duplicated below START
+ for (int i = 0; i < searchLength; i++) {
+ if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
+ searchList[i].isEmpty() || replacementList[i] == null) {
+ continue;
+ }
+ tempIndex = text.indexOf(searchList[i]);
+
+ // see if we need to keep searching for this
+ if (tempIndex == -1) {
+ noMoreMatchesForReplIndex[i] = true;
+ } else {
+ if (textIndex == -1 || tempIndex < textIndex) {
+ textIndex = tempIndex;
+ replaceIndex = i;
+ }
+ }
+ }
+ // NOTE: logic mostly below END
+
+ // no search strings found, we are done
+ if (textIndex == -1) {
+ return text;
+ }
+
+ int start = 0;
+
+ // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit
+ int increase = 0;
+
+ // count the replacement text elements that are larger than their corresponding text being replaced
+ for (int i = 0; i < searchList.length; i++) {
+ if (searchList[i] == null || replacementList[i] == null) {
+ continue;
+ }
+ final int greater = replacementList[i].length() - searchList[i].length();
+ if (greater > 0) {
+ increase += 3 * greater; // assume 3 matches
+ }
+ }
+ // have upper-bound at 20% increase, then let Java take over
+ increase = Math.min(increase, text.length() / 5);
+
+ final StringBuilder buf = new StringBuilder(text.length() + increase);
+
+ while (textIndex != -1) {
+
+ for (int i = start; i < textIndex; i++) {
+ buf.append(text.charAt(i));
+ }
+ buf.append(replacementList[replaceIndex]);
+
+ start = textIndex + searchList[replaceIndex].length();
+
+ textIndex = -1;
+ replaceIndex = -1;
+ tempIndex = -1;
+ // find the next earliest match
+ // NOTE: logic mostly duplicated above START
+ for (int i = 0; i < searchLength; i++) {
+ if (noMoreMatchesForReplIndex[i] || searchList[i] == null ||
+ searchList[i].isEmpty() || replacementList[i] == null) {
+ continue;
+ }
+ tempIndex = text.indexOf(searchList[i], start);
+
+ // see if we need to keep searching for this
+ if (tempIndex == -1) {
+ noMoreMatchesForReplIndex[i] = true;
+ } else {
+ if (textIndex == -1 || tempIndex < textIndex) {
+ textIndex = tempIndex;
+ replaceIndex = i;
+ }
+ }
+ }
+ // NOTE: logic duplicated above END
+
+ }
+ final int textLength = text.length();
+ for (int i = start; i < textLength; i++) {
+ buf.append(text.charAt(i));
+ }
+ final String result = buf.toString();
+ if (!repeat) {
+ return result;
+ }
+
+ return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
+ }
+
+ // Replace, character based
+ //-----------------------------------------------------------------------
+ /**
+ * Replaces all occurrences of a character in a String with another.
+ * This is a null-safe version of {@link String#replace(char, char)}.
+ *
+ * A {@code null} string input returns {@code null}.
+ * An empty ("") string input returns an empty string.
+ *
+ *
+ * StringUtils.replaceChars(null, *, *) = null
+ * StringUtils.replaceChars("", *, *) = ""
+ * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
+ * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
+ *
+ *
+ * @param str String to replace characters in, may be null
+ * @param searchChar the character to search for, may be null
+ * @param replaceChar the character to replace, may be null
+ * @return modified String, {@code null} if null string input
+ * @since 2.0
+ */
+ public static String replaceChars(final String str, final char searchChar, final char replaceChar) {
+ if (str == null) {
+ return null;
+ }
+ return str.replace(searchChar, replaceChar);
+ }
+
+ /**
+ * Replaces multiple characters in a String in one go.
+ * This method can also be used to delete characters.
+ *
+ * For example:
+ * replaceChars("hello", "ho", "jy") = jelly
.
+ *
+ * A {@code null} string input returns {@code null}.
+ * An empty ("") string input returns an empty string.
+ * A null or empty set of search characters returns the input string.
+ *
+ * The length of the search characters should normally equal the length
+ * of the replace characters.
+ * If the search characters is longer, then the extra search characters
+ * are deleted.
+ * If the search characters is shorter, then the extra replace characters
+ * are ignored.
+ *
+ *
+ * StringUtils.replaceChars(null, *, *) = null
+ * StringUtils.replaceChars("", *, *) = ""
+ * StringUtils.replaceChars("abc", null, *) = "abc"
+ * StringUtils.replaceChars("abc", "", *) = "abc"
+ * StringUtils.replaceChars("abc", "b", null) = "ac"
+ * StringUtils.replaceChars("abc", "b", "") = "ac"
+ * StringUtils.replaceChars("abcba", "bc", "yz") = "ayzya"
+ * StringUtils.replaceChars("abcba", "bc", "y") = "ayya"
+ * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
+ *
+ *
+ * @param str String to replace characters in, may be null
+ * @param searchChars a set of characters to search for, may be null
+ * @param replaceChars a set of characters to replace, may be null
+ * @return modified String, {@code null} if null string input
+ * @since 2.0
+ */
+ public static String replaceChars(final String str, final String searchChars, String replaceChars) {
+ if (isEmpty(str) || isEmpty(searchChars)) {
+ return str;
+ }
+ if (replaceChars == null) {
+ replaceChars = EMPTY;
+ }
+ boolean modified = false;
+ final int replaceCharsLength = replaceChars.length();
+ final int strLength = str.length();
+ final StringBuilder buf = new StringBuilder(strLength);
+ for (int i = 0; i < strLength; i++) {
+ final char ch = str.charAt(i);
+ final int index = searchChars.indexOf(ch);
+ if (index >= 0) {
+ modified = true;
+ if (index < replaceCharsLength) {
+ buf.append(replaceChars.charAt(index));
+ }
+ } else {
+ buf.append(ch);
+ }
+ }
+ if (modified) {
+ return buf.toString();
+ }
+ return str;
+ }
+
+ // Overlay
+ //-----------------------------------------------------------------------
+ /**
+ * Overlays part of a String with another String.
+ *
+ * A {@code null} string input returns {@code null}.
+ * A negative index is treated as zero.
+ * An index greater than the string length is treated as the string length.
+ * The start index is always the smaller of the two indices.
+ *
+ *
+ * StringUtils.overlay(null, *, *, *) = null
+ * StringUtils.overlay("", "abc", 0, 0) = "abc"
+ * StringUtils.overlay("abcdef", null, 2, 4) = "abef"
+ * StringUtils.overlay("abcdef", "", 2, 4) = "abef"
+ * StringUtils.overlay("abcdef", "", 4, 2) = "abef"
+ * StringUtils.overlay("abcdef", "zzzz", 2, 4) = "abzzzzef"
+ * StringUtils.overlay("abcdef", "zzzz", 4, 2) = "abzzzzef"
+ * StringUtils.overlay("abcdef", "zzzz", -1, 4) = "zzzzef"
+ * StringUtils.overlay("abcdef", "zzzz", 2, 8) = "abzzzz"
+ * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
+ * StringUtils.overlay("abcdef", "zzzz", 8, 10) = "abcdefzzzz"
+ *
+ *
+ * @param str the String to do overlaying in, may be null
+ * @param overlay the String to overlay, may be null
+ * @param start the position to start overlaying at
+ * @param end the position to stop overlaying before
+ * @return overlayed String, {@code null} if null String input
+ * @since 2.0
+ */
+ public static String overlay(final String str, String overlay, int start, int end) {
+ if (str == null) {
+ return null;
+ }
+ if (overlay == null) {
+ overlay = EMPTY;
+ }
+ final int len = str.length();
+ if (start < 0) {
+ start = 0;
+ }
+ if (start > len) {
+ start = len;
+ }
+ if (end < 0) {
+ end = 0;
+ }
+ if (end > len) {
+ end = len;
+ }
+ if (start > end) {
+ final int temp = start;
+ start = end;
+ end = temp;
+ }
+ return new StringBuilder(len + start - end + overlay.length() + 1)
+ .append(str.substring(0, start))
+ .append(overlay)
+ .append(str.substring(end))
+ .toString();
+ }
+
+ // Chomping
+ //-----------------------------------------------------------------------
+ /**
+ * Removes one newline from end of a String if it's there,
+ * otherwise leave it alone. A newline is "{@code \n}",
+ * "{@code \r}", or "{@code \r\n}".
+ *
+ * NOTE: This method changed in 2.0.
+ * It now more closely matches Perl chomp.
+ *
+ *
+ * StringUtils.chomp(null) = null
+ * StringUtils.chomp("") = ""
+ * StringUtils.chomp("abc \r") = "abc "
+ * StringUtils.chomp("abc\n") = "abc"
+ * StringUtils.chomp("abc\r\n") = "abc"
+ * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
+ * StringUtils.chomp("abc\n\r") = "abc\n"
+ * StringUtils.chomp("abc\n\rabc") = "abc\n\rabc"
+ * StringUtils.chomp("\r") = ""
+ * StringUtils.chomp("\n") = ""
+ * StringUtils.chomp("\r\n") = ""
+ *
+ *
+ * @param str the String to chomp a newline from, may be null
+ * @return String without newline, {@code null} if null String input
+ */
+ public static String chomp(final String str) {
+ if (isEmpty(str)) {
+ return str;
+ }
+
+ if (str.length() == 1) {
+ final char ch = str.charAt(0);
+ if (ch == CharUtils.CR || ch == CharUtils.LF) {
+ return EMPTY;
+ }
+ return str;
+ }
+
+ int lastIdx = str.length() - 1;
+ final char last = str.charAt(lastIdx);
+
+ if (last == CharUtils.LF) {
+ if (str.charAt(lastIdx - 1) == CharUtils.CR) {
+ lastIdx--;
+ }
+ } else if (last != CharUtils.CR) {
+ lastIdx++;
+ }
+ return str.substring(0, lastIdx);
+ }
+
+ /**
+ * Removes {@code separator} from the end of
+ * {@code str} if it's there, otherwise leave it alone.
+ *
+ * NOTE: This method changed in version 2.0.
+ * It now more closely matches Perl chomp.
+ * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
+ * This method uses {@link String#endsWith(String)}.
+ *
+ *
+ * StringUtils.chomp(null, *) = null
+ * StringUtils.chomp("", *) = ""
+ * StringUtils.chomp("foobar", "bar") = "foo"
+ * StringUtils.chomp("foobar", "baz") = "foobar"
+ * StringUtils.chomp("foo", "foo") = ""
+ * StringUtils.chomp("foo ", "foo") = "foo "
+ * StringUtils.chomp(" foo", "foo") = " "
+ * StringUtils.chomp("foo", "foooo") = "foo"
+ * StringUtils.chomp("foo", "") = "foo"
+ * StringUtils.chomp("foo", null) = "foo"
+ *
+ *
+ * @param str the String to chomp from, may be null
+ * @param separator separator String, may be null
+ * @return String without trailing separator, {@code null} if null String input
+ * @deprecated This feature will be removed in Lang 4.0, use {@link StringUtils#removeEnd(String, String)} instead
+ */
+ @Deprecated
+ public static String chomp(final String str, final String separator) {
+ return removeEnd(str,separator);
+ }
+
+ // Chopping
+ //-----------------------------------------------------------------------
+ /**
+ * Remove the last character from a String.
+ *
+ * If the String ends in {@code \r\n}, then remove both
+ * of them.
+ *
+ *
+ * StringUtils.chop(null) = null
+ * StringUtils.chop("") = ""
+ * StringUtils.chop("abc \r") = "abc "
+ * StringUtils.chop("abc\n") = "abc"
+ * StringUtils.chop("abc\r\n") = "abc"
+ * StringUtils.chop("abc") = "ab"
+ * StringUtils.chop("abc\nabc") = "abc\nab"
+ * StringUtils.chop("a") = ""
+ * StringUtils.chop("\r") = ""
+ * StringUtils.chop("\n") = ""
+ * StringUtils.chop("\r\n") = ""
+ *
+ *
+ * @param str the String to chop last character from, may be null
+ * @return String without last character, {@code null} if null String input
+ */
+ public static String chop(final String str) {
+ if (str == null) {
+ return null;
+ }
+ final int strLen = str.length();
+ if (strLen < 2) {
+ return EMPTY;
+ }
+ final int lastIdx = strLen - 1;
+ final String ret = str.substring(0, lastIdx);
+ final char last = str.charAt(lastIdx);
+ if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
+ return ret.substring(0, lastIdx - 1);
+ }
+ return ret;
+ }
+
+ // Conversion
+ //-----------------------------------------------------------------------
+
+ // Padding
+ //-----------------------------------------------------------------------
+ /**
+ * Repeat a String {@code repeat} times to form a
+ * new String.
+ *
+ *
+ * StringUtils.repeat(null, 2) = null
+ * StringUtils.repeat("", 0) = ""
+ * StringUtils.repeat("", 2) = ""
+ * StringUtils.repeat("a", 3) = "aaa"
+ * StringUtils.repeat("ab", 2) = "abab"
+ * StringUtils.repeat("a", -2) = ""
+ *
+ *
+ * @param str the String to repeat, may be null
+ * @param repeat number of times to repeat str, negative treated as zero
+ * @return a new String consisting of the original String repeated,
+ * {@code null} if null String input
+ */
+ public static String repeat(final String str, final int repeat) {
+ // Performance tuned for 2.0 (JDK1.4)
+
+ if (str == null) {
+ return null;
+ }
+ if (repeat <= 0) {
+ return EMPTY;
+ }
+ final int inputLength = str.length();
+ if (repeat == 1 || inputLength == 0) {
+ return str;
+ }
+ if (inputLength == 1 && repeat <= PAD_LIMIT) {
+ return repeat(str.charAt(0), repeat);
+ }
+
+ final int outputLength = inputLength * repeat;
+ switch (inputLength) {
+ case 1 :
+ return repeat(str.charAt(0), repeat);
+ case 2 :
+ final char ch0 = str.charAt(0);
+ final char ch1 = str.charAt(1);
+ final char[] output2 = new char[outputLength];
+ for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
+ output2[i] = ch0;
+ output2[i + 1] = ch1;
+ }
+ return new String(output2);
+ default :
+ final StringBuilder buf = new StringBuilder(outputLength);
+ for (int i = 0; i < repeat; i++) {
+ buf.append(str);
+ }
+ return buf.toString();
+ }
+ }
+
+ /**
+ * Repeat a String {@code repeat} times to form a
+ * new String, with a String separator injected each time.
+ *
+ *
+ * StringUtils.repeat(null, null, 2) = null
+ * StringUtils.repeat(null, "x", 2) = null
+ * StringUtils.repeat("", null, 0) = ""
+ * StringUtils.repeat("", "", 2) = ""
+ * StringUtils.repeat("", "x", 3) = "xxx"
+ * StringUtils.repeat("?", ", ", 3) = "?, ?, ?"
+ *
+ *
+ * @param str the String to repeat, may be null
+ * @param separator the String to inject, may be null
+ * @param repeat number of times to repeat str, negative treated as zero
+ * @return a new String consisting of the original String repeated,
+ * {@code null} if null String input
+ * @since 2.5
+ */
+ public static String repeat(final String str, final String separator, final int repeat) {
+ if(str == null || separator == null) {
+ return repeat(str, repeat);
+ }
+ // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
+ final String result = repeat(str + separator, repeat);
+ return removeEnd(result, separator);
+ }
+
+ /**
+ * Returns padding using the specified delimiter repeated
+ * to a given length.
+ *
+ *
+ * StringUtils.repeat('e', 0) = ""
+ * StringUtils.repeat('e', 3) = "eee"
+ * StringUtils.repeat('e', -2) = ""
+ *
+ *
+ * Note: this method doesn't not support padding with
+ * Unicode Supplementary Characters
+ * as they require a pair of {@code char}s to be represented.
+ * If you are needing to support full I18N of your applications
+ * consider using {@link #repeat(String, int)} instead.
+ *
+ *
+ * @param ch character to repeat
+ * @param repeat number of times to repeat char, negative treated as zero
+ * @return String with repeated character
+ * @see #repeat(String, int)
+ */
+ public static String repeat(final char ch, final int repeat) {
+ if (repeat <= 0) {
+ return EMPTY;
+ }
+ final char[] buf = new char[repeat];
+ for (int i = repeat - 1; i >= 0; i--) {
+ buf[i] = ch;
+ }
+ return new String(buf);
+ }
+
+ /**
+ * Right pad a String with spaces (' ').
+ *
+ * The String is padded to the size of {@code size}.
+ *
+ *
+ * StringUtils.rightPad(null, *) = null
+ * StringUtils.rightPad("", 3) = " "
+ * StringUtils.rightPad("bat", 3) = "bat"
+ * StringUtils.rightPad("bat", 5) = "bat "
+ * StringUtils.rightPad("bat", 1) = "bat"
+ * StringUtils.rightPad("bat", -1) = "bat"
+ *
+ *
+ * @param str the String to pad out, may be null
+ * @param size the size to pad to
+ * @return right padded String or original String if no padding is necessary,
+ * {@code null} if null String input
+ */
+ public static String rightPad(final String str, final int size) {
+ return rightPad(str, size, ' ');
+ }
+
+ /**
+ * Right pad a String with a specified character.
+ *
+ * The String is padded to the size of {@code size}.
+ *
+ *
+ * StringUtils.rightPad(null, *, *) = null
+ * StringUtils.rightPad("", 3, 'z') = "zzz"
+ * StringUtils.rightPad("bat", 3, 'z') = "bat"
+ * StringUtils.rightPad("bat", 5, 'z') = "batzz"
+ * StringUtils.rightPad("bat", 1, 'z') = "bat"
+ * StringUtils.rightPad("bat", -1, 'z') = "bat"
+ *
+ *
+ * @param str the String to pad out, may be null
+ * @param size the size to pad to
+ * @param padChar the character to pad with
+ * @return right padded String or original String if no padding is necessary,
+ * {@code null} if null String input
+ * @since 2.0
+ */
+ public static String rightPad(final String str, final int size, final char padChar) {
+ if (str == null) {
+ return null;
+ }
+ final int pads = size - str.length();
+ if (pads <= 0) {
+ return str; // returns original String when possible
+ }
+ if (pads > PAD_LIMIT) {
+ return rightPad(str, size, String.valueOf(padChar));
+ }
+ return str.concat(repeat(padChar, pads));
+ }
+
+ /**
+ * Right pad a String with a specified String.
+ *
+ * The String is padded to the size of {@code size}.
+ *
+ *
+ * StringUtils.rightPad(null, *, *) = null
+ * StringUtils.rightPad("", 3, "z") = "zzz"
+ * StringUtils.rightPad("bat", 3, "yz") = "bat"
+ * StringUtils.rightPad("bat", 5, "yz") = "batyz"
+ * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy"
+ * StringUtils.rightPad("bat", 1, "yz") = "bat"
+ * StringUtils.rightPad("bat", -1, "yz") = "bat"
+ * StringUtils.rightPad("bat", 5, null) = "bat "
+ * StringUtils.rightPad("bat", 5, "") = "bat "
+ *
+ *
+ * @param str the String to pad out, may be null
+ * @param size the size to pad to
+ * @param padStr the String to pad with, null or empty treated as single space
+ * @return right padded String or original String if no padding is necessary,
+ * {@code null} if null String input
+ */
+ public static String rightPad(final String str, final int size, String padStr) {
+ if (str == null) {
+ return null;
+ }
+ if (isEmpty(padStr)) {
+ padStr = SPACE;
+ }
+ final int padLen = padStr.length();
+ final int strLen = str.length();
+ final int pads = size - strLen;
+ if (pads <= 0) {
+ return str; // returns original String when possible
+ }
+ if (padLen == 1 && pads <= PAD_LIMIT) {
+ return rightPad(str, size, padStr.charAt(0));
+ }
+
+ if (pads == padLen) {
+ return str.concat(padStr);
+ } else if (pads < padLen) {
+ return str.concat(padStr.substring(0, pads));
+ } else {
+ final char[] padding = new char[pads];
+ final char[] padChars = padStr.toCharArray();
+ for (int i = 0; i < pads; i++) {
+ padding[i] = padChars[i % padLen];
+ }
+ return str.concat(new String(padding));
+ }
+ }
+
+ /**
+ * Left pad a String with spaces (' ').
+ *
+ * The String is padded to the size of {@code size}.
+ *
+ *
+ * StringUtils.leftPad(null, *) = null
+ * StringUtils.leftPad("", 3) = " "
+ * StringUtils.leftPad("bat", 3) = "bat"
+ * StringUtils.leftPad("bat", 5) = " bat"
+ * StringUtils.leftPad("bat", 1) = "bat"
+ * StringUtils.leftPad("bat", -1) = "bat"
+ *
+ *
+ * @param str the String to pad out, may be null
+ * @param size the size to pad to
+ * @return left padded String or original String if no padding is necessary,
+ * {@code null} if null String input
+ */
+ public static String leftPad(final String str, final int size) {
+ return leftPad(str, size, ' ');
+ }
+
+ /**
+ * Left pad a String with a specified character.
+ *
+ * Pad to a size of {@code size}.
+ *
+ *
+ * StringUtils.leftPad(null, *, *) = null
+ * StringUtils.leftPad("", 3, 'z') = "zzz"
+ * StringUtils.leftPad("bat", 3, 'z') = "bat"
+ * StringUtils.leftPad("bat", 5, 'z') = "zzbat"
+ * StringUtils.leftPad("bat", 1, 'z') = "bat"
+ * StringUtils.leftPad("bat", -1, 'z') = "bat"
+ *
+ *
+ * @param str the String to pad out, may be null
+ * @param size the size to pad to
+ * @param padChar the character to pad with
+ * @return left padded String or original String if no padding is necessary,
+ * {@code null} if null String input
+ * @since 2.0
+ */
+ public static String leftPad(final String str, final int size, final char padChar) {
+ if (str == null) {
+ return null;
+ }
+ final int pads = size - str.length();
+ if (pads <= 0) {
+ return str; // returns original String when possible
+ }
+ if (pads > PAD_LIMIT) {
+ return leftPad(str, size, String.valueOf(padChar));
+ }
+ return repeat(padChar, pads).concat(str);
+ }
+
+ /**
+ * Left pad a String with a specified String.
+ *
+ * Pad to a size of {@code size}.
+ *
+ *
+ * StringUtils.leftPad(null, *, *) = null
+ * StringUtils.leftPad("", 3, "z") = "zzz"
+ * StringUtils.leftPad("bat", 3, "yz") = "bat"
+ * StringUtils.leftPad("bat", 5, "yz") = "yzbat"
+ * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat"
+ * StringUtils.leftPad("bat", 1, "yz") = "bat"
+ * StringUtils.leftPad("bat", -1, "yz") = "bat"
+ * StringUtils.leftPad("bat", 5, null) = " bat"
+ * StringUtils.leftPad("bat", 5, "") = " bat"
+ *
+ *
+ * @param str the String to pad out, may be null
+ * @param size the size to pad to
+ * @param padStr the String to pad with, null or empty treated as single space
+ * @return left padded String or original String if no padding is necessary,
+ * {@code null} if null String input
+ */
+ public static String leftPad(final String str, final int size, String padStr) {
+ if (str == null) {
+ return null;
+ }
+ if (isEmpty(padStr)) {
+ padStr = SPACE;
+ }
+ final int padLen = padStr.length();
+ final int strLen = str.length();
+ final int pads = size - strLen;
+ if (pads <= 0) {
+ return str; // returns original String when possible
+ }
+ if (padLen == 1 && pads <= PAD_LIMIT) {
+ return leftPad(str, size, padStr.charAt(0));
+ }
+
+ if (pads == padLen) {
+ return padStr.concat(str);
+ } else if (pads < padLen) {
+ return padStr.substring(0, pads).concat(str);
+ } else {
+ final char[] padding = new char[pads];
+ final char[] padChars = padStr.toCharArray();
+ for (int i = 0; i < pads; i++) {
+ padding[i] = padChars[i % padLen];
+ }
+ return new String(padding).concat(str);
+ }
+ }
+
+ /**
+ * Gets a CharSequence length or {@code 0} if the CharSequence is
+ * {@code null}.
+ *
+ * @param cs
+ * a CharSequence or {@code null}
+ * @return CharSequence length or {@code 0} if the CharSequence is
+ * {@code null}.
+ * @since 2.4
+ * @since 3.0 Changed signature from length(String) to length(CharSequence)
+ */
+ public static int length(final CharSequence cs) {
+ return cs == null ? 0 : cs.length();
+ }
+
+ // Centering
+ //-----------------------------------------------------------------------
+ /**
+ * Centers a String in a larger String of size {@code size}
+ * using the space character (' ').
+ *
+ * If the size is less than the String length, the String is returned.
+ * A {@code null} String returns {@code null}.
+ * A negative size is treated as zero.
+ *
+ * Equivalent to {@code center(str, size, " ")}.
+ *
+ *
+ * StringUtils.center(null, *) = null
+ * StringUtils.center("", 4) = " "
+ * StringUtils.center("ab", -1) = "ab"
+ * StringUtils.center("ab", 4) = " ab "
+ * StringUtils.center("abcd", 2) = "abcd"
+ * StringUtils.center("a", 4) = " a "
+ *
+ *
+ * @param str the String to center, may be null
+ * @param size the int size of new String, negative treated as zero
+ * @return centered String, {@code null} if null String input
+ */
+ public static String center(final String str, final int size) {
+ return center(str, size, ' ');
+ }
+
+ /**
+ * Centers a String in a larger String of size {@code size}.
+ * Uses a supplied character as the value to pad the String with.
+ *
+ * If the size is less than the String length, the String is returned.
+ * A {@code null} String returns {@code null}.
+ * A negative size is treated as zero.
+ *
+ *
+ * StringUtils.center(null, *, *) = null
+ * StringUtils.center("", 4, ' ') = " "
+ * StringUtils.center("ab", -1, ' ') = "ab"
+ * StringUtils.center("ab", 4, ' ') = " ab "
+ * StringUtils.center("abcd", 2, ' ') = "abcd"
+ * StringUtils.center("a", 4, ' ') = " a "
+ * StringUtils.center("a", 4, 'y') = "yayy"
+ *
+ *
+ * @param str the String to center, may be null
+ * @param size the int size of new String, negative treated as zero
+ * @param padChar the character to pad the new String with
+ * @return centered String, {@code null} if null String input
+ * @since 2.0
+ */
+ public static String center(String str, final int size, final char padChar) {
+ if (str == null || size <= 0) {
+ return str;
+ }
+ final int strLen = str.length();
+ final int pads = size - strLen;
+ if (pads <= 0) {
+ return str;
+ }
+ str = leftPad(str, strLen + pads / 2, padChar);
+ str = rightPad(str, size, padChar);
+ return str;
+ }
+
+ /**
+ * Centers a String in a larger String of size {@code size}.
+ * Uses a supplied String as the value to pad the String with.
+ *
+ * If the size is less than the String length, the String is returned.
+ * A {@code null} String returns {@code null}.
+ * A negative size is treated as zero.
+ *
+ *
+ * StringUtils.center(null, *, *) = null
+ * StringUtils.center("", 4, " ") = " "
+ * StringUtils.center("ab", -1, " ") = "ab"
+ * StringUtils.center("ab", 4, " ") = " ab "
+ * StringUtils.center("abcd", 2, " ") = "abcd"
+ * StringUtils.center("a", 4, " ") = " a "
+ * StringUtils.center("a", 4, "yz") = "yayz"
+ * StringUtils.center("abc", 7, null) = " abc "
+ * StringUtils.center("abc", 7, "") = " abc "
+ *
+ *
+ * @param str the String to center, may be null
+ * @param size the int size of new String, negative treated as zero
+ * @param padStr the String to pad the new String with, must not be null or empty
+ * @return centered String, {@code null} if null String input
+ * @throws IllegalArgumentException if padStr is {@code null} or empty
+ */
+ public static String center(String str, final int size, String padStr) {
+ if (str == null || size <= 0) {
+ return str;
+ }
+ if (isEmpty(padStr)) {
+ padStr = SPACE;
+ }
+ final int strLen = str.length();
+ final int pads = size - strLen;
+ if (pads <= 0) {
+ return str;
+ }
+ str = leftPad(str, strLen + pads / 2, padStr);
+ str = rightPad(str, size, padStr);
+ return str;
+ }
+
+ // Case conversion
+ //-----------------------------------------------------------------------
+ /**
+ * Converts a String to upper case as per {@link String#toUpperCase()}.
+ *
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.upperCase(null) = null
+ * StringUtils.upperCase("") = ""
+ * StringUtils.upperCase("aBc") = "ABC"
+ *
+ *
+ * Note: As described in the documentation for {@link String#toUpperCase()},
+ * the result of this method is affected by the current locale.
+ * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
+ * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).
+ *
+ * @param str the String to upper case, may be null
+ * @return the upper cased String, {@code null} if null String input
+ */
+ public static String upperCase(final String str) {
+ if (str == null) {
+ return null;
+ }
+ return str.toUpperCase();
+ }
+
+ /**
+ * Converts a String to upper case as per {@link String#toUpperCase(Locale)}.
+ *
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.upperCase(null, Locale.ENGLISH) = null
+ * StringUtils.upperCase("", Locale.ENGLISH) = ""
+ * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
+ *
+ *
+ * @param str the String to upper case, may be null
+ * @param locale the locale that defines the case transformation rules, must not be null
+ * @return the upper cased String, {@code null} if null String input
+ * @since 2.5
+ */
+ public static String upperCase(final String str, final Locale locale) {
+ if (str == null) {
+ return null;
+ }
+ return str.toUpperCase(locale);
+ }
+
+ /**
+ * Converts a String to lower case as per {@link String#toLowerCase()}.
+ *
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.lowerCase(null) = null
+ * StringUtils.lowerCase("") = ""
+ * StringUtils.lowerCase("aBc") = "abc"
+ *
+ *
+ * Note: As described in the documentation for {@link String#toLowerCase()},
+ * the result of this method is affected by the current locale.
+ * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
+ * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).
+ *
+ * @param str the String to lower case, may be null
+ * @return the lower cased String, {@code null} if null String input
+ */
+ public static String lowerCase(final String str) {
+ if (str == null) {
+ return null;
+ }
+ return str.toLowerCase();
+ }
+
+ /**
+ * Converts a String to lower case as per {@link String#toLowerCase(Locale)}.
+ *
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.lowerCase(null, Locale.ENGLISH) = null
+ * StringUtils.lowerCase("", Locale.ENGLISH) = ""
+ * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
+ *
+ *
+ * @param str the String to lower case, may be null
+ * @param locale the locale that defines the case transformation rules, must not be null
+ * @return the lower cased String, {@code null} if null String input
+ * @since 2.5
+ */
+ public static String lowerCase(final String str, final Locale locale) {
+ if (str == null) {
+ return null;
+ }
+ return str.toLowerCase(locale);
+ }
+
+ /**
+ * Capitalizes a String changing the first character to title case as
+ * per {@link Character#toTitleCase(char)}. No other characters are changed.
+ *
+ * For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#capitalize(String)}.
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.capitalize(null) = null
+ * StringUtils.capitalize("") = ""
+ * StringUtils.capitalize("cat") = "Cat"
+ * StringUtils.capitalize("cAt") = "CAt"
+ * StringUtils.capitalize("'cat'") = "'cat'"
+ *
+ *
+ * @param str the String to capitalize, may be null
+ * @return the capitalized String, {@code null} if null String input
+ * @see org.apache.commons.lang3.text.WordUtils#capitalize(String)
+ * @see #uncapitalize(String)
+ * @since 2.0
+ */
+ public static String capitalize(final String str) {
+ int strLen;
+ if (str == null || (strLen = str.length()) == 0) {
+ return str;
+ }
+
+ final char firstChar = str.charAt(0);
+ final char newChar = Character.toTitleCase(firstChar);
+ if (firstChar == newChar) {
+ // already capitalized
+ return str;
+ }
+
+ char[] newChars = new char[strLen];
+ newChars[0] = newChar;
+ str.getChars(1,strLen, newChars, 1);
+ return String.valueOf(newChars);
+ }
+
+ /**
+ * Uncapitalizes a String, changing the first character to lower case as
+ * per {@link Character#toLowerCase(char)}. No other characters are changed.
+ *
+ * For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#uncapitalize(String)}.
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.uncapitalize(null) = null
+ * StringUtils.uncapitalize("") = ""
+ * StringUtils.uncapitalize("cat") = "cat"
+ * StringUtils.uncapitalize("Cat") = "cat"
+ * StringUtils.uncapitalize("CAT") = "cAT"
+ *
+ *
+ * @param str the String to uncapitalize, may be null
+ * @return the uncapitalized String, {@code null} if null String input
+ * @see org.apache.commons.lang3.text.WordUtils#uncapitalize(String)
+ * @see #capitalize(String)
+ * @since 2.0
+ */
+ public static String uncapitalize(final String str) {
+ int strLen;
+ if (str == null || (strLen = str.length()) == 0) {
+ return str;
+ }
+
+ final char firstChar = str.charAt(0);
+ final char newChar = Character.toLowerCase(firstChar);
+ if (firstChar == newChar) {
+ // already uncapitalized
+ return str;
+ }
+
+ char[] newChars = new char[strLen];
+ newChars[0] = newChar;
+ str.getChars(1,strLen, newChars, 1);
+ return String.valueOf(newChars);
+ }
+
+ /**
+ * Swaps the case of a String changing upper and title case to
+ * lower case, and lower case to upper case.
+ *
+ *
+ * Upper case character converts to Lower case
+ * Title case character converts to Lower case
+ * Lower case character converts to Upper case
+ *
+ *
+ * For a word based algorithm, see {@link org.apache.commons.lang3.text.WordUtils#swapCase(String)}.
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ * StringUtils.swapCase(null) = null
+ * StringUtils.swapCase("") = ""
+ * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
+ *
+ *
+ * NOTE: This method changed in Lang version 2.0.
+ * It no longer performs a word based algorithm.
+ * If you only use ASCII, you will notice no change.
+ * That functionality is available in org.apache.commons.lang3.text.WordUtils.
+ *
+ * @param str the String to swap case, may be null
+ * @return the changed String, {@code null} if null String input
+ */
+ public static String swapCase(final String str) {
+ if (StringUtils.isEmpty(str)) {
+ return str;
+ }
+
+ final char[] buffer = str.toCharArray();
+
+ for (int i = 0; i < buffer.length; i++) {
+ final char ch = buffer[i];
+ if (Character.isUpperCase(ch)) {
+ buffer[i] = Character.toLowerCase(ch);
+ } else if (Character.isTitleCase(ch)) {
+ buffer[i] = Character.toLowerCase(ch);
+ } else if (Character.isLowerCase(ch)) {
+ buffer[i] = Character.toUpperCase(ch);
+ }
+ }
+ return new String(buffer);
+ }
+
+ // Count matches
+ //-----------------------------------------------------------------------
+ /**
+ * Counts how many times the substring appears in the larger string.
+ *
+ * A {@code null} or empty ("") String input returns {@code 0}.
+ *
+ *
+ * StringUtils.countMatches(null, *) = 0
+ * StringUtils.countMatches("", *) = 0
+ * StringUtils.countMatches("abba", null) = 0
+ * StringUtils.countMatches("abba", "") = 0
+ * StringUtils.countMatches("abba", "a") = 2
+ * StringUtils.countMatches("abba", "ab") = 1
+ * StringUtils.countMatches("abba", "xxx") = 0
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param sub the substring to count, may be null
+ * @return the number of occurrences, 0 if either CharSequence is {@code null}
+ * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence)
+ */
+ public static int countMatches(final CharSequence str, final CharSequence sub) {
+ if (isEmpty(str) || isEmpty(sub)) {
+ return 0;
+ }
+ int count = 0;
+ int idx = 0;
+ while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) {
+ count++;
+ idx += sub.length();
+ }
+ return count;
+ }
+
+ /**
+ * Counts how many times the char appears in the given string.
+ *
+ * A {@code null} or empty ("") String input returns {@code 0}.
+ *
+ *
+ * StringUtils.countMatches(null, *) = 0
+ * StringUtils.countMatches("", *) = 0
+ * StringUtils.countMatches("abba", 0) = 0
+ * StringUtils.countMatches("abba", 'a') = 2
+ * StringUtils.countMatches("abba", 'b') = 2
+ * StringUtils.countMatches("abba", 'x') = 0
+ *
+ *
+ * @param str the CharSequence to check, may be null
+ * @param ch the char to count
+ * @return the number of occurrences, 0 if the CharSequence is {@code null}
+ * @since 3.4
+ */
+ public static int countMatches(final CharSequence str, final char ch) {
+ if (isEmpty(str)) {
+ return 0;
+ }
+ int count = 0;
+ // We could also call str.toCharArray() for faster look ups but that would generate more garbage.
+ for (int i = 0; i < str.length(); i++) {
+ if (ch == str.charAt(i)) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ // Character Tests
+ //-----------------------------------------------------------------------
+ /**
+ * Checks if the CharSequence contains only Unicode letters.
+ *
+ * {@code null} will return {@code false}.
+ * An empty CharSequence (length()=0) will return {@code false}.
+ *
+ *
+ * StringUtils.isAlpha(null) = false
+ * StringUtils.isAlpha("") = false
+ * StringUtils.isAlpha(" ") = false
+ * StringUtils.isAlpha("abc") = true
+ * StringUtils.isAlpha("ab2c") = false
+ * StringUtils.isAlpha("ab-c") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if only contains letters, and is non-null
+ * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence)
+ * @since 3.0 Changed "" to return false and not true
+ */
+ public static boolean isAlpha(final CharSequence cs) {
+ if (isEmpty(cs)) {
+ return false;
+ }
+ final int sz = cs.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isLetter(cs.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the CharSequence contains only Unicode letters and
+ * space (' ').
+ *
+ * {@code null} will return {@code false}
+ * An empty CharSequence (length()=0) will return {@code true}.
+ *
+ *
+ * StringUtils.isAlphaSpace(null) = false
+ * StringUtils.isAlphaSpace("") = true
+ * StringUtils.isAlphaSpace(" ") = true
+ * StringUtils.isAlphaSpace("abc") = true
+ * StringUtils.isAlphaSpace("ab c") = true
+ * StringUtils.isAlphaSpace("ab2c") = false
+ * StringUtils.isAlphaSpace("ab-c") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if only contains letters and space,
+ * and is non-null
+ * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence)
+ */
+ public static boolean isAlphaSpace(final CharSequence cs) {
+ if (cs == null) {
+ return false;
+ }
+ final int sz = cs.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isLetter(cs.charAt(i)) == false && cs.charAt(i) != ' ') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the CharSequence contains only Unicode letters or digits.
+ *
+ * {@code null} will return {@code false}.
+ * An empty CharSequence (length()=0) will return {@code false}.
+ *
+ *
+ * StringUtils.isAlphanumeric(null) = false
+ * StringUtils.isAlphanumeric("") = false
+ * StringUtils.isAlphanumeric(" ") = false
+ * StringUtils.isAlphanumeric("abc") = true
+ * StringUtils.isAlphanumeric("ab c") = false
+ * StringUtils.isAlphanumeric("ab2c") = true
+ * StringUtils.isAlphanumeric("ab-c") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if only contains letters or digits,
+ * and is non-null
+ * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence)
+ * @since 3.0 Changed "" to return false and not true
+ */
+ public static boolean isAlphanumeric(final CharSequence cs) {
+ if (isEmpty(cs)) {
+ return false;
+ }
+ final int sz = cs.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isLetterOrDigit(cs.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the CharSequence contains only Unicode letters, digits
+ * or space ({@code ' '}).
+ *
+ * {@code null} will return {@code false}.
+ * An empty CharSequence (length()=0) will return {@code true}.
+ *
+ *
+ * StringUtils.isAlphanumericSpace(null) = false
+ * StringUtils.isAlphanumericSpace("") = true
+ * StringUtils.isAlphanumericSpace(" ") = true
+ * StringUtils.isAlphanumericSpace("abc") = true
+ * StringUtils.isAlphanumericSpace("ab c") = true
+ * StringUtils.isAlphanumericSpace("ab2c") = true
+ * StringUtils.isAlphanumericSpace("ab-c") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if only contains letters, digits or space,
+ * and is non-null
+ * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence)
+ */
+ public static boolean isAlphanumericSpace(final CharSequence cs) {
+ if (cs == null) {
+ return false;
+ }
+ final int sz = cs.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isLetterOrDigit(cs.charAt(i)) == false && cs.charAt(i) != ' ') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the CharSequence contains only ASCII printable characters.
+ *
+ * {@code null} will return {@code false}.
+ * An empty CharSequence (length()=0) will return {@code true}.
+ *
+ *
+ * StringUtils.isAsciiPrintable(null) = false
+ * StringUtils.isAsciiPrintable("") = true
+ * StringUtils.isAsciiPrintable(" ") = true
+ * StringUtils.isAsciiPrintable("Ceki") = true
+ * StringUtils.isAsciiPrintable("ab2c") = true
+ * StringUtils.isAsciiPrintable("!ab-c~") = true
+ * StringUtils.isAsciiPrintable("\u0020") = true
+ * StringUtils.isAsciiPrintable("\u0021") = true
+ * StringUtils.isAsciiPrintable("\u007e") = true
+ * StringUtils.isAsciiPrintable("\u007f") = false
+ * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if every character is in the range
+ * 32 thru 126
+ * @since 2.1
+ * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence)
+ */
+ public static boolean isAsciiPrintable(final CharSequence cs) {
+ if (cs == null) {
+ return false;
+ }
+ final int sz = cs.length();
+ for (int i = 0; i < sz; i++) {
+ if (CharUtils.isAsciiPrintable(cs.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the CharSequence contains only Unicode digits.
+ * A decimal point is not a Unicode digit and returns false.
+ *
+ * {@code null} will return {@code false}.
+ * An empty CharSequence (length()=0) will return {@code false}.
+ *
+ * Note that the method does not allow for a leading sign, either positive or negative.
+ * Also, if a String passes the numeric test, it may still generate a NumberFormatException
+ * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range
+ * for int or long respectively.
+ *
+ *
+ * StringUtils.isNumeric(null) = false
+ * StringUtils.isNumeric("") = false
+ * StringUtils.isNumeric(" ") = false
+ * StringUtils.isNumeric("123") = true
+ * StringUtils.isNumeric("\u0967\u0968\u0969") = true
+ * StringUtils.isNumeric("12 3") = false
+ * StringUtils.isNumeric("ab2c") = false
+ * StringUtils.isNumeric("12-3") = false
+ * StringUtils.isNumeric("12.3") = false
+ * StringUtils.isNumeric("-123") = false
+ * StringUtils.isNumeric("+123") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if only contains digits, and is non-null
+ * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
+ * @since 3.0 Changed "" to return false and not true
+ */
+ public static boolean isNumeric(final CharSequence cs) {
+ if (isEmpty(cs)) {
+ return false;
+ }
+ final int sz = cs.length();
+ for (int i = 0; i < sz; i++) {
+ if (!Character.isDigit(cs.charAt(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the CharSequence contains only Unicode digits or space
+ * ({@code ' '}).
+ * A decimal point is not a Unicode digit and returns false.
+ *
+ * {@code null} will return {@code false}.
+ * An empty CharSequence (length()=0) will return {@code true}.
+ *
+ *
+ * StringUtils.isNumericSpace(null) = false
+ * StringUtils.isNumericSpace("") = true
+ * StringUtils.isNumericSpace(" ") = true
+ * StringUtils.isNumericSpace("123") = true
+ * StringUtils.isNumericSpace("12 3") = true
+ * StringUtils.isNumeric("\u0967\u0968\u0969") = true
+ * StringUtils.isNumeric("\u0967\u0968 \u0969") = true
+ * StringUtils.isNumericSpace("ab2c") = false
+ * StringUtils.isNumericSpace("12-3") = false
+ * StringUtils.isNumericSpace("12.3") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if only contains digits or space,
+ * and is non-null
+ * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence)
+ */
+ public static boolean isNumericSpace(final CharSequence cs) {
+ if (cs == null) {
+ return false;
+ }
+ final int sz = cs.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isDigit(cs.charAt(i)) == false && cs.charAt(i) != ' ') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the CharSequence contains only whitespace.
+ *
+ * {@code null} will return {@code false}.
+ * An empty CharSequence (length()=0) will return {@code true}.
+ *
+ *
+ * StringUtils.isWhitespace(null) = false
+ * StringUtils.isWhitespace("") = true
+ * StringUtils.isWhitespace(" ") = true
+ * StringUtils.isWhitespace("abc") = false
+ * StringUtils.isWhitespace("ab2c") = false
+ * StringUtils.isWhitespace("ab-c") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if only contains whitespace, and is non-null
+ * @since 2.0
+ * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence)
+ */
+ public static boolean isWhitespace(final CharSequence cs) {
+ if (cs == null) {
+ return false;
+ }
+ final int sz = cs.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isWhitespace(cs.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the CharSequence contains only lowercase characters.
+ *
+ * {@code null} will return {@code false}.
+ * An empty CharSequence (length()=0) will return {@code false}.
+ *
+ *
+ * StringUtils.isAllLowerCase(null) = false
+ * StringUtils.isAllLowerCase("") = false
+ * StringUtils.isAllLowerCase(" ") = false
+ * StringUtils.isAllLowerCase("abc") = true
+ * StringUtils.isAllLowerCase("abC") = false
+ * StringUtils.isAllLowerCase("ab c") = false
+ * StringUtils.isAllLowerCase("ab1c") = false
+ * StringUtils.isAllLowerCase("ab/c") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if only contains lowercase characters, and is non-null
+ * @since 2.5
+ * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence)
+ */
+ public static boolean isAllLowerCase(final CharSequence cs) {
+ if (cs == null || isEmpty(cs)) {
+ return false;
+ }
+ final int sz = cs.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isLowerCase(cs.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the CharSequence contains only uppercase characters.
+ *
+ * {@code null} will return {@code false}.
+ * An empty String (length()=0) will return {@code false}.
+ *
+ *
+ * StringUtils.isAllUpperCase(null) = false
+ * StringUtils.isAllUpperCase("") = false
+ * StringUtils.isAllUpperCase(" ") = false
+ * StringUtils.isAllUpperCase("ABC") = true
+ * StringUtils.isAllUpperCase("aBC") = false
+ * StringUtils.isAllUpperCase("A C") = false
+ * StringUtils.isAllUpperCase("A1C") = false
+ * StringUtils.isAllUpperCase("A/C") = false
+ *
+ *
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if only contains uppercase characters, and is non-null
+ * @since 2.5
+ * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence)
+ */
+ public static boolean isAllUpperCase(final CharSequence cs) {
+ if (cs == null || isEmpty(cs)) {
+ return false;
+ }
+ final int sz = cs.length();
+ for (int i = 0; i < sz; i++) {
+ if (Character.isUpperCase(cs.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Defaults
+ //-----------------------------------------------------------------------
+ /**
+ * Returns either the passed in String,
+ * or if the String is {@code null}, an empty String ("").
+ *
+ *
+ * StringUtils.defaultString(null) = ""
+ * StringUtils.defaultString("") = ""
+ * StringUtils.defaultString("bat") = "bat"
+ *
+ *
+ * @see ObjectUtils#toString(Object)
+ * @see String#valueOf(Object)
+ * @param str the String to check, may be null
+ * @return the passed in String, or the empty String if it
+ * was {@code null}
+ */
+ public static String defaultString(final String str) {
+ return str == null ? EMPTY : str;
+ }
+
+ /**
+ * Returns either the passed in String, or if the String is
+ * {@code null}, the value of {@code defaultStr}.
+ *
+ *
+ * StringUtils.defaultString(null, "NULL") = "NULL"
+ * StringUtils.defaultString("", "NULL") = ""
+ * StringUtils.defaultString("bat", "NULL") = "bat"
+ *
+ *
+ * @see ObjectUtils#toString(Object,String)
+ * @see String#valueOf(Object)
+ * @param str the String to check, may be null
+ * @param defaultStr the default String to return
+ * if the input is {@code null}, may be null
+ * @return the passed in String, or the default if it was {@code null}
+ */
+ public static String defaultString(final String str, final String defaultStr) {
+ return str == null ? defaultStr : str;
+ }
+
+ /**
+ * Returns either the passed in CharSequence, or if the CharSequence is
+ * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}.
+ *
+ *
+ * StringUtils.defaultIfBlank(null, "NULL") = "NULL"
+ * StringUtils.defaultIfBlank("", "NULL") = "NULL"
+ * StringUtils.defaultIfBlank(" ", "NULL") = "NULL"
+ * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
+ * StringUtils.defaultIfBlank("", null) = null
+ *
+ * @param the specific kind of CharSequence
+ * @param str the CharSequence to check, may be null
+ * @param defaultStr the default CharSequence to return
+ * if the input is whitespace, empty ("") or {@code null}, may be null
+ * @return the passed in CharSequence, or the default
+ * @see StringUtils#defaultString(String, String)
+ */
+ public static T defaultIfBlank(final T str, final T defaultStr) {
+ return isBlank(str) ? defaultStr : str;
+ }
+
+ /**
+ * Returns either the passed in CharSequence, or if the CharSequence is
+ * empty or {@code null}, the value of {@code defaultStr}.
+ *
+ *
+ * StringUtils.defaultIfEmpty(null, "NULL") = "NULL"
+ * StringUtils.defaultIfEmpty("", "NULL") = "NULL"
+ * StringUtils.defaultIfEmpty(" ", "NULL") = " "
+ * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
+ * StringUtils.defaultIfEmpty("", null) = null
+ *
+ * @param the specific kind of CharSequence
+ * @param str the CharSequence to check, may be null
+ * @param defaultStr the default CharSequence to return
+ * if the input is empty ("") or {@code null}, may be null
+ * @return the passed in CharSequence, or the default
+ * @see StringUtils#defaultString(String, String)
+ */
+ public static T defaultIfEmpty(final T str, final T defaultStr) {
+ return isEmpty(str) ? defaultStr : str;
+ }
+
+ // Rotating (circular shift)
+ //-----------------------------------------------------------------------
+ /**
+ * Rotate (circular shift) a String of {@code shift} characters.
+ *
+ * If {@code shift > 0}, right circular shift (ex : ABCDEF => FABCDE)
+ * If {@code shift < 0}, left circular shift (ex : ABCDEF => BCDEFA)
+ *
+ *
+ *
+ * StringUtils.rotate(null, *) = null
+ * StringUtils.rotate("", *) = ""
+ * StringUtils.rotate("abcdefg", 0) = "abcdefg"
+ * StringUtils.rotate("abcdefg", 2) = "fgabcde"
+ * StringUtils.rotate("abcdefg", -2) = "cdefgab"
+ * StringUtils.rotate("abcdefg", 7) = "abcdefg"
+ * StringUtils.rotate("abcdefg", -7) = "abcdefg"
+ * StringUtils.rotate("abcdefg", 9) = "fgabcde"
+ * StringUtils.rotate("abcdefg", -9) = "cdefgab"
+ *
+ *
+ * @param str the String to rotate, may be null
+ * @param shift number of time to shift (positive : right shift, negative : left shift)
+ * @return the rotated String,
+ * or the original String if {@code shift == 0},
+ * or {@code null} if null String input
+ * @since 3.5
+ */
+ public static String rotate(String str, int shift) {
+ if (str == null) {
+ return null;
+ }
+
+ final int strLen = str.length();
+ if (shift == 0 || strLen == 0 || shift % strLen == 0) {
+ return str;
+ }
+
+ final StringBuilder builder = new StringBuilder(strLen);
+ final int offset = - (shift % strLen);
+ builder.append(substring(str, offset));
+ builder.append(substring(str, 0, offset));
+ return builder.toString();
+ }
+
+ // Reversing
+ //-----------------------------------------------------------------------
+ /**
+ * Reverses a String as per {@link StringBuilder#reverse()}.
+ *
+ * A {@code null} String returns {@code null}.
+ *
+ *
+ * StringUtils.reverse(null) = null
+ * StringUtils.reverse("") = ""
+ * StringUtils.reverse("bat") = "tab"
+ *
+ *
+ * @param str the String to reverse, may be null
+ * @return the reversed String, {@code null} if null String input
+ */
+ public static String reverse(final String str) {
+ if (str == null) {
+ return null;
+ }
+ return new StringBuilder(str).reverse().toString();
+ }
+
+ /**
+ * Reverses a String that is delimited by a specific character.
+ *
+ * The Strings between the delimiters are not reversed.
+ * Thus java.lang.String becomes String.lang.java (if the delimiter
+ * is {@code '.'}).
+ *
+ *
+ * StringUtils.reverseDelimited(null, *) = null
+ * StringUtils.reverseDelimited("", *) = ""
+ * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
+ * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
+ *
+ *
+ * @param str the String to reverse, may be null
+ * @param separatorChar the separator character to use
+ * @return the reversed String, {@code null} if null String input
+ * @since 2.0
+ */
+ public static String reverseDelimited(final String str, final char separatorChar) {
+ if (str == null) {
+ return null;
+ }
+ // could implement manually, but simple way is to reuse other,
+ // probably slower, methods.
+ final String[] strs = split(str, separatorChar);
+ ArrayUtils.reverse(strs);
+ return join(strs, separatorChar);
+ }
+
+ // Abbreviating
+ //-----------------------------------------------------------------------
+ /**
+ * Abbreviates a String using ellipses. This will turn
+ * "Now is the time for all good men" into "Now is the time for..."
+ *
+ * Specifically:
+ *
+ * If the number of characters in {@code str} is less than or equal to
+ * {@code maxWidth}, return {@code str}.
+ * Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.
+ * If {@code maxWidth} is less than {@code 4}, throw an
+ * {@code IllegalArgumentException}.
+ * In no case will it return a String of length greater than
+ * {@code maxWidth}.
+ *
+ *
+ *
+ * StringUtils.abbreviate(null, *) = null
+ * StringUtils.abbreviate("", 4) = ""
+ * StringUtils.abbreviate("abcdefg", 6) = "abc..."
+ * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
+ * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
+ * StringUtils.abbreviate("abcdefg", 4) = "a..."
+ * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
+ *
+ *
+ * @param str the String to check, may be null
+ * @param maxWidth maximum length of result String, must be at least 4
+ * @return abbreviated String, {@code null} if null String input
+ * @throws IllegalArgumentException if the width is too small
+ * @since 2.0
+ */
+ public static String abbreviate(final String str, final int maxWidth) {
+ return abbreviate(str, 0, maxWidth);
+ }
+
+ /**
+ * Abbreviates a String using ellipses. This will turn
+ * "Now is the time for all good men" into "...is the time for..."
+ *
+ * Works like {@code abbreviate(String, int)}, but allows you to specify
+ * a "left edge" offset. Note that this left edge is not necessarily going to
+ * be the leftmost character in the result, or the first character following the
+ * ellipses, but it will appear somewhere in the result.
+ *
+ *
In no case will it return a String of length greater than
+ * {@code maxWidth}.
+ *
+ *
+ * StringUtils.abbreviate(null, *, *) = null
+ * StringUtils.abbreviate("", 0, 4) = ""
+ * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
+ * StringUtils.abbreviate("abcdefghijklmno", 0, 10) = "abcdefg..."
+ * StringUtils.abbreviate("abcdefghijklmno", 1, 10) = "abcdefg..."
+ * StringUtils.abbreviate("abcdefghijklmno", 4, 10) = "abcdefg..."
+ * StringUtils.abbreviate("abcdefghijklmno", 5, 10) = "...fghi..."
+ * StringUtils.abbreviate("abcdefghijklmno", 6, 10) = "...ghij..."
+ * StringUtils.abbreviate("abcdefghijklmno", 8, 10) = "...ijklmno"
+ * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
+ * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
+ * StringUtils.abbreviate("abcdefghij", 0, 3) = IllegalArgumentException
+ * StringUtils.abbreviate("abcdefghij", 5, 6) = IllegalArgumentException
+ *
+ *
+ * @param str the String to check, may be null
+ * @param offset left edge of source String
+ * @param maxWidth maximum length of result String, must be at least 4
+ * @return abbreviated String, {@code null} if null String input
+ * @throws IllegalArgumentException if the width is too small
+ * @since 2.0
+ */
+ public static String abbreviate(final String str, int offset, final int maxWidth) {
+ if (str == null) {
+ return null;
+ }
+ if (maxWidth < 4) {
+ throw new IllegalArgumentException("Minimum abbreviation width is 4");
+ }
+ if (str.length() <= maxWidth) {
+ return str;
+ }
+ if (offset > str.length()) {
+ offset = str.length();
+ }
+ if (str.length() - offset < maxWidth - 3) {
+ offset = str.length() - (maxWidth - 3);
+ }
+ final String abrevMarker = "...";
+ if (offset <= 4) {
+ return str.substring(0, maxWidth - 3) + abrevMarker;
+ }
+ if (maxWidth < 7) {
+ throw new IllegalArgumentException("Minimum abbreviation width with offset is 7");
+ }
+ if (offset + maxWidth - 3 < str.length()) {
+ return abrevMarker + abbreviate(str.substring(offset), maxWidth - 3);
+ }
+ return abrevMarker + str.substring(str.length() - (maxWidth - 3));
+ }
+
+ /**
+ * Abbreviates a String to the length passed, replacing the middle characters with the supplied
+ * replacement String.
+ *
+ * This abbreviation only occurs if the following criteria is met:
+ *
+ * Neither the String for abbreviation nor the replacement String are null or empty
+ * The length to truncate to is less than the length of the supplied String
+ * The length to truncate to is greater than 0
+ * The abbreviated String will have enough room for the length supplied replacement String
+ * and the first and last characters of the supplied String for abbreviation
+ *
+ * Otherwise, the returned String will be the same as the supplied String for abbreviation.
+ *
+ *
+ *
+ * StringUtils.abbreviateMiddle(null, null, 0) = null
+ * StringUtils.abbreviateMiddle("abc", null, 0) = "abc"
+ * StringUtils.abbreviateMiddle("abc", ".", 0) = "abc"
+ * StringUtils.abbreviateMiddle("abc", ".", 3) = "abc"
+ * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f"
+ *
+ *
+ * @param str the String to abbreviate, may be null
+ * @param middle the String to replace the middle characters with, may be null
+ * @param length the length to abbreviate {@code str} to.
+ * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
+ * @since 2.5
+ */
+ public static String abbreviateMiddle(final String str, final String middle, final int length) {
+ if (isEmpty(str) || isEmpty(middle)) {
+ return str;
+ }
+
+ if (length >= str.length() || length < middle.length()+2) {
+ return str;
+ }
+
+ final int targetSting = length-middle.length();
+ final int startOffset = targetSting/2+targetSting%2;
+ final int endOffset = str.length()-targetSting/2;
+
+ final StringBuilder builder = new StringBuilder(length);
+ builder.append(str.substring(0,startOffset));
+ builder.append(middle);
+ builder.append(str.substring(endOffset));
+
+ return builder.toString();
+ }
+
+ // Difference
+ //-----------------------------------------------------------------------
+ /**
+ * Compares two Strings, and returns the portion where they differ.
+ * More precisely, return the remainder of the second String,
+ * starting from where it's different from the first. This means that
+ * the difference between "abc" and "ab" is the empty String and not "c".
+ *
+ * For example,
+ * {@code difference("i am a machine", "i am a robot") -> "robot"}.
+ *
+ *
+ * StringUtils.difference(null, null) = null
+ * StringUtils.difference("", "") = ""
+ * StringUtils.difference("", "abc") = "abc"
+ * StringUtils.difference("abc", "") = ""
+ * StringUtils.difference("abc", "abc") = ""
+ * StringUtils.difference("abc", "ab") = ""
+ * StringUtils.difference("ab", "abxyz") = "xyz"
+ * StringUtils.difference("abcde", "abxyz") = "xyz"
+ * StringUtils.difference("abcde", "xyz") = "xyz"
+ *
+ *
+ * @param str1 the first String, may be null
+ * @param str2 the second String, may be null
+ * @return the portion of str2 where it differs from str1; returns the
+ * empty String if they are equal
+ * @see #indexOfDifference(CharSequence,CharSequence)
+ * @since 2.0
+ */
+ public static String difference(final String str1, final String str2) {
+ if (str1 == null) {
+ return str2;
+ }
+ if (str2 == null) {
+ return str1;
+ }
+ final int at = indexOfDifference(str1, str2);
+ if (at == INDEX_NOT_FOUND) {
+ return EMPTY;
+ }
+ return str2.substring(at);
+ }
+
+ /**
+ * Compares two CharSequences, and returns the index at which the
+ * CharSequences begin to differ.
+ *
+ * For example,
+ * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}
+ *
+ *
+ * StringUtils.indexOfDifference(null, null) = -1
+ * StringUtils.indexOfDifference("", "") = -1
+ * StringUtils.indexOfDifference("", "abc") = 0
+ * StringUtils.indexOfDifference("abc", "") = 0
+ * StringUtils.indexOfDifference("abc", "abc") = -1
+ * StringUtils.indexOfDifference("ab", "abxyz") = 2
+ * StringUtils.indexOfDifference("abcde", "abxyz") = 2
+ * StringUtils.indexOfDifference("abcde", "xyz") = 0
+ *
+ *
+ * @param cs1 the first CharSequence, may be null
+ * @param cs2 the second CharSequence, may be null
+ * @return the index where cs1 and cs2 begin to differ; -1 if they are equal
+ * @since 2.0
+ * @since 3.0 Changed signature from indexOfDifference(String, String) to
+ * indexOfDifference(CharSequence, CharSequence)
+ */
+ public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) {
+ if (cs1 == cs2) {
+ return INDEX_NOT_FOUND;
+ }
+ if (cs1 == null || cs2 == null) {
+ return 0;
+ }
+ int i;
+ for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {
+ if (cs1.charAt(i) != cs2.charAt(i)) {
+ break;
+ }
+ }
+ if (i < cs2.length() || i < cs1.length()) {
+ return i;
+ }
+ return INDEX_NOT_FOUND;
+ }
+
+ /**
+ * Compares all CharSequences in an array and returns the index at which the
+ * CharSequences begin to differ.
+ *
+ * For example,
+ * indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7
+ *
+ *
+ * StringUtils.indexOfDifference(null) = -1
+ * StringUtils.indexOfDifference(new String[] {}) = -1
+ * StringUtils.indexOfDifference(new String[] {"abc"}) = -1
+ * StringUtils.indexOfDifference(new String[] {null, null}) = -1
+ * StringUtils.indexOfDifference(new String[] {"", ""}) = -1
+ * StringUtils.indexOfDifference(new String[] {"", null}) = 0
+ * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
+ * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
+ * StringUtils.indexOfDifference(new String[] {"", "abc"}) = 0
+ * StringUtils.indexOfDifference(new String[] {"abc", ""}) = 0
+ * StringUtils.indexOfDifference(new String[] {"abc", "abc"}) = -1
+ * StringUtils.indexOfDifference(new String[] {"abc", "a"}) = 1
+ * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"}) = 2
+ * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"}) = 2
+ * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"}) = 0
+ * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"}) = 0
+ * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
+ *
+ *
+ * @param css array of CharSequences, entries may be null
+ * @return the index where the strings begin to differ; -1 if they are all equal
+ * @since 2.4
+ * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...)
+ */
+ public static int indexOfDifference(final CharSequence... css) {
+ if (css == null || css.length <= 1) {
+ return INDEX_NOT_FOUND;
+ }
+ boolean anyStringNull = false;
+ boolean allStringsNull = true;
+ final int arrayLen = css.length;
+ int shortestStrLen = Integer.MAX_VALUE;
+ int longestStrLen = 0;
+
+ // find the min and max string lengths; this avoids checking to make
+ // sure we are not exceeding the length of the string each time through
+ // the bottom loop.
+ for (int i = 0; i < arrayLen; i++) {
+ if (css[i] == null) {
+ anyStringNull = true;
+ shortestStrLen = 0;
+ } else {
+ allStringsNull = false;
+ shortestStrLen = Math.min(css[i].length(), shortestStrLen);
+ longestStrLen = Math.max(css[i].length(), longestStrLen);
+ }
+ }
+
+ // handle lists containing all nulls or all empty strings
+ if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
+ return INDEX_NOT_FOUND;
+ }
+
+ // handle lists containing some nulls or some empty strings
+ if (shortestStrLen == 0) {
+ return 0;
+ }
+
+ // find the position with the first difference across all strings
+ int firstDiff = -1;
+ for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
+ final char comparisonChar = css[0].charAt(stringPos);
+ for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
+ if (css[arrayPos].charAt(stringPos) != comparisonChar) {
+ firstDiff = stringPos;
+ break;
+ }
+ }
+ if (firstDiff != -1) {
+ break;
+ }
+ }
+
+ if (firstDiff == -1 && shortestStrLen != longestStrLen) {
+ // we compared all of the characters up to the length of the
+ // shortest string and didn't find a match, but the string lengths
+ // vary, so return the length of the shortest string.
+ return shortestStrLen;
+ }
+ return firstDiff;
+ }
+
+ /**
+ * Compares all Strings in an array and returns the initial sequence of
+ * characters that is common to all of them.
+ *
+ * For example,
+ * getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -> "i am a "
+ *
+ *
+ * StringUtils.getCommonPrefix(null) = ""
+ * StringUtils.getCommonPrefix(new String[] {}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"abc"}) = "abc"
+ * StringUtils.getCommonPrefix(new String[] {null, null}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"", ""}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"", null}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
+ * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"", "abc"}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"abc", ""}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"abc", "abc"}) = "abc"
+ * StringUtils.getCommonPrefix(new String[] {"abc", "a"}) = "a"
+ * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"}) = "ab"
+ * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"}) = "ab"
+ * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"}) = ""
+ * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
+ *
+ *
+ * @param strs array of String objects, entries may be null
+ * @return the initial sequence of characters that are common to all Strings
+ * in the array; empty String if the array is null, the elements are all null
+ * or if there is no common prefix.
+ * @since 2.4
+ */
+ public static String getCommonPrefix(final String... strs) {
+ if (strs == null || strs.length == 0) {
+ return EMPTY;
+ }
+ final int smallestIndexOfDiff = indexOfDifference(strs);
+ if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
+ // all strings were identical
+ if (strs[0] == null) {
+ return EMPTY;
+ }
+ return strs[0];
+ } else if (smallestIndexOfDiff == 0) {
+ // there were no common initial characters
+ return EMPTY;
+ } else {
+ // we found a common initial character sequence
+ return strs[0].substring(0, smallestIndexOfDiff);
+ }
+ }
+
+ // Misc
+ //-----------------------------------------------------------------------
+ /**
+ * Find the Levenshtein distance between two Strings.
+ *
+ * This is the number of changes needed to change one String into
+ * another, where each change is a single character modification (deletion,
+ * insertion or substitution).
+ *
+ * The previous implementation of the Levenshtein distance algorithm
+ * was from
+ * https://web.archive.org/web/20120604192456/http://www.merriampark.com/ld.htm
+ *
+ * Chas Emerick has written an implementation in Java, which avoids an OutOfMemoryError
+ * which can occur when my Java implementation is used with very large strings.
+ * This implementation of the Levenshtein distance algorithm
+ * is from
+ * https://web.archive.org/web/20120526085419/http://www.merriampark.com/ldjava.htm
+ *
+ *
+ * StringUtils.getLevenshteinDistance(null, *) = IllegalArgumentException
+ * StringUtils.getLevenshteinDistance(*, null) = IllegalArgumentException
+ * StringUtils.getLevenshteinDistance("","") = 0
+ * StringUtils.getLevenshteinDistance("","a") = 1
+ * StringUtils.getLevenshteinDistance("aaapppp", "") = 7
+ * StringUtils.getLevenshteinDistance("frog", "fog") = 1
+ * StringUtils.getLevenshteinDistance("fly", "ant") = 3
+ * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
+ * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
+ * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
+ * StringUtils.getLevenshteinDistance("hello", "hallo") = 1
+ *
+ *
+ * @param s the first String, must not be null
+ * @param t the second String, must not be null
+ * @return result distance
+ * @throws IllegalArgumentException if either String input {@code null}
+ * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to
+ * getLevenshteinDistance(CharSequence, CharSequence)
+ */
+ public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
+ if (s == null || t == null) {
+ throw new IllegalArgumentException("Strings must not be null");
+ }
+
+ /*
+ The difference between this impl. and the previous is that, rather
+ than creating and retaining a matrix of size s.length() + 1 by t.length() + 1,
+ we maintain two single-dimensional arrays of length s.length() + 1. The first, d,
+ is the 'current working' distance array that maintains the newest distance cost
+ counts as we iterate through the characters of String s. Each time we increment
+ the index of String t we are comparing, d is copied to p, the second int[]. Doing so
+ allows us to retain the previous cost counts as required by the algorithm (taking
+ the minimum of the cost count to the left, up one, and diagonally up and to the left
+ of the current cost count being calculated). (Note that the arrays aren't really
+ copied anymore, just switched...this is clearly much better than cloning an array
+ or doing a System.arraycopy() each time through the outer loop.)
+
+ Effectively, the difference between the two implementations is this one does not
+ cause an out of memory condition when calculating the LD over two very large strings.
+ */
+
+ int n = s.length(); // length of s
+ int m = t.length(); // length of t
+
+ if (n == 0) {
+ return m;
+ } else if (m == 0) {
+ return n;
+ }
+
+ if (n > m) {
+ // swap the input strings to consume less memory
+ final CharSequence tmp = s;
+ s = t;
+ t = tmp;
+ n = m;
+ m = t.length();
+ }
+
+ int p[] = new int[n + 1]; //'previous' cost array, horizontally
+ int d[] = new int[n + 1]; // cost array, horizontally
+ int _d[]; //placeholder to assist in swapping p and d
+
+ // indexes into strings s and t
+ int i; // iterates through s
+ int j; // iterates through t
+
+ char t_j; // jth character of t
+
+ int cost; // cost
+
+ for (i = 0; i <= n; i++) {
+ p[i] = i;
+ }
+
+ for (j = 1; j <= m; j++) {
+ t_j = t.charAt(j - 1);
+ d[0] = j;
+
+ for (i = 1; i <= n; i++) {
+ cost = s.charAt(i - 1) == t_j ? 0 : 1;
+ // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
+ d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost);
+ }
+
+ // copy current distance counts to 'previous row' distance counts
+ _d = p;
+ p = d;
+ d = _d;
+ }
+
+ // our last action in the above loop was to switch d and p, so p now
+ // actually has the most recent cost counts
+ return p[n];
+ }
+
+ /**
+ * Find the Levenshtein distance between two Strings if it's less than or equal to a given
+ * threshold.
+ *
+ * This is the number of changes needed to change one String into
+ * another, where each change is a single character modification (deletion,
+ * insertion or substitution).
+ *
+ * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield
+ * and Chas Emerick's implementation of the Levenshtein distance algorithm from
+ * http://www.merriampark.com/ld.htm
+ *
+ *
+ * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException
+ * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException
+ * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException
+ * StringUtils.getLevenshteinDistance("","", 0) = 0
+ * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7
+ * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7
+ * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1
+ * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7
+ * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1
+ * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7
+ * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1
+ *
+ *
+ * @param s the first String, must not be null
+ * @param t the second String, must not be null
+ * @param threshold the target threshold, must not be negative
+ * @return result distance, or {@code -1} if the distance would be greater than the threshold
+ * @throws IllegalArgumentException if either String input {@code null} or negative threshold
+ */
+ public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) {
+ if (s == null || t == null) {
+ throw new IllegalArgumentException("Strings must not be null");
+ }
+ if (threshold < 0) {
+ throw new IllegalArgumentException("Threshold must not be negative");
+ }
+
+ /*
+ This implementation only computes the distance if it's less than or equal to the
+ threshold value, returning -1 if it's greater. The advantage is performance: unbounded
+ distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only
+ computing a diagonal stripe of width 2k + 1 of the cost table.
+ It is also possible to use this to compute the unbounded Levenshtein distance by starting
+ the threshold at 1 and doubling each time until the distance is found; this is O(dm), where
+ d is the distance.
+
+ One subtlety comes from needing to ignore entries on the border of our stripe
+ eg.
+ p[] = |#|#|#|*
+ d[] = *|#|#|#|
+ We must ignore the entry to the left of the leftmost member
+ We must ignore the entry above the rightmost member
+
+ Another subtlety comes from our stripe running off the matrix if the strings aren't
+ of the same size. Since string s is always swapped to be the shorter of the two,
+ the stripe will always run off to the upper right instead of the lower left of the matrix.
+
+ As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1.
+ In this case we're going to walk a stripe of length 3. The matrix would look like so:
+
+ 1 2 3 4 5
+ 1 |#|#| | | |
+ 2 |#|#|#| | |
+ 3 | |#|#|#| |
+ 4 | | |#|#|#|
+ 5 | | | |#|#|
+ 6 | | | | |#|
+ 7 | | | | | |
+
+ Note how the stripe leads off the table as there is no possible way to turn a string of length 5
+ into one of length 7 in edit distance of 1.
+
+ Additionally, this implementation decreases memory usage by using two
+ single-dimensional arrays and swapping them back and forth instead of allocating
+ an entire n by m matrix. This requires a few minor changes, such as immediately returning
+ when it's detected that the stripe has run off the matrix and initially filling the arrays with
+ large values so that entries we don't compute are ignored.
+
+ See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion.
+ */
+
+ int n = s.length(); // length of s
+ int m = t.length(); // length of t
+
+ // if one string is empty, the edit distance is necessarily the length of the other
+ if (n == 0) {
+ return m <= threshold ? m : -1;
+ } else if (m == 0) {
+ return n <= threshold ? n : -1;
+ }
+ // no need to calculate the distance if the length difference is greater than the threshold
+ else if (Math.abs(n - m) > threshold) {
+ return -1;
+ }
+
+ if (n > m) {
+ // swap the two strings to consume less memory
+ final CharSequence tmp = s;
+ s = t;
+ t = tmp;
+ n = m;
+ m = t.length();
+ }
+
+ int p[] = new int[n + 1]; // 'previous' cost array, horizontally
+ int d[] = new int[n + 1]; // cost array, horizontally
+ int _d[]; // placeholder to assist in swapping p and d
+
+ // fill in starting table values
+ final int boundary = Math.min(n, threshold) + 1;
+ for (int i = 0; i < boundary; i++) {
+ p[i] = i;
+ }
+ // these fills ensure that the value above the rightmost entry of our
+ // stripe will be ignored in following loop iterations
+ Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE);
+ Arrays.fill(d, Integer.MAX_VALUE);
+
+ // iterates through t
+ for (int j = 1; j <= m; j++) {
+ final char t_j = t.charAt(j - 1); // jth character of t
+ d[0] = j;
+
+ // compute stripe indices, constrain to array size
+ final int min = Math.max(1, j - threshold);
+ final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold);
+
+ // the stripe may lead off of the table if s and t are of different sizes
+ if (min > max) {
+ return -1;
+ }
+
+ // ignore entry left of leftmost
+ if (min > 1) {
+ d[min - 1] = Integer.MAX_VALUE;
+ }
+
+ // iterates through [min, max] in s
+ for (int i = min; i <= max; i++) {
+ if (s.charAt(i - 1) == t_j) {
+ // diagonally left and up
+ d[i] = p[i - 1];
+ } else {
+ // 1 + minimum of cell to the left, to the top, diagonally left and up
+ d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);
+ }
+ }
+
+ // copy current distance counts to 'previous row' distance counts
+ _d = p;
+ p = d;
+ d = _d;
+ }
+
+ // if p[n] is greater than the threshold, there's no guarantee on it being the correct
+ // distance
+ if (p[n] <= threshold) {
+ return p[n];
+ }
+ return -1;
+ }
+
+ /**
+ * Find the Jaro Winkler Distance which indicates the similarity score between two Strings.
+ *
+ * The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters.
+ * Winkler increased this measure for matching initial characters.
+ *
+ * This implementation is based on the Jaro Winkler similarity algorithm
+ * from http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance .
+ *
+ *
+ * StringUtils.getJaroWinklerDistance(null, null) = IllegalArgumentException
+ * StringUtils.getJaroWinklerDistance("","") = 0.0
+ * StringUtils.getJaroWinklerDistance("","a") = 0.0
+ * StringUtils.getJaroWinklerDistance("aaapppp", "") = 0.0
+ * StringUtils.getJaroWinklerDistance("frog", "fog") = 0.93
+ * StringUtils.getJaroWinklerDistance("fly", "ant") = 0.0
+ * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44
+ * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44
+ * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0
+ * StringUtils.getJaroWinklerDistance("hello", "hallo") = 0.88
+ * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93
+ * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc.") = 0.95
+ * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92
+ * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88
+ *
+ *
+ * @param first the first String, must not be null
+ * @param second the second String, must not be null
+ * @return result distance
+ * @throws IllegalArgumentException if either String input {@code null}
+ * @since 3.3
+ */
+ public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) {
+ final double DEFAULT_SCALING_FACTOR = 0.1;
+
+ if (first == null || second == null) {
+ throw new IllegalArgumentException("Strings must not be null");
+ }
+
+ int[] mtp = matches(first, second);
+ double m = mtp[0];
+ if (m == 0) {
+ return 0D;
+ }
+ double j = ((m / first.length() + m / second.length() + (m - mtp[1]) / m)) / 3;
+ double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j);
+ return Math.round(jw * 100.0D) / 100.0D;
+ }
+
+ private static int[] matches(final CharSequence first, final CharSequence second) {
+ CharSequence max, min;
+ if (first.length() > second.length()) {
+ max = first;
+ min = second;
+ } else {
+ max = second;
+ min = first;
+ }
+ int range = Math.max(max.length() / 2 - 1, 0);
+ int[] matchIndexes = new int[min.length()];
+ Arrays.fill(matchIndexes, -1);
+ boolean[] matchFlags = new boolean[max.length()];
+ int matches = 0;
+ for (int mi = 0; mi < min.length(); mi++) {
+ char c1 = min.charAt(mi);
+ for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) {
+ if (!matchFlags[xi] && c1 == max.charAt(xi)) {
+ matchIndexes[mi] = xi;
+ matchFlags[xi] = true;
+ matches++;
+ break;
+ }
+ }
+ }
+ char[] ms1 = new char[matches];
+ char[] ms2 = new char[matches];
+ for (int i = 0, si = 0; i < min.length(); i++) {
+ if (matchIndexes[i] != -1) {
+ ms1[si] = min.charAt(i);
+ si++;
+ }
+ }
+ for (int i = 0, si = 0; i < max.length(); i++) {
+ if (matchFlags[i]) {
+ ms2[si] = max.charAt(i);
+ si++;
+ }
+ }
+ int transpositions = 0;
+ for (int mi = 0; mi < ms1.length; mi++) {
+ if (ms1[mi] != ms2[mi]) {
+ transpositions++;
+ }
+ }
+ int prefix = 0;
+ for (int mi = 0; mi < min.length(); mi++) {
+ if (first.charAt(mi) == second.charAt(mi)) {
+ prefix++;
+ } else {
+ break;
+ }
+ }
+ return new int[] { matches, transpositions / 2, prefix, max.length() };
+ }
+
+ /**
+ * Find the Fuzzy Distance which indicates the similarity score between two Strings.
+ *
+ * This string matching algorithm is similar to the algorithms of editors such as Sublime Text,
+ * TextMate, Atom and others. One point is given for every matched character. Subsequent
+ * matches yield two bonus points. A higher score indicates a higher similarity.
+ *
+ *
+ * StringUtils.getFuzzyDistance(null, null, null) = IllegalArgumentException
+ * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH) = 0
+ * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH) = 0
+ * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH) = 1
+ * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH) = 1
+ * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH) = 2
+ * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH) = 4
+ * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3
+ *
+ *
+ * @param term a full term that should be matched against, must not be null
+ * @param query the query that will be matched against a term, must not be null
+ * @param locale This string matching logic is case insensitive. A locale is necessary to normalize
+ * both Strings to lower case.
+ * @return result score
+ * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null}
+ * @since 3.4
+ */
+ public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) {
+ if (term == null || query == null) {
+ throw new IllegalArgumentException("Strings must not be null");
+ } else if (locale == null) {
+ throw new IllegalArgumentException("Locale must not be null");
+ }
+
+ // fuzzy logic is case insensitive. We normalize the Strings to lower
+ // case right from the start. Turning characters to lower case
+ // via Character.toLowerCase(char) is unfortunately insufficient
+ // as it does not accept a locale.
+ final String termLowerCase = term.toString().toLowerCase(locale);
+ final String queryLowerCase = query.toString().toLowerCase(locale);
+
+ // the resulting score
+ int score = 0;
+
+ // the position in the term which will be scanned next for potential
+ // query character matches
+ int termIndex = 0;
+
+ // index of the previously matched character in the term
+ int previousMatchingCharacterIndex = Integer.MIN_VALUE;
+
+ for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) {
+ final char queryChar = queryLowerCase.charAt(queryIndex);
+
+ boolean termCharacterMatchFound = false;
+ for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) {
+ final char termChar = termLowerCase.charAt(termIndex);
+
+ if (queryChar == termChar) {
+ // simple character matches result in one point
+ score++;
+
+ // subsequent character matches further improve
+ // the score.
+ if (previousMatchingCharacterIndex + 1 == termIndex) {
+ score += 2;
+ }
+
+ previousMatchingCharacterIndex = termIndex;
+
+ // we can leave the nested loop. Every character in the
+ // query can match at most one character in the term.
+ termCharacterMatchFound = true;
+ }
+ }
+ }
+
+ return score;
+ }
+
+ // startsWith
+ //-----------------------------------------------------------------------
+
+ /**
+ * Check if a CharSequence starts with a specified prefix.
+ *
+ * {@code null}s are handled without exceptions. Two {@code null}
+ * references are considered to be equal. The comparison is case sensitive.
+ *
+ *
+ * StringUtils.startsWith(null, null) = true
+ * StringUtils.startsWith(null, "abc") = false
+ * StringUtils.startsWith("abcdef", null) = false
+ * StringUtils.startsWith("abcdef", "abc") = true
+ * StringUtils.startsWith("ABCDEF", "abc") = false
+ *
+ *
+ * @see java.lang.String#startsWith(String)
+ * @param str the CharSequence to check, may be null
+ * @param prefix the prefix to find, may be null
+ * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or
+ * both {@code null}
+ * @since 2.4
+ * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
+ */
+ public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
+ return startsWith(str, prefix, false);
+ }
+
+ /**
+ * Case insensitive check if a CharSequence starts with a specified prefix.
+ *
+ * {@code null}s are handled without exceptions. Two {@code null}
+ * references are considered to be equal. The comparison is case insensitive.
+ *
+ *
+ * StringUtils.startsWithIgnoreCase(null, null) = true
+ * StringUtils.startsWithIgnoreCase(null, "abc") = false
+ * StringUtils.startsWithIgnoreCase("abcdef", null) = false
+ * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
+ * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
+ *
+ *
+ * @see java.lang.String#startsWith(String)
+ * @param str the CharSequence to check, may be null
+ * @param prefix the prefix to find, may be null
+ * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or
+ * both {@code null}
+ * @since 2.4
+ * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
+ */
+ public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
+ return startsWith(str, prefix, true);
+ }
+
+ /**
+ * Check if a CharSequence starts with a specified prefix (optionally case insensitive).
+ *
+ * @see java.lang.String#startsWith(String)
+ * @param str the CharSequence to check, may be null
+ * @param prefix the prefix to find, may be null
+ * @param ignoreCase indicates whether the compare should ignore case
+ * (case insensitive) or not.
+ * @return {@code true} if the CharSequence starts with the prefix or
+ * both {@code null}
+ */
+ private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
+ if (str == null || prefix == null) {
+ return str == null && prefix == null;
+ }
+ if (prefix.length() > str.length()) {
+ return false;
+ }
+ return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0, prefix.length());
+ }
+
+ /**
+ * Check if a CharSequence starts with any of the provided case-sensitive prefixes.
+ *
+ *
+ * StringUtils.startsWithAny(null, null) = false
+ * StringUtils.startsWithAny(null, new String[] {"abc"}) = false
+ * StringUtils.startsWithAny("abcxyz", null) = false
+ * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true
+ * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
+ * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
+ * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false
+ * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false
+ *
+ *
+ * @param sequence the CharSequence to check, may be null
+ * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null}
+ * @see StringUtils#startsWith(CharSequence, CharSequence)
+ * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
+ * the input {@code sequence} begins with any of the provided case-sensitive {@code searchStrings}.
+ * @since 2.5
+ * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...)
+ */
+ public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
+ if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {
+ return false;
+ }
+ for (final CharSequence searchString : searchStrings) {
+ if (startsWith(sequence, searchString)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // endsWith
+ //-----------------------------------------------------------------------
+
+ /**
+ * Check if a CharSequence ends with a specified suffix.
+ *
+ * {@code null}s are handled without exceptions. Two {@code null}
+ * references are considered to be equal. The comparison is case sensitive.
+ *
+ *
+ * StringUtils.endsWith(null, null) = true
+ * StringUtils.endsWith(null, "def") = false
+ * StringUtils.endsWith("abcdef", null) = false
+ * StringUtils.endsWith("abcdef", "def") = true
+ * StringUtils.endsWith("ABCDEF", "def") = false
+ * StringUtils.endsWith("ABCDEF", "cde") = false
+ * StringUtils.endsWith("ABCDEF", "") = true
+ *
+ *
+ * @see java.lang.String#endsWith(String)
+ * @param str the CharSequence to check, may be null
+ * @param suffix the suffix to find, may be null
+ * @return {@code true} if the CharSequence ends with the suffix, case sensitive, or
+ * both {@code null}
+ * @since 2.4
+ * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence)
+ */
+ public static boolean endsWith(final CharSequence str, final CharSequence suffix) {
+ return endsWith(str, suffix, false);
+ }
+
+ /**
+ * Case insensitive check if a CharSequence ends with a specified suffix.
+ *
+ * {@code null}s are handled without exceptions. Two {@code null}
+ * references are considered to be equal. The comparison is case insensitive.
+ *
+ *
+ * StringUtils.endsWithIgnoreCase(null, null) = true
+ * StringUtils.endsWithIgnoreCase(null, "def") = false
+ * StringUtils.endsWithIgnoreCase("abcdef", null) = false
+ * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
+ * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
+ * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
+ *
+ *
+ * @see java.lang.String#endsWith(String)
+ * @param str the CharSequence to check, may be null
+ * @param suffix the suffix to find, may be null
+ * @return {@code true} if the CharSequence ends with the suffix, case insensitive, or
+ * both {@code null}
+ * @since 2.4
+ * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence)
+ */
+ public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) {
+ return endsWith(str, suffix, true);
+ }
+
+ /**
+ * Check if a CharSequence ends with a specified suffix (optionally case insensitive).
+ *
+ * @see java.lang.String#endsWith(String)
+ * @param str the CharSequence to check, may be null
+ * @param suffix the suffix to find, may be null
+ * @param ignoreCase indicates whether the compare should ignore case
+ * (case insensitive) or not.
+ * @return {@code true} if the CharSequence starts with the prefix or
+ * both {@code null}
+ */
+ private static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) {
+ if (str == null || suffix == null) {
+ return str == null && suffix == null;
+ }
+ if (suffix.length() > str.length()) {
+ return false;
+ }
+ final int strOffset = str.length() - suffix.length();
+ return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length());
+ }
+
+ /**
+ *
+ * Similar to http://www.w3.org/TR/xpath/#function-normalize
+ * -space
+ *
+ *
+ * The function returns the argument string with whitespace normalized by using
+ * {@link #trim(String)}
to remove leading and trailing whitespace
+ * and then replacing sequences of whitespace characters by a single space.
+ *
+ * In XML Whitespace characters are the same as those allowed by the S production, which is S ::= (#x20 | #x9 | #xD | #xA)+
+ *
+ * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r]
+ *
+ *
For reference:
+ *
+ * \x0B = vertical tab
+ * \f = #xC = form feed
+ * #x20 = space
+ * #x9 = \t
+ * #xA = \n
+ * #xD = \r
+ *
+ *
+ *
+ * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also
+ * normalize. Additionally {@link #trim(String)}
removes control characters (char <= 32) from both
+ * ends of this String.
+ *
+ *
+ * @see Pattern
+ * @see #trim(String)
+ * @see http://www.w3.org/TR/xpath/#function-normalize-space
+ * @param str the source String to normalize whitespaces from, may be null
+ * @return the modified string with whitespace normalized, {@code null} if null String input
+ *
+ * @since 3.0
+ */
+ public static String normalizeSpace(final String str) {
+ // LANG-1020: Improved performance significantly by normalizing manually instead of using regex
+ // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test
+ if (isEmpty(str)) {
+ return str;
+ }
+ final int size = str.length();
+ final char[] newChars = new char[size];
+ int count = 0;
+ int whitespacesCount = 0;
+ boolean startWhitespaces = true;
+ for (int i = 0; i < size; i++) {
+ char actualChar = str.charAt(i);
+ boolean isWhitespace = Character.isWhitespace(actualChar);
+ if (!isWhitespace) {
+ startWhitespaces = false;
+ newChars[count++] = (actualChar == 160 ? 32 : actualChar);
+ whitespacesCount = 0;
+ } else {
+ if (whitespacesCount == 0 && !startWhitespaces) {
+ newChars[count++] = SPACE.charAt(0);
+ }
+ whitespacesCount++;
+ }
+ }
+ if (startWhitespaces) {
+ return EMPTY;
+ }
+ return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim();
+ }
+
+ /**
+ * Check if a CharSequence ends with any of the provided case-sensitive suffixes.
+ *
+ *
+ * StringUtils.endsWithAny(null, null) = false
+ * StringUtils.endsWithAny(null, new String[] {"abc"}) = false
+ * StringUtils.endsWithAny("abcxyz", null) = false
+ * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
+ * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
+ * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
+ * StringUtils.endsWithAny("abcXYZ", "def", "XYZ") = true
+ * StringUtils.endsWithAny("abcXYZ", "def", "xyz") = false
+ *
+ *
+ * @param sequence the CharSequence to check, may be null
+ * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null}
+ * @see StringUtils#endsWith(CharSequence, CharSequence)
+ * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
+ * the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}.
+ * @since 3.0
+ */
+ public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
+ if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {
+ return false;
+ }
+ for (final CharSequence searchString : searchStrings) {
+ if (endsWith(sequence, searchString)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Appends the suffix to the end of the string if the string does not
+ * already end with the suffix.
+ *
+ * @param str The string.
+ * @param suffix The suffix to append to the end of the string.
+ * @param ignoreCase Indicates whether the compare should ignore case.
+ * @param suffixes Additional suffixes that are valid terminators (optional).
+ *
+ * @return A new String if suffix was appended, the same string otherwise.
+ */
+ private static String appendIfMissing(final String str, final CharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes) {
+ if (str == null || isEmpty(suffix) || endsWith(str, suffix, ignoreCase)) {
+ return str;
+ }
+ if (suffixes != null && suffixes.length > 0) {
+ for (final CharSequence s : suffixes) {
+ if (endsWith(str, s, ignoreCase)) {
+ return str;
+ }
+ }
+ }
+ return str + suffix.toString();
+ }
+
+ /**
+ * Appends the suffix to the end of the string if the string does not
+ * already end with any of the suffixes.
+ *
+ *
+ * StringUtils.appendIfMissing(null, null) = null
+ * StringUtils.appendIfMissing("abc", null) = "abc"
+ * StringUtils.appendIfMissing("", "xyz") = "xyz"
+ * StringUtils.appendIfMissing("abc", "xyz") = "abcxyz"
+ * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz"
+ * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz"
+ *
+ * With additional suffixes,
+ *
+ * StringUtils.appendIfMissing(null, null, null) = null
+ * StringUtils.appendIfMissing("abc", null, null) = "abc"
+ * StringUtils.appendIfMissing("", "xyz", null) = "xyz"
+ * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
+ * StringUtils.appendIfMissing("abc", "xyz", "") = "abc"
+ * StringUtils.appendIfMissing("abc", "xyz", "mno") = "abcxyz"
+ * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz"
+ * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno"
+ * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz"
+ * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz"
+ *
+ *
+ * @param str The string.
+ * @param suffix The suffix to append to the end of the string.
+ * @param suffixes Additional suffixes that are valid terminators.
+ *
+ * @return A new String if suffix was appended, the same string otherwise.
+ *
+ * @since 3.2
+ */
+ public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) {
+ return appendIfMissing(str, suffix, false, suffixes);
+ }
+
+ /**
+ * Appends the suffix to the end of the string if the string does not
+ * already end, case insensitive, with any of the suffixes.
+ *
+ *
+ * StringUtils.appendIfMissingIgnoreCase(null, null) = null
+ * StringUtils.appendIfMissingIgnoreCase("abc", null) = "abc"
+ * StringUtils.appendIfMissingIgnoreCase("", "xyz") = "xyz"
+ * StringUtils.appendIfMissingIgnoreCase("abc", "xyz") = "abcxyz"
+ * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz"
+ * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ"
+ *
+ * With additional suffixes,
+ *
+ * StringUtils.appendIfMissingIgnoreCase(null, null, null) = null
+ * StringUtils.appendIfMissingIgnoreCase("abc", null, null) = "abc"
+ * StringUtils.appendIfMissingIgnoreCase("", "xyz", null) = "xyz"
+ * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
+ * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "") = "abc"
+ * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno") = "axyz"
+ * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz"
+ * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno"
+ * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ"
+ * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO"
+ *
+ *
+ * @param str The string.
+ * @param suffix The suffix to append to the end of the string.
+ * @param suffixes Additional suffixes that are valid terminators.
+ *
+ * @return A new String if suffix was appended, the same string otherwise.
+ *
+ * @since 3.2
+ */
+ public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) {
+ return appendIfMissing(str, suffix, true, suffixes);
+ }
+
+ /**
+ * Prepends the prefix to the start of the string if the string does not
+ * already start with any of the prefixes.
+ *
+ * @param str The string.
+ * @param prefix The prefix to prepend to the start of the string.
+ * @param ignoreCase Indicates whether the compare should ignore case.
+ * @param prefixes Additional prefixes that are valid (optional).
+ *
+ * @return A new String if prefix was prepended, the same string otherwise.
+ */
+ private static String prependIfMissing(final String str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) {
+ if (str == null || isEmpty(prefix) || startsWith(str, prefix, ignoreCase)) {
+ return str;
+ }
+ if (prefixes != null && prefixes.length > 0) {
+ for (final CharSequence p : prefixes) {
+ if (startsWith(str, p, ignoreCase)) {
+ return str;
+ }
+ }
+ }
+ return prefix.toString() + str;
+ }
+
+ /**
+ * Prepends the prefix to the start of the string if the string does not
+ * already start with any of the prefixes.
+ *
+ *
+ * StringUtils.prependIfMissing(null, null) = null
+ * StringUtils.prependIfMissing("abc", null) = "abc"
+ * StringUtils.prependIfMissing("", "xyz") = "xyz"
+ * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc"
+ * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc"
+ * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc"
+ *
+ * With additional prefixes,
+ *
+ * StringUtils.prependIfMissing(null, null, null) = null
+ * StringUtils.prependIfMissing("abc", null, null) = "abc"
+ * StringUtils.prependIfMissing("", "xyz", null) = "xyz"
+ * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
+ * StringUtils.prependIfMissing("abc", "xyz", "") = "abc"
+ * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc"
+ * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc"
+ * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc"
+ * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc"
+ * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc"
+ *
+ *
+ * @param str The string.
+ * @param prefix The prefix to prepend to the start of the string.
+ * @param prefixes Additional prefixes that are valid.
+ *
+ * @return A new String if prefix was prepended, the same string otherwise.
+ *
+ * @since 3.2
+ */
+ public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) {
+ return prependIfMissing(str, prefix, false, prefixes);
+ }
+
+ /**
+ * Prepends the prefix to the start of the string if the string does not
+ * already start, case insensitive, with any of the prefixes.
+ *
+ *
+ * StringUtils.prependIfMissingIgnoreCase(null, null) = null
+ * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc"
+ * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz"
+ * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc"
+ * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc"
+ * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc"
+ *
+ * With additional prefixes,
+ *
+ * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null
+ * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc"
+ * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz"
+ * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
+ * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc"
+ * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc"
+ * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc"
+ * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc"
+ * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc"
+ * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc"
+ *
+ *
+ * @param str The string.
+ * @param prefix The prefix to prepend to the start of the string.
+ * @param prefixes Additional prefixes that are valid (optional).
+ *
+ * @return A new String if prefix was prepended, the same string otherwise.
+ *
+ * @since 3.2
+ */
+ public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) {
+ return prependIfMissing(str, prefix, true, prefixes);
+ }
+
+ /**
+ * Converts a byte[]
to a String using the specified character encoding.
+ *
+ * @param bytes
+ * the byte array to read from
+ * @param charsetName
+ * the encoding to use, if null then use the platform default
+ * @return a new String
+ * @throws UnsupportedEncodingException
+ * If the named charset is not supported
+ * @throws NullPointerException
+ * if the input is null
+ * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code
+ * @since 3.1
+ */
+ @Deprecated
+ public static String toString(final byte[] bytes, final String charsetName) throws UnsupportedEncodingException {
+ return charsetName != null ? new String(bytes, charsetName) : new String(bytes, Charset.defaultCharset());
+ }
+
+ /**
+ * Converts a byte[]
to a String using the specified character encoding.
+ *
+ * @param bytes
+ * the byte array to read from
+ * @param charset
+ * the encoding to use, if null then use the platform default
+ * @return a new String
+ * @throws NullPointerException
+ * if {@code bytes} is null
+ * @since 3.2
+ * @since 3.3 No longer throws {@link UnsupportedEncodingException}.
+ */
+ public static String toEncodedString(final byte[] bytes, final Charset charset) {
+ return new String(bytes, charset != null ? charset : Charset.defaultCharset());
+ }
+
+ /**
+ *
+ * Wraps a string with a char.
+ *
+ *
+ *
+ * StringUtils.wrap(null, *) = null
+ * StringUtils.wrap("", *) = ""
+ * StringUtils.wrap("ab", '\0') = "ab"
+ * StringUtils.wrap("ab", 'x') = "xabx"
+ * StringUtils.wrap("ab", '\'') = "'ab'"
+ * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\""
+ *
+ *
+ * @param str
+ * the string to be wrapped, may be {@code null}
+ * @param wrapWith
+ * the char that will wrap {@code str}
+ * @return the wrapped string, or {@code null} if {@code str==null}
+ * @since 3.4
+ */
+ public static String wrap(final String str, final char wrapWith) {
+
+ if (isEmpty(str) || wrapWith == '\0') {
+ return str;
+ }
+
+ return wrapWith + str + wrapWith;
+ }
+
+ /**
+ *
+ * Wraps a String with another String.
+ *
+ *
+ *
+ * A {@code null} input String returns {@code null}.
+ *
+ *
+ *
+ * StringUtils.wrap(null, *) = null
+ * StringUtils.wrap("", *) = ""
+ * StringUtils.wrap("ab", null) = "ab"
+ * StringUtils.wrap("ab", "x") = "xabx"
+ * StringUtils.wrap("ab", "\"") = "\"ab\""
+ * StringUtils.wrap("\"ab\"", "\"") = "\"\"ab\"\""
+ * StringUtils.wrap("ab", "'") = "'ab'"
+ * StringUtils.wrap("'abcd'", "'") = "''abcd''"
+ * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'"
+ * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\""
+ *
+ *
+ * @param str
+ * the String to be wrapper, may be null
+ * @param wrapWith
+ * the String that will wrap str
+ * @return wrapped String, {@code null} if null String input
+ * @since 3.4
+ */
+ public static String wrap(final String str, final String wrapWith) {
+
+ if (isEmpty(str) || isEmpty(wrapWith)) {
+ return str;
+ }
+
+ return wrapWith.concat(str).concat(wrapWith);
+ }
+
+ /**
+ *
+ * Wraps a string with a char if that char is missing from the start or end of the given string.
+ *
+ *
+ *
+ * StringUtils.wrap(null, *) = null
+ * StringUtils.wrap("", *) = ""
+ * StringUtils.wrap("ab", '\0') = "ab"
+ * StringUtils.wrap("ab", 'x') = "xabx"
+ * StringUtils.wrap("ab", '\'') = "'ab'"
+ * StringUtils.wrap("\"ab\"", '\"') = "\"ab\""
+ * StringUtils.wrap("/", '/') = "/"
+ * StringUtils.wrap("a/b/c", '/') = "/a/b/c/"
+ * StringUtils.wrap("/a/b/c", '/') = "/a/b/c/"
+ * StringUtils.wrap("a/b/c/", '/') = "/a/b/c/"
+ *
+ *
+ * @param str
+ * the string to be wrapped, may be {@code null}
+ * @param wrapWith
+ * the char that will wrap {@code str}
+ * @return the wrapped string, or {@code null} if {@code str==null}
+ * @since 3.5
+ */
+ public static String wrapIfMissing(final String str, final char wrapWith) {
+ if (isEmpty(str) || wrapWith == '\0') {
+ return str;
+ }
+ StringBuilder builder = new StringBuilder(str.length() + 2);
+ if (str.charAt(0) != wrapWith) {
+ builder.append(wrapWith);
+ }
+ builder.append(str);
+ if (str.charAt(str.length() - 1) != wrapWith) {
+ builder.append(wrapWith);
+ }
+ return builder.toString();
+ }
+
+ /**
+ *
+ * Wraps a string with a string if that string is missing from the start or end of the given string.
+ *
+ *
+ *
+ * StringUtils.wrap(null, *) = null
+ * StringUtils.wrap("", *) = ""
+ * StringUtils.wrap("ab", null) = "ab"
+ * StringUtils.wrap("ab", "x") = "xabx"
+ * StringUtils.wrap("ab", "\"") = "\"ab\""
+ * StringUtils.wrap("\"ab\"", "\"") = "\"ab\""
+ * StringUtils.wrap("ab", "'") = "'ab'"
+ * StringUtils.wrap("'abcd'", "'") = "'abcd'"
+ * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'"
+ * StringUtils.wrap("'abcd'", "\"") = "\"'abcd'\""
+ * StringUtils.wrap("/", "/") = "/"
+ * StringUtils.wrap("a/b/c", "/") = "/a/b/c/"
+ * StringUtils.wrap("/a/b/c", "/") = "/a/b/c/"
+ * StringUtils.wrap("a/b/c/", "/") = "/a/b/c/"
+ *
+ *
+ * @param str
+ * the string to be wrapped, may be {@code null}
+ * @param wrapWith
+ * the char that will wrap {@code str}
+ * @return the wrapped string, or {@code null} if {@code str==null}
+ * @since 3.5
+ */
+ public static String wrapIfMissing(final String str, final String wrapWith) {
+ if (isEmpty(str) || isEmpty(wrapWith)) {
+ return str;
+ }
+ StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length());
+ if (!str.startsWith(wrapWith)) {
+ builder.append(wrapWith);
+ }
+ builder.append(str);
+ if (!str.endsWith(wrapWith)) {
+ builder.append(wrapWith);
+ }
+ return builder.toString();
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SystemUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SystemUtils.java
new file mode 100644
index 000000000..a8d860d27
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/SystemUtils.java
@@ -0,0 +1,1724 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.io.File;
+
+/**
+ *
+ * Helpers for {@code java.lang.System}.
+ *
+ *
+ * If a system property cannot be read due to security restrictions, the corresponding field in this class will be set
+ * to {@code null} and a message will be written to {@code System.err}.
+ *
+ *
+ * #ThreadSafe#
+ *
+ *
+ * @since 1.0
+ */
+public class SystemUtils {
+
+ /**
+ * The prefix String for all Windows OS.
+ */
+ private static final String OS_NAME_WINDOWS_PREFIX = "Windows";
+
+ // System property constants
+ // -----------------------------------------------------------------------
+ // These MUST be declared first. Other constants depend on this.
+
+ /**
+ * The System property key for the user home directory.
+ */
+ private static final String USER_HOME_KEY = "user.home";
+
+ /**
+ * The System property key for the user directory.
+ */
+ private static final String USER_DIR_KEY = "user.dir";
+
+ /**
+ * The System property key for the Java IO temporary directory.
+ */
+ private static final String JAVA_IO_TMPDIR_KEY = "java.io.tmpdir";
+
+ /**
+ * The System property key for the Java home directory.
+ */
+ private static final String JAVA_HOME_KEY = "java.home";
+
+ /**
+ *
+ * The {@code awt.toolkit} System Property.
+ *
+ *
+ * Holds a class name, on Windows XP this is {@code sun.awt.windows.WToolkit}.
+ *
+ *
+ * On platforms without a GUI, this value is {@code null}.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String AWT_TOOLKIT = getSystemProperty("awt.toolkit");
+
+ /**
+ *
+ * The {@code file.encoding} System Property.
+ *
+ *
+ * File encoding, such as {@code Cp1252}.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.0
+ * @since Java 1.2
+ */
+ public static final String FILE_ENCODING = getSystemProperty("file.encoding");
+
+ /**
+ *
+ * The {@code file.separator} System Property.
+ * The file separator is:
+ *
+ *
+ * {@code "/"} on UNIX
+ * {@code "\"} on Windows.
+ *
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @deprecated Use {@link File#separator}, since it is guaranteed to be a
+ * string containing a single character and it does not require a privilege check.
+ * @since Java 1.1
+ */
+ @Deprecated
+ public static final String FILE_SEPARATOR = getSystemProperty("file.separator");
+
+ /**
+ *
+ * The {@code java.awt.fonts} System Property.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String JAVA_AWT_FONTS = getSystemProperty("java.awt.fonts");
+
+ /**
+ *
+ * The {@code java.awt.graphicsenv} System Property.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String JAVA_AWT_GRAPHICSENV = getSystemProperty("java.awt.graphicsenv");
+
+ /**
+ *
+ * The {@code java.awt.headless} System Property. The value of this property is the String {@code "true"} or
+ * {@code "false"}.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @see #isJavaAwtHeadless()
+ * @since 2.1
+ * @since Java 1.4
+ */
+ public static final String JAVA_AWT_HEADLESS = getSystemProperty("java.awt.headless");
+
+ /**
+ *
+ * The {@code java.awt.printerjob} System Property.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String JAVA_AWT_PRINTERJOB = getSystemProperty("java.awt.printerjob");
+
+ /**
+ *
+ * The {@code java.class.path} System Property. Java class path.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_CLASS_PATH = getSystemProperty("java.class.path");
+
+ /**
+ *
+ * The {@code java.class.version} System Property. Java class format version number.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_CLASS_VERSION = getSystemProperty("java.class.version");
+
+ /**
+ *
+ * The {@code java.compiler} System Property. Name of JIT compiler to use. First in JDK version 1.2. Not used in Sun
+ * JDKs after 1.2.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2. Not used in Sun versions after 1.2.
+ */
+ public static final String JAVA_COMPILER = getSystemProperty("java.compiler");
+
+ /**
+ *
+ * The {@code java.endorsed.dirs} System Property. Path of endorsed directory or directories.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.4
+ */
+ public static final String JAVA_ENDORSED_DIRS = getSystemProperty("java.endorsed.dirs");
+
+ /**
+ *
+ * The {@code java.ext.dirs} System Property. Path of extension directory or directories.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.3
+ */
+ public static final String JAVA_EXT_DIRS = getSystemProperty("java.ext.dirs");
+
+ /**
+ *
+ * The {@code java.home} System Property. Java installation directory.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_HOME = getSystemProperty(JAVA_HOME_KEY);
+
+ /**
+ *
+ * The {@code java.io.tmpdir} System Property. Default temp file path.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_IO_TMPDIR = getSystemProperty(JAVA_IO_TMPDIR_KEY);
+
+ /**
+ *
+ * The {@code java.library.path} System Property. List of paths to search when loading libraries.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_LIBRARY_PATH = getSystemProperty("java.library.path");
+
+ /**
+ *
+ * The {@code java.runtime.name} System Property. Java Runtime Environment name.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.0
+ * @since Java 1.3
+ */
+ public static final String JAVA_RUNTIME_NAME = getSystemProperty("java.runtime.name");
+
+ /**
+ *
+ * The {@code java.runtime.version} System Property. Java Runtime Environment version.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.0
+ * @since Java 1.3
+ */
+ public static final String JAVA_RUNTIME_VERSION = getSystemProperty("java.runtime.version");
+
+ /**
+ *
+ * The {@code java.specification.name} System Property. Java Runtime Environment specification name.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_SPECIFICATION_NAME = getSystemProperty("java.specification.name");
+
+ /**
+ *
+ * The {@code java.specification.vendor} System Property. Java Runtime Environment specification vendor.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_SPECIFICATION_VENDOR = getSystemProperty("java.specification.vendor");
+
+ /**
+ *
+ * The {@code java.specification.version} System Property. Java Runtime Environment specification version.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.3
+ */
+ public static final String JAVA_SPECIFICATION_VERSION = getSystemProperty("java.specification.version");
+ private static final JavaVersion JAVA_SPECIFICATION_VERSION_AS_ENUM = JavaVersion.get(JAVA_SPECIFICATION_VERSION);
+
+ /**
+ *
+ * The {@code java.util.prefs.PreferencesFactory} System Property. A class name.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.1
+ * @since Java 1.4
+ */
+ public static final String JAVA_UTIL_PREFS_PREFERENCES_FACTORY =
+ getSystemProperty("java.util.prefs.PreferencesFactory");
+
+ /**
+ *
+ * The {@code java.vendor} System Property. Java vendor-specific string.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_VENDOR = getSystemProperty("java.vendor");
+
+ /**
+ *
+ * The {@code java.vendor.url} System Property. Java vendor URL.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_VENDOR_URL = getSystemProperty("java.vendor.url");
+
+ /**
+ *
+ * The {@code java.version} System Property. Java version number.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String JAVA_VERSION = getSystemProperty("java.version");
+
+ /**
+ *
+ * The {@code java.vm.info} System Property. Java Virtual Machine implementation info.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.0
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_INFO = getSystemProperty("java.vm.info");
+
+ /**
+ *
+ * The {@code java.vm.name} System Property. Java Virtual Machine implementation name.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_NAME = getSystemProperty("java.vm.name");
+
+ /**
+ *
+ * The {@code java.vm.specification.name} System Property. Java Virtual Machine specification name.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_SPECIFICATION_NAME = getSystemProperty("java.vm.specification.name");
+
+ /**
+ *
+ * The {@code java.vm.specification.vendor} System Property. Java Virtual Machine specification vendor.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_SPECIFICATION_VENDOR = getSystemProperty("java.vm.specification.vendor");
+
+ /**
+ *
+ * The {@code java.vm.specification.version} System Property. Java Virtual Machine specification version.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_SPECIFICATION_VERSION = getSystemProperty("java.vm.specification.version");
+
+ /**
+ *
+ * The {@code java.vm.vendor} System Property. Java Virtual Machine implementation vendor.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_VENDOR = getSystemProperty("java.vm.vendor");
+
+ /**
+ *
+ * The {@code java.vm.version} System Property. Java Virtual Machine implementation version.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.2
+ */
+ public static final String JAVA_VM_VERSION = getSystemProperty("java.vm.version");
+
+ /**
+ *
+ * The {@code line.separator} System Property. Line separator ("\n"
on UNIX).
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String LINE_SEPARATOR = getSystemProperty("line.separator");
+
+ /**
+ *
+ * The {@code os.arch} System Property. Operating system architecture.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String OS_ARCH = getSystemProperty("os.arch");
+
+ /**
+ *
+ * The {@code os.name} System Property. Operating system name.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String OS_NAME = getSystemProperty("os.name");
+
+ /**
+ *
+ * The {@code os.version} System Property. Operating system version.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String OS_VERSION = getSystemProperty("os.version");
+
+ /**
+ *
+ * The {@code path.separator} System Property. Path separator (":"
on UNIX).
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @deprecated Use {@link File#pathSeparator}, since it is guaranteed to be a
+ * string containing a single character and it does not require a privilege check.
+ * @since Java 1.1
+ */
+ @Deprecated
+ public static final String PATH_SEPARATOR = getSystemProperty("path.separator");
+
+ /**
+ *
+ * The {@code user.country} or {@code user.region} System Property. User's country code, such as {@code GB}. First
+ * in Java version 1.2 as {@code user.region}. Renamed to {@code user.country} in 1.4
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.0
+ * @since Java 1.2
+ */
+ public static final String USER_COUNTRY = getSystemProperty("user.country") == null ?
+ getSystemProperty("user.region") : getSystemProperty("user.country");
+
+ /**
+ *
+ * The {@code user.dir} System Property. User's current working directory.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String USER_DIR = getSystemProperty(USER_DIR_KEY);
+
+ /**
+ *
+ * The {@code user.home} System Property. User's home directory.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String USER_HOME = getSystemProperty(USER_HOME_KEY);
+
+ /**
+ *
+ * The {@code user.language} System Property. User's language code, such as {@code "en"}.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.0
+ * @since Java 1.2
+ */
+ public static final String USER_LANGUAGE = getSystemProperty("user.language");
+
+ /**
+ *
+ * The {@code user.name} System Property. User's account name.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since Java 1.1
+ */
+ public static final String USER_NAME = getSystemProperty("user.name");
+
+ /**
+ *
+ * The {@code user.timezone} System Property. For example: {@code "America/Los_Angeles"}.
+ *
+ *
+ * Defaults to {@code null} if the runtime does not have security access to read this property or the property does
+ * not exist.
+ *
+ *
+ * This value is initialized when the class is loaded. If {@link System#setProperty(String,String)} or
+ * {@link System#setProperties(java.util.Properties)} is called after this class is loaded, the value will be out of
+ * sync with that System property.
+ *
+ *
+ * @since 2.1
+ */
+ public static final String USER_TIMEZONE = getSystemProperty("user.timezone");
+
+ // Java version checks
+ // -----------------------------------------------------------------------
+ // These MUST be declared after those above as they depend on the
+ // values being set up
+
+ /**
+ *
+ * Is {@code true} if this is Java version 1.1 (also 1.1.x versions).
+ *
+ *
+ * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
+ *
+ */
+ public static final boolean IS_JAVA_1_1 = getJavaVersionMatches("1.1");
+
+ /**
+ *
+ * Is {@code true} if this is Java version 1.2 (also 1.2.x versions).
+ *
+ *
+ * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
+ *
+ */
+ public static final boolean IS_JAVA_1_2 = getJavaVersionMatches("1.2");
+
+ /**
+ *
+ * Is {@code true} if this is Java version 1.3 (also 1.3.x versions).
+ *
+ *
+ * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
+ *
+ */
+ public static final boolean IS_JAVA_1_3 = getJavaVersionMatches("1.3");
+
+ /**
+ *
+ * Is {@code true} if this is Java version 1.4 (also 1.4.x versions).
+ *
+ *
+ * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
+ *
+ */
+ public static final boolean IS_JAVA_1_4 = getJavaVersionMatches("1.4");
+
+ /**
+ *
+ * Is {@code true} if this is Java version 1.5 (also 1.5.x versions).
+ *
+ *
+ * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
+ *
+ */
+ public static final boolean IS_JAVA_1_5 = getJavaVersionMatches("1.5");
+
+ /**
+ *
+ * Is {@code true} if this is Java version 1.6 (also 1.6.x versions).
+ *
+ *
+ * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
+ *
+ */
+ public static final boolean IS_JAVA_1_6 = getJavaVersionMatches("1.6");
+
+ /**
+ *
+ * Is {@code true} if this is Java version 1.7 (also 1.7.x versions).
+ *
+ *
+ * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
+ *
+ *
+ * @since 3.0
+ */
+ public static final boolean IS_JAVA_1_7 = getJavaVersionMatches("1.7");
+
+ /**
+ *
+ * Is {@code true} if this is Java version 1.8 (also 1.8.x versions).
+ *
+ *
+ * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
+ *
+ *
+ * @since 3.3.2
+ */
+ public static final boolean IS_JAVA_1_8 = getJavaVersionMatches("1.8");
+
+ /**
+ *
+ * Is {@code true} if this is Java version 1.9 (also 1.9.x versions).
+ *
+ *
+ * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
+ *
+ *
+ * @since 3.4
+ *
+ * @deprecated As of release 3.5, replaced by {@link #IS_JAVA_9}
+ */
+ @Deprecated
+ public static final boolean IS_JAVA_1_9 = getJavaVersionMatches("9");
+
+ /**
+ *
+ * Is {@code true} if this is Java version 9 (also 9.x versions).
+ *
+ *
+ * The field will return {@code false} if {@link #JAVA_VERSION} is {@code null}.
+ *
+ *
+ * @since 3.5
+ */
+ public static final boolean IS_JAVA_9 = getJavaVersionMatches("9");
+
+ // Operating system checks
+ // -----------------------------------------------------------------------
+ // These MUST be declared after those above as they depend on the
+ // values being set up
+ // OS names from http://www.vamphq.com/os.html
+ // Selected ones included - please advise dev@commons.apache.org
+ // if you want another added or a mistake corrected
+
+ /**
+ *
+ * Is {@code true} if this is AIX.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_AIX = getOSMatchesName("AIX");
+
+ /**
+ *
+ * Is {@code true} if this is HP-UX.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_HP_UX = getOSMatchesName("HP-UX");
+
+ /**
+ *
+ * Is {@code true} if this is IBM OS/400.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.3
+ */
+ public static final boolean IS_OS_400 = getOSMatchesName("OS/400");
+
+ /**
+ *
+ * Is {@code true} if this is Irix.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_IRIX = getOSMatchesName("Irix");
+
+ /**
+ *
+ * Is {@code true} if this is Linux.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_LINUX = getOSMatchesName("Linux") || getOSMatchesName("LINUX");
+
+ /**
+ *
+ * Is {@code true} if this is Mac.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_MAC = getOSMatchesName("Mac");
+
+ /**
+ *
+ * Is {@code true} if this is Mac.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_MAC_OSX = getOSMatchesName("Mac OS X");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Cheetah.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_CHEETAH = getOSMatches("Mac OS X", "10.0");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Puma.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_PUMA = getOSMatches("Mac OS X", "10.1");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Jaguar.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_JAGUAR = getOSMatches("Mac OS X", "10.2");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Panther.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_PANTHER = getOSMatches("Mac OS X", "10.3");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Tiger.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_TIGER = getOSMatches("Mac OS X", "10.4");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Leopard.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_LEOPARD = getOSMatches("Mac OS X", "10.5");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Snow Leopard.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_SNOW_LEOPARD = getOSMatches("Mac OS X", "10.6");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Lion.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_LION = getOSMatches("Mac OS X", "10.7");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Mountain Lion.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_MOUNTAIN_LION = getOSMatches("Mac OS X", "10.8");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Mavericks.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_MAVERICKS = getOSMatches("Mac OS X", "10.9");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X Yosemite.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_MAC_OSX_YOSEMITE = getOSMatches("Mac OS X", "10.10");
+
+ /**
+ *
+ * Is {@code true} if this is Mac OS X El Capitan.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.5
+ */
+ public static final boolean IS_OS_MAC_OSX_EL_CAPITAN = getOSMatches("Mac OS X", "10.11");
+
+ /**
+ *
+ * Is {@code true} if this is FreeBSD.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.1
+ */
+ public static final boolean IS_OS_FREE_BSD = getOSMatchesName("FreeBSD");
+
+ /**
+ *
+ * Is {@code true} if this is OpenBSD.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.1
+ */
+ public static final boolean IS_OS_OPEN_BSD = getOSMatchesName("OpenBSD");
+
+ /**
+ *
+ * Is {@code true} if this is NetBSD.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.1
+ */
+ public static final boolean IS_OS_NET_BSD = getOSMatchesName("NetBSD");
+
+ /**
+ *
+ * Is {@code true} if this is OS/2.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_OS2 = getOSMatchesName("OS/2");
+
+ /**
+ *
+ * Is {@code true} if this is Solaris.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_SOLARIS = getOSMatchesName("Solaris");
+
+ /**
+ *
+ * Is {@code true} if this is SunOS.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_SUN_OS = getOSMatchesName("SunOS");
+
+ /**
+ *
+ * Is {@code true} if this is a UNIX like system, as in any of AIX, HP-UX, Irix, Linux, MacOSX, Solaris or SUN OS.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.1
+ */
+ public static final boolean IS_OS_UNIX = IS_OS_AIX || IS_OS_HP_UX || IS_OS_IRIX || IS_OS_LINUX || IS_OS_MAC_OSX
+ || IS_OS_SOLARIS || IS_OS_SUN_OS || IS_OS_FREE_BSD || IS_OS_OPEN_BSD || IS_OS_NET_BSD;
+
+ /**
+ *
+ * Is {@code true} if this is Windows.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS = getOSMatchesName(OS_NAME_WINDOWS_PREFIX);
+
+ /**
+ *
+ * Is {@code true} if this is Windows 2000.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_2000 = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " 2000");
+
+ /**
+ *
+ * Is {@code true} if this is Windows 2003.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.1
+ */
+ public static final boolean IS_OS_WINDOWS_2003 = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " 2003");
+
+ /**
+ *
+ * Is {@code true} if this is Windows Server 2008.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.1
+ */
+ public static final boolean IS_OS_WINDOWS_2008 = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " Server 2008");
+
+ /**
+ *
+ * Is {@code true} if this is Windows Server 2012.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.4
+ */
+ public static final boolean IS_OS_WINDOWS_2012 = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " Server 2012");
+
+ /**
+ *
+ * Is {@code true} if this is Windows 95.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_95 = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " 95");
+
+ /**
+ *
+ * Is {@code true} if this is Windows 98.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_98 = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " 98");
+
+ /**
+ *
+ * Is {@code true} if this is Windows ME.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_ME = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " Me");
+
+ /**
+ *
+ * Is {@code true} if this is Windows NT.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_NT = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " NT");
+
+ /**
+ *
+ * Is {@code true} if this is Windows XP.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.0
+ */
+ public static final boolean IS_OS_WINDOWS_XP = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " XP");
+
+ // -----------------------------------------------------------------------
+ /**
+ *
+ * Is {@code true} if this is Windows Vista.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 2.4
+ */
+ public static final boolean IS_OS_WINDOWS_VISTA = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " Vista");
+
+ /**
+ *
+ * Is {@code true} if this is Windows 7.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.0
+ */
+ public static final boolean IS_OS_WINDOWS_7 = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " 7");
+
+ /**
+ *
+ * Is {@code true} if this is Windows 8.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.2
+ */
+ public static final boolean IS_OS_WINDOWS_8 = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " 8");
+
+ /**
+ *
+ * Is {@code true} if this is Windows 10.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.5
+ */
+ public static final boolean IS_OS_WINDOWS_10 = getOSMatchesName(OS_NAME_WINDOWS_PREFIX + " 10");
+
+ /**
+ *
+ * Is {@code true} if this is z/OS.
+ *
+ *
+ * The field will return {@code false} if {@code OS_NAME} is {@code null}.
+ *
+ *
+ * @since 3.5
+ */
+ // Values on a z/OS system I tested (Gary Gregory - 2016-03-12)
+ // os.arch = s390x
+ // os.encoding = ISO8859_1
+ // os.name = z/OS
+ // os.version = 02.02.00
+ public static final boolean IS_OS_ZOS = getOSMatchesName("z/OS");
+
+ /**
+ *
+ * Gets the Java home directory as a {@code File}.
+ *
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
+ * access to the specified system property.
+ * @see System#getProperty(String)
+ * @since 2.1
+ */
+ public static File getJavaHome() {
+ return new File(System.getProperty(JAVA_HOME_KEY));
+ }
+
+ /**
+ *
+ * Gets the Java IO temporary directory as a {@code File}.
+ *
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
+ * access to the specified system property.
+ * @see System#getProperty(String)
+ * @since 2.1
+ */
+ public static File getJavaIoTmpDir() {
+ return new File(System.getProperty(JAVA_IO_TMPDIR_KEY));
+ }
+
+ /**
+ *
+ * Decides if the Java version matches.
+ *
+ *
+ * @param versionPrefix the prefix for the java version
+ * @return true if matches, or false if not or can't determine
+ */
+ private static boolean getJavaVersionMatches(final String versionPrefix) {
+ return isJavaVersionMatch(JAVA_SPECIFICATION_VERSION, versionPrefix);
+ }
+
+ /**
+ * Decides if the operating system matches.
+ *
+ * @param osNamePrefix the prefix for the os name
+ * @param osVersionPrefix the prefix for the version
+ * @return true if matches, or false if not or can't determine
+ */
+ private static boolean getOSMatches(final String osNamePrefix, final String osVersionPrefix) {
+ return isOSMatch(OS_NAME, OS_VERSION, osNamePrefix, osVersionPrefix);
+ }
+
+ /**
+ * Decides if the operating system matches.
+ *
+ * @param osNamePrefix the prefix for the os name
+ * @return true if matches, or false if not or can't determine
+ */
+ private static boolean getOSMatchesName(final String osNamePrefix) {
+ return isOSNameMatch(OS_NAME, osNamePrefix);
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ *
+ * Gets a System property, defaulting to {@code null} if the property cannot be read.
+ *
+ *
+ * If a {@code SecurityException} is caught, the return value is {@code null} and a message is written to
+ * {@code System.err}.
+ *
+ *
+ * @param property the system property name
+ * @return the system property value or {@code null} if a security problem occurs
+ */
+ private static String getSystemProperty(final String property) {
+ try {
+ return System.getProperty(property);
+ } catch (final SecurityException ex) {
+ // we are not allowed to look at this property
+ System.err.println("Caught a SecurityException reading the system property '" + property
+ + "'; the SystemUtils property value will default to null.");
+ return null;
+ }
+ }
+
+ /**
+ *
+ * Gets the user directory as a {@code File}.
+ *
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
+ * access to the specified system property.
+ * @see System#getProperty(String)
+ * @since 2.1
+ */
+ public static File getUserDir() {
+ return new File(System.getProperty(USER_DIR_KEY));
+ }
+
+ /**
+ *
+ * Gets the user home directory as a {@code File}.
+ *
+ *
+ * @return a directory
+ * @throws SecurityException if a security manager exists and its {@code checkPropertyAccess} method doesn't allow
+ * access to the specified system property.
+ * @see System#getProperty(String)
+ * @since 2.1
+ */
+ public static File getUserHome() {
+ return new File(System.getProperty(USER_HOME_KEY));
+ }
+
+ /**
+ * Returns whether the {@link #JAVA_AWT_HEADLESS} value is {@code true}.
+ *
+ * @return {@code true} if {@code JAVA_AWT_HEADLESS} is {@code "true"}, {@code false} otherwise.
+ * @see #JAVA_AWT_HEADLESS
+ * @since 2.1
+ * @since Java 1.4
+ */
+ public static boolean isJavaAwtHeadless() {
+ return Boolean.TRUE.toString().equals(JAVA_AWT_HEADLESS);
+ }
+
+ /**
+ *
+ * Is the Java version at least the requested version.
+ *
+ *
+ * Example input:
+ *
+ *
+ * {@code 1.2f} to test for Java 1.2
+ * {@code 1.31f} to test for Java 1.3.1
+ *
+ *
+ * @param requiredVersion the required version, for example 1.31f
+ * @return {@code true} if the actual version is equal or greater than the required version
+ */
+ public static boolean isJavaVersionAtLeast(final JavaVersion requiredVersion) {
+ return JAVA_SPECIFICATION_VERSION_AS_ENUM.atLeast(requiredVersion);
+ }
+
+ /**
+ *
+ * Decides if the Java version matches.
+ *
+ *
+ * This method is package private instead of private to support unit test invocation.
+ *
+ *
+ * @param version the actual Java version
+ * @param versionPrefix the prefix for the expected Java version
+ * @return true if matches, or false if not or can't determine
+ */
+ static boolean isJavaVersionMatch(final String version, final String versionPrefix) {
+ if (version == null) {
+ return false;
+ }
+ return version.startsWith(versionPrefix);
+ }
+
+ /**
+ * Decides if the operating system matches.
+ *
+ * This method is package private instead of private to support unit test invocation.
+ *
+ *
+ * @param osName the actual OS name
+ * @param osVersion the actual OS version
+ * @param osNamePrefix the prefix for the expected OS name
+ * @param osVersionPrefix the prefix for the expected OS version
+ * @return true if matches, or false if not or can't determine
+ */
+ static boolean isOSMatch(final String osName, final String osVersion, final String osNamePrefix, final String osVersionPrefix) {
+ if (osName == null || osVersion == null) {
+ return false;
+ }
+ return isOSNameMatch(osName, osNamePrefix) && isOSVersionMatch(osVersion, osVersionPrefix);
+ }
+
+ /**
+ * Decides if the operating system matches.
+ *
+ * This method is package private instead of private to support unit test invocation.
+ *
+ *
+ * @param osName the actual OS name
+ * @param osNamePrefix the prefix for the expected OS name
+ * @return true if matches, or false if not or can't determine
+ */
+ static boolean isOSNameMatch(final String osName, final String osNamePrefix) {
+ if (osName == null) {
+ return false;
+ }
+ return osName.startsWith(osNamePrefix);
+ }
+
+ /**
+ * Decides if the operating system version matches.
+ *
+ * This method is package private instead of private to support unit test invocation.
+ *
+ *
+ * @param osVersion the actual OS version
+ * @param osVersionPrefix the prefix for the expected OS version
+ * @return true if matches, or false if not or can't determine
+ */
+ static boolean isOSVersionMatch(final String osVersion, final String osVersionPrefix) {
+ if (StringUtils.isEmpty(osVersion)) {
+ return false;
+ }
+ // Compare parts of the version string instead of using String.startsWith(String) because otherwise
+ // osVersionPrefix 10.1 would also match osVersion 10.10
+ String[] versionPrefixParts = osVersionPrefix.split("\\.");
+ String[] versionParts = osVersion.split("\\.");
+ for (int i = 0; i < Math.min(versionPrefixParts.length, versionParts.length); i++) {
+ if (!versionPrefixParts[i].equals(versionParts[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ *
+ * SystemUtils instances should NOT be constructed in standard programming. Instead, the class should be used as
+ * {@code SystemUtils.FILE_SEPARATOR}.
+ *
+ *
+ * This constructor is public to permit tools that require a JavaBean instance to operate.
+ *
+ */
+ public SystemUtils() {
+ super();
+ }
+
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ThreadUtils.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ThreadUtils.java
new file mode 100644
index 000000000..89a59cea5
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/ThreadUtils.java
@@ -0,0 +1,460 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ * Helpers for {@code java.lang.Thread} and {@code java.lang.ThreadGroup}.
+ *
+ *
+ * #ThreadSafe#
+ *
+ *
+ * @see java.lang.Thread
+ * @see java.lang.ThreadGroup
+ * @since 3.5
+ */
+public class ThreadUtils {
+
+ /**
+ * Return the active thread with the specified id if it belong's to the specified thread group.
+ *
+ * @param threadId The thread id
+ * @param threadGroup The thread group
+ * @return The thread which belongs to a specified thread group and the thread's id match the specified id.
+ * {@code null} is returned if no such thread exists
+ * @throws IllegalArgumentException if the specified id is zero or negative or the group is null
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ *
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Thread findThreadById(final long threadId, final ThreadGroup threadGroup) {
+ if (threadGroup == null) {
+ throw new IllegalArgumentException("The thread group must not be null");
+ }
+ final Thread thread = findThreadById(threadId);
+ if(thread != null && threadGroup.equals(thread.getThreadGroup())) {
+ return thread;
+ }
+ return null;
+ }
+
+ /**
+ * Return the active thread with the specified id if it belong's to a thread group with the specified group name.
+ *
+ * @param threadId The thread id
+ * @param threadGroupName The thread group name
+ * @return The threads which belongs to a thread group with the specified group name and the thread's id match the specified id.
+ * {@code null} is returned if no such thread exists
+ * @throws IllegalArgumentException if the specified id is zero or negative or the group name is null
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ *
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Thread findThreadById(final long threadId, final String threadGroupName) {
+ if (threadGroupName == null) {
+ throw new IllegalArgumentException("The thread group name must not be null");
+ }
+ final Thread thread = findThreadById(threadId);
+ if(thread != null && thread.getThreadGroup() != null && thread.getThreadGroup().getName().equals(threadGroupName)) {
+ return thread;
+ }
+ return null;
+ }
+
+ /**
+ * Return active threads with the specified name if they belong to a specified thread group.
+ *
+ * @param threadName The thread name
+ * @param threadGroup The thread group
+ * @return The threads which belongs to a thread group and the thread's name match the specified name,
+ * An empty collection is returned if no such thread exists. The collection returned is always unmodifiable.
+ * @throws IllegalArgumentException if the specified thread name or group is null
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ *
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Collection findThreadsByName(final String threadName, final ThreadGroup threadGroup) {
+ return findThreads(threadGroup, false, new NamePredicate(threadName));
+ }
+
+ /**
+ * Return active threads with the specified name if they belong to a thread group with the specified group name.
+ *
+ * @param threadName The thread name
+ * @param threadGroupName The thread group name
+ * @return The threads which belongs to a thread group with the specified group name and the thread's name match the specified name,
+ * An empty collection is returned if no such thread exists. The collection returned is always unmodifiable.
+ * @throws IllegalArgumentException if the specified thread name or group name is null
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ *
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Collection findThreadsByName(final String threadName, final String threadGroupName) {
+ if (threadName == null) {
+ throw new IllegalArgumentException("The thread name must not be null");
+ }
+ if (threadGroupName == null) {
+ throw new IllegalArgumentException("The thread group name must not be null");
+ }
+
+ final Collection threadGroups = findThreadGroups(new NamePredicate(threadGroupName));
+
+ if(threadGroups.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ final Collection result = new ArrayList();
+ final NamePredicate threadNamePredicate = new NamePredicate(threadName);
+ for(final ThreadGroup group : threadGroups) {
+ result.addAll(findThreads(group, false, threadNamePredicate));
+ }
+ return Collections.unmodifiableCollection(result);
+ }
+
+ /**
+ * Return active thread groups with the specified group name.
+ *
+ * @param threadGroupName The thread group name
+ * @return the thread groups with the specified group name or an empty collection if no such thread group exists. The collection returned is always unmodifiable.
+ * @throws IllegalArgumentException if group name is null
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ *
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Collection findThreadGroupsByName(final String threadGroupName) {
+ return findThreadGroups(new NamePredicate(threadGroupName));
+ }
+
+ /**
+ * Return all active thread groups excluding the system thread group (A thread group is active if it has been not destroyed).
+ *
+ * @return all thread groups excluding the system thread group. The collection returned is always unmodifiable.
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ *
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Collection getAllThreadGroups() {
+ return findThreadGroups(ALWAYS_TRUE_PREDICATE);
+ }
+
+ /**
+ * Return the system thread group (sometimes also referred as "root thread group").
+ *
+ * @return the system thread group
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static ThreadGroup getSystemThreadGroup() {
+ ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
+ while(threadGroup.getParent() != null) {
+ threadGroup = threadGroup.getParent();
+ }
+ return threadGroup;
+ }
+
+ /**
+ * Return all active threads (A thread is active if it has been started and has not yet died).
+ *
+ * @return all active threads. The collection returned is always unmodifiable.
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ *
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Collection getAllThreads() {
+ return findThreads(ALWAYS_TRUE_PREDICATE);
+ }
+
+ /**
+ * Return active threads with the specified name.
+ *
+ * @param threadName The thread name
+ * @return The threads with the specified name or an empty collection if no such thread exists. The collection returned is always unmodifiable.
+ * @throws IllegalArgumentException if the specified name is null
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ *
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Collection findThreadsByName(final String threadName) {
+ return findThreads(new NamePredicate(threadName));
+ }
+
+ /**
+ * Return the active thread with the specified id.
+ *
+ * @param threadId The thread id
+ * @return The thread with the specified id or {@code null} if no such thread exists
+ * @throws IllegalArgumentException if the specified id is zero or negative
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ *
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Thread findThreadById(final long threadId) {
+ final Collection result = findThreads(new ThreadIdPredicate(threadId));
+ return result.isEmpty() ? null : result.iterator().next();
+ }
+
+ /**
+ *
+ * ThreadUtils instances should NOT be constructed in standard programming. Instead, the class should be used as
+ * {@code ThreadUtils.getAllThreads()}
+ *
+ *
+ * This constructor is public to permit tools that require a JavaBean instance to operate.
+ *
+ */
+ public ThreadUtils() {
+ super();
+ }
+
+ /**
+ * A predicate for selecting threads.
+ */
+ //if java minimal version for lang becomes 1.8 extend this interface from java.util.function.Predicate
+ public interface ThreadPredicate /*extends java.util.function.Predicate*/{
+
+ /**
+ * Evaluates this predicate on the given thread.
+ * @param thread the thread
+ * @return {@code true} if the thread matches the predicate, otherwise {@code false}
+ */
+ boolean test(Thread thread);
+ }
+
+ /**
+ * A predicate for selecting threadgroups.
+ */
+ //if java minimal version for lang becomes 1.8 extend this interface from java.util.function.Predicate
+ public interface ThreadGroupPredicate /*extends java.util.function.Predicate*/{
+
+ /**
+ * Evaluates this predicate on the given threadgroup.
+ * @param threadGroup the threadgroup
+ * @return {@code true} if the threadGroup matches the predicate, otherwise {@code false}
+ */
+ boolean test(ThreadGroup threadGroup);
+ }
+
+ /**
+ * Predicate which always returns true.
+ */
+ public static final AlwaysTruePredicate ALWAYS_TRUE_PREDICATE = new AlwaysTruePredicate();
+
+ /**
+ * A predicate implementation which always returns true.
+ */
+ private final static class AlwaysTruePredicate implements ThreadPredicate, ThreadGroupPredicate{
+
+ private AlwaysTruePredicate() {
+ }
+
+ @Override
+ public boolean test(final ThreadGroup threadGroup) {
+ return true;
+ }
+
+ @Override
+ public boolean test(final Thread thread) {
+ return true;
+ }
+ }
+
+ /**
+ * A predicate implementation which matches a thread or threadgroup name.
+ */
+ public static class NamePredicate implements ThreadPredicate, ThreadGroupPredicate {
+
+ private final String name;
+
+ /**
+ * Predicate constructor
+ *
+ * @param name thread or threadgroup name
+ * @throws IllegalArgumentException if the name is {@code null}
+ */
+ public NamePredicate(final String name) {
+ super();
+ if (name == null) {
+ throw new IllegalArgumentException("The name must not be null");
+ }
+ this.name = name;
+ }
+
+ @Override
+ public boolean test(final ThreadGroup threadGroup) {
+ return threadGroup != null && threadGroup.getName().equals(name);
+ }
+
+ @Override
+ public boolean test(final Thread thread) {
+ return thread != null && thread.getName().equals(name);
+ }
+ }
+
+ /**
+ * A predicate implementation which matches a thread id.
+ */
+ public static class ThreadIdPredicate implements ThreadPredicate {
+
+ private final long threadId;
+
+ /**
+ * Predicate constructor
+ *
+ * @param threadId the threadId to match
+ * @throws IllegalArgumentException if the threadId is zero or negative
+ */
+ public ThreadIdPredicate(final long threadId) {
+ super();
+ if (threadId <= 0) {
+ throw new IllegalArgumentException("The thread id must be greater than zero");
+ }
+ this.threadId = threadId;
+ }
+
+ @Override
+ public boolean test(final Thread thread) {
+ return thread != null && thread.getId() == threadId;
+ }
+ }
+
+ /**
+ * Select all active threads which match the given predicate.
+ *
+ * @param predicate the predicate
+ * @return An unmodifiable {@code Collection} of active threads matching the given predicate
+ *
+ * @throws IllegalArgumentException if the predicate is null
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Collection findThreads(final ThreadPredicate predicate){
+ return findThreads(getSystemThreadGroup(), true, predicate);
+ }
+
+ /**
+ * Select all active threadgroups which match the given predicate.
+ *
+ * @param predicate the predicate
+ * @return An unmodifiable {@code Collection} of active threadgroups matching the given predicate
+ * @throws IllegalArgumentException if the predicate is null
+ * @throws SecurityException
+ * if the current thread cannot access the system thread group
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Collection findThreadGroups(final ThreadGroupPredicate predicate){
+ return findThreadGroups(getSystemThreadGroup(), true, predicate);
+ }
+
+ /**
+ * Select all active threads which match the given predicate and which belongs to the given thread group (or one of its subgroups).
+ *
+ * @param group the thread group
+ * @param recurse if {@code true} then evaluate the predicate recursively on all threads in all subgroups of the given group
+ * @param predicate the predicate
+ * @return An unmodifiable {@code Collection} of active threads which match the given predicate and which belongs to the given thread group
+ * @throws IllegalArgumentException if the given group or predicate is null
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Collection findThreads(final ThreadGroup group, final boolean recurse, final ThreadPredicate predicate) {
+ if (group == null) {
+ throw new IllegalArgumentException("The group must not be null");
+ }
+ if (predicate == null) {
+ throw new IllegalArgumentException("The predicate must not be null");
+ }
+
+ int count = group.activeCount();
+ Thread[] threads;
+ do {
+ threads = new Thread[count + (count / 2) + 1]; //slightly grow the array size
+ count = group.enumerate(threads, recurse);
+ //return value of enumerate() must be strictly less than the array size according to javadoc
+ } while (count >= threads.length);
+
+ final List result = new ArrayList(count);
+ for (int i = 0; i < count; ++i) {
+ if (predicate.test(threads[i])) {
+ result.add(threads[i]);
+ }
+ }
+ return Collections.unmodifiableCollection(result);
+ }
+
+ /**
+ * Select all active threadgroups which match the given predicate and which is a subgroup of the given thread group (or one of its subgroups).
+ *
+ * @param group the thread group
+ * @param recurse if {@code true} then evaluate the predicate recursively on all threadgroups in all subgroups of the given group
+ * @param predicate the predicate
+ * @return An unmodifiable {@code Collection} of active threadgroups which match the given predicate and which is a subgroup of the given thread group
+ * @throws IllegalArgumentException if the given group or predicate is null
+ * @throws SecurityException if the current thread cannot modify
+ * thread groups from this thread's thread group up to the system thread group
+ */
+ public static Collection findThreadGroups(final ThreadGroup group, final boolean recurse, final ThreadGroupPredicate predicate){
+ if (group == null) {
+ throw new IllegalArgumentException("The group must not be null");
+ }
+ if (predicate == null) {
+ throw new IllegalArgumentException("The predicate must not be null");
+ }
+
+ int count = group.activeGroupCount();
+ ThreadGroup[] threadGroups;
+ do {
+ threadGroups = new ThreadGroup[count + (count / 2) + 1]; //slightly grow the array size
+ count = group.enumerate(threadGroups, recurse);
+ //return value of enumerate() must be strictly less than the array size according to javadoc
+ } while(count >= threadGroups.length);
+
+ final List result = new ArrayList(count);
+ for(int i = 0; i < count; ++i) {
+ if(predicate.test(threadGroups[i])) {
+ result.add(threadGroups[i]);
+ }
+ }
+ return Collections.unmodifiableCollection(result);
+ }
+}
diff --git a/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Validate.java b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Validate.java
new file mode 100644
index 000000000..508845ad7
--- /dev/null
+++ b/Java-base/commons-lang/src/src/main/java/org/apache/commons/lang3/Validate.java
@@ -0,0 +1,1342 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.apache.commons.lang3;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * This class assists in validating arguments. The validation methods are
+ * based along the following principles:
+ *
+ * An invalid {@code null} argument causes a {@link NullPointerException}.
+ * A non-{@code null} argument causes an {@link IllegalArgumentException}.
+ * An invalid index into an array/collection/map/string causes an {@link IndexOutOfBoundsException}.
+ *
+ *
+ * All exceptions messages are
+ * format strings
+ * as defined by the Java platform. For example:
+ *
+ *
+ * Validate.isTrue(i > 0, "The value must be greater than zero: %d", i);
+ * Validate.notNull(surname, "The surname must not be %s", null);
+ *
+ *
+ * #ThreadSafe#
+ * @see java.lang.String#format(String, Object...)
+ * @since 2.0
+ */
+public class Validate {
+
+ private static final String DEFAULT_NOT_NAN_EX_MESSAGE =
+ "The validated value is not a number";
+ private static final String DEFAULT_FINITE_EX_MESSAGE =
+ "The value is invalid: %f";
+ private static final String DEFAULT_EXCLUSIVE_BETWEEN_EX_MESSAGE =
+ "The value %s is not in the specified exclusive range of %s to %s";
+ private static final String DEFAULT_INCLUSIVE_BETWEEN_EX_MESSAGE =
+ "The value %s is not in the specified inclusive range of %s to %s";
+ private static final String DEFAULT_MATCHES_PATTERN_EX = "The string %s does not match the pattern %s";
+ private static final String DEFAULT_IS_NULL_EX_MESSAGE = "The validated object is null";
+ private static final String DEFAULT_IS_TRUE_EX_MESSAGE = "The validated expression is false";
+ private static final String DEFAULT_NO_NULL_ELEMENTS_ARRAY_EX_MESSAGE =
+ "The validated array contains null element at index: %d";
+ private static final String DEFAULT_NO_NULL_ELEMENTS_COLLECTION_EX_MESSAGE =
+ "The validated collection contains null element at index: %d";
+ private static final String DEFAULT_NOT_BLANK_EX_MESSAGE = "The validated character sequence is blank";
+ private static final String DEFAULT_NOT_EMPTY_ARRAY_EX_MESSAGE = "The validated array is empty";
+ private static final String DEFAULT_NOT_EMPTY_CHAR_SEQUENCE_EX_MESSAGE =
+ "The validated character sequence is empty";
+ private static final String DEFAULT_NOT_EMPTY_COLLECTION_EX_MESSAGE = "The validated collection is empty";
+ private static final String DEFAULT_NOT_EMPTY_MAP_EX_MESSAGE = "The validated map is empty";
+ private static final String DEFAULT_VALID_INDEX_ARRAY_EX_MESSAGE = "The validated array index is invalid: %d";
+ private static final String DEFAULT_VALID_INDEX_CHAR_SEQUENCE_EX_MESSAGE =
+ "The validated character sequence index is invalid: %d";
+ private static final String DEFAULT_VALID_INDEX_COLLECTION_EX_MESSAGE =
+ "The validated collection index is invalid: %d";
+ private static final String DEFAULT_VALID_STATE_EX_MESSAGE = "The validated state is false";
+ private static final String DEFAULT_IS_ASSIGNABLE_EX_MESSAGE = "Cannot assign a %s to a %s";
+ private static final String DEFAULT_IS_INSTANCE_OF_EX_MESSAGE = "Expected type: %s, actual: %s";
+
+ /**
+ * Constructor. This class should not normally be instantiated.
+ */
+ public Validate() {
+ super();
+ }
+
+ // isTrue
+ //---------------------------------------------------------------------------------
+
+ /**
+ * Validate that the argument condition is {@code true}; otherwise
+ * throwing an exception with the specified message. This method is useful when
+ * validating according to an arbitrary boolean expression, such as validating a
+ * primitive number or using your own custom validation expression.
+ *
+ * Validate.isTrue(i > 0.0, "The value must be greater than zero: %d", i);
+ *
+ * For performance reasons, the long value is passed as a separate parameter and
+ * appended to the exception message only in the case of an error.
+ *
+ * @param expression the boolean expression to check
+ * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
+ * @param value the value to append to the message when invalid
+ * @throws IllegalArgumentException if expression is {@code false}
+ * @see #isTrue(boolean)
+ * @see #isTrue(boolean, String, double)
+ * @see #isTrue(boolean, String, Object...)
+ */
+ public static void isTrue(final boolean expression, final String message, final long value) {
+ if (expression == false) {
+ throw new IllegalArgumentException(String.format(message, Long.valueOf(value)));
+ }
+ }
+
+ /**
+ * Validate that the argument condition is {@code true}; otherwise
+ * throwing an exception with the specified message. This method is useful when
+ * validating according to an arbitrary boolean expression, such as validating a
+ * primitive number or using your own custom validation expression.
+ *
+ * Validate.isTrue(d > 0.0, "The value must be greater than zero: %s", d);
+ *
+ * For performance reasons, the double value is passed as a separate parameter and
+ * appended to the exception message only in the case of an error.
+ *
+ * @param expression the boolean expression to check
+ * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
+ * @param value the value to append to the message when invalid
+ * @throws IllegalArgumentException if expression is {@code false}
+ * @see #isTrue(boolean)
+ * @see #isTrue(boolean, String, long)
+ * @see #isTrue(boolean, String, Object...)
+ */
+ public static void isTrue(final boolean expression, final String message, final double value) {
+ if (expression == false) {
+ throw new IllegalArgumentException(String.format(message, Double.valueOf(value)));
+ }
+ }
+
+ /**
+ * Validate that the argument condition is {@code true}; otherwise
+ * throwing an exception with the specified message. This method is useful when
+ * validating according to an arbitrary boolean expression, such as validating a
+ * primitive number or using your own custom validation expression.
+ *
+ *
+ * Validate.isTrue(i >= min && i <= max, "The value must be between %d and %d", min, max);
+ * Validate.isTrue(myObject.isOk(), "The object is not okay");
+ *
+ * @param expression the boolean expression to check
+ * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
+ * @param values the optional values for the formatted exception message, null array not recommended
+ * @throws IllegalArgumentException if expression is {@code false}
+ * @see #isTrue(boolean)
+ * @see #isTrue(boolean, String, long)
+ * @see #isTrue(boolean, String, double)
+ */
+ public static void isTrue(final boolean expression, final String message, final Object... values) {
+ if (expression == false) {
+ throw new IllegalArgumentException(String.format(message, values));
+ }
+ }
+
+ /**
+ * Validate that the argument condition is {@code true}; otherwise
+ * throwing an exception. This method is useful when validating according
+ * to an arbitrary boolean expression, such as validating a
+ * primitive number or using your own custom validation expression.
+ *
+ *
+ * Validate.isTrue(i > 0);
+ * Validate.isTrue(myObject.isOk());
+ *
+ * The message of the exception is "The validated expression is
+ * false".
+ *
+ * @param expression the boolean expression to check
+ * @throws IllegalArgumentException if expression is {@code false}
+ * @see #isTrue(boolean, String, long)
+ * @see #isTrue(boolean, String, double)
+ * @see #isTrue(boolean, String, Object...)
+ */
+ public static void isTrue(final boolean expression) {
+ if (expression == false) {
+ throw new IllegalArgumentException(DEFAULT_IS_TRUE_EX_MESSAGE);
+ }
+ }
+
+ // notNull
+ //---------------------------------------------------------------------------------
+
+ /**
+ * Validate that the specified argument is not {@code null};
+ * otherwise throwing an exception.
+ *
+ *
Validate.notNull(myObject, "The object must not be null");
+ *
+ * The message of the exception is "The validated object is
+ * null".
+ *
+ * @param the object type
+ * @param object the object to check
+ * @return the validated object (never {@code null} for method chaining)
+ * @throws NullPointerException if the object is {@code null}
+ * @see #notNull(Object, String, Object...)
+ */
+ public static T notNull(final T object) {
+ return notNull(object, DEFAULT_IS_NULL_EX_MESSAGE);
+ }
+
+ /**
+ * Validate that the specified argument is not {@code null};
+ * otherwise throwing an exception with the specified message.
+ *
+ *
Validate.notNull(myObject, "The object must not be null");
+ *
+ * @param the object type
+ * @param object the object to check
+ * @param message the {@link String#format(String, Object...)} exception message if invalid, not null
+ * @param values the optional values for the formatted exception message
+ * @return the validated object (never {@code null} for method chaining)
+ * @throws NullPointerException if the object is {@code null}
+ * @see #notNull(Object)
+ */
+ public static