From b7de4359fd8ed47ecdeb8cc28378b081e7daa4e8 Mon Sep 17 00:00:00 2001 From: Liam Newman Date: Sun, 1 Mar 2020 21:12:38 -0800 Subject: [PATCH] Alternative proposal The guts of this version are a bit ugly but they result reasonable API code without a ton of extra code needed. --- src/main/java/org/kohsuke/github/GHLabel.java | 168 ++++++++++++------ .../java/org/kohsuke/github/GHRepository.java | 4 +- src/test/java/org/kohsuke/github/AppTest.java | 7 +- 3 files changed, 122 insertions(+), 57 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHLabel.java b/src/main/java/org/kohsuke/github/GHLabel.java index b33f97851..b93911a45 100644 --- a/src/main/java/org/kohsuke/github/GHLabel.java +++ b/src/main/java/org/kohsuke/github/GHLabel.java @@ -1,14 +1,12 @@ package org.kohsuke.github; import com.fasterxml.jackson.annotation.JacksonInject; -import com.fasterxml.jackson.annotation.JsonCreator; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; -import java.util.function.Consumer; import javax.annotation.Nonnull; @@ -68,11 +66,11 @@ public class GHLabel { * 6-letter hex color code, like "f29513" * @throws IOException * the io exception - * @deprecated use {@link #update(Consumer)} instead + * @deprecated use {@link #set()} instead */ @Deprecated public void setColor(String newColor) throws IOException { - this.update(i -> i.color(newColor)); + this.set().color(newColor); } /** @@ -82,11 +80,11 @@ public class GHLabel { * Description of label * @throws IOException * the io exception - * @deprecated use {@link #update(Consumer)} instead + * @deprecated use {@link #set()} instead */ @Deprecated public void setDescription(String newDescription) throws IOException { - this.update(i -> i.description(newDescription)); + this.set().description(newDescription); } static Collection toNames(Collection labels) { @@ -99,16 +97,20 @@ public class GHLabel { // NEW IMPLEMENTATION STARTS HERE + @JacksonInject @Nonnull - private final GitHub root; + protected final GitHub root; @Nonnull private final String url, name, color, description; - private GHRepository repository; + protected GHRepository repository; - @JsonCreator(mode = JsonCreator.Mode.DELEGATING) - private GHLabel(@Nonnull Builder builder) { + GHLabel() { + this(new GHLabelBuilder()); + } + + private GHLabel(@Nonnull GHLabelBuilder builder) { this.root = builder.root; this.url = builder.url; this.name = builder.name; @@ -122,18 +124,8 @@ public class GHLabel { * @throws IOException * the io exception */ - public static GHLabel create(GHRepository repository, Consumer initializer) throws IOException { - Builder builder = new Builder(); - initializer.accept(builder); - return repository.root.createRequest() - .withUrlPath(repository.getApiTailUrl("labels")) - .method("POST") - .with("name", builder.name) - .with("color", builder.color) - .with("description", builder.description) - .fetch(GHLabel.class) - .lateBind(repository); - + public static Creator create(GHRepository repository) throws IOException { + return new Creator(repository); } /** @@ -212,18 +204,18 @@ public class GHLabel { * @throws IOException * the io exception */ - public GHLabel update(Consumer updater) throws IOException { - Builder builder = new Builder(this); - updater.accept(builder); + public BatchUpdater update() throws IOException { + return new BatchUpdater(this); + } - return repository.root.createRequest() - .method("PATCH") - .with("name", builder.name) - .with("color", builder.color) - .with("description", builder.description) - .setRawUrlPath(url) - .fetch(GHLabel.class) - .lateBind(repository); + /** + * Modifies a label in a repository. + * + * @throws IOException + * the io exception + */ + public SingleUpdater set() throws IOException { + return new SingleUpdater(this); } /** @@ -253,41 +245,115 @@ public class GHLabel { return Objects.hash(url, name, color, repository); } - public static class Builder { + public static class SingleUpdater extends Builder { + private SingleUpdater(GHLabel base) throws IOException { + super(base, true); + requester.method("PATCH").setRawUrlPath(base.url()); + } + } + + public static class BatchUpdater extends Builder { + private BatchUpdater(GHLabel base) throws IOException { + super(base, false); + requester.method("PATCH").setRawUrlPath(base.url()); + } + } + + public static class Creator extends Builder { + private Creator(GHRepository repository) throws IOException { + super(repository); + requester.method("POST").withUrlPath(repository.getApiTailUrl("labels")); + } + } + + public static class GHLabelBuilder { private String url, name, color, description; @JacksonInject private GitHub root; - public Builder() { + public GHLabelBuilder() { + root = null; url = ""; name = ""; color = ""; description = ""; } + } - public Builder(GHLabel label) { - this.root = label.root; - // Url is maintained on the mutator but cannot be changed locally. - url = label.url(); - name = label.name(); - color = label.color(); - description = label.description(); + public static class Builder extends BaseBuilder { + + final GHRepository repository; + + public Builder(GHLabel label, boolean immediate) throws IOException { + super(label.root, GHLabel.class, label, immediate); + repository = label.repository; } - public Builder name(String value) { - name = value; - return this; + public Builder(GHRepository repository) throws IOException { + super(repository.root, GHLabel.class, new GHLabel(new GHLabelBuilder()), false); + this.repository = repository; } - public Builder color(String value) { - color = value; - return this; + public U name(String value) throws IOException { + return with("name", value); } - public Builder description(String value) { - description = value; - return this; + public U color(String value) throws IOException { + return with("color", value); + } + + public U description(String value) throws IOException { + return with("description", value); + } + + @Override + protected void initialize(GHLabel base) throws IOException { + // Set initial values + name(base.name()); + color(base.color()); + description(base.description()); + } + + @Override + public GHLabel done() throws IOException { + return requester.fetch(returnType).lateBind(repository); + } + } + + /** + * + * @param + * @param + */ + public abstract static class BaseBuilder { + + private final boolean initialized; + private final boolean immediate; + protected final Class returnType; + protected final Requester requester; + + protected BaseBuilder(GitHub root, Class returnType, T base, boolean immediate) throws IOException { + this.requester = root.createRequest(); + this.immediate = immediate; + this.returnType = returnType; + initialize(base); + this.initialized = true; + } + + public abstract T done() throws IOException; + + protected abstract void initialize(T base) throws IOException; + + protected U with(String name, Object value) throws IOException { + requester.with(name, value); + if (initialized) { + if (immediate) { + return (U) done(); + } + return (U) this; + } + return null; } } } diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 4ab12c4bd..36f0734fd 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1900,7 +1900,7 @@ public class GHRepository extends GHObject { * the io exception */ public GHLabel createLabel(String name, String color) throws IOException { - return GHLabel.create(this, l -> l.name(name).color(color)); + return GHLabel.create(this).name(name).color(color).done(); } /** @@ -1917,7 +1917,7 @@ public class GHRepository extends GHObject { * the io exception */ public GHLabel createLabel(String name, String color, String description) throws IOException { - return GHLabel.create(this, l -> l.name(name).color(color).description(description)); + return GHLabel.create(this).name(name).color(color).description(description).done(); } /** diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index b70157289..f91de42ab 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -814,8 +814,8 @@ public class AppTest extends AbstractGitHubWireMockTest { assertEquals(t.url(), t2.url()); // update works on multiple changes in one call - t.setColor(""); - t2 = t.update(i -> i.color("000000").description("It is dark!")); + // t.setColor(""); + t2 = t.update().color("000000").description("It is dark!").done(); // instances are immutable, but update returns a new updated instance. assertEquals(t.color(), "123456"); @@ -824,9 +824,8 @@ public class AppTest extends AbstractGitHubWireMockTest { assertEquals(t2.description(), "It is dark!"); t = r.getLabel("test"); - t.update(i -> i.description("this is also a test")); + GHLabel t3 = t.set().description("this is also a test"); - GHLabel t3 = r.getLabel("test"); assertEquals(t3.color(), "000000"); assertEquals(t3.description(), "this is also a test"); t.delete();