<document xmlns="http://maven.apache.org/changes/1.0.0">
	<properties>
		<title>KDGCommons Change Log</title>
	</properties>

    <body>
        <release version="1.0.17" date="2019-08-03"
            description="TBD">
            <action dev='kdgregory' type='add'>
                Counters: add toString()
            </action>
            <action dev='kdgregory' type='add'>
                JDBCUtil: add functions to support simple SQL operations
            </action>
            <action dev='kdgregory' type='update'>
                CollectionUtil.last(): optimization for linked lists
            </action>
            <action dev='kdgregory' type='update'>
                Counters: work-around signature change in ConcurrentHashMap
                (was producing an invalid artifact when compiling with JDK 8)
            </action>
            <action dev='kdgregory' type='update'>
                HashMultimap: Behavior enum was not public
            </action>
            <action dev='kdgregory' type='update'>
                SelfMock: retain invocation arguments
            </action>
        </release>

        <release version="1.0.16" date="2018-07-22"
            description="grab-bag of additions">
            <action dev='kdgregory' type='add'>
                ClassUtil.getFieldValue(): retrieves a field's value from wherever it's defined in
                the class hierarchy
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.isEmpty(), isNotEmpty(): now accept Maps
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.partition(): breaks a passed collection into a list of max-size lists
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.submap(): extracts mappings for a set of keys.
            </action>
            <action dev='kdgregory' type='add'>
                NumericAsserts: add assertApproximate() for long and double values
            </action>
            <action dev='kdgregory' type='add'>
                NumericAsserts.assertInRange(): allows caller to assert that the actual value is
                within an arbitrary range +/- of the expected value
            </action>
            <action dev='kdgregory' type='add'>
                StringAsserts.assertNotEmpty()
            </action>
            <action dev='kdgregory' type='add'>
                SelfMock: a reflection-based mock object that invokes methods on itself; used to mock
                a portion of an interface without a long if-else chain in the invocation handler
            </action>
        </release>

        <release version="1.0.15" date="2017-01-22"
            description="A variety of new functions, across utils">
            <action dev='kdgregory' type='add'>
                BufferUtil.toArray: returns the entire contents of a ByteBuffer as an array
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.asMap(): produce a HashMap from a list of values
            </action>
            <action dev='kdgregory' type='update'>
                CollectionUtil.asSet(): be explicit that we return a HashSet
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.cast(): add variant for maps
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.getVia(): traverses hierarchies of maps, lists, and arrays
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.putIf(), putIfNotNull(): conditional stores for maps
            </action>
            <action dev='kdgregory' type='add'>
                ReadThroughCache: a size-limited LRU cache that uses a retriever function to load values
            </action>
            <action dev='kdgregory' type='add'>
                StringUtil.substr: flexible substring that's null-safe, bounds-safe, and allows
                selection of the right side of the string
            </action>
        </release>

        <release version="1.0.14" date="2014-01-21"
            description="Multiple additions">
            <action dev='kdgregory' type='add'>
                ArrayAsserts: JUnit assertions for primitive arrays
            </action>
            <action dev='kdgregory' type='add'>
                Base64Codec: translates between byte[] and String using a Base-64 representation
            </action>
            <action dev='kdgregory' type='add'>
                HexCodec: translates between byte[] and String using a hex representation
            </action>
            <action dev='kdgregory' type='add'>
                CharSequenceUtil: utility methods common to all character sequences; initial methods
                are startsWith(), endsWith(), and containsAt()
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.compare(): compares the elements of two collections in iterator order
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.putIfAbsent(Map,Map): adds all mappings not present in base
            </action>
            <action dev='kdgregory' type='add'>
                Object.compare(): null-safe comparison, where null is optionally low or high when
                compared to not-null
            </action>
            <action dev='kdgregory' type='add'>
                StringUtil.valueOf(): a replacement for String.valueOf() that returns an empty string
                when passed null
            </action>
            <action dev='kdgregory' type='add'>
                Tuple2, ComparableTuple2: parameterized holder for a pair of values
            </action>
            <action dev='kdgregory' type='add'>
                UnclosingInputStream, UnclosingOutputStream: stream decorators that silently ignore
                close(); used to multiplex output onto a single stream
            </action>
            <action dev='kdgregory' type='update'>
                Base64Converter: deprecated in favor of Base64Codec
            </action>
        </release>

        <release version="1.0.13" date="2013-08-29"
            description="Collections, Serialization">
            <action dev='kdgregory' type='add'>
                CollectionUtil: add first() and .last(): null-safe, empty-safe retrieval of first or last
                element of a list
            </action>
            <action dev='kdgregory' type='add'>
                Added equals() and hashCode() to DefaultMap, Hashmultimap
            </action>
            <action dev='kdgregory' type='update'>
                The following classes are now Serializable: CompoundKey, DefaultMap, HashMultimap, NameValue
            </action>
        </release>

        <release version="1.0.12" date="2013-06-30"
            description="Introspection">
            <action dev='kdgregory' type='add'>
                CollectionUtil.addIfNotNull(): used to progressively build a collection where
                the source data may use null as a flag value
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.putIfAbsent(): a simple way to add default values to maps
            </action>
            <action dev='kdgregory' type='add'>
                StringUtil.length(): a null-safe length check (although StringUtil.isBlang()) is a
                better choice in most situations)
            </action>
            <action dev='kdgregory' type='update'>
                Introspection and IntrospectionCache now allow an optional setAccessible(true)
                on introspected methods
            </action>
        </release>

        <release version="1.0.11" date="2013-06-15"
            description="Lang, Collections">
            <action dev='kdgregory' type='add'>
                CollectionUtil.addIfNotNull(): used to progressively build a collection where
                the source data may use null as a flag value
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.filter(): the third common list-processing higher-order function
            </action>
            <action dev='kdgregory' type='add'>
                ObjectUtil.equals() variants that compare int and long with their object
                wrappers, to avoid null pointer exceptions from auto-unboxing
            </action>
        </release>

        <release version="1.0.10" date="2013-05-26"
            description="Collections">
            <action dev='kdgregory' type='add'>
                CollectionUtil.map() / reduce(): because every utilities library needs these
            </action>
            <action dev='kdgregory' type='add'>
                Counters: a threadsafe map of longs, used to summarize a stream of data
            </action>
        </release>

        <release version="1.0.9" date="2013-04-07"
            description="Collections, Lang">
            <action dev='kdgregory' type='add'>
                EnumerationIterable: allows old-style enumerations to be used in a for-each loop
            </action>
            <action dev='kdgregory' type='add'>
                IteratorIterable: allows arbitrary iterators to be used in a for-each loop
            </action>
            <action dev='kdgregory' type='add'>
                ClassUtil.getPrimitiveType(): returns the TYPE value for primitive wrapper instances
            </action>
            <action dev='kdgregory' type='add'>
                ClassUtil.getDeclaredMethodsByAccess(): slices and dices the result of Class.getDeclaredMethods()
            </action>
            <action dev='kdgregory' type='add'>
                ClassUtil.getVisibleMethods(), ClassUtil.getVisibleMethodMap(): returns all methods that a given
                class either declares or inherits from ancestors
            </action>
            <action dev='kdgregory' type='add'>
                ClassUtil.getBestMethod(): returns compiler's method selection rules to runtime arguments
            </action>
            <action dev='kdgregory' type='add'>
                StringUtil.trimToNull(): trim that produces a flag value on blank string
            </action>
            <action dev='kdgregory' type='update'>
                ClassUtil.getAnnotatedMethods(): now uses getVisibleMethods()
            </action>
            <action dev='kdgregory' type='update'>
                ClassUtil.getAllMethods(): deprecated in favor of getVisibleMethods()
            </action>
        </release>

        <release version="1.0.8" date="2013-02-16"
            description="Collections, IO, Utils">
            <action dev='kdgregory' type='add'>
                SimpleCLIParser: processes an argument vector, extracting recognized options
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.addIf(): optionally adds an element to a collection
            </action>
            <action dev='kdgregory' type='add'>
                IOUtil.skipFully(): offers a higher level of skipping than InputStream.skip()
            </action>
            <action dev='kdgregory' type='add'>
                StringUtil.equalOrEmpty(): equality test where null is treated as an empty string
            </action>
        </release>

        <release version="1.0.7" date="2012-08-26"
            description="Collections, IO">
            <action dev='kdgregory' type='add'>
                CollectionUtil.combine(): combines collections, returning result
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.isEmpty(), isNotEmpty(): null-safe tests for collection contents
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.defaultIfNull(): enables a null-safe for loop without explicit
                test/replace (applies to any iterable)
            </action>
            <action dev='kdgregory' type='add'>
                CollectionUtil.defaultIfEmpty(): used to eliminate "if for action else action"
                constructs
            </action>
            <action dev='kdgregory' type='update'>
                IOUtil.createTempFile(InputStream): now closes stream after copy
            </action>
            <action dev='kdgregory' type='update'>
                This library no longer establishes a transitive dependency on JUnit 3.8.x. If you
                use the assertion classes, you will need to provide your own JUnit dependency
            </action>
        </release>

        <release version="1.0.6" date="2012-06-30"
            description="Lang">
            <action dev='kdgregory' type='add'>
                ClassUtil.internalNameToExternal(): turns the type names from reflective
                signatures into actual classes
            </action>
            <action dev='kdgregory' type='add'>
                ObjectUtil.defaultValue(): replaces nulls with a default value, either literal or
                created from a factory
            </action>
            <action dev='kdgregory' type='add'>
                StringUtil.extractLeft(), extractRight(), extractLeftOfLast(), extractRightOfLast():
                methods to partition a string around a delimiter
            </action>
            <action dev='kdgregory' type='add'>
                StringUtil.isIn(): tests a string against multiple candidates
            </action>
            <action dev='kdgregory' type='add'>
                StringBuilderUtil.appendUnless(): used to build up argument lists, where a comma
                goes before every element but the first
            </action>
        </release>

        <release version="1.0.5" date="2012-05-17"
            description="Beans, Collections, Threads">
            <action dev='kdgregory' type='add'>
                Introspection, IntrospectionCache: a replacement for the JDK's introspector;
                originally written for PracticalXml
            </action>
            <action dev='kdgregory' type='add'>
                MapBuilder: create and populate a Map in one expression
            </action>
            <action dev='kdgregory' type='add'>
                NamedThreadFactory: allows thread pools to name their threads
            </action>
            <action dev='kdgregory' type='add'>
                ThreadUtil.sleepQuietly(): catches and ignores InterruptedException
            </action>
        </release>

        <release version="1.0.4" date="2012-04-28"
            description="Buffer, Lang, IO">
            <action dev='kdgregory' type='add'>
                ClassUtil: utilities to muck with Class objects
            </action>
            <action dev='kdgregory' type='add'>
                IOUtil.readFully(): actually does what everyone things InputStream.read() does
            </action>
            <action dev='kdgregory' type='add'>
                UnreachableCodeException: a trap for branches that should never execute
            </action>
            <action dev='kdgregory' type='update'>
                ByteArray: String conversions now enforce 8-bit character limitation
            </action>
            <action dev='kdgregory' type='update'>
                ByteArray: fixed bug in remove()
            </action>
        </release>

        <release version="1.0.3" date="2012-04-22"
            description="Collections">
            <action dev='kdgregory' type='add'>
                CollectionUtil.filter(): produces one list from another by applying a regex
            </action>
        </release>

        <release version="1.0.2" date="2012-04-16"
            description="Collections, Html, IO">
            <action dev='kdgregory' type='update'>
                HtmlUtil.escape(): bugfix for escaped single quotes; add escaping of all non-ASCII characters
            </action>
            <action dev='kdgregory' type='update'>
                CollectionUtil.join(): turns a collection into a string, with separator
            </action>
            <action dev='kdgregory' type='add'>
                IOUtil.copy(): copies input stream to output stream; exists to eliminate dependencies
            </action>
            <action dev='kdgregory' type='add'>
                IOUtil.createTempFile(): variant that will fill file from InputStream
            </action>
        </release>

        <release version="1.0.1" date="2011-12-29"
            description="Collections, Html">
            <action dev='kdgregory' type='add'>
                CombiningIterable: use a single loop to iterate multiple collections
            </action>
            <action dev='kdgregory' type='update'>
                HtmlUtil.escape(): bugfix for escaped single quotes; add escaping of all non-ASCII characters
            </action>
        </release>

        <release version="1.0.0" date="2011-08-27" description="Initial public release"/>
	</body>
</document>
