Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
rhbz1139950 - apply rule mapping to Raw/File push strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Huang committed Sep 25, 2014
1 parent 93c8b3a commit 88306ea
Show file tree
Hide file tree
Showing 10 changed files with 437 additions and 41 deletions.
Expand Up @@ -26,6 +26,7 @@
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Nonnull;
Expand All @@ -34,10 +35,14 @@
import org.slf4j.LoggerFactory;
import org.zanata.client.config.FileMappingRule;
import org.zanata.client.config.LocaleMapping;
import org.zanata.common.ProjectType;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.io.Files;

import static org.zanata.client.commands.TransFileResolver.QualifiedSrcDocName;

/**
* @author Patrick Huang <a
* href="mailto:pahuang@redhat.com">pahuang@redhat.com</a>
Expand All @@ -46,8 +51,11 @@ public class FileMappingRuleParser {
private static final Logger log =
LoggerFactory.getLogger(FileMappingRuleParser.class);
private final FileMappingRule mappingRule;
private final ProjectType projectType;

public FileMappingRuleParser(FileMappingRule rule) {
public FileMappingRuleParser(FileMappingRule rule, ProjectType projectType) {
this.projectType = projectType;
Preconditions.checkState(isRuleValid(rule.getRule()), "rule defined is not valid: %s", rule.getRule());
Preconditions.checkArgument(isRuleValid(rule.getRule()));
this.mappingRule = rule;
}
Expand All @@ -58,20 +66,25 @@ protected static boolean isRuleValid(String rule) {
|| rule.contains(Placeholders.localeWithUnderscore.holder);
}

public boolean isApplicable(String qualifiedDocName) {
boolean ruleValid = isRuleValid(mappingRule.getRule());
if (!ruleValid) {
return false;
public boolean isApplicable(QualifiedSrcDocName qualifiedSrcDocName) {
if (Strings.isNullOrEmpty(mappingRule.getPattern())) {
return matchFileExtensionWithProjectType(qualifiedSrcDocName);
}
PathMatcher matcher =
FileSystems.getDefault().getPathMatcher("glob:" + mappingRule.getPattern());
return matcher.matches(Paths.get(qualifiedDocName));
return matcher.matches(Paths.get(qualifiedSrcDocName.getFullName()));
}

private boolean matchFileExtensionWithProjectType(QualifiedSrcDocName qualifiedSrcDocName) {
List<String> supportedTypes =
ProjectType.getSupportedSourceFileTypes(projectType);
return supportedTypes.contains(qualifiedSrcDocName.getExtension());
}

public String getRelativePathFromRule(@Nonnull String sourceFile,
public String getRelativePathFromRule(QualifiedSrcDocName qualifiedSrcDocName,
@Nonnull LocaleMapping localeMapping) {
EnumMap<Placeholders, String> map =
parseToMap(sourceFile, localeMapping);
parseToMap(qualifiedSrcDocName.getFullName(), localeMapping);

String temp = mappingRule.getRule();
for (Map.Entry<Placeholders, String> entry : map.entrySet()) {
Expand Down
Expand Up @@ -22,35 +22,147 @@
package org.zanata.client.commands;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Files;
import org.zanata.client.config.FileMappingRule;
import org.zanata.client.config.LocaleMapping;
import org.zanata.common.ProjectType;

import java.io.File;
import java.util.List;
import java.util.Map;

import static org.zanata.client.commands.Messages._;

/**
* @author Patrick Huang
* <a href="mailto:pahuang@redhat.com">pahuang@redhat.com</a>
* @author Patrick Huang <a
* href="mailto:pahuang@redhat.com">pahuang@redhat.com</a>
*/
public class TransFileResolver {
private final ConfigurableProjectOptions opts;
private Map<ProjectType, FileMappingRule> defaultProjectTypeToRules =
ImmutableMap
.<ProjectType, FileMappingRule> builder()
.put(ProjectType.File, new FileMappingRule(null,
"{locale}/{path}/{filename}.{extension}"))
.put(ProjectType.Gettext, new FileMappingRule(null, ""))
.build();

public TransFileResolver(ConfigurableProjectOptions opts) {
this.opts = opts;
}

public Optional<File> getTransFile(String sourceDocWithExtension,
LocaleMapping localeMapping) {
public File getTransFile(QualifiedSrcDocName qualifiedSrcDocName,
LocaleMapping localeMapping) {
Optional<File> fileOptional =
tryGetTransFileFromProjectMappingRules(qualifiedSrcDocName,
localeMapping);
if (fileOptional.isPresent()) {
return fileOptional.get();
} else {
ProjectType projectType = getProjectType();
return getDefaultTransFileFromProjectType(qualifiedSrcDocName,
localeMapping, projectType);
}
}

public File getTransFile(UnqualifiedSrcDocName unqualifiedSrcDocName,
LocaleMapping localeMapping) {
QualifiedSrcDocName qualifiedSrcDocName =
unqualifiedSrcDocName.toQualifiedDocName(getProjectType());
return getTransFile(qualifiedSrcDocName, localeMapping);
}

private ProjectType getProjectType() {
try {
return ProjectType.getValueOf(
opts.getProjectType());
} catch (Exception e) {
throw Throwables.propagate(e);
}
}

private File getDefaultTransFileFromProjectType(
QualifiedSrcDocName qualifiedSrcDocName, LocaleMapping localeMapping,
ProjectType projectType) {
FileMappingRule rule = defaultProjectTypeToRules.get(projectType);
Preconditions
.checkNotNull(rule, _("no.default.mapping"), projectType);
String relativePath = new FileMappingRuleParser(rule, projectType)
.getRelativePathFromRule(qualifiedSrcDocName, localeMapping);
return new File(opts.getTransDir(), relativePath);
}

private Optional<File> tryGetTransFileFromProjectMappingRules(
QualifiedSrcDocName qualifiedSrcDocName, LocaleMapping localeMapping) {
List<FileMappingRule> fileMappingRules = opts.getFileMappingRules();
// TODO may need to sort the rules. put rules without pattern to last
for (FileMappingRule rule : fileMappingRules) {
FileMappingRuleParser parser = new FileMappingRuleParser(rule);
if (parser.isApplicable(sourceDocWithExtension)) {
FileMappingRuleParser parser = new FileMappingRuleParser(rule,
getProjectType());
if (parser.isApplicable(qualifiedSrcDocName)) {
String relativePath = parser
.getRelativePathFromRule(sourceDocWithExtension,
localeMapping);
.getRelativePathFromRule(qualifiedSrcDocName,
localeMapping);
return Optional.of(new File(opts.getTransDir(), relativePath));
}
}
return Optional.absent();
}

public static class QualifiedSrcDocName {
private final String fullName;
private final String extension;

private QualifiedSrcDocName(String fullName) {
this.fullName = fullName;
extension = Files.getFileExtension(fullName).toLowerCase();
}
public static QualifiedSrcDocName from(String qualifiedName) {
String extension = Files.getFileExtension(qualifiedName);
Preconditions.checkArgument(!Strings.isNullOrEmpty(extension), "expect a qualified document name (with extension)");
return new QualifiedSrcDocName(qualifiedName);
}
public static QualifiedSrcDocName from(String unqualifiedName, String extension) {
return new QualifiedSrcDocName(unqualifiedName + "." + extension);
}

public String getFullName() {
return fullName;
}

public String getExtension() {
return extension;
}
}
public static class UnqualifiedSrcDocName {
private final String name;
private UnqualifiedSrcDocName(String name) {
this.name = name;
}
public static UnqualifiedSrcDocName from(String docName) {
String extension = Files.getFileExtension(docName);
Preconditions.checkArgument(Strings.isNullOrEmpty(extension), "expect an unqualifed document name (without extension)");
return new UnqualifiedSrcDocName(docName);
}
public QualifiedSrcDocName toQualifiedDocName(ProjectType projectType) {
switch (projectType) {
case Utf8Properties:
case Properties:
return QualifiedSrcDocName.from(name, ".properties");
case Gettext:
case Podir:
return QualifiedSrcDocName.from(name, ".pot");
case Xliff:
case Xml:
return QualifiedSrcDocName.from(name, ".xml");
case File:
throw new IllegalArgumentException("You can not using unqualified document name in file type project");
}
throw new IllegalStateException("Can not convert unqualified document name for this project type: " + projectType);
}
}
}
Expand Up @@ -21,11 +21,10 @@
package org.zanata.client.commands.push;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zanata.client.commands.TransFileResolver;
import org.zanata.client.config.LocaleMapping;

/**
Expand Down Expand Up @@ -61,9 +60,10 @@ public void visitTranslationFiles(String sourceDocument,
return;
}
for (LocaleMapping localeMapping : getOpts().getLocaleMapList()) {
String locale = localeMapping.getLocalLocale();
File localeDir = new File(getOpts().getTransDir(), locale);
File translationFile = new File(localeDir, sourceDocument);
File translationFile = new TransFileResolver(getOpts())
.getTransFile(TransFileResolver.QualifiedSrcDocName.from(
sourceDocument), localeMapping);

if (translationFile.canRead()) {
visitor.visit(localeMapping, translationFile);
} else {
Expand Down
3 changes: 3 additions & 0 deletions zanata-client-commands/src/main/resources/prompts.properties
Expand Up @@ -84,3 +84,6 @@ update.marker.hint=You can edit the file to change when and how your client chec
no.check.update.prompt=true|false. Whether to ask before performing an update.
latest.version.confirm=You are running the latest version of Zanata client.
create.file.failure=Failed to create file at %s. Check permissions.

no.default.mapping=Can not find default translation file mapping rule for project type %s

@@ -0,0 +1,58 @@
/*
* Copyright 2014, 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;

import java.io.File;
import java.io.IOException;

import org.junit.rules.TemporaryFolder;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

/**
* @author Patrick Huang
* <a href="mailto:pahuang@redhat.com">pahuang@redhat.com</a>
*/
public class TempTransFileRule extends TemporaryFolder {
private File transDir;

@Override
protected void before() throws Throwable {
super.before();
if (transDir == null) {
transDir = getRoot();
}
}

public File createTransFileRelativeToTransDir(String path)
throws IOException {
File file = new File(transDir, path);
assertThat(file.getParentFile().mkdirs(), is(true));
assertThat(file.createNewFile(), is(true));
return file;
}

public File getTransDir() {
return transDir;
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2014, 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;

import org.zanata.client.commands.ConfigurableProjectOptions;
import org.zanata.client.config.LocaleMapping;
import com.google.common.base.Optional;

/**
* @author Patrick Huang
* <a href="mailto:pahuang@redhat.com">pahuang@redhat.com</a>
*/
public class TestUtils {
/**
* Creates a LocaleMapping with optional map from and then add to options.
* @return the created LocaleMapping
*/
public static LocaleMapping createAndAddLocaleMapping(String localeId,
Optional<String> optionalMapFrom, ConfigurableProjectOptions opts) {
LocaleMapping mapping = new LocaleMapping(localeId);
if (optionalMapFrom.isPresent()) {
mapping.setMapFrom(optionalMapFrom.get());
}
opts.getLocaleMapList().add(mapping);
return mapping;
}
}

0 comments on commit 88306ea

Please sign in to comment.