/* * ExperienceMod - Bukkit server plugin for modifying the experience system in Minecraft. * Copyright (C) 2012 Kristian S. Stangeland * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ package com.comphenix.xp.lookup; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class Parameter<TParam> { protected Map<TParam, Set<Integer>> reverseLookup = new HashMap<TParam, Set<Integer>>(); public int size() { return reverseLookup.size(); } public void put(List<TParam> params, Integer id) { // Associate every parameter for (TParam param : params) { putSingle(param, id); } } /** * Insert every parameter key and its corresponding ID list from the given parameter. * @param other - given parameter. * @param offsetID - the amount to increment every ID in the given parameter. */ public void putAll(Parameter<TParam> other, Integer offsetID) { // Associate every parameter for (TParam param : other.reverseLookup.keySet()) { Set<Integer> list = reverseLookup.get(param); // Initialize the list if (list == null) { list = new HashSet<Integer>(); reverseLookup.put(param, list); } // Add every ID for (Integer id : other.reverseLookup.get(param)) { list.add(offsetID + id); } } } private void putSingle(TParam param, Integer id) { Set<Integer> list = reverseLookup.get(param); // Initialize the list if (list == null) { list = new HashSet<Integer>(); reverseLookup.put(param, list); } // Store the direct and reverse lookup if (!list.add(id)) throw new IllegalArgumentException( String.format("Duplicate parameter %s at index %s", id, param)); } /** * Indexes of queries with the given parameter. * @param param - parameter to search for. * @return Every query that is listed under the given parameter, or NULL if nothing was found. */ public Set<Integer> getSingle(TParam param) { return reverseLookup.get(param); } public Set<Integer> getCopy(List<TParam> params) { Set<Integer> copy = new HashSet<Integer>(); // Union of all parameter sets for (TParam param : params) { Set<Integer> result = reverseLookup.get(param); if (result != null) copy.addAll(result); } return copy; } public void retain(Set<Integer> current, List<TParam> params) { // Save some time if (current.size() == 0) return; // Set subtraction Set<TParam> blacklist = new HashSet<TParam>(reverseLookup.keySet()); blacklist.removeAll(params); // Queries WITH this parameter will not be removed in this phase Set<Integer> whitelist = getWhitelist(current, params); // Remove everything but the items with the given parameter for (TParam key : blacklist) { current.removeAll(reverseLookup.get(key)); if (current.size() == 0) { break; } } // Add back the whitelist if (whitelist.size() > 0) { current.addAll(whitelist); } // Optimize idea: Store the negative (all elements NOT in the given lookup), // instead of a loop. } private Set<Integer> getWhitelist(Set<Integer> current, List<TParam> params) { Set<Integer> whitelist = new HashSet<Integer>(); // Add every query that qualify for (TParam param : params) { Set<Integer> result = reverseLookup.get(param); if (result != null) whitelist.addAll(result); } // But remove those previously eliminated whitelist.retainAll(current); return whitelist; } /** * Retrieves every stored parameter. * @return Every stored parameter. */ public Collection<TParam> getKeys() { return reverseLookup.keySet(); } }