001/*
002 *  Copyright 2017 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.repository.metadata;
017
018import java.util.Collections;
019import java.util.LinkedHashMap;
020import java.util.List;
021import java.util.Locale;
022import java.util.Map;
023import java.util.Set;
024
025import org.apache.commons.lang3.LocaleUtils;
026
027import org.ametys.plugins.repository.AmetysRepositoryException;
028
029/**
030 * Helper methods for {@link MultilingualString} metadata
031 */
032public final class MultilingualStringHelper
033{
034    /** The default locale */
035    public static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
036 
037    private MultilingualStringHelper()
038    {
039        // Hide default constructor.
040    }
041    
042    /**
043     * Returns the closest non-empty value for a {@link MultilingualString} metadata in a given locale.
044     * If no close locale is found, return the value for {@link Locale#ENGLISH} if exists.<br>
045     * Otherwise, the value of first stored locale will be returned.<br>
046     * @param parentMetadata The metadata holder
047     * @param metadataName The metadata name
048     * @param locale The requested locale
049     * @return the closest non-empty localized value or <code>null</code> if not found.
050     * @throws AmetysRepositoryException if an errors occurs.
051     */
052    public static String getValue(CompositeMetadata parentMetadata, String metadataName, Locale locale) throws AmetysRepositoryException
053    {
054        if (parentMetadata.hasMetadata(metadataName))
055        {
056            MultilingualString multilingualString = parentMetadata.getMultilingualString(metadataName);
057            
058            return getValue(multilingualString, locale);
059        }
060        
061        return null;
062    }
063    
064    /**
065     * Returns the closest non-empty value for a {@link MultilingualString} in a given locale.
066     * If no close locale is found, return the value for {@link Locale#ENGLISH} if exists.<br>
067     * Otherwise, the value of first stored locale will be returned.<br>
068     * @param multilingualString The multilingual string
069     * @param locale The requested locale. Can be null.
070     * @return the closest non-empty localized value or <code>null</code> if not found.
071     * @throws AmetysRepositoryException if an errors occurs.
072     */
073    public static String getValue(MultilingualString multilingualString, Locale locale) throws AmetysRepositoryException
074    {
075        if (locale != null && multilingualString.hasLocale(locale))
076        {
077            return multilingualString.getValue(locale);
078        }
079        else
080        {
081            // Try to find the closest locale
082            List<Locale> closedLocales = localeLookupList(locale);
083            for (Locale closedLocale : closedLocales)
084            {
085                if (multilingualString.hasLocale(closedLocale))
086                {
087                    return multilingualString.getValue(closedLocale);
088                }
089            }
090            
091            // No locale found, get the first stored locale
092            Set<Locale> allLocales = multilingualString.getLocales();
093            if (!allLocales.isEmpty())
094            {
095                Locale firstLocale = allLocales.iterator().next();
096                return multilingualString.getValue(firstLocale);
097            }
098            
099            return null;
100        }
101    }
102    
103    /**
104     * Return the list of closest locales to search 
105     * @param locale  the locale to start from. If null, returns the default locale
106     * @return the unmodifiable list of Locale objects, 0 being locale, not null
107     */
108    public static List<Locale> localeLookupList(Locale locale)
109    {
110        if (locale != null)
111        {
112            return LocaleUtils.localeLookupList(locale, DEFAULT_LOCALE);
113        }
114        else
115        {
116            return Collections.singletonList(DEFAULT_LOCALE);
117        }
118    }
119    
120    /**
121     * Get the JSON representation of a {@link MultilingualString}
122     * @param multilingualString The multilingual string. Cannot be null.
123     * @return A map with the locales and values.
124     * @throws AmetysRepositoryException if an error occurs
125     */
126    public static Map<String, Object> toJson(MultilingualString multilingualString) throws AmetysRepositoryException
127    {
128        Map<String, Object> json = new LinkedHashMap<>();
129        
130        for (Locale locale : multilingualString.getLocales())
131        {
132            json.put(locale.toString(), multilingualString.getValue(locale));
133        }
134        
135        return json;
136    }
137}