diff --git a/stub-server/src/main/java/org/zanata/rest/service/MockGlossaryResource.java b/stub-server/src/main/java/org/zanata/rest/service/MockGlossaryResource.java index ead30c4e..9d9822ab 100644 --- a/stub-server/src/main/java/org/zanata/rest/service/MockGlossaryResource.java +++ b/stub-server/src/main/java/org/zanata/rest/service/MockGlossaryResource.java @@ -22,6 +22,7 @@ package org.zanata.rest.service; import java.util.List; +import javax.ws.rs.DefaultValue; import javax.ws.rs.Path; import javax.ws.rs.core.Context; import javax.ws.rs.core.GenericEntity; @@ -53,6 +54,12 @@ public Response getEntries(LocaleId srcLocale, return MockResourceUtil.notUsedByClient(); } + @Override + public Response downloadFile(@DefaultValue("csv") String fileType, + String locales) { + return MockResourceUtil.notUsedByClient(); + } + @Override public Response post(List glossaryEntries) { GenericEntity> genericEntity = diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableGlossaryOptions.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableGlossaryOptions.java new file mode 100644 index 00000000..8ed003cf --- /dev/null +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/ConfigurableGlossaryOptions.java @@ -0,0 +1,18 @@ +package org.zanata.client.commands; + +import java.io.File; + +import org.kohsuke.args4j.Option; + +/** + * @author Alex Eng aeng@redhat.com + */ +public interface ConfigurableGlossaryOptions extends ConfigurableOptions { + + public File getConfig(); + + @Option(name = "--config", metaVar = "FILENAME", + usage = "Configuration file, eg zanata.xml", + required = false) + public void setConfig(File config); +} diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java index f1849387..8958a0a5 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/OptionsUtil.java @@ -81,6 +81,23 @@ public static void applyConfigFiles(ConfigurableOptions opts) projectConfigFile); } } + } else if (opts instanceof ConfigurableGlossaryOptions) { + ConfigurableGlossaryOptions glossaryOpts = + (ConfigurableGlossaryOptions) opts; + File configFile = glossaryOpts.getConfig(); + if (configFile != null) { + JAXBContext jc = JAXBContext.newInstance(ZanataConfig.class); + Unmarshaller unmarshaller = jc.createUnmarshaller(); + if (configFile.exists()) { + log.info("Loading config from {}", configFile); + ZanataConfig projectConfig = (ZanataConfig) unmarshaller + .unmarshal(configFile); + applyBasicConfig(glossaryOpts, projectConfig); + } else { + log.warn("Config file '{}' not found; ignoring.", + configFile); + } + } } if (opts.getUserConfig() != null) { if (opts.getUserConfig().exists()) { @@ -132,12 +149,10 @@ public LocaleMapping apply(LocaleDetails input) { */ private static void applyProjectConfig(ConfigurableProjectOptions opts, ZanataConfig config) { + applyBasicConfig(opts, config); if (opts.getProj() == null) { opts.setProj(config.getProject()); } - if (opts.getUrl() == null) { - opts.setUrl(config.getUrl()); - } if (opts.getProjectVersion() == null) { opts.setProjectVersion(config.getProjectVersion()); } @@ -156,6 +171,13 @@ private static void applyProjectConfig(ConfigurableProjectOptions opts, checkPotentialMistakesInRules(opts, new ConsoleInteractorImpl(opts)); } + private static void applyBasicConfig(ConfigurableOptions opts, + ZanataConfig config) { + if (opts.getUrl() == null) { + opts.setUrl(config.getUrl()); + } + } + /** * Will check potential mistakes in file mapping rules. Missing locale in * the rule is considered invalid. Extra "{" and/or "}" will incur warnings diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/delete/GlossaryDeleteCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/delete/GlossaryDeleteCommand.java index 954e91a5..eb36df11 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/delete/GlossaryDeleteCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/delete/GlossaryDeleteCommand.java @@ -25,10 +25,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zanata.client.commands.ConfigurableCommand; +import org.zanata.client.commands.ConsoleInteractor; +import org.zanata.client.commands.ConsoleInteractorImpl; import org.zanata.client.commands.OptionsUtil; import org.zanata.rest.client.GlossaryClient; import org.zanata.rest.client.RestClientFactory; +import static org.zanata.client.commands.ConsoleInteractor.DisplayMode.Question; + /** * * @author Alex Eng aeng@redhat.com @@ -54,10 +58,16 @@ public GlossaryDeleteCommand(GlossaryDeleteOptions opts) { public void run() throws Exception { log.info("Server: {}", getOpts().getUrl()); log.info("Username: {}", getOpts().getUsername()); - log.info("Entry id to delete: {}", getOpts().getId()); + if (!StringUtils.isEmpty(getOpts().getId())) { + log.info("Entry id to delete: {}", getOpts().getId()); + } log.info("Delete entire glossary?: {}", getOpts().getAllGlossary()); - if (getOpts().getAllGlossary()) { + if (getOpts().isInteractiveMode()) { + ConsoleInteractor console = new ConsoleInteractorImpl(getOpts()); + console.printf(Question, "\nAre you sure (y/n)? "); + console.expectYes(); + } glossaryClient.deleteAll(); } else if (!StringUtils.isEmpty(getOpts().getId())) { glossaryClient.delete(getOpts().getId()); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/delete/GlossaryDeleteOptions.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/delete/GlossaryDeleteOptions.java index d7941e9c..3696f4ca 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/delete/GlossaryDeleteOptions.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/delete/GlossaryDeleteOptions.java @@ -1,8 +1,8 @@ package org.zanata.client.commands.glossary.delete; -import org.zanata.client.commands.ConfigurableProjectOptions; +import org.zanata.client.commands.ConfigurableGlossaryOptions; -public interface GlossaryDeleteOptions extends ConfigurableProjectOptions { +public interface GlossaryDeleteOptions extends ConfigurableGlossaryOptions { public String getId(); public boolean getAllGlossary(); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/pull/GlossaryPullCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/pull/GlossaryPullCommand.java new file mode 100644 index 00000000..bbda425b --- /dev/null +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/pull/GlossaryPullCommand.java @@ -0,0 +1,114 @@ +/* + * Copyright 2011, Red Hat, Inc. and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.zanata.client.commands.glossary.pull; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.zanata.client.commands.ConfigurableCommand; +import org.zanata.client.commands.OptionsUtil; +import org.zanata.rest.client.ClientUtil; +import org.zanata.rest.client.GlossaryClient; +import org.zanata.rest.client.RestClientFactory; +import org.zanata.util.PathUtil; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; +import com.sun.jersey.api.client.ClientResponse; + +/** + * + * @author Alex Eng aeng@redhat.com + * + **/ +public class GlossaryPullCommand extends + ConfigurableCommand { + private static final Logger log = + LoggerFactory.getLogger(GlossaryPullCommand.class); + + private final GlossaryClient client; + + public GlossaryPullCommand(GlossaryPullOptions opts, + RestClientFactory clientFactory) { + super(opts, clientFactory); + client = getClientFactory().getGlossaryClient(); + } + + public GlossaryPullCommand(GlossaryPullOptions opts) { + this(opts, OptionsUtil.createClientFactory(opts)); + } + + @Override + public void run() throws Exception { + String fileType = StringUtils.isEmpty(getOpts().getFileType()) ? "csv" + : getOpts().getFileType(); + if (!fileType.equalsIgnoreCase("po") + && !fileType.equalsIgnoreCase("csv")) { + throw new RuntimeException( + "Option 'zanata.fileType' is not valid. Please use 'csv' or 'po'"); + } + + log.info("Server: {}", getOpts().getUrl()); + log.info("Username: {}", getOpts().getUsername()); + log.info("File type: {}", fileType); + ImmutableList transLang = getOpts().getTransLang(); + if (transLang != null && !transLang.isEmpty()) { + log.info("Translation language: {}", Joiner.on(",").join(transLang)); + } + + log.info("pulling glossary from server"); + ClientResponse response = + client.downloadFile(fileType, transLang); + + if (response + .getClientResponseStatus() == ClientResponse.Status.NOT_FOUND) { + log.info("No glossary file in server"); + return; + } + + ClientUtil.checkResult(response); + InputStream glossaryFile = response.getEntity(InputStream.class); + if (glossaryFile == null) { + log.info("No glossary file in server"); + return; + } + String fileName = + ClientUtil.getFileNameFromHeader(response.getHeaders()); + File file = new File(fileName); + PathUtil.makeDirs(file.getParentFile()); + try (OutputStream out = new FileOutputStream(file)) { + int read; + byte[] buffer = new byte[1024]; + while ((read = glossaryFile.read(buffer)) != -1) { + out.write(buffer, 0, read); + } + out.flush(); + } finally { + glossaryFile.close(); + } + } +} diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/pull/GlossaryPullOptions.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/pull/GlossaryPullOptions.java new file mode 100644 index 00000000..a35097d4 --- /dev/null +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/pull/GlossaryPullOptions.java @@ -0,0 +1,12 @@ +package org.zanata.client.commands.glossary.pull; + +import org.zanata.client.commands.ConfigurableGlossaryOptions; +import org.zanata.client.commands.ConfigurableOptions; + +import com.google.common.collect.ImmutableList; + +public interface GlossaryPullOptions extends ConfigurableGlossaryOptions { + public String getFileType(); + + public ImmutableList getTransLang(); +} diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/push/GlossaryPushCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/push/GlossaryPushCommand.java index 89e194f7..ed34f5a2 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/push/GlossaryPushCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/push/GlossaryPushCommand.java @@ -64,32 +64,18 @@ public GlossaryPushCommand(GlossaryPushOptions opts, client = getClientFactory().getGlossaryClient(); } - public GlossaryPushCommand(GlossaryPushOptions opts) { this(opts, OptionsUtil.createClientFactory(opts)); + LocaleId srcLocaleId = new LocaleId(getOpts().getSourceLang()); + LocaleId transLocaleId = new LocaleId(getOpts().getTransLang()); glossaryReaders.put("po", new GlossaryPoReader( - getLocaleFromMap(getOpts().getSourceLang()), - getLocaleFromMap(getOpts().getTransLang()), getOpts() - .getBatchSize())); + srcLocaleId, transLocaleId, getOpts().getBatchSize())); glossaryReaders - .put("csv", new GlossaryCSVReader(getLocaleFromMap( - getOpts().getSourceLang()), + .put("csv", new GlossaryCSVReader(srcLocaleId, getOpts().getBatchSize())); } - private LocaleId getLocaleFromMap(String localLocale) { - if (getOpts() != null && getOpts().getLocaleMapList() != null - && !getOpts().getLocaleMapList().isEmpty()) { - for (LocaleMapping loc : getOpts().getLocaleMapList()) { - if (loc.getLocalLocale().equals(localLocale)) { - return new LocaleId(loc.getLocale()); - } - } - } - return new LocaleId(localLocale); - } - private AbstractGlossaryPushReader getReader(String fileExtension) { AbstractGlossaryPushReader reader = glossaryReaders.get(fileExtension); if (reader == null) { diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/push/GlossaryPushOptions.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/push/GlossaryPushOptions.java index 26c3786a..a8883983 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/push/GlossaryPushOptions.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/glossary/push/GlossaryPushOptions.java @@ -2,9 +2,10 @@ import java.io.File; -import org.zanata.client.commands.ConfigurableProjectOptions; +import org.zanata.client.commands.ConfigurableGlossaryOptions; +import org.zanata.client.commands.ConfigurableOptions; -public interface GlossaryPushOptions extends ConfigurableProjectOptions { +public interface GlossaryPushOptions extends ConfigurableGlossaryOptions { public File getGlossaryFile(); public String getSourceLang(); diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/stats/CsvStatisticsOutput.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/stats/CsvStatisticsOutput.java index 6465b158..be21da18 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/stats/CsvStatisticsOutput.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/stats/CsvStatisticsOutput.java @@ -29,8 +29,6 @@ import org.zanata.rest.dto.stats.ContainerTranslationStatistics; import org.zanata.rest.dto.stats.TranslationStatistics; -import org.apache.commons.csv.CSVPrinter; - import com.google.common.collect.Lists; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; diff --git a/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryDeleteMojo.java b/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryDeleteMojo.java index 9ad98724..ef20e073 100644 --- a/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryDeleteMojo.java +++ b/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryDeleteMojo.java @@ -32,9 +32,8 @@ * @author Alex Eng aeng@redhat.com * **/ -public class GlossaryDeleteMojo extends - ConfigurableProjectMojo implements - GlossaryDeleteOptions { +public class GlossaryDeleteMojo extends GlossaryMojo + implements GlossaryDeleteOptions { /** * id of glossary to delete @@ -71,5 +70,4 @@ public GlossaryDeleteCommand initCommand() { public String getCommandName() { return "glossary-delete"; } - } diff --git a/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryMojo.java b/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryMojo.java new file mode 100644 index 00000000..8712cc7d --- /dev/null +++ b/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryMojo.java @@ -0,0 +1,32 @@ +package org.zanata.maven; + +import java.io.File; + +import org.zanata.client.commands.ConfigurableGlossaryOptions; +import org.zanata.client.commands.ConfigurableOptions; + +/** + * Base mojo for glossary commands. + * + * @author Alex Eng aeng@redhat.com + */ +public abstract class GlossaryMojo + extends ConfigurableMojo implements ConfigurableGlossaryOptions { + /** + * Zanata configuration file. + * + * @parameter expression="${zanata.config}" + * default-value="${basedir}/zanata.xml" + */ + private File config; + + @Override + public File getConfig() { + return config; + } + + @Override + public void setConfig(File config) { + this.config = config; + } +} diff --git a/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryPullMojo.java b/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryPullMojo.java new file mode 100644 index 00000000..7d16316b --- /dev/null +++ b/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryPullMojo.java @@ -0,0 +1,80 @@ +/* + * Copyright 2011, Red Hat, Inc. and individual contributors + * as indicated by the @author tags. See the copyright.txt file in the + * distribution for a full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.zanata.maven; + +import org.zanata.client.commands.glossary.pull.GlossaryPullCommand; +import org.zanata.client.commands.glossary.pull.GlossaryPullOptions; + +import com.google.common.collect.ImmutableList; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +/** + * Pull glossary file from Zanata. + * + * @goal glossary-pull + * @author Alex Eng aeng@redhat.com + * + **/ +public class GlossaryPullMojo extends GlossaryMojo + implements GlossaryPullOptions { + + /** + * File type to be downloaded. + * csv - csv file format with comma separated + * po - a zip file of po files on available locales + * + * @parameter expression="${zanata.fileType}" default-value="csv" + */ + private String fileType = "csv"; + + /** + * Optional translation languages to pull. Leave empty for all available locales + * + * @parameter expression="${zanata.transLang}" + */ + private String[] transLang; + + public GlossaryPullMojo() throws Exception { + super(); + } + + @Override + public String getFileType() { + return fileType; + } + + @Override + public GlossaryPullCommand initCommand() { + return new GlossaryPullCommand(this); + } + + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", + justification = "Injected by Maven") + @Override + public ImmutableList getTransLang() { + return ImmutableList.copyOf(transLang); + } + + @Override + public String getCommandName() { + return "glossary-pull"; + } +} diff --git a/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryPushMojo.java b/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryPushMojo.java index 01f892c1..0bb461ec 100644 --- a/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryPushMojo.java +++ b/zanata-maven-plugin/src/main/java/org/zanata/maven/GlossaryPushMojo.java @@ -21,11 +21,7 @@ package org.zanata.maven; import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import org.apache.commons.lang.StringUtils; import org.zanata.client.commands.glossary.push.GlossaryPushCommand; import org.zanata.client.commands.glossary.push.GlossaryPushOptions; @@ -38,9 +34,8 @@ * @author Alex Eng aeng@redhat.com * **/ -public class GlossaryPushMojo extends - ConfigurableProjectMojo implements - GlossaryPushOptions { +public class GlossaryPushMojo extends GlossaryMojo + implements GlossaryPushOptions { /** * Source language of document diff --git a/zanata-rest-client/src/main/java/org/zanata/rest/client/GlossaryClient.java b/zanata-rest-client/src/main/java/org/zanata/rest/client/GlossaryClient.java index b536b786..0b31574d 100644 --- a/zanata-rest-client/src/main/java/org/zanata/rest/client/GlossaryClient.java +++ b/zanata-rest-client/src/main/java/org/zanata/rest/client/GlossaryClient.java @@ -32,6 +32,9 @@ import org.zanata.rest.dto.Project; import org.zanata.rest.service.GlossaryResource; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; +import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.GenericType; import com.sun.jersey.api.client.WebResource; @@ -60,6 +63,17 @@ public void post(List glossaryEntries) { .post(entity); } + public ClientResponse downloadFile(String fileType, + ImmutableList transLang) { + if (transLang != null && !transLang.isEmpty()) { + return webResource().path("file").queryParam("fileType", fileType) + .queryParam("locales", Joiner.on(",").join(transLang)) + .get(ClientResponse.class); + } + return webResource().path("file").queryParam("fileType", fileType) + .get(ClientResponse.class); + } + public void delete(String id) { webResource().path("entries/" + id) .delete(); diff --git a/zanata-rest-client/src/main/java/org/zanata/rest/client/InvalidContentTypeFilter.java b/zanata-rest-client/src/main/java/org/zanata/rest/client/InvalidContentTypeFilter.java index 780f0a19..0889641b 100644 --- a/zanata-rest-client/src/main/java/org/zanata/rest/client/InvalidContentTypeFilter.java +++ b/zanata-rest-client/src/main/java/org/zanata/rest/client/InvalidContentTypeFilter.java @@ -50,7 +50,7 @@ public class InvalidContentTypeFilter extends ClientFilter { "Please check the server URL is correct (in zanata.ini and in zanata.xml) and make sure you use the correct address."; - // we assume application/* are all the valid types (wildcard type is also considered compatible) + // allows content type of application/.* private static final Pattern VALID_TYPES_REGEX = Pattern.compile("application/.*");