Browse Source

Reworked the client/spec/config/builder on how features are implemented and called.

rewrite-connect
Eric Kok 8 years ago
parent
commit
bd73271753
  1. 60
      connect/src/main/java/org/transdroid/connect/Configuration.java
  2. 38
      connect/src/main/java/org/transdroid/connect/clients/Client.java
  3. 42
      connect/src/main/java/org/transdroid/connect/clients/ClientDelegate.java
  4. 15
      connect/src/main/java/org/transdroid/connect/clients/ClientSpec.java
  5. 54
      connect/src/main/java/org/transdroid/connect/clients/Feature.java
  6. 22
      connect/src/main/java/org/transdroid/connect/clients/UnsupportedFeatureException.java
  7. 19
      connect/src/main/java/org/transdroid/connect/clients/rtorrent/Rtorrent.java
  8. 5
      connect/src/main/java/org/transdroid/connect/clients/transmission/Transmission.java
  9. 21
      connect/src/test/java/org/transdroid/connect/clients/rtorrent/RtorrentTest.java

60
connect/src/main/java/org/transdroid/connect/Configuration.java

@ -4,22 +4,66 @@ import com.burgstaller.okhttp.digest.Credentials;
import org.transdroid.connect.clients.Client; import org.transdroid.connect.clients.Client;
import org.transdroid.connect.clients.ClientSpec; import org.transdroid.connect.clients.ClientSpec;
import org.transdroid.connect.util.StringUtil;
/**
* Configuration settings to connect to a torrent client.
*/
public final class Configuration { public final class Configuration {
private final Client client; private final Client client;
private final String baseUrl; private final String baseUrl;
private final String endpoint; private String endpoint;
private final Credentials credentials; private Credentials credentials;
private final boolean loggingEnabled; private boolean loggingEnabled;
public Configuration(Client client, String baseUrl, String endpoint, String user, String password, boolean loggingEnabled) { public static class Builder {
private final Client client;
private String baseUrl;
private String endpoint;
private Credentials credentials;
private boolean loggingEnabled;
public Builder(Client client) {
this.client = client; this.client = client;
}
public Builder baseUrl(String baseUrl) {
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
return this;
}
public Builder endpoint(String endpoint) {
this.endpoint = endpoint; this.endpoint = endpoint;
this.credentials = (!StringUtil.isEmpty(user) && password != null) ? new Credentials(user, password) : null; return this;
}
public Builder credentials(String user, String password) {
this.credentials = new Credentials(user, password);
return this;
}
public Builder loggingEnabled(boolean loggingEnabled) {
this.loggingEnabled = loggingEnabled; this.loggingEnabled = loggingEnabled;
return this;
}
public Configuration build() {
Configuration configuration = new Configuration(client, baseUrl);
configuration.endpoint = this.endpoint;
configuration.credentials = this.credentials;
return configuration;
}
}
private Configuration(Client client, String baseUrl) {
this.client = client;
this.baseUrl = baseUrl;
}
public Client client() {
return client;
} }
public String baseUrl() { public String baseUrl() {
@ -38,8 +82,8 @@ public final class Configuration {
return credentials; return credentials;
} }
public ClientSpec create() { public ClientSpec createClient() {
return client.create(this); return client.createClient(this);
} }
} }

38
connect/src/main/java/org/transdroid/connect/clients/Client.java

@ -2,29 +2,45 @@ package org.transdroid.connect.clients;
import org.transdroid.connect.Configuration; import org.transdroid.connect.Configuration;
import org.transdroid.connect.clients.rtorrent.Rtorrent; import org.transdroid.connect.clients.rtorrent.Rtorrent;
import org.transdroid.connect.clients.transmission.Transmission;
import java.util.Set; /**
* Support clients enum, allowing you to create instances (given a configuration) and query for feature support.
*/
@SuppressWarnings("unchecked")
public enum Client { public enum Client {
RTORRENT { RTORRENT(Rtorrent.class) {
@Override @Override
public ClientSpec create(Configuration configuration) { public Rtorrent create(Configuration configuration) {
return new Rtorrent(configuration); return new Rtorrent(configuration);
} }
},
TRANSMISSION(Transmission.class) {
@Override @Override
Set<Feature> features() { public Transmission create(Configuration configuration) {
return Rtorrent.FEATURES; return new Transmission();
} }
}; };
public abstract ClientSpec create(Configuration configuration); final Class<?> type;
Client(Class<?> type) {
this.type = type;
}
public final Class<?> type() {
return type;
}
abstract Object create(Configuration configuration);
abstract Set<Feature> features(); public final ClientSpec createClient(Configuration configuration) {
return new ClientDelegate(configuration.client(), create(configuration));
}
public boolean supports(Feature feature) { public final boolean supports(Feature feature) {
return features().contains(feature); return feature.type().isAssignableFrom(type);
} }
} }

42
connect/src/main/java/org/transdroid/connect/clients/ClientDelegate.java

@ -0,0 +1,42 @@
package org.transdroid.connect.clients;
import org.transdroid.connect.model.Torrent;
import io.reactivex.Flowable;
/**
* Wraps an actual client implementation by calling through the appropriate method only if it is supported. This allows the final
* {@link ClientSpec} API to expose all methods without forcing the individual implementations to implement unsupported featured with a no-op.
*/
final class ClientDelegate implements ClientSpec {
private final Client client;
private final Object actual;
ClientDelegate(Client client, Object actual) {
this.client = client;
this.actual = actual;
}
@Override
public Flowable<Torrent> torrents() {
if (client.supports(Feature.LISTING))
return ((Feature.Listing) actual).torrents();
throw new UnsupportedFeatureException(client, Feature.LISTING);
}
@Override
public Flowable<String> clientVersion() {
if (client.supports(Feature.VERSION))
return ((Feature.Version) actual).clientVersion();
throw new UnsupportedFeatureException(client, Feature.VERSION);
}
@Override
public Flowable<Torrent> forceStartTorrent() {
if (client.supports(Feature.FORCE_STARTING))
return ((Feature.ForceStarting) actual).forceStartTorrent();
throw new UnsupportedFeatureException(client, Feature.FORCE_STARTING);
}
}

15
connect/src/main/java/org/transdroid/connect/clients/ClientSpec.java

@ -1,13 +1,10 @@
package org.transdroid.connect.clients; package org.transdroid.connect.clients;
import org.transdroid.connect.model.Torrent; public interface ClientSpec extends
Feature.Version,
import io.reactivex.Flowable; Feature.Listing,
Feature.StartingStopping,
public interface ClientSpec { Feature.ResumingPausing,
Feature.ForceStarting {
Flowable<String> clientVersion();
Flowable<Torrent> torrents();
} }

54
connect/src/main/java/org/transdroid/connect/clients/Feature.java

@ -1,11 +1,55 @@
package org.transdroid.connect.clients; package org.transdroid.connect.clients;
import org.transdroid.connect.model.Torrent;
import io.reactivex.Flowable;
/**
* Available feature enum which can be implemented by clients. Use {@link Client#supports(Feature)} to see if a certain {@link Client} support a
* {@link Feature}.
*/
public enum Feature { public enum Feature {
VERSION, VERSION(Version.class),
STARTING, LISTING(Listing.class),
STOPPING, STARTING_STOPPING(StartingStopping.class),
RESUMING, RESUMING_PAUSING(ResumingPausing.class),
PAUSING FORCE_STARTING(ForceStarting.class);
private final Class<?> type;
Feature(Class<?> type) {
this.type = type;
}
public Class<?> type() {
return type;
}
public interface Version {
Flowable<String> clientVersion();
}
public interface Listing {
Flowable<Torrent> torrents();
}
public interface StartingStopping {
}
public interface ResumingPausing {
}
public interface ForceStarting {
Flowable<Torrent> forceStartTorrent();
}
} }

22
connect/src/main/java/org/transdroid/connect/clients/UnsupportedFeatureException.java

@ -0,0 +1,22 @@
package org.transdroid.connect.clients;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
/**
* Thrown when trying to call into a client method for a feature which the client does not support.
*/
public class UnsupportedFeatureException extends NotImplementedException {
private final Client client;
private final Feature feature;
UnsupportedFeatureException(Client client, Feature feature) {
this.client = client;
this.feature = feature;
}
public String getMessage() {
return client.name() + " does not support " + feature.name();
}
}

19
connect/src/main/java/org/transdroid/connect/clients/rtorrent/Rtorrent.java

@ -3,7 +3,6 @@ package org.transdroid.connect.clients.rtorrent;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import org.transdroid.connect.Configuration; import org.transdroid.connect.Configuration;
import org.transdroid.connect.clients.ClientSpec;
import org.transdroid.connect.clients.Feature; import org.transdroid.connect.clients.Feature;
import org.transdroid.connect.model.Torrent; import org.transdroid.connect.model.Torrent;
import org.transdroid.connect.model.TorrentStatus; import org.transdroid.connect.model.TorrentStatus;
@ -11,8 +10,6 @@ import org.transdroid.connect.util.OkHttpBuilder;
import org.transdroid.connect.util.RxUtil; import org.transdroid.connect.util.RxUtil;
import java.util.Date; import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import io.reactivex.Flowable; import io.reactivex.Flowable;
import io.reactivex.functions.Function; import io.reactivex.functions.Function;
@ -20,17 +17,11 @@ import nl.nl2312.xmlrpc.Nothing;
import nl.nl2312.xmlrpc.XmlRpcConverterFactory; import nl.nl2312.xmlrpc.XmlRpcConverterFactory;
import retrofit2.Retrofit; import retrofit2.Retrofit;
public final class Rtorrent implements ClientSpec { public final class Rtorrent implements
Feature.Version,
public static final Set<Feature> FEATURES = new HashSet<>(); Feature.Listing,
Feature.StartingStopping,
{ Feature.ResumingPausing {
FEATURES.add(Feature.VERSION);
FEATURES.add(Feature.STARTING);
FEATURES.add(Feature.STOPPING);
FEATURES.add(Feature.RESUMING);
FEATURES.add(Feature.PAUSING);
}
private final Configuration configuration; private final Configuration configuration;
private final Service service; private final Service service;

5
connect/src/main/java/org/transdroid/connect/clients/transmission/Transmission.java

@ -0,0 +1,5 @@
package org.transdroid.connect.clients.transmission;
public final class Transmission {
}

21
connect/src/test/java/org/transdroid/connect/clients/rtorrent/RtorrentTest.java

@ -6,6 +6,7 @@ import org.transdroid.connect.Configuration;
import org.transdroid.connect.clients.Client; import org.transdroid.connect.clients.Client;
import org.transdroid.connect.clients.ClientSpec; import org.transdroid.connect.clients.ClientSpec;
import org.transdroid.connect.clients.Feature; import org.transdroid.connect.clients.Feature;
import org.transdroid.connect.clients.UnsupportedFeatureException;
import org.transdroid.connect.model.Torrent; import org.transdroid.connect.model.Torrent;
import java.io.IOException; import java.io.IOException;
@ -21,17 +22,19 @@ public final class RtorrentTest {
@Before @Before
public void setUp() { public void setUp() {
Configuration configuration = new Configuration(Client.RTORRENT, "http://localhost:8008/", "RPC2", null, null, true); rtorrent = new Configuration.Builder(Client.RTORRENT)
rtorrent = configuration.create(); .baseUrl("http://localhost:8008/")
.endpoint("/RPC2")
.build()
.createClient();
} }
@Test @Test
public void features() { public void features() {
assertThat(Client.RTORRENT.supports(Feature.VERSION)).isTrue(); assertThat(Client.RTORRENT.supports(Feature.VERSION)).isTrue();
assertThat(Client.RTORRENT.supports(Feature.STARTING)).isTrue(); assertThat(Client.RTORRENT.supports(Feature.STARTING_STOPPING)).isTrue();
assertThat(Client.RTORRENT.supports(Feature.STOPPING)).isTrue(); assertThat(Client.RTORRENT.supports(Feature.RESUMING_PAUSING)).isTrue();
assertThat(Client.RTORRENT.supports(Feature.RESUMING)).isTrue(); assertThat(Client.RTORRENT.supports(Feature.FORCE_STARTING)).isFalse();
assertThat(Client.RTORRENT.supports(Feature.PAUSING)).isTrue();
} }
@Test @Test
@ -54,4 +57,10 @@ public final class RtorrentTest {
}); });
} }
@Test(expected = UnsupportedFeatureException.class)
public void forceStart() throws IOException {
rtorrent.forceStartTorrent()
.test();
}
} }

Loading…
Cancel
Save