mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-22 12:02:05 +01:00
Introduced unchangedEntries in Roster logic
If the connection has been reconnected, then we will receive entries that have been unchanged since the last time we received a roster result. Without this change, those entries ended up in 'toDelete' and got deleted. This change also inlines some roster methods.
This commit is contained in:
parent
9a61c75ab0
commit
f1f7713513
1 changed files with 64 additions and 72 deletions
|
@ -686,9 +686,8 @@ public class Roster {
|
|||
}
|
||||
}
|
||||
|
||||
private void addUpdateEntry(Collection<String> addedEntries,
|
||||
Collection<String> updatedEntries, RosterPacket.Item item,
|
||||
RosterEntry entry){
|
||||
private void addUpdateEntry(Collection<String> addedEntries, Collection<String> updatedEntries,
|
||||
Collection<String> unchangedEntries, RosterPacket.Item item, RosterEntry entry) {
|
||||
RosterEntry oldEntry = entries.put(item.getUser(), entry);
|
||||
if (oldEntry == null) {
|
||||
addedEntries.add(item.getUser());
|
||||
|
@ -697,6 +696,9 @@ public class Roster {
|
|||
RosterPacket.Item oldItem = RosterEntry.toRosterItem(oldEntry);
|
||||
if (!oldEntry.equalsDeep(entry) || !item.getGroupNames().equals(oldItem.getGroupNames())) {
|
||||
updatedEntries.add(item.getUser());
|
||||
} else {
|
||||
// Record the entry as unchanged, so that it doesn't end up as deleted entry
|
||||
unchangedEntries.add(item.getUser());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -950,63 +952,17 @@ public class Roster {
|
|||
|
||||
IQ result = (IQ)packet;
|
||||
if (!result.getType().equals(IQ.Type.RESULT)) {
|
||||
LOGGER.severe("Roster result IQ not of type result");
|
||||
LOGGER.severe("Roster result IQ not of type result. Packet: " + result.toXML());
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<String> addedEntries = new ArrayList<String>();
|
||||
Collection<String> updatedEntries = new ArrayList<String>();
|
||||
Collection<String> deletedEntries = new ArrayList<String>();
|
||||
Collection<String> unchangedEntries = new ArrayList<String>();
|
||||
|
||||
if (packet instanceof RosterPacket) {
|
||||
nonemptyResult((RosterPacket) packet, addedEntries, updatedEntries, deletedEntries);
|
||||
}
|
||||
else {
|
||||
emptyResult(addedEntries, updatedEntries);
|
||||
}
|
||||
|
||||
synchronized (Roster.this) {
|
||||
rosterInitialized = true;
|
||||
Roster.this.notifyAll();
|
||||
}
|
||||
// Fire event for roster listeners.
|
||||
fireRosterChangedEvent(addedEntries, updatedEntries, deletedEntries);
|
||||
}
|
||||
|
||||
private void emptyResult(Collection<String> addedEntries, Collection<String> updatedEntries) {
|
||||
for(RosterPacket.Item item : rosterStore.getEntries()){
|
||||
RosterEntry entry = new RosterEntry(item.getUser(), item.getName(),
|
||||
item.getItemType(), item.getItemStatus(), Roster.this, connection);
|
||||
addUpdateEntry(addedEntries,updatedEntries,item,entry);
|
||||
}
|
||||
}
|
||||
|
||||
private void addEntries(Collection<String> addedEntries, Collection<String> updatedEntries,
|
||||
Collection<String> deletedEntries, String version, Collection<Item> items) {
|
||||
for (RosterPacket.Item item : items) {
|
||||
RosterEntry entry = new RosterEntry(item.getUser(), item.getName(),
|
||||
item.getItemType(), item.getItemStatus(), Roster.this, connection);
|
||||
addUpdateEntry(addedEntries, updatedEntries, item, entry);
|
||||
}
|
||||
List<String> toDelete = new ArrayList<String>();
|
||||
|
||||
// Delete all entries which where not added or updated
|
||||
for (RosterEntry entry : entries.values()) {
|
||||
toDelete.add(entry.getUser());
|
||||
}
|
||||
toDelete.removeAll(addedEntries);
|
||||
toDelete.removeAll(updatedEntries);
|
||||
for (String user : toDelete) {
|
||||
deleteEntry(deletedEntries, entries.get(user));
|
||||
}
|
||||
|
||||
if (rosterStore != null) {
|
||||
rosterStore.resetEntries(items, version);
|
||||
}
|
||||
}
|
||||
|
||||
private void nonemptyResult(RosterPacket packet, Collection<String> addedEntries,
|
||||
Collection<String> updatedEntries, Collection<String> deletedEntries) {
|
||||
// Non-empty roster result. This stanza contains all the roster elements.
|
||||
RosterPacket rosterPacket = (RosterPacket) packet;
|
||||
|
||||
String version = rosterPacket.getVersion();
|
||||
|
@ -1019,10 +975,49 @@ public class Roster {
|
|||
}
|
||||
}
|
||||
|
||||
addEntries(addedEntries, updatedEntries, deletedEntries, version, validItems);
|
||||
for (RosterPacket.Item item : validItems) {
|
||||
RosterEntry entry = new RosterEntry(item.getUser(), item.getName(),
|
||||
item.getItemType(), item.getItemStatus(), Roster.this, connection);
|
||||
addUpdateEntry(addedEntries, updatedEntries, unchangedEntries, item, entry);
|
||||
}
|
||||
|
||||
// Delete all entries which where not added or updated
|
||||
Set<String> toDelete = new HashSet<String>();
|
||||
for (RosterEntry entry : entries.values()) {
|
||||
toDelete.add(entry.getUser());
|
||||
}
|
||||
toDelete.removeAll(addedEntries);
|
||||
toDelete.removeAll(updatedEntries);
|
||||
toDelete.removeAll(unchangedEntries);
|
||||
for (String user : toDelete) {
|
||||
deleteEntry(deletedEntries, entries.get(user));
|
||||
}
|
||||
|
||||
if (rosterStore != null) {
|
||||
rosterStore.resetEntries(validItems, version);
|
||||
}
|
||||
|
||||
removeEmptyGroups();
|
||||
}
|
||||
else {
|
||||
// Empty roster result as defined in RFC6121 2.6.3. An empty roster result basically
|
||||
// means that rosterver was used and the roster hasn't changed (much) since the
|
||||
// version we presented the server. So we simply load the roster from the store and
|
||||
// await possible further roster pushes.
|
||||
for (RosterPacket.Item item : rosterStore.getEntries()) {
|
||||
RosterEntry entry = new RosterEntry(item.getUser(), item.getName(),
|
||||
item.getItemType(), item.getItemStatus(), Roster.this, connection);
|
||||
addUpdateEntry(addedEntries, updatedEntries, unchangedEntries, item, entry);
|
||||
}
|
||||
}
|
||||
|
||||
rosterInitialized = true;
|
||||
synchronized (Roster.this) {
|
||||
Roster.this.notifyAll();
|
||||
}
|
||||
// Fire event for roster listeners.
|
||||
fireRosterChangedEvent(addedEntries, updatedEntries, deletedEntries);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1055,20 +1050,11 @@ public class Roster {
|
|||
Collection<String> addedEntries = new ArrayList<String>();
|
||||
Collection<String> updatedEntries = new ArrayList<String>();
|
||||
Collection<String> deletedEntries = new ArrayList<String>();
|
||||
Collection<String> unchangedEntries = new ArrayList<String>();
|
||||
|
||||
// We assured abouve that the size of items is exaclty 1, therefore we are able to
|
||||
// safely retrieve this single item here.
|
||||
Item item = items.iterator().next();
|
||||
processPushItem(addedEntries, updatedEntries, deletedEntries, version, item);
|
||||
|
||||
connection.sendPacket(IQ.createResultIQ(rosterPacket));
|
||||
|
||||
removeEmptyGroups();
|
||||
|
||||
// Fire event for roster listeners.
|
||||
fireRosterChangedEvent(addedEntries, updatedEntries, deletedEntries);
|
||||
}
|
||||
|
||||
private void processPushItem(Collection<String> addedEntries, Collection<String> updatedEntries,
|
||||
Collection<String> deletedEntries, String version, Item item) {
|
||||
RosterEntry entry = new RosterEntry(item.getUser(), item.getName(),
|
||||
item.getItemType(), item.getItemStatus(), Roster.this, connection);
|
||||
|
||||
|
@ -1079,11 +1065,17 @@ public class Roster {
|
|||
}
|
||||
}
|
||||
else if (hasValidSubscriptionType(item)) {
|
||||
addUpdateEntry(addedEntries, updatedEntries, item, entry);
|
||||
addUpdateEntry(addedEntries, updatedEntries, unchangedEntries, item, entry);
|
||||
if (rosterStore != null) {
|
||||
rosterStore.addEntry(item, version);
|
||||
}
|
||||
}
|
||||
connection.sendPacket(IQ.createResultIQ(rosterPacket));
|
||||
|
||||
removeEmptyGroups();
|
||||
|
||||
// Fire event for roster listeners.
|
||||
fireRosterChangedEvent(addedEntries, updatedEntries, deletedEntries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue