Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Commit

Permalink
Added time zone delivery in I18nProviderImpl.java
Browse files Browse the repository at this point in the history
Signed-off-by: Erdoan Hadzhiyusein <3rdoan@gmail.com>
  • Loading branch information
doandzhi committed Oct 6, 2017
1 parent ed20f39 commit 79f729d
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 19 deletions.
Expand Up @@ -8,10 +8,16 @@
package org.eclipse.smarthome.config.core.internal.i18n;

import java.net.URI;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand All @@ -23,29 +29,64 @@
* {@link ConfigOptionProvider} that provides a list of
*
* @author Simon Kaufmann - initial contribution and API
* @author Erdoan Hadzhiyusein - Added time zone
*
*/
@Component(immediate = true)
public class I18nConfigOptionsProvider implements ConfigOptionProvider {

private static final String NO_OFFSET_FORMAT = "(GMT) %s";
private static final String NEGATIVE_OFFSET_FORMAT = "%s (GMT%d:%02d)";
private static final String POSITIVE_OFFSET_FORMAT = "%s (GMT+%d:%02d)";

@Override
public Collection<ParameterOption> getParameterOptions(URI uri, String param, Locale locale) {
if (uri.toString().equals("system:i18n")) {
Locale translation = locale != null ? locale : Locale.getDefault();
if (param.equals("language")) {
return getAvailable(locale, l -> new ParameterOption(l.getLanguage(), l.getDisplayLanguage(translation)));
} else if (param.equals("region")) {
return getAvailable(locale, l -> new ParameterOption(l.getCountry(), l.getDisplayCountry(translation)));
} else if (param.equals("variant")) {
return getAvailable(locale, l -> new ParameterOption(l.getVariant(), l.getDisplayVariant(translation)));
}
return processParamType(param, locale, translation);
}
return null;
}

private Collection<ParameterOption> processParamType(String param, Locale locale, Locale translation) {
switch (param) {
case "language":
return getAvailable(locale,
l -> new ParameterOption(l.getLanguage(), l.getDisplayLanguage(translation)));
case "region":
return getAvailable(locale,
l -> new ParameterOption(l.getCountry(), l.getDisplayCountry(translation)));
case "variant":
return getAvailable(locale,
l -> new ParameterOption(l.getVariant(), l.getDisplayVariant(translation)));
case "timezone":
return ZoneId.getAvailableZoneIds().stream().map(TimeZone::getTimeZone).sorted((tz1, tz2) -> {
return tz2.getRawOffset() - tz2.getRawOffset();
}).map(tz -> {
return new ParameterOption(tz.getID(), getTimeZoneRepresentation(tz));
}).collect(Collectors.toList());
default:
return null;
}
}

private static String getTimeZoneRepresentation(TimeZone tz) {
long hours = TimeUnit.MILLISECONDS.toHours(tz.getRawOffset());
long minutes = TimeUnit.MILLISECONDS.toMinutes(tz.getRawOffset()) - TimeUnit.HOURS.toMinutes(hours);
minutes = Math.abs(minutes);
final String result;
if (hours > 0) {
result = String.format(POSITIVE_OFFSET_FORMAT, tz.getID(), hours, minutes);
} else if (hours < 0) {
result = String.format(NEGATIVE_OFFSET_FORMAT, tz.getID(), hours, minutes);
} else {
result = String.format(NO_OFFSET_FORMAT, tz.getDisplayName(Locale.getDefault()));
}
return result;
}

private Collection<ParameterOption> getAvailable(Locale locale, Function<Locale, ParameterOption> mapFunction) {
return Arrays.stream(Locale.getAvailableLocales()).map(l -> mapFunction.apply(l)).distinct()
.sorted(Comparator.comparing(a -> a.getLabel())).collect(Collectors.toList());
}

}
Expand Up @@ -43,6 +43,14 @@
</description>
<advanced>true</advanced>
</parameter>
<parameter name="timezone" type="text" required="false">
<label>Time zone</label>
<description><![CDATA[
<p>A time zone can be set from the dropdown menu.</p>
<p>The underlying system's time zone is the default.</p>
]]>
</description>
</parameter>
<parameter name="location" type="text" required="false">
<context>location</context>
<label>Location</label>
Expand Down
@@ -0,0 +1,25 @@
/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.i18n;

import java.time.ZoneId;

/**
* This interface describes a provider for a location and time zone.
*
* @author Erdoan Hadzhiyusein - Initial contribution and API
*/
public interface TimeZoneProvider {

/**
* Provides access to the time zone property.
*
* @return the time zone set in the Paper UI and if there isn't one, the default time zone of the underlying system
*/
ZoneId getTimeZone();
}
Expand Up @@ -8,13 +8,16 @@
package org.eclipse.smarthome.core.internal.i18n;

import java.text.MessageFormat;
import java.time.ZoneId;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.TimeZone;

import org.apache.commons.lang.StringUtils;
import org.eclipse.smarthome.core.i18n.LocaleProvider;
import org.eclipse.smarthome.core.i18n.LocationProvider;
import org.eclipse.smarthome.core.i18n.TimeZoneProvider;
import org.eclipse.smarthome.core.i18n.TranslationProvider;
import org.eclipse.smarthome.core.library.types.PointType;
import org.osgi.framework.Bundle;
Expand Down Expand Up @@ -43,12 +46,14 @@
* @author Thomas Höfer - Added getText operation with arguments
* @author Markus Rathgeb - Initial contribution and API of LocaleProvider
* @author Stefan Triller - Initial contribution and API of LocationProvider
* @author Erdoan Hadzhiyusein - Added time zone
*
*/

@Component(immediate = true, configurationPid = "org.eclipse.smarthome.core.i18nprovider", property = {
"service.pid=org.eclipse.smarthome.core.i18nprovider", "service.config.description.uri:String=system:i18n",
"service.config.label:String=Regional Settings", "service.config.category:String=system" })
public class I18nProviderImpl implements TranslationProvider, LocaleProvider, LocationProvider {
public class I18nProviderImpl implements TranslationProvider, LocaleProvider, LocationProvider, TimeZoneProvider {

private final Logger logger = LoggerFactory.getLogger(getClass());

Expand All @@ -57,6 +62,7 @@ public class I18nProviderImpl implements TranslationProvider, LocaleProvider, Lo
private static final String SCRIPT = "script";
private static final String REGION = "region";
private static final String VARIANT = "variant";
private static final String TIMEZONE = "timezone";
private Locale locale;

// TranslationProvider
Expand All @@ -65,6 +71,7 @@ public class I18nProviderImpl implements TranslationProvider, LocaleProvider, Lo
// LocationProvider
private static final String LOCATION = "location";
private PointType location;
private ZoneId timeZone;

@Activate
@SuppressWarnings("unchecked")
Expand All @@ -87,16 +94,11 @@ protected synchronized void modified(Map<String, Object> config) {
final String region = (String) config.get(REGION);
final String variant = (String) config.get(VARIANT);
final String location = (String) config.get(LOCATION);
final ZoneId timeZone = (ZoneId) config.get(TIMEZONE);

if (location != null) {
try {
this.location = PointType.valueOf(location);
} catch (IllegalArgumentException e) {
// preserve old location or null if none was set before
logger.warn("Could not set new location, keeping old one: ", e.getMessage());
}
}

setTimeZone(timeZone);
setLocation(location);

if (StringUtils.isEmpty(language)) {
// at least the language must be defined otherwise the system default locale is used
logger.debug("No language set, fallback to default system locale");
Expand Down Expand Up @@ -135,14 +137,41 @@ protected synchronized void modified(Map<String, Object> config) {

locale = builder.build();

logger.info("Locale set to {}, Location set to {}", locale, this.location);
logger.info("Locale set to {}, Location set to {}, Time zone set to {}", locale, this.location, this.timeZone);
}

private void setLocation(final String location) {
if (location != null) {
try {
this.location = PointType.valueOf(location);
} catch (IllegalArgumentException e) {
// preserve old location or null if none was set before
logger.warn("Could not set new location, keeping old one: ", e);
}
}
}

private void setTimeZone(final ZoneId timeZone) {
if (timeZone != null) {
try {
this.timeZone = TimeZone.getTimeZone(timeZone).toZoneId();
} catch (IllegalArgumentException e) {
this.timeZone = TimeZone.getDefault().toZoneId();
logger.warn("Could not set a new time zone, the system's default time zone will be used ", e);
}
}
}

@Override
public PointType getLocation() {
return location;
}

@Override
public ZoneId getTimeZone() {
return this.timeZone;
}

@Override
public Locale getLocale() {
if (locale == null) {
Expand Down

0 comments on commit 79f729d

Please sign in to comment.