Skip to content

Commit

Permalink
Parse and print CDS response when pushing source strings
Browse files Browse the repository at this point in the history
CDSHandler has been updated so that the CDS's response is parsed
to the corresponding LocaleData object. Affected classes and their unit
tests have been updated.

Improvements to test-only resources in txsdk

The unit tests of txsdk require some resources. At the same time,
we don't want these resources to exist when building the app or
the android library. As a workaround we set these resources
in the debug build variant. The downside is that the unit tests
that run in release mode fail, because these resources are not
accessible in this case.

The updated txsdk gradle configuration adds the required
resources only when running a test. The resources have been
moved from the debug to the test directory. Some unit tests in
the clitool module accessed these resourced by path and
have now been updated to point to the new location.

Improvements in transitive dependencies

"clitool" module depends on "common" module, which depends
on other libraries. In order to build a fat .jar that contains all needed
libraries, we had to re-declare "common's libraries in "clitool".
Now, this is not needed as we use the "runtimeClasspath" when
building the fat .jar.
  • Loading branch information
Petrakeas committed Feb 9, 2021
1 parent caa074a commit 12631d5
Show file tree
Hide file tree
Showing 12 changed files with 113 additions and 48 deletions.
11 changes: 4 additions & 7 deletions TransifexNativeSDK/clitool/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ jar {
)
}

archiveName("transifex.jar")
archivesBaseName = "transifex"

// Add dependencies in the final jar file to create a fat jar
// https://discuss.gradle.org/t/how-to-include-dependencies-in-jar/19571/18
from {
configurations.compileClasspath.filter{ it.exists() }.collect { it.isDirectory() ? it : zipTree(it) }
configurations.runtimeClasspath.filter{ it.exists() }.collect { it.isDirectory() ? it : zipTree(it) }
}
}

Expand All @@ -23,14 +23,14 @@ java {
targetCompatibility = JavaVersion.VERSION_1_8
}


// Read the source code using UTF-8
// https://gist.github.com/rponte/d660919434d094bbd35a1aabf7ef1bf0
compileJava.options.encoding = "UTF-8"
compileTestJava.options.encoding = "UTF-8"
javadoc.options.encoding = 'UTF-8'
// Use UTF-8 in the JVM that executes the test gradle tasks

tasks.withType(Test) {
// Use UTF-8 in the JVM that executes the test gradle tasks
systemProperty "file.encoding", "UTF-8"
}

