/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.databridge.receiver.thrift.converter;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.databridge.commons.AttributeType;
import org.wso2.carbon.databridge.commons.Event;
import org.wso2.carbon.databridge.commons.thrift.data.ThriftEventBundle;
import org.wso2.carbon.databridge.commons.utils.DataBridgeCommonsUtils;
import org.wso2.carbon.databridge.commons.utils.EventDefinitionConverterUtils;
import org.wso2.carbon.databridge.core.EventConverter;
import org.wso2.carbon.databridge.core.StreamTypeHolder;
import org.wso2.carbon.databridge.core.exception.EventConversionException;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* the util class that converts Events and its definitions in to various forms
*/
public final class ThriftEventConverter implements EventConverter {
public Object[] toObjectArray(ThriftEventBundle thriftEventBundle,
AttributeType[] attributeTypeOrder,
IndexCounter indexCounter) {
if (attributeTypeOrder != null) {
Object[] objects = new Object[attributeTypeOrder.length];
for (int i = 0; i < attributeTypeOrder.length; i++) {
switch (attributeTypeOrder[i]) {
case INT:
objects[i] = thriftEventBundle.getIntAttributeList().get(indexCounter.getIntCount());
indexCounter.incrementIntCount();
break;
case LONG:
objects[i] = thriftEventBundle.getLongAttributeList().get(indexCounter.getLongCount());
indexCounter.incrementLongCount();
break;
case STRING:
String stringValue = thriftEventBundle.getStringAttributeList().get(indexCounter.getStringCount());
if (stringValue.equals(EventDefinitionConverterUtils.nullString)) {
objects[i] = null;
} else {
objects[i] = stringValue;
}
indexCounter.incrementStringCount();
break;
case DOUBLE:
objects[i] = thriftEventBundle.getDoubleAttributeList().get(indexCounter.getDoubleCount());
indexCounter.incrementDoubleCount();
break;
case FLOAT:
objects[i] = thriftEventBundle.getDoubleAttributeList().get(indexCounter.getDoubleCount()).floatValue();
indexCounter.incrementDoubleCount();
break;
case BOOL:
objects[i] = thriftEventBundle.getBoolAttributeList().get(indexCounter.getBoolCount());
indexCounter.incrementBoolCount();
break;
}
}
return objects;
} else {
return null;
}
}
public List<Event> toEventList(Object eventBundle,
StreamTypeHolder streamTypeHolder) {
if (eventBundle instanceof ThriftEventBundle) {
return createEventList((ThriftEventBundle) eventBundle, streamTypeHolder);
} else {
throw new EventConversionException("Wrong type of event received " + eventBundle.getClass());
}
}
@Override
public int getSize(Object eventBundle) {
if (eventBundle instanceof ThriftEventBundle) {
ThriftEventBundle thriftEventBundle = (ThriftEventBundle) eventBundle;
int eventBundleSize = 0;
//arbitray data
if (thriftEventBundle.isSetArbitraryDataMapMap()){
Set<Map.Entry<Integer, Map<String, String>>> arbitraryDataMap = thriftEventBundle.getArbitraryDataMapMap().entrySet();
for (Map.Entry<Integer, Map<String, String>> arbitraryData : arbitraryDataMap){
eventBundleSize += DataBridgeCommonsUtils.getSize(arbitraryData.getValue());
}
eventBundleSize += arbitraryDataMap.size() * 4; // 4 byte per integer
eventBundleSize += arbitraryDataMap.size() * DataBridgeCommonsUtils.getReferenceSize() * 2; //for the reference
}
eventBundleSize += thriftEventBundle.getBoolAttributeListSize(); //1 byte per boolean field
eventBundleSize += thriftEventBundle.getBoolAttributeListSize() * DataBridgeCommonsUtils.getReferenceSize(); // for each reference
eventBundleSize += thriftEventBundle.getDoubleAttributeListSize() * 8; //8 bytes per double field
eventBundleSize += thriftEventBundle.getDoubleAttributeListSize() * DataBridgeCommonsUtils.getReferenceSize(); // for each double reference.
eventBundleSize += thriftEventBundle.getIntAttributeListSize() * 4; // 4 bytes per int field
eventBundleSize += thriftEventBundle.getIntAttributeListSize() * DataBridgeCommonsUtils.getReferenceSize(); // for each int reference
eventBundleSize += thriftEventBundle.getLongAttributeListSize() * 8; // 8 bytes per long field
eventBundleSize += thriftEventBundle.getLongAttributeListSize() * DataBridgeCommonsUtils.getReferenceSize(); // for each long reference
for (String aStringField : thriftEventBundle.getStringAttributeList()){
eventBundleSize += aStringField.getBytes().length;
}
eventBundleSize += thriftEventBundle.getStringAttributeListSize() * DataBridgeCommonsUtils.getReferenceSize(); // for each string reference
eventBundleSize += 4; //for eventNum field
eventBundleSize += DataBridgeCommonsUtils.getSize(thriftEventBundle.getSessionId());
eventBundleSize += 7 * DataBridgeCommonsUtils.getReferenceSize(); // for the references of list and string attributes in thrift event bundle
return eventBundleSize;
} else {
throw new EventConversionException("Wrong type of event received " + eventBundle.getClass());
}
}
@Override
public int getNumberOfEvents(Object eventBundle) {
if (eventBundle instanceof ThriftEventBundle) {
return ((ThriftEventBundle) eventBundle).getEventNum();
} else {
throw new EventConversionException("Wrong type event relieved " + eventBundle.getClass());
}
}
private List<Event> createEventList(ThriftEventBundle thriftEventBundle,
StreamTypeHolder streamTypeHolder) {
IndexCounter indexCounter = new IndexCounter();
List<Event> eventList = new ArrayList<>(thriftEventBundle.getEventNum());
String streamId = null;
try {
for (int i = 0; i < thriftEventBundle.getEventNum(); i++) {
Event event = new Event();
streamId = thriftEventBundle.getStringAttributeList().get(indexCounter.getStringCount());
indexCounter.incrementStringCount();
event.setStreamId(streamId);
long timeStamp = thriftEventBundle.getLongAttributeList().get(indexCounter.getLongCount());
indexCounter.incrementLongCount();
event.setTimeStamp(timeStamp);
AttributeType[][] attributeTypeOrder = streamTypeHolder.getDataType(streamId);
if (attributeTypeOrder == null) {
PrivilegedCarbonContext privilegedCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
if (privilegedCarbonContext.getTenantDomain() == null) {
privilegedCarbonContext.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME);
privilegedCarbonContext.setTenantId(MultitenantConstants.SUPER_TENANT_ID);
}
streamTypeHolder.reloadStreamTypeHolder();
attributeTypeOrder = streamTypeHolder.getDataType(streamId);
if (attributeTypeOrder == null) {
throw new EventConversionException("No StreamDefinition for streamId " + streamId + " present in cache ");
}
}
event.setMetaData(this.toObjectArray(thriftEventBundle, attributeTypeOrder[0], indexCounter));
event.setCorrelationData(this.toObjectArray(thriftEventBundle, attributeTypeOrder[1], indexCounter));
event.setPayloadData(this.toObjectArray(thriftEventBundle, attributeTypeOrder[2], indexCounter));
if (thriftEventBundle.isSetArbitraryDataMapMap()) {
Map<String, String> arbitraryData = thriftEventBundle.getArbitraryDataMapMap().get(i);
if (null != arbitraryData) {
event.setArbitraryDataMap(arbitraryData);
}
}
eventList.add(event);
}
} catch (RuntimeException re) {
throw new EventConversionException("Error when converting " + streamId + " of event bundle with events " + thriftEventBundle.getEventNum(), re);
}
return eventList;
}
}