Java tutorial
/* * Copyright 2015 Haulmont * * 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 com.haulmont.mp2xls.writer; import com.haulmont.mp2xls.object.LocalizationLog; import com.haulmont.mp2xls.object.LocalizationsBatch; import com.haulmont.mp2xls.object.MessagesLocalization; import com.haulmont.mp2xls.reader.MessagesFolderReader; import com.haulmont.mp2xls.writer.commons.MessagePropertiesIOFactory; import org.apache.commons.configuration2.Configuration; import org.apache.commons.configuration2.FileBasedConfiguration; import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.configuration2.PropertiesConfigurationLayout; import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder; import org.apache.commons.configuration2.builder.fluent.Parameters; import org.apache.commons.lang.StringUtils; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class LocalizationBatchFileWriter { private LocalizationsBatch sourceLocalization; private LocalizationsBatch fileLocalization; public LocalizationBatchFileWriter(LocalizationsBatch sourceLocalization, LocalizationsBatch fileLocalization) { this.sourceLocalization = sourceLocalization; this.fileLocalization = fileLocalization; } public void process(String logFile, boolean overwriteExistingMessages) throws IOException { File basePath = new File(fileLocalization.getProjectDirectory()); List<LocalizationLog> differences = new ArrayList<>(); for (String localizationPack : fileLocalization.getMessagesLocalizations().keySet()) { Set<MessagesLocalization> messagesLocalizations = fileLocalization.getMessagesLocalizations() .get(localizationPack); Set<MessagesLocalization> sourceMessagesLocalizations = sourceLocalization.getMessagesLocalizations() .get(localizationPack); for (MessagesLocalization localization : messagesLocalizations) { if (localization.getMessages().size() == 0) continue; if (!fileLocalization.getScanLocalizationIds() .contains(localization.getLocaleId() == null ? "en" : localization.getLocaleId())) continue; List<String> parameters = Arrays.asList(localization.getMessages().keySet() .toArray(new String[localization.getMessages().keySet().size()])); Collections.sort(parameters, new Comparator<String>() { @Override public int compare(String o1, String o2) { o1 = o1.replaceFirst("^#", ""); o2 = o2.replaceFirst("^#", ""); Boolean o1System = MessagesFolderReader.systemKeys.contains(o1); Boolean o2System = MessagesFolderReader.systemKeys.contains(o2); if (o1System && o2System) return o1.compareTo(o2); if (o1System) return -1; if (o2System) return 1; return o1.compareTo(o2); } }); List<String> stringsToPrint = new ArrayList<>(); List<LocalizationLog> addedInNewFile = new ArrayList<>(); for (String param : parameters) { if (localization.getMessages().get(param) != null) { stringsToPrint.add(param + " = " + localization.getMessages().get(param)); addedInNewFile.add(new LocalizationLog(localization.getPath(), param, "", localization.getMessages().get(param), LocalizationLog.Type.ADDED_IN_NEW_FILE)); } } if (stringsToPrint.size() > 0) { List<LocalizationLog> currentLocalizationBatchDifferences = getDifferences(localization, sourceMessagesLocalizations); differences.addAll(currentLocalizationBatchDifferences); File messageFile = new File(basePath, localization.getPath()); if (!messageFile.exists()) { createNewFileLocalization(stringsToPrint, messageFile); differences.addAll(addedInNewFile); } else if (overwriteExistingMessages) { mergeLocalizationProperties(messageFile, currentLocalizationBatchDifferences); } } } } for (String localizationPack : sourceLocalization.getMessagesLocalizations().keySet()) { Set<MessagesLocalization> messagesLocalizations = fileLocalization.getMessagesLocalizations() .get(localizationPack); Set<MessagesLocalization> sourceMessagesLocalizations = sourceLocalization.getMessagesLocalizations() .get(localizationPack); for (MessagesLocalization localization : sourceMessagesLocalizations) { if (localization.getMessages().size() == 0) continue; if (!sourceLocalization.getScanLocalizationIds() .contains(localization.getLocaleId() == null ? "en" : localization.getLocaleId())) continue; List<String> parameters = Arrays.asList(localization.getMessages().keySet() .toArray(new String[localization.getMessages().keySet().size()])); Collections.sort(parameters, new Comparator<String>() { @Override public int compare(String o1, String o2) { o1 = o1.replaceFirst("^#", ""); o2 = o2.replaceFirst("^#", ""); Boolean o1System = MessagesFolderReader.systemKeys.contains(o1); Boolean o2System = MessagesFolderReader.systemKeys.contains(o2); if (o1System && o2System) return o1.compareTo(o2); if (o1System) return -1; if (o2System) return 1; return o1.compareTo(o2); } }); List<String> stringsToPrint = new ArrayList<>(); for (String param : parameters) { if (localization.getMessages().get(param) != null) { stringsToPrint.add(param + " = " + localization.getMessages().get(param)); } } if (stringsToPrint.size() > 0) { differences.addAll(getNotFoundLocalizationInExcel(localization, messagesLocalizations)); File messageFile = new File(basePath, localization.getPath()); if (!messageFile.exists()) { createNewFileLocalization(stringsToPrint, messageFile); } } } } if (differences.size() > 0) { LocalizationLogExcelWriter.exportToXls(differences, logFile); } } /** * Writing all changed properties to the passed file. Using apache commons-configuration to write properties, * because it preserves the original file format unlike the java.util.Properties class. * * @param messagesFile - messages file * @param diffs - differences */ protected void mergeLocalizationProperties(File messagesFile, Collection<LocalizationLog> diffs) { if (diffs == null || diffs.isEmpty()) return; try { Parameters parameters = new Parameters(); FileBasedConfigurationBuilder<FileBasedConfiguration> builder = new FileBasedConfigurationBuilder<FileBasedConfiguration>( PropertiesConfiguration.class) .configure(parameters.properties().setFile(messagesFile).setEncoding("UTF-8") .setIOFactory(new MessagePropertiesIOFactory()) .setLayout(new PropertiesConfigurationLayout())); Configuration configuration = builder.getConfiguration(); for (LocalizationLog diff : diffs) { if (LocalizationLog.Type.CHANGED.equals(diff.getType())) { configuration.setProperty(diff.getParameterName(), diff.getExcelValue()); } } builder.save(); } catch (Exception e) { throw new RuntimeException("Exception during properties file merging", e); } } protected void createNewFileLocalization(List<String> stringsToPrint, File messageFile) throws IOException { if (!messageFile.getParentFile().exists()) messageFile.getParentFile().mkdirs(); messageFile.createNewFile(); try (PrintWriter writer = new PrintWriter(messageFile, "UTF-8")) { writer.println("#"); String prev = "#"; for (String str : stringsToPrint) { if (addEmptyLine(str, prev)) writer.println(); writer.println(str); prev = str; } } } private boolean addEmptyLine(String currentLine, String prevLine) { Pattern p = Pattern.compile( "[ \\t]*#?(?<keyPrefix>[a-zA-Z0-9_]+).?(?<keyPostfix>[a-zA-Z0-9_\\.]+)?[ \\t]*=[ \\t]*(?<value>.+)?"); Matcher cur = p.matcher(currentLine); Matcher prev = p.matcher(prevLine); return !(cur.matches() && prev.matches()) || !cur.group("keyPrefix").equals(prev.group("keyPrefix")); } private List<LocalizationLog> getNotFoundLocalizationInExcel(MessagesLocalization sourceMessagesLocalization, Set<MessagesLocalization> messagesLocalizations) { List<LocalizationLog> notFoundLocalizations = new ArrayList<>(); List<LocalizationLog> movedMessages = new ArrayList<>(); MessagesLocalization messagesLocalization = notFindMessagesLocalizationInExcel(sourceMessagesLocalization, messagesLocalizations); Map<String, String> messages = sourceMessagesLocalization.getMessages(); if (messagesLocalization != null) { for (String message : messages.keySet()) { String key = messages.get(message); if (StringUtils.isNotEmpty(key)) { if (StringUtils.isNotEmpty(messages.get(message))) { movedMessages.add(new LocalizationLog(messagesLocalization.getPath(), message, "", messages.get(message), LocalizationLog.Type.MOVED)); } } } } notFoundLocalizations.addAll(movedMessages); return notFoundLocalizations; } private List<LocalizationLog> getDifferences(MessagesLocalization messagesLocalization, Set<MessagesLocalization> sourceMessagesLocalizations) { List<LocalizationLog> differences = new ArrayList<>(); List<LocalizationLog> addedMessages = new ArrayList<>(); List<LocalizationLog> changedMessages = new ArrayList<>(); List<LocalizationLog> movedMessages = new ArrayList<>(); MessagesLocalization sourceMessagesLocalization = findMessagesLocalizationInSource(messagesLocalization, sourceMessagesLocalizations); Map<String, String> messages = messagesLocalization.getMessages(); if (sourceMessagesLocalization == null) { for (String message : messages.keySet()) { String key = messages.get(message); if (StringUtils.isNotEmpty(key)) { if (StringUtils.isNotEmpty(messages.get(message))) { addedMessages.add(new LocalizationLog(messagesLocalization.getPath(), message, "", messages.get(message), LocalizationLog.Type.ADDED_IN_NEW_FILE)); } } } } else { Map<String, String> sourceMessages = sourceMessagesLocalization.getMessages(); for (String message : messages.keySet()) { String key = sourceMessages.get(message); if (StringUtils.isEmpty(key)) { if (StringUtils.isNotEmpty(messages.get(message))) { addedMessages.add(new LocalizationLog(sourceMessagesLocalization.getPath(), message, "", messages.get(message), LocalizationLog.Type.ADDED)); } } else if (!StringUtils.equals(messages.get(message), sourceMessages.get(message))) { changedMessages.add(new LocalizationLog(sourceMessagesLocalization.getPath(), message, sourceMessages.get(message), messages.get(message), LocalizationLog.Type.CHANGED)); } } for (String message : sourceMessages.keySet()) { String key = messages.get(message); if (StringUtils.isEmpty(key)) { if (StringUtils.isNotEmpty(sourceMessages.get(message))) { movedMessages.add(new LocalizationLog(sourceMessagesLocalization.getPath(), message, sourceMessages.get(message), "", LocalizationLog.Type.MOVED)); } } } } differences.addAll(addedMessages); differences.addAll(movedMessages); differences.addAll(changedMessages); return differences; } private MessagesLocalization notFindMessagesLocalizationInExcel(MessagesLocalization sourceMessagesLocalization, Set<MessagesLocalization> messagesLocalizations) { MessagesLocalization notFoundMessagesLocalization = null; boolean found = false; if (messagesLocalizations != null) { Set<MessagesLocalization> messagesLocalizationsWithoutEmpty = excludeEmptyLocalization( messagesLocalizations); for (MessagesLocalization messagesLocalization : messagesLocalizationsWithoutEmpty) { if (sourceMessagesLocalization.getPath().equals(messagesLocalization.getPath())) { found = true; break; } } } if (!found) { notFoundMessagesLocalization = sourceMessagesLocalization; } return notFoundMessagesLocalization; } protected Set<MessagesLocalization> excludeEmptyLocalization(Set<MessagesLocalization> messagesLocalizations) { Set<MessagesLocalization> messagesLocalizationsWithoutEmpty = new HashSet<>(); for (MessagesLocalization messagesLocalization : messagesLocalizations) { boolean found = false; if (messagesLocalization.getMessages() != null) { for (String key : messagesLocalization.getMessages().keySet()) { if (StringUtils.isNotEmpty(messagesLocalization.getMessages().get(key))) { found = true; break; } } if (found) { messagesLocalizationsWithoutEmpty.add(messagesLocalization); } } } return messagesLocalizationsWithoutEmpty; } private MessagesLocalization findMessagesLocalizationInSource(MessagesLocalization messagesLocalization, Set<MessagesLocalization> sourceMessagesLocalizations) { if (sourceMessagesLocalizations != null && sourceMessagesLocalizations.size() > 0) { for (MessagesLocalization sourceMessagesLocalization : sourceMessagesLocalizations) { if (sourceMessagesLocalization.getPath().equals(messagesLocalization.getPath())) { return sourceMessagesLocalization; } } } return null; } }