Skip to content

Commit f85efeb

Browse files
authored
Fix commons-app#4347: Remove leading and trailing spaces in title (commons-app#5141)
* Update method to remove leading whitespace * Update test cases testing remove whitespace method * Remove unused whitespace check method * Add comment about use of strip and trim in dealing with whitespace
1 parent 654a0fc commit f85efeb

File tree

2 files changed

+45
-42
lines changed

2 files changed

+45
-42
lines changed

app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailAdapter.java

+26-22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package fr.free.nrw.commons.upload;
22

33
import android.app.Dialog;
4-
import android.content.Intent;
54
import android.text.Editable;
65
import android.text.InputFilter;
76
import android.text.TextUtils;
@@ -23,7 +22,6 @@
2322
import butterknife.ButterKnife;
2423
import com.google.android.material.textfield.TextInputLayout;
2524
import fr.free.nrw.commons.R;
26-
import fr.free.nrw.commons.contributions.MainActivity;
2725
import fr.free.nrw.commons.recentlanguages.Language;
2826
import fr.free.nrw.commons.recentlanguages.RecentLanguagesAdapter;
2927
import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao;
@@ -32,10 +30,8 @@
3230
import java.util.ArrayList;
3331
import java.util.HashMap;
3432
import java.util.List;
35-
import java.util.Locale;
3633
import java.util.Objects;
3734
import java.util.regex.Pattern;
38-
import javax.inject.Inject;
3935
import timber.log.Timber;
4036

