/type-map

TypeMap and TypeConverter for a dynamic, extendable, high-performance type conversion library that's native-ready for GraalVM. This robust Java utility provides type-safe retrieval and conversion, leveraging ConcurrentHashMap for thread-safe operations without reflection.

Primary LanguageJavaApache License 2.0Apache-2.0

TypeMap & TypeList incl. TypeConverter

Build Maintainable Coverage Issues Commit Dependencies License Central Tag Javadoc Size Label Label

Introduction

In modern Java development, managing data types efficiently and effectively can be a complex task, especially when dealing with dynamic data sources or preparing for GraalVM native compilation. Our TypeMap & TypeList library, equipped with the powerful TypeConverter and JsonConverter, is engineered to simplify these challenges. It's designed for developers who seek a hassle-free way to handle diverse data types and conversions, enabling you to focus more on business logic rather than boilerplate code.

Motivation

Working with type conversions in Java, I frequently encountered libraries that were either heavy on reflection, consumed substantial memory, or were cumbersome to extend. This inspired me to create a solution that's lightweight, easy to understand, and simple to enhance, all without any "magic" under the hood.

Benefits

  • Pure Java: No external dependencies for a lightweight integration.
  • Functional Design: Embraces modern Java functional paradigms.
  • No Reflection: Ensures compatibility with GraalVM native images.
  • High Performance: Tailored for efficiency in intensive workloads.
  • Dynamic & Extendable: Simplifies adding new type conversions.
  • Type Safety: Utilizes Java generics for compile-time type checking.
  • Lazy Loading: Conversions occur only when needed, enhancing performance and reducing memory usage.

Classes

Usage

Basics

    TypeMap typeMap = new TypeMap().putReturn(new Date(), "myTime");
    OffsetDateTime timeValue = typeMap.asOffsetDateTime("myTime");
    OffsetDateTime timeValue = typeMap.as(OffsetDateTime.class, "myTime");
    TypeList typeList=new TypeList().addd(new Date());
    OffsetDateTime timeValue = typeMap.asOffsetDateTime(0);
    OffsetDateTime timeValue = typeMap.as(OffsetDateTime.class, 0);

Collections

    TypeMap typeMap=new TypeMap().putReturn("myKey",new String[]{"1","2","3"});

    TypeList list1=typeMap.asList("myKey");
    Integer numberThree=typeList.asList("myKey").as(2,Integer.class)
    List<Integer> list2=typeMap.asList(Integer.class, "myKey");
    List<Integer> list3=typeMap.asList(ArrayList::new,Integer.class, "myKey");
    TypeList typeList=new TypeList().addd(new String[]{"1","2","3"});

    TypeList list1=typeList.asList(0);
    Integer numberThree=typeList.asList(0).asIntList(2)
    List<Integer> list2=typeList.asIntList(0);
    List<Integer> list3=typeList.asList(Integer::new,Integer.class, 0);

Maps

    TypeMap typeMap=new TypeMap().putReturn("mykey",Map.of(6,new Date()));

LinkedTypeMap map1 = typeMap.asMap("myKey");
Map<Long, Instant> map2 = typeMap.asMap(Long.class, Instant.class, "mykey")
Map<Long, Instant> map2 = typeMap.asMap(() -> new HashMap<>(), Long.class, "mykey")
    TypeList typeLst = new TypeList().addd(Map.of(6, new Date()));

LinkedTypeMap map1 = typeLst.asMap(0);
Map<Long, Instant> map2 = typeLst.asMap(Long.class, Instant.class, 0);
Map<Long, Instant> map3 = typeLst.asMap(HashMap::new, Long.class, Instant.class, 0);

Json & XML

JsonEncoder & JsonDecoder is used internally

    final String jsonString =
    "{\n"
        + "  \"outerMap\": {\n"
        + "    \"innerMap\": {\n"
        + "      \"timestamp\": 1800000000000,\n"
        + "    },\n"
        + "    \"myList\": [\"BB\",1,true,null,1.2]\n"
        + "  }\n"
        + "}";

