use of org.matrix.androidsdk.rest.model.RoomMember in project matrix-android-sdk by matrix-org.
the class RoomState method applyState.
/**
* Apply the given event (relevant for state changes) to our state.
*
* @param store the store to use
* @param event the event
* @param direction how the event should affect the state: Forwards for applying, backwards for un-applying (applying the previous state)
* @return true if the event is managed
*/
public boolean applyState(IMXStore store, Event event, EventTimeline.Direction direction) {
if (event.stateKey == null) {
return false;
}
JsonObject contentToConsider = (direction == EventTimeline.Direction.FORWARDS) ? event.getContentAsJsonObject() : event.getPrevContentAsJsonObject();
String eventType = event.getType();
try {
if (Event.EVENT_TYPE_STATE_ROOM_NAME.equals(eventType)) {
name = JsonUtils.toRoomState(contentToConsider).name;
} else if (Event.EVENT_TYPE_STATE_ROOM_TOPIC.equals(eventType)) {
topic = JsonUtils.toRoomState(contentToConsider).topic;
} else if (Event.EVENT_TYPE_STATE_ROOM_CREATE.equals(eventType)) {
creator = JsonUtils.toRoomState(contentToConsider).creator;
} else if (Event.EVENT_TYPE_STATE_ROOM_JOIN_RULES.equals(eventType)) {
join_rule = JsonUtils.toRoomState(contentToConsider).join_rule;
} else if (Event.EVENT_TYPE_STATE_ROOM_GUEST_ACCESS.equals(eventType)) {
guest_access = JsonUtils.toRoomState(contentToConsider).guest_access;
} else if (Event.EVENT_TYPE_STATE_ROOM_ALIASES.equals(eventType)) {
if (!TextUtils.isEmpty(event.stateKey)) {
// backward compatibility
aliases = JsonUtils.toRoomState(contentToConsider).aliases;
// sanity check
if (null != aliases) {
mAliasesByDomain.put(event.stateKey, aliases);
mRoomAliases.put(event.stateKey, event);
} else {
mAliasesByDomain.put(event.stateKey, new ArrayList<String>());
}
}
} else if (Event.EVENT_TYPE_MESSAGE_ENCRYPTION.equals(eventType)) {
algorithm = JsonUtils.toRoomState(contentToConsider).algorithm;
// This flag should not be cleared if a later m.room.encryption event changes the configuration. This is to avoid a situation where a MITM can simply ask participants to disable encryption. In short: once encryption is enabled in a room, it can never be disabled.
if (null == algorithm) {
algorithm = "";
}
} else if (Event.EVENT_TYPE_STATE_CANONICAL_ALIAS.equals(eventType)) {
// SPEC-125
alias = JsonUtils.toRoomState(contentToConsider).alias;
} else if (Event.EVENT_TYPE_STATE_HISTORY_VISIBILITY.equals(eventType)) {
// SPEC-134
history_visibility = JsonUtils.toRoomState(contentToConsider).history_visibility;
} else if (Event.EVENT_TYPE_STATE_ROOM_AVATAR.equals(eventType)) {
url = JsonUtils.toRoomState(contentToConsider).url;
} else if (Event.EVENT_TYPE_STATE_RELATED_GROUPS.equals(eventType)) {
groups = JsonUtils.toRoomState(contentToConsider).groups;
} else if (Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(eventType)) {
RoomMember member = JsonUtils.toRoomMember(contentToConsider);
String userId = event.stateKey;
if (null == userId) {
Log.e(LOG_TAG, "## applyState() : null stateKey in " + roomId);
} else if (null == member) {
// the member has already been removed
if (null == getMember(userId)) {
Log.e(LOG_TAG, "## applyState() : the user " + userId + " is not anymore a member of " + roomId);
return false;
}
removeMember(userId);
} else {
try {
member.setUserId(userId);
member.setOriginServerTs(event.getOriginServerTs());
member.setOriginalEventId(event.eventId);
member.mSender = event.getSender();
if ((null != store) && (direction == EventTimeline.Direction.FORWARDS)) {
store.storeRoomStateEvent(roomId, event);
}
RoomMember currentMember = getMember(userId);
// duplicated message ?
if (member.equals(currentMember)) {
Log.e(LOG_TAG, "## applyState() : seems being a duplicated event for " + userId + " in room " + roomId);
return false;
}
// when a member leaves a room, his avatar / display name is not anymore provided
if (null != currentMember) {
if (TextUtils.equals(member.membership, RoomMember.MEMBERSHIP_LEAVE) || TextUtils.equals(member.membership, (RoomMember.MEMBERSHIP_BAN))) {
if (null == member.getAvatarUrl()) {
member.setAvatarUrl(currentMember.getAvatarUrl());
}
if (null == member.displayname) {
member.displayname = currentMember.displayname;
}
// remove the cached display name
if (null != mMemberDisplayNameByUserId) {
mMemberDisplayNameByUserId.remove(userId);
}
// test if the user has been kicked
if (!TextUtils.equals(event.getSender(), event.stateKey) && TextUtils.equals(currentMember.membership, RoomMember.MEMBERSHIP_JOIN) && TextUtils.equals(member.membership, RoomMember.MEMBERSHIP_LEAVE)) {
member.membership = RoomMember.MEMBERSHIP_KICK;
}
}
}
if ((direction == EventTimeline.Direction.FORWARDS) && (null != store)) {
store.updateUserWithRoomMemberEvent(member);
}
// Cache room member event that is successor of a third party invite event
if (!TextUtils.isEmpty(member.getThirdPartyInviteToken())) {
mMembersWithThirdPartyInviteTokenCache.put(member.getThirdPartyInviteToken(), member);
}
} catch (Exception e) {
Log.e(LOG_TAG, "## applyState() - EVENT_TYPE_STATE_ROOM_MEMBER failed " + e.getMessage());
}
setMember(userId, member);
}
} else if (Event.EVENT_TYPE_STATE_ROOM_POWER_LEVELS.equals(eventType)) {
powerLevels = JsonUtils.toPowerLevels(contentToConsider);
} else if (Event.EVENT_TYPE_STATE_ROOM_THIRD_PARTY_INVITE.equals(event.getType())) {
if (null != contentToConsider) {
RoomThirdPartyInvite thirdPartyInvite = JsonUtils.toRoomThirdPartyInvite(contentToConsider);
thirdPartyInvite.token = event.stateKey;
if ((direction == EventTimeline.Direction.FORWARDS) && (null != store)) {
store.storeRoomStateEvent(roomId, event);
}
if (!TextUtils.isEmpty(thirdPartyInvite.token)) {
mThirdPartyInvites.put(thirdPartyInvite.token, thirdPartyInvite);
}
}
}
// they are saved elsewhere
if (!TextUtils.isEmpty(eventType) && !Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(eventType)) {
List<Event> eventsList = mStateEvents.get(eventType);
if (null == eventsList) {
eventsList = new ArrayList<>();
mStateEvents.put(eventType, eventsList);
}
eventsList.add(event);
}
} catch (Exception e) {
Log.e(LOG_TAG, "applyState failed with error " + e.getMessage());
}
return true;
}
use of org.matrix.androidsdk.rest.model.RoomMember in project matrix-android-sdk by matrix-org.
the class RoomState method isConferenceUserRoom.
/**
* Tells if the room is a call conference one
* i.e. this room has been created to manage the call conference
*
* @return true if it is a call conference room.
*/
public boolean isConferenceUserRoom() {
// test if it is not yet initialized
if (null == mIsConferenceUserRoom) {
mIsConferenceUserRoom = false;
Collection<RoomMember> members = getMembers();
// works only with 1:1 room
if (2 == members.size()) {
for (RoomMember member : members) {
if (MXCallsManager.isConferenceUserId(member.getUserId())) {
mIsConferenceUserRoom = true;
break;
}
}
}
}
return mIsConferenceUserRoom;
}
use of org.matrix.androidsdk.rest.model.RoomMember in project matrix-android-sdk by matrix-org.
the class RoomState method canBackPaginated.
/**
* Check if the user userId can back paginate.
*
* @param userId the user Id.
* @return true if the user can backpaginate.
*/
public boolean canBackPaginated(String userId) {
RoomMember member = getMember(userId);
String membership = (null != member) ? member.membership : "";
String visibility = TextUtils.isEmpty(history_visibility) ? HISTORY_VISIBILITY_SHARED : history_visibility;
return visibility.equals(HISTORY_VISIBILITY_WORLD_READABLE) || visibility.equals(HISTORY_VISIBILITY_SHARED) || (RoomMember.MEMBERSHIP_JOIN.equals(membership)) || /*&&visibility == invited or joined */
(RoomMember.MEMBERSHIP_INVITE.equals(membership) && visibility.equals(HISTORY_VISIBILITY_INVITED));
}
use of org.matrix.androidsdk.rest.model.RoomMember in project matrix-android-sdk by matrix-org.
the class RoomState method deepCopy.
/**
* Make a deep copy of this room state object.
*
* @return the copy
*/
public RoomState deepCopy() {
RoomState copy = new RoomState();
copy.roomId = roomId;
copy.setPowerLevels((powerLevels == null) ? null : powerLevels.deepCopy());
copy.aliases = (aliases == null) ? null : new ArrayList<>(aliases);
copy.mAliasesByDomain = new HashMap<>(mAliasesByDomain);
copy.alias = this.alias;
copy.name = name;
copy.topic = topic;
copy.url = url;
copy.creator = creator;
copy.join_rule = join_rule;
copy.guest_access = guest_access;
copy.history_visibility = history_visibility;
copy.visibility = visibility;
copy.roomAliasName = roomAliasName;
copy.token = token;
copy.groups = groups;
copy.mDataHandler = mDataHandler;
copy.mMembership = mMembership;
copy.mIsLive = mIsLive;
copy.mIsConferenceUserRoom = mIsConferenceUserRoom;
copy.algorithm = algorithm;
copy.mRoomAliases = new HashMap<>(mRoomAliases);
copy.mStateEvents = new HashMap<>(mStateEvents);
synchronized (this) {
Iterator it = mMembers.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, RoomMember> pair = (Map.Entry<String, RoomMember>) it.next();
copy.setMember(pair.getKey(), pair.getValue().deepCopy());
}
Collection<String> keys = mThirdPartyInvites.keySet();
for (String key : keys) {
copy.mThirdPartyInvites.put(key, mThirdPartyInvites.get(key).deepCopy());
}
keys = mMembersWithThirdPartyInviteTokenCache.keySet();
for (String key : keys) {
copy.mMembersWithThirdPartyInviteTokenCache.put(key, mMembersWithThirdPartyInviteTokenCache.get(key).deepCopy());
}
}
return copy;
}
use of org.matrix.androidsdk.rest.model.RoomMember in project matrix-android-sdk by matrix-org.
the class MXFileStore method open.
/**
* Open the store.
*/
@Override
public void open() {
super.open();
final long fLoadTimeT0 = System.currentTimeMillis();
// avoid concurrency call.
synchronized (this) {
if (!mIsReady && !mIsOpening && (null != mMetadata) && (null != mHandlerThread)) {
mIsOpening = true;
Log.e(LOG_TAG, "Open the store.");
// creation the background handler.
if (null == mFileStoreHandler) {
// never succeeded to reproduce but it was reported in GA.
try {
mHandlerThread.start();
} catch (IllegalThreadStateException e) {
Log.e(LOG_TAG, "mHandlerThread is already started.");
// already started
return;
}
mFileStoreHandler = new MXOsHandler(mHandlerThread.getLooper());
}
Runnable r = new Runnable() {
@Override
public void run() {
mFileStoreHandler.post(new Runnable() {
public void run() {
Log.e(LOG_TAG, "Open the store in the background thread.");
String errorDescription = null;
boolean succeed = (mMetadata.mVersion == MXFILE_VERSION) && TextUtils.equals(mMetadata.mUserId, mCredentials.userId) && TextUtils.equals(mMetadata.mAccessToken, mCredentials.accessToken);
if (!succeed) {
errorDescription = "Invalid store content";
Log.e(LOG_TAG, errorDescription);
}
if (succeed) {
succeed &= loadRoomsMessages();
if (!succeed) {
errorDescription = "loadRoomsMessages fails";
Log.e(LOG_TAG, errorDescription);
} else {
Log.e(LOG_TAG, "loadRoomsMessages succeeds");
}
}
if (succeed) {
succeed &= loadGroups();
if (!succeed) {
errorDescription = "loadGroups fails";
Log.e(LOG_TAG, errorDescription);
} else {
Log.e(LOG_TAG, "loadGroups succeeds");
}
}
if (succeed) {
succeed &= loadRoomsState();
if (!succeed) {
errorDescription = "loadRoomsState fails";
Log.e(LOG_TAG, errorDescription);
} else {
Log.e(LOG_TAG, "loadRoomsState succeeds");
long t0 = System.currentTimeMillis();
Log.e(LOG_TAG, "Retrieve the users from the roomstate");
Collection<Room> rooms = getRooms();
for (Room room : rooms) {
Collection<RoomMember> members = room.getLiveState().getMembers();
for (RoomMember member : members) {
updateUserWithRoomMemberEvent(member);
}
}
long delta = System.currentTimeMillis() - t0;
Log.e(LOG_TAG, "Retrieve " + mUsers.size() + " users with the room states in " + delta + " ms");
mStoreStats.put("Retrieve users", delta);
}
}
if (succeed) {
succeed &= loadSummaries();
if (!succeed) {
errorDescription = "loadSummaries fails";
Log.e(LOG_TAG, errorDescription);
} else {
Log.e(LOG_TAG, "loadSummaries succeeds");
for (String roomId : mRoomSummaries.keySet()) {
Room room = getRoom(roomId);
if (null == room) {
succeed = false;
Log.e(LOG_TAG, "loadSummaries : the room " + roomId + " does not exist");
} else if (null == room.getMember(mCredentials.userId)) {
// succeed = false;
Log.e(LOG_TAG, "loadSummaries) : a summary exists for the roomId " + roomId + " but the user is not anymore a member");
}
}
}
}
if (succeed) {
succeed &= loadRoomsAccountData();
if (!succeed) {
errorDescription = "loadRoomsAccountData fails";
Log.e(LOG_TAG, errorDescription);
} else {
Log.e(LOG_TAG, "loadRoomsAccountData succeeds");
}
}
// assume that something is corrupted
if (!succeed) {
Log.e(LOG_TAG, "Fail to open the store in background");
// delete all data set mMetadata to null
// backup it to restore it
// the behaviour should be the same as first login
MXFileStoreMetaData tmpMetadata = mMetadata;
deleteAllData(true);
mRoomsToCommitForMessages = new HashSet<>();
mRoomsToCommitForStates = new HashSet<>();
// mRoomsToCommitForStatesEvents = new HashSet<>();
mRoomsToCommitForSummaries = new HashSet<>();
mRoomsToCommitForReceipts = new HashSet<>();
mMetadata = tmpMetadata;
// mMetadata should only be null at file store loading
if (null == mMetadata) {
mMetadata = new MXFileStoreMetaData();
mMetadata.mUserId = mCredentials.userId;
mMetadata.mAccessToken = mCredentials.accessToken;
mMetaDataHasChanged = true;
} else {
mMetadata.mEventStreamToken = null;
}
mMetadata.mVersion = MXFILE_VERSION;
// the event stream token is put to zero to ensure ta
mEventStreamToken = null;
mAreReceiptsReady = true;
} else {
Log.d(LOG_TAG, "++ store stats");
Set<String> roomIds = mRoomEvents.keySet();
for (String roomId : roomIds) {
Room room = getRoom(roomId);
if ((null != room) && (null != room.getLiveState())) {
int membersCount = room.getLiveState().getMembers().size();
int eventsCount = mRoomEvents.get(roomId).size();
Log.d(LOG_TAG, " room " + roomId + " : membersCount " + membersCount + " - eventsCount " + eventsCount);
}
}
Log.d(LOG_TAG, "-- store stats");
}
// post processing
Log.d(LOG_TAG, "## open() : post processing.");
dispatchPostProcess(mCredentials.userId);
mIsPostProcessingDone = true;
synchronized (this) {
mIsReady = true;
}
mIsOpening = false;
if (!succeed && !mIsNewStorage) {
Log.e(LOG_TAG, "The store is corrupted.");
dispatchOnStoreCorrupted(mCredentials.userId, errorDescription);
} else {
// extract the room states
mRoomReceiptsToLoad.addAll(listFiles(mStoreRoomsMessagesReceiptsFolderFile.list()));
mPreloadTime = System.currentTimeMillis() - fLoadTimeT0;
Log.e(LOG_TAG, "The store is opened.");
dispatchOnStoreReady(mCredentials.userId);
// load the following items with delay
// theses items are not required to be ready
// load the receipts
loadReceipts();
// load the users
loadUsers();
}
}
});
}
};
Thread t = new Thread(r);
t.start();
} else if (mIsReady) {
Runnable r = new Runnable() {
@Override
public void run() {
mFileStoreHandler.post(new Runnable() {
@Override
public void run() {
// should never happen
if (!mIsPostProcessingDone && !mIsNewStorage) {
Log.e(LOG_TAG, "## open() : is ready but the post processing was not yet done : please wait....");
return;
} else {
if (!mIsPostProcessingDone) {
Log.e(LOG_TAG, "## open() : is ready but the post processing was not yet done.");
dispatchPostProcess(mCredentials.userId);
mIsPostProcessingDone = true;
} else {
Log.e(LOG_TAG, "## open() when ready : the post processing is already done.");
}
dispatchOnStoreReady(mCredentials.userId);
mPreloadTime = System.currentTimeMillis() - fLoadTimeT0;
}
}
});
}
};
Thread t = new Thread(r);
t.start();
}
}
}
Aggregations