From 6f1e4c43d7cb5765bf38982cb0327ab660ce3aeb Mon Sep 17 00:00:00 2001
From: Benoit Lavenier <benoit.lavenier@e-is.pro>
Date: Fri, 10 Jan 2020 13:53:18 +0100
Subject: [PATCH] [enh] Allow to get /wot/pending and /wot/requirements

---
 .../model/bma/WotPendingMembership.java       |  58 +++++++++
 .../model/bma/WotPendingMemberships.java      |  38 ++++++
 .../client/model/bma/WotRequirements.java     | 122 ++++++++++++++++++
 .../model/bma/WotRequirementsResponse.java    |  36 ++++++
 .../bma/BlockchainRemoteServiceImpl.java      |   1 +
 .../client/service/bma/WotRemoteService.java  |   8 +-
 .../service/bma/WotRemoteServiceImpl.java     |  38 +++++-
 .../service/bma/WotRemoteServiceTest.java     |  34 ++++-
 8 files changed, 321 insertions(+), 14 deletions(-)
 create mode 100644 duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotPendingMembership.java
 create mode 100644 duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotPendingMemberships.java
 create mode 100644 duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotRequirements.java
 create mode 100644 duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotRequirementsResponse.java

diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotPendingMembership.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotPendingMembership.java
new file mode 100644
index 00000000..74555d1f
--- /dev/null
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotPendingMembership.java
@@ -0,0 +1,58 @@
+package org.duniter.core.client.model.bma;
+
+import java.io.Serializable;
+
+public class WotPendingMembership implements Serializable {
+		private static final long serialVersionUID = 1L;
+
+		private String pubkey;
+		private String uid;
+		private String version;
+		private String currency;
+		private String membership;
+		private long blockNumber;
+		private String blockHash;
+
+		public String getPubkey() {
+			return pubkey;
+		}
+		public void setPubkey(String pubkey) {
+			this.pubkey = pubkey;
+		}
+		public String getUid() {
+			return uid;
+		}
+		public void setUid(String uid) {
+			this.uid = uid;
+		}
+		public String getVersion() {
+			return version;
+		}
+		public void setVersion(String version) {
+			this.version = version;
+		}
+		public String getCurrency() {
+			return currency;
+		}
+		public void setCurrency(String currency) {
+			this.currency = currency;
+		}
+		public String getMembership() {
+			return membership;
+		}
+		public void setMembership(String membership) {
+			this.membership = membership;
+		}
+		public long getBlockNumber() {
+			return blockNumber;
+		}
+		public void setBlockNumber(long blockNumber) {
+			this.blockNumber = blockNumber;
+		}
+		public String getBlockHash() {
+			return blockHash;
+		}
+		public void setBlockHash(String blockHash) {
+			this.blockHash = blockHash;
+		}
+	}
\ No newline at end of file
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotPendingMemberships.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotPendingMemberships.java
new file mode 100644
index 00000000..8d7e5e8e
--- /dev/null
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotPendingMemberships.java
@@ -0,0 +1,38 @@
+package org.duniter.core.client.model.bma;
+
+/*
+ * #%L
+ * UCoin Java :: Core Client API
+ * %%
+ * Copyright (C) 2014 - 2016 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import org.duniter.core.client.model.BasicIdentity;
+
+import java.io.Serializable;
+
+public class WotPendingMemberships extends BasicIdentity {
+	private static final long serialVersionUID = -5631089862725952431L;
+
+	private WotPendingMembership[] memberships;
+
+	public WotPendingMembership[] getMemberships() {
+		return memberships;
+	}
+
+}
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotRequirements.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotRequirements.java
new file mode 100644
index 00000000..b050da1d
--- /dev/null
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotRequirements.java
@@ -0,0 +1,122 @@
+package org.duniter.core.client.model.bma;
+
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonSetter;
+
+import java.io.Serializable;
+
+public class WotRequirements implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	private String pubkey;
+	private String uid;
+	private String sig;
+	private Meta meta;
+	private String revocation_sig;
+	private Boolean revoked;
+	private Long revoked_on;
+	private Boolean expired;
+	private Boolean outdistanced;
+	private Boolean isSentry;
+	private Boolean wasMember;
+
+	public String getPubkey() {
+		return pubkey;
+	}
+
+	public void setPubkey(String pubkey) {
+		this.pubkey = pubkey;
+	}
+
+	public String getUid() {
+		return uid;
+	}
+
+	public void setUid(String uid) {
+		this.uid = uid;
+	}
+
+	public String getSig() {
+		return sig;
+	}
+
+	public void setSig(String sig) {
+		this.sig = sig;
+	}
+
+	public Meta getMeta() {
+		return meta;
+	}
+
+	public void setMeta(Meta meta) {
+		this.meta = meta;
+	}
+
+	public String getRevocation_sig() {
+		return revocation_sig;
+	}
+
+	public void setRevocation_sig(String revocation_sig) {
+		this.revocation_sig = revocation_sig;
+	}
+
+	public Boolean getRevoked() {
+		return revoked;
+	}
+
+	public void setRevoked(Boolean revoked) {
+		this.revoked = revoked;
+	}
+
+	public Long getRevoked_on() {
+		return revoked_on;
+	}
+
+	public void setRevoked_on(Long revoked_on) {
+		this.revoked_on = revoked_on;
+	}
+
+	public Boolean getExpired() {
+		return expired;
+	}
+
+	public void setExpired(Boolean expired) {
+		this.expired = expired;
+	}
+
+	public Boolean getOutdistanced() {
+		return outdistanced;
+	}
+
+	public void setOutdistanced(Boolean outdistanced) {
+		this.outdistanced = outdistanced;
+	}
+
+	public Boolean getSentry() {
+		return isSentry;
+	}
+
+	public void setSentry(Boolean sentry) {
+		isSentry = sentry;
+	}
+
+	public Boolean getWasMember() {
+		return wasMember;
+	}
+
+	public void setWasMember(Boolean wasMember) {
+		this.wasMember = wasMember;
+	}
+
+	public static class Meta implements Serializable {
+		private String timestamp;
+
+		public String getTimestamp() {
+			return timestamp;
+		}
+
+		public void setTimestamp(String timestamp) {
+			this.timestamp = timestamp;
+		}
+	}
+}
\ No newline at end of file
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotRequirementsResponse.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotRequirementsResponse.java
new file mode 100644
index 00000000..e6972804
--- /dev/null
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/model/bma/WotRequirementsResponse.java
@@ -0,0 +1,36 @@
+package org.duniter.core.client.model.bma;
+
+/*
+ * #%L
+ * UCoin Java :: Core Client API
+ * %%
+ * Copyright (C) 2014 - 2016 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import org.duniter.core.client.model.BasicIdentity;
+
+public class WotRequirementsResponse extends BasicIdentity {
+	private static final long serialVersionUID = -5631089862725952141L;
+
+	private WotRequirements[] identities;
+
+	public WotRequirements[] getIdentities() {
+		return identities;
+	}
+
+}
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/BlockchainRemoteServiceImpl.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/BlockchainRemoteServiceImpl.java
index 017650c1..97bc1d8a 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/BlockchainRemoteServiceImpl.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/BlockchainRemoteServiceImpl.java
@@ -482,6 +482,7 @@ public class BlockchainRemoteServiceImpl extends BaseRemoteServiceImpl implement
                 .append('\n').toString();
     }
 
+
     /**
      * Get UD, by block number
      *
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/WotRemoteService.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/WotRemoteService.java
index 4cc37b8c..4f26739c 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/WotRemoteService.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/WotRemoteService.java
@@ -23,8 +23,7 @@ package org.duniter.core.client.service.bma;
  */
 
 import org.duniter.core.beans.Service;
