dk.dma.msinm.common.time.TimeTranslator.java Source code

Java tutorial

Introduction

Here is the source code for dk.dma.msinm.common.time.TimeTranslator.java

Source

/* Copyright (c) 2011 Danish Maritime Authority
 *
 * This library 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 3 of the License, or (at your option) any later version.
 *
 * This library 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 General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */
package dk.dma.msinm.common.time;

import org.apache.commons.lang.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Represents a time translator that can translate to and fro an english version of the time description
 */
public class TimeTranslator implements TimeConstants {

    private static final Map<String, TimeTranslator> CACHE = new HashMap<>();

    String[] monthsEn = MONTHS_EN.split(",");
    String[] seasonsEn = SEASONS_EN.split(",");
    String[] months;
    String[] seasons;
    Map<String, String> translateToEnRules = new LinkedHashMap<>();
    Map<String, String> translateFromEnRules = new LinkedHashMap<>();

    /**
     * Disable public construction
     */
    private TimeTranslator(String language) throws TimeException {

        String file = "/timeTranslator_" + language + ".txt";
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(getClass().getResourceAsStream(file), "UTF-8"))) {

            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (StringUtils.isBlank(line) || line.startsWith("#")) {
                    continue;
                }

                int index = line.indexOf(":");
                if (index == -1) {
                    throw new TimeException("Invalid record: " + line);
                }
                String key = line.substring(0, index).trim();
                String value = line.substring(index + 1).trim();

                switch (key) {
                case "months":
                    months = value.toLowerCase().split(",");
                    if (months.length != 12) {
                        throw new TimeException("Invalid month definition: " + value);
                    }
                    break;

                case "seasons":
                    seasons = value.toLowerCase().split(",");
                    if (seasons.length != 4) {
                        throw new TimeException("Invalid season definition: " + value);
                    }
                    break;

                case "translate_rule":
                    if (value.contains("<->")) {
                        int x = value.indexOf("<->");
                        String local = unquote(value.substring(0, x).trim());
                        String english = unquote(value.substring(x + "<->".length()).trim());
                        translateToEnRules.put(local, english);
                        translateFromEnRules.put(english, local);
                    } else if (value.contains("->")) {
                        int x = value.indexOf("->");
                        String local = unquote(value.substring(0, x).trim());
                        String english = unquote(value.substring(x + "->".length()).trim());
                        translateToEnRules.put(local, english);
                    } else if (value.contains("<-")) {
                        int x = value.indexOf("<-");
                        String local = unquote(value.substring(0, x).trim());
                        String english = unquote(value.substring(x + "<-".length()).trim());
                        translateFromEnRules.put(english, local);
                    } else {
                        throw new TimeException("Invalid rewrite rule: " + value);
                    }
                    break;

                default:
                    throw new TimeException("Invalid record: " + line);
                }

            }

        } catch (IOException e) {
            throw new TimeException("Error reading " + file + ": " + e);
        }

        // Read the "months" property, or fall back to use the SimpleDateFormat definitions
        if (months == null) {
            months = new String[12];
            SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM", new Locale(language));
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.DAY_OF_MONTH, 1);
            for (int m = 0; m < 12; m++) {
                cal.set(Calendar.MONTH, m);
                months[m] = dateFormat.format(cal.getTime());
            }
        }

        // Add the month translation rules
        for (int m = 0; m < 12; m++) {
            translateToEnRules.put(months[m], monthsEn[m]);
            translateFromEnRules.put(monthsEn[m], months[m]);
        }

        // Check that seasons is defined
        if (seasons == null || seasons.length != 4) {
            throw new TimeException("Seasons not properly defined in " + file);
        }

        // Add the month translation rules
        for (int m = 0; m < 4; m++) {
            translateToEnRules.put(seasons[m], seasonsEn[m]);
            translateFromEnRules.put(seasonsEn[m], seasons[m]);
        }
    }

    /**
     * Return the time translator for the specific language
     * @param language the language
     * @return the time translator for the specific language
     */
    public synchronized static TimeTranslator get(String language) throws TimeException {

        // Cache the parser
        TimeTranslator parser = CACHE.get(language);
        if (parser == null) {
            parser = new TimeTranslator(language);
            CACHE.put(language, parser);
        }

        return parser;
    }

    /**
     * Translate the time description
     * @param time the time description to translate
     * @param translateRules the translation rules to apply
     * @return the result
     */
    public String translate(String time, Map<String, String> translateRules) throws TimeException {

        BufferedReader reader = new BufferedReader(new StringReader(time));
        String line;
        StringBuilder result = new StringBuilder();
        try {
            while ((line = reader.readLine()) != null) {
                //line = line.trim().toLowerCase();

                // Replace according to replace rules
                for (String key : translateRules.keySet()) {
                    String value = translateRules.get(key);

                    Matcher m = Pattern.compile(key, Pattern.CASE_INSENSITIVE).matcher(line);
                    StringBuffer sb = new StringBuffer();
                    while (m.find()) {
                        String text = m.group();
                        m.appendReplacement(sb, value);
                    }
                    m.appendTail(sb);
                    line = sb.toString();
                }

                // Capitalize, unless the line starts with something like "a) xxx"
                if (!line.matches("\\w\\) .*")) {
                    line = StringUtils.capitalize(line);
                }

                result.append(line + "\n");
            }
        } catch (Exception e) {
            throw new TimeException("Failed translating time description", e);
        }

        return result.toString().trim();
    }

    /**
     * Translate the given time description to English
     * @param time the time description to translate
     * @return the translated time description
     */
    public String translateToEnglish(String time) throws TimeException {
        return translate(time, translateToEnRules);
    }

    /**
     * Translate the given time description from English
     * @param time the time description to translate
     * @return the translated time description
     */
    public String translateFromEnglish(String time) throws TimeException {
        return translate(time, translateFromEnRules);
    }

    public static void main(String... args) throws TimeException {

        TimeTranslator translator = TimeTranslator.get("da");

        System.out.println(translator
                .translateToEnglish("a) Until 11 October 2014.\nb) 23 May - 7 June 2014, hours 0500 - 2200."));
    }

}