Java tutorial
/* * Copyright (c) 2011 by Martin Simons. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package net.lunikon.rethul.service; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import net.lunikon.rethul.data.FileDAO; import net.lunikon.rethul.data.StringsDAO; import net.lunikon.rethul.model.File; import net.lunikon.rethul.model.FileStatus; import net.lunikon.rethul.model.LocalizedString; import net.lunikon.rethul.model.Project; import net.lunikon.rethul.util.SortedProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; /** * FileService. * * @author Martin Simons */ @Transactional public class FileService { /** * The E_FILE_NAME_EXISTS. */ public static final String E_FILE_NAME_EXISTS = "File.e.name.exists"; /** * The fileDAO. */ @Autowired private FileDAO fileDAO; /** * The stringsDAO. */ @Autowired private StringsDAO stringsDAO; /** * Adds the given file name to the project. * * @param project * The project. * @param name * The name of the file to create. * @throws ServiceException * when a file by this name already exists. */ public void create(Project project, String name) throws ServiceException { File file = fileDAO.getByProjectAndName(project, name); if (file != null) throw new ServiceException(E_FILE_NAME_EXISTS); file = new File(project, name); fileDAO.save(file); } /** * Reloads the master file. New keys are added. If a key value changes, the * corresponding translations are marked as pending. Keys that have dropped * from the master file are deleted in all translations. * * @param file * The file. * @return an array containing the number of affected keys/strings. [0] new * keys added, [1] changed master values, [2] strings marked as * pending, [3] keys removed, [4] strings deleted */ public Object[] reloadMaster(File file) { // load properties Properties props = new Properties(); try { FileInputStream is = new FileInputStream(FileStatus.getLanguageFilePath(file, null)); props.load(is); is.close(); } catch (Exception e) { throw new RuntimeException(e); } // load existing master strings from database and add them to a map List<LocalizedString> strings = stringsDAO.loadMasterStrings(file); Map<String, LocalizedString> existing = new HashMap<String, LocalizedString>(strings.size()); for (LocalizedString ls : strings) existing.put(ls.getKey(), ls); // an array containing some counters that will be returned as the result Object[] results = new Object[5]; // run through properties int added = 0, changed = 0; Set<String> pending = new HashSet<String>(); for (String key : props.stringPropertyNames()) { // does key exist yet? LocalizedString value = existing.get(key); String masterValue = props.getProperty(key); if (value != null) { if (!value.getTranslation().equals(masterValue)) { // mark key as pending pending.add(key); changed++; // update master value.setTranslation(masterValue); stringsDAO.update(value); } } else { // create new key value = new LocalizedString(file, key, masterValue); stringsDAO.save(value); added++; } // remove from existing list existing.remove(key); } results[0] = added; results[1] = changed; // mark all strings that changed in master as pending for other locales results[2] = stringsDAO.markPending(file, pending); // delete strings that have dropped from the master results[3] = existing.size(); results[4] = stringsDAO.deleteKeys(file, existing.keySet()); return results; } /** * Loads a language file and writes its content to the corresponding file in * rethul. Only keys are imported that are also defined by the master. All * imported strings are marked as "pending". * * @param file * The file. * @param locale * The locale. */ public void reload(File file, Locale locale) { // first, load master keys Set<String> masterKeys = stringsDAO.loadMasterKeySet(file); // load properties from file Properties props = new Properties(); try { String path = FileStatus.getLanguageFilePath(file, locale); FileInputStream is = new FileInputStream(path); props.load(is); is.close(); } catch (Exception e) { throw new RuntimeException(e); } // add all values that exist in master for (String key : props.stringPropertyNames()) { if (!masterKeys.contains(key)) continue; String value = props.getProperty(key); LocalizedString ls = new LocalizedString(file, key, value); ls.setLocale(locale); ls.setPending(true); stringsDAO.save(ls); } } public void writeOut(File file) { // load all completed strings List<LocalizedString> completed = stringsDAO.loadCompletedStrings(file); if (completed.isEmpty()) return; // sort them into properties Map<Locale, SortedProperties> properties = new HashMap<Locale, SortedProperties>(); for (LocalizedString string : completed) { Locale locale = string.getLocale(); SortedProperties props = properties.get(locale); if (props == null) { props = new SortedProperties(); properties.put(locale, props); } props.setProperty(string.getKey(), string.getTranslation()); } // write out files for (Locale locale : properties.keySet()) { Properties props = properties.get(locale); String filename = FileStatus.getLanguageFilePath(file, locale); try { FileOutputStream out = new FileOutputStream(filename); props.store(out, null); out.close(); } catch (Exception e) { throw new RuntimeException(e); } } } }