package org.juxtapose.streamline.protocol.message; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.juxtapose.streamline.producer.ISTMEntryKey; 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.Message; import org.juxtapose.streamline.protocol.message.StreamDataProtocol.NullEntry; import org.juxtapose.streamline.protocol.message.StreamDataProtocol.ReferenceEntry; import org.juxtapose.streamline.protocol.message.StreamDataProtocol.RequestMessage; 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.protocol.message.StreamDataProtocol.SubQueryResponseMessage; import org.juxtapose.streamline.protocol.message.StreamDataProtocol.SubscribeMessage; import org.juxtapose.streamline.protocol.message.StreamDataProtocol.UpdateMessage; import org.juxtapose.streamline.util.ISTMEntry; 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.DataTypeNull; 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; /** * @author Pontus J�rgne * May 16, 2012 * Copyright (c) Pontus J�rgne. All rights reserved */ public class PreMarshaller { /** * @param inService * @param inQuery * @return */ public static Message createSubQuery( String inService, int inTag, Map<String, String> inQuery ) { SubQueryMessage.Builder builder = SubQueryMessage.newBuilder(); builder.setService( inService ); builder.setTag( inTag ); StringMap.Builder dataBuilder = StringMap.newBuilder(); for( Map.Entry<String, String> keyVal : inQuery.entrySet() ) { addStringValue( dataBuilder, keyVal.getKey(), keyVal.getValue() ); } builder.setQueryMap( dataBuilder.build() ); Message.Builder messBuilder = Message.newBuilder(); messBuilder.setSubQueryMessage( builder.build() ); messBuilder.setType( Message.Type.SubQueryMessage ); return messBuilder.build(); } /** * @param inReference * @return */ public static Message createSubscriptionMessage( int inReference ) { SubscribeMessage.Builder subMessB = SubscribeMessage.newBuilder(); subMessB.setReference( inReference ); Message.Builder messB = Message.newBuilder(); messB.setSubscribeMessage( subMessB ); messB.setType( Message.Type.SubscribeMessage ); return messB.build(); } public static Message createSubscriptionMessage( int inReference, ISTMEntryKey inKey ) { SubscribeMessage.Builder subMessB = SubscribeMessage.newBuilder(); DataKey key = createDataKey( inKey ); subMessB.setKey( key ); subMessB.setReference( inReference ); Message.Builder messB = Message.newBuilder(); messB.setSubscribeMessage( subMessB ); messB.setType( Message.Type.SubscribeMessage ); return messB.build(); } /** * @param inRef * @param inDataMap * @return */ public static Message createUpdateMessage( int inRef, ISTMEntry inEntry, boolean inFullUpdate, ISTMEntryKey inKey ) { IPersistentMap<String, DataType<?>> dataMap = inEntry.getDataMap(); UpdateMessage.Builder builder = UpdateMessage.newBuilder(); builder.setReference( inRef ); builder.setFullupdate( inFullUpdate ); DataMap.Builder dataMapBuilder = DataMap.newBuilder(); if( inFullUpdate ) { parseMapValues( dataMap, dataMapBuilder ); } else { parseDeltaMapValues( dataMap, inEntry.getDeltaSet(), dataMapBuilder ); } builder.setData( dataMapBuilder.build() ); if( inKey != null ) { DataKey dKey = createDataKey( inKey ); } Message.Builder messBuilder = Message.newBuilder(); try { messBuilder.setUpdateMessage( builder.build() ); }catch( Throwable t ) { t.printStackTrace(); } messBuilder.setType( Message.Type.UpdateMessage ); return messBuilder.build(); } public static Message createUpdateMessage( int inRef, ISTMEntry inEntry, boolean inFullUpdate ) { return createUpdateMessage( inRef, inEntry, inFullUpdate, null ); } /** * @param inTag * @param inRef * @return */ public static Message createSubResponse( Long inTag, int inRef, Status inStatus ) { SubQueryResponseMessage.Builder builder = SubQueryResponseMessage.newBuilder(); builder.setReference( inRef ); builder.setTag( inTag.intValue() ); builder.setStatus( inStatus.ordinal() ); Message.Builder messBuilder = Message.newBuilder(); messBuilder.setSubQueryResponseMessage( builder.build() ); messBuilder.setType( Message.Type.SubQueryResponseMessage ); return messBuilder.build(); } /** * @param inTag * @param inRef * @param inStatus * @param inEntry * @return */ public static Message createSubResponse( Long inTag, int inRef, Status inStatus, ISTMEntryKey inKey, ISTMEntry inEntry ) { SubQueryResponseMessage.Builder builder = SubQueryResponseMessage.newBuilder(); builder.setReference( inRef ); builder.setTag( inTag.intValue() ); builder.setStatus( inStatus.ordinal() ); if( inEntry != null ) { DataMap.Builder dataBuilder = DataMap.newBuilder(); parseMapValues( inEntry.getDataMap(), dataBuilder ); builder.setData( dataBuilder.build() ); } if( inKey != null ) { DataKey dKey = createDataKey( inKey ); builder.setKey( dKey ); } Message.Builder messBuilder = Message.newBuilder(); messBuilder.setSubQueryResponseMessage( builder.build() ); messBuilder.setType( Message.Type.SubQueryResponseMessage ); return messBuilder.build(); } /** * @param inTag * @param inVariable * @param inData * @return */ public static Message createRequestMessage( int inTag, long inType, String inService, String inVariable, IPersistentMap<String, DataType<?>> inData ) { RequestMessage.Builder builder = RequestMessage.newBuilder(); builder.setTag( inTag ); builder.setService( inService ); if( inVariable != null) builder.setVariable( inVariable ); if( inData != null ) { DataMap.Builder dataMapBuilder = DataMap.newBuilder(); parseMapValues( inData, dataMapBuilder ); builder.setData( dataMapBuilder.build() ); builder.setType( inType ); } Message.Builder messBuilder = Message.newBuilder(); messBuilder.setType( Message.Type.RequestMessage ); messBuilder.setRequestMessage( builder.build() ); return messBuilder.build(); } /** * @param inKey * @return */ public static DataKey createDataKey( ISTMEntryKey inKey ) { DataKey.Builder dataKeyB = DataKey.newBuilder(); dataKeyB.setType( inKey.getType() ); dataKeyB.setService( inKey.getService() ); for( String key : inKey.getKeys() ) { String val = inKey.getValue( key ); StringEntry.Builder entryB = StringEntry.newBuilder(); entryB.setField( key ); entryB.setData( val ); dataKeyB.addStringEntries( entryB.build() ); } return dataKeyB.build(); } /** * @param inKey * @param inData * @param inBuilder */ public static void parseValueToMap( String inKey, DataType<?> inData, DataMap.Builder inBuilder ) { if( inData instanceof DataTypeString ) { StringEntry.Builder strBuilder = StringEntry.newBuilder(); strBuilder.setField( inKey ); strBuilder.setData( ((DataTypeString)inData).get() ); inBuilder.addStringEntries( strBuilder.build() ); } else if( inData instanceof DataTypeBigDecimal ) { DataTypeBigDecimal bd = (DataTypeBigDecimal)inData; BigDecimalEntry.Builder bdBuilder = BigDecimalEntry.newBuilder(); bdBuilder.setField( inKey ); bdBuilder.setScale( bd.get().scale()); bdBuilder.setIntBytes( ByteString.copyFrom( bd.get().unscaledValue().toByteArray() )); inBuilder.addBDEntries( bdBuilder.build() ); } if( inData instanceof DataTypeLong ) { LongEntry.Builder longBuilder = LongEntry.newBuilder(); longBuilder.setField( inKey ); longBuilder.setData( ((DataTypeLong)inData).get() ); inBuilder.addLongEntries( longBuilder.build() ); } if( inData instanceof DataTypeBoolean) { BooleanEntry.Builder booleanBuilder = BooleanEntry.newBuilder(); booleanBuilder.setField( inKey ); booleanBuilder.setData( ((DataTypeBoolean)inData).get() ); inBuilder.addBoolEntries( booleanBuilder.build() ); } if( inData instanceof DataTypeNull ) { NullEntry.Builder nullBuilder = NullEntry.newBuilder(); nullBuilder.setField( inKey ); inBuilder.addNullEntries( nullBuilder.build() ); } if( inData instanceof DataTypeHashMap ) { HashMapEntry.Builder dataMapBuilder = HashMapEntry.newBuilder(); dataMapBuilder.setField( inKey ); DataTypeHashMap hashMap = (DataTypeHashMap)inData; DataMap.Builder hashMapBuilder = DataMap.newBuilder(); parseMapValues( hashMap.get(), hashMapBuilder ); dataMapBuilder.setData( hashMapBuilder.build() ); inBuilder.addHashMapEntries( dataMapBuilder.build() ); } if( inData instanceof DataTypeArrayList ) { HashMapEntry.Builder dataMapBuilder = HashMapEntry.newBuilder(); dataMapBuilder.setField( inKey ); dataMapBuilder.setList( true ); DataTypeArrayList list = (DataTypeArrayList)inData; DataMap.Builder hashMapBuilder = DataMap.newBuilder(); parseListValues( (PersistentArrayList<DataType<?>>) list.get(), hashMapBuilder ); dataMapBuilder.setData( hashMapBuilder.build() ); inBuilder.addHashMapEntries( dataMapBuilder.build() ); } else if( inData instanceof DataTypeStatus ) { inBuilder.setStatus( ((DataTypeStatus)inData).get().ordinal() ); } else if( inData instanceof DataTypeRef ) { ISTMEntryKey entryKey = ((DataTypeRef)inData).get(); parseReference( inKey, entryKey, inBuilder, false ); } else if( inData instanceof DataTypeLazyRef ) { ISTMEntryKey entryKey = ((DataTypeLazyRef)inData).get(); parseReference( inKey, entryKey, inBuilder, true ); } } private static void parseReference( String inFieldKey, ISTMEntryKey entryKey, DataMap.Builder inBuilder, boolean inLazy ) { ReferenceEntry.Builder refBuilder = ReferenceEntry.newBuilder(); DataKey key = createDataKey( entryKey ); refBuilder.setField( inFieldKey ); refBuilder.setKey( key ); refBuilder.setLazy( inLazy ); inBuilder.addRefEntries( refBuilder.build() ); } /** * @param inDataMap * @param inBuilder */ public static void parseMapValues( IPersistentMap<String, DataType<?>> inDataMap, DataMap.Builder inBuilder ) { Iterator<Map.Entry<String, DataType<?>>> iterator = inDataMap.iterator(); while( iterator.hasNext() ) { Map.Entry<String, DataType<?>> entry = iterator.next(); parseValueToMap( entry.getKey(), entry.getValue(), inBuilder ); } } public static void parseDeltaMapValues( IPersistentMap<String, DataType<?>> inDataMap, Set<String> inDeltaSet, DataMap.Builder inBuilder ) { Iterator<String> iterator = inDeltaSet.iterator(); while( iterator.hasNext() ) { String key = iterator.next(); DataType<?> val = inDataMap.valAt( key ); parseValueToMap( key, val, inBuilder ); } } public static void parseListValues( PersistentArrayList<DataType<?>> inList, DataMap.Builder inBuilder ) { for( int i = 0; i < inList.size(); i++ ) { DataType<?> data = inList.get( i ); parseValueToMap( Integer.toString( i ), data, inBuilder ); } } /** * @param inData * @param inField * @param inValue */ public static void addStringValue( DataMap.Builder inData, String inField, String inValue ) { StringEntry.Builder strEntryBuilder = StringEntry.newBuilder(); strEntryBuilder.setData( inValue ); strEntryBuilder.setField( inField ); inData.addStringEntries( strEntryBuilder.build() ); } public static void addStringValue( StringMap.Builder inData, String inField, String inValue ) { StringEntry.Builder strEntryBuilder = StringEntry.newBuilder(); strEntryBuilder.setData( inValue ); strEntryBuilder.setField( inField ); inData.addStringEntries( strEntryBuilder.build() ); } }