package net.minecraft.command.type.metadata;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.minecraft.command.parser.Parser;
import net.minecraft.command.type.metadata.MetaID.MetaType;
public class Metadata<D> implements IMetadata<D>
{
private final MetaType type;
private final List<MetaEntry<?, ? super D>> entries;
private final Set<MetaID<?>> ownEntries;
private Set<Metadata<? extends D>> childNodes;
private Metadata(final MetaType type, final Set<MetaID<?>> ownEntries)
{
this.type = type;
this.entries = new ArrayList<>(type.getCount());
this.ownEntries = ownEntries;
}
public Metadata(final MetaType type)
{
this(type, (Set<MetaID<?>>) null);
}
public Metadata(final MetaType type, final Metadata<? super D> parent)
{
this(type, new HashSet<MetaID<?>>(type.getCount()));
if (parent.type != type)
throw new IllegalArgumentException("Metadata of type " + type.name + " can't inherit from data of type " + parent.type.name);
parent.addChildNode(this);
}
private void addChildNode(final Metadata<? extends D> child)
{
if (this.childNodes == null)
this.childNodes = new HashSet<>();
this.childNodes.add(child);
for (final MetaEntry<?, ? super D> entry : this.entries)
if (entry != null)
child.addParentEntry(entry);
}
private void addParentEntry(final MetaEntry<?, ? super D> entry)
{
if (!this.ownEntries.contains(entry.id))
this.addEntry(entry);
}
// Checked...
@Override
@SuppressWarnings("unchecked")
public final <T> MetaEntry<T, ? super D> getEntry(final MetaID<T> metaID)
{
if (this.type != metaID.type)
return null;
final int id = metaID.getId();
return id < this.entries.size() ? (MetaEntry<T, ? super D>) this.entries.get(id) : null;
}
@Override
public final boolean canProvide(final MetaID<?> metaID)
{
if (this.type != metaID.type)
return false;
final int id = metaID.getId();
return id < this.entries.size() ? this.entries.get(id) != null : false;
}
@Override
public final <T> T getData(final MetaID<T> metaID, final Parser parser, final D parserData)
{
final MetaEntry<T, ? super D> entry = this.getEntry(metaID);
if (entry == null)
return null;
return entry.get(parser, parserData);
}
@Override
public final void addEntry(final MetaEntry<?, ? super D> entry)
{
if (this.type != entry.id.type)
throw new IllegalArgumentException("Metadata of type " + this.type.name + " can't store entries of type " + entry.id.type.name);
final int id = entry.id.getId();
if (this.ownEntries != null)
this.ownEntries.add(entry.id);
if (this.childNodes != null)
for (final Metadata<? extends D> child : this.childNodes)
child.addParentEntry(entry);
if (id < this.entries.size())
{
this.entries.set(id, entry);
return;
}
for (int i = this.entries.size(); i < id; ++i)
this.entries.add(null);
this.entries.add(entry);
}
}