/* * 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.ArrayList; import java.util.List; import org.apache.commons.lang.NullArgumentException; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.inventory.ItemStack; import com.comphenix.xp.parser.Utility; import com.google.common.collect.Lists; /** * Generic immutable representation of an item/block query. * * @author Kristian */ public class ItemQuery implements Query { private List<Integer> itemID; private List<Integer> durability; private List<Boolean> playerCreated; /** * Universal query. Matches everything. * @return The universal query. */ public static ItemQuery fromAny() { return fromAny(null, null, null); } /** * Creates a query from the given material and data. * @param material - material to create from. * @return The created query. */ public static ItemQuery fromAny(Material material) { return fromAny(material != null ? material.getId() : null, null); } /** * Creates a query from the given material and data. * @param material - material to create from. * @param durability - durability to create from. * @return The created query. */ public static ItemQuery fromAny(Material material, Integer durability) { return fromAny(material != null ? material.getId() : null, durability); } /** * Creates a query from the given material and data, where NULL represents any value. * @param itemID - ID to create from, or NULL to indicate every ID. * @param durability - durability to create from, or NULL to indicate every durability. * @return The created query. */ public static ItemQuery fromAny(Integer itemID, Integer durability) { return fromAny(itemID, durability, null); } /** * Creates a query from the given material and data, where NULL represents any value. * @param itemID - ID to create from, or NULL to indicate every ID. * @param durability - durability to create from, or NULL to indicate every durability. * @param playerCreated - whether or not the block was created/placed by a player. * @return The created query. */ public static ItemQuery fromAny(Integer itemID, Integer durability, Boolean playerCreated) { return new ItemQuery( Utility.getElementList(itemID), Utility.getElementList(durability), Utility.getElementList(playerCreated) ); } /** * Extracts the item type and durability. Note that the item count property is ignored. * @param stack - item type. * @return The created query. * @throws NullArgumentException if the stack is null. */ public static ItemQuery fromAny(ItemStack stack) { if (stack == null) throw new NullArgumentException("stack"); return fromAny(stack.getTypeId(), (int) stack.getDurability(), null); } /** * Creates a query from a given world block. * @param block - block to create from. * @return The created query. */ public static ItemQuery fromAny(Block block) { if (block == null) throw new NullArgumentException("block"); return fromAny(block.getTypeId(), (int) block.getData(), null); } /** * Creates a query from a given world block. * @param block - block to create from. * @return The created query. */ public static ItemQuery fromExact(Block block) { if (block == null) throw new NullArgumentException("block"); return fromExact(block.getTypeId(), (int) block.getData()); } /** * Extracts the item type and durability. Note that the item count property is ignored. * @param stack - item type. * @return The created query. * @throws NullArgumentException if the stack is null. */ public static ItemQuery fromExact(ItemStack stack) { if (stack == null) throw new NullArgumentException("stack"); return fromExact(stack.getTypeId(), (int) stack.getDurability()); } /** * Creates a query from the given ID and durability. NULL is used to ONLY match universal queries. * @param itemID - ID to match, or NULL to match queries without IDs. * @param durability - durability to match, or NULL to match queries without durabilities. * @return The created query. */ public static ItemQuery fromExact(Integer itemID, Integer durability) { return fromExact(itemID, durability, null); } /** * Creates a query from the given ID and durability. NULL is used to ONLY match universal queries. * @param itemID - ID to match, or NULL to match queries without IDs. * @param durability - durability to match, or NULL to match queries without durabilities. * @return The created query. */ public static ItemQuery fromExact(Integer itemID, Integer durability, Boolean playerCreated) { return new ItemQuery( Lists.newArrayList(itemID), Lists.newArrayList(durability), Lists.newArrayList(playerCreated) ); } /** * Constructs a query with the given IDs and durabilities. * @param itemID - list of IDs. * @param durability - list of durabilities. */ public ItemQuery(List<Integer> itemID, List<Integer> durability) { this(itemID, durability, Utility.getElementList((Boolean) null)); } /** * Constructs a query with the given IDs and durabilities. * @param itemID - list of IDs. * @param durability - list of durabilities. * @param playerCreated - option specifying whether or not the block was placed by a player. */ public ItemQuery(List<Integer> itemID, List<Integer> durability, List<Boolean> playerCreated) { this.itemID = itemID; this.durability = durability; this.playerCreated = playerCreated; } public List<Integer> getItemID() { return itemID; } public List<Integer> getDurability() { return durability; } public List<Boolean> getPlayerCreated() { return playerCreated; } public boolean hasItemID() { return itemID != null && !itemID.isEmpty(); } public boolean hasDurability() { return durability != null && !durability.isEmpty(); } public boolean hasPlayerCreated() { return playerCreated != null && !playerCreated.isEmpty(); } @Override public boolean match(Query other) { if (other instanceof ItemQuery) { ItemQuery query = (ItemQuery) other; // Make sure the current query is the superset of the given return QueryMatching.matchParameter(itemID, query.itemID) && QueryMatching.matchParameter(durability, query.durability) && QueryMatching.matchParameter(playerCreated, query.playerCreated); } // Query must be of the same type return false; } /** * Determines if the current query matches the given item. * @param id - id of item, or NULL for every ID. * @param durability - durability of item, or NULL for every durability. * @return TRUE if the current query matches the given item. */ public boolean match(Integer id, Integer durability, Boolean playerCreated) { return match(ItemQuery.fromAny(id, durability, playerCreated)); } /** * Determines if the current query matches the given item. * @param id - id of item, or NULL for every ID. * @param durability - durability of item, or NULL for every durability. * @return TRUE if the current query matches the given item. */ public boolean match(Integer id, Integer durability) { return match(ItemQuery.fromAny(id, durability)); } /** * Determines if the current query matches the given item. * @param item - item to test, or NULL for every possible item. * @return TRUE if the current query matches the given item. */ public boolean match(Material item) { if (item == null) return true; else return match(ItemQuery.fromAny(item.getId(), null)); } @Override public int hashCode() { return new HashCodeBuilder(17, 31). append(itemID). append(durability). append(playerCreated). toHashCode(); } @Override public boolean equals(Object obj) { if (obj == null) return false; if (obj == this) return true; if (obj.getClass() != getClass()) return false; ItemQuery other = (ItemQuery) obj; return new EqualsBuilder(). append(itemID, other.itemID). append(durability, other.durability). append(playerCreated, other.playerCreated). isEquals(); } // We're only interested in the String representation private List<Object> getMaterials() { List<Object> materials = new ArrayList<Object>(); if (itemID == null) return materials; // Map each integer to its corresponding material for (Integer id : itemID) { if (id != null) { Material material = Material.getMaterial(id); if (material != null) materials.add(material); else materials.add(id); } } return materials; } /** * Converts the given query to an item stack if possible. * @return The converted item stack, or NULL if not possible. */ public ItemStack toItemStack(int amount) { int data = 0; if (containsSingleNonNull(itemID)) { // We'll treat no durability as zero if (containsSingleNonNull(durability)) { data = durability.get(0); } else if (durability.isEmpty()) { data = 0; } else { return null; } // Create the item stack return new ItemStack(itemID.get(0), amount, (short) data); } return null; } private boolean containsSingleNonNull(List<Integer> list) { return list != null && list.size() == 1 && !list.contains(null); } @Override public String toString() { String itemsText = StringUtils.join(getMaterials(), ", "); String durabilityText = StringUtils.join(durability, ", "); String playerText = Utility.formatBoolean("player", playerCreated); if (hasPlayerCreated()) return String.format("%s|%s|%s", itemsText, durabilityText, playerText); else if (hasDurability()) return String.format("%s|%s", itemsText, durabilityText); else return String.format("%s", itemsText); } @Override public Types getQueryType() { return Types.ITEMS; } /** * Determines if the given item stack is non-empty. * @param stack - item stack to test. * @return TRUE if it is non-null and non-empty, FALSE otherwise. */ public static boolean hasItems(ItemStack stack) { return stack != null && stack.getAmount() > 0; } }