package org.xmlsh.types.xtypes;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.AbstractList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import org.xmlsh.core.InvalidArgumentException;
import org.xmlsh.core.XValue;
import org.xmlsh.sh.shell.SerializeOpts;
import org.xmlsh.types.TypeFamily;
import org.xmlsh.util.Util;
/*
* A sparse array indexable by string or integer
* Default starts at index 1 (not 0)
*
*/
public class XValueArray extends AbstractList<XValue> implements IXValueMap, IXValueList
{
private TreeMap<Integer,XValue> mArray;
private int maxIndex = -1; // maximum integer value
public XValueArray() {
mArray = new TreeMap<>();
}
public XValueArray( XValueArray that ) {
mArray = new TreeMap<>( that.mArray );
}
public int extent() { return maxIndex ; }
@Override
public int size() { return mArray.size() ; }
@Override
public boolean isEmpty() { return mArray.isEmpty() ; }
@Override
public void removeAll() {
mArray.clear();
maxIndex = -1;
}
/*
* Different then setAt as it should shift everyting - not supported
@Override
public void add(int index, XValue element) {
}
*/
@Override
public boolean add( XValue arg )
{
mArray.put( Integer.valueOf(++maxIndex), arg);
return true ;
}
@Override
public Set<String> keySet()
{
TreeSet<String> s = new TreeSet<String>(
new Comparator<String>() {
@Override
public int compare(String o1, String o2)
{
return Integer.valueOf( o1).compareTo
(Integer.valueOf(o2));
}
});
for( Integer i : mArray.keySet() )
s.add( i.toString());
return s;
}
@Override
public Collection<XValue> values()
{
return mArray.values();
}
public void addAll(List<XValue> args)
{
for( XValue a : args )
add(a);
}
@Override
public void serialize(OutputStream out, SerializeOpts opts) throws IOException, InvalidArgumentException
{
try ( OutputStreamWriter ps = new OutputStreamWriter(out, opts.getInputTextEncoding() ) ){
String sep = "";
ps.write("[");
for( Entry<Integer, XValue> entry : mArray.entrySet() ) {
ps.write(sep);;
ps.write( "[" );
ps.write( entry.getKey().toString());
ps.write("]=");
ps.flush();
entry.getValue().serialize(out, opts);
ps.write(" ");
sep = ",";
}
ps.write("]");
}
}
@Override
public XValue get(int index)
{
return mArray.get(Integer.valueOf(index));
}
@Override
public boolean isMap()
{
return false;
}
@Override
public boolean isList()
{
return true;
}
@Override
public boolean isAtomic()
{
return false;
}
/*
* Create a new value by appending this one
* @see org.xmlsh.core.IXValueContainer#append(org.xmlsh.core.XValue)
*/
@Override
public XValue append(XValue item) throws InvalidArgumentException {
XValueArray newArray = new XValueArray(this);
newArray.add( item );
return XValue.newXValue( TypeFamily.XTYPE , newArray ) ;
}
@Override
public XValue getAt(int index)
{
return get(index);
}
@Override
public XValue setAt(int index, XValue value)
{
return mArray.put(index , value);
}
@Override
public XValue asXValue() throws InvalidArgumentException
{
return XValue.newXValue( TypeFamily.XTYPE , this );
}
@Override
public boolean isContainer()
{
return true ;
}
@Override
public boolean isSequence()
{
return false ;
}
@Override
public IXValueContainer asXContainer()
{
// TODO Auto-generated method stub
return this;
}
@Override
public IXValueMap asXMap()
{
return this;
}
@Override
public IXValueList asXList()
{
return this;
}
@Override
public IXValueSequence<? extends IXValueSequence<?>> asXSequence()
{
return new XValueSequence( this );
}
public static XValueArray emptyArray()
{
return new XValueArray();
}
@Override
public List<XValue> asList()
{
return Util.toList(iterator());
}
@Override
public XValue get(String name) {
return getAt( Util.parseInt(name, 0));
}
@Override
public XValue put(String key, XValue value) {
return setAt( Util.parseInt(key,0),value);
}
@Override
public boolean containsKey(String key) {
return mArray.containsKey(Util.parseInt(key,0));
}
}