Quarkus GraalVM native image DateTimeFormatter and Localization - date

I tried to use localization in java to print date with local style.
I already make a similar functionality with numbers and currencies but I failed to apply the same behavior to date.
As I learning when I posted this topics few days ago, GraalVM Quarkus Locale in native mode , use localization in native mode need to use create an "#AutomaticFeature".
This trick works for numbers and currencies :
#AutomaticFeature
public class NativeNumberFormatFeature implements Feature {
#Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
ImageSingletons
.lookup(RuntimeClassInitializationSupport.class)
.initializeAtBuildTime(NumberFormatSupport.class, this.getClass().getName());
ImageSingletons.add(NumberFormatSupport.class, new NumberFormatSupport());
}
}
public class NumberFormatSupport {
private Map<Locale, NumberFormat> numberInstancesByLocale;
private Map<Locale, Map<String, NumberFormat>> currencyInstancesByLocale;
public NumberFormatSupport() {
numberInstancesByLocale = new HashMap<>();
currencyInstancesByLocale = new HashMap<>();
for (Locale locale : Locale.getAvailableLocales()) {
numberInstancesByLocale.put(locale, NumberFormat.getNumberInstance(locale));
currencyInstancesByLocale.put(locale, new HashMap<>());
for (Currency currency : Currency.getAvailableCurrencies()) {
currencyInstancesByLocale.get(locale).put(currency.getCurrencyCode(), NumberFormat.getCurrencyInstance(locale));
currencyInstancesByLocale.get(locale).get(currency.getCurrencyCode()).setCurrency(currency);
}
}
}
public NumberFormat getNumberFormat(Locale locale) {
return (NumberFormat) numberInstancesByLocale.get(locale).clone();
}
public NumberFormat getCurrencyFormat(Locale locale, Currency currency) {
return (NumberFormat) currencyInstancesByLocale.get(locale).get(currency.getCurrencyCode()).clone();
}
}
But it's not works with DateTimeFormatter :
#AutomaticFeature
public class NativeDateFormatterFeature implements Feature {
#Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
ImageSingletons
.lookup(RuntimeClassInitializationSupport.class)
.initializeAtBuildTime(DateFormatterSupport.class, this.getClass().getName());
ImageSingletons.add(DateFormatterSupport.class, new DateFormatterSupport());
}
}
public class DateFormatterSupport {
private Map<Locale, DateTimeFormatter> dateTimeFormatterByLocale;
public DateFormatterSupport() {
dateTimeFormatterByLocale = Arrays.stream(Locale.getAvailableLocales()).collect(Collectors.toMap(
Function.identity(),
l -> DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(l)));
}
public DateTimeFormatter get(Locale locale) {
return dateTimeFormatterByLocale.get(locale);
}
}
In development mode all is ok but in native mode, locale is ignore. Style is always le same, month name isn't translate.
I was looking for a solution on google but i didn't find anything so I ask on StackOverflow.
I am at your disposal if needed.
Regards,
Stéphane.

I don't understand why, but the following solution works :
public class DateFormatterSupport {
private Map<Locale, DateTimeFormatter> dateTimeFormatterByLocale;
public DateFormatterSupport() {
dateTimeFormatterByLocale = Arrays.stream(Locale.getAvailableLocales()).collect(Collectors.toMap(
Function.identity(),
l -> DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(l)));
Arrays.stream(Locale.getAvailableLocales()).forEach(locale -> {
dateTimeFormatterByLocale.get(locale).format(LocalDate.now());
});
}
public DateTimeFormatter get(Locale locale) {
return dateTimeFormatterByLocale.get(locale);
}
}

Related

MapStruct use nested mapper based on input parameters

