![JAR search and dependency download from the Maven repository](/logo.png)
org.everit.i18n.propsxlsconverter.internal.I18nConverterImpl Maven / Gradle / Ivy
/*
* Copyright (C) 2011 Everit Kft. (http://www.everit.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.everit.i18n.propsxlsconverter.internal;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.RegexFileFilter;
import org.apache.commons.lang.StringEscapeUtils;
import org.everit.i18n.propsxlsconverter.I18nConverter;
import org.everit.i18n.propsxlsconverter.internal.dto.PropKeyRowNumberDTO;
import org.everit.i18n.propsxlsconverter.internal.dto.WorkbookRowDTO;
import org.everit.i18n.propsxlsconverter.internal.workbook.WorkbookReader;
import org.everit.i18n.propsxlsconverter.internal.workbook.WorkbookWriter;
/**
* The {@link I18nConverter} implementation.
*/
public class I18nConverterImpl implements I18nConverter {
private static final int SEPARATOR_SIZE = 5;
private static final String UNDERLINE = "_";
/**
* Map key is fileAccces.
*/
private Map> fileAccessPropertyKeyRowNumber =
new HashMap>();
private void addPropKeyRowNumberToWorkbookKeyMap(final String fileAccess,
final String propKey, final int rowNumber) {
List list = fileAccessPropertyKeyRowNumber.get(fileAccess);
PropKeyRowNumberDTO propKeyRowNumber = new PropKeyRowNumberDTO()
.propKey(propKey)
.rowNumber(rowNumber);
if (list == null) {
list = new ArrayList();
list.add(propKeyRowNumber);
fileAccessPropertyKeyRowNumber.put(fileAccess, list);
} else {
list.add(propKeyRowNumber);
}
}
private String calculateDefaultLangFileName(final String fileName, final String searchLang,
final int lastIndexOf) {
String fileNameFirstPart = fileName.substring(0, lastIndexOf);
String fileNameSecondPart = fileName.substring(lastIndexOf + searchLang.length());
return fileNameFirstPart + fileNameSecondPart;
}
/**
* Calculate file access between the working directory and language file.
*
* @param languageFile
* the language file.
* @return the calculated file access path.
*/
private String calculateFileAccess(final File languageFile, final String[] languages,
final String workingDirectory) {
Path workingDirectoryPath = Paths.get(workingDirectory);
String languageFileAbsolutePath = languageFile.getAbsolutePath();
Path languageFilePath = Paths.get(languageFileAbsolutePath);
String fileName = languageFile.getName();
for (String lang : languages) {
String searchLang = UNDERLINE + lang;
int lastIndexOf = fileName.lastIndexOf(searchLang);
if (lastIndexOf > -1) {
String defaultLangFileName = calculateDefaultLangFileName(fileName,
searchLang,
lastIndexOf);
String defaultLangFileAbsolutePath = languageFileAbsolutePath.replace(fileName,
defaultLangFileName);
languageFilePath = Paths.get(defaultLangFileAbsolutePath);
}
}
Path relativize = workingDirectoryPath.relativize(languageFilePath);
return relativize.toString();
}
private String calculateLangFileName(final String fileAccess, final String lang,
final int lastIndexOfFolderSeparator) {
String fileName = lastIndexOfFolderSeparator > -1
? fileAccess.substring(lastIndexOfFolderSeparator)
: fileAccess;
int lastDotIndex = fileName.lastIndexOf(".");
return fileName.substring(0, lastDotIndex) + UNDERLINE + lang
+ fileName.substring(lastDotIndex);
}
@Override
public void exportToXls(final String xlsFileName, final String workingDirectory,
final String fileRegularExpression, final String[] languages) {
validateExportParameters(xlsFileName, workingDirectory, fileRegularExpression, languages);
File workingDirectoryFile = new File(workingDirectory);
Collection files = getFilesWithSorted(fileRegularExpression, workingDirectoryFile);
WorkbookWriter workbookWriter = new WorkbookWriter(xlsFileName, languages);
if (files.isEmpty()) {
workbookWriter.writeWorkbookToFile();
return;
}
for (File file : files) {
String lang = getLanguage(file.getName(), languages);
String fileAccess = calculateFileAccess(file, languages, workingDirectory);
try (FileInputStream fileInputStream = new FileInputStream(file);
InputStreamReader inputStreamReader =
new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(inputStreamReader)) {
String line = null;
while ((line = br.readLine()) != null) {
// ignore empty and comment lines
if (!"".equals(line) && (line.charAt(0) != '#')) {
String unescapedLine = StringEscapeUtils.unescapeJava(line);
int separatorIndex = getPropertySeparatorIndex(unescapedLine);
String propKey = unescapedLine.substring(0, separatorIndex);
String propValue = unescapedLine.substring(separatorIndex + 1);
insertOrUpdateWorkbookRow(workbookWriter, lang, fileAccess, propKey, propValue);
}
}
} catch (IOException e) {
throw new RuntimeException("Has problem with IO when try to load/process properties "
+ "files.", e);
}
}
workbookWriter.writeWorkbookToFile();
}
private Integer findRowNumber(final String relativePathToDefaultLanguageFile,
final String propKey) {
List list = fileAccessPropertyKeyRowNumber
.get(relativePathToDefaultLanguageFile);
if ((list == null) || list.isEmpty()) {
return null;
}
for (PropKeyRowNumberDTO pkrn : list) {
if (pkrn.propKey.equals(propKey)) {
return pkrn.rowNumber;
}
}
return null;
}
private Collection getFilesWithSorted(final String fileRegularExpression,
final File workingDirectoryFile) {
Collection files = FileUtils.listFiles(workingDirectoryFile,
new RegexFileFilter(fileRegularExpression),
DirectoryFileFilter.DIRECTORY);
if (files instanceof List>) {
// guarantees that the first file is the default language file.
Collections.sort((List) files,
(file1, file2) -> file1.getName().compareTo(file2.getName()));
}
return files;
}
/**
* Gets language from file name.
*
* @param fileName
* the file name.
* @return the language (hu, de) or if default language "" (empty string).
*/
private String getLanguage(final String fileName, final String[] languages) {
for (String lang : languages) {
if (fileName.contains(UNDERLINE + lang)) {
return lang;
}
}
return "";
}
private int getLastIndexOfFolderSeparator(final String fileAccess) {
int lastIndexOf = fileAccess.lastIndexOf("/");
if (lastIndexOf == -1) {
lastIndexOf = fileAccess.lastIndexOf("\\");
}
return lastIndexOf;
}
private String getPathWithoutFileName(final String fileAccess,
final int lastIndexOfFolderSeparator) {
if (lastIndexOfFolderSeparator > -1) {
return fileAccess.substring(0, lastIndexOfFolderSeparator);
}
return "";
}
private int getPropertySeparatorIndex(final String unescapedLine) {
int[] separators = new int[SEPARATOR_SIZE];
int index = 0;
separators[index++] = unescapedLine.indexOf('=');
separators[index++] = unescapedLine.indexOf(' ');
separators[index++] = unescapedLine.indexOf(':');
separators[index++] = unescapedLine.indexOf('\t');
separators[index++] = unescapedLine.indexOf('\f');
Arrays.sort(separators);
for (int i = 0; i < separators.length; i++) {
if (separators[i] != -1) {
return separators[i];
}
}
throw new RuntimeException("Not find separator in the line. Unescaped line: [" + unescapedLine
+ "].");
}
@Override
public void importFromXls(final String xlsFileName, final String workingDirectory) {
validateImportParameters(xlsFileName, workingDirectory);
WorkbookReader workbookReader = new WorkbookReader(xlsFileName);
Map langProperties = new HashMap();
langProperties.put("", new Properties());
String[] languages = workbookReader.getLanguages();
for (String lang : languages) {
langProperties.put(lang, new Properties());
}
String prevPropertiesFile = null;
ArrayList propKeySequence = new ArrayList();
int lastRowNumber = workbookReader.getLastRowNumber();
for (int i = 1; i <= lastRowNumber; i++) {
WorkbookRowDTO nextRow = workbookReader.getNextRow();
if (prevPropertiesFile == null) {
prevPropertiesFile = nextRow.propertiesFile;
}
if (!prevPropertiesFile.equals(nextRow.propertiesFile)) {
writePropertiesToFiles(langProperties, prevPropertiesFile, workingDirectory,
propKeySequence);
prevPropertiesFile = nextRow.propertiesFile;
}
langProperties.get("").setProperty(nextRow.propKey, nextRow.defaultLangValue);
for (String lang : languages) {
langProperties.get(lang).setProperty(nextRow.propKey, nextRow.langValues.get(lang));
}
propKeySequence.add(nextRow.propKey);
}
writePropertiesToFiles(langProperties, prevPropertiesFile, workingDirectory,
propKeySequence);
}
private void insertOrUpdateWorkbookRow(final WorkbookWriter workbookWriter, final String lang,
final String fileAccess, final String propKey, final String propValue) {
Integer updatedRowNumber = findRowNumber(fileAccess, propKey);
if (updatedRowNumber == null) {
int rowNumber = workbookWriter.insertRow(fileAccess,
propKey,
lang,
propValue);
addPropKeyRowNumberToWorkbookKeyMap(fileAccess, propKey,
rowNumber);
} else {
workbookWriter.updateRow(updatedRowNumber,
lang,
propValue);
}
}
private void makeDirectories(final String workingDirectory, final String pathWithoutFileName) {
File file = new File(workingDirectory, pathWithoutFileName);
if (!file.exists() && !file.mkdirs()) {
throw new RuntimeException("Cannot create directories.");
}
}
/**
* Validate parameters.
*
* @param exportedFileName
* the name of the exported file.
* @param workingDirectory
* the working directory (Example: c:\\temp or /tmp).
* @param fileRegularExpression
* the regex expression to find files which want to export to XLS file. Example:
* .*\.properties$ to find all properties files.
* @param languages
* the languages which want to search.
*
* @throws NullPointerException
* if one of parameter is null.
* @throws IllegalArgumentException
* if exportedFileName or workingDirectory or fileRegularExpression is empty. If
* workingDirectory is not directory.
* @throws java.util.regex.PatternSyntaxException
* if fileRegularExpression is not valid.
*/
private void validateExportParameters(final String exportedFileName,
final String workingDirectory, final String fileRegularExpression, final String[] languages) {
Objects.requireNonNull(exportedFileName, "Cannot be null exportedFileName.");
Objects.requireNonNull(workingDirectory, "Cannot be null workingDirectoryName.");
Objects.requireNonNull(fileRegularExpression, "Cannot be null fileRegularExpression.");
Objects.requireNonNull(languages, "Cannot be null languages.");
if (exportedFileName.trim().isEmpty()) {
throw new IllegalArgumentException("The exportedFileName is empty. Cannot be empty.");
}
if (workingDirectory.trim().isEmpty()) {
throw new IllegalArgumentException("The workingDirectoryName is empty. Cannot be empty.");
}
if (fileRegularExpression.trim().isEmpty()) {
throw new IllegalArgumentException("The fileRegularExpression is empty. Cannot be empty.");
}
File workingDirectoryFile = new File(workingDirectory);
if (!workingDirectoryFile.isDirectory()) {
throw new RuntimeException("The working directory is not directory.");
}
Pattern.compile(fileRegularExpression);
}
/**
* Validate parameters.
*
* @param importedFileName
* the name of the imported file.
* @param workingDirectory
* the working directory (Example: c:\\temp or /tmp).
*
* @throws NullPointerException
* if one of parameter is null.
* @throws IllegalArgumentException
* if importedFileName or workingDirectory is empty. If workingDirectory is not
* directory.
*/
private void validateImportParameters(final String importedFileName,
final String workingDirectory) {
Objects.requireNonNull(importedFileName, "Cannot be null importedFileName.");
Objects.requireNonNull(workingDirectory, "Cannot be null workingDirectoryName.");
if (importedFileName.trim().isEmpty()) {
throw new IllegalArgumentException("The importedFileName is empty. Cannot be empty.");
}
if (workingDirectory.trim().isEmpty()) {
throw new IllegalArgumentException("The workingDirectoryName is empty. Cannot be empty.");
}
File workingDirectoryFile = new File(workingDirectory);
if (!workingDirectoryFile.isDirectory()) {
throw new RuntimeException("The working directory is not directory.");
}
}
private void writePropertiesToFiles(final Map langProperties,
final String fileAccess, final String workingDirectory,
final ArrayList propKeySequence) {
langProperties.forEach((key, value) -> {
File langFile = null;
String pathWithoutFileName = null;
String langFileName = fileAccess;
if ("".equals(key)) {
int lastIndexOfFolderSeparator = getLastIndexOfFolderSeparator(fileAccess);
pathWithoutFileName = getPathWithoutFileName(langFileName,
lastIndexOfFolderSeparator);
makeDirectories(workingDirectory, pathWithoutFileName);
langFile = new File(workingDirectory, langFileName);
} else {
int lastIndexOfFolderSeparator = getLastIndexOfFolderSeparator(fileAccess);
pathWithoutFileName = getPathWithoutFileName(fileAccess,
lastIndexOfFolderSeparator);
makeDirectories(workingDirectory, pathWithoutFileName);
langFileName = calculateLangFileName(fileAccess, key,
lastIndexOfFolderSeparator);
langFile = new File(workingDirectory, pathWithoutFileName + langFileName);
}
try (FileOutputStream out = new FileOutputStream(langFile);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(out,
StandardCharsets.UTF_8);
BufferedWriter bw = new BufferedWriter(outputStreamWriter);) {
StringBuilder sb = new StringBuilder();
propKeySequence.forEach((propKey) -> {
String propValue = value.getProperty(propKey);
sb.append(propKey);
sb.append("=");
sb.append(StringEscapeUtils.escapeJava(propValue));
sb.append("\n");
});
bw.write(sb.toString());
} catch (IOException e) {
throw new RuntimeException(
"Failed to save file [" + pathWithoutFileName + langFileName + "]", e);
}
value.clear();
});
propKeySequence.clear();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy