Git Product home page Git Product logo

unij's Introduction

UniJ: Universal JDK 9+ API Facade

Build (Linux) Build (Windows) Code coverage Codacy grade

Maven Central Javadocs Semantic Versioning Automated Release Notes by gren

Introduction

UniJ targets JDK 8 and is a facade of:

  1. unmodifiable List/Set/Map factory methods (equivalent to those introduced in JDK 9+)

  2. some new Collector providers (equivalent to those introduced in JDK 9+)

UniJ provides a facade of above-mentioned methods in a similar way that SLF4J (Simple Logging Facade for Java) provides a facade of logging. In both cases, there is an API that can be implemented in many different ways and then be injected at runtime as a Java service.

UniJ consists of three key parts described further on: its API, its bindings, and its bundles.

Note: if you look for a specific UniJ project, consult UniJ project layout.

Analogy

UniJ is to new parts of JDK 9+ API what SLF4J is to logging API — a facade.

Quick Example

JDK 9+
Set<Integer> set = Set.of(1, 2);
List<Integer> list = List.of(1, 2, 1);
Map<Integer, String> map = Map.of(1, "a", 2, "b");

Set.copyOf(list); // ⇒ [1, 2]
Set.of(1, 2, 1); // throws "duplicate element" exception
Set.of(1, 2, null); // throws null-pointer exception
UniJ (JDK 8+)
Set<Integer> set = UniSets.of(1, 2);
List<Integer> list = UniLists.of(1, 2, 1);
Map<Integer, String> map = UniMaps.of(1, "a", 2, "b");

UniSets.copyOf(list); // ⇒ [1, 2]
UniSets.of(1, 2, 1); // throws "duplicate element" exception
UniSets.of(1, 2, null); // throws null-pointer exception

Notes

  1. UniJ is meant only as a facade of the official JDK APIs. UniJ will not introduce any APIs of its own design. UniJ may only introduce new APIs that directly correspond to APIs in the latest stable release of the JDK (currently, it's JDK 13).

  2. UniJ is also a partial:

Method Summary

JDK 9+UniJ (JDK 8+)
type static method name type
List
Set
of, copyOf UniLists
UniSets
Map of, copyOf,
entry, ofEntries
UniMaps
Collectors toUnmodifiableList
toUnmodifiableSet
toUnmodifiableMap
filtering
flatMapping
UniCollectors

Motivation

This library has been designed primarily for:

  1. End Users Stuck on JDK 8
  2. Libraries Targeting JDK 8

End Users Stuck on JDK 8

If you're stuck on JDK 8, you can't use JDK 9+'s new methods like List.of, etc.

However, by adding a dependency on a UniJ bundle of your choosing (plus some optional extra dependencies), you can enjoy a JDK 11-like API on JDK 8!

See:

Libraries Targeting JDK 8

If you maintain a library targeting JDK 8, you can't use JDK 9+'s new methods like List.of, etc.

However, by adding a dependency on UniJ User API, you can program to JDK 11-like API!

Note: your users will have to provide implementations of the above-mentioned API (as per Usage for End Users).

See:

API

UniJ has two kind of APIs:

  • User API: utility classes (this is what the user interacts with)
  • Service API: interfaces (this is what the service provider implements)

The call chain looks as follows:

end user ⟷ User API ⟷ Service API ⟷ service provider

In other words, the end user isn't aware of the Service API, and the service provider isn't aware of the User API.

User API

The User API is defined in pl.tlinkowski.unij.api and consists of the following utility classes: UniLists, UniSets, UniMaps and UniCollectors (see Method Summary for details).

This API has strict equivalence to the corresponding JDK API (see API Specification for details).

Service API

Disclaimer: As an end user, you don't need to be concerned with this API.

UniJ Service API is defined in pl.tlinkowski.unij.service.api and consists of the following interfaces:

A module providing implementations of one or more of these interfaces constitutes a binding.

API Specification

UniJ APIs come with a detailed specification for the Service API interfaces. The specification is based on the contract of the original JDK API (expressed mostly in JavaDoc), and tries to follow it as close as possible.

The focal points of the specification are:

  • null treatment (no nulls allowed)
  • duplicate handling (e.g. no duplicates allowed in of methods of UniSets and UniMaps)
  • consistency (e.g. only one empty collection instance)

The specification is fully expressed as the following Spock test classes defined pl.tlinkowski.unij.test:

Read the source of the Spock tests linked above to see what every UniJ binding guarantees.

Bindings

A binding is simply a library with implementation(s) of the Service API.

Note that UniJ supports multiple bindings of the same type at runtime.

Predefined Bindings

UniJ comes with a number of predefined bindings, which can all be found under subprojects/bindings.

Collection Factory API Bindings

UniJ currently provides four types of Collection factory API bindings:

  1. JDK 10 (pl.tlinkowski.unij.service.collect.jdk10)

  2. JDK 8 (pl.tlinkowski.unij.service.collect.jdk8)

  3. Guava (pl.tlinkowski.unij.service.collect.guava)

  4. Eclipse Collections (pl.tlinkowski.unij.service.collect.eclipse)

Miscellaneous API Bindings

UniJ currently provides two types of miscellaneous API bindings:

  1. JDK 11 (pl.tlinkowski.unij.service.misc.jdk11)

  2. JDK 8 (pl.tlinkowski.unij.service.misc.jdk8)

Custom Bindings

Instead of any of the predefined bindings mentioned above, you can create and depend on a custom binding.

See:

Bundles

A UniJ bundle is a module having no source (save for its module-info.java) and depending on the following three modules:

  1. pl.tlinkowski.unij.api module (transitive dependency)
  2. Collection factory API binding (= one of pl.tlinkowski.unij.service.collect.___ modules)
  3. miscellaneous API binding (= one of pl.tlinkowski.unij.service.misc.___ modules)

Predefined Bundles

Currently, UniJ provides the following four bundles:

  1. JDK 11 bundle (pl.tlinkowski.unij.bundle.jdk11), made of:

  2. pure JDK 8 bundle (pl.tlinkowski.unij.bundle.jdk8), made of:

  3. Guava on JDK 8 bundle (pl.tlinkowski.unij.bundle.guava_jdk8), made of:

  4. Eclipse Collections on JDK 8 bundle (pl.tlinkowski.unij.bundle.eclipse_jdk8), made of:

Usage

See Usage document.

Extra Information

See Extra Information document.

Questions & Answers

See Q&A document.

Changelog

See Changelog document.

Requirements

Usage: JDK 8+.

Building: Gradle 5+, JDK 11+.

About the Author

See my webpage (tlinkowski.pl) or find me on Twitter (@t_linkowski).

unij's People

Contributors

tlinkowski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

unij's Issues

Support loading priority for UniJ services

If it so happens that there's more than one UniJ service, they should be selected according to some priority.

Options:

  • priority inside an annotation, e.g. @UniJService(priority = 10)
  • priority as configuration, e.g. in a ".properties" file:
    service1.priority = 10
    service2.priority = 20
    

Blocked by #18.

Create UnmodifiableMapFactory and related classes

  • interface UnmodifiableMapFactory
  • abstract test AbstractUnmodifiableMapFactorySpec in unij-test
  • JDK10 implementation Jdk10UnmodifiableMapFactory
  • JDK10 test Jdk10UnmodifiableMapFactorySpec
  • add UniMaps utility class
  • add UniMapsSpec test

Change artifact names to module names

Apply @sormuras' naming convention to this project:

  • unij-api -> pl.tlinkowski.unij.api
  • unij-bundle-eclipse-jdk8 -> pl.tlinkowski.unij.bundle.eclipse_jdk8
  • unij-bundle-guava-jdk8 -> pl.tlinkowski.unij.bundle.guava_jdk8
  • unij-bundle-jdk11 -> pl.tlinkowski.unij.bundle.jdk11
  • unij-bundle-jdk8 -> pl.tlinkowski.unij.bundle.jdk8
  • unij-collect-eclipse -> pl.tlinkowski.unij.service.collect.eclipse
  • unij-collect-guava -> pl.tlinkowski.unij.service.collect.guava
  • unij-collect-jdk10 -> pl.tlinkowski.unij.service.collect.jdk10
  • unij-collect-jdk8 -> pl.tlinkowski.unij.service.collect.jdk8
  • unij-misc-jdk11 -> pl.tlinkowski.unij.service.misc.jdk11
  • unij-misc-jdk8 -> pl.tlinkowski.unij.service.misc.jdk8
  • unij-service-api -> pl.tlinkowski.unij.service.api
  • unij-test -> pl.tlinkowski.unij.test

Related to tlinkowski/tlinkowski-superpom#64.

Architecture improvements

Make the architecture depend on two parts - "collect" and "misc":

  • rename unij-core to unij-api
  • extract unij-collect-jdk10 and unij-misc-jdk11 from unij-jdk11; leave unij-bundle-jdk11 as simple aggregation
  • extract unij-collect-jdk8 and unij-misc-jdk8 from unij-jdk8; leave unij-bundle-jdk8 as simple aggregation
  • rename unij-guava to unij-collect-guava
  • rename unij-eclipse to unij-collect-eclipse

Fix `module-info.java` for `unij-bundle-*`

Find out if module-info.java in unij-bundle-* should declare uses. For sure, module-info.java should somehow reflect the runtimeOnly dependency we have on unij-collect-* and unij-misc-*.

Related to #40.

Create MiscellaneousApiProvider and related classes

  • interface MiscellaneousApiProvider
  • abstract test AbstractMiscellaneousApiProviderSpec in unij-test
  • JDK11 implementation Jdk11MiscellaneousApiProvider
  • JDK11 test Jdk11MiscellaneousApiProviderSpec
  • add methods to UniCollectors class
  • add feature methods to UniCollectorsSpec class

[unij-test] Tighten the Spock specs

We currently don't yet test if:

  1. null elements are indeed disallowed in collections (all currently tested methods, as parametrized tests)
  2. duplicate keys in MapProvider.of() and MapProvider.ofEntries() throw errors
  3. factory.of() returns the same instance as empty.collect(factory.collector()), factory.copyOf() and factory.of(array)

There's probably more (read the JDK's unmodifiable List/Set/Map specs to discover).