in this simple scenario I have a Pen that have a Color. I want to map the color of a pen using a nested mapper method instead of another, based on a variable input in the Pen mapper.
Color entity:
public class ColorEntity {
private Long colorId;
private String colorName;
}
Pen entity:
public class PenEntity {
private Long penId;
private String penArticle;
private ColorEntity color;
}
Color DTO:
public class ColorDTO {
private Long colorId;
private String colorName;
}
Pen DTO:
public class PenDTO {
private Long penId;
private String penArticle;
private ColorDTO color;
}
Color mapper: if I call ColorMapper.toDto(color, locale) the second method should be used.
#Mapper(componentModel = "spring")
public interface ColorMapper {
ColorDTO toDto(ColorEntity colorEntity);
default ColorDTO toDto(ColorEntity colorEntity, Locale locale) {
ColorDTO colorDTO = toDto(colorEntity);
if(locale.equals(Locale.ITALIAN)) {
colorDTO.setColorName("ROSSO");
}
else {
colorDTO.setColorName("Language not supported");
}
return colorDTO;
}
}
Pen mapper: same of ColorMapper, if I call PenMapper.toDto(pen, locale) the second method should be used.
#Mapper(componentModel = "spring", uses = {ColorMapper.class})
public interface PenMapper {
PenDTO toDto(PenEntity penEntity);
PenDTO toDto(PenEntity penEntity, Locale locale);
}
The problem is that in the generated PenMapperImpl, the method public PenDTO toDto(PenEntity penEntity, Locale locale) doesn't use the method ColorMapper.toDto(color, locale) to translate the color.
#Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2021-04-21T17:33:22+0200",
comments = "version: 1.4.2.Final, compiler: Eclipse JDT (IDE) 1.3.1200.v20200916-0645, environment: Java 15.0.2 (Oracle Corporation)"
)
#Component
public class PenMapperImpl implements PenMapper {
#Autowired
private ColorMapper colorMapper;
#Override
public PenDTO toDto(PenEntity penEntity) {
if ( penEntity == null ) {
return null;
}
PenDTO penDTO = new PenDTO();
penDTO.setColor( colorMapper.toDto( penEntity.getColor() ) );
penDTO.setPenArticle( penEntity.getPenArticle() );
penDTO.setPenId( penEntity.getPenId() );
return penDTO;
}
#Override
public PenDTO toDto(PenEntity penEntity, Locale locale) {
if ( penEntity == null && locale == null ) {
return null;
}
PenDTO penDTO = new PenDTO();
if ( penEntity != null ) {
// HERE SHOULD BE GENERATED THE
// penDTO.setColor( colorMapper.toDto( penEntity.getColor() , locale ) );
penDTO.setColor( colorMapper.toDto( penEntity.getColor() ) );
penDTO.setPenArticle( penEntity.getPenArticle() );
penDTO.setPenId( penEntity.getPenId() );
}
return penDTO;
}
}
How can I resolve this? I'm looking for a general solution (not puntual for this case) because I have a lot of this same situations in a project.
Thanks and regards
MapStruct does not use the input parameters when looking for methods in other mappers.
In order to achieve this you'll need to give some help to MapStruct.
The way to do this would be to use #Context. Using that MapStruct will propagate that to other mappers.
So in your case it will look something like:
#Mapper(componentModel = "spring")
public interface ColorMapper {
ColorDTO toDto(ColorEntity colorEntity);
default ColorDTO toDto(ColorEntity colorEntity, #Context Locale locale) {
ColorDTO colorDTO = toDto(colorEntity);
if(locale.equals(Locale.ITALIAN)) {
colorDTO.setColorName("ROSSO");
}
else {
colorDTO.setColorName("Language not supported");
}
return colorDTO;
}
}
#Mapper(componentModel = "spring", uses = {ColorMapper.class})
public interface PenMapper {
PenDTO toDto(PenEntity penEntity);
PenDTO toDto(PenEntity penEntity, #Context Locale locale);
}
This way when using the toDto with the Locale context MapStruct will choose the ColorMapper#toDto with the Locale.

Error : Cannot find Facebook SDK Version

the SDK 7.x is not working on Unity 5.1.0f3 , i always got the error version not found .
does someone have see this error ?
Actually, it's just a warning. But you can fix it.
There are several places where facebook plugin calls
FBBuildVersionAttribute.GetVersionAttributeOfType(typeof(AbstractFacebook));
So first, you need to modify FBBuildVersionAttribute to this:
// we are going to apply this attribute to Class
// instead of Assembly
// also make it inheritable for all implementations
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public class FBBuildVersionAttribute : Attribute
{
private DateTime buildDate;
private string buildHash;
private string buildVersion;
private string sdkVersion;
public DateTime Date { get { return buildDate; } }
public string Hash { get { return buildHash; } }
public string SdkVersion { get { return sdkVersion; } }
public string BuildVersion { get { return buildVersion; } }
public FBBuildVersionAttribute(string sdkVersion, string buildVersion)
{
this.buildVersion = buildVersion;
var parts = buildVersion.Split('.');
buildDate = DateTime.ParseExact(parts[0], "yyMMdd", System.Globalization.CultureInfo.InvariantCulture);
buildHash = parts[1];
this.sdkVersion = sdkVersion;
}
public override string ToString()
{
return buildVersion;
}
public static FBBuildVersionAttribute GetVersionAttributeOfType(Type type)
{
foreach (FBBuildVersionAttribute attribute in getAttributes(type))
{
return attribute;
}
return null;
}
private static FBBuildVersionAttribute[] getAttributes(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
// we want to get attributes from type instead of assmebly
return (FBBuildVersionAttribute[])(type.GetCustomAttributes(typeof(FBBuildVersionAttribute), false));
}
}
No you just need to add this attribute to AbstractFacebook:
[FBBuildVersionAttribute("7.0.1", "150604.98558e55096475c")]
public abstract class AbstractFacebook : MonoBehaviour
{
// ...
}
Note that 98558e55096475c part is trash string. It's not actual build hash, cause I don't have one.
Get the latest version of the FB Unity SDK. Change log says it's fixed now.
https://developers.facebook.com/docs/unity/change-log

Jersey2 Custom Date convertor

Has anyone created a CustomConvertor class for Jersey2 to convert
ISO 8601 dates to Date /Epoch time?
I pass date as query param in ISO_8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; I need to convert to epoch seconds. I have all that is necessary, I am lost in gluing it up.
I want the custom convertor to kick in once we see the DateEpochMarker interface. I use jersey 2
what is step which I am missing?
Could some one please help me out?
I have a customer Convertor, a marker Interface and resource method.
public class DateToEpochConvertor implements ParamConverter<Long> {
private static final String ISO_8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
#Override
public Long fromString(String value) {
DateFormat df1 = new SimpleDateFormat(ISO_8601_FORMAT);
Date date = new Date();
try {
date = df1.parse(value);
} catch (ParseException e) {
throw new WebApplicationException("The Date "+value+" is not in the ISO 8601 Format ");
}
return date.getTime();
}
#Override
public String toString(Long value) {
DateFormat df1 = new SimpleDateFormat(ISO_8601_FORMAT);
Date dt = new Date();
dt.setTime(value);
return df1.format(dt);
}
}
Marker Interface
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
public #interface DateEpochMarker {}
Resource Method
#GET
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#Path("/epochtime")
public Long getEpochTime(#DateEpochMarker #QueryParam("startTime") Long startEpochTime){
return startEpochTime;
}
I feel foolish to answer my own Question.
Somehow I was not been able to make the above working, what I ended up was using custom Jodatime Convertor.
Pasting the code so that anyone stumbling upon the same query might have a answer
#Provider
public class DateTimeParamConverterProvider implements ParamConverterProvider {
private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(DateTimeParamConverterProvider.class);
#Override
public <T> ParamConverter<T> getConverter(Class<T> type, Type genericType, Annotation[] annotations) {
if (type.equals(DateTime.class)) {
return (ParamConverter<T>) new DateTimeParamConverter();
} else {
return null;
}
}
private static class DateTimeParamConverter implements ParamConverter<DateTime> {
#Override
public DateTime fromString(String value) {
LOGGER.debug("The ISO Date that is provided is {}", value);
try {
return ISODateTimeFormat.dateTimeNoMillis().parseDateTime(value);
} catch (IllegalArgumentException e) {
return ISODateTimeFormat.dateTime().parseDateTime(value);
}
}
#Override
public String toString(DateTime value) {
return value.toString();
}
}
}

SuggestBox override addSelectionHandler

I have a custom Oracle with Objects to pass to the SuggestBox. Then I need get back a object when it's selected from de SuggestBox.
public HandlerRegistration addSelectionHandler(SelectionHandler<SuggestOracle.Suggestion> handler)
The problem is that I don't have Suggestion. I have "CustomSuggestion". I read de API and I try to write a Custom SuggestBox implementing the interface HasSelectionHandlers but I can't because the SuggestBox have a implementation of the interface. I get the error:
The interface HasSelectionHandlers cannot be implemented more than once with different arguments: HasSelectionHandlers<SuggestOracle.Suggestion> and HasSelectionHandlers<CustomSuggestion>
Can you help me? Sorry for my bad english.
Not sure I understand your problem. Have a look at the following example (really basic but you should get an idea on how to deal with custom suggestions). Hope that helps:
public void onModuleLoad() {
SuggestBox box = new SuggestBox(new CustomOracle<CustomSuggestion>());
box.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {
#Override
public void onSelection(SelectionEvent<Suggestion> event) {
String value = ((CustomSuggestion) event.getSelectedItem()).fSomeOtherValue;
Window.alert(value);
}
});
RootPanel.get().add(box);
}
private class CustomOracle<CustomSuggestion> extends SuggestOracle {
private LinkedList<Starter.CustomSuggestion> fStore;
public CustomOracle() {
fStore = new LinkedList<Starter.CustomSuggestion>();
fStore.add(new Starter.CustomSuggestion("2", "two", "foo"));
fStore.add(new Starter.CustomSuggestion("22", "twenty-two", "bar"));
fStore.add(new Starter.CustomSuggestion("222", "two-hundred twenty-two", "w000t"));
}
#Override
public void requestSuggestions(Request request, Callback callback) {
String query = request.getQuery();
LinkedList<Starter.CustomSuggestion> result = new LinkedList<Starter.CustomSuggestion>();
for (Starter.CustomSuggestion entry : fStore) {
if (entry.fDisplay.contains(query)) {
result.add(entry);
}
}
callback.onSuggestionsReady(request, new Response(result));
}
}
private class CustomSuggestion implements Suggestion {
private String fReplace;
private String fDisplay;
private String fSomeOtherValue;
public CustomSuggestion(String display, String replace, String someOtherValue) {
fDisplay = display;
fReplace = replace;
fSomeOtherValue = someOtherValue;
}
#Override
public String getDisplayString() {
return fDisplay;
}
#Override
public String getReplacementString() {
return fReplace;
}
}

