net.lunikon.rethul.data.StringsDAO.java Source code

Java tutorial

Introduction

Here is the source code for net.lunikon.rethul.data.StringsDAO.java

Source

/*
 * 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.data;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import net.lunikon.rethul.model.File;
import net.lunikon.rethul.model.LocalizedString;

import org.hibernate.Criteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

/**
 * StringsDAO.
 * 
 * @author Martin Simons
 */
public class StringsDAO extends AbstractDAO<LocalizedString> {
    /**
     * Constructs a new instance of this class.
     */
    public StringsDAO() {
        super(LocalizedString.class);
    }

    /**
     * Loads all master strings for the given file.
     * 
     * @param file
     *            The file.
     * @return a list of {@link LocalizedString}.
     */
    @SuppressWarnings("unchecked")
    public List<LocalizedString> loadMasterStrings(File file) {
        return getSession() //
                .createCriteria(LocalizedString.class) //
                .add(Restrictions.eq("file", file)) //
                .add(Restrictions.isNull("locale")) //
                .list();
    }

    /**
     * Searches for all strings of the given file and language that contain the
     * given phrase anywhere in the string.
     * 
     * @param file
     *            The file.
     * @param locale
     *            The locale.
     * @param phrase
     *            The phrase to search for.
     * @return a list of found strings.
     */
    @SuppressWarnings("unchecked")
    public List<LocalizedString> search(File file, Locale locale, String phrase) {
        return getSession() //
                .createCriteria(LocalizedString.class) //
                .add(Restrictions.eq("file", file)) //
                .add(Restrictions.eq("locale", locale)) //
                .add(Restrictions.ilike("translation", phrase, MatchMode.ANYWHERE)) //
                .addOrder(Order.asc("key")) //
                .list();
    }

    /**
     * Searches for the specified key/key pattern. If translated keys exist they
     * are returned, otherwise the matching master.
     * 
     * @param file
     *            The file.
     * @param locale
     *            The desired locale.
     * @param pattern
     *            The pattern to search for.
     * @return a list of found strings.
     */
    @SuppressWarnings("unchecked")
    public List<LocalizedString> searchKeys(File file, Locale locale, String pattern) {
        pattern = pattern.replace('*', '%');
        if (pattern.isEmpty() || pattern.equals("%"))
            return Collections.emptyList();

        List<LocalizedString> masters = getSession() //
                .createCriteria(LocalizedString.class) //
                .add(Restrictions.eq("file", file)) //
                .add(Restrictions.isNull("locale")) //
                .add(Restrictions.ilike("key", pattern)) //
                .list();

        if (masters.isEmpty())
            return masters;

        Map<String, LocalizedString> result = new TreeMap<String, LocalizedString>();
        for (LocalizedString master : masters)
            result.put(master.getKey(), master);

        List<LocalizedString> translated = getSession() //
                .createCriteria(LocalizedString.class) //
                .add(Restrictions.eq("file", file)) //
                .add(Restrictions.eq("locale", locale)) //
                .add(Restrictions.ilike("key", pattern)) //
                .list();
        for (LocalizedString str : translated)
            result.put(str.getKey(), str);

        return new ArrayList<LocalizedString>(result.values());
    }

    /**
     * Marks all strings in a file as pending that match any of the given keys.
     * This only affects translations, not the master strings.
     * 
     * @param file
     *            The file.
     * @param keys
     *            The keys.
     * @return the amount of affected strings.
     */
    public int markPending(File file, Collection<String> keys) {
        if (keys.isEmpty())
            return 0;

        return getSession() //
                .createQuery(
                        "update LocalizedString ls set ls.pending = true where ls.file = :file and ls.locale is not null and ls.key in (:keys)") //
                .setEntity("file", file) //
                .setParameterList("keys", keys) //
                .executeUpdate();
    }

