maidh91 / guava-libraries

Automatically exported from code.google.com/p/guava-libraries
Apache License 2.0
0 stars 0 forks source link

Add functions to check blank Strings in com.google.common.base.Strings #352

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Would be useful to have functions to check blank Strings "à la" commons-lang 
in 
com.google.common.base.Strings.

Could be :
static public boolean isBlank(final String s)
static public boolean isNullOrBlank(@Nullable final String s)

Could also add :
static public @Nullable String blankToNull(@Nullable final String s).

Original issue reported on code.google.com by jbaumgarten@gmail.com on 24 Apr 2010 at 7:25

GoogleCodeExporter commented 9 years ago
I second that request. `StringUtils.isBlank()` is definitely the method in 
Commons
Lang we by far use most.

The name is also pleasantly compact. I also suggest to rename
`Strings.isNullOrEmpty()` to `Strings.isEmpty()` because that is also nicely 
compact,
uses the same naming style, and eases the transition from Commons Lang to Guava
(however, that last point is of no importance).

Original comment by j...@nwsnet.de on 27 Apr 2010 at 2:05

GoogleCodeExporter commented 9 years ago
With blankToNull, I'd propose a corresponding:

static public String nullToBlank(@Nullable final String s)

Original comment by david.he...@gmail.com on 28 Apr 2010 at 2:42

GoogleCodeExporter commented 9 years ago
What would nullToBlank be for? It'd just be the same as nullToEmpty.

Original comment by cgdec...@gmail.com on 28 Apr 2010 at 5:16

GoogleCodeExporter commented 9 years ago
Any news regarding this?

I just noticed that I can't port my code over from Commons Lang without 
`isNullOrBlank()`. It even took me a while to discover that my tests failed 
because I mistakenly replaced `StringUtils.isBlank()` with 
`Strings.isNullOrEmpty()`. :(

Original comment by j...@nwsnet.de on 21 Jun 2010 at 3:09

GoogleCodeExporter commented 9 years ago
Issue 387 has been merged into this issue.

Original comment by kevinb@google.com on 30 Jul 2010 at 3:22

GoogleCodeExporter commented 9 years ago
> I just noticed that I can't port my code over from Commons Lang without 
`isNullOrBlank()`.

If it were the only thing stopping me from switching to Guava, I would:
- create a "com.mycompany.common.thingsIWishWereInGuava.Strings2" class
- copy over the static method I am interested in (isNullOrBlank)
- configure Eclipse to use static imports as described here: 
http://piotrjagielski.com/blog/working-with-static-imports-in-eclipse/
- use the method as if it were in Guava
- star this issue, to get notified when Guava adds this method (if deemed 
useful enough), and remove my temporary class

Original comment by nev...@gmail.com on 14 Sep 2010 at 8:50

GoogleCodeExporter commented 9 years ago
It's not about switching to Guava (which I did), but ditching (our most common 
reason for using) Commons Lang.

Introducing a temporarily method, bothering co-workers to use it instead of 
what they know and have used for years, and then bothering them again to use 
the Guava method as soon as it hopefully has appeared there is far too 
cumbersome.

AFAIK, IntelliJ IDEA doesn't support static import favorites as Eclipse do, so 
that won't work. If it does, please let me know; I badly miss this for unit 
tests.

Original comment by j...@nwsnet.de on 14 Sep 2010 at 1:41

GoogleCodeExporter commented 9 years ago
My bad, I did not think about the "social" aspect of such a refactoring. 
Changing habits is often the hardest part.