Refactoring two basic classes

How would you refactor these two classes to abstract out the similarities? An abstract class? Simple inheritance? What would the refactored class(es) look like?
public class LanguageCode
{
/// <summary>
/// Get the lowercase two-character ISO 639-1 language code.
/// </summary>
public readonly string Value;
public LanguageCode(string language)
{
this.Value = new CultureInfo(language).TwoLetterISOLanguageName;
}
public static LanguageCode TryParse(string language)
{
if (language == null)
{
return null;
}
if (language.Length > 2)
{
language = language.Substring(0, 2);
}
try
{
return new LanguageCode(language);
}
catch (ArgumentException)
{
return null;
}
}
}
public class RegionCode
{
/// <summary>
/// Get the uppercase two-character ISO 3166 region/country code.
/// </summary>
public readonly string Value;
public RegionCode(string region)
{
this.Value = new RegionInfo(region).TwoLetterISORegionName;
}
public static RegionCode TryParse(string region)
{
if (region == null)
{
return null;
}
if (region.Length > 2)
{
region = region.Substring(0, 2);
}
try
{
return new RegionCode(region);
}
catch (ArgumentException)
{
return null;
}
}
}
It depends, if they are not going to do much more, then I would probably leave them as is - IMHO factoring out stuff is likely to be more complex, in this case.
Unless you have a strong reason for refactoring (because you are going to add more classes like those in near future) the penalty of changing the design for such a small and contrived example would overcome the gain in maintenance or overhead in this scenario. Anyhow here is a possible design based on generic and lambda expressions.
public class TwoLetterCode<T>
{
private readonly string value;
public TwoLetterCode(string value, Func<string, string> predicate)
{
this.value = predicate(value);
}
public static T TryParse(string value, Func<string, T> predicate)
{
if (value == null)
{
return default(T);
}
if (value.Length > 2)
{
value = value.Substring(0, 2);
}
try
{
return predicate(value);
}
catch (ArgumentException)
{
return default(T);
}
}
public string Value { get { return this.value; } }
}
public class LanguageCode : TwoLetterCode<LanguageCode> {
public LanguageCode(string language)
: base(language, v => new CultureInfo(v).TwoLetterISOLanguageName)
{
}
public static LanguageCode TryParse(string language)
{
return TwoLetterCode<LanguageCode>.TryParse(language, v => new LanguageCode(v));
}
}
public class RegionCode : TwoLetterCode<RegionCode>
{
public RegionCode(string language)
: base(language, v => new CultureInfo(v).TwoLetterISORegionName)
{
}
public static RegionCode TryParse(string language)
{
return TwoLetterCode<RegionCode>.TryParse(language, v => new RegionCode(v));
}
}
This is a rather simple question and to me smells awefully like a homework assignment.
You can obviously see the common bits in the code and I'm pretty sure you can make an attempt at it yourself by putting such things into a super-class.
You could maybe combine them into a Locale class, which stores both Language code and Region code, has accessors for Region and Language plus one parse function which also allows for strings like "en_gb"...
That's how I've seen locales be handled in various frameworks.
These two, as they stand, aren't going to refactor well because of the static methods.
You'd either end up with some kind of factory method on a base class that returns an a type of that base class (which would subsequently need casting) or you'd need some kind of additional helper class.
Given the amount of extra code and subsequent casting to the appropriate type, it's not worth it.
Create a generic base class (eg AbstractCode<T>)
add abstract methods like
protected T GetConstructor(string code);
override in base classes like
protected override RegionCode GetConstructor(string code)
{
return new RegionCode(code);
}
Finally, do the same with string GetIsoName(string code), eg
protected override GetIsoName(string code)
{
return new RegionCode(code).TowLetterISORegionName;
}
That will refactor the both. Chris Kimpton does raise the important question as to whether the effort is worth it.
I'm sure there is a better generics based solution. But still gave it a shot.
EDIT: As the comment says, static methods can't be overridden so one option would be to retain it and use TwoLetterCode objects around and cast them, but, as some other person has already pointed out, that is rather useless.
How about this?
public class TwoLetterCode {
public readonly string Value;
public static TwoLetterCode TryParseSt(string tlc) {
if (tlc == null)
{
return null;
}
if (tlc.Length > 2)
{
tlc = tlc.Substring(0, 2);
}
try
{
return new TwoLetterCode(tlc);
}
catch (ArgumentException)
{
return null;
}
}
}
//Likewise for Region
public class LanguageCode : TwoLetterCode {
public LanguageCode(string language)
{
this.Value = new CultureInfo(language).TwoLetterISOLanguageName;
}
public static LanguageCode TryParse(string language) {
return (LanguageCode)TwoLetterCode.TryParseSt(language);
}
}