final TypeMap jsonMap = new TypeMap(jsonString);
// or xmlTypeOf(xmlString); jsonTypeOf(jsonOrXml); new TypeList(jsonOrXmlString);

final LinkedTypeMap map1 = jsonMap.asMap("outerMap", "innerMap")
final Map<String, Instant> map2 jsonMap.asMap(String .class, Instant .class,"outerMap","innerMap")

final TypeList list1 = jsonMap.asMap("outerMap").asList("myList")
final TypeList list2 = jsonMap.asList("outerMap", "myList")
final List<Object> list3 = jsonMap.asList(Object.class, "outerMap", "myList")
final TestEnum enum1 = jsonMap.asMap("outerMap").asList("myList").as(TestEnum.class, 0)
final TestEnum enum2 = jsonMap.asList("outerMap", "myList").as(TestEnum.class, 0)

final Date myDate = jsonMap.asLong("outerMap", "innerMap", "timestamp");
final Long myTimestamp = jsonMap.asLong(, "outerMap", "innerMap", "timestamp");
final TestEnum myEnum = jsonMap.as(TestEnum.class, "outerMap", "myList", 0);
final Boolean myBoolean = jsonMap.asBoolean("outerMap", "myList", 2);
final String backToJson = jsonMap.toJson();

Args

ArgsDecoder is used internally

final String[] cliArgs = {" myCommand1    myCommand2 --help  -v2=\"true\" -v=\"true\" -v=\"true\" --verbose=\"true\"   -Args=\"true\" -param 42   54   -ArgList=\"item 1\" --ArgList=\"item 2\" -v2=\"false\" --ArgList=\"-item 3\"  "};
final TypeMap map1 = new TypeMap(cliArgs);

final Boolean help = map.asBoolean("help");
final Boolean v = map.asBoolean("v");
final Boolean v2 = map.asBoolean("v2");
final Boolean verbose = map.asBoolean("verbose");
final Boolean args = map.asBoolean("Args");
final List<Boolean> v2List = map.asList(Boolean.class, "v2")
final List<Integer> paramList = map.asList(Integer.class, "param");
final TypeList argList = map.asList("ArgList");

TypeConverter

TypeConverter - The TypeConverter is the core of the TypeMap/TypeList

  • TypeConverter.mapOf
  • TypeConverter.convertObj
  • TypeConverter.collectionOf
  • JsonEncoder.toJson
  • JsonDecoder.jsonOf
  • JsonDecoder.jsonMapOf
  • JsonDecoder.jsonListOf
// ENUM
final TestEnum enum2=enumOf("BB",TestEnum.class)

// OBJECT
final TestEnum enum1=convertObj("BB",TestEnum.class)
final Long long1=convertObj("1800000000000",Long.class)
final OffsetDateTime time1=convertObj("1800000000000",OffsetDateTime.class)

// MAP
final TypeMap map1=mapOf(Map.of("12","34","56","78"))
final Map<String, Integer> map2=mapOf(Map.of("12","34","56","78"),String.class,Integer.class)
final Map<String, Integer> map3=mapOf(Map.of("12","34","56","78"),()->new HashMap<>(),String.class,Integer.class)

// COLLECTION
final TypeList list1=collectionOf(asList("123","456"))
final Set<Integer.class>list2=collectionOf(asList("123","456"),Integer.class)
final Set<Integer.class>set1=collectionOf(asList("123","456"),()->new HashSet<>(),Integer.class)

Extension Mechanism

Register custom conversions

TypeConversionRegister - Exception are ignored and results in null

    conversionFrom(String.class).to(Integer.class).register(Path::toUri);
    TypeConversionRegister.registerTypeConvert(Path.class,File.class,Path::toFile);
    TypeConversionRegister.registerTypeConvert(Path.class,URL.class,path->path.toUri().toURL());