-import org.duniter.core.client.model.bma.WotCertification;
-import org.duniter.core.client.model.bma.WotLookup;
+import org.duniter.core.client.model.bma.*;
 import org.duniter.core.client.model.local.*;
 
 import java.util.Collection;
@@ -39,7 +38,8 @@ public interface WotRemoteService extends Service {
     WotLookup.Uid find(Peer peer, String uidOrPubKey);
     WotLookup.Uid find(String currencyId, String uidOrPubKey);
 
-    void getRequirements(String currencyId, String pubKey);
+    List<WotRequirements> getRequirements(Peer peer, String pubKey);
+    List<WotRequirements> getRequirements(String currencyId, String pubKey);
 
     WotLookup.Uid findByUid(Peer peer, String uid);
     WotLookup.Uid findByUid(String currencyId, String uid);
@@ -70,6 +70,8 @@ public interface WotRemoteService extends Service {
     Map<String, String> getMembersUids(Peer peer);
     List<Member> getMembers(Peer peer);
     List<Member> getMembers(String currencyId);
+    List<WotPendingMembership> getPendingMemberships(Peer peer);
+    List<WotPendingMembership> getPendingMemberships(String currencyId);
 
     void sendIdentity(Peer peer, String currency, byte[] pubKey, byte[] secKey, String uid, String blockUid);
     void sendIdentity(String currencyId, byte[] pubKey, byte[] secKey, String uid, String blockUid);
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/WotRemoteServiceImpl.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/WotRemoteServiceImpl.java
index a230da41..9fc355c4 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/WotRemoteServiceImpl.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/bma/WotRemoteServiceImpl.java
@@ -23,6 +23,7 @@ package org.duniter.core.client.service.bma;
  */
 
 import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import org.apache.commons.collections4.MapUtils;
@@ -31,6 +32,7 @@ import org.duniter.core.client.model.ModelUtils;
 import org.duniter.core.client.model.bma.*;
 import org.duniter.core.client.model.local.*;
 import org.duniter.core.client.service.ServiceLocator;
+import org.duniter.core.client.service.exception.HttpBadRequestException;
 import org.duniter.core.client.service.local.CurrencyService;
 import org.duniter.core.exception.TechnicalException;
 import org.duniter.core.service.CryptoService;
@@ -60,6 +62,8 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
 
     public static final String URL_MEMBERS = URL_BASE + "/members";
 
+    public static final String URL_PENDING = URL_BASE + "/pending";
+
     public static final String URL_LOOKUP = URL_BASE + "/lookup/%s";
 
     public static final String URL_REQUIREMENT = URL_BASE+"/requirements/%s";
@@ -169,15 +173,35 @@ public class WotRemoteServiceImpl extends BaseRemoteServiceImpl implements WotRe
         return result;
     }
 
-    public void getRequirements(String currencyId, String pubKey) {
-        if (log.isDebugEnabled()) {
-            log.debug(String.format("TODO: implement /wot/requirements on [%s]", pubKey));
+    public List<WotPendingMembership> getPendingMemberships(Peer peer) {
+        try {
+            WotPendingMemberships lists = httpService.executeRequest(peer, URL_PENDING, WotPendingMemberships.class);
+            return ImmutableList.copyOf(lists.getMemberships());
+        } catch (HttpBadRequestException e) {
+            log.debug("Unable to get pending memberships");
+            return null;
         }
-        // get parameter
-        String path = String.format(URL_REQUIREMENT, pubKey);
-        // TODO : managed requirements
-        //WotLookup lookupResults = executeRequest(currencyId, path, WotLookup.class);
+    }
+
+    @Override
+    public List<WotPendingMembership> getPendingMemberships(String currencyId) {
+        return getPendingMemberships(peerService.getActivePeerByCurrencyId(currencyId));
+    }
+
+    @Override
+    public List<WotRequirements> getRequirements(Peer peer, String pubKey) {
+        try {
+            WotRequirementsResponse response = httpService.executeRequest(peer, String.format(URL_REQUIREMENT, pubKey), WotRequirementsResponse.class);
+            return ImmutableList.copyOf(response.getIdentities());
+        } catch (HttpBadRequestException e) {
+            log.debug(String.format("Unable to get memberships for {%.8s}", pubKey));
+            return null;
+        }
+    }
 
+    @Override
+    public List<WotRequirements> getRequirements(String currencyId, String pubKey) {
+        return getRequirements(peerService.getActivePeerByCurrencyId(currencyId), pubKey);
     }
 
     public WotLookup.Uid findByUid(Peer peer, String uid) {
diff --git a/duniter4j-core-client/src/test/java/org/duniter/core/client/service/bma/WotRemoteServiceTest.java b/duniter4j-core-client/src/test/java/org/duniter/core/client/service/bma/WotRemoteServiceTest.java
index a58bb52f..54d37f7c 100644
--- a/duniter4j-core-client/src/test/java/org/duniter/core/client/service/bma/WotRemoteServiceTest.java
+++ b/duniter4j-core-client/src/test/java/org/duniter/core/client/service/bma/WotRemoteServiceTest.java
@@ -23,9 +23,10 @@ package org.duniter.core.client.service.bma;
  */
 
 
+import org.apache.commons.lang3.mutable.MutableInt;
 import org.duniter.core.client.TestResource;
 import org.duniter.core.client.config.Configuration;
-import org.duniter.core.client.model.bma.ErrorCode;
+import org.duniter.core.client.model.bma.*;
 import org.duniter.core.client.model.local.Identity;
 import org.duniter.core.client.model.local.Member;
 import org.duniter.core.client.model.local.Peer;
@@ -34,9 +35,6 @@ import org.duniter.core.client.service.ServiceLocator;
 import org.duniter.core.client.service.exception.HttpBadRequestException;
 import org.duniter.core.util.CollectionUtils;
 import org.duniter.core.util.crypto.CryptoUtils;
-import org.duniter.core.client.model.bma.BlockchainBlock;
-import org.duniter.core.client.model.bma.WotCertification;
-import org.duniter.core.client.model.bma.WotLookup;
 import org.junit.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -184,6 +182,34 @@ public class WotRemoteServiceTest {
 		Assert.assertTrue(result.size() > 0);
 	}
 
+	@Test
+	public void getPendingMemberships() {
+		Peer peer = createTestPeer();
+		List<WotPendingMembership> result = service.getPendingMemberships(peer);
+		Assert.assertNotNull(result);
+		Assert.assertTrue(result.size() > 0);
+	}
+
+	@Test
+	public void getRequirements() {
+		Peer peer = createTestPeer();
+		List<WotPendingMembership> pendingMemberships = service.getPendingMemberships(peer);
+		Assume.assumeTrue(CollectionUtils.isNotEmpty(pendingMemberships));
+
+		MutableInt counter = new MutableInt(0);
+		pendingMemberships.stream()
+				// Get first 10
+			.filter(ms -> {
+				counter.increment();
+				return counter.getValue() < 10;
+			})
+			.forEach(ms -> {
+				List<WotRequirements> result = service.getRequirements(peer, ms.getPubkey());
+				Assert.assertNotNull(result);
+				Assert.assertNotNull(result.size() > 0);
+			});
+	}
+
 	/* -- internal methods */
 
 	protected Wallet createTestWallet() {
-- 
GitLab