2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.common
;
11 import java
.io
.BufferedReader
;
12 import java
.io
.IOException
;
13 import java
.io
.InputStream
;
14 import java
.io
.InputStreamReader
;
15 import java
.lang
.annotation
.Annotation
;
16 import java
.lang
.reflect
.Field
;
17 import java
.lang
.reflect
.Modifier
;
18 import java
.net
.HttpURLConnection
;
19 import java
.net
.MalformedURLException
;
21 import java
.util
.ArrayList
;
22 import java
.util
.HashMap
;
23 import java
.util
.List
;
25 import java
.util
.regex
.Matcher
;
26 import java
.util
.regex
.Pattern
;
28 import org
.apache
.commons
.lang3
.StringUtils
;
29 import org
.apache
.log4j
.Logger
;
33 * @author a.kohlbecker
35 public class CdmUtils
{
37 private static final Logger logger
= Logger
.getLogger(CdmUtils
.class);
39 static private boolean urlIsJarOrBundle(URL url
){
40 return url
.getProtocol().startsWith("jar") || url
.getProtocol().startsWith("bundleresource");
44 * Returns the an InputStream for a read-only source
45 * @param resourceFileName the resources path within the classpath(!)
49 public static InputStream
getReadableResourceStream(String resourceFileName
)
51 InputStream urlStream
= CdmUtils
.class.getResourceAsStream("/"+ resourceFileName
);
56 * Returns an InputStream for a read-only source
57 * @param resourceFileName the resources path within the classpath(!)
61 public static InputStreamReader
getUtf8ResourceReader(String resourceFileName
)
63 InputStream urlStream
= CdmUtils
.class.getResourceAsStream("/"+ resourceFileName
);
64 InputStreamReader inputStreamReader
= new InputStreamReader(urlStream
, "UTF8");
65 return inputStreamReader
;
69 * Returns the file name for the file in which 'clazz' is to be found (helps finding according libraries)
73 static public String
findLibrary(Class
<?
> clazz
){
76 String fullPackageName
= clazz
.getCanonicalName();
77 fullPackageName
= fullPackageName
.replace(".", "/");
78 URL url
= CdmUtils
.class.getResource("/" + fullPackageName
+ ".class" );
80 result
= url
.getFile();
84 logger
.debug("LibraryURL for " + clazz
.getCanonicalName() + " : " + result
);
89 static public String
readInputLine(String inputQuestion
){
92 System
.out
.print(inputQuestion
);
93 BufferedReader in
= new BufferedReader( new InputStreamReader( System
.in
));
95 input
= in
.readLine();
97 } catch (IOException e
) {
98 logger
.warn("IOExeption");
104 * Returns the trimmed value string if value is not <code>null</code>.
105 * Returns the empty string if value is <code>null</code>.
109 static public String
NzTrim(String value
){
110 return (value
== null ?
"" : value
);
114 * Returns value if value is not <code>null</code>. Returns empty string if value is <code>null</code>.
118 static public String
Nz(String value
){
119 return (value
== null ?
"" : value
);
123 * Returns value if value is not <code>null</code>. Returns defaultValue if value is <code>null</code>.
127 static public String
Nz(String value
, String defaultValue
){
128 return (value
== null ? defaultValue
: value
);
132 * Returns value if value is not <code>null</code>. Returns 0 if value is <code>null</code>.
136 static public Integer
Nz(Integer value
){
137 return (value
== null ?
0 : value
);
141 * Returns value if value is not <code>null</code>. Returns 0 if value is <code>null</code>.
145 static public Long
Nz(Long value
){
146 return (value
== null ?
0 : value
);
150 * Returns str if str is not the empty String (''). Returns null if str is empty.
154 static public String
Ne(String str
){
155 return ("".equals(str
)?
null : str
);
159 * Returns str if str.trim() is not empty. Returns null otherwise.
163 static public String
Nb(String str
){
164 return (str
== null || str
.trim().equals("")?
null : str
);
168 * Concatenates an array of strings using the defined separator.<BR>
169 * <code>Null</code> values and empty strings are handled as if they
170 * do not exist. So <BR><BR>
172 * concat(":", "a", "", null, "b") results in "a:b"<BR><BR>
174 * If all strings are <code>null</code> then <code>null</code> is returned.
176 * @see #concat(CharSequence, String, String)
177 * @param strings the strings to concatenate
178 * @param seperator the separator for concatenation
179 * @return String the concatenation result
181 static public String
concat(CharSequence separator
, String
... strings
){
182 StringBuilder result
= new StringBuilder();
183 boolean allNull
= true;
184 for (String string
: strings
){
186 if (result
.length() > 0 && string
.length() > 0){
187 result
.append(separator
);
189 result
.append(string
);
193 //if all strings are null result should be null, not ""
197 return result
.toString();
203 * Concatenates two strings, using the defined separator.<BR>
204 * <code>Null</code> values are interpreted as empty strings.<BR>
205 * Empty strings are not included in concatenation so concat(":", "a", "")
206 * results in "a", not "a:".<BR>
208 * If both strings are <code>null</code> then <code>null</code> is returned.
210 * @see #concat(CharSequence, String[])
211 * @param sepearator the separator
212 * @param string1 first string to concatenate
213 * @param string2 second string to concatenate
214 * @return String the concatenated string
216 static public String
concat(CharSequence separator
, String string1
, String string2
){
217 String
[] strings
= {string1
, string2
};
218 return concat(separator
, strings
);
222 * Returns <code>preferred</code> if not blank, else returns <code>alternative</code>.
223 * If reverse is <code>true</code> computation is
224 * the other way round (<code>alternative</code> if not blank, otherwise <code>preferred</code>).
225 * @param preferred first string
226 * @param alternative second string
227 * @param reverse reverse flag
228 * @param nzTrim if <code>true</code> the result is trimmed and <code>null</code> values are replaced by empty string.
229 * @return the preferred string
231 static public String
getPreferredNonEmptyString(String preferred
, String alternative
, boolean reverse
, boolean nzTrim
){
234 result
= StringUtils
.isBlank(preferred
) ? alternative
: preferred
;
236 result
= StringUtils
.isBlank(alternative
) ? preferred
: alternative
;
239 result
= Nz(result
).trim();
244 /** Returns a version of the input where all contiguous
245 * whitespace characters are replaced with a single
246 * space. Line terminators are treated like whitespace.
251 public static CharSequence
removeDuplicateWhitespace(CharSequence inputStr
) {
253 String patternStr
= "\\s+";
254 String replaceStr
= " ";
255 Pattern pattern
= Pattern
.compile(patternStr
);
256 Matcher matcher
= pattern
.matcher(inputStr
);
257 return matcher
.replaceAll(replaceStr
);
261 * Builds a list of strings by splitting an input string
262 * with delimiters whitespace, comma, or semicolon
266 public static List
<String
> buildList(String value
) {
268 List
<String
> resultList
= new ArrayList
<String
>();
269 for (String tag
: value
.split("[\\s,;]+")) {
275 static public boolean urlExists(String strUrl
, boolean withWarning
){
277 HttpURLConnection
.setFollowRedirects(false);
278 // note : you may also need
279 // HttpURLConnection.setInstanceFollowRedirects(false)
280 HttpURLConnection con
=
281 (HttpURLConnection
) new URL(strUrl
).openConnection();
282 con
.setRequestMethod("HEAD");
283 return (con
.getResponseCode() == HttpURLConnection
.HTTP_OK
);
284 } catch (MalformedURLException e
) {
288 } catch (IOException e
) {
294 static public boolean isNumeric(String string
){
299 Double
.valueOf(string
);
301 } catch (NumberFormatException e
) {
307 * Returns <code>true</code> if the passed string starts with an upper case letter.
308 * <code>false</code> otherwise. The later includes <code>null</code> and empty strings.
312 static public boolean isCapital(String string
){
313 if (isBlank(string
)){
316 Character firstChar
= string
.charAt(0);
317 if (firstChar
.equals(Character
.toUpperCase(firstChar
))){
326 * Returns true if string is null, "" or string.trim() is ""
327 * @see isNotEmpty(String string)
331 static public boolean isBlank(String string
){
335 if ("".equals(string
.trim())){
342 * Returns <code>false</code> if string is null, "" or string.trim() is ""
343 * @see isNotEmpty(String string)
347 static public boolean isNotBlank(String string
){
348 return ! isBlank(string
);
352 * @see #isBlank(String)
353 * @deprecated use {@link #isBlank(String)} instead
358 static public boolean isEmpty(String string
){
359 return isBlank(string
);
362 static public boolean areBlank(String
... strings
){
363 for (String string
: strings
){
364 if (! isBlank(string
)){
372 * Tests if two objects are equal or both null. Otherwise returns false
377 public static boolean nullSafeEqual(Object obj1
, Object obj2
) {
381 return (obj1
.equals(obj2
));
385 * Compares 2 instances of {@link Comparable} with defined values for <code>null</code>
387 public static <T
extends Comparable
<T
>> int nullSafeCompareTo(T c1
, T c2
) {
389 return c2
== null ?
0 : -1;
390 }else if (c2
== null){
393 return (c1
.compareTo(c2
));
398 * Computes all fields recursively
402 public static Map
<String
, Field
> getAllFields(Class clazz
, Class highestClass
, boolean includeStatic
, boolean includeTransient
, boolean makeAccessible
, boolean includeHighestClass
) {
403 Map
<String
, Field
> result
= new HashMap
<>();
404 if ( highestClass
.isAssignableFrom(clazz
) && (clazz
!= highestClass
|| includeHighestClass
)){
406 for (Field field
: clazz
.getDeclaredFields()){
407 if (includeStatic
|| ! Modifier
.isStatic(field
.getModifiers())){
408 if (includeTransient
|| ! isTransient(field
)){
409 field
.setAccessible(makeAccessible
);
410 result
.put(field
.getName(), field
);
415 //include superclass fields
416 Class
<?
> superclass
= clazz
.getSuperclass();
417 if (superclass
!= null){
418 result
.putAll(getAllFields(superclass
, highestClass
, includeStatic
, includeTransient
, makeAccessible
, includeHighestClass
));
425 * Returns true, if field has an annotation of type javax.persistence.Annotation
429 protected static boolean isTransient(Field field
) {
430 for (Annotation annotation
: field
.getAnnotations()){
431 //if (Transient.class.isAssignableFrom(annotation.annotationType())){
432 if (annotation
.annotationType().getSimpleName().equals("Transient")){
440 * Trims the string and if the string ends with 1 or more dots removes it.
442 public static String
removeTrailingDots(String string
){
443 while (string
!= null && string
.trim().endsWith(".")){
444 return string
.substring(0, string
.length() -1);
450 * Adds a trailing dot to the given String
451 * if string is not blank and does not end with dot already.
452 * Otherwise str is returned.
454 public static String
addTrailingDotIfNotExists(String str
){
455 if (StringUtils
.isNotBlank(str
) && !str
.endsWith(".")){
462 * Returns surrounding brackets "(",")". Trim the string if necessary.
466 public static String
removeBrackets(String text
) {
471 if (text
.matches("^\\(.*\\)$")){
472 text
= text
.substring(1, text
.length() -1);
478 * Compares 2 strings. If they are not empty and equal returns <code>true</code>
483 * @return compare result as boolean
485 public static boolean nonEmptyEquals(String str1
, String str2
) {
486 return (isNotBlank(str1
) && str1
.equals(str2
));
490 * Compares if str1 and str2 is equal when ignoring whitespaces.
491 * Returns <code>true</code> if both or <code>null</code> or
492 * whitespace ignore equal.
497 public static boolean equalsIgnoreWS(String str1
, String str2
) {
500 }else if (str2
== null){
503 return str1
.replaceAll("\\s", "").equals(str2
.replaceAll("\\s", ""));
508 * Checks if all strings given provide are {@link #isBlank(String) blank}.
509 * Returns <code>true</code> if strs is null or empty
513 public static boolean isBlank(String
... strs
) {
517 for (String str
: strs
) {
518 if (isNotBlank(str
)){
526 * Transforms a search string which allows wildcard "*" into a
527 * java regular expression such that all other characters are handled as normal text.
531 public static String
quoteRegExWithWildcard(String regEx
){
532 return Pattern
.quote(regEx
).replace("*", "\\E.*\\Q").replace("\\Q\\E", "");
535 public static int diffIndex(String str1
, String str2
) {
536 if (str1
== null || str2
== null){
539 for (int i
= 0; i
<str1
.length() && i
<str2
.length() ;i
++) {
540 if (str1
.charAt(i
)!= str2
.charAt(i
)){
544 if(str1
.length()!=str2
.length()){
545 return Math
.max(str1
.length(), str2
.length());
550 public static String
userFriendlyCamelCase(String camelCase
){
551 return String
.join(" ", StringUtils
.splitByCharacterTypeCamelCase(camelCase
));
554 public static String
userFriendlyClassName(Class
<?
> clazz
){
555 return userFriendlyCamelCase(clazz
.getSimpleName());