001package net.tnemc.item.platform.conversion;
002/*
003 * The New Item Library
004 * Copyright (C) 2022 - 2025 Daniel "creatorfromhell" Vidmar
005 *
006 * This program is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019 */
020
021import java.util.HashMap;
022import java.util.Map;
023import java.util.function.Function;
024
025/**
026 * PlatformConverter is used for converting TNIL-based data strings to the Platform's enum/registry entries.
027 *
028 * @author creatorfromhell
029 * @since 0.2.0.0
030 */
031public class PlatformConverter {
032
033  private final Map<Class<?>, Map<Class<?>, Function<Object, Object>>> registry = new HashMap<>();
034
035  /**
036   * Registers a conversion between input and output classes using a provided converter function.
037   *
038   * @param <I> The input class type
039   * @param <O> The output class type
040   * @param inputClass The class of the input object to convert from
041   * @param outputClass The class of the output object to convert to
042   * @param converter The function that performs the conversion from input to output
043   * @author creatorfromhell
044   * @since 0.2.0.0
045   * @since 0.2.0.0
046   */
047  public <I, O> void registerConversion(final Class<I> inputClass, final Class<O> outputClass, final Function<I, O> converter) {
048    registry.computeIfAbsent(inputClass, k->new HashMap<>())
049            .put(outputClass, input->converter.apply(inputClass.cast(input)));
050  }
051
052  /**
053   * Performs a conversion from input type to output type using registered converters.
054   *
055   * @param <I> The type of the input object
056   * @param <O> The class of the output object
057   * @param input The input object to be converted
058   * @param outputClass The class of the output type to be converted to
059   * @return The converted output object
060   * @throws IllegalArgumentException if the input is null or if no conversion is registered for the specified types
061   * @author creatorfromhell
062   * @since 0.2.0.0
063   * @since 0.2.0.0
064   */
065  public <I, O> O convert(final I input, final Class<O> outputClass) {
066    if(input == null) {
067      throw new IllegalArgumentException("Input cannot be null");
068    }
069
070    final Class<?> inputClass = input.getClass();
071    final Function<Object, Object> converter = registry.getOrDefault(inputClass, Map.of()).get(outputClass);
072
073    if(converter == null) {
074      throw new IllegalArgumentException("No conversion registered from " + inputClass.getName() + " to " + outputClass.getName());
075    }
076
077    return outputClass.cast(converter.apply(input));
078  }
079}