Package com.bergerkiller.bukkit.common.nbt

Source Code of com.bergerkiller.bukkit.common.nbt.CommonTagCompound

package com.bergerkiller.bukkit.common.nbt;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import com.bergerkiller.bukkit.common.config.TempFileOutputStream;
import com.bergerkiller.bukkit.common.conversion.Conversion;
import com.bergerkiller.bukkit.common.reflection.classes.NBTRef;
import com.bergerkiller.bukkit.common.utils.NBTUtil;

/**
* An NBTTagCompound wrapper which is used to map values to keys<br>
* See also the {@link CommonTag} class description for more information
*/
@SuppressWarnings("unchecked")
public class CommonTagCompound extends CommonTag implements Map<String, CommonTag> {

  public CommonTagCompound() {
    this(new HashMap<String, CommonTag>());
  }

  public CommonTagCompound(Map<String, ?> data) {
    this((Object) data);
  }

  protected CommonTagCompound(Object data) {
    super(data);
  }

  @Override
  public Map<String, CommonTag> getData() {
    return (Map<String, CommonTag>) super.getData();
  }

  @Override
  protected Map<String, Object> getRawData() {
    return (Map<String, Object>) super.getRawData();
  }

  private Collection<Object> getHandleValues() {
    return NBTRef.nbtCompoundGetValues.invoke(handle);
  }

  @Override
  public CommonTagCompound clone() {
    return (CommonTagCompound) super.clone();
  }

  /**
   * Removes and returns the value contained at a given key. Possible returned types:<br>
   * <u>List<CommonTag>, Map<String, CommonTag>, byte, short, int, long, float, double, byte[], int[], String</u>
   *
   * @param key of the element to remove
   * @return the removed element value, or null if nothing was removed
   */
  public Object removeValue(String key) {
    if (key == null) {
      return null;
    }
    Object removedHandle = getRawData().remove(key);
    return removedHandle == null ? null : nbtToCommon(NBTUtil.getData(removedHandle), false);
  }

  /**
   * Removes and returns the tag contained at a given key.
   *
   * @param key of the element to remove
   * @return the removed CommonTag, or null if nothing was removed
   */
  @Override
  public CommonTag remove(Object key) {
    if (key == null) {
      return null;
    }
    return create(getRawData().remove(key.toString()));
  }

  /**
   * Sets the value of the element representing a given key.
   * Use a data of null to remove the data at the key. Supported data types:<br>
   * <u>CommonTag, NBTBase, List<CommonTag>, Map<String, CommonTag>, byte, short, int, long, float, double, byte[], int[], String</u>
   *
   * @param key of the element to set
   * @param value to assign to this key
   */
  public void putValue(String key, Object value) {
    if (value == null) {
      NBTRef.nbtCompoundRemove.invoke(handle, key);
    } else {
      Object elementHandle = commonToNbt(value);
      if (!NBTRef.NBTBase.isInstance(elementHandle)) {
        elementHandle = NBTUtil.createHandle(value);
      }
      NBTRef.nbtCompoundSet.invoke(handle, key, elementHandle);
    }
  }

  /**
   * Puts a new Tag list at the key, filled with the values specified
   *
   * @param key to put at
   * @param values to set the elements of the list to
   */
  public <T> void putListValues(String key, T... values) {
    final CommonTagList list = new CommonTagList();
    list.setAllValues(values);
    this.put(key, list);
  }

  /**
   * Gets the value associated with a key. This is the value of the tag, not the tag itself.
   * Possible returned types:<br>
   * <u>List<CommonTag>, Map<String, CommonTag>, byte, short, int, long, float, double, byte[], int[], String</u>
   *
   * @param key to get
   * @return value of the tag at the key
   */
  public Object getValue(String key) {
    if (key == null) {
      return null;
    }
    return nbtToCommon(NBTUtil.getData(NBTRef.nbtCompoundGet.invoke(handle, key)), false);
  }

  /**
   * Gets the value associated with a key.
   * This is the value of the tag, not the tag itself.
   * Returns the default value if no tag is contained.
   * Possible returned types:<br>
   * <u>List<CommonTag>, Map<String, CommonTag>, byte, short, int, long, float, double, byte[], int[], String</u>
   *
   * @param key to get
   * @param def value to return when not found (can not be null)
   * @return value of the tag at the key
   */
  public <T> T getValue(String key, T def) {
    return Conversion.convert(getValue(key), def);
  }

