diff --git a/WordPressUtils/build.gradle b/WordPressUtils/build.gradle index 5ac4e6ec1d99..06e48011763c 100644 --- a/WordPressUtils/build.gradle +++ b/WordPressUtils/build.gradle @@ -20,8 +20,7 @@ dependencies { exclude group: 'commons-logging' } compile 'com.mcxiaoke.volley:library:1.0.18' - compile 'com.android.support:support-v13:23.0.0' - compile 'com.android.support:design:23.0.0' + compile 'com.android.support:support-v13:23.0.1' } android { @@ -30,7 +29,7 @@ android { publishNonDefault true compileSdkVersion 23 - buildToolsVersion '23.0.0' + buildToolsVersion '23.0.1' defaultConfig { versionName "1.5.0" diff --git a/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java b/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java new file mode 100644 index 000000000000..f7c747ff7024 --- /dev/null +++ b/WordPressUtils/src/androidTest/java/org/wordpress/android/util/JSONUtilsTest.java @@ -0,0 +1,32 @@ +package org.wordpress.android.util; + +import android.test.InstrumentationTestCase; + +import org.json.JSONArray; +import org.json.JSONObject; + +public class JSONUtilsTest extends InstrumentationTestCase { + public void testQueryJSONNullSource1() { + JSONUtils.queryJSON((JSONObject) null, "", ""); + } + + public void testQueryJSONNullSource2() { + JSONUtils.queryJSON((JSONArray) null, "", ""); + } + + public void testQueryJSONNullQuery1() { + JSONUtils.queryJSON(new JSONObject(), null, ""); + } + + public void testQueryJSONNullQuery2() { + JSONUtils.queryJSON(new JSONArray(), null, ""); + } + + public void testQueryJSONNullReturnValue1() { + JSONUtils.queryJSON(new JSONObject(), "", null); + } + + public void testQueryJSONNullReturnValue2() { + JSONUtils.queryJSON(new JSONArray(), "", null); + } +} diff --git a/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java b/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java index 7b0bb6beeca7..b72e94821203 100644 --- a/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java +++ b/WordPressUtils/src/androidTest/java/org/wordpress/android/util/UrlUtilsTest.java @@ -2,6 +2,9 @@ import android.test.InstrumentationTestCase; +import java.util.HashMap; +import java.util.Map; + public class UrlUtilsTest extends InstrumentationTestCase { public void testGetDomainFromUrlWithEmptyStringDoesNotReturnNull() { assertNotNull(UrlUtils.getDomainFromUrl("")); @@ -17,4 +20,59 @@ public void testGetDomainFromUrlWithHostReturnsHost() { assertTrue(host.equals("www.wordpress.com")); } + + public void testAppendUrlParameter1() { + String url = UrlUtils.appendUrlParameter("http://wp.com/test", "preview", "true"); + assertEquals("http://wp.com/test?preview=true", url); + } + + public void testAppendUrlParameter2() { + String url = UrlUtils.appendUrlParameter("http://wp.com/test?q=pony", "preview", "true"); + assertEquals("http://wp.com/test?q=pony&preview=true", url); + } + + public void testAppendUrlParameter3() { + String url = UrlUtils.appendUrlParameter("http://wp.com/test?q=pony#unicorn", "preview", "true"); + assertEquals("http://wp.com/test?q=pony&preview=true#unicorn", url); + } + + public void testAppendUrlParameter4() { + String url = UrlUtils.appendUrlParameter("/relative/test", "preview", "true"); + assertEquals("/relative/test?preview=true", url); + } + + public void testAppendUrlParameter5() { + String url = UrlUtils.appendUrlParameter("/relative/", "preview", "true"); + assertEquals("/relative/?preview=true", url); + } + + public void testAppendUrlParameter6() { + String url = UrlUtils.appendUrlParameter("http://wp.com/test/", "preview", "true"); + assertEquals("http://wp.com/test/?preview=true", url); + } + + public void testAppendUrlParameter7() { + String url = UrlUtils.appendUrlParameter("http://wp.com/test/?q=pony", "preview", "true"); + assertEquals("http://wp.com/test/?q=pony&preview=true", url); + } + + public void testAppendUrlParameters1() { + Map params = new HashMap<>(); + params.put("w", "200"); + params.put("h", "300"); + String url = UrlUtils.appendUrlParameters("http://wp.com/test", params); + if (!url.equals("http://wp.com/test?h=300&w=200") && !url.equals("http://wp.com/test?w=200&h=300")) { + assertTrue("failed test on url: " + url, false); + } + } + + public void testAppendUrlParameters2() { + Map params = new HashMap<>(); + params.put("h", "300"); + params.put("w", "200"); + String url = UrlUtils.appendUrlParameters("/relative/test", params); + if (!url.equals("/relative/test?h=300&w=200") && !url.equals("/relative/test?w=200&h=300")) { + assertTrue("failed test on url: " + url, false); + } + } } diff --git a/WordPressUtils/src/main/java/org/wordpress/android/util/BlogUtils.java b/WordPressUtils/src/main/java/org/wordpress/android/util/BlogUtils.java index 0e07040a97c6..685aabf9ec53 100644 --- a/WordPressUtils/src/main/java/org/wordpress/android/util/BlogUtils.java +++ b/WordPressUtils/src/main/java/org/wordpress/android/util/BlogUtils.java @@ -8,19 +8,19 @@ public class BlogUtils { public int compare(Object blog1, Object blog2) { Map blogMap1 = (Map) blog1; Map blogMap2 = (Map) blog2; - String blogName1 = getBlogNameOrHostNameFromAccountMap(blogMap1); - String blogName2 = getBlogNameOrHostNameFromAccountMap(blogMap2); + String blogName1 = getBlogNameOrHomeURLFromAccountMap(blogMap1); + String blogName2 = getBlogNameOrHomeURLFromAccountMap(blogMap2); return blogName1.compareToIgnoreCase(blogName2); } }; /** - * Return a blog name or blog url (host part only) if trimmed name is an empty string + * Return a blog name or blog home URL if trimmed name is an empty string */ - public static String getBlogNameOrHostNameFromAccountMap(Map account) { + public static String getBlogNameOrHomeURLFromAccountMap(Map account) { String blogName = getBlogNameFromAccountMap(account); if (blogName.trim().length() == 0) { - blogName = StringUtils.getHost(MapUtils.getMapStr(account, "url")); + blogName = BlogUtils.getHomeURLOrHostNameFromAccountMap(account); } return blogName; } @@ -33,9 +33,16 @@ public static String getBlogNameFromAccountMap(Map account) { } /** - * Return blog url (host part only) if trimmed name is an empty string + * Return the blog home URL setting or the host name if home URL is an empty string. */ - public static String getHostNameFromAccountMap(Map account) { - return StringUtils.getHost(MapUtils.getMapStr(account, "url")); + public static String getHomeURLOrHostNameFromAccountMap(Map account) { + String homeURL = UrlUtils.removeScheme(MapUtils.getMapStr(account, "homeURL")); + homeURL = StringUtils.removeTrailingSlash(homeURL); + + if (homeURL.length() == 0) { + return StringUtils.getHost(MapUtils.getMapStr(account, "url")); + } + + return homeURL; } } diff --git a/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java b/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java index 4c92478cb4d7..8738acd24384 100644 --- a/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java +++ b/WordPressUtils/src/main/java/org/wordpress/android/util/JSONUtils.java @@ -8,23 +8,30 @@ import org.wordpress.android.util.AppLog.T; import java.util.ArrayList; -import java.util.Iterator; public class JSONUtils { - private static String QUERY_SEPERATOR="."; - private static String QUERY_ARRAY_INDEX_START="["; - private static String QUERY_ARRAY_INDEX_END="]"; - private static String QUERY_ARRAY_FIRST="first"; - private static String QUERY_ARRAY_LAST="last"; + private static String QUERY_SEPERATOR = "."; + private static String QUERY_ARRAY_INDEX_START = "["; + private static String QUERY_ARRAY_INDEX_END = "]"; + private static String QUERY_ARRAY_FIRST = "first"; + private static String QUERY_ARRAY_LAST = "last"; private static final String JSON_NULL_STR = "null"; + private static final String TAG = "JSONUtils"; - private static final String TAG="JSONUtils"; /** * Given a JSONObject and a key path (e.g property.child) and a default it will * traverse the object graph and pull out the desired property */ public static U queryJSON(JSONObject source, String query, U defaultObject) { + if (source == null) { + AppLog.e(T.UTILS, "Parameter source is null, can't query a null object"); + return defaultObject; + } + if (query == null) { + AppLog.e(T.UTILS, "Parameter query is null"); + return defaultObject; + } int nextSeperator = query.indexOf(QUERY_SEPERATOR); int nextIndexStart = query.indexOf(QUERY_ARRAY_INDEX_START); if (nextSeperator == -1 && nextIndexStart == -1) { @@ -56,9 +63,6 @@ public static U queryJSON(JSONObject source, String query, U defaultObject) String nextQuery = query.substring(endQuery); String key = query.substring(0, endQuery); try { - if (source == null) { - return defaultObject; - } if (nextQuery.indexOf(QUERY_SEPERATOR) == 0) { return queryJSON(source.getJSONObject(key), nextQuery.substring(1), defaultObject); } else if (nextQuery.indexOf(QUERY_ARRAY_INDEX_START) == 0) { @@ -89,7 +93,15 @@ public static U queryJSON(JSONObject source, String query, U defaultObject) * Acceptable indexes include negative numbers to reference items from the end of * the list as well as "last" and "first" as more explicit references to "0" and "-1" */ - public static U queryJSON(JSONArray source, String query, U defaultObject){ + public static U queryJSON(JSONArray source, String query, U defaultObject) { + if (source == null) { + AppLog.e(T.UTILS, "Parameter source is null, can't query a null object"); + return defaultObject; + } + if (query == null) { + AppLog.e(T.UTILS, "Parameter query is null"); + return defaultObject; + } // query must start with [ have an index and then have ] int indexStart = query.indexOf(QUERY_ARRAY_INDEX_START); int indexEnd = query.indexOf(QUERY_ARRAY_INDEX_END); diff --git a/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java b/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java index 991c7680b478..4660a3500b25 100644 --- a/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java +++ b/WordPressUtils/src/main/java/org/wordpress/android/util/ProfilingUtils.java @@ -28,6 +28,10 @@ public static void dump() { getInstance().dumpToLog(); } + public static void stop() { + getInstance().reset(null); + } + private static ProfilingUtils getInstance() { if (sInstance == null) { sInstance = new ProfilingUtils(); @@ -56,12 +60,18 @@ public void reset() { } public void addSplit(String splitLabel) { + if (mLabel == null) { + return; + } long now = SystemClock.elapsedRealtime(); mSplits.add(now); mSplitLabels.add(splitLabel); } public void dumpToLog() { + if (mLabel == null) { + return; + } AppLog.d(T.PROFILING, mLabel + ": begin"); final long first = mSplits.get(0); long now = first; diff --git a/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java b/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java index 68e3113c3d5d..136cc4e541a4 100644 --- a/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java +++ b/WordPressUtils/src/main/java/org/wordpress/android/util/StringUtils.java @@ -180,6 +180,14 @@ public static String capitalize(final String str) { return new StringBuilder(strLen).append(Character.toTitleCase(firstChar)).append(str.substring(1)).toString(); } + public static String removeTrailingSlash(final String str) { + if (TextUtils.isEmpty(str) || !str.endsWith("/")) { + return str; + } + + return str.substring(0, str.length() -1); + } + /* * Wrap an image URL in a photon URL * Check out http://developer.wordpress.com/docs/photon/ diff --git a/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java b/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java index 7ac4dbaf089d..f4b5756d25ee 100644 --- a/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java +++ b/WordPressUtils/src/main/java/org/wordpress/android/util/UrlUtils.java @@ -10,10 +10,11 @@ import java.io.UnsupportedEncodingException; import java.net.IDN; import java.net.URI; -import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; public class UrlUtils { public static String urlEncode(final String text) { @@ -137,6 +138,25 @@ public static String normalizeUrl(final String urlString) { } } + + /** + * returns the passed url without the scheme + */ + public static String removeScheme(final String urlString) { + if (urlString == null) { + return null; + } + + int doubleslash = urlString.indexOf("//"); + if (doubleslash == -1) { + doubleslash = 0; + } else { + doubleslash += 2; + } + + return urlString.substring(doubleslash, urlString.length()); + } + /** * returns the passed url without the query parameters */ @@ -144,11 +164,7 @@ public static String removeQuery(final String urlString) { if (urlString == null) { return null; } - int pos = urlString.indexOf("?"); - if (pos == -1) { - return urlString; - } - return urlString.substring(0, pos); + return Uri.parse(urlString).buildUpon().clearQuery().toString(); } /** @@ -214,4 +230,18 @@ public static boolean isImageUrl(String url) { return cleanedUrl.endsWith("jpg") || cleanedUrl.endsWith("jpeg") || cleanedUrl.endsWith("gif") || cleanedUrl.endsWith("png"); } + + public static String appendUrlParameter(String url, String paramName, String paramValue) { + Map parameters = new HashMap<>(); + parameters.put(paramName, paramValue); + return appendUrlParameters(url, parameters); + } + + public static String appendUrlParameters(String url, Map parameters) { + Uri.Builder uriBuilder = Uri.parse(url).buildUpon(); + for (Map.Entry parameter : parameters.entrySet()) { + uriBuilder.appendQueryParameter(parameter.getKey(), parameter.getValue()); + } + return uriBuilder.build().toString(); + } }