Expand All @@ -39,9 +39,6 @@ dependencies {
implementation 'org.jdom:jdom:2.0.2'
implementation 'info.picocli:picocli:4.6.1'
implementation project(':common')
// Inherited dependencies from :common
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'net.moznion:uribuilder-tiny:2.7.1'

testImplementation 'junit:junit:4.13.1'
testImplementation 'com.google.truth:truth:1.1'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.logging.Logger;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import picocli.CommandLine;

import static picocli.CommandLine.ArgGroup;
Expand Down Expand Up @@ -131,10 +134,18 @@ public Integer call() throws Exception {
// Push to CDS
CDSHandler cdsHandler = new CDSHandler(null, mainClass.token,
mainClass.secret, mainClass.hostURL);
boolean success = cdsHandler.postSourceStrings(postData);
LocaleData.TxPostResponseData response = cdsHandler.pushSourceStrings(postData);

if (success) {
if (response != null) {
System.out.println("Source strings pushed successfully to CDS");

System.out.println(getDetailsString(response));

String errorString = getErrorString(response);
if (errorString != null) {
System.out.println(errorString);
}

return 0;
}
else {
Expand Down Expand Up @@ -162,10 +173,19 @@ public Integer call() throws Exception {
// Push to CDS
CDSHandler cdsHandler = new CDSHandler(null, mainClass.token,
mainClass.secret, mainClass.hostURL);
boolean success = cdsHandler.postSourceStrings(postData);
LocaleData.TxPostResponseData response = cdsHandler.pushSourceStrings(postData);

if (success) {
if (response != null) {
System.out.println("Source strings cleared from CDS");

String details = String.format(Locale.US, "%d strings deleted", response.deleted);
System.out.println(details);

String errorString = getErrorString(response);
if (errorString != null) {
System.out.println(errorString);
}

return 0;
}
else {
Expand All @@ -188,4 +208,33 @@ File getStringFileForModule(@NonNull File projectDirectory, @NonNull String modu
Path filePath = Paths.get(projectDirectory.getAbsolutePath(), moduleName, "src", "main", "res", "values", "strings.xml");
return filePath.toFile();
}

/**
* Utility method to get a human-readable string representation of the errors of a TxPostResponseData
* object.
*
* @return A string containing all the errors of the provided response object or
* <code>null</code> if the provided response object contains no errors.
*/
static @Nullable
String getErrorString(@NonNull LocaleData.TxPostResponseData response) {
if (response.errors.length == 0) {
return null;
}

return "Errors: " + Arrays.toString(response.errors);
}

/**
* Utility method to get a human-readable string representation of the information of a
* TxPostResponseData object.
*
* @return A string containing details about the provided response object.
*/
static @NonNull String getDetailsString(@NonNull LocaleData.TxPostResponseData response) {
return String.format(Locale.US, "%d strings created, %d strings updated, " +
"%d strings skipped, %d strings deleted, %d strings failed",
response.created, response.updated, response.skipped, response.deleted,
response.failed);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ private Dispatcher getPostDispatcher() {
@Override
public MockResponse dispatch (RecordedRequest request) throws InterruptedException {

String dummyCDSResponse = "{\"created\":0,\"updated\":0,\"skipped\":0,\"deleted\":0,\"failed\":0,\"errors\":[]}";

switch (request.getPath()) {
case "/content":
return new MockResponse().setResponseCode(200);
return new MockResponse().setResponseCode(200).setBody(dummyCDSResponse);
}
return new MockResponse().setResponseCode(404);
}
Expand Down Expand Up @@ -83,12 +85,12 @@ public void testPush_wrongModuleName() {
@Test
public void testPush_useFile() {
// This test relies on having the following file:
// txsdk/src/debug/res/values/strings.xml
// txsdk/src/test/res/values/strings.xml

server.setDispatcher(getPostDispatcher());

String args = String.format("-t token -s secret -u %s push -f %s", baseUrl,
"../txsdk/src/debug/res/values/strings.xml");
"../txsdk/src/test/res/values/strings.xml");
int returnValue = MainClass.testMain(args);

assertThat(returnValue).isEqualTo(0);
Expand All @@ -110,14 +112,14 @@ public void testPush_useFile() {
@Test
public void testPush_useMultipleFiles() {
// This test relies on having the following files:
// txsdk/src/debug/res/values/strings.xml
// txsdk/src/debug/res/values-el/strings.xml"
// txsdk/src/test/res/values/strings.xml
// txsdk/src/test/res/values-el/strings.xml"

server.setDispatcher(getPostDispatcher());

String args = String.format("-t token -s secret -u %s push -f %s -f %s", baseUrl,
"../txsdk/src/debug/res/values/strings.xml",
"../txsdk/src/debug/res/values-el/strings.xml");
"../txsdk/src/test/res/values/strings.xml",
"../txsdk/src/test/res/values-el/strings.xml");
int returnValue = MainClass.testMain(args);

assertThat(returnValue).isEqualTo(0);
Expand Down
1 change: 1 addition & 0 deletions TransifexNativeSDK/common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ java {
compileJava.options.encoding = "UTF-8"
compileTestJava.options.encoding = "UTF-8"
javadoc.options.encoding = 'UTF-8'

tasks.withType(Test) {
systemProperty "file.encoding", "UTF-8"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;


import net.moznion.uribuildertiny.URIBuilderTiny;

import java.io.BufferedReader;
Expand All @@ -19,7 +18,6 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand Down Expand Up @@ -56,10 +54,10 @@ public class CDSHandler {
* Class that contains the result of {@link #fetchLocale(URI, String)}.
*/
private static class FetchLocaleResult {
LocaleData.TxResponseData response;
LocaleData.TxPullResponseData response;
HttpURLConnection connection;

public FetchLocaleResult(LocaleData.TxResponseData response, HttpURLConnection connection) {
public FetchLocaleResult(LocaleData.TxPullResponseData response, HttpURLConnection connection) {
this.response = response;
this.connection = connection;
}
Expand Down Expand Up @@ -115,7 +113,7 @@ public LocaleData.TranslationMap fetchTranslations(@Nullable String localeCode)
HttpURLConnection lastConnection = null;
for (String fetchLocalCode : fetchLocalCodes) {
FetchLocaleResult results = fetchLocale(cdsContentURI, fetchLocalCode);
LocaleData.TxResponseData responseData = results.response;
LocaleData.TxPullResponseData responseData = results.response;
if (responseData!= null) {
translations.put(fetchLocalCode, new LocaleData.LocaleStrings(responseData.data));
}
Expand Down Expand Up @@ -170,10 +168,10 @@ FetchLocaleResult fetchLocale(URI cdsContentURI, String localeCode) {
int code = connection.getResponseCode();
switch (code) {
case 200: {
LocaleData.TxResponseData responseData = null;
LocaleData.TxPullResponseData responseData = null;
Reader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
try {
responseData = mGson.fromJson(reader, LocaleData.TxResponseData.class);
responseData = mGson.fromJson(reader, LocaleData.TxPullResponseData.class);
} catch (JsonSyntaxException e) {
LOGGER.log(Level.SEVERE, "Could not parse JSON response to object for locale " + localeCode);
}
Expand Down Expand Up @@ -214,9 +212,11 @@ FetchLocaleResult fetchLocale(URI cdsContentURI, String localeCode) {
*
* @param postData The data containing the source strings and the purge value.
*
* @return <code>true</code> if data were pushed successfully, <code>false</code> otherwise.
* @return a {@link LocaleData.TxPostResponseData} object if data were pushed successfully,
* <code>null</code> otherwise.
*/
public boolean postSourceStrings(@NonNull LocaleData.TxPostData postData) {
public @Nullable
LocaleData.TxPostResponseData pushSourceStrings(@NonNull LocaleData.TxPostData postData) {
// Check URL
URL url = null;
try {
Expand All @@ -225,7 +225,7 @@ public boolean postSourceStrings(@NonNull LocaleData.TxPostData postData) {
url = new URL(cdsContentURI.toString());
} catch (MalformedURLException | URISyntaxException e) {
LOGGER.log(Level.SEVERE, "Invalid CDS host URL: " + mCdsHost);
return false;
return null;
}

// Post data
Expand All @@ -234,7 +234,7 @@ public boolean postSourceStrings(@NonNull LocaleData.TxPostData postData) {
connection = (HttpURLConnection) url.openConnection();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "IOException when opening connection: " + e);
return false;
return null;
}

addHeaders(connection, true, null);
Expand All @@ -252,15 +252,13 @@ public boolean postSourceStrings(@NonNull LocaleData.TxPostData postData) {
case 200: {
String result = Utils.readInputStream(connection.getInputStream());
connection.getInputStream().close();
LocaleData.TxPostResponseData responseData = mGson.fromJson(result, LocaleData.TxPostResponseData.class);

//TODO: (optional) parse the JSON response and return it as an object
// https://github.com/transifex/transifex-delivery/#push-content

return true;
return responseData;
}
default:
LOGGER.log(Level.SEVERE, "Server responded with code " + code);
return false;
return null;
}
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "IOException: " + e);
Expand All @@ -272,7 +270,7 @@ public boolean postSourceStrings(@NonNull LocaleData.TxPostData postData) {
} catch (IOException ignored) {
}

return false;
return null;
} finally {
connection.disconnect();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public String toString() {
* @see <a href="https://github.com/transifex/transifex-delivery/#pull-content">
* https://github.com/transifex/transifex-delivery/#pull-content</a>
*/
public static class TxResponseData {
public static class TxPullResponseData {

public HashMap<String, StringInfo> data;

Expand All @@ -67,11 +67,11 @@ public String toString() {
/**
* The data structure the CDS accepts when pushing the source strings.
*
* @see TxResponseData
* @see TxPullResponseData
* @see <a href="https://github.com/transifex/transifex-delivery/#push-content">
* https://github.com/transifex/transifex-delivery/#push-content</a>
*/
public static class TxPostData extends TxResponseData {
public static class TxPostData extends TxPullResponseData {

public static class Meta {
public Boolean purge;
Expand All @@ -97,6 +97,21 @@ public String toString() {
}
}

/**
* The data structure that CDS responds with when pushing the source strings.
*
* @see <a href="https://github.com/transifex/transifex-delivery/#push-content">
* https://github.com/transifex/transifex-delivery/#push-content</a>
*/
public static class TxPostResponseData {
public int created;
public int updated;
public int skipped;
public int deleted;
public int failed;
public String[] errors;
}

/**
* A class holding key-value pairs for some locale's strings.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,16 @@
import java.io.InputStream;
import java.io.InputStreamReader;

import androidx.annotation.NonNull;

public class Utils {

/**
* Reads an input stream to a string.
* <p>
* The caller should close the input stream.
*/
public static String readInputStream(InputStream inputStream) throws IOException {
if (inputStream == null) {
return null;
}

public @NonNull static String readInputStream(@NonNull InputStream inputStream) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
StringBuilder result = new StringBuilder();
String line;
Expand Down
Loading

0 comments on commit 12631d5

Please sign in to comment.