Add appendPath and appendPathSegments methods to URIBuilder (#234)

diff --git a/httpcore5/src/main/java/org/apache/hc/core5/net/URIBuilder.java b/httpcore5/src/main/java/org/apache/hc/core5/net/URIBuilder.java
index 89768e9..25da44d 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/net/URIBuilder.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/net/URIBuilder.java
@@ -500,6 +500,18 @@
     }
 
     /**
+     * Appends path to URI. The value is expected to be unescaped and may contain non ASCII characters.
+     *
+     * @return this.
+     */
+    public URIBuilder appendPath(final String path) {
+        if (path != null) {
+            appendPathSegments(splitPath(path));
+        }
+        return this;
+    }
+
+    /**
      * Sets URI path. The value is expected to be unescaped and may contain non ASCII characters.
      *
      * @return this.
@@ -513,6 +525,15 @@
     }
 
     /**
+     * Appends segments URI path. The value is expected to be unescaped and may contain non ASCII characters.
+     *
+     * @return this.
+     */
+    public URIBuilder appendPathSegments(final String... pathSegments) {
+        return appendPathSegments(Arrays.asList(pathSegments));
+    }
+
+    /**
      * Sets rootless URI path (the first segment does not start with a /).
      * The value is expected to be unescaped and may contain non ASCII characters.
      *
@@ -542,6 +563,20 @@
     }
 
     /**
+     * Appends segments to URI path. The value is expected to be unescaped and may contain non ASCII characters.
+     *
+     * @return this.
+     */
+    public URIBuilder appendPathSegments(final List<String> pathSegments) {
+        if (pathSegments != null & pathSegments.size() > 0) {
+            final List<String> segments = new ArrayList<>(getPathSegments());
+            segments.addAll(pathSegments);
+            setPathSegments(segments);
+        }
+        return this;
+    }
+
+    /**
      * Sets rootless URI path (the first segment does not start with a /).
      * The value is expected to be unescaped and may contain non ASCII characters.
      *
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/net/TestURIBuilder.java b/httpcore5/src/test/java/org/apache/hc/core5/net/TestURIBuilder.java
index 8e5b334..cdea710 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/net/TestURIBuilder.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/net/TestURIBuilder.java
@@ -545,6 +545,90 @@
     }
 
     @Test
+    public void testAppendToExistingPath() throws Exception {
+        final URI uri = new URIBuilder()
+            .setScheme("https")
+            .setHost("somehost")
+            .setPath("api")
+            .appendPath("v1/resources")
+            .build();
+        MatcherAssert.assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/api/v1/resources")));
+    }
+
+    @Test
+    public void testAppendToNonExistingPath() throws Exception {
+        final URI uri = new URIBuilder()
+            .setScheme("https")
+            .setHost("somehost")
+            .appendPath("api/v2/customers")
+            .build();
+        MatcherAssert.assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/api/v2/customers")));
+    }
+
+    @Test
+    public void testAppendNullToExistingPath() throws Exception {
+        final URI uri = new URIBuilder()
+            .setScheme("https")
+            .setHost("somehost")
+            .setPath("api")
+            .appendPath(null)
+            .build();
+        MatcherAssert.assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/api")));
+    }
+
+    @Test
+    public void testAppendNullToNonExistingPath() throws Exception {
+        final URI uri = new URIBuilder()
+            .setScheme("https")
+            .setHost("somehost")
+            .appendPath(null)
+            .build();
+        MatcherAssert.assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost")));
+    }
+
+    @Test
+    public void testAppendSegmentsToExistingPath() throws Exception {
+        final URI uri = new URIBuilder()
+            .setScheme("https")
+            .setHost("myhost")
+            .setPath("api")
+            .appendPathSegments("v3", "products")
+            .build();
+        MatcherAssert.assertThat(uri, CoreMatchers.equalTo(URI.create("https://myhost/api/v3/products")));
+    }
+
+    @Test
+    public void testAppendSegmentsToNonExistingPath() throws Exception {
+        final URI uri = new URIBuilder()
+            .setScheme("https")
+            .setHost("somehost")
+            .appendPathSegments("api", "v2", "customers")
+            .build();
+        MatcherAssert.assertThat(uri, CoreMatchers.equalTo(URI.create("https://somehost/api/v2/customers")));
+    }
+
+    @Test
+    public void testAppendSegmentsListToExistingPath() throws Exception {
+        final URI uri = new URIBuilder()
+            .setScheme("http")
+            .setHost("myhost")
+            .setPath("api")
+            .appendPathSegments(Arrays.asList("v3", "products"))
+            .build();
+        MatcherAssert.assertThat(uri, CoreMatchers.equalTo(URI.create("http://myhost/api/v3/products")));
+    }
+
+    @Test
+    public void testAppendSegmentsListToNonExistingPath() throws Exception {
+        final URI uri = new URIBuilder()
+            .setScheme("http")
+            .setHost("myhost")
+            .appendPathSegments(Arrays.asList("api", "v3", "customers"))
+            .build();
+        MatcherAssert.assertThat(uri, CoreMatchers.equalTo(URI.create("http://myhost/api/v3/customers")));
+    }
+
+    @Test
     public void testNoAuthorityAndPathSegments() throws Exception {
         final URI uri = new URIBuilder()
                 .setScheme("file")