4137
public class UploadMediaDetailAdapter extends RecyclerView.Adapter<UploadMediaDetailAdapter.ViewHolder> {
@@ -198,7 +194,8 @@ public void bind(int position) {
198194

199195
removeButton.setOnClickListener(v -> removeDescription(uploadMediaDetail, position));
200196
captionListener = new AbstractTextWatcher(
201-
captionText -> uploadMediaDetails.get(position).setCaptionText(convertIdeographicSpaceToLatinSpace(removeTrailingWhitespace(captionText))));
197+
captionText -> uploadMediaDetails.get(position).setCaptionText(convertIdeographicSpaceToLatinSpace(
198+
removeLeadingAndTrailingWhitespace(captionText))));
202199
descriptionListener = new AbstractTextWatcher(
203200
descriptionText -> uploadMediaDetails.get(position).setDescriptionText(descriptionText));
204201
captionItemEditText.addTextChangedListener(captionListener);
@@ -421,28 +418,35 @@ private void setUpRecentLanguagesSection(final List<Language> recentLanguages) {
421418
}
422419

423420
/**
424-
* Checks if the source string contains trailing whitespace
421+
* Removes any leading and trailing whitespace from the source text.
425422
* @param source input string
426-
* @return true if contains trailing whitespace and false otherwise
423+
* @return a string without leading and trailing whitespace
427424
*/
428-
public Boolean checkTrailingWhitespace(String source) {
429-
int len = source.length();
430-
if (len == 0) {
431-
return false;
425+
public String removeLeadingAndTrailingWhitespace(String source) {
426+
// This method can be replaced with the inbuilt String::strip when updated to JDK 11.
427+
// Note that String::trim does not adequately remove all whitespace chars.
428+
int firstNonWhitespaceIndex = 0;
429+
while (firstNonWhitespaceIndex < source.length()) {
430+
if (Character.isWhitespace(source.charAt(firstNonWhitespaceIndex))) {
431+
firstNonWhitespaceIndex++;
432+
} else {
433+
break;
434+
}
435+
}
436+
if (firstNonWhitespaceIndex == source.length()) {
437+
return "";
432438
}
433-
return Character.isWhitespace(source.charAt(len - 1));
434-
}
435439

436-
/**
437-
* Removes any trailing whitespace from the source text.
438-
* @param source input string
439-
* @return a string without trailing whitespace
440-
*/
441-
public String removeTrailingWhitespace(String source) {
442-
while (checkTrailingWhitespace(source)) {
443-
source = source.substring(0, source.length() - 1);
440+
int lastNonWhitespaceIndex = source.length() - 1;
441+
while (lastNonWhitespaceIndex > firstNonWhitespaceIndex) {
442+
if (Character.isWhitespace(source.charAt(lastNonWhitespaceIndex))) {
443+
lastNonWhitespaceIndex--;
444+
} else {
445+
break;
446+
}
444447
}
445-
return source;
448+
449+
return source.substring(firstNonWhitespaceIndex, lastNonWhitespaceIndex + 1);
446450
}
447451

448452
/**

app/src/test/kotlin/fr/free/nrw/commons/upload/UploadMediaDetailAdapterUnitTest.kt

+19-20
Original file line numberDiff line numberDiff line change
@@ -248,39 +248,39 @@ class UploadMediaDetailAdapterUnitTest {
248248
}
249249

250250
@Test
251-
fun testRemoveTrailingWhitespace() {
251+
fun testRemoveLeadingAndTrailingWhitespace() {
252252
// empty space
253-
val test1 = "test "
253+
val test1 = " test "
254254
val expected1 = "test"
255-
Assert.assertTrue(viewHolder.checkTrailingWhitespace(test1));
256-
Assert.assertEquals(expected1, viewHolder.removeTrailingWhitespace(test1))
255+
Assert.assertEquals(expected1, viewHolder.removeLeadingAndTrailingWhitespace(test1))
257256

258-
val test2 = "test test "
257+
val test2 = " test test "
259258
val expected2 = "test test"
260-
Assert.assertTrue(viewHolder.checkTrailingWhitespace(test2));
261-
Assert.assertEquals(expected2, viewHolder.removeTrailingWhitespace(test2))
259+
Assert.assertEquals(expected2, viewHolder.removeLeadingAndTrailingWhitespace(test2))
262260

263261
// No whitespace
264262
val test3 = "No trailing space";
265263
val expected3 = "No trailing space";
266-
Assert.assertFalse(viewHolder.checkTrailingWhitespace(test3))
267-
Assert.assertEquals(expected3, viewHolder.removeTrailingWhitespace(test3))
264+
Assert.assertEquals(expected3, viewHolder.removeLeadingAndTrailingWhitespace(test3))
265+
266+
// blank string
267+
val test4 = " \r \t "
268+
val expected4 = "";
269+
Assert.assertEquals(expected4, viewHolder.removeLeadingAndTrailingWhitespace(test4))
268270
}
269271

270272
@Test
271-
fun testRemoveTrailingInstanceTab() {
272-
val test = "test\t"
273+
fun testRemoveLeadingAndTrailingInstanceTab() {
274+
val test = "\ttest\t"
273275
val expected = "test"
274-
Assert.assertTrue(viewHolder.checkTrailingWhitespace(test));
275-
Assert.assertEquals(expected, viewHolder.removeTrailingWhitespace(test))
276+
Assert.assertEquals(expected, viewHolder.removeLeadingAndTrailingWhitespace(test))
276277
}
277278

278279
@Test
279-
fun testRemoveTrailingCarriageReturn() {
280-
val test = "test\r"
280+
fun testRemoveLeadingAndTrailingCarriageReturn() {
281+
val test = "\rtest\r"
281282
val expected = "test"
282-
Assert.assertTrue(viewHolder.checkTrailingWhitespace(test));
283-
Assert.assertEquals(expected, viewHolder.removeTrailingWhitespace(test))
283+
Assert.assertEquals(expected, viewHolder.removeLeadingAndTrailingWhitespace(test))
284284
}
285285

286286
@Test
@@ -289,9 +289,8 @@ class UploadMediaDetailAdapterUnitTest {
289289
val expected1 = "テスト テスト"
290290
Assert.assertEquals(expected1, viewHolder.convertIdeographicSpaceToLatinSpace(test1));
291291

292-
val test2 = "テスト \r \t "
292+
val test2 = " \r \t テスト \r \t "
293293
val expected2 = "テスト"
294-
Assert.assertTrue(viewHolder.checkTrailingWhitespace(test2));
295-
Assert.assertEquals(expected2, viewHolder.removeTrailingWhitespace(test2))
294+
Assert.assertEquals(expected2, viewHolder.removeLeadingAndTrailingWhitespace(test2))
296295
}
297296
}

0 commit comments

Comments
 (0)