All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.terrestris.shoguncore.service.Csv2ExtJsLocaleService Maven / Gradle / Ivy

There is a newer version: 5.3.13
Show newest version
package de.terrestris.shoguncore.service;

import com.opencsv.CSVParser;
import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.jboss.elasticsearch.tools.content.StructureUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Pattern;

/**
 * @author Nils Bühner
 */
@Service("localeService")
public class Csv2ExtJsLocaleService {

    private static final int NUM_HEADER_LINES = 3;
    @Autowired
    private ResourceLoader resourceLoader;

    /**
     * @param appId  The name of a CSV file in META-INF/locale
     * @param locale The name of the locale column in the CSV
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public Map getAllComponentsForLocale(String appId, String locale) throws Exception {

        Map resultMap = new TreeMap();
        Resource csvResource = resourceLoader.getResource("classpath:META-INF/locale/" + appId + ".csv"); // TODO make location configurable

        if (!csvResource.exists()) {
            throw new Exception("CSV locale resource for " + appId + " does not exist.");
        }

        FileInputStream fileIs = new FileInputStream(csvResource.getFile().getCanonicalPath());
        Reader reader = new InputStreamReader(fileIs, StandardCharsets.UTF_8);

        final CSVParser csvParser = new CSVParserBuilder().
            withSeparator(';').
            withQuoteChar('"').
            withEscapeChar('\\').
            build();

        final CSVReader csvReader = new CSVReaderBuilder(reader).
            withCSVParser(csvParser).
            build();

        try {
            int columnIndexOfLocale = detectColumnIndexOfLocale(locale, csvReader);

            List nextLine;
            boolean nextLineIsNotEmpty = true;

            while (nextLineIsNotEmpty) {
                final String[] nextLineArray = ArrayUtils.nullToEmpty(csvReader.readNext());
                nextLine = Arrays.asList(nextLineArray);
                nextLineIsNotEmpty = !nextLine.isEmpty();

                if (nextLineIsNotEmpty) {
                    String component = nextLine.get(0);
                    String field = nextLine.get(1);
                    String localeValue = nextLine.get(columnIndexOfLocale);

                    Object value = localeValue;

                    if (component.isEmpty()) {
                        throw new Exception("Missing component entry in CSV line " + csvReader.getLinesRead());
                    }
                    if (field.isEmpty()) {
                        throw new Exception("Missing field entry in CSV line " + csvReader.getLinesRead());
                    }

                    Object componentEntry;

                    if (resultMap.containsKey(component)) {
                        componentEntry = resultMap.get(component);
                    } else {
                        componentEntry = new TreeMap();
                    }

                    // handle arrays
                    if (field.contains("[]")) {
                        // assure that [] occurs only once at end of string
                        if (Pattern.matches(".+(\\[])$", field) &&
                            StringUtils.countMatches(field, "[]") == 1) { //TODO check this within the regex above
                            // convert localeValue to an array and adapt field
                            field = field.replace("[]", StringUtils.EMPTY);
                            value = localeValue.isEmpty() ? ArrayUtils.EMPTY_STRING_ARRAY : localeValue.split(",");
                        } else {
                            throw new Exception("Invalid field description '" + field
                                + "': '[]' may only occure once at the end, but not before");
                        }
                    }

                    // insert the value
                    StructureUtils.putValueIntoMapOfMaps((Map) componentEntry, field, value);

                    resultMap.put(component, componentEntry);
                }

            }
        } catch (Exception e) {
            throw e;
        } finally {
            IOUtils.closeQuietly(fileIs);
            IOUtils.closeQuietly(reader);
            IOUtils.closeQuietly(csvReader);
        }

        return resultMap;
    }

    /**
     * Extracts the column index of the given locale in the CSV file.
     *
     * @param locale
     * @param csvReader
     * @return
     * @throws IOException
     * @throws Exception
     */
    private int detectColumnIndexOfLocale(String locale, CSVReader csvReader) throws Exception {
        int indexOfLocale = -1;
        List headerLine = Arrays.asList(ArrayUtils.nullToEmpty(csvReader.readNext()));

        if (headerLine.isEmpty()) {
            throw new Exception("CSV locale file seems to be empty.");
        }

        if (headerLine.size() < NUM_HEADER_LINES) {
            // we expect at least three columns: component;field;locale1
            throw new Exception("CSV locale file is invalid: Not enough columns.");
        }

        // start with the third column as the first two columns must not be a
        // locale column
        for (int i = 2; i < headerLine.size(); i++) {
            String columnName = headerLine.get(i);
            if (locale.equalsIgnoreCase(columnName)) {
                indexOfLocale = headerLine.indexOf(columnName);
                break;
            }
        }
        if (indexOfLocale < 0) {
            throw new Exception("Could not find locale " + locale + " in CSV file");
        }
        return indexOfLocale;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy