Skip to content
This repository has been archived by the owner on Oct 7, 2022. It is now read-only.

Commit

Permalink
(#114) Refactor IssueSpec (#115)
Browse files Browse the repository at this point in the history
(NEW) IssueSpec.summary() : String
(NEW) IssueSpec.description : Optional<String>
(DEL) IssueSpec.nameValuePairs() : List<NameValuePair>
(NEW) UncheckedUriBuilder.paramIfPresent(String, Optional<String>):
      convenience method that adds a parameter to the URI if the
      value is present
(REF) UncheckedUriBuilder.setParameter(String, String) ->
      param(String, String)
  • Loading branch information
llorllale committed Dec 20, 2017
1 parent c529201 commit 80ff440
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 59 deletions.
7 changes: 4 additions & 3 deletions src/main/java/org/llorllale/youtrack/api/DefaultIssues.java
Expand Up @@ -83,7 +83,7 @@ public Stream<Issue> stream() throws IOException, UnauthorizedException {
this.session.baseUrl().toString()
.concat("/issue/byproject/")
.concat(this.project().id())
).setParameter("after", String.valueOf(n))
).param("after", String.valueOf(n))
.build()
)
),
Expand Down Expand Up @@ -137,8 +137,9 @@ public Issue create(IssueSpec spec) throws IOException, UnauthorizedException {
new HttpPut(
new UncheckedUriBuilder(
this.session.baseUrl().toString().concat("/issue")
).setParameter("project", this.project().id())
.addParameters(spec.nameValuePairs())
).param("project", this.project().id())
.param("summary", spec.summary())
.paramIfPresent("description", spec.description())
.build()
)
)
Expand Down
Expand Up @@ -104,7 +104,8 @@ private Issue updateSmmryDesc(IssueSpec spec) throws IOException, UnauthorizedEx
new UncheckedUriBuilder(
this.session.baseUrl().toString()
.concat(String.format(PATH_TEMPLATE, this.issue.id()))
).addParameters(spec.nameValuePairs())
).param("summary", spec.summary())
.paramIfPresent("description", spec.description())
.build()
)
)
Expand Down
59 changes: 23 additions & 36 deletions src/main/java/org/llorllale/youtrack/api/Issues.java
Expand Up @@ -17,17 +17,12 @@
package org.llorllale.youtrack.api;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import org.llorllale.youtrack.api.session.Session;
import org.llorllale.youtrack.api.session.UnauthorizedException;

Expand Down Expand Up @@ -84,19 +79,13 @@ public interface Issues {
/**
* Specifications for building an {@link Issue}.
*
* <p><strong>None</strong> of the transformations <em>spec -&gt; issue -&gt; spec</em> are
* reversible.
* The following truisms hold:
* <p>Note the following:
*
* <ul>
* <li>Users <strong>cannot</strong> expect two Issues derived from the same spec to be
* equal</li>
* <li>Two specs derived from the same issue <strong>can</strong> be expected to be equal</li>
* <li>Two Issues created from the same spec are <strong>not</strong> equal.</li>
* <li>Two specs derived from the same issue <strong>are</strong> equal.</li>
* </ul>
*
* <p>An {@link IssueSpec} is just a <em>blueprint</em> to create {@link Issue issues} and nothing
* more. The final {@link Issue#id() id} of the issue is determined by the YouTrack backend.
*
* @since 0.4.0
*/
class IssueSpec {
Expand Down Expand Up @@ -168,16 +157,23 @@ public IssueSpec with(Field field, FieldValue value) {
}

/**
* A view of this spec as name-value pairs.
* The summary text for the issue.
*
* @return this spec as name-value pairs
* @since 0.4.0
* @return the summary text for the issue
* @since 1.0.0
*/
public String summary() {
return this.summary;
}

/**
* The descriptive text for the issue, if specified.
*
* @return the descriptive text for the issue, if specified
* @since 1.0.0
*/
List<NameValuePair> nameValuePairs() {
final List<NameValuePair> pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair("summary", this.summary));
this.description.ifPresent(d -> pairs.add(new BasicNameValuePair("description", d)));
return pairs;
public Optional<String> description() {
return this.description;
}

/**
Expand All @@ -186,7 +182,7 @@ List<NameValuePair> nameValuePairs() {
* @return this spec as Issue {@link Field fields} and {@link FieldValue values}
* @since 0.8.0
*/
Map<Field, FieldValue> fields() {
public Map<Field, FieldValue> fields() {
return Collections.unmodifiableMap(this.fields);
}

Expand All @@ -198,23 +194,14 @@ public boolean equals(Object object) {
}

final IssueSpec other = (IssueSpec) object;

if (this.nameValuePairs().size() != other.nameValuePairs().size()) {
return false;
}

for (NameValuePair pair : this.nameValuePairs()) {
if (!other.nameValuePairs().contains(pair)) {
return false;
}
}

return this.fields().equals(other.fields());
return this.summary().equals(other.summary())
&& this.description().equals(other.description())
&& this.fields().equals(other.fields());
}

@Override
public int hashCode() {
return this.nameValuePairs().hashCode() + this.fields().hashCode();
return this.summary().hashCode() + this.description().hashCode() + this.fields().hashCode();
}
}
}
Expand Up @@ -19,9 +19,7 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;