    /**
     * Deletes all strings from a given file, that match any of the provided
     * keys. Also affects master strings.
     * 
     * @param file
     *            The file.
     * @param keys
     *            The keys.
     * @return the amount of deleted strings.
     */
    public int deleteKeys(File file, Collection<String> keys) {
        if (keys.isEmpty())
            return 0;

        return getSession() //
                .createQuery("delete LocalizedString ls where ls.file = :file and ls.key in (:keys)") //
                .setEntity("file", file) //
                .setParameterList("keys", keys) //
                .executeUpdate();
    }

    /**
     * Loads a {@link LocalizedString} by the given key for the given file and
     * locale.
     * 
     * @param file
     *            The file.
     * @param key
     *            The key.
     * @param locale
     *            The locale. Master is returned when locale is
     *            <code>null</code>.
     * @return the {@link LocalizedString} or <code>null</code> if it doesn't
     *         exist.
     */
    public LocalizedString get(File file, String key, Locale locale) {
        Criteria c = criteria() //
                .add(Restrictions.eq("file", file)) //
                .add(Restrictions.eq("key", key));

        if (locale == null)
            c.add(Restrictions.isNull("locale")); // master
        else
            c.add(Restrictions.eq("locale", locale)); // translation

        return (LocalizedString) c //
                .setMaxResults(1) //
                .uniqueResult();
    }

    /**
     * Gets a {@link LocalizedString} marked as pending for the given file.
     * 
     * @param file
     *            The file.
     * @param locale
     *            The locale.
     * @param onlyPending
     *            Only load strings marked as pending.
     * @param index
     *            The first result to return (for paging).
     * @return the localized string or <code>null</code> if none exists matching
     *         this query.
     */
    public LocalizedString getForReview(File file, Locale locale, boolean onlyPending, int index) {
        Criteria c = criteria() //
                .add(Restrictions.eq("file", file)) //
                .add(Restrictions.eq("locale", locale));

        if (onlyPending)
            c.add(Restrictions.eq("pending", Boolean.TRUE));

        return (LocalizedString) c //
                .addOrder(Order.asc("key")) //
                .setFirstResult(index) //
                .setMaxResults(1) //
                .uniqueResult();
    }

    /**
     * Loads the master string for a key that's missing in the file for the
     * given locale.
     * 
     * @param file
     *            The file.
     * @param locale
     *            The locale.
     * @param index
     *            The first result to return (for paging).
     * @return the MASTER string (no locale) for a key that's missing or
     *         <code>null</code> if none exists matching the query.
     */
    public LocalizedString getMissing(File file, Locale locale, int index) {
        StringBuilder q = new StringBuilder();
        q.append("from LocalizedString as master where master.key not in (");
        q.append("select localized.key from LocalizedString localized where ");
        q.append("localized.file = :file ");
        q.append("and localized.locale = :locale ");
        q.append(')');
        q.append("and master.file is :file ");
        q.append("and master.locale is null ");
        q.append("order by master.key");

        return (LocalizedString) getSession() //
                .createQuery(q.toString()) //
                .setEntity("file", file) //
                .setParameter("locale", locale) //
                .setFirstResult(index) //
                .setMaxResults(1) //
                .uniqueResult();
    }

    /**
     * Loads all strings of the given file marked as "done", ignoring master
     * strings.
     * 
     * @param file
     *            The file.
     * @return a list of {@link LocalizedString}.
     */
    @SuppressWarnings("unchecked")
    public List<LocalizedString> loadCompletedStrings(File file) {
        return criteria() //
                .add(Restrictions.eq("file", file)) //
                .add(Restrictions.eq("pending", Boolean.FALSE)) //
                .add(Restrictions.isNotNull("locale")) //
                .addOrder(Order.asc("key")) //
                .list();
    }

    public Set<String> loadMasterKeySet(File file) {
        StringBuilder q = new StringBuilder();
        q.append("select key from LocalizedString ");
        q.append("where file = :file ");
        q.append("and locale is null");

        @SuppressWarnings("unchecked")
        List<String> list = getSession() //
                .createQuery(q.toString()) //
                .setEntity("file", file) //
                .list();

        return new HashSet<String>(list);
    }
}