/* * This file is part of Spoutcraft. * * Copyright (c) 2011 SpoutcraftDev <http://spoutcraft.org/> * Spoutcraft is licensed under the GNU Lesser General Public License. * * Spoutcraft is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Spoutcraft is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.spoutcraft.client.util; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; public class UniqueItemStringMap { private static final ConcurrentHashMap<Integer,String> reverse = new ConcurrentHashMap<Integer,String>(); private static final ConcurrentHashMap<Integer,String> reverseStable = new ConcurrentHashMap<Integer,String>(); private static final ConcurrentHashMap<String,Integer> forward = new ConcurrentHashMap<String,Integer>(); private static final AtomicInteger idCounter = new AtomicInteger(1024); // private static Configuration config; // public static void setConfigFile(Configuration config) { // UniqueItemStringMap.config = config; // List<String> keys = config.getKeys(); // // for (String key : keys) { // Integer id = getIdFromFile(decodeKey(key)); // if (id != null) { // forward.put(key, id); // reverse.put(id, key); // reverseStable.put(id, key); // } // } // } // private static Integer getIdFromFile(String key) { // // synchronized(config) { // key = encodeKey(key); // if (config.getProperty(key) == null) { // return null; // } else { // int id = config.getInt(key, -1); // if (id == -1) { // config.removeProperty(key); // return null; // } else { // return id; // } // } // } // // } // private static void setIdInFile(String key, int id) { // // synchronized(config) { // key = encodeKey(key); // config.setProperty(key, id); // config.save(); // } // // } private static String encodeKey(String key) { key = key.replace("*", "-*-"); return key.replace(".", "**"); } private static String decodeKey(String key) { key = key.replace("**", "."); return key.replace("-*-", "*"); } public static Set<Integer> getIds() { return reverse.keySet(); } /** * Associates a unique id for each string * * These associations persist over reloads and server restarts * * @param string the string to be associated * @return the id associated with the string. */ public static int getId(String string) { string = encodeKey(string); Integer id = null; boolean success = false; int testId = idCounter.incrementAndGet() & 0x0FFFF; while (!success || id == null) { id = forward.get(string); if (id != null) { return id; } if (reverse.containsKey(testId)) { // id already in use testId = idCounter.incrementAndGet() & 0x0FFFF; if (testId == 65535 || testId < 1024) { throw new RuntimeException("[Spout] Out of custom item IDs"); } continue; } String oldString = reverse.putIfAbsent(testId, string); if (oldString == null) { // reverse link success Integer oldId = forward.putIfAbsent(string, testId); if (oldId != null) { // forward link failed reverse.remove(testId, string); // remove reverse link continue; } id = testId; } else { // reverse link failed continue; } reverseStable.put(testId, string); // setIdInFile(decodeKey(string), id); success = true; } return id; } /** * Returns the id associated with a string * * These associations persist over reloads and server restarts * * Note: . characters are replaced with * characters * * @param id the id * @return the string associated with the id, or null if no string is associated */ public static String getString(int id) { return decodeKey(reverseStable.get(id)); } }