In that case, if you really want to get rid of commons-lang, you could simply 
name your "temporary" utility class "org.apache.commons.lang.StringUtils" 
(exact same name as commons-lang's StringUtils), and remove the commons-lang 
jar from your classpath...
But you must be sure commons-lang won't be included by some other third-party 
jar (such as Spring), or you might have weird classpath errors. But then, if 
the jar is included anyway, why not keep using the old method for now?
Personally, I wouldn't bother...

Anyway, I was suggesting this mainly as a temporary workaround, in case you did 
not want to wait for a Guava inclusion to get rid of commons-lang.

I'm surprised that static import favorites are not supported in IntelliJ IDEA 
(according to http://youtrack.jetbrains.net/issue/IDEABKL-5119 ).

PS: StringUtils.isBlank() and StringUtils.isNotBlank() were also some of the 
most used commons-lang methods in my last project. Including those helper 
methods in Guava would be great.

Original comment by nev...@gmail.com on 14 Sep 2010 at 3:25

GoogleCodeExporter commented 9 years ago
(Note that it is not assured that this method will never appear in Guava.)

Original comment by kevinb@google.com on 15 Sep 2010 at 5:27

GoogleCodeExporter commented 9 years ago
Issue 397 has been merged into this issue.

Original comment by boppenh...@google.com on 23 Sep 2010 at 5:05

GoogleCodeExporter commented 9 years ago
is there anything new about this issue? Will a 

static public boolean isBlank(final String s)
or
static public boolean isNullOrBlank(@Nullable final String s)

be implemented in further releases?

wbr

Original comment by bernd.fa...@gmail.com on 16 Dec 2010 at 9:22

GoogleCodeExporter commented 9 years ago
static public boolean isNullOrBlank(@Nullable final String s)
  >> Strings.isNullOrEmpty() already exists.

static public boolean isBlank(final String s)
  >> If you use Java6, you can just use str.isEmpty()

Original comment by kurt.kluever on 17 Dec 2010 at 12:22

GoogleCodeExporter commented 9 years ago
@kurt.kluever:
Empty and blank are not the same thing... here blank means empty or consisting 
only of whitespace.

Original comment by cgdec...@gmail.com on 17 Dec 2010 at 12:46

GoogleCodeExporter commented 9 years ago
That makes this issue really tricky because there are tons of different 
definitions of whitespace.

Original comment by kurt.kluever on 17 Dec 2010 at 3:05

GoogleCodeExporter commented 9 years ago
> If you use Java6, you can just use str.isEmpty()
Yeap but I first have to check that the str is not null and 
Strings.isNullOrEmpty() doesn't trim the string. 
I'm agree with preceding comments, I really miss this function to remove 
commons-lang.

Original comment by christop...@gmail.com on 17 Dec 2010 at 7:55

GoogleCodeExporter commented 9 years ago
@kurt.kluever:
I don't see many definitions of whitespace: Character.isWhitespace(char/int) is 
the only one in Java.

Original comment by ogregoire on 17 Dec 2010 at 9:32

GoogleCodeExporter commented 9 years ago
@ogregoire
Pattern.compile("\\s"), StringTokenizer, String.trim(), 
Character.isWhitespace(), Unicode 5.0 "whitespace", and Unicode 5.0 "pattern 
whitespace" all have different definitions of which characters count as 
whitespace. Kevin has an awesome (Google internal) spreedsheet breaking down 
the differences between all of them.  I'll ask him if he can post it externally 
in some form.

Original comment by kurt.kluever on 17 Dec 2010 at 3:47

GoogleCodeExporter commented 9 years ago
@kurt.kluever: I'm guessing you're talking about this spreadsheet that's linked 
from CharMatcher.WHITESPACE: 
http://spreadsheets.google.com/pub?key=pd8dAQyHbdewRsnE5x5GzKQ

I agree that the different definitions of whitespace is an issue here. I think 
what many people would be replacing here is either "string == null || 
string.trim().length() == 0" (which uses the trim definition obviously) or 
StringUtils.isBlank, which uses Character.isWhitespace.

It's not as pretty as "isNullOrBlank", but maybe a more flexible approach would 
be something like:

   boolean isNullOrMatches(String string, CharMatcher matcher);

That would allow users to choose their definition of whitespace:

   if (isNullOrMatches(string, CharMatcher.JAVA_WHITESPACE)) { ... }

I feel like the problem then is that people don't want to have to choose and 
are happy with having one of Java's definitions of whitespace chosen for them. 
Maybe that's a bad thing.

Original comment by cgdec...@gmail.com on 17 Dec 2010 at 4:25

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Looking at CharMatcher also reveals a number of whitespace definitions, such as 
CharMatcher.WHITESPACE, CharMatcher.BREAKING_WHITESPACE and 
CharMatcher.JAVA_WHITESPACE.

CharMatcher.WHITESPACE.matchesAllOf(s) does the same as the isBlank(s) method 
suggested above (it is more verbose, though). If one needs to check the 
"blankness" according to a different kind of "whitespaceness", one could use 
the other CharMatchers.
It wouldn't replace isNullOrBlank(), because matchesAllOf() rejects null values 
(one of Guava's principles is to reject null values, which is a most of the 
time a good thing).

I'd like to think about the bigger picture: simple methods such as isBlank() 
and isNullOrBlank() would be great, but it would be even better to be able to 
combine Predicate, CharMatcher, and string matching. Note that you can already 
do that by creating utility classes such as:

public static StringPredicates {

public static final Predicate<String> IS_BLANK = 
matchesAllOf(CharMatcher.WHITESPACE);

public static final Predicate<String> IS_NULL_OR_BLANK = 
Predicates.and(Predicates.notNull(), IS_BLANK);

public static Predicate<String> matchesAllOf(final CharMatcher charMatcher) {
    return new Predicate<String>() {
        public boolean apply(String string) {
            return charMatcher.matchesAllOf(string);
        }
    };
}

}

Then, in your code, using static imports:

public void foo(String maybeBlankOrNull) {
    if (IS_NULL_OR_BLANK.apply(maybeBlankOrNull)) {
        // do something
    }
}

public void foo(List<String> stringsMaybeBlankOrNull) {
    List<String> strings = ImmutableList.copyOf(Collections2.filter(stringsMaybeBlankOrNull, Predicates.not(IS_NULL_OR_BLANK));
    // do something

}

Since predicates might sometimes be less readable, we could also add some of 
these utility methods with sensible defaults ("isNullOrBlank(s)" is nicer to 
read than "IS_NULL_OR_BLANK.apply(s)").

PS: I saw Colin's post after writing this... I think some of our ideas are 
similar

Original comment by nev...@gmail.com on 17 Dec 2010 at 4:42

GoogleCodeExporter commented 9 years ago
what about having an option to trim on the isNullOrEmpty. That gives people the 
option to decide if whitespace is considered empty or not for them.

boolean isNullOrEmpty(String string, boolean trim)
{
   if(trim)
   {
      return string == null || string.trim().length() == 0;
   }
   else
   {
      return string == null || string.length() == 0;
   }
}

boolean isNullOrEmpty(String string)
{
   return isNullOrEmpty(string, false);
}

Original comment by cody.le...@gmail.com on 31 Dec 2010 at 8:46

GoogleCodeExporter commented 9 years ago
cody.lerum,
This is what isNullOrBlank() should actually do, boolean parameters generally 
cause confusion.

Original comment by lystoc...@gmail.com on 1 Jan 2011 at 12:18

GoogleCodeExporter commented 9 years ago
I'm fine with isNullOrBlank(). What is the status of this making it into a 
future guava?

Original comment by cody.le...@gmail.com on 3 Jan 2011 at 1:58

GoogleCodeExporter commented 9 years ago

Original comment by fry@google.com on 28 Jan 2011 at 4:05

GoogleCodeExporter commented 9 years ago
We have had internal discussion about it.  I have begged for someone who 
understands why this method would actually be useful to explain it to me, 
because I just do not get it.

Why would you ever want to know if a string is "blank", as you say, but NOT 
want to actually trim the thing?  The fact you're even wanting to call 
isBlank() proves that leading and trailing whitespace is insignificant to you, 
so why on earth leave it there?

Where you say "checkArgument(!Strings.isBlank(s)); this.s = s;" I see "this.s = 
WHITESPACE.trimFrom(s); checkArgument(!s.isEmpty());".  The latter makes sense 
to me, the first doesn't.

And even at that, for most of the usages of this kind of method that I look at, 
I can't even find any good reason why a string with whitespace around it should 
be accepted in the first place.  I mean, sure, in a UI, where a user is 
entering text, of course you want to get whitespace off of that, but I see this 
isBlank() nonsense *everywhere* at all levels -- why?  Who's going to be 
sticking whitespace around everything?  Of course, I strongly suspect that 
there is no need to accept this kind of messy data, but well-intentioned 
developers think that it's always nice to be as accepting as possible (which is 
dead wrong).

So.  What am I missing?  It must be *something*, because this seems to be the 
most popular method in the history of computing.

Original comment by kevinb@google.com on 3 Feb 2011 at 6:32

GoogleCodeExporter commented 9 years ago
You are right in that one would really want to trim the whitespace before using 
(and checking!) in most cases.

One could think of cases, though, in which user input should be considered 
missing when nothing or just whitespace was given, but when letters were given, 
no leading or trailing whitespace should be trimmed (because it matters, e.g. 
in various markup languages).

Another issue I see that people want both a boolean indicating of a string is 
"blank" as well as the string itself (trimmed or not). That's hard to do with a 
single method as the result must be used both in a condition and for further 
string processing.

While `WHITESPACE.trimFrom(s)` solves the issue of `s.trim()` (where `s` could 
be `null` and thus needs to be checked separately), it does require a static 
import (or is quite long when called with the containing class' name).

I'll keep an eye on our usages, maybe one could all do it differently. This 
might be a case of something that is just used routinely without actually 
re-evaluating it.

In the end, a fitting helper method should be doable, but it *might* not be 
`isBlank` (as I, too, was thinking of out of habit).

Original comment by j...@nwsnet.de on 3 Feb 2011 at 9:37

GoogleCodeExporter commented 9 years ago
"One could think of cases...."  I don't know who this "one" is, but it's not 
me. :)

I don't blindly accept that "null needs to be checked separately."  Most of the 
time, null should simply cause NullPointerException.

We created CharMatcher in full awareness that using it will be more verbose 
than if we had a set of 47 static methods instead.  It's worth it.  It exposes 
the flexibility to you that you're going to need if not here, then somewhere 
else.  Also, perhaps it prompts you to question whether our WHITESPACE constant 
is really the right definition of whitespace that you're looking for... since 
there are so many.

Original comment by kevinb@google.com on 3 Feb 2011 at 2:12

GoogleCodeExporter commented 9 years ago
Actually, after further internal discussion, I'm more convinced than ever that 
this is not a useful method.  I'm closing it.  Well-reasoned arguments with 
strong evidence will still be listened to.

Original comment by kevinb@google.com on 3 Feb 2011 at 3:40

GoogleCodeExporter commented 9 years ago
@kevinb: I don't think that it's always the case that you need a trimmed 
version of the string after the test. I agree with you: I wouldn't use it in 
such cases. But I've had reasons to use isBlank() lots of times, like in this 
simple example: 

// Example 1

StringBuffer sb = new StringBuffer();
...
if (StringUtils.isBlank(email)) {
    sb.append("[not entered]"); // I don't need email trimmed!
}
...

And there are complex examples:
(this is just an arbitrary, real-life example I'm currently encountering in my 
code)

// Example 2

Google ReCaptcha explains 
(http://code.google.com/apis/recaptcha/docs/tips.html), that you should avoid 
sending captcha requests to Google's service, if the user's 
captcha_response_field was empty (let's say: blank). So I test it with 
StringUtils.isBlank(captchaResponseField);

However: I do want to send the captcha_response_field unmodified and untrimmed, 
in case the user entered at least one non-whitespace character. (Probably I 
*could* trim it, but I feel that it's more clean to send it unmodified, because 
sometimes ReCaptcha accidentally displays one blank word (never two blank 
words). Who knows, if the service might work better, if I send it untrimmed? I 
don't know. But my point is: The isBlank test can be seen as separate from the 
need to trim a string.)

Note: The value can easily be null (if the POST request from the user didn't 
contain the captcha_response_field parameter at all).

StringUtils.isBlank() is very useful, and often makes the code so much more 
readable.

Original comment by chris.lercher on 9 Jun 2011 at 3:24

GoogleCodeExporter commented 9 years ago
>> StringBuffer sb = new StringBuffer();
>> if (StringUtils.isBlank(email)) {
>>    sb.append("[not entered]"); // I don't need email trimmed!
>> }

How about a 1 liner:
sb.append(Objects.firstNonNull(Strings.emptyToNull(email), "[not entered]"));

Original comment by kurt.kluever on 9 Jun 2011 at 6:33

GoogleCodeExporter commented 9 years ago
@kurt: Unfortunately, that's not the same: Note the difference between 
"isBlank()" and "isEmpty()" - see 
http://commons.apache.org/lang/api-release/org/apache/commons/lang/StringUtils.h
tml#isBlank(java.lang.String)

i.e. in your example, we would need a Strings.blankToNull() method

Original comment by chris.lercher on 9 Jun 2011 at 6:59

GoogleCodeExporter commented 9 years ago
Just to sum up:

1) Blank is null, empty, or containing only whitespace:
isBlank(null) == true
isBlank("") == true
isBlank(" ") == true
isBlank("  ") == true
isBlank(" x") == false

2) There isn't just one definition of what whitespace is.

3) WHITESPACE.matchesAllOf(nullToEmpty(email))

4) There are IMHO far more interesting one liners that were rejected in Guava.

