/**
* $Id: $
* $Date: $
*
*/
package org.xmlsh.types.xtypes;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.xmlsh.core.InvalidArgumentException;
import org.xmlsh.core.XValue;
import org.xmlsh.sh.shell.SerializeOpts;
import org.xmlsh.types.TypeFamily;
import org.xmlsh.types.XTypeUtils;
import org.xmlsh.util.Util;
import org.xmlsh.util.XNamedValue;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
/*
* Generic Properties
* A set of Name/Value pairs to any object
*/
public class XValueMap extends AbstractMap<String,XValue> implements IXValueMap {
private Map<String,XValue> mMap;
public XValueMap(XValueMap that) {
mMap = new HashMap<>(that.mMap );
}
public XValueMap() {
mMap = new HashMap<>();
}
public XValueMap(int extent)
{
mMap = new HashMap<>(extent);
}
public static XValueMap emptyMap() {
return new XValueMap();
}
@Override
public XValue get( String name ) {
return mMap.get(name);
}
// How many entries
@Override
public int size() { return mMap.size() ; }
@Override
public boolean isEmpty() { return mMap.isEmpty() ; }
@JsonAnyGetter
public Map<String,XValue> properties(){ return mMap ; }
@Override
public void removeAll() {
mMap.clear();
}
@Override
public XValue put(String key, XValue value)
{
assert( key != null );
assert( value != null );
return mMap.put(key, value);
}
/* (non-Javadoc)
* @see org.xmlsh.core.IXValueMap#keySet()
*/
@Override
public Set<String> keySet()
{
return mMap.keySet();
}
@Override
public Collection<XValue> values()
{
return mMap.values();
}
@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<String, XValue> entry : mMap.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("}");
}
}
public void addAll( XValueMap map )
{
mMap.putAll(map.mMap);
}
public void put(String key , boolean value )
{
put( key , XValue.newXValue(value));
}
// special string->string that avoids conversion exception
public void put(String key, String value) {
put( key , XValue.newXValue(value));
}
public <T> void put(String key, T value) throws InvalidArgumentException
{
if( value instanceof XValue )
put( key , (XValue) value );
else
put( key , XValue.newXValue(null,value) );
}
public void put( XValueProperty prop ) {
put( prop.getName() , prop.getValue() );
}
@Override
public Set<java.util.Map.Entry<String, XValue>> entrySet()
{
return mMap.entrySet();
}
// Adds an XValue if it can turn it into a property or property set
public boolean add(XValue arg)
{
if( arg.isInstanceOf( XValueMap.class ))
addAll( ((XValueMap) arg.asObject()) );
else
if( arg.isInstanceOf( XValueProperty.class ))
add( ((XValueProperty) arg.asObject()) );
else
// Maybe too much hack
try {
put( XTypeUtils.newNamedValue( arg ) );
} catch (InvalidArgumentException e) {
Util.wrapException(e,IllegalArgumentException.class);
}
return true ;
}
public void put(XNamedValue nv )
{
if( Util.isBlank(nv.getName()))
throw new IllegalArgumentException( "Cannot add an entry to a map with an empty key");
put( nv.getName() , nv.getValue() );
}
@Override
public boolean isMap()
{
return true;
}
@Override
public boolean isList()
{
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isAtomic()
{
// TODO Auto-generated method stub
return false;
}
@Override
public XValue append(XValue item) {
XValueMap newMap = new XValueMap(this);
newMap.add(item);
return XValue.newXValue(newMap);
}
public void add(XValueProperty prop) {
put( prop.getName() , prop.getValue() );
}
@Override
public Iterator<XValue> iterator() {
return mMap.values().iterator();
}
@Override
public XValue asXValue() throws InvalidArgumentException
{
return XValue.newXValue( TypeFamily.XTYPE , this );
}
@Override
public boolean isContainer()
{
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isSequence()
{
// TODO Auto-generated method stub
return false;
}
@Override
public IXValueContainer asXContainer()
{
// TODO Auto-generated method stub
return this;
}
public List<XValueProperty> asPropertyList() {
List<XValueProperty> list = new ArrayList<>(this.size());
Set<java.util.Map.Entry<String, XValue>> entries = entrySet();
for( java.util.Map.Entry<String, XValue> e : entries )
list.add(new XValueProperty( e.getKey(), e.getValue()));
return list ;
}
@Override
public IXValueMap asXMap()
{
return this;
}
@Override
public IXValueList asXList()
{
return new XValueList( values() );
}
@Override
public IXValueSequence<? extends IXValueSequence<?>> asXSequence()
{
return new XValueSequence( values( ));
}
public void put(java.util.Map.Entry<String, XValue> e)
{
put( e.getKey() , e.getValue() );
}
@Override
public boolean containsKey(String key) {
return mMap.containsKey(key);
}
}
/*
* Copyright (C) 2008-2012 David A. Lee.
*
* The contents of this file are subject to the "Simplified BSD License" (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy of the
* License at http://www.opensource.org/licenses/bsd-license.php
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the License for the specific language governing rights and limitations under the License.
*
* The Original Code is: all this file.
*
* The Initial Developer of the Original Code is David A. Lee
*
* Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
*
* Contributor(s): David A. Lee
*
*/