  /**
   * Gets the value associated with a key.
   * This is the value of the tag, not the tag itself.
   * Returns null if no tag is contained.
   * Possible returned types:<br>
   * <u>List<CommonTag>, Map<String, CommonTag>, byte, short, int, long, float, double, byte[], int[], String</u>
   *
   * @param key to get
   * @param type to case the value to
   * @return value of the tag at the key
   */
  public <T> T getValue(String key, Class<T> type) {
    return Conversion.convert(getValue(key), type);
  }

  /**
   * Gets the value associated with a key.
   * This is the value of the tag, not the tag itself.
   * Returns the default value if no tag is contained.
   * Possible returned types:<br>
   * <u>List<CommonTag>, Map<String, CommonTag>, byte, short, int, long, float, double, byte[], int[], String</u>
   *
   * @param key to get
   * @param type to case the value to
   * @param def value to return when not found
   * @return value of the tag at the key
   */
  public <T> T getValue(String key, Class<T> type, T def) {
    return Conversion.convert(getValue(key), type, def);
  }

  /**
   * Gets all values contained in this CommonTagCompound and casts it to the type specified<br>
   * Lists, Sets and arrays (also primitive) are supported for types
   *
   * @param type to cast to
   * @return all data contained
   */
  public <T> T getAllValues(Class<T> type) {
    T values = Conversion.convert(this.values(), type);
    if (values == null) {
      throw new IllegalArgumentException("Unsupported type: " + type.getName());
    } else {
      return values;
    }
  }

  /**
   * Gets an UUID value from two previously-stored keys.
   * If the key is 'Entity' then two long values 'EntityUUIDMost' and 'EntityUUIDLeast' are read.
   * If either of the two values are missing, null is returned instead
   *
   * @param key to read
   * @return value at the key
   */
  public UUID getUUID(String key) {
    Object most = getValue(key + "UUIDMost");
    Object least = getValue(key + "UUIDLeast");
    if (most instanceof Long && least instanceof Long) {
      return new UUID((Long) most, (Long) least);
    } else {
      return null;
    }
  }

  /**
   * Puts an UUID value by storing it under two keys.
   * If the key is 'Entity' then two long values 'EntityUUIDMost' and 'EntityUUIDLeast' are stored.
   * If the data is null, the elements at the key are removed
   *
   * @param key to put at
   * @param data to put
   */
  public void putUUID(String key, UUID data) {
    final Long most, least;
    if (data == null) {
      most = least = null;
    } else {
      most = data.getMostSignificantBits();
      least = data.getLeastSignificantBits();
    }
    putValue(key + "UUIDMost", most);
    putValue(key + "UUIDLeast", least);
  }

  /**
   * Obtains a CommonTagCompound at the key, if it does not exist
   * a new one is created at the key.
   *
   * @param key to get or create at
   * @return CommonTagCompound
   */
  public CommonTagCompound createCompound(Object key) {
    if (key == null) {
      throw new IllegalArgumentException("Can not store elements under null keys");
    }
    Object elementHandle = getRawData().get(key);
    if (!NBTRef.NBTTagCompound.isInstance(elementHandle)) {
      elementHandle = NBTRef.NBTTagCompound.newInstance();
      getRawData().put(key.toString(), elementHandle);
    }
    return (CommonTagCompound) create(elementHandle);
  }

  /**
   * Obtains a CommonTagList at the key, if it does not exist
   * a new one is created at the key.
   *
   * @param key to get or create at
   * @return CommonTagList
   */
  public CommonTagList createList(Object key) {
    if (key == null) {
      throw new IllegalArgumentException("Can not store elements under null keys");
    }
    Object elementHandle = getRawData().get(key);
    if (!NBTRef.NBTTagList.isInstance(elementHandle)) {
      elementHandle = NBTRef.NBTTagList.newInstance();
      getRawData().put(key.toString(), elementHandle);
    }
    return (CommonTagList) create(elementHandle);
  }

  /**
   * Gets a certain type of tag from this Tag Compound
   *
   * @param key to get the tag at
   * @param type of tag to get
   * @return the tag, or null if this was not possible
   */
  public <T extends CommonTag> T get(Object key, Class<T> type) {
    return Conversion.convert(get(key), type);
  }

