Skip to content

Commit b33bcfc

Browse files
committed
Several Bugfixes
1 parent d25253b commit b33bcfc

File tree

6 files changed

+105
-38
lines changed

6 files changed

+105
-38
lines changed

src/main/java/io/codebottle/api/CodeBottle.java

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.codebottle.api;
22

33
import java.util.Collection;
4+
import java.util.Collections;
45
import java.util.List;
56
import java.util.Map;
67
import java.util.Optional;
@@ -20,9 +21,9 @@
2021
public final class CodeBottle {
2122
public final CompletionStage<Void> lazyLoading;
2223

23-
private final Map<Integer, Language> languageCache = new ConcurrentHashMap<>();
24-
private final Map<Integer, Category> categoryCache = new ConcurrentHashMap<>();
25-
private final Map<Integer, Snippet> snippetCache = new ConcurrentHashMap<>();
24+
private final Map<String, Language> languageCache = new ConcurrentHashMap<>();
25+
private final Map<String, Category> categoryCache = new ConcurrentHashMap<>();
26+
private final Map<String, Snippet> snippetCache = new ConcurrentHashMap<>();
2627
private final String token;
2728

2829
public CodeBottle() {
@@ -38,16 +39,20 @@ public CodeBottle(@Nullable String token) {
3839
public Optional<String> getToken() {
3940
return Optional.ofNullable(token);
4041
}
41-
42-
public Optional<Language> getLanguageByID(int id) {
43-
if (id == -1) return Optional.empty();
44-
42+
43+
public Optional<Language> getLanguageByID(String id) {
4544
synchronized (languageCache) {
4645
return Optional.ofNullable(languageCache.get(id));
4746
}
4847
}
4948

50-
public CompletableFuture<Language> requestLanguageByID(int id) {
49+
public Collection<Language> getLanguages() {
50+
synchronized (languageCache) {
51+
return languageCache.values();
52+
}
53+
}
54+
55+
public CompletableFuture<Language> requestLanguageByID(String id) {
5156
return new CodeBottleRequest<Language>(this)
5257
.to(Endpoint.LANGUAGE_SPECIFIC, id)
5358
.makeGET()
@@ -69,7 +74,7 @@ public CompletableFuture<Collection<Language>> requestLanguages() {
6974
.then(data -> {
7075
synchronized (languageCache) {
7176
return StreamSupport.stream(data.spliterator(), false)
72-
.map(node -> getLanguageByID(node.path("id").asInt())
77+
.map(node -> getLanguageByID(node.path("id").asText())
7378
.map(entity -> entity.update(node))
7479
.orElseGet(() -> {
7580
final Language language = new Language(this, node);
@@ -83,15 +88,19 @@ public CompletableFuture<Collection<Language>> requestLanguages() {
8388
});
8489
}
8590

86-
public Optional<Category> getCategoryByID(int id) {
87-
if (id == -1) return Optional.empty();
88-
91+
public Optional<Category> getCategoryByID(String id) {
8992
synchronized (categoryCache) {
9093
return Optional.ofNullable(categoryCache.get(id));
9194
}
9295
}
9396

94-
public CompletableFuture<Category> requestCategoryByID(int id) {
97+
public Collection<Category> getCategories() {
98+
synchronized (categoryCache) {
99+
return categoryCache.values();
100+
}
101+
}
102+
103+
public CompletableFuture<Category> requestCategoryByID(String id) {
95104
return new CodeBottleRequest<Category>(this)
96105
.to(Endpoint.CATEGORY_SPECIFIC, id)
97106
.makeGET()
@@ -113,7 +122,7 @@ public CompletableFuture<Collection<Category>> requestCategories() {
113122
.then(data -> {
114123
synchronized (categoryCache) {
115124
return StreamSupport.stream(data.spliterator(), false)
116-
.map(node -> getCategoryByID(node.path("id").asInt())
125+
.map(node -> getCategoryByID(node.path("id").asText())
117126
.map(entity -> entity.update(node))
118127
.orElseGet(() -> {
119128
final Category category = new Category(this, node);
@@ -127,15 +136,19 @@ public CompletableFuture<Collection<Category>> requestCategories() {
127136
});
128137
}
129138

130-
public Optional<Snippet> getSnippetByID(int id) {
131-
if (id == -1) return Optional.empty();
132-
139+
public Optional<Snippet> getSnippetByID(String id) {
133140
synchronized (snippetCache) {
134141
return Optional.ofNullable(snippetCache.get(id));
135142
}
136143
}
137144

138-
public CompletableFuture<Snippet> requestSnippetByID(int id) {
145+
public Collection<Snippet> getSnippets() {
146+
synchronized (snippetCache) {
147+
return snippetCache.values();
148+
}
149+
}
150+
151+
public CompletableFuture<Snippet> requestSnippetByID(String id) {
139152
return new CodeBottleRequest<Snippet>(this)
140153
.to(Endpoint.SNIPPET_SPECIFIC, id)
141154
.makeGET()
@@ -157,7 +170,7 @@ public CompletableFuture<Collection<Snippet>> requestSnippets() {
157170
.then(data -> {
158171
synchronized (snippetCache) {
159172
return StreamSupport.stream(data.spliterator(), false)
160-
.map(node -> getSnippetByID(node.path("id").asInt())
173+
.map(node -> getSnippetByID(node.path("id").asText())
161174
.map(entity -> entity.update(node))
162175
.orElseGet(() -> {
163176
final Snippet snippet = new Snippet(this, node);
@@ -171,22 +184,29 @@ public CompletableFuture<Collection<Snippet>> requestSnippets() {
171184
});
172185
}
173186

174-
public Optional<Snippet.Revision> getSnippetRevisionByID(int snippetId, int id) throws IndexOutOfBoundsException {
175-
if (id == -1) return Optional.empty();
176-
187+
public Optional<Snippet.Revision> getSnippetRevisionByID(String snippetId, int id) throws IndexOutOfBoundsException {
177188
synchronized (snippetCache) {
178-
return Optional.ofNullable(snippetCache.get(id))
189+
return Optional.ofNullable(snippetCache.get(snippetId))
179190
.flatMap(snippet -> snippet.getRevisionByID(id));
180191
}
181192
}
193+
194+
public Collection<Snippet.Revision> getSnippetRevisions() {
195+
synchronized (snippetCache) {
196+
return snippetCache.values()
197+
.stream()
198+
.flatMap(snippet -> snippet.getRevisions().stream())
199+
.collect(Collectors.toList());
200+
}
201+
}
182202

183-
public CompletableFuture<Snippet.Revision> requestSnippetRevision(int snippetId, int id) {
203+
public CompletableFuture<Snippet.Revision> requestSnippetRevision(String snippetId, int id) {
184204
return getSnippetByID(snippetId)
185205
.orElseGet(() -> requestSnippetByID(snippetId).join())
186206
.requestRevision(id);
187207
}
188208

189-
public CompletableFuture<List<Snippet.Revision>> requestSnippetRevisions(int snippetId, int id) {
209+
public CompletableFuture<List<Snippet.Revision>> requestSnippetRevisions(String snippetId, int id) {
190210
return getSnippetByID(snippetId)
191211
.orElseGet(() -> requestSnippetByID(snippetId).join())
192212
.requestRevisions();

src/main/java/io/codebottle/api/model/AbstractEntity.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@
77
public abstract class AbstractEntity {
88
protected final CodeBottle context;
99

10-
protected final @JsonProperty(required = true) int id;
10+
protected final @JsonProperty(required = true) String id;
1111

1212
protected AbstractEntity(CodeBottle context, JsonNode data) {
1313
this.context = context;
14-
this.id = data.get("id").asInt();
14+
this.id = data.get("id").asText();
1515

1616
update(data);
1717
}
1818

1919
public AbstractEntity(CodeBottle context, int id) {
2020
this.context = context;
2121

22-
this.id = id;
22+
this.id = String.valueOf(id);
2323
}
2424

25-
public int getID() {
25+
public String getID() {
2626
return id;
2727
}
2828

src/main/java/io/codebottle/api/model/Snippet.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.time.Instant;
44
import java.util.ArrayList;
5+
import java.util.Collection;
56
import java.util.Collections;
67
import java.util.List;
78
import java.util.Optional;
@@ -80,10 +81,10 @@ public Snippet update(JsonNode data) {
8081
this.description = data.path("description").asText(description);
8182
this.code = data.path("code").asText(code);
8283
this.views = data.path("views").asInt(views);
83-
this.language = context.getLanguageByID(data.path("language").path("id").asInt(-1))
84+
this.language = context.getLanguageByID(data.path("language").path("id").asText(null))
8485
.orElseGet(() -> new Language(context, data.path("language")))
8586
.update(data.path("language"));
86-
this.category = context.getCategoryByID(data.path("category").path("id").asInt(-1))
87+
this.category = context.getCategoryByID(data.path("category").path("id").asText(null))
8788
.orElseGet(() -> new Category(context, data.path("category")))
8889
.update(data.path("category"));
8990
this.votes = data.path("votes").asInt(votes);
@@ -104,6 +105,10 @@ public Optional<Revision> getRevisionByID(int id) throws IndexOutOfBoundsExcepti
104105
}
105106
}
106107

108+
public Collection<Revision> getRevisions() {
109+
return Collections.unmodifiableCollection(revisions);
110+
}
111+
107112
public CompletableFuture<Revision> requestRevision(int id) {
108113
return new CodeBottleRequest<Revision>(context)
109114
.to(Endpoint.SNIPPET_REVISION_SPECIFIC, this.id, id)
@@ -214,10 +219,10 @@ public Revision update(JsonNode data) {
214219
this.title = data.path("title").asText(title);
215220
this.description = data.path("description").asText(description);
216221
this.code = data.path("code").asText(code);
217-
this.language = context.getLanguageByID(data.path("language").path("id").asInt(-1))
222+
this.language = context.getLanguageByID(data.path("language").path("id").asText(null))
218223
.orElseGet(() -> new Language(context, data.path("language")))
219224
.update(data.path("language"));
220-
this.category = context.getCategoryByID(data.path("category").path("id").asInt(-1))
225+
this.category = context.getCategoryByID(data.path("category").path("id").asText(null))
221226
.orElseGet(() -> new Category(context, data.path("category")))
222227
.update(data.path("category"));
223228
this.author = data.path("author").asText(author);

src/main/java/io/codebottle/api/rest/CodeBottleRequest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import com.fasterxml.jackson.core.JsonProcessingException;
99
import com.fasterxml.jackson.databind.JsonNode;
1010
import com.fasterxml.jackson.databind.ObjectMapper;
11-
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
1211
import io.codebottle.api.CodeBottle;
1312
import io.codebottle.api.rest.exception.UnexpectedStatusCodeException;
1413
import okhttp3.Call;
@@ -48,7 +47,7 @@ public final class CodeBottleRequest<T> {
4847

4948
private final Request.Builder httpRequest;
5049

51-
private int expected;
50+
private int expected = HTTPCodes.OK;
5251

5352
static {
5453
objectMapper = new ObjectMapper();
@@ -66,13 +65,14 @@ public CodeBottleRequest(CodeBottle context) {
6665
}
6766

6867
public CodeBottleRequest<T> make(Method method, JsonNode withData) {
69-
httpRequest.method(method.name(), RequestBody.create(withData.toString(), MediaType.parse("application/json")));
68+
httpRequest.method(method.name(), method == Method.GET ? null : RequestBody.create(withData.toString(), MediaType.parse("application/json")));
7069

7170
return this;
7271
}
7372

7473
public CodeBottleRequest<T> makeGET() {
75-
return make(Method.GET, JsonNodeFactory.instance.objectNode());
74+
//noinspection ConstantConditions
75+
return make(Method.GET, null);
7676
}
7777

7878
public CodeBottleRequest<T> to(Endpoint endpoint, Object... at) throws IllegalArgumentException {

src/main/java/io/codebottle/api/rest/Endpoint.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
public enum Endpoint {
99
// Languages
10-
LANGUAGES("language"),
10+
LANGUAGES("languages"),
1111
LANGUAGE_SPECIFIC("language/%s"),
1212

1313
// Categories
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package io.codebottle.api.test;
2+
3+
import java.util.concurrent.CompletableFuture;
4+
5+
import io.codebottle.api.CodeBottle;
6+
import io.codebottle.api.model.Snippet;
7+
import org.junit.Before;
8+
import org.junit.Test;
9+
10+
import static java.lang.System.currentTimeMillis;
11+
12+
public class PerformanceTest {
13+
private CodeBottle codeBottle;
14+
15+
@Before
16+
public void setUp() {
17+
this.codeBottle = new CodeBottle();
18+
}
19+
20+
@Test
21+
public void requestEverything() {
22+
long start, end;
23+
24+
System.out.printf("Started requesting everything at %d epoch\n", start = currentTimeMillis());
25+
26+
codeBottle.requestLanguages().join();
27+
codeBottle.requestCategories().join();
28+
codeBottle.requestSnippets().join()
29+
.stream()
30+
.map(Snippet::requestRevisions)
31+
.forEachOrdered(CompletableFuture::join);
32+
33+
System.out.printf("Finished ingesting everything at %d epoch; took %d milliseconds\n\n", end = currentTimeMillis(), end - start);
34+
35+
final int languageCount = codeBottle.getLanguages().size();
36+
final int categoryCount = codeBottle.getCategories().size();
37+
final int snippetCount = codeBottle.getSnippets().size();
38+
final int revisionCount = codeBottle.getSnippetRevisions().size();
39+
40+
System.out.printf("Requested:\n\tLanguages:\t%d\n\tCategories:\t%d\n\tSnippets:\t%d\n\tRevisions:\t%d\n", languageCount, categoryCount, snippetCount, revisionCount);
41+
}
42+
}

0 commit comments

Comments
 (0)