import org.apache.http.NameValuePair;
import java.util.Optional;
import org.apache.http.client.utils.URIBuilder;

/**
Expand Down Expand Up @@ -98,20 +96,22 @@ final class UncheckedUriBuilder {
* @return this object
* @since 0.1.0
*/
public UncheckedUriBuilder setParameter(String name, String value) {
public UncheckedUriBuilder param(String name, String value) {
this.builder.setParameter(name, value);
return this;
}

/**
* Adds {@code params} on the internal {@link URIBuilder}.
* Calls the internal {@link URIBuilder#setParameter(java.lang.String, java.lang.String)} with
* the values provided, if {@code value} is present.
*
* @param params the query parameters
* @param name the name of the parameter
* @param value the parameter's value
* @return this object
* @since 0.4.0
* @since 1.0.0
*/
public UncheckedUriBuilder addParameters(List<NameValuePair> params) {
this.builder.addParameters(params);
public UncheckedUriBuilder paramIfPresent(String name, Optional<String> value) {
value.ifPresent(v -> this.param(name, v));
return this;
}

Expand Down
48 changes: 38 additions & 10 deletions src/test/java/org/llorllale/youtrack/api/IssueSpecTest.java
Expand Up @@ -18,7 +18,7 @@

import java.util.Map;
import java.util.Objects;
import org.apache.http.message.BasicNameValuePair;
import java.util.Optional;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.containsInAnyOrder;
Expand All @@ -37,14 +37,42 @@
* @since 0.4.0
*/
public class IssueSpecTest {
/**
* {@link IssueSpec#summary()} must return the input summary text.
*
* @since 1.0.0
*/
@Test
public void nameValuePairs() {
public void summary() {
assertThat(
new IssueSpec("summary", "description").nameValuePairs(),
containsInAnyOrder(
new BasicNameValuePair("summary", "summary"),
new BasicNameValuePair("description", "description")
)
new IssueSpec("summary").summary(),
is("summary")
);
}

/**
* {@link IssueSpec#description()} must return an optional with the given description.
*
* @since 1.0.0
*/
@Test
public void description() {
assertThat(
new IssueSpec("", "description").description(),
is(Optional.of("description"))
);
}

/**
* {@link IssueSpec#description()} must return an empty optional if no description was provided.
*
* @since 1.0.0
*/
@Test
public void noDescription() {
assertThat(
new IssueSpec("summary").description(),
is(Optional.empty())
);
}

Expand Down Expand Up @@ -135,7 +163,7 @@ public void equalsIsFalseWithNonIssueSpec() {
* @since 1.0.0
*/
@Test
public void equalsIfFalseWithDiffNameValuePairs() {
public void equalsIfFalseWithDiffDescription() {
final Field f1 = new MockField("field1", new MockProject());
final FieldValue v1 = new MockFieldValue(f1, "value1");
final Field f2 = new MockField("field2", new MockProject());
Expand All @@ -149,7 +177,7 @@ public void equalsIfFalseWithDiffNameValuePairs() {
}

/**
* Hashcode must be equal to hashcodes of namevaluepairs and fields.
* Hashcode must be equal to hashcodes of the summary, description, and the fields.
*
* @since 1.0.0
*/
Expand All @@ -165,7 +193,7 @@ public void testHashCode() {

assertThat(
spec.hashCode(),
is(spec.nameValuePairs().hashCode() + spec.fields().hashCode())
is(spec.summary().hashCode() + spec.description().hashCode() + spec.fields().hashCode())
);
}

Expand Down

0 comments on commit 80ff440

Please sign in to comment.