  @Override
  public CommonTag get(Object key) {
    if (key == null) {
      return null;
    }
    return create(NBTRef.nbtCompoundGet.invoke(handle, key.toString()));
  }

  @Override
  public CommonTag put(String key, CommonTag value) {
    final CommonTag prev = get(key);
    putValue(key, value);
    return prev;
  }

  @Override
  public void clear() {
    getRawData().clear();
  }

  @Override
  public int size() {
    return getRawData().size();
  }

  @Override
  public boolean isEmpty() {
    return NBTRef.nbtCompoundIsEmpty.invoke(handle);
  }

  @Override
  public boolean containsKey(Object key) {
    return NBTRef.nbtCompoundContains.invoke(handle, key.toString());
  }

  @Override
  public boolean containsValue(Object value) {
    if (value == null) {
      return false;
    } else if (value instanceof CommonTag) {
      value = ((CommonTag) value).getHandle();
    }
    if (NBTRef.NBTBase.isInstance(value)) {
      // Compare NBT elements
      return getHandleValues().contains(value);
    } else {
      // Compare the data of the NBT elements
      for (Object base : getHandleValues()) {
        if (NBTUtil.getData(base).equals(value)) {
          return true;
        }
      }
      return false;
    }
  }

  @Override
  public void putAll(Map<? extends String, ? extends CommonTag> m) {
    for (Entry<? extends String, ? extends CommonTag> entry : m.entrySet()) {
      put(entry.getKey(), entry.getValue());
    }
  }

  @Override
  public Set<String> keySet() {
    return getRawData().keySet();
  }

  @Override
  public Collection<CommonTag> values() {
    return Collections.unmodifiableCollection((Collection<CommonTag>) nbtToCommon(getHandleValues(), true));
  }

  @Override
  public Set<Entry<String, CommonTag>> entrySet() {
    return Collections.unmodifiableSet((Set<Entry<String, CommonTag>>) nbtToCommon(getRawData(), true));
  }

  /**
   * Writes this CommonTagCompound to the OutputStream specified.
   * This method writes the compound as raw, uncompressed data.
   *
   * @param stream to write to
   * @throws IOException
   */
  public void writeToUncompressed(OutputStream stream) throws IOException {
    NBTUtil.writeCompoundUncompressed(getHandle(), stream);
  }

  /**
   * Writes this CommonTagCompound to the OutputStream specified.
   * This method writes the compound as GZIP-compressed data.
   *
   * @param stream to write to
   * @throws IOException
   */
  public void writeTo(OutputStream stream) throws IOException {
    NBTUtil.writeCompound(getHandle(), stream);
  }

  /**
   * Writes this CommonTagCompound to the file specified.
   * First writes to a temporary file to avoid corrupted files.
   * This method writes the compound as GZIP-compressed data to the file.
   *
   * @param file to write to
   * @throws IOException on failure
   */
  public void writeTo(File file) throws IOException {
    TempFileOutputStream stream = new TempFileOutputStream(file);
    boolean successful = false;
    try {
      writeTo(stream);
      successful = true;
    } finally {
      stream.close(successful);
    }
  }

  /**
   * Reads a CommonTagCompound from the InputStream specified.
   * This method expects an Input Stream containing raw, uncompressed data.
   *
   * @param stream to read from
   * @return read compound
   * @throws IOException on failure
   */
  public static CommonTagCompound readFromUncompressed(InputStream stream) throws IOException {
    return (CommonTagCompound) create(NBTUtil.readCompoundUncompressed(stream));
  }

  /**
   * Reads a CommonTagCompound from the InputStream specified.
   * This method expects an Input Stream containing GZIP-compressed data.
   *
   * @param stream to read from
   * @return read compound
   * @throws IOException on failure
   */
  public static CommonTagCompound readFrom(InputStream stream) throws IOException {
    return (CommonTagCompound) create(NBTUtil.readCompound(stream));
  }

  /**
   * Reads a CommonTagCompound from the file specified.
   * This method expects a file containing GZIP-compressed data.
   *
   * @param file to read from
   * @return read compound
   * @throws IOException on failure
   */
  public static CommonTagCompound readFrom(File file) throws IOException {
    FileInputStream stream = new FileInputStream(file);
    try {
      return readFrom(stream);
    } finally {
      stream.close();
    }
  }
}
TOP

Related Classes of com.bergerkiller.bukkit.common.nbt.CommonTagCompound

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.