package org.xmlsh.types; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.xmlsh.core.CoreException; import org.xmlsh.core.InvalidArgumentException; import org.xmlsh.core.XValue; import org.xmlsh.sh.shell.SerializeOpts; import org.xmlsh.types.xtypes.XValueSequence; import org.xmlsh.util.JavaUtils; import org.xmlsh.util.Util; public class JavaTypeFamily extends AbstractTypeFamily implements ITypeFamily { private static final JavaTypeFamily _instance = new JavaTypeFamily(); private static final Object _nullValue = null ; @Override public boolean isClassOfFamily(Class<?> cls) { return true; } @Override public boolean isInstanceOfFamily(Object obj) { return true; } @Override public TypeFamily typeFamily() { return TypeFamily.JAVA; } @Override public String asString(Object value) { if( value == null ) return ""; return value.toString(); } @Override public int getSize(Object obj) { if(obj == null) return 0; return JavaUtils.getSize(obj); } @Override public XValue getXValue(Object obj, String ind) throws CoreException { if(obj == null) return nullXValue(); assert (!Util.isBlank(ind)); Object res = null; boolean isInt = Util.isInt(ind, false); if(isInt && JavaUtils.isArrayClass(obj.getClass())) res = JavaUtils.getIndexValue(obj, Util.parseInt(ind, 0)); else if( ! isAtomic(obj) ) res = JavaUtils.getNameIndexValue( obj , ind ); return getXValue(res); } @Override public void serialize(Object value, OutputStream out, SerializeOpts opts) throws IOException { if(value == null) return; out.write(JavaUtils.toByteArray(value, opts)); } @Override public boolean isEmpty(Object value) { return JavaUtils.isEmpty(value); } // Set a string indexed value @Override public XValue setXValue(XValue xobj, String ind, XValue value) throws CoreException { assert (xobj != null && !xobj.isNull()); if(xobj == null || xobj.isNull()) throw new CoreException("Cannot set indexed value to null object"); assert (!Util.isBlank(ind)); try { JavaUtils.setNameIndexedValue(xobj.asObject(), ind, value.asObject()); return xobj; } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { Util.wrapCoreException("Exception setting indexed value", e); } return xobj; } // Get all values of a collection or just this value @Override public List<XValue> getXValues(Object obj) throws InvalidArgumentException { if(obj == null) return Collections.emptyList(); if( JavaUtils.isContainerOf( obj , XValue.class ) ) return JavaUtils.<XValue>getValues( obj ); if( JavaUtils.isCollectionOf(obj ,XValue.class) ) return JavaUtils.<XValue>getValues( obj ); if( obj instanceof XValue ) return ((XValue)obj).getXValues(); if(JavaUtils.isContainer(obj)){ List<?> list = JavaUtils.getValues(obj); List<XValue> xlist = new ArrayList<>(list.size()); for( Object o : list ){ xlist.add( XValue.newXValue(o)); } return xlist ; } return Collections.singletonList(getXValue(obj)); } @Override public XValue getXValue(Object obj) throws InvalidArgumentException { if( obj == null ) return nullXValue() ; if( obj instanceof XValue ) return( (XValue) obj ); return XValue.newXValue( this, obj , false ); } @Override public boolean isAtomic(Object value) { return JavaUtils.isAtomicClass(value.getClass()); } @Override public XValue getXValue(Object obj, int index) throws CoreException { Object r = JavaUtils.getIndexValue(obj, index); return getXValue(r); } @Override public XValue setXValue(XValue xobj, int index, XValue value) throws CoreException { assert (xobj != null && !xobj.isNull()); if(xobj == null || xobj.isNull()) throw new CoreException("Cannot set indexed value to null object"); assert (index >= 0 ); try { JavaUtils.setNamePositionalValue(xobj.asObject(), index, value.asObject()); return xobj; } catch (SecurityException | IllegalArgumentException e) { Util.wrapCoreException("Exception setting indexed value", e); } return xobj; } @Override public Object nullValue() { return _nullValue; } @Override public XValue nullXValue() { try { return XValue.newXValue(this , _nullValue , false); } catch (InvalidArgumentException e) { throw new IllegalArgumentException(e); } } public static JavaTypeFamily getInstance() { return _instance; } @Override public boolean hasKey(Object obj, String key) { return JavaUtils.hasKey( obj , key ); } @Override public XValue append(Object value, XValue v) throws InvalidArgumentException { if( isContainer(value)){ /* Class common = JavaUtils.getCommonAncestor( JavaUtils.getContainedType(value) , v.asObject() ); Object newContainer = JavaUtils.newConatainerOf( value.getClass() , common ); JavaUtils.addAll( newContainer , value ); JavaUtils.add( newContainer , v.asObject() ); */ List<Object> ret = JavaUtils.getValues(value ); ret.add((Object) v.asObject()); return XValue.newXValue( TypeFamily.JAVA , ret ); } // Atomics - turn into Sequences return XValue.newXValue(new XValueSequence( getXValue(value) , v )); } @Override public boolean isContainer(Object obj) { assert( obj != null ); return JavaUtils.isContainerClass(obj.getClass()); } }