package org.juxtapose.streamline.protocol.message;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.juxtapose.streamline.producer.ISTMEntryKey;
import static org.juxtapose.streamline.tools.STMUtil.*;
import org.juxtapose.streamline.protocol.message.StreamDataProtocol.BigDecimalEntry;
import org.juxtapose.streamline.protocol.message.StreamDataProtocol.BooleanEntry;
import org.juxtapose.streamline.protocol.message.StreamDataProtocol.DataKey;
import org.juxtapose.streamline.protocol.message.StreamDataProtocol.DataMap;
import org.juxtapose.streamline.protocol.message.StreamDataProtocol.HashMapEntry;
import org.juxtapose.streamline.protocol.message.StreamDataProtocol.LongEntry;
import org.juxtapose.streamline.protocol.message.StreamDataProtocol.ReferenceEntry;
import org.juxtapose.streamline.protocol.message.StreamDataProtocol.StringEntry;
import org.juxtapose.streamline.protocol.message.StreamDataProtocol.StringMap;
import org.juxtapose.streamline.protocol.message.StreamDataProtocol.SubQueryMessage;
import org.juxtapose.streamline.tools.DataConstants;
import org.juxtapose.streamline.tools.STMEntryKey;
import org.juxtapose.streamline.util.PersistentArrayList;
import org.juxtapose.streamline.util.Status;
import org.juxtapose.streamline.util.data.DataType;
import org.juxtapose.streamline.util.data.DataTypeArrayList;
import org.juxtapose.streamline.util.data.DataTypeBigDecimal;
import org.juxtapose.streamline.util.data.DataTypeBoolean;
import org.juxtapose.streamline.util.data.DataTypeHashMap;
import org.juxtapose.streamline.util.data.DataTypeLazyRef;
import org.juxtapose.streamline.util.data.DataTypeLong;
import org.juxtapose.streamline.util.data.DataTypeRef;
import org.juxtapose.streamline.util.data.DataTypeStatus;
import org.juxtapose.streamline.util.data.DataTypeString;
import com.google.protobuf.ByteString;
import com.trifork.clj_ds.IPersistentMap;
import com.trifork.clj_ds.PersistentHashMap;
/**
* @author Pontus J�rgne
* 25 apr 2013
* Copyright (c) Pontus J�rgne. All rights reserved
*/
public class PostMarshaller
{
public static interface IParseObject
{
public void update( String inField, DataType<?> inData );
}
public static class MapParseObject implements IParseObject
{
IPersistentMap<String, DataType<?>> map;
public MapParseObject( IPersistentMap<String, DataType<?>> inMap )
{
map = inMap;
}
@Override
public void update( String inField, DataType<?> inData )
{
map = map.assoc( inField, inData );
}
}
public static class ArrayParseObject implements IParseObject
{
SortedMap<String, DataType<?>> map;
public ArrayParseObject( SortedMap<String, DataType<?>> inMap )
{
map = inMap;
}
@Override
public void update( String inField, DataType<?> inData )
{
map.put( inField, inData );
}
}
/**
* @param inMessage
* @return
*/
public static final Map<String, String> parseQueryMap( SubQueryMessage inMessage )
{
StringMap dMap = inMessage.getQueryMap();
Map<String, String> queryMap = new HashMap<String, String>();
for( int i = 0; i < dMap.getStringEntriesCount(); i++ )
{
StringEntry snt = dMap.getStringEntries( i );
queryMap.put(snt.getField(), snt.getData());
}
return queryMap;
}
public static final ISTMEntryKey parseKey( DataKey inKey )
{
String keys[] = new String[ inKey.getStringEntriesCount() ];
String vals[] = new String[ inKey.getStringEntriesCount() ];
for( int i = 0; i < inKey.getStringEntriesCount(); i++ )
{
StringEntry entry = inKey.getStringEntries( i );
keys[i] = entry.getField();
vals[i] = entry.getData();
}
if( keys.length == 1 && DataConstants.FIELD_SINGLE_VALUE_DATA_KEY.equals( keys[0] ))
{
return createEntryKey( inKey.getService(), inKey.getType(), vals[0] );
}
else
{
return createEntryKey( inKey.getService(), inKey.getType(), keys, vals );
}
}
public static final void parseData( DataMap inDataMap, IParseObject inParseObject )
{
List<StringEntry> stringEntries = inDataMap.getStringEntriesList();
if( stringEntries != null && !stringEntries.isEmpty() )
{
for( StringEntry entry : stringEntries )
{
String field = entry.getField();
String data = entry.getData();
inParseObject.update( field, new DataTypeString(data) );
}
}
List<BigDecimalEntry> bdEntries = inDataMap.getBDEntriesList();
if( bdEntries != null && !bdEntries.isEmpty() )
{
for( BigDecimalEntry entry : bdEntries )
{
String field = entry.getField();
int scale = entry.getScale();
ByteString bs = entry.getIntBytes();
BigInteger bi = new BigInteger(bs.toByteArray());
BigDecimal bd = new BigDecimal(bi, scale);
inParseObject.update( field, new DataTypeBigDecimal(bd) );
}
}
List<LongEntry> longEntries = inDataMap.getLongEntriesList();
if( longEntries != null && !longEntries.isEmpty() )
{
for( LongEntry entry : longEntries )
{
String field = entry.getField();
long value = entry.getData();
inParseObject.update( field, new DataTypeLong( value ) );
}
}
List<BooleanEntry> boolEntries = inDataMap.getBoolEntriesList();
if( boolEntries != null && !boolEntries.isEmpty() )
{
for( BooleanEntry entry : boolEntries )
{
String field = entry.getField();
boolean value = entry.getData();
inParseObject.update( field, new DataTypeBoolean(value) );
}
}
List<HashMapEntry> hashMapEntries = inDataMap.getHashMapEntriesList();
if( hashMapEntries != null && !hashMapEntries.isEmpty() )
{
for( HashMapEntry entry : hashMapEntries )
{
String field = entry.getField();
DataMap dMap = entry.getData();
boolean list = entry.getList();
if( list )
{
PersistentArrayList<DataType<?>> arr = parseDataList( dMap );
inParseObject.update( field, new DataTypeArrayList( arr ) );
}
else
{
IPersistentMap< String, DataType<?>> subMap = PersistentHashMap.emptyMap();
subMap = parseDataMap( dMap, subMap );
inParseObject.update( field, new DataTypeHashMap(subMap) );
}
}
}
List<ReferenceEntry> refEntries = inDataMap.getRefEntriesList();
if( refEntries != null && !refEntries.isEmpty() )
{
for( ReferenceEntry refEntry : refEntries )
{
String field = refEntry.getField();
DataKey key = refEntry.getKey();
boolean lazy = refEntry.getLazy();
ISTMEntryKey entryKey = parseKey( key );
inParseObject.update( field, lazy ? new DataTypeLazyRef( entryKey ) : new DataTypeRef( entryKey ) );
}
}
}
public static final PersistentArrayList<DataType<?>> parseDataList( DataMap inDataMap )
{
PersistentArrayList<DataType<?>> perList = new PersistentArrayList<DataType<?>>();
TreeMap<String, DataType<?>> sortedMap = new TreeMap<String, DataType<?>>();
ArrayParseObject parseObject = new ArrayParseObject( sortedMap );
parseData( inDataMap, parseObject );
for( Map.Entry<String, DataType<?>> entry : sortedMap.entrySet() )
{
perList = perList.add( entry.getValue() );
}
return perList;
}
/**
* @param inDataMap
* @param inMap
* @return
*/
public static final IPersistentMap<String, DataType<?>> parseDataMap( DataMap inDataMap, IPersistentMap <String, DataType<?>> inMap )
{
IPersistentMap<String, DataType<?>> map = inMap;
MapParseObject parseObject = new MapParseObject( map );
parseData( inDataMap, parseObject );
map = parseObject.map;
if( inDataMap.hasStatus() )
{
Integer status = inDataMap.getStatus();
Status st = Status.values()[status];
map = map.assoc( DataConstants.FIELD_STATUS, new DataTypeStatus( st ) );
}
return map;
}
}