001package net.tnemc.item.persistent; 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 net.tnemc.item.JSONHelper; 022import net.tnemc.item.platform.ItemPlatform; 023import org.json.simple.JSONObject; 024 025import java.lang.invoke.MethodHandle; 026import java.lang.invoke.MethodHandles; 027import java.lang.invoke.MethodType; 028import java.util.Map; 029import java.util.Optional; 030import java.util.concurrent.ConcurrentHashMap; 031 032/** 033 * PersistentDataHolder 034 * 035 * @author creatorfromhell 036 * @since 0.2.0.0 037 */ 038public class PersistentDataHolder { 039 040 private final Map<String, PersistentDataType<?>> dataMap = new ConcurrentHashMap<>(); 041 042 /** 043 * Decodes the {@link JSONHelper JSON object} and sets the values in the current instance. 044 * 045 * @param json The {@link JSONHelper JSON object} to be decoded 046 * @since 0.2.0.0 047 */ 048 public void readJSON(final JSONObject json, final ItemPlatform<?, ?, ?> platform) { 049 050 json.forEach((key, value)->{ 051 final String identifier = String.valueOf(key); 052 053 final Optional<PersistentDataType<?>> data = decode(new JSONHelper((JSONObject)value), platform); 054 data.ifPresent(dataentry->dataMap.put(identifier, dataentry)); 055 }); 056 } 057 058 /** 059 * Convert a PersistentDataHolder object to a JSONObject. 060 * 061 * @return The JSONObject representation of the PersistentDataHolder object. 062 * @since 0.2.0.0 063 */ 064 public JSONObject toJSON() { 065 066 final JSONObject persistentData = new JSONObject(); 067 for(final Map.Entry<String, PersistentDataType<?>> entry : dataMap.entrySet()) { 068 persistentData.put(entry.getKey(), entry.getValue().toJSON()); 069 } 070 071 return persistentData; 072 } 073 074 /** 075 * Decodes the provided JSON object and returns an Optional containing the decoded 076 * PersistentDataType. 077 * 078 * @param json The JSONHelper object to be decoded 079 * 080 * @return An Optional containing the decoded PersistentDataType if it exists, otherwise an empty 081 * Optional 082 * @since 0.2.0.0 083 */ 084 public Optional<PersistentDataType<?>> decode(final JSONHelper json, final ItemPlatform<?, ?, ?> platform) { 085 086 final String type = json.getString("type"); 087 final String namespace = json.getString("namespace"); 088 final String key = json.getString("key"); 089 090 final Class<? extends PersistentDataType<?>> dataClass = platform.getClasses().get(type); 091 if(dataClass != null) { 092 093 try { 094 final MethodType constructorType = MethodType.methodType(void.class, String.class, String.class); 095 final MethodHandle constructorHandle = MethodHandles.lookup().findConstructor(dataClass, constructorType); 096 097 final PersistentDataType<?> persistentData = (PersistentDataType<?>)constructorHandle.invoke(namespace, key); 098 persistentData.readJSON(json); 099 100 return Optional.of(persistentData); 101 102 } catch(final Throwable ignore) { 103 104 return Optional.empty(); 105 } 106 } 107 return Optional.empty(); 108 } 109 110 public Map<String, PersistentDataType<?>> getData() { 111 112 return dataMap; 113 } 114}