Add tests for modulepath service registration

Currently, our specs only test if a service is properly registered on classpath ("proper service is registered on classpath"). It's easy to check, because we're testing on classpath only (due to Groovy 2). However, we should find some way to also test if a service is properly registered on modulepath (and generally test everything on modulepath too - should be possible with Groovy 3).

Clean up `README.md`

  • shorter
  • cleaner layout ("For End User", "For Library Maintainer", "For Binding Provider" sections?)
  • perhaps separated into more files?
  • add table of contents

Create UnmodifiableSetFactory and related classes

  • interface UnmodifiableSetFactory
  • abstract test AbstractUnmodifiableSetFactorySpec in unij-test
  • JDK10 implementation Jdk10UnmodifiableSetFactory
  • JDK10 test Jdk10UnmodifiableSetFactorySpec
  • add UniSets utility class
  • add UniSetsSpec test

Introduce "bundle" modules

In spirit of "convention over configuration", "bundle" modules have no own source code, and simply aggregate other modules:

  • bundle-jdk8: collect-jdk8 + misc-jdk8
  • bundle-jdk11: collect-jdk10 + misc-jdk11 (this bundle would make sense only when using a library based on unij-api)
  • bundle-guava-jdk8: collect-guava + misc-jdk8
  • bundle-guava-jdk11: collect-guava + misc-jdk11
  • bundle-eclipse-jdk8: collect-eclipse + misc-jdk8
  • bundle-eclipse-jdk11: collect-eclipse + misc-jdk11

Other bundles can be added per request.

Related to #31.

Can't sync to Maven Central

Maven Central reports missing Javadoc JARs in all modules.

Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.service.collect.jdk8/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.service.collect.jdk10/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.bundle.guava_jdk8/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.service.api/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.bundle.eclipse_jdk8/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.service.misc.jdk11/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.api/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.bundle.jdk8/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.service.misc.jdk8/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.service.collect.eclipse/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.test/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.service.collect.guava/0.1.0'
Missing: no javadoc jar found in folder '/pl/tlinkowski/unij/pl.tlinkowski.unij.bundle.jdk11/0.1.0'
Dropping existing partial staging repository.

Related to tlinkowski/basic-annotations#13.

Add sample projects

  • pl.tlinkowski.unij.sample.enduser
  • pl.tlinkowski.unij.sample.lib
  • pl.tlinkowski.unij.sample.lib.usage.eclipse
  • pl.tlinkowski.unij.sample.lib.usage.guava
  • pl.tlinkowski.unij.sample.lib.usage.jdk8
  • pl.tlinkowski.unij.sample.lib.usage.jdk11

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.