Skip to content
This repository was archived by the owner on Jan 31, 2022. It is now read-only.

Commit d32860a

Browse files
authored
ignorePlurals: Also accept list of language ISO codes (#178)
* ignorePlurals: Also accept list of country ISO codes * Changelog: add ignorePlurals update [ci skip] * ignorePlurals: take unboxed boolean parameter in setter * ignorePlurals: Use Collection instead of List * ignorePlurals: Accept String vararg instead of comma-separated list * ignorePlurals: take unboxed boolean parameter in constructor too * ignorePlurals: update documentation * ignorePlurals: Null-safety and annotations * ignorePlurals: Update tests
1 parent 709c04c commit d32860a

File tree

3 files changed

+195
-15
lines changed

3 files changed

+195
-15
lines changed

ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Change Log
66
### New features
77

88
- (#163) Search in your facets values with `Index.searchForFacetValues`
9+
- (#178) Accept a list of language ISO codes for ignorePlurals. **Note**: this introduces backward-incompatible changes.
10+
911

1012
## 3.6.0 (2016-11-10)
1113

algoliasearch/src/main/java/com/algolia/search/saas/Query.java

Lines changed: 141 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
import org.json.JSONException;
99

1010
import java.util.ArrayList;
11+
import java.util.Arrays;
12+
import java.util.Collection;
13+
import java.util.Collections;
1114
import java.util.List;
1215

1316
/*
@@ -422,16 +425,151 @@ public Integer getHitsPerPage() {
422425

423426
private static final String KEY_IGNORE_PLURALS = "ignorePlurals";
424427

428+
/**
429+
* A value of the {@code ignorePlurals} setting.
430+
* Can represent either a boolean or a list of language codes, see https://www.algolia.com/doc/faq/searching/how-does-ignoreplurals-work.
431+
*/
432+
public static final class IgnorePlurals {
433+
/** Wether plurals are ignored. */
434+
public final boolean enabled;
435+
436+
/** A list containing every active language's code. When {@code null}, all supported languages are be used. */
437+
public final List<String> languageCodes;
438+
439+
/**
440+
* Construct an IgnorePlurals object for a boolean value.
441+
*
442+
* @param b if {@code true}, the engine will ignore plurals in all supported languages.
443+
*/
444+
public IgnorePlurals(boolean b) {
445+
this.enabled = b;
446+
languageCodes = null;
447+
}
448+
449+
/**
450+
* Construct an IgnorePlurals object for a {@link Collection} of language codes.
451+
*
452+
* @param codes a list of language codes to ignore plurals from. if {@code null},
453+
* the engine will ignore plurals in all supported languages.
454+
*/
455+
public IgnorePlurals(@Nullable Collection<String> codes) {
456+
this.enabled = !isEmptyCollection(codes);
457+
languageCodes = codes != null ? new ArrayList<>(codes) : null;
458+
}
459+
460+
/**
461+
* Construct an IgnorePlurals object for some language codes.
462+
*
463+
* @param codes one or several language codes to ignore plurals from.
464+
* if {@code null}, the engine will ignore plurals in all supported languages.
465+
*/
466+
public IgnorePlurals(@Nullable String... codes) {
467+
this(codes == null ? null : Arrays.asList(codes));
468+
}
469+
470+
private boolean isEmptyCollection(@Nullable Collection<String> codesList) {
471+
return codesList == null || codesList.size() == 0;
472+
}
473+
474+
@Override
475+
public String toString() {
476+
if (!enabled) {
477+
return "false";
478+
} else {
479+
if (isEmptyCollection(languageCodes)) { // enabled without specific language
480+
return "true";
481+
} else {
482+
return TextUtils.join(",", languageCodes);
483+
}
484+
}
485+
}
486+
487+
static @NonNull IgnorePlurals parse(String s) {
488+
if (s == null || s.length() == 0 || s.equals("null")) {
489+
return new IgnorePlurals(false);
490+
} else if ("true".equals(s) || "false".equals(s)) {
491+
return new IgnorePlurals(parseBoolean(s));
492+
} else {
493+
ArrayList<String> codesList = new ArrayList<>();
494+
//ignorePlurals=["en","fi"]
495+
try {
496+
JSONArray codesArray = new JSONArray(s);
497+
for (int i = 0; i < codesArray.length(); i++) {
498+
codesList.add(codesArray.getJSONObject(i).toString());
499+
}
500+
return new IgnorePlurals(codesList);
501+
} catch (JSONException e) {
502+
// s was not a JSONArray of strings. Maybe it is a comma-separated list?
503+
final String[] split = TextUtils.split(s, ",");
504+
if (split != null && split.length != 0) {
505+
Collections.addAll(codesList, split);
506+
return new IgnorePlurals(codesList);
507+
} else {
508+
final String msg = "Error while parsing `" + s + "`: invalid ignorePlurals value.";
509+
throw new RuntimeException(msg);
510+
}
511+
}
512+
}
513+
}
514+
515+
@Override
516+
public boolean equals(Object o) {
517+
if (this == o) {
518+
return true;
519+
}
520+
if (o == null || getClass() != o.getClass()) {
521+
return false;
522+
}
523+
524+
IgnorePlurals that = (IgnorePlurals) o;
525+
526+
if (enabled != that.enabled) {
527+
return false;
528+
}
529+
return languageCodes != null ? languageCodes.equals(that.languageCodes) : that.languageCodes == null;
530+
531+
}
532+
533+
@Override
534+
public int hashCode() {
535+
int result = (enabled ? 1 : 0);
536+
result = 31 * result + (languageCodes != null ? languageCodes.hashCode() : 0);
537+
return result;
538+
}
539+
}
540+
425541
/**
426542
* If set to true, plural won't be considered as a typo (for example
427543
* car/cars will be considered as equals). Default to false.
428544
*/
429-
public @NonNull Query setIgnorePlurals(Boolean enabled) {
545+
public
546+
@NonNull
547+
Query setIgnorePlurals(boolean enabled) {
430548
return set(KEY_IGNORE_PLURALS, enabled);
431549
}
432550

433-
public Boolean getIgnorePlurals() {
434-
return parseBoolean(get(KEY_IGNORE_PLURALS));
551+
/**
552+
* A list of language codes for which plural won't be considered as a typo (for example
553+
* car/cars will be considered as equals). If empty or null, this disables the feature.
554+
*/
555+
public
556+
@NonNull
557+
Query setIgnorePlurals(@Nullable Collection<String> languageISOCodes) {
558+
return set(KEY_IGNORE_PLURALS, new IgnorePlurals(languageISOCodes));
559+
}
560+
561+
/**
562+
* One or several language codes for which plural won't be considered as a typo (for example
563+
* car/cars will be considered as equals). If empty or null, this disables the feature.
564+
*/
565+
public
566+
@NonNull
567+
Query setIgnorePlurals(@Nullable String... languageISOCodes) {
568+
return set(KEY_IGNORE_PLURALS, new IgnorePlurals(languageISOCodes));
569+
}
570+
571+
public @NonNull IgnorePlurals getIgnorePlurals() {
572+
return IgnorePlurals.parse(get(KEY_IGNORE_PLURALS));
435573
}
436574

437575
/**

algoliasearch/src/test/java/com/algolia/search/saas/QueryTest.java

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727
import org.json.JSONException;
2828
import org.junit.Test;
2929

30+
import java.util.ArrayList;
31+
import java.util.List;
32+
33+
import static junit.framework.Assert.assertFalse;
34+
import static junit.framework.Assert.assertNotNull;
3035
import static org.junit.Assert.assertArrayEquals;
3136
import static org.junit.Assert.assertEquals;
3237
import static org.junit.Assert.assertNull;
@@ -36,7 +41,7 @@
3641
/**
3742
* Unit tests for the `Query` class.
3843
*/
39-
public class QueryTest extends RobolectricTestCase {
44+
public class QueryTest extends RobolectricTestCase {
4045

4146
// ----------------------------------------------------------------------
4247
// Build & parse
@@ -152,17 +157,52 @@ public void test_getRankingInfo() {
152157

153158
@Test
154159
public void test_ignorePlurals() {
155-
Query query1 = new Query();
156-
assertNull(query1.getIgnorePlurals());
157-
query1.setIgnorePlurals(true);
158-
assertEquals(query1.getIgnorePlurals(), Boolean.TRUE);
159-
Query query2 = Query.parse(query1.build());
160-
assertEquals(query2.getIgnorePlurals(), query1.getIgnorePlurals());
161-
162-
query1.setIgnorePlurals(false);
163-
assertEquals(query1.getIgnorePlurals(), Boolean.FALSE);
164-
Query query3 = Query.parse(query1.build());
165-
assertEquals(query3.getIgnorePlurals(), query1.getIgnorePlurals());
160+
// No value
161+
Query query = new Query();
162+
assertFalse("By default, ignorePlurals should be disabled.", query.getIgnorePlurals().enabled);
163+
164+
// Boolean values
165+
query.setIgnorePlurals(true);
166+
assertEquals("A true boolean should enable ignorePlurals.", Boolean.TRUE, query.getIgnorePlurals().enabled);
167+
assertEquals("A true boolean should be built and parsed successfully.", query.getIgnorePlurals(), Query.parse(query.build()).getIgnorePlurals());
168+
169+
query.setIgnorePlurals(false);
170+
assertEquals("A false boolean should disable ignorePlurals.", Boolean.FALSE, query.getIgnorePlurals().enabled);
171+
assertEquals("A false boolean should be built and parsed successfully.", query.getIgnorePlurals(), Query.parse(query.build()).getIgnorePlurals());
172+
173+
// List values
174+
query.setIgnorePlurals((List<String>) null);
175+
assertFalse("A null list value should disable ignorePlurals.", query.getIgnorePlurals().enabled);
176+
assertEquals("A null list value should be built and parsed successfully.", query.getIgnorePlurals(), Query.parse(query.build()).getIgnorePlurals());
177+
178+
query.setIgnorePlurals(new ArrayList<String>());
179+
assertFalse("Setting an empty list should disable ignorePlurals.", query.getIgnorePlurals().enabled);
180+
181+
ArrayList<String> languageCodes = new ArrayList<>(java.util.Arrays.asList("en", "fr"));
182+
query.setIgnorePlurals(languageCodes);
183+
assertTrue("Setting a non-empty list should enable ignorePlurals.", query.getIgnorePlurals().enabled);
184+
assertNotNull("The language codes should not be null", query.getIgnorePlurals().languageCodes);
185+
assertEquals("Two language codes should be in ignorePlurals.", 2, query.getIgnorePlurals().languageCodes.size());
186+
assertTrue("The first language code should be in ignorePlurals", query.getIgnorePlurals().languageCodes.contains(languageCodes.get(0)));
187+
assertTrue("The second language code should be in ignorePlurals", query.getIgnorePlurals().languageCodes.contains(languageCodes.get(1)));
188+
189+
// String[] values
190+
query.setIgnorePlurals("");
191+
assertFalse("An empty string should disable ignorePlurals.", query.getIgnorePlurals().enabled);
192+
assertEquals("A empty string should be built and parsed successfully.", query.getIgnorePlurals(), Query.parse(query.build()).getIgnorePlurals());
193+
194+
query.setIgnorePlurals("en");
195+
assertEquals("A single language code should enable ignorePlurals.", Boolean.TRUE, query.getIgnorePlurals().enabled);
196+
assertEquals("A single language code should be built and parsed successfully.", query.getIgnorePlurals(), Query.parse(query.build()).getIgnorePlurals());
197+
assertEquals("One language code should be in ignorePlurals.", 1, query.getIgnorePlurals().languageCodes.size());
198+
assertTrue("The language code should be in ignorePlurals", query.getIgnorePlurals().languageCodes.contains("en"));
199+
200+
query.setIgnorePlurals("en", "fr");
201+
assertEquals("Two language codes should enable ignorePlurals.", Boolean.TRUE, query.getIgnorePlurals().enabled);
202+
assertEquals("Two language codes should be built and parsed successfully.", query.getIgnorePlurals(), Query.parse(query.build()).getIgnorePlurals());
203+
assertEquals("Two language codes should be in ignorePlurals.", 2, query.getIgnorePlurals().languageCodes.size());
204+
assertTrue("The first language code should be in ignorePlurals", query.getIgnorePlurals().languageCodes.contains("en"));
205+
assertTrue("The second language code should be in ignorePlurals", query.getIgnorePlurals().languageCodes.contains("fr"));
166206
}
167207

168208
@Test

0 commit comments

Comments
 (0)