BKCommonLib features a broad and versatile data type conversion system to convert (or cast, in some cases) one data type to another. For example, conversion between:
- numeric values (byte, short, int, long, float, double)
- String (or String producing object) data and numeric values
- Collections and arrays (list, set, map, object array, primitive array (int))
- Wrappers and their handles (CommonTag, Entity, World, Chunk, DataWatcher, etc.)
- Enumerations and Strings (Material, GameMode, PermissionDefault, etc.)
- Properties (item container and item, difficulty and difficulty ID, etc.)
- Custom (plugins can register their own)
Whenever you set something in a generic way, or try to obtain one in a generic way, the Conversion service takes care of it. It is used in most of the data storage classes BKCommonLib provides, including configuration and NBT API. The conversion service adds functionality where serialization and de-serialization of data fails.
The Converter takes care of the conversion from an unknown Object to a certain output type. It also provides several helper methods to make working with converters easier. These, if not provided in a base class, can be copied over without an issue. The default base class, which provides the basic needs, is called BasicConverter.
Every converter defines several methods:
- convert (and overloads) converts to the output type of the converter. The convert without default should be final.
- getOutputType tells the Conversion service what type of Object this converter can produce
- isCastingSupported tells the Conversion service whether the produced type allows casting (e.g. Entity to Creeper)
- isRegisterSupported tells the Conversion service whether the converter can be registered at all
Make sure that for converters that produce common types, such as Object and Integer, the isRegisterSupported returns false. Not doing so may result in your (limited) converter replacing other converters that can actually do the job. This mainly applies to conversion from property owner to property. You do not want your 'Item to Item Material' converter to replace the 'Anything to Material' converter.
A ConverterPair is a combination of two Converters that can convert from one to the other, and back. The class is self-explanatory. These pairs can be used to provide self-converting collections, accessors and other two-way 'setting and getting' types. All default pairs can be found in the ConversionPairs class.
The main use case for Converter Pairs is reflection. To access a field of type 'net.minecraft.server.Entity' without losing type information, you can provide a translation. For example, the definition of the field 'passenger' in the nms.Entity class:
public static final TranslatorFieldAccessor<Entity> = entityTemplate.getField("passenger").translate(ConversionPairs.entity);
Now you can get and set the passenger using Bukkit entities. The TranslatorFieldAccessor allows you to still get and set the base type (nms.Entity), but no type is exposed (it's an Object).
Converting to a generic type
To convert a value to a type that is not known at compile time (generics), use the following method:
Object input = ...; Class<T> typeToGet = ...; T default = ...; T value = Conversion.convert(input, typeToGet, default);
The default is returned when conversion, for some reason, fails. There are also overloads of this method to return null on failure, or to use the default class type instead of typeToGet.