org.tonguetied.datatransfer.importing.AbstractPropertiesImporter.java Source code

Java tutorial

Introduction

Here is the source code for org.tonguetied.datatransfer.importing.AbstractPropertiesImporter.java

Source

/*
 * Copyright 2008 The Tongue-Tied Authors
 * 
 * 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.tonguetied.datatransfer.importing;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.tonguetied.datatransfer.importing.ImportException.ImportErrorCode;
import org.tonguetied.keywordmanagement.Bundle;
import org.tonguetied.keywordmanagement.Country;
import org.tonguetied.keywordmanagement.Keyword;
import org.tonguetied.keywordmanagement.KeywordService;
import org.tonguetied.keywordmanagement.Language;
import org.tonguetied.keywordmanagement.Translation;
import org.tonguetied.keywordmanagement.TranslationPredicate;
import org.tonguetied.keywordmanagement.Country.CountryCode;
import org.tonguetied.keywordmanagement.Language.LanguageCode;
import org.tonguetied.keywordmanagement.Translation.TranslationState;

/**
 * Base data importer that handles input in the Java resource or property file
 * type format. The resource file is read and entries are transformed into 
 * {@link Translation}s and added to the system. Implementers of this file will
 * determine how to handle the keys and translations.
 *   
 * @author bsion
 */
public abstract class AbstractPropertiesImporter extends AbstractSingleResourceImporter {
    /**
     * Create a new instance of PropertiesImporter.
     * 
     * @param keywordService the interface to keyword functions
     */
    public AbstractPropertiesImporter(KeywordService keywordService) {
        super(keywordService);
    }

    @Override
    protected void doImport(final byte[] input, final TranslationState state) throws ImportException {
        Map<Object, Object> properties = loadProperties(input);
        Keyword keyword;
        Translation translation;
        String value;
        for (Entry<Object, Object> entry : properties.entrySet()) {
            keyword = getKeywordService().getKeyword((String) entry.getKey());
            value = "".equals(entry.getValue()) ? null : (String) entry.getValue();
            if (keyword == null) {
                keyword = new Keyword();
                keyword.setKeyword((String) entry.getKey());
                translation = new Translation(getBundle(), getCountry(), getLanguage(), value, state);
                keyword.addTranslation(translation);
            } else {
                translation = findTranslation(keyword);
                if (translation == null) {
                    translation = new Translation(getBundle(), getCountry(), getLanguage(), value, state);
                    keyword.addTranslation(translation);
                } else {
                    translation.setState(state);
                    translation.setValue(value);
                }
            }

            getKeywordService().saveOrUpdate(keyword);
        }
        if (logger.isInfoEnabled())
            logger.info("processed " + properties.size() + " translations");
    }

    /**
     * Loads the properties file into a format readable by the importer.
     * 
     * @param input the input byte array of the properties file contents.
     * @return a key value mapping of keywords and translations.
     */
    protected abstract Map<Object, Object> loadProperties(final byte[] input);

    /**
     * Find a translation from an existing keyword that matches the business 
     * keys.
     * 
     * @param keyword the existing keyword to search
     * @return the matching translation or <code>null</code> if no match is 
     * found
     */
    private Translation findTranslation(final Keyword keyword) {
        Translation translation = null;
        if (!keyword.getTranslations().isEmpty()) {
            final Predicate predicate = new TranslationPredicate(getBundle(), getCountry(), getLanguage());
            translation = (Translation) CollectionUtils.find(keyword.getTranslations(), predicate);
        }

        return translation;
    }

    /**
     * Validates the <code>fileName</code> to ensure that the fileName 
     * corresponds to an existing {@link Bundle}, {@link Country} and 
     * {@link Language}.
     * 
     */
    @Override
    protected void validate(final String fileName, final Bundle bundle, List<ImportErrorCode> errorCodes)
            throws ImportException {
        String[] tokens = fileName.split("_");

        CountryCode countryCode = null;
        LanguageCode languageCode = null;
        switch (tokens.length) {
        case 1:
            // this is the default bundle, so no country or language
            countryCode = CountryCode.DEFAULT;
            languageCode = LanguageCode.DEFAULT;
            break;
        case 2:
            if (isCountryCode(tokens[1])) {
                countryCode = ImporterUtils.evaluateCountryCode(tokens[1], errorCodes);
                languageCode = LanguageCode.DEFAULT;
            } else {
                countryCode = CountryCode.DEFAULT;
                languageCode = ImporterUtils.evaluateLanguageCode(tokens[1], errorCodes);
            }
            break;
        case 3:
            countryCode = ImporterUtils.evaluateCountryCode(tokens[2], errorCodes);
            languageCode = ImporterUtils.evaluateLanguageCode(tokens[1], errorCodes);
            break;
        default:
            errorCodes.add(ImportErrorCode.invalidNameFormat);
            break;
        }

        if (logger.isDebugEnabled()) {
            logger.debug("bundle name = " + tokens[0]);
        }

        if (bundle == null) {
            setBundle(getKeywordService().getBundleByResourceName(tokens[0]));
            if (getBundle() == null)
                errorCodes.add(ImportErrorCode.unknownBundle);
        } else {
            setBundle(bundle);
        }

        this.setCountry(getKeywordService().getCountry(countryCode));
        if (getCountry() == null)
            errorCodes.add(ImportErrorCode.unknownCountry);

        this.setLanguage(getKeywordService().getLanguage(languageCode));
        if (getLanguage() == null)
            errorCodes.add(ImportErrorCode.unknownLanguage);

        if (!errorCodes.isEmpty())
            logger.warn("Cannot process " + fileName + ". It contains " + errorCodes.size() + " errors");
    }

    /**
     * Determines if the string component is a country code or not.
     * 
     * @param code the code to evaluate
     * @return <code>true</code> if the string corresponds to a potential 
     * country code, <code>false</code> otherwise
     */
    protected boolean isCountryCode(String code) {
        boolean isCountryCode = false;
        if (code != null && !"".equals(code))
            isCountryCode = Character.isUpperCase(code.charAt(0));

        return isCountryCode;
    }
}