1.4: Refactor packages, remove generics from ListTag, add value<->tag conversion system, merge NBTFileIO and NBTIO

This commit is contained in:
Steveice10 2014-03-25 20:16:23 -07:00
parent ff376a4c76
commit 1c005ad1ec
47 changed files with 883 additions and 296 deletions

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.spacehq</groupId>
<artifactId>opennbt</artifactId>
<version>1.3</version>
<version>1.4</version>
<packaging>jar</packaging>
<name>OpenNBT</name>

View File

@ -1,128 +0,0 @@
package org.spacehq.opennbt;
import org.spacehq.opennbt.tag.CompoundTag;
import org.spacehq.opennbt.tag.Tag;
import java.io.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class NBTFileIO {
/**
* Reads the root CompoundTag from the given file.
*
* @param path Path of the file.
* @return The read compound tag.
* @throws java.io.IOException If an I/O error occurs.
*/
public static CompoundTag readFile(String path) throws IOException {
return readFile(new File(path));
}
/**
* Reads the root CompoundTag from the given file.
*
* @param file File to read from.
* @return The read compound tag.
* @throws java.io.IOException If an I/O error occurs.
*/
public static CompoundTag readFile(File file) throws IOException {
return readFile(file, true);
}
/**
* Reads the root CompoundTag from the given file.
*
* @param path Path of the file.
* @param compressed Whether the NBT file is compressed.
* @return The read compound tag.
* @throws java.io.IOException If an I/O error occurs.
*/
public static CompoundTag readFile(String path, boolean compressed) throws IOException {
return readFile(new File(path), compressed);
}
/**
* Reads the root CompoundTag from the given file.
*
* @param file File to read from.
* @param compressed Whether the NBT file is compressed.
* @return The read compound tag.
* @throws java.io.IOException If an I/O error occurs.
*/
public static CompoundTag readFile(File file, boolean compressed) throws IOException {
InputStream in = new FileInputStream(file);
if(compressed) {
in = new GZIPInputStream(in);
}
Tag tag = NBTIO.readTag(new DataInputStream(in));
if(!(tag instanceof CompoundTag)) {
throw new IOException("Root tag is not a CompoundTag!");
}
return (CompoundTag) tag;
}
/**
* Writes the given root CompoundTag to the given file.
*
* @param tag Tag to write.
* @param path Path to write to.
* @throws java.io.IOException If an I/O error occurs.
*/
public static void writeFile(CompoundTag tag, String path) throws IOException {
writeFile(tag, new File(path));
}
/**
* Writes the given root CompoundTag to the given file.
*
* @param tag Tag to write.
* @param file File to write to.
* @throws java.io.IOException If an I/O error occurs.
*/
public static void writeFile(CompoundTag tag, File file) throws IOException {
writeFile(tag, file, true);
}
/**
* Writes the given root CompoundTag to the given file.
*
* @param tag Tag to write.
* @param path Path to write to.
* @param compressed Whether the NBT file should be compressed.
* @throws java.io.IOException If an I/O error occurs.
*/
public static void writeFile(CompoundTag tag, String path, boolean compressed) throws IOException {
writeFile(tag, new File(path), compressed);
}
/**
* Writes the given root CompoundTag to the given file.
*
* @param tag Tag to write.
* @param file File to write to.
* @param compressed Whether the NBT file should be compressed.
* @throws java.io.IOException If an I/O error occurs.
*/
public static void writeFile(CompoundTag tag, File file, boolean compressed) throws IOException {
if(!file.exists()) {
if(file.getParentFile() != null && !file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
file.createNewFile();
}
OutputStream out = new FileOutputStream(file);
if(compressed) {
out = new GZIPOutputStream(out);
}
NBTIO.writeTag(new DataOutputStream(out), tag);
out.close();
}
}

View File

@ -1,15 +1,14 @@
package org.spacehq.opennbt;
import org.spacehq.opennbt.tag.Tag;
import org.spacehq.opennbt.tag.TagCreateException;
import org.spacehq.opennbt.tag.TagRegistry;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
import org.spacehq.opennbt.tag.builtin.Tag;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* A class containing methods for reading/writing NBT tags.
@ -19,24 +18,119 @@ public class NBTIO {
public static final Charset CHARSET = Charset.forName("UTF-8");
/**
* Reads NBT tags until an end tag is reached.
* Reads the root CompoundTag from the given file.
*
* @param in Input stream to read from.
* @return The read tags.
* @param path Path of the file.
* @return The read compound tag.
* @throws java.io.IOException If an I/O error occurs.
*/
public static List<Tag> readUntilEndTag(DataInputStream in) throws IOException {
List<Tag> ret = new ArrayList<Tag>();
try {
Tag tag;
while((tag = readTag(in)) != null) {
ret.add(tag);
}
} catch(EOFException e) {
throw new IOException("Closing EndTag was not found!");
public static CompoundTag readFile(String path) throws IOException {
return readFile(new File(path));
}
/**
* Reads the root CompoundTag from the given file.
*
* @param file File to read from.
* @return The read compound tag.
* @throws java.io.IOException If an I/O error occurs.
*/
public static CompoundTag readFile(File file) throws IOException {
return readFile(file, true);
}
/**
* Reads the root CompoundTag from the given file.
*
* @param path Path of the file.
* @param compressed Whether the NBT file is compressed.
* @return The read compound tag.
* @throws java.io.IOException If an I/O error occurs.
*/
public static CompoundTag readFile(String path, boolean compressed) throws IOException {
return readFile(new File(path), compressed);
}
/**
* Reads the root CompoundTag from the given file.
*
* @param file File to read from.
* @param compressed Whether the NBT file is compressed.
* @return The read compound tag.
* @throws java.io.IOException If an I/O error occurs.
*/
public static CompoundTag readFile(File file, boolean compressed) throws IOException {
InputStream in = new FileInputStream(file);
if(compressed) {
in = new GZIPInputStream(in);
}
return ret;
Tag tag = readTag(new DataInputStream(in));
if(!(tag instanceof CompoundTag)) {
throw new IOException("Root tag is not a CompoundTag!");
}
return (CompoundTag) tag;
}
/**
* Writes the given root CompoundTag to the given file.
*
* @param tag Tag to write.
* @param path Path to write to.
* @throws java.io.IOException If an I/O error occurs.
*/
public static void writeFile(CompoundTag tag, String path) throws IOException {
writeFile(tag, new File(path));
}
/**
* Writes the given root CompoundTag to the given file.
*
* @param tag Tag to write.
* @param file File to write to.
* @throws java.io.IOException If an I/O error occurs.
*/
public static void writeFile(CompoundTag tag, File file) throws IOException {
writeFile(tag, file, true);
}
/**
* Writes the given root CompoundTag to the given file.
*
* @param tag Tag to write.
* @param path Path to write to.
* @param compressed Whether the NBT file should be compressed.
* @throws java.io.IOException If an I/O error occurs.
*/
public static void writeFile(CompoundTag tag, String path, boolean compressed) throws IOException {
writeFile(tag, new File(path), compressed);
}
/**
* Writes the given root CompoundTag to the given file.
*
* @param tag Tag to write.
* @param file File to write to.
* @param compressed Whether the NBT file should be compressed.
* @throws java.io.IOException If an I/O error occurs.
*/
public static void writeFile(CompoundTag tag, File file, boolean compressed) throws IOException {
if(!file.exists()) {
if(file.getParentFile() != null && !file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
file.createNewFile();
}
OutputStream out = new FileOutputStream(file);
if(compressed) {
out = new GZIPOutputStream(out);
}
writeTag(new DataOutputStream(out), tag);
out.close();
}
/**
@ -66,19 +160,6 @@ public class NBTIO {
return tag;
}
/**
* Writes a collection of tags to an output stream.
*
* @param out Output stream to write to.
* @param tags Tags to write.
* @throws java.io.IOException If an I/O error occurs.
*/
public static void writeTags(DataOutputStream out, Collection<Tag> tags) throws IOException {
for(Tag tag : tags) {
writeTag(out, tag);
}
}
/**
* Writes a tag to an output stream.
*

View File

@ -0,0 +1,26 @@
package org.spacehq.opennbt.conversion;
/**
* An exception thrown when an error occurs while converting something.
*/
public class ConversionException extends RuntimeException {
private static final long serialVersionUID = -2022049594558041160L;
public ConversionException() {
super();
}
public ConversionException(String message) {
super(message);
}
public ConversionException(Throwable cause) {
super(cause);
}
public ConversionException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,26 @@
package org.spacehq.opennbt.conversion;
/**
* An exception thrown when an error occurs while registering a converter.
*/
public class ConverterRegisterException extends RuntimeException {
private static final long serialVersionUID = -2022049594558041160L;
public ConverterRegisterException() {
super();
}
public ConverterRegisterException(String message) {
super(message);
}
public ConverterRegisterException(Throwable cause) {
super(cause);
}
public ConverterRegisterException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,144 @@
package org.spacehq.opennbt.conversion;
import org.spacehq.opennbt.conversion.builtin.*;
import org.spacehq.opennbt.conversion.builtin.custom.*;
import org.spacehq.opennbt.tag.TagRegisterException;
import org.spacehq.opennbt.tag.builtin.*;
import org.spacehq.opennbt.tag.builtin.custom.*;
import java.io.Serializable;
import java.util.*;
/**
* A registry mapping tags and value types to converters.
*/
public class ConverterRegistry {
private static final Map<Class<? extends Tag>, TagConverter<? extends Tag, ?>> tagToConverter = new HashMap<Class<? extends Tag>, TagConverter<? extends Tag, ?>>();
private static final Map<Class<?>, TagConverter<? extends Tag, ?>> typeToConverter = new HashMap<Class<?>, TagConverter<? extends Tag, ?>>();
static {
register(ByteTag.class, Byte.class, new ByteTagConverter());
register(ShortTag.class, Short.class, new ShortTagConverter());
register(IntTag.class, Integer.class, new IntTagConverter());
register(LongTag.class, Long.class, new LongTagConverter());
register(FloatTag.class, Float.class, new FloatTagConverter());
register(DoubleTag.class, Double.class, new DoubleTagConverter());
register(ByteArrayTag.class, byte[].class, new ByteArrayTagConverter());
register(StringTag.class, String.class, new StringTagConverter());
register(ListTag.class, List.class, new ListTagConverter());
register(CompoundTag.class, Map.class, new CompoundTagConverter());
register(IntArrayTag.class, int[].class, new IntArrayTagConverter());
register(DoubleArrayTag.class, double[].class, new DoubleArrayTagConverter());
register(FloatArrayTag.class, float[].class, new FloatArrayTagConverter());
register(LongArrayTag.class, long[].class, new LongArrayTagConverter());
register(SerializableArrayTag.class, Serializable[].class, new SerializableArrayTagConverter());
register(SerializableTag.class, Serializable.class, new SerializableTagConverter());
register(ShortArrayTag.class, short[].class, new ShortArrayTagConverter());
register(StringArrayTag.class, String[].class, new StringArrayTagConverter());
}
/**
* Registers a converter.
*
* @param tag Tag type class to register the converter to.
* @param type Value type class to register the converter to.
* @param converter Converter to register.
* @throws ConverterRegisterException If an error occurs while registering the converter.
*/
public static <T extends Tag, V> void register(Class<T> tag, Class<V> type, TagConverter<T, V> converter) throws ConverterRegisterException {
if(tagToConverter.containsKey(tag)) {
throw new TagRegisterException("Type conversion to tag " + tag.getName() + " is already registered.");
}
if(typeToConverter.containsKey(type)) {
throw new TagRegisterException("Tag conversion to type " + type.getName() + " is already registered.");
}
tagToConverter.put(tag, converter);
typeToConverter.put(type, converter);
}
/**
* Converts the given tag to a value.
*
* @param tag Tag to convert.
* @return The converted value.
* @throw ConversionException If a suitable converter could not be found.
*/
public static <T extends Tag, V> V convertToValue(T tag) throws ConversionException {
if(tag == null || tag.getValue() == null) {
return null;
}
if(!tagToConverter.containsKey(tag.getClass())) {
throw new ConversionException("Tag type " + tag.getClass().getName() + " has no converter.");
}
TagConverter<T, ?> converter = (TagConverter<T, ?>) tagToConverter.get(tag.getClass());
return (V) converter.convert(tag);
}
/**
* Converts the given value to a tag.
*
* @param name Name of the resulting tag.
* @param value Value to convert.
* @return The converted tag.
* @throw ConversionException If a suitable converter could not be found.
*/
public static <V, T extends Tag> T convertToTag(String name, V value) throws ConversionException {
if(value == null) {
return null;
}
TagConverter<T, V> converter = (TagConverter<T, V>) typeToConverter.get(value.getClass());
if(converter == null) {
for(Class<?> clazz : getAllClasses(value.getClass())) {
if(typeToConverter.containsKey(clazz)) {
try {
converter = (TagConverter<T, V>) typeToConverter.get(clazz);
break;
} catch(ClassCastException e) {
}
}
}
}
if(converter == null) {
throw new ConversionException("Value type " + value.getClass().getName() + " has no converter.");
}
return converter.convert(name, value);
}
private static Set<Class<?>> getAllClasses(Class<?> clazz) {
Set<Class<?>> ret = new LinkedHashSet<Class<?>>();
Class<?> c = clazz;
while(c != null) {
ret.add(c);
ret.addAll(getAllSuperInterfaces(c));
c = c.getSuperclass();
}
// Make sure Serializable is at the end to avoid mix-ups.
if(ret.contains(Serializable.class)) {
ret.remove(Serializable.class);
ret.add(Serializable.class);
}
return ret;
}
private static Set<Class<?>> getAllSuperInterfaces(Class<?> clazz) {
Set<Class<?>> ret = new HashSet<Class<?>>();
for(Class<?> c : clazz.getInterfaces()) {
ret.add(c);
ret.addAll(getAllSuperInterfaces(c));
}
return ret;
}
}

View File

@ -0,0 +1,29 @@
package org.spacehq.opennbt.conversion;
import org.spacehq.opennbt.tag.builtin.Tag;
/**
* A converter that converts between a tag type and a value type. A converted tag will have its value and all children converted to raw types and vice versa.
*
* @param <T> Tag type.
* @param <V> Value type.
*/
public interface TagConverter<T extends Tag, V> {
/**
* Converts a tag to a value.
*
* @param tag Tag to convert.
* @return The converted value.
*/
public V convert(T tag);
/**
* Converts a value to a tag.
*
* @param value Value to convert.
* @return The converted tag.
*/
public T convert(String name, V value);
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.ByteArrayTag;
/**
* A converter that converts between ByteArrayTag and byte[].
*/
public class ByteArrayTagConverter implements TagConverter<ByteArrayTag, byte[]> {
@Override
public byte[] convert(ByteArrayTag tag) {
return tag.getValue();
}
@Override
public ByteArrayTag convert(String name, byte[] value) {
return new ByteArrayTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.ByteTag;
/**
* A converter that converts between ByteTag and byte.
*/
public class ByteTagConverter implements TagConverter<ByteTag, Byte> {
@Override
public Byte convert(ByteTag tag) {
return tag.getValue();
}
@Override
public ByteTag convert(String name, Byte value) {
return new ByteTag(name, value);
}
}

View File

@ -0,0 +1,39 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.ConverterRegistry;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.CompoundTag;
import org.spacehq.opennbt.tag.builtin.Tag;
import java.util.HashMap;
import java.util.Map;
/**
* A converter that converts between CompoundTag and Map.
*/
public class CompoundTagConverter implements TagConverter<CompoundTag, Map> {
@Override
public Map convert(CompoundTag tag) {
Map<String, Object> ret = new HashMap<String, Object>();
Map<String, Tag> tags = tag.getValue();
for(String name : tags.keySet()) {
Tag t = tags.get(name);
ret.put(t.getName(), ConverterRegistry.convertToValue(t));
}
return ret;
}
@Override
public CompoundTag convert(String name, Map value) {
Map<String, Tag> tags = new HashMap<String, Tag>();
for(Object na : value.keySet()) {
String n = (String) na;
tags.put(n, ConverterRegistry.convertToTag(n, value.get(n)));
}
return new CompoundTag(name, tags);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.DoubleTag;
/**
* A converter that converts between DoubleTag and double.
*/
public class DoubleTagConverter implements TagConverter<DoubleTag, Double> {
@Override
public Double convert(DoubleTag tag) {
return tag.getValue();
}
@Override
public DoubleTag convert(String name, Double value) {
return new DoubleTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.FloatTag;
/**
* A converter that converts between FloatTag and float.
*/
public class FloatTagConverter implements TagConverter<FloatTag, Float> {
@Override
public Float convert(FloatTag tag) {
return tag.getValue();
}
@Override
public FloatTag convert(String name, Float value) {
return new FloatTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.IntArrayTag;
/**
* A converter that converts between IntArrayTag and int[].
*/
public class IntArrayTagConverter implements TagConverter<IntArrayTag, int[]> {
@Override
public int[] convert(IntArrayTag tag) {
return tag.getValue();
}
@Override
public IntArrayTag convert(String name, int[] value) {
return new IntArrayTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.IntTag;
/**
* A converter that converts between IntTag and int.
*/
public class IntTagConverter implements TagConverter<IntTag, Integer> {
@Override
public Integer convert(IntTag tag) {
return tag.getValue();
}
@Override
public IntTag convert(String name, Integer value) {
return new IntTag(name, value);
}
}

View File

@ -0,0 +1,41 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.ConverterRegistry;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.ListTag;
import org.spacehq.opennbt.tag.builtin.Tag;
import java.util.ArrayList;
import java.util.List;
/**
* A converter that converts between CompoundTag and Map.
*/
public class ListTagConverter implements TagConverter<ListTag, List> {
@Override
public List convert(ListTag tag) {
List<Object> ret = new ArrayList<Object>();
List<? extends Tag> tags = tag.getValue();
for(Tag t : tags) {
ret.add(ConverterRegistry.convertToValue(t));
}
return ret;
}
@Override
public ListTag convert(String name, List value) {
if(value.isEmpty()) {
throw new IllegalArgumentException("Cannot convert ListTag with size of 0.");
}
List<Tag> tags = new ArrayList<Tag>();
for(Object o : value) {
tags.add(ConverterRegistry.convertToTag("", o));
}
return new ListTag(name, tags);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.LongTag;
/**
* A converter that converts between LongTag and long.
*/
public class LongTagConverter implements TagConverter<LongTag, Long> {
@Override
public Long convert(LongTag tag) {
return tag.getValue();
}
@Override
public LongTag convert(String name, Long value) {
return new LongTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.ShortTag;
/**
* A converter that converts between ShortTag and short.
*/
public class ShortTagConverter implements TagConverter<ShortTag, Short> {
@Override
public Short convert(ShortTag tag) {
return tag.getValue();
}
@Override
public ShortTag convert(String name, Short value) {
return new ShortTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.StringTag;
/**
* A converter that converts between StringTag and String.
*/
public class StringTagConverter implements TagConverter<StringTag, String> {
@Override
public String convert(StringTag tag) {
return tag.getValue();
}
@Override
public StringTag convert(String name, String value) {
return new StringTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin.custom;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.custom.DoubleArrayTag;
/**
* A converter that converts between DoubleArrayTag and double[].
*/
public class DoubleArrayTagConverter implements TagConverter<DoubleArrayTag, double[]> {
@Override
public double[] convert(DoubleArrayTag tag) {
return tag.getValue();
}
@Override
public DoubleArrayTag convert(String name, double[] value) {
return new DoubleArrayTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin.custom;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.custom.FloatArrayTag;
/**
* A converter that converts between FloatArrayTag and float[].
*/
public class FloatArrayTagConverter implements TagConverter<FloatArrayTag, float[]> {
@Override
public float[] convert(FloatArrayTag tag) {
return tag.getValue();
}
@Override
public FloatArrayTag convert(String name, float[] value) {
return new FloatArrayTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin.custom;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.custom.LongArrayTag;
/**
* A converter that converts between LongArrayTag and long[].
*/
public class LongArrayTagConverter implements TagConverter<LongArrayTag, long[]> {
@Override
public long[] convert(LongArrayTag tag) {
return tag.getValue();
}
@Override
public LongArrayTag convert(String name, long[] value) {
return new LongArrayTag(name, value);
}
}

View File

@ -0,0 +1,23 @@
package org.spacehq.opennbt.conversion.builtin.custom;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.custom.SerializableArrayTag;
import java.io.Serializable;
/**
* A converter that converts between SerializableArrayTag and Serializable[].
*/
public class SerializableArrayTagConverter implements TagConverter<SerializableArrayTag, Serializable[]> {
@Override
public Serializable[] convert(SerializableArrayTag tag) {
return tag.getValue();
}
@Override
public SerializableArrayTag convert(String name, Serializable[] value) {
return new SerializableArrayTag(name, value);
}
}

View File

@ -0,0 +1,23 @@
package org.spacehq.opennbt.conversion.builtin.custom;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.custom.SerializableTag;
import java.io.Serializable;
/**
* A converter that converts between SerializableTag and Serializable.
*/
public class SerializableTagConverter implements TagConverter<SerializableTag, Serializable> {
@Override
public Serializable convert(SerializableTag tag) {
return tag.getValue();
}
@Override
public SerializableTag convert(String name, Serializable value) {
return new SerializableTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin.custom;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.custom.ShortArrayTag;
/**
* A converter that converts between ShortArrayTag and short[].
*/
public class ShortArrayTagConverter implements TagConverter<ShortArrayTag, short[]> {
@Override
public short[] convert(ShortArrayTag tag) {
return tag.getValue();
}
@Override
public ShortArrayTag convert(String name, short[] value) {
return new ShortArrayTag(name, value);
}
}

View File

@ -0,0 +1,21 @@
package org.spacehq.opennbt.conversion.builtin.custom;
import org.spacehq.opennbt.conversion.TagConverter;
import org.spacehq.opennbt.tag.builtin.custom.StringArrayTag;
/**
* A converter that converts between StringArrayTag and String[].
*/
public class StringArrayTagConverter implements TagConverter<StringArrayTag, String[]> {
@Override
public String[] convert(StringArrayTag tag) {
return tag.getValue();
}
@Override
public StringArrayTag convert(String name, String[] value) {
return new StringArrayTag(name, value);
}
}

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt;
package org.spacehq.opennbt.tag;
/**
* An exception thrown when an error occurs while created a tag instance.

View File

@ -1,9 +1,9 @@
package org.spacehq.opennbt;
package org.spacehq.opennbt.tag;
/**
* An exception thrown when an error occurs while registering a tag class.
* An exception thrown when an error occurs while registering a tag.
*/
public class TagRegisterException extends Exception {
public class TagRegisterException extends RuntimeException {
private static final long serialVersionUID = -2022049594558041160L;

View File

@ -1,7 +1,7 @@
package org.spacehq.opennbt;
package org.spacehq.opennbt.tag;
import org.spacehq.opennbt.tag.*;
import org.spacehq.opennbt.tag.custom.*;
import org.spacehq.opennbt.tag.builtin.*;
import org.spacehq.opennbt.tag.builtin.custom.*;
import java.lang.reflect.Constructor;
import java.util.HashMap;
@ -16,29 +16,25 @@ public class TagRegistry {
private static final Map<Class<? extends Tag>, Integer> tagToId = new HashMap<Class<? extends Tag>, Integer>();
static {
try {
register(1, ByteTag.class);
register(2, ShortTag.class);
register(3, IntTag.class);
register(4, LongTag.class);
register(5, FloatTag.class);
register(6, DoubleTag.class);
register(7, ByteArrayTag.class);
register(8, StringTag.class);
register(9, ListTag.class);
register(10, CompoundTag.class);
register(11, IntArrayTag.class);
register(1, ByteTag.class);
register(2, ShortTag.class);
register(3, IntTag.class);
register(4, LongTag.class);
register(5, FloatTag.class);
register(6, DoubleTag.class);
register(7, ByteArrayTag.class);
register(8, StringTag.class);
register(9, ListTag.class);
register(10, CompoundTag.class);
register(11, IntArrayTag.class);
register(60, DoubleArrayTag.class);
register(61, FloatArrayTag.class);
register(62, LongArrayTag.class);
register(63, SerializableArrayTag.class);
register(64, SerializableTag.class);
register(65, ShortArrayTag.class);
register(66, StringArrayTag.class);
} catch(TagRegisterException e) {
throw new RuntimeException("Failed to register default tags.", e);
}
register(60, DoubleArrayTag.class);
register(61, FloatArrayTag.class);
register(62, LongArrayTag.class);
register(63, SerializableArrayTag.class);
register(64, SerializableTag.class);
register(65, ShortArrayTag.class);
register(66, StringArrayTag.class);
}
/**

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,9 +1,10 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import org.spacehq.opennbt.NBTIO;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
@ -132,29 +133,6 @@ public class CompoundTag extends Tag implements Iterable<Tag> {
this.value.clear();
}
/**
* Converts this CompoundTag to a Map<String, Object> with non-tag values.
* @return A Map<String, Object> with non-tag values.
*/
public Map<String, Object> toMap() {
Map<String, Object> ret = new HashMap<String, Object>();
for(String name : this.value.keySet()) {
Tag tag = this.value.get(name);
Object o = null;
if(tag instanceof CompoundTag) {
o = ((CompoundTag) tag).toMap();
} else if(tag instanceof ListTag) {
o = ((ListTag) tag).toList();
} else {
o = tag.getValue();
}
ret.put(name, o);
}
return ret;
}
@Override
public Iterator<Tag> iterator() {
return this.values().iterator();
@ -162,7 +140,16 @@ public class CompoundTag extends Tag implements Iterable<Tag> {
@Override
public void read(DataInputStream in) throws IOException {
List<Tag> tags = NBTIO.readUntilEndTag(in);
List<Tag> tags = new ArrayList<Tag>();
try {
Tag tag;
while((tag = NBTIO.readTag(in)) != null) {
tags.add(tag);
}
} catch(EOFException e) {
throw new IOException("Closing EndTag was not found!");
}
for(Tag tag : tags) {
this.put(tag);
}
@ -170,7 +157,10 @@ public class CompoundTag extends Tag implements Iterable<Tag> {
@Override
public void write(DataOutputStream out) throws IOException {
NBTIO.writeTags(out, this.value.values());
for(Tag tag : this.value.values()) {
NBTIO.writeTag(out, tag);
}
out.writeByte(0);
}

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,20 +1,22 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import org.spacehq.opennbt.TagCreateException;
import org.spacehq.opennbt.TagRegistry;
import org.spacehq.opennbt.tag.TagCreateException;
import org.spacehq.opennbt.tag.TagRegistry;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* A tag containing a list of tags.
*/
public class ListTag<T extends Tag> extends Tag implements Iterable<T> {
public class ListTag extends Tag implements Iterable<Tag> {
private Class<T> type;
private List<T> value;
private Class<? extends Tag> type;
private List<Tag> value;
/**
* Creates a tag with the specified name.
@ -31,26 +33,41 @@ public class ListTag<T extends Tag> extends Tag implements Iterable<T> {
* @param name The name of the tag.
* @param type Tag type of the list.
*/
public ListTag(String name, Class<T> type) {
this(name, type, new ArrayList<T>());
public ListTag(String name, Class<? extends Tag> type) {
super(name);
this.type = type;
this.value = new ArrayList<Tag>();
}
/**
* Creates a tag with the specified name.
*
* @param name The name of the tag.
* @param type Tag type of the list.
* @param value The value of the tag.
* @throws IllegalArgumentException If all tags in the list are not of the same type.
*/
public ListTag(String name, Class<T> type, List<T> value) {
public ListTag(String name, List<Tag> value) throws IllegalArgumentException {
super(name);
Class<? extends Tag> type = null;
for(Tag tag : value) {
if(tag == null) {
throw new IllegalArgumentException("List cannot contain null tags.");
}
if(type == null) {
type = tag.getClass();
} else if(tag.getClass() != type) {
throw new IllegalArgumentException("All tags must be of the same type.");
}
}
this.type = type;
this.value = new ArrayList<T>(value);
this.value = new ArrayList<Tag>(value);
}
@Override
public List<T> getValue() {
return new ArrayList<T>(this.value);
public List<Tag> getValue() {
return new ArrayList<Tag>(this.value);
}
/**
@ -58,8 +75,14 @@ public class ListTag<T extends Tag> extends Tag implements Iterable<T> {
*
* @param value New value of this tag.
*/
public void setValue(List<T> value) {
this.value = new ArrayList<T>(value);
public void setValue(List<Tag> value) {
for(Tag tag : value) {
if(tag.getClass() != this.type) {
throw new IllegalArgumentException("Tag type cannot differ from ListTag type.");
}
}
this.value = new ArrayList<Tag>(value);
}
/**
@ -67,7 +90,7 @@ public class ListTag<T extends Tag> extends Tag implements Iterable<T> {
*
* @return The ListTag's element type.
*/
public Class<T> getElementType() {
public Class<? extends Tag> getElementType() {
return this.type;
}
@ -77,7 +100,11 @@ public class ListTag<T extends Tag> extends Tag implements Iterable<T> {
* @param tag Tag to add.
* @return If the list was changed as a result.
*/
public boolean add(T tag) {
public boolean add(Tag tag) {
if(tag.getClass() != this.type) {
throw new IllegalArgumentException("Tag type cannot differ from ListTag type.");
}
return this.value.add(tag);
}
@ -87,7 +114,7 @@ public class ListTag<T extends Tag> extends Tag implements Iterable<T> {
* @param tag Tag to remove.
* @return If the list contained the tag.
*/
public boolean remove(T tag) {
public boolean remove(Tag tag) {
return this.value.remove(tag);
}
@ -97,8 +124,8 @@ public class ListTag<T extends Tag> extends Tag implements Iterable<T> {
* @param index Index of the tag.
* @return The tag at the given index.
*/
public T get(int index) {
return this.value.get(index);
public <T extends Tag> T get(int index) {
return (T) this.value.get(index);
}
/**
@ -110,39 +137,16 @@ public class ListTag<T extends Tag> extends Tag implements Iterable<T> {
return this.value.size();
}
/**
* Converts this CompoundTag to a List<Object> with non-tag values.
* @return A List<Object> with non-tag values.
*/
public List<Object> toList() {
List<Object> ret = new ArrayList<Object>();
for(Tag tag : this.value) {
Object o = null;
if(tag instanceof CompoundTag) {
o = ((CompoundTag) tag).toMap();
} else if(tag instanceof ListTag) {
o = ((ListTag) tag).toList();
} else {
o = tag.getValue();
}
ret.add(o);
}
return ret;
}
@Override
public Iterator<T> iterator() {
public Iterator<Tag> iterator() {
return this.value.iterator();
}
@SuppressWarnings("unchecked")
@Override
public void read(DataInputStream in) throws IOException {
int id = in.readUnsignedByte();
this.type = (Class<T>) TagRegistry.getClassFor(id);
this.value = new ArrayList<T>();
this.type = TagRegistry.getClassFor(id);
this.value = new ArrayList<Tag>();
if(this.type == null) {
throw new IOException("Unknown tag ID in ListTag: " + id);
}
@ -157,7 +161,7 @@ public class ListTag<T extends Tag> extends Tag implements Iterable<T> {
}
tag.read(in);
this.add((T) tag);
this.add(tag);
}
}
@ -175,15 +179,14 @@ public class ListTag<T extends Tag> extends Tag implements Iterable<T> {
}
}
@SuppressWarnings("unchecked")
@Override
public ListTag<T> clone() {
List<T> newList = new ArrayList<T>();
for(T value : this.value) {
newList.add((T) value.clone());
public ListTag clone() {
List<Tag> newList = new ArrayList<Tag>();
for(Tag value : this.value) {
newList.add(value.clone());
}
return new ListTag<T>(this.getName(), this.type, newList);
return new ListTag(this.getName(), newList);
}
}

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import org.spacehq.opennbt.NBTIO;

View File

@ -1,4 +1,4 @@
package org.spacehq.opennbt.tag;
package org.spacehq.opennbt.tag.builtin;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,6 +1,6 @@
package org.spacehq.opennbt.tag.custom;
package org.spacehq.opennbt.tag.builtin.custom;
import org.spacehq.opennbt.tag.Tag;
import org.spacehq.opennbt.tag.builtin.Tag;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,6 +1,6 @@
package org.spacehq.opennbt.tag.custom;
package org.spacehq.opennbt.tag.builtin.custom;
import org.spacehq.opennbt.tag.Tag;
import org.spacehq.opennbt.tag.builtin.Tag;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,6 +1,6 @@
package org.spacehq.opennbt.tag.custom;
package org.spacehq.opennbt.tag.builtin.custom;
import org.spacehq.opennbt.tag.Tag;
import org.spacehq.opennbt.tag.builtin.Tag;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,6 +1,6 @@
package org.spacehq.opennbt.tag.custom;
package org.spacehq.opennbt.tag.builtin.custom;
import org.spacehq.opennbt.tag.Tag;
import org.spacehq.opennbt.tag.builtin.Tag;
import java.io.*;

View File

@ -1,6 +1,6 @@
package org.spacehq.opennbt.tag.custom;
package org.spacehq.opennbt.tag.builtin.custom;
import org.spacehq.opennbt.tag.Tag;
import org.spacehq.opennbt.tag.builtin.Tag;
import java.io.*;

View File

@ -1,6 +1,6 @@
package org.spacehq.opennbt.tag.custom;
package org.spacehq.opennbt.tag.builtin.custom;
import org.spacehq.opennbt.tag.Tag;
import org.spacehq.opennbt.tag.builtin.Tag;
import java.io.DataInputStream;
import java.io.DataOutputStream;

View File

@ -1,7 +1,7 @@
package org.spacehq.opennbt.tag.custom;
package org.spacehq.opennbt.tag.builtin.custom;
import org.spacehq.opennbt.NBTIO;
import org.spacehq.opennbt.tag.Tag;
import org.spacehq.opennbt.tag.builtin.Tag;
import java.io.DataInputStream;
import java.io.DataOutputStream;