diff --git a/src/main/java/com/jcabi/github/Coordinates.java b/src/main/java/com/jcabi/github/Coordinates.java index 786e1aa40..3549595fd 100644 --- a/src/main/java/com/jcabi/github/Coordinates.java +++ b/src/main/java/com/jcabi/github/Coordinates.java @@ -43,6 +43,11 @@ @Immutable public interface Coordinates extends Comparable { + /** + * Coordinate pats separator. + */ + String SEPARATOR = "/"; + /** * Get usr name. * @return User name @@ -59,7 +64,7 @@ public interface Coordinates extends Comparable { * Jcabi.http implementation. */ @Immutable - @EqualsAndHashCode(of = { "usr", "rpo" }) + @EqualsAndHashCode(of = {"usr", "rpo"}) final class Simple implements Coordinates { /** * User name. @@ -69,6 +74,7 @@ final class Simple implements Coordinates { * Repository name. */ private final transient String rpo; + /** * Public ctor. * @param user User name @@ -78,12 +84,13 @@ public Simple(final String user, final String repo) { this.usr = user; this.rpo = repo; } + /** * Public ctor. * @param mnemo Mnemo name */ public Simple(final String mnemo) { - final String[] parts = mnemo.split("/", 2); + final String[] parts = mnemo.split(Coordinates.SEPARATOR, 2); if (parts.length != 2) { throw new IllegalArgumentException( String.format("invalid coordinates '%s'", mnemo) @@ -92,18 +99,22 @@ public Simple(final String mnemo) { this.usr = parts[0]; this.rpo = parts[1]; } + @Override public String toString() { return String.format("%s/%s", this.usr, this.rpo); } + @Override public String user() { return this.usr; } + @Override public String repo() { return this.rpo; } + @Override public int compareTo(final Coordinates other) { return new CompareToBuilder() @@ -112,4 +123,73 @@ public int compareTo(final Coordinates other) { .build(); } } + + /** + * Implementation of HTTPs coordinates. + * @author volodya-lombrozo + */ + @Immutable + @EqualsAndHashCode + final class Https implements Coordinates { + + /** + * Github domain. + */ + private static final String DOMAIN = "https://github.com/"; + + /** + * URL. + */ + private final String url; + + /** + * Public ctor. + * @param https URL + */ + public Https(final String https) { + this.url = https; + } + + @Override + public String user() { + return this.split()[0]; + } + + @Override + public String repo() { + final String repo = this.split()[1]; + final String suffix = ".git"; + if (repo.endsWith(suffix)) { + return repo.substring(0, repo.length() - suffix.length()); + } else { + return repo; + } + } + + @Override + public int compareTo(final Coordinates other) { + return new CompareToBuilder() + .append(this.user(), other.user()) + .append(this.repo(), other.repo()) + .build(); + } + + /** + * Split URL. + * @return Array of repo coordinates. + */ + private String[] split() { + if (!this.url.startsWith(Https.DOMAIN)) { + throw new IllegalArgumentException( + String.format( + "Invalid URL, the '%s' should start with '%s'", + this.url, + Https.DOMAIN + ) + ); + } + return this.url.substring(Https.DOMAIN.length()) + .split(Coordinates.SEPARATOR, 2); + } + } } diff --git a/src/test/java/com/jcabi/github/CoordinatesTest.java b/src/test/java/com/jcabi/github/CoordinatesTest.java new file mode 100644 index 000000000..860924ba7 --- /dev/null +++ b/src/test/java/com/jcabi/github/CoordinatesTest.java @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2013-2023, jcabi.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: 1) Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. 2) Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. 3) Neither the name of the jcabi.com nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jcabi.github; + +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; + +/** + * Test case for {@link Coordinates}. + * @author Volodya Lombrozo (volodya.lombrozo@gmail.com) + * @version $Id$ + */ +public final class CoordinatesTest { + + /** + * Coordinates.Https can retrieve user and repo from https coordinates. + */ + @Test + public void retrievesUserAndRepoFromHttpsCoordinates() { + final Coordinates coords = new Coordinates.Https( + "https://github.com/yegor256/takes.git" + ); + final String repo = "takes"; + final String user = "yegor256"; + MatcherAssert.assertThat( + String.format( + "Repo is retrieved incorrectly, we expect '%s', but was '%s'", + repo, + coords.repo() + ), + coords.repo(), + Matchers.equalTo(repo) + ); + MatcherAssert.assertThat( + String.format( + "User is retrieved incorrectly, we expect '%s', but was '%s'", + user, + coords.user() + ), + coords.user(), + Matchers.equalTo(user) + ); + } + + /** + * Coordinates.Https equal if they have the same url. + */ + @Test + public void sameHttpsCoordinatesAreEqual() { + final String same = "https://github.com/apache/tomcat.git"; + MatcherAssert.assertThat( + "Same coordinates are equal", + new Coordinates.Https(same), + Matchers.equalTo(new Coordinates.Https(same)) + ); + } + + /** + * Coordinates.Https can be compared. + */ + @Test + public void comparesHttpsCoordinates() { + final String first = "https://github.com/apache/kafka.git"; + final String second = "https://github.com/jcabi/jcabi-github"; + final int difference = 9; + MatcherAssert.assertThat( + "First coordinates are less than second", + new Coordinates.Https(first) + .compareTo(new Coordinates.Https(second)), + Matchers.equalTo(-difference) + ); + MatcherAssert.assertThat( + "Second coordinates are greater than first", + new Coordinates.Https(second) + .compareTo(new Coordinates.Https(first)), + Matchers.equalTo(difference) + ); + MatcherAssert.assertThat( + "Same https coordinates are equal", + new Coordinates.Https(first) + .compareTo(new Coordinates.Https(first)), + Matchers.equalTo(0) + ); + } + + /** + * Coordinates.Simple can be compared with Coordinates.Https. + */ + @Test + public void comparesSimpleAndHttpsCoordinates() { + MatcherAssert.assertThat( + "Coordinates should be equal", + new Coordinates.Simple("volodya-lombrozo/jtcop") + .compareTo( + new Coordinates.Https( + "https://github.com/volodya-lombrozo/jtcop" + ) + ), + Matchers.equalTo(0) + ); + } +}