make name+namespace assignment in xmpp less error prone
This commit is contained in:
parent
07c1669813
commit
38c612d35d
|
@ -20,8 +20,9 @@ public class DiscoEntity {
|
|||
@PrimaryKey(autoGenerate = true)
|
||||
public Long id;
|
||||
|
||||
@NonNull Long accountId;
|
||||
|
||||
public byte[] capsHash;
|
||||
public byte[] caps2Hash;
|
||||
public String caps2Algorithm;
|
||||
@NonNull Long accountId;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package im.conversations.android.database.entity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
import androidx.room.PrimaryKey;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
|
||||
@Entity(
|
||||
tableName = "disco_item",
|
||||
foreignKeys = {
|
||||
@ForeignKey(
|
||||
entity = AccountEntity.class,
|
||||
parentColumns = {"id"},
|
||||
childColumns = {"accountId"},
|
||||
onDelete = ForeignKey.CASCADE),
|
||||
@ForeignKey(
|
||||
entity = DiscoEntity.class,
|
||||
parentColumns = {"id"},
|
||||
childColumns = {"discoId"},
|
||||
onDelete = ForeignKey.CASCADE)
|
||||
},
|
||||
indices = {
|
||||
@Index(
|
||||
value = {"accountId", "address"},
|
||||
unique = true),
|
||||
@Index(
|
||||
value = {"accountId", "parent"},
|
||||
unique = false)
|
||||
})
|
||||
public class DiscoItemEntity {
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
public Long id;
|
||||
|
||||
@NonNull Long accountId;
|
||||
|
||||
@NonNull Jid address;
|
||||
|
||||
@Nullable public Jid parent;
|
||||
|
||||
public Long discoId;
|
||||
}
|
|
@ -2,7 +2,8 @@ package im.conversations.android.xmpp;
|
|||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.annotation.XmlPackage;
|
||||
|
@ -12,31 +13,37 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public final class Extensions {
|
||||
|
||||
// TODO these two maps can easily be generated by an annotation processor
|
||||
private static final List<Class<? extends Extension>> ELEMENTS =
|
||||
Arrays.asList(
|
||||
im.conversations.android.xmpp.model.roster.Query.class,
|
||||
im.conversations.android.xmpp.model.roster.Item.class,
|
||||
im.conversations.android.xmpp.model.blocking.Item.class,
|
||||
im.conversations.android.xmpp.model.blocking.Block.class,
|
||||
im.conversations.android.xmpp.model.blocking.Blocklist.class,
|
||||
im.conversations.android.xmpp.model.blocking.Unblock.class);
|
||||
im.conversations.android.xmpp.model.blocking.Unblock.class,
|
||||
im.conversations.android.xmpp.model.data.Data.class,
|
||||
im.conversations.android.xmpp.model.data.Field.class,
|
||||
im.conversations.android.xmpp.model.disco.info.Feature.class,
|
||||
im.conversations.android.xmpp.model.disco.info.Identity.class,
|
||||
im.conversations.android.xmpp.model.disco.info.InfoQuery.class,
|
||||
im.conversations.android.xmpp.model.disco.items.Item.class,
|
||||
im.conversations.android.xmpp.model.disco.items.ItemsQuery.class,
|
||||
im.conversations.android.xmpp.model.roster.Query.class,
|
||||
im.conversations.android.xmpp.model.roster.Item.class);
|
||||
|
||||
private static final Map<Id, Class<? extends Extension>> EXTENSION_CLASS_MAP;
|
||||
private static final BiMap<Id, Class<? extends Extension>> EXTENSION_CLASS_MAP;
|
||||
|
||||
static {
|
||||
final var builder = new ImmutableMap.Builder<Id, Class<? extends Extension>>();
|
||||
final var builder = new ImmutableBiMap.Builder<Id, Class<? extends Extension>>();
|
||||
for (final Class<? extends Extension> clazz : ELEMENTS) {
|
||||
builder.put(id(clazz), clazz);
|
||||
builder.put(of(clazz), clazz);
|
||||
}
|
||||
EXTENSION_CLASS_MAP = builder.build();
|
||||
}
|
||||
|
||||
private static Id id(final Class<? extends Extension> clazz) {
|
||||
private static Id of(final Class<? extends Extension> clazz) {
|
||||
final XmlElement xmlElement = clazz.getAnnotation(XmlElement.class);
|
||||
final Package clazzPackage = clazz.getPackage();
|
||||
final XmlPackage xmlPackage =
|
||||
|
@ -92,6 +99,10 @@ public final class Extensions {
|
|||
return EXTENSION_CLASS_MAP.get(new Id(name, namespace));
|
||||
}
|
||||
|
||||
public static Id id(final Class<? extends Extension> clazz) {
|
||||
return EXTENSION_CLASS_MAP.inverse().get(clazz);
|
||||
}
|
||||
|
||||
private Extensions() {}
|
||||
|
||||
public static class Id {
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.google.common.collect.ImmutableClassToInstanceMap;
|
|||
import im.conversations.android.xmpp.manager.AbstractManager;
|
||||
import im.conversations.android.xmpp.manager.BlockingManager;
|
||||
import im.conversations.android.xmpp.manager.BookmarkManager;
|
||||
import im.conversations.android.xmpp.manager.DiscoManager;
|
||||
import im.conversations.android.xmpp.manager.RosterManager;
|
||||
|
||||
public final class Managers {
|
||||
|
@ -17,6 +18,7 @@ public final class Managers {
|
|||
return new ImmutableClassToInstanceMap.Builder<AbstractManager>()
|
||||
.put(BlockingManager.class, new BlockingManager(context, connection))
|
||||
.put(BookmarkManager.class, new BookmarkManager(context, connection))
|
||||
.put(DiscoManager.class, new DiscoManager(context, connection))
|
||||
.put(RosterManager.class, new RosterManager(context, connection))
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import androidx.annotation.Nullable;
|
|||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ClassToInstanceMap;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.SettableFuture;
|
||||
import eu.siacs.conversations.Config;
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.crypto.XmppDomainVerifier;
|
||||
|
@ -97,6 +99,7 @@ import java.util.List;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiFunction;
|
||||
|
@ -2235,6 +2238,24 @@ public class XmppConnection implements Runnable {
|
|||
return String.format("%s.%s", context.getString(R.string.app_name), postfixId);
|
||||
}
|
||||
|
||||
public ListenableFuture<IqPacket> sendIqPacket(final IqPacket packet) {
|
||||
final SettableFuture<IqPacket> future = SettableFuture.create();
|
||||
sendIqPacket(
|
||||
packet,
|
||||
result -> {
|
||||
final var type = result.getType();
|
||||
if (type == IqPacket.TYPE.RESULT) {
|
||||
future.set(result);
|
||||
} else if (type == IqPacket.TYPE.TIMEOUT) {
|
||||
future.setException(new TimeoutException());
|
||||
} else {
|
||||
// TODO some sort of IqErrorException
|
||||
future.setException(new IOException());
|
||||
}
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
public String sendIqPacket(final IqPacket packet, final Consumer<IqPacket> callback) {
|
||||
packet.setFrom(account.address);
|
||||
return this.sendUnmodifiedIqPacket(packet, callback, false);
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package im.conversations.android.xmpp.manager;
|
||||
|
||||
import android.content.Context;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||
import im.conversations.android.xmpp.XmppConnection;
|
||||
import im.conversations.android.xmpp.model.disco.info.InfoQuery;
|
||||
import im.conversations.android.xmpp.model.disco.items.Item;
|
||||
import im.conversations.android.xmpp.model.disco.items.ItemsQuery;
|
||||
import java.util.Collection;
|
||||
|
||||
public class DiscoManager extends AbstractManager {
|
||||
|
||||
public DiscoManager(Context context, XmppConnection connection) {
|
||||
super(context, connection);
|
||||
}
|
||||
|
||||
public ListenableFuture<InfoQuery> info(final Jid entity) {
|
||||
final var iqPacket = new IqPacket(IqPacket.TYPE.GET);
|
||||
iqPacket.setTo(entity);
|
||||
iqPacket.addChild(new InfoQuery());
|
||||
final var future = connection.sendIqPacket(iqPacket);
|
||||
return Futures.transform(
|
||||
future,
|
||||
iqResult -> {
|
||||
final var infoQuery = iqResult.getExtension(InfoQuery.class);
|
||||
if (infoQuery == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
// TODO store query
|
||||
return infoQuery;
|
||||
},
|
||||
MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
public ListenableFuture<Collection<Item>> items(final Jid entity) {
|
||||
final var iqPacket = new IqPacket(IqPacket.TYPE.GET);
|
||||
iqPacket.setTo(entity);
|
||||
iqPacket.addChild(new ItemsQuery());
|
||||
final var future = connection.sendIqPacket(iqPacket);
|
||||
return Futures.transform(
|
||||
future,
|
||||
iqResult -> {
|
||||
final var itemsQuery = iqResult.getExtension(ItemsQuery.class);
|
||||
if (itemsQuery == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
// TODO store items
|
||||
final var items = itemsQuery.getExtensions(Item.class);
|
||||
return items;
|
||||
},
|
||||
MoreExecutors.directExecutor());
|
||||
}
|
||||
}
|
|
@ -1,9 +1,15 @@
|
|||
package im.conversations.android.xmpp.model;
|
||||
|
||||
import eu.siacs.conversations.xml.Element;
|
||||
import im.conversations.android.xmpp.Extensions;
|
||||
|
||||
public class Extension extends Element {
|
||||
public Extension(String name, String xmlns) {
|
||||
super(name, xmlns);
|
||||
|
||||
private Extension(final Extensions.Id id) {
|
||||
super(id.name, id.namespace);
|
||||
}
|
||||
|
||||
public Extension(final Class<? extends Extension> clazz) {
|
||||
this(Extensions.id(clazz));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package im.conversations.android.xmpp.model.blocking;
|
||||
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
|
@ -8,6 +7,6 @@ import im.conversations.android.xmpp.model.Extension;
|
|||
public class Block extends Extension {
|
||||
|
||||
public Block() {
|
||||
super("block", Namespace.BLOCKING);
|
||||
super(Block.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
package im.conversations.android.xmpp.model.blocking;
|
||||
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement
|
||||
public class Blocklist extends Extension {
|
||||
public Blocklist() {
|
||||
super("blocklist", Namespace.BLOCKING);
|
||||
super(Blocklist.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package im.conversations.android.xmpp.model.blocking;
|
||||
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
@ -9,7 +8,7 @@ import im.conversations.android.xmpp.model.Extension;
|
|||
public class Item extends Extension {
|
||||
|
||||
public Item() {
|
||||
super("item", Namespace.BLOCKING);
|
||||
super(Item.class);
|
||||
}
|
||||
|
||||
public Jid getJid() {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package im.conversations.android.xmpp.model.blocking;
|
||||
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
|
@ -8,6 +7,6 @@ import im.conversations.android.xmpp.model.Extension;
|
|||
public class Unblock extends Extension {
|
||||
|
||||
public Unblock() {
|
||||
super("unblock", Namespace.BLOCKING);
|
||||
super(Unblock.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
@XmlPackage(namespace = Namespace.BLOCKING)
|
||||
package im.conversations.android.xmpp.model.blocking;
|
||||
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import im.conversations.android.annotation.XmlPackage;
|
|
@ -0,0 +1,11 @@
|
|||
package im.conversations.android.xmpp.model.data;
|
||||
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement(name = "x")
|
||||
public class Data extends Extension {
|
||||
public Data() {
|
||||
super(Data.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package im.conversations.android.xmpp.model.data;
|
||||
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement
|
||||
public class Field extends Extension {
|
||||
public Field() {
|
||||
super(Field.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
@XmlPackage(namespace = Namespace.DATA)
|
||||
package im.conversations.android.xmpp.model.data;
|
||||
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import im.conversations.android.annotation.XmlPackage;
|
|
@ -0,0 +1,11 @@
|
|||
package im.conversations.android.xmpp.model.disco.info;
|
||||
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement
|
||||
public class Feature extends Extension {
|
||||
public Feature() {
|
||||
super(Feature.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package im.conversations.android.xmpp.model.disco.info;
|
||||
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement
|
||||
public class Identity extends Extension {
|
||||
public Identity() {
|
||||
super(Identity.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package im.conversations.android.xmpp.model.disco.info;
|
||||
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement(name = "query")
|
||||
public class InfoQuery extends Extension {
|
||||
|
||||
public InfoQuery() {
|
||||
super(InfoQuery.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
@XmlPackage(namespace = Namespace.DISCO_INFO)
|
||||
package im.conversations.android.xmpp.model.disco.info;
|
||||
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import im.conversations.android.annotation.XmlPackage;
|
|
@ -0,0 +1,20 @@
|
|||
package im.conversations.android.xmpp.model.disco.items;
|
||||
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement
|
||||
public class Item extends Extension {
|
||||
public Item() {
|
||||
super(Item.class);
|
||||
}
|
||||
|
||||
public Jid getJid() {
|
||||
return getAttributeAsJid("jid");
|
||||
}
|
||||
|
||||
public String getNode() {
|
||||
return this.getAttribute("node");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package im.conversations.android.xmpp.model.disco.items;
|
||||
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
||||
@XmlElement(name = "query")
|
||||
public class ItemsQuery extends Extension {
|
||||
public ItemsQuery() {
|
||||
super(ItemsQuery.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
@XmlPackage(namespace = Namespace.DISCO_ITEMS)
|
||||
package im.conversations.android.xmpp.model.disco.items;
|
||||
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import im.conversations.android.annotation.XmlPackage;
|
|
@ -1,6 +1,5 @@
|
|||
package im.conversations.android.xmpp.model.roster;
|
||||
|
||||
import eu.siacs.conversations.xml.Namespace;
|
||||
import eu.siacs.conversations.xmpp.Jid;
|
||||
import im.conversations.android.annotation.XmlElement;
|
||||
import im.conversations.android.xmpp.model.Extension;
|
||||
|
@ -15,7 +14,7 @@ public class Item extends Extension {
|
|||
Arrays.asList(Subscription.NONE, Subscription.TO, Subscription.FROM, Subscription.BOTH);
|
||||
|
||||
public Item() {
|
||||
super("item", Namespace.ROSTER);
|
||||
super(Item.class);
|
||||
}
|
||||
|
||||
public Jid getJid() {
|
||||
|
|
|
@ -8,7 +8,7 @@ import im.conversations.android.xmpp.model.Extension;
|
|||
public class Query extends Extension {
|
||||
|
||||
public Query() {
|
||||
super("query", Namespace.ROSTER);
|
||||
super(Query.class);
|
||||
}
|
||||
|
||||
public void setVersion(final String rosterVersion) {
|
||||
|
|
Loading…
Reference in a new issue