Original comment by gscerbak@gmail.com on 9 Jun 2011 at 7:39

GoogleCodeExporter commented 9 years ago
Issue 652 has been merged into this issue.

Original comment by kurt.kluever on 7 Jul 2011 at 2:46

GoogleCodeExporter commented 9 years ago
What about passing a special Enum(WhitespaceTypeEnum) as a second argument to 
isNullOrBlank, which would give the definition of whitespace?

>Why would you ever want to know if a string is "blank", as you say, but NOT 
want to actually trim the thing?  The fact you're even wanting to call 
isBlank() proves that leading and trailing whitespace is insignificant to you, 
so why on earth leave it there?

Because I don't want to be checking for null before calling trim(), that would 
spoil the whole point of using a library. The beauty of isNullOrEmpty is that 
it checks simultaneously(!) for null and emptiness.

Original comment by elchin.a...@gmail.com on 7 Jul 2011 at 3:34

GoogleCodeExporter commented 9 years ago
Well you can't safely trim a string if you've not yet checked for null. If you 
have checked for null, you probably wouldn't be using isNullOrEmpty either

Original comment by raymond....@gmail.com on 7 Jul 2011 at 4:56

GoogleCodeExporter commented 9 years ago
@raymond: Consider this example:

    if (!StringUtils.isBlank(str)) {

       stringBuffer.append(str.trim());
    }

Original comment by chris.lercher on 7 Jul 2011 at 5:31

GoogleCodeExporter commented 9 years ago
better like this :
stringBuffer.append(Strings.nullToEmpty(str).trim());

Original comment by amer...@gmail.com on 7 Jul 2011 at 6:54

GoogleCodeExporter commented 9 years ago
@lercherc 
And what if in that case str is something like "   ", and according to my 
business logic I should have processed is same as null or empty String? In this 
particular case with StringBuffer that will not make a difference, however if 
you want to pass it to for example DataFormat.parse() or Integer.parseInt(), 
then it does not work.

Original comment by elchin.a...@gmail.com on 7 Jul 2011 at 7:23

GoogleCodeExporter commented 9 years ago
@elchin: My example (using isBlank) works also in your case. The modified 
example by amer...@gmail.com (using nullToEmpty) will only work for some 
situations.

So let's make a better example:

if (!StringUtils.isBlank(str)) {

    stringBuffer.append("[not entered]");

} else {

    stringBuffer.append(str.trim());
}

Original comment by chris.lercher on 7 Jul 2011 at 7:34

GoogleCodeExporter commented 9 years ago
@lercherc 
I have a bit of a hard time trying to figure out your example, however I am 
going to show you mine, and I want to see if there is currently a way to do it:

try {
    if (StringUtils.isNullOrBlank(inputString)) {
        // do nothing, optional date field left empty
    } else {
        someBusinessObject.setSomeBusinessDate(someDateFormat.parse(inputString));
    }
} catch (ParseException e) {
    throw new IllegalArgumentException("Date given in wrong format");
}

Original comment by elchin.a...@gmail.com on 7 Jul 2011 at 7:43

GoogleCodeExporter commented 9 years ago
@elchin: Yes, that's basically a very similar example. It adds another valid 
use case.

Original comment by chris.lercher on 7 Jul 2011 at 7:46

GoogleCodeExporter commented 9 years ago
Usefulness of trailing spaces is very rare, again check the comment of kevinb 
http://code.google.com/p/guava-libraries/issues/detail?id=352#c25

If your if-statement does nothing why keeping it ?

Original comment by amer...@gmail.com on 7 Jul 2011 at 8:06

GoogleCodeExporter commented 9 years ago
Because otherwise (in case of blank String) someDateFormat.parse(inputString) 
will throw ParseException!

Original comment by elchin.a...@gmail.com on 7 Jul 2011 at 8:11

GoogleCodeExporter commented 9 years ago
I wonder if a wrapper method around `String.trim(String)` which would return 
Optional<String> if the input value is null or - after trimming - an empty 
string would be helpful here.

It could be used like this (based on the example in comment #39):

  stringBuilder.append(Strings.trim(input).or("[not entered]"));

Original comment by j...@nwsnet.de on 8 Jul 2011 at 9:11

GoogleCodeExporter commented 9 years ago
Addenda:

The method would of course return Optional<String> in any case, that'd be part 
of the signature.

Also, the definition of whitespace is the one used by `String.trim()` (though 
it is different from `StringUtils.isBlank()`, which uses 
`Characters.isWhitespace()`) and thus developers should be at least familiar 
with its behaviour.

Original comment by j...@nwsnet.de on 8 Jul 2011 at 9:30

GoogleCodeExporter commented 9 years ago
Issue 1760 has been merged into this issue.

Original comment by cgdecker@google.com on 21 May 2014 at 6:48

GoogleCodeExporter commented 9 years ago
Issue 1760 has been merged into this issue.

Original comment by cgdecker@google.com on 21 May 2014 at 6:48

GoogleCodeExporter commented 9 years ago
This issue has been migrated to GitHub.

It can be found at https://github.com/google/guava/issues/<id>

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:15

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 3 Nov 2014 at 9:10