use of com.vodafone360.people.service.io.Request.Type in project 360-Engine-for-Android by 360.
the class DecoderThread method run.
/**
* Thread's run function If the decoding queue contains any entries we
* decode the first response and add the decoded data to the response queue.
* If the decode queue is empty, the thread will become inactive. It is
* resumed when a raw data entry is added to the decode queue.
*/
public void run() {
LogUtils.logI("DecoderThread.run() [Start thread]");
while (mRunning) {
EngineId engineId = EngineId.UNDEFINED;
Type type = Type.PUSH_MSG;
int reqId = -1;
try {
if (mResponses.size() > 0) {
LogUtils.logI("DecoderThread.run() Decoding [" + mResponses.size() + "x] responses");
// Decode first entry in queue
RawResponse decode = mResponses.get(0);
reqId = decode.mReqId;
if (!decode.mIsPushMessage) {
// Attempt to get type from request
Request request = QueueManager.getInstance().getRequest(reqId);
if (request != null) {
type = request.mType;
engineId = request.mEngineId;
long backendResponseTime = decode.mTimeStamp - request.getAuthTimestamp();
LogUtils.logD("Backend response time was " + backendResponseTime + "ms");
} else {
type = Type.COMMON;
}
}
DecodedResponse response = mHessianDecoder.decodeHessianByteArray(reqId, decode.mData, type, decode.mIsCompressed, engineId);
// if we have a push message let's try to find out to which engine it should be routed
if ((response.getResponseType() == DecodedResponse.ResponseType.PUSH_MESSAGE.ordinal()) && (response.mDataTypes.get(0) != null)) {
// for push messages we have to override the engine id as it is parsed inside the hessian decoder
engineId = ((PushEvent) response.mDataTypes.get(0)).mEngineId;
response.mSource = engineId;
// TODO mSource should get the engineId inside the decoder once types for mDataTypes is out. see PAND-1805.
}
// the request ID.
if (type == Type.PUSH_MSG && reqId != 0 && engineId == EngineId.UNDEFINED) {
Request request = QueueManager.getInstance().getRequest(reqId);
if (request != null) {
engineId = request.mEngineId;
}
}
if (engineId == EngineId.UNDEFINED) {
LogUtils.logE("DecoderThread.run() Unknown engine for message with type[" + type.name() + "]");
// TODO: Throw Exception for undefined messages, as
// otherwise they might always remain on the Queue?
}
// Add data to response queue
HttpConnectionThread.logV("DecoderThread.run()", "Add message[" + decode.mReqId + "] to ResponseQueue for engine[" + engineId + "] with data [" + response.mDataTypes + "]");
mRespQueue.addToResponseQueue(response);
// Remove item from our list of responses.
mResponses.remove(0);
// be nice to the other threads
Thread.sleep(THREAD_SLEEP_TIME);
} else {
synchronized (this) {
// No waiting responses, so the thread should sleep.
try {
LogUtils.logV("DecoderThread.run() [Waiting for more responses]");
wait();
} catch (InterruptedException ie) {
// Do nothing
}
}
}
} catch (Throwable t) {
/*
* Keep thread running regardless of error. When something goes
* wrong we should remove response from queue and report error
* back to engine.
*/
if (mResponses.size() > 0) {
mResponses.remove(0);
}
if (type != Type.PUSH_MSG && engineId != EngineId.UNDEFINED) {
List<BaseDataType> list = new ArrayList<BaseDataType>();
// this error type was chosen to make engines remove request
// or retry
// we may consider using other error code later
ServerError error = new ServerError(ServerError.ErrorType.INTERNALERROR);
error.errorDescription = "Decoder thread was unable to decode server message";
list.add(error);
mRespQueue.addToResponseQueue(new DecodedResponse(reqId, list, engineId, DecodedResponse.ResponseType.SERVER_ERROR.ordinal()));
}
LogUtils.logE("DecoderThread.run() Throwable on reqId[" + reqId + "]", t);
}
}
LogUtils.logI("DecoderThread.run() [End thread]");
}
use of com.vodafone360.people.service.io.Request.Type in project 360-Engine-for-Android by 360.
the class HessianDecoder method decodeResponse.
/**
*
*
*
* @param is
* @param requestId
* @param type
* @param isZipped
* @param engineId
*
* @return
*
* @throws IOException
*/
@SuppressWarnings("unchecked")
private DecodedResponse decodeResponse(InputStream is, int requestId, Request.Type type, boolean isZipped, EngineId engineId) throws IOException {
boolean usesReplyTag = false;
int responseType = DecodedResponse.ResponseType.UNKNOWN.ordinal();
List<BaseDataType> resultList = new ArrayList<BaseDataType>();
mMicroHessianInput.init(is);
// skip start
// initial map tag or fail
int tag = is.read();
if (tag == 'r') {
// reply / response
// read major and minor
is.read();
is.read();
// read next tag
tag = is.read();
usesReplyTag = true;
}
if (tag == -1) {
return null;
}
// read reason string and throw exception
if (tag == 'f') {
ServerError zybErr = new ServerError(mMicroHessianInput.readFault().errString());
resultList.add(zybErr);
DecodedResponse decodedResponse = new DecodedResponse(requestId, resultList, engineId, DecodedResponse.ResponseType.SERVER_ERROR.ordinal());
return decodedResponse;
}
// this is not wrapped up in a hashtable
if (type == Request.Type.EXTERNAL_RPG_RESPONSE) {
LogUtils.logV("HessianDecoder.decodeResponse() EXTERNAL_RPG_RESPONSE");
if (tag != 'I') {
LogUtils.logE("HessianDecoder.decodeResponse() " + "tag!='I' Unexpected Hessian type:" + tag);
}
parseExternalResponse(resultList, is, tag);
DecodedResponse decodedResponse = new DecodedResponse(requestId, resultList, engineId, DecodedResponse.ResponseType.SERVER_ERROR.ordinal());
return decodedResponse;
}
// internal response: should contain a Map type - i.e. Hashtable
if (tag != 'M') {
LogUtils.logE("HessianDecoder.decodeResponse() tag!='M' Unexpected Hessian type:" + tag);
throw new IOException("Unexpected Hessian type");
} else if (// if we have a common request or sign in request
(type == Request.Type.COMMON) || (type == Request.Type.SIGN_IN) || (type == Request.Type.GET_MY_IDENTITIES) || (type == Request.Type.GET_AVAILABLE_IDENTITIES)) {
Hashtable<String, Object> map = (Hashtable<String, Object>) mMicroHessianInput.readHashMap(tag);
if (null == map) {
return null;
}
if (map.containsKey(KEY_SESSION)) {
AuthSessionHolder auth = new AuthSessionHolder();
Hashtable<String, Object> authHash = (Hashtable<String, Object>) map.get(KEY_SESSION);
resultList.add(auth.createFromHashtable(authHash));
responseType = DecodedResponse.ResponseType.LOGIN_RESPONSE.ordinal();
} else if (map.containsKey(KEY_CONTACT_LIST)) {
// contact list
getContacts(resultList, ((Vector<?>) map.get(KEY_CONTACT_LIST)));
responseType = DecodedResponse.ResponseType.GET_CONTACTCHANGES_RESPONSE.ordinal();
} else if (map.containsKey(KEY_USER_PROFILE_LIST)) {
Vector<Hashtable<String, Object>> upVect = (Vector<Hashtable<String, Object>>) map.get(KEY_USER_PROFILE_LIST);
for (Hashtable<String, Object> obj : upVect) {
resultList.add(UserProfile.createFromHashtable(obj));
}
responseType = DecodedResponse.ResponseType.GETME_RESPONSE.ordinal();
} else if (map.containsKey(KEY_USER_PROFILE)) {
Hashtable<String, Object> userProfileHash = (Hashtable<String, Object>) map.get(KEY_USER_PROFILE);
resultList.add(UserProfile.createFromHashtable(userProfileHash));
responseType = DecodedResponse.ResponseType.GETME_RESPONSE.ordinal();
} else if (// we have identity items in the map which we can parse
(map.containsKey(KEY_IDENTITY_LIST)) || (map.containsKey(KEY_AVAILABLE_IDENTITY_LIST))) {
int identityType = 0;
Vector<Hashtable<String, Object>> idcap = null;
if (map.containsKey(KEY_IDENTITY_LIST)) {
idcap = (Vector<Hashtable<String, Object>>) map.get(KEY_IDENTITY_LIST);
identityType = BaseDataType.MY_IDENTITY_DATA_TYPE;
responseType = DecodedResponse.ResponseType.GET_MY_IDENTITIES_RESPONSE.ordinal();
} else {
idcap = (Vector<Hashtable<String, Object>>) map.get(KEY_AVAILABLE_IDENTITY_LIST);
identityType = BaseDataType.AVAILABLE_IDENTITY_DATA_TYPE;
responseType = DecodedResponse.ResponseType.GET_AVAILABLE_IDENTITIES_RESPONSE.ordinal();
}
for (Hashtable<String, Object> obj : idcap) {
Identity id = new Identity(identityType);
resultList.add(id.createFromHashtable(obj));
}
} else if (type == Request.Type.GET_AVAILABLE_IDENTITIES) {
// we have an available identities response, but it is empty
responseType = DecodedResponse.ResponseType.GET_AVAILABLE_IDENTITIES_RESPONSE.ordinal();
} else if (type == Request.Type.GET_MY_IDENTITIES) {
// we have a my identities response, but it is empty
responseType = DecodedResponse.ResponseType.GET_MY_IDENTITIES_RESPONSE.ordinal();
} else if (map.containsKey(KEY_ACTIVITY_LIST)) {
Vector<Hashtable<String, Object>> activityList = (Vector<Hashtable<String, Object>>) map.get(KEY_ACTIVITY_LIST);
for (Hashtable<String, Object> obj : activityList) {
resultList.add(ActivityItem.createFromHashtable(obj));
}
responseType = DecodedResponse.ResponseType.GET_ACTIVITY_RESPONSE.ordinal();
}
} else if ((type != Request.Type.COMMON) && (type != Request.Type.SIGN_IN)) {
// get initial hash table
// TODO: we cast every response to a Map, losing e.g. push event
// "c0" which only contains a string - to fix
Hashtable<String, Object> hash = (Hashtable<String, Object>) mMicroHessianInput.decodeType(tag);
responseType = decodeResponseByRequestType(resultList, hash, type);
}
if (usesReplyTag) {
// read the last 'z'
is.read();
}
DecodedResponse decodedResponse = new DecodedResponse(requestId, resultList, engineId, responseType);
return decodedResponse;
}
use of com.vodafone360.people.service.io.Request.Type in project 360-Engine-for-Android by 360.
the class HessianDecoder method parsePushPayload.
private void parsePushPayload(RpgPushMessage msg, List<BaseDataType> list) {
// convert push msg type string to PushMsgType
PushMessageTypes type = msg.mType;
EngineId engineId = EngineId.UNDEFINED;
if (type != null) {
switch(type) {
case CHAT_MESSAGE:
LogUtils.logV("Parse incomming chat_message");
engineId = EngineId.PRESENCE_ENGINE;
list.add(new PushChatMessageEvent(msg, engineId));
return;
case AVAILABILITY_STATE_CHANGE:
LogUtils.logV("Parse availability state change:");
engineId = EngineId.PRESENCE_ENGINE;
list.add(PushAvailabilityEvent.createPushEvent(msg, engineId));
return;
case START_CONVERSATION:
LogUtils.logV("Parse new conversation event:");
engineId = EngineId.PRESENCE_ENGINE;
list.add(new PushChatConversationEvent(msg, engineId));
return;
case CLOSED_CONVERSATION:
LogUtils.logV("Parse closed conversation event:");
engineId = EngineId.PRESENCE_ENGINE;
list.add(new PushClosedConversationEvent(msg, engineId));
return;
case CONVERSATION_END:
break;
// API events create push message type
case PROFILE_CHANGE:
engineId = EngineId.SYNCME_ENGINE;
break;
case CONTACTS_CHANGE:
engineId = EngineId.CONTACT_SYNC_ENGINE;
break;
case TIMELINE_ACTIVITY_CHANGE:
case STATUS_ACTIVITY_CHANGE:
engineId = EngineId.ACTIVITIES_ENGINE;
break;
case FRIENDSHIP_REQUEST_RECEIVED:
break;
case IDENTITY_CHANGE:
engineId = EngineId.IDENTITIES_ENGINE;
break;
case IDENTITY_NETWORK_CHANGE:
engineId = EngineId.IDENTITIES_ENGINE;
break;
case SYSTEM_NOTIFICATION:
LogUtils.logE("SYSTEM_NOTIFICATION push msg:" + msg.mHash);
list.add(SystemNotification.createFromHashtable(msg.mHash, engineId));
return;
default:
}
list.add(PushEvent.createPushEvent(msg, engineId));
}
}
use of com.vodafone360.people.service.io.Request.Type in project 360-Engine-for-Android by 360.
the class NativeContactsApi2 method readOrganization.
/**
* Reads an organization detail as a {@link ContactChange} from the provided
* cursor. For this type of detail we need to use a VCARD (semicolon
* separated) value. In reality two different changes may be read if a title
* is also present.
*
* @param cursor Cursor to read from
* @param ccList List of Contact Changes to add read detail data
* @param nabContactId ID of the NAB Contact
*/
private void readOrganization(Cursor cursor, List<ContactChange> ccList, long nabContactId) {
final int type = CursorUtils.getInt(cursor, Organization.TYPE);
int flags = mapFromNabOrganizationType(type);
final boolean isPrimary = CursorUtils.getInt(cursor, Organization.IS_PRIMARY) != 0;
if (isPrimary) {
flags |= ContactChange.FLAG_PREFERRED;
}
final long nabDetailId = CursorUtils.getLong(cursor, Organization._ID);
if (!mHaveReadOrganization) {
// VCard Helper data type (CAB)
final Organisation organization = new Organisation();
// Company
organization.name = CursorUtils.getString(cursor, Organization.COMPANY);
// Department
final String department = CursorUtils.getString(cursor, Organization.DEPARTMENT);
if (!TextUtils.isEmpty(department)) {
organization.unitNames.add(department);
}
if ((organization.unitNames != null && organization.unitNames.size() > 0) || !TextUtils.isEmpty(organization.name)) {
final ContactChange cc = new ContactChange(ContactChange.KEY_VCARD_ORG, VCardHelper.makeOrg(organization), flags);
cc.setNabContactId(nabContactId);
cc.setNabDetailId(nabDetailId);
ccList.add(cc);
mHaveReadOrganization = true;
}
// Title
final String title = CursorUtils.getString(cursor, Organization.TITLE);
if (!TextUtils.isEmpty(title)) {
final ContactChange cc = new ContactChange(ContactChange.KEY_VCARD_TITLE, title, flags);
cc.setNabContactId(nabContactId);
cc.setNabDetailId(nabDetailId);
ccList.add(cc);
mHaveReadOrganization = true;
}
}
}
use of com.vodafone360.people.service.io.Request.Type in project 360-Engine-for-Android by 360.
the class PeopleContactsApi method updateNativeContact.
/**
* Updates a native contact in the people database.
*
* Note: it assumes that the changes come from native as it sets flags
* to prevent syncing back to native
*
* @param contact the contact changes to apply to the contact
*/
public void updateNativeContact(ContactChange[] contact) {
mAddedDetails.clear();
mDeletedDetails.clear();
mUpdatedDetails.clear();
for (int i = 0; i < contact.length; i++) {
final ContactChange change = contact[i];
// convert the ContactChange into a ContactDetail
final ContactDetail detail = mDbh.convertContactChange(change);
final int type = change.getType();
switch(type) {
case ContactChange.TYPE_ADD_DETAIL:
mAddedDetails.add(detail);
break;
case ContactChange.TYPE_DELETE_DETAIL:
mDeletedDetails.add(detail);
break;
case ContactChange.TYPE_UPDATE_DETAIL:
mUpdatedDetails.add(detail);
break;
}
}
if (mAddedDetails.size() > 0) {
mDbh.syncAddContactDetailList(mAddedDetails, true, false);
}
if (mDeletedDetails.size() > 0) {
mDbh.syncDeleteContactDetailList(mDeletedDetails, true, false);
}
if (mUpdatedDetails.size() > 0) {
mDbh.syncModifyContactDetailList(mUpdatedDetails, true, false);
}
// TODO: Throttle the event
mDbh.fireDatabaseChangedEvent(DatabaseChangeType.CONTACTS, true);
}
Aggregations