Skip to content

Commit

Permalink
feat: add bundle command support into cli (#549)
Browse files Browse the repository at this point in the history
  • Loading branch information
yzerk authored Apr 21, 2023
1 parent ec52558 commit 67d059c
Show file tree
Hide file tree
Showing 35 changed files with 1,060 additions and 23 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ dependencies {
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'

implementation 'com.github.crowdin:crowdin-api-client-java:1.4.2'
implementation 'com.github.crowdin:crowdin-api-client-java:1.6.2'

testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
testImplementation 'org.hamcrest:hamcrest:2.2'
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/com/crowdin/cli/client/ClientBundle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.crowdin.cli.client;

import com.crowdin.client.bundles.model.Bundle;
import com.crowdin.client.bundles.model.BundleExport;
import com.crowdin.client.tasks.model.Status;
import com.crowdin.client.translationmemory.model.TranslationMemoryExportRequest;
import com.crowdin.client.translationmemory.model.TranslationMemoryExportStatus;

import java.net.URL;
import java.util.List;
import java.util.Optional;

public interface ClientBundle extends Client {

List<Bundle> listBundle();

Bundle addBundle(Bundle request);

Optional<Bundle> getBundle(Long id);

URL downloadBundle(Long id, String exportId);

BundleExport startExportingBundle(Long id, Bundle bundle);

BundleExport checkExportingBundle(Long tmId, String exportId);

}
5 changes: 5 additions & 0 deletions src/main/java/com/crowdin/cli/client/Clients.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ public static ClientTask getClientTask(String apiToken, String baseUrl, String p
return new CrowdinClientTask(client, projectId);
}

public static ClientBundle getClientBundle(String apiToken, String baseUrl, String projectId) {
com.crowdin.client.Client client = prepareClient(apiToken, baseUrl);
return new CrowdinClientBundle(client, projectId);
}

// mb divide args to move token and url to constructor?
public static ProjectClient getProjectClient(String apiToken, String baseUrl, long projectId) {
com.crowdin.client.Client client = prepareClient(apiToken, baseUrl);
Expand Down
66 changes: 66 additions & 0 deletions src/main/java/com/crowdin/cli/client/CrowdinClientBundle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.crowdin.cli.client;


import com.crowdin.client.bundles.model.Bundle;
import com.crowdin.client.bundles.model.BundleExport;
import com.crowdin.client.glossaries.model.Glossary;

import java.net.URL;
import java.util.List;
import java.util.Optional;

public class CrowdinClientBundle extends CrowdinClientCore implements ClientBundle {

private final com.crowdin.client.Client client;
private final String projectId;

public CrowdinClientBundle(com.crowdin.client.Client client, String projectId) {
this.client = client;
this.projectId = projectId;
}

public List<Bundle> listBundle() {
return executeRequestFullList((limit, offset) -> this.client.getBundlesApi()
.listBundles(Long.valueOf(projectId)));
}

@Override
public Bundle addBundle(Bundle bundleRequest) {
return executeRequest(() -> this.client.getBundlesApi()
.addBundle(Long.valueOf(projectId), bundleRequest)
.getData());
}

@Override
public Optional<Bundle> getBundle(Long bundleId) {
try {
return Optional.of(executeRequest(() -> this.client.getBundlesApi()
.getBundle(Long.valueOf(projectId), bundleId))
.getData());
} catch (Exception e) {
return Optional.empty();
}
}

@Override
public URL downloadBundle(Long id, String exportId) {
return url(executeRequest(() -> this.client.getBundlesApi()
.downloadBundle(Long.valueOf(projectId), id, exportId)
.getData()));
}

@Override
public BundleExport startExportingBundle(Long id, Bundle bundle) {
return executeRequest(() -> this.client.getBundlesApi()
.exportBundle(Long.valueOf(projectId), id, bundle)
.getData());
}

@Override
public BundleExport checkExportingBundle(Long id, String exportId) {
return executeRequest(() -> this.client.getBundlesApi()
.checkBundleExportStatus(Long.valueOf(projectId), id, exportId)
.getData());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public URL downloadGlossary(Long glossaryId, String exportId) {
@Override
public List<Term> listTerms(Long glossaryId) {
return executeRequestFullList((limit, offset) -> this.client.getGlossariesApi()
.listTerms(glossaryId, null, null, null, limit, offset));
.listTerms(glossaryId, null, null, null, null, limit, offset));
}

@Override
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/crowdin/cli/commands/Actions.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ NewAction<BaseProperties, ClientTm> tmDownload(

NewAction<ProjectProperties, ClientTask> taskAdd(String title, Integer type, String language, List<Long> fileId, Long workflowStep, String description, boolean skipAssignedStrings, boolean skipUntranslatedStrings, List<Long> labels);

NewAction<ProjectProperties, ClientBundle> bundleList(boolean plainView, boolean isVerbose);

NewAction<ProjectProperties, ClientBundle> bundleAdd(String name, String format, List<String> source, List<String> ignore, String translation, List<Long> labels, boolean plainView);

NewAction<PropertiesWithTargets, ProjectClient> downloadTargets(
List<String> targetNames, FilesInterface files, boolean noProgress,
List<String> langIds, boolean isVerbose, boolean plainView, boolean debug, String branchName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.crowdin.cli.commands.actions;

import com.crowdin.cli.client.ClientBundle;
import com.crowdin.cli.commands.NewAction;
import com.crowdin.cli.commands.Outputter;
import com.crowdin.cli.properties.ProjectProperties;
import com.crowdin.client.bundles.model.Bundle;
import lombok.AllArgsConstructor;

import java.util.List;
import java.util.Optional;

import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE;
import static com.crowdin.cli.utils.console.ExecutionStatus.OK;

@AllArgsConstructor
class BundleAddAction implements NewAction<ProjectProperties, ClientBundle> {

private String name;

private String format;

private List<String> source;

private List<String> ignore;

private String translation;

private List<Long> labels;

private boolean plainView;

@Override
public void act(Outputter out, ProjectProperties pb, ClientBundle client) {
Bundle bundle;
Bundle addBundleRequest = new Bundle();
Optional.ofNullable(name).ifPresent(addBundleRequest::setName);
Optional.ofNullable(format).ifPresent(addBundleRequest::setFormat);
Optional.ofNullable(source).ifPresent(addBundleRequest::setSourcePatterns);
Optional.ofNullable(ignore).ifPresent(addBundleRequest::setIgnorePatterns);
Optional.ofNullable(translation).ifPresent(addBundleRequest::setExportPattern);

Optional.ofNullable(labels).ifPresent(addBundleRequest::setLabelIds);

try {
bundle = client.addBundle(addBundleRequest);
} catch (Exception e) {
throw new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.bundle_is_not_added"), addBundleRequest), e);
}

if (!plainView) {
out.println(OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.bundle.added"), bundle.getId(), bundle.getName())));
} else {
out.println(String.valueOf(bundle.getId()));
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.crowdin.cli.commands.actions;

import com.crowdin.cli.client.ClientBundle;
import com.crowdin.cli.commands.NewAction;
import com.crowdin.cli.commands.Outputter;
import com.crowdin.cli.properties.ProjectProperties;
import com.crowdin.client.bundles.model.Bundle;

import java.util.List;

import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE;
import static com.crowdin.cli.utils.console.ExecutionStatus.*;

class BundleListAction implements NewAction<ProjectProperties, ClientBundle> {

private final boolean plainView;

public BundleListAction(boolean plainView) {
this.plainView = plainView;
}

@Override
public void act(Outputter out, ProjectProperties pb, ClientBundle client) {
List<Bundle> bundles = client.listBundle();
for (Bundle bundle : bundles) {
if (!plainView) {
out.println(String.format(RESOURCE_BUNDLE.getString("message.bundle.list"), bundle.getId(),
bundle.getName(),
bundle.getFormat(), bundle.getExportPattern()));
} else {
out.println(bundle.getId() + " " + bundle.getName());
}
}
if (bundles.isEmpty()) {
if (!plainView) {
out.println(WARNING.withIcon(RESOURCE_BUNDLE.getString("message.bundle.list_empty")));
} else {
out.println(RESOURCE_BUNDLE.getString("message.bundle.list_empty"));
}
}
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/crowdin/cli/commands/actions/CliActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,16 @@ public NewAction<ProjectProperties, ClientTask> taskAdd(String title, Integer ty
return new TaskAddAction(title, type, language, fileId, workflowStep, description, skipAssignedStrings, skipUntranslatedStrings, labels);
}

@Override
public NewAction<ProjectProperties, ClientBundle> bundleList(boolean plainView, boolean isVerbose) {
return new BundleListAction(plainView);
}

@Override
public NewAction<ProjectProperties, ClientBundle> bundleAdd(String name, String format, List<String> source, List<String> ignore, String translation, List<Long> labels, boolean plainView) {
return new BundleAddAction(name, format, source, ignore, translation, labels, plainView);
}

@Override
public NewAction<NoProperties, NoClient> checkNewVersion() {
return new CheckNewVersionAction();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package com.crowdin.cli.commands.actions;

import com.crowdin.cli.client.ClientBundle;
import com.crowdin.cli.commands.NewAction;
import com.crowdin.cli.commands.Outputter;
import com.crowdin.cli.commands.functionality.*;
import com.crowdin.cli.properties.ProjectProperties;
import com.crowdin.cli.utils.Utils;
import com.crowdin.cli.utils.console.ConsoleSpinner;
import com.crowdin.client.bundles.model.Bundle;
import com.crowdin.client.bundles.model.BundleExport;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;

import static com.crowdin.cli.BaseCli.RESOURCE_BUNDLE;
import static com.crowdin.cli.utils.console.ExecutionStatus.ERROR;
import static com.crowdin.cli.utils.console.ExecutionStatus.OK;

public class DownloadBundleAction implements NewAction<ProjectProperties, ClientBundle> {

private final Long id;
private FilesInterface files;
private boolean noProgress;
private boolean plainView;
private boolean keepArchive;
private File to;

private Outputter out;

public DownloadBundleAction(Long id, FilesInterface files, boolean plainView, boolean keepArchive, boolean noProgress) {
this.id = id;
this.files = files;
this.plainView = plainView;
this.keepArchive = keepArchive;
this.noProgress = noProgress;
}

@Override
public void act(Outputter out, ProjectProperties pb, ClientBundle client) {
this.out = out;
Bundle bundle = getBundle(client);
BundleExport status = this.buildBundle(out, client, bundle.getId(), bundle);
to = new File("bundle-" + status.getIdentifier() + ".zip");
downloadBundle(client, bundle.getId(), status.getIdentifier());
out.println(OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.bundle.download_success"), bundle.getId(), bundle.getName())));

String baseTemp = StringUtils.removeEnd(pb.getBasePath(), Utils.PATH_SEPARATOR) + Utils.PATH_SEPARATOR;
java.io.File baseTempDir = new java.io.File(baseTemp + Utils.PATH_SEPARATOR);
List<java.io.File> downloadedFiles = extractArchive(to, baseTempDir);
for (File file: downloadedFiles) {
String filePath = Utils.noSepAtStart(StringUtils.removeStart(file.getAbsolutePath(), baseTempDir.getAbsolutePath()));
out.println(OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.extracted_file"), filePath)));
}
if (!keepArchive) {
try {
files.deleteFile(to);
} catch (IOException e) {
out.println(ERROR.withIcon(String.format(RESOURCE_BUNDLE.getString("error.deleting_archive"), to)));
}
} else {
out.println(OK.withIcon(String.format(RESOURCE_BUNDLE.getString("message.archive"), to.getAbsolutePath())));
}
}

private Bundle getBundle(ClientBundle client) {
return client.getBundle(id)
.orElseThrow(() -> new RuntimeException(RESOURCE_BUNDLE.getString("error.bundle.not_found_by_id")));
}

private BundleExport buildBundle(Outputter out, ClientBundle client, Long bundleId, Bundle request) {
return ConsoleSpinner.execute(
out,
"message.spinner.building_bundle",
"error.bundle.build_bundle",
this.noProgress,
false,
() -> {
BundleExport status = client.startExportingBundle(bundleId, request);

while (!status.getStatus().equalsIgnoreCase("finished")) {
ConsoleSpinner.update(String.format(RESOURCE_BUNDLE.getString("message.spinner.building_bundle_percents"), status.getProgress()));
Thread.sleep(1000);

status = client.checkExportingBundle(bundleId, status.getIdentifier());

if (status.getStatus().equalsIgnoreCase("failed")) {
throw new RuntimeException(RESOURCE_BUNDLE.getString("message.spinner.build_has_failed"));
}
}

ConsoleSpinner.update(String.format(RESOURCE_BUNDLE.getString("message.spinner.building_bundle_percents"), 100));

return status;
}
);
}

private void downloadBundle(ClientBundle client, Long bundleId, String exportId) {
URL url = client.downloadBundle(bundleId, exportId);
try (InputStream data = url.openStream()) {
files.writeToFile(to.toString(), data);
} catch (IOException e) {
throw new RuntimeException(RESOURCE_BUNDLE.getString("error.write_file"), e);
}
}

private List<File> extractArchive(java.io.File zipArchive, java.io.File dir) {
return ConsoleSpinner.execute(
out,
"message.spinner.extracting_archive",
"error.extracting_files",
this.noProgress,
this.plainView,
() -> files.extractZipArchive(zipArchive, dir)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public void act(Outputter out, ProjectProperties pb, ClientTask client) {
String okMessage = isVerbose ? "message.task.list.verbose" : "message.task.list";
String deadline = task.getDeadline() == null ? "NoDueDate" : task.getDeadline().toString();
if (!plainView) {
out.println(LIST_ITEM.withIcon(
String.format(RESOURCE_BUNDLE.getString(okMessage), task.getId(), task.getTargetLanguageId(), task.getTitle(), task.getStatus(), task.getWordsCount(), deadline)));
out.println(String.format(RESOURCE_BUNDLE.getString(okMessage), task.getId(),
task.getTargetLanguageId(), task.getTitle(), task.getStatus(), task.getWordsCount(), deadline));
} else {
out.println(String.format(RESOURCE_BUNDLE.getString(okMessage), task.getId(), task.getTargetLanguageId(), task.getTitle(), task.getStatus(), task.getWordsCount(), deadline));
}
Expand Down
Loading

0 comments on commit 67d059c

Please sign in to comment.