org.nuiton.jaxx.compiler.I18nHelper Maven / Gradle / Ivy
/*
* #%L
* JAXX :: Compiler
* %%
* Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.jaxx.compiler;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.CharUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import io.ultreia.java4all.i18n.I18n;
import org.nuiton.jaxx.compiler.reflect.ClassDescriptor;
import org.nuiton.jaxx.runtime.swing.SwingUtil;
/**
* I18n methods to add {@link I18n#t(String, Object...)} method on some attributes.
*
* Make sure to set an i18nable compiler to have his {@link CompilerConfiguration#isI18nable()} returning true.
*
* @author Tony Chemit - [email protected]
*/
public class I18nHelper {
protected static final Logger log = LogManager.getLogger(I18nHelper.class);
//FIXME Find a way to register mapping by class as it has been done in JAXXEngine but... Without any computation
//FIXME Just a place to register for each component i18n attributes, in that way it will be extendable
public static final List I18N_ATTRIBUTES = Arrays.asList("text",
"title",
"label",
"toolTipText",
"resetTip",
"openLinkTip",
"labelText",
"infoLabelTip");
/**
* FIXME We should use {@link JAXXEngine#getI18nProperty(ClassDescriptor)} to obtain this value
* Test if we have an active i18n attribute (says an i18n attribute on a i18neable compiler).
*
* @param attributeName name of attribute to test
* @param compiler current used compiler (contains options)
* @return true
if wa have an active i18n attribute, false
otherwise.
*/
public static boolean isI18nableAttribute(String attributeName, JAXXCompiler compiler) {
return compiler.getConfiguration().isI18nable() && isI18nAttribute(attributeName);
}
/**
* FIXME We should use {@link JAXXEngine#getI18nProperty(ClassDescriptor)} to obtain this value
* Test if we have an i18n attribute.
*
* @param attributeName name of attribute to test
* @return true
if wa have an active i18n attribute, false
otherwise.
*/
public static boolean isI18nAttribute(String attributeName) {
return I18N_ATTRIBUTES.contains(attributeName);
}
/**
* Add the i18n on a attribute.
*
* Note: Be ware : no test is done here to ensure we are on a i18neable attribute for an i18nable compiler.
*
* Make sure with the method {@link I18nHelper#isI18nableAttribute(String, JAXXCompiler)} returns
* true
before using this method.
*
* @param widgetId the id of the widget
* @param attributeName the name of the attribute
* @param attributeValueCode the value code of the attribute value
* @param compiler the current used compile
* @return the surrender i18n call if attribute name is match the
* attributeValueCode otherwise
*/
public static String addI18nInvocation(String widgetId, String attributeName, String attributeValueCode, JAXXCompiler compiler) {
if (log.isDebugEnabled()) {
log.debug(" try i18n support for [" + widgetId + ":" + attributeName + "] : " + attributeValueCode);
}
boolean doWarn = false;
int indexOf = attributeValueCode.indexOf("t(");
if (indexOf > -1 && !attributeValueCode.contains(",")) {
if (indexOf == 0) {
doWarn = true;
} else {
// make sure that the previous character is not alphabetical (means yet another method than t())
char charBefore = attributeValueCode.charAt(indexOf - 1);
if (CharUtils.isAsciiAlphanumeric(charBefore)) {
doWarn = false;
} else {
//TODO tchemit-2014-08-24 Maybe could we do better ?
doWarn = true;
}
}
}
if (doWarn) {
compiler.reportWarning("\n\tjaxx supports i18n, no need to add explicit call to I18n.t for attribute '" + attributeName + "' in component '" + widgetId + "' : [" + attributeValueCode + "]");
} else {
if (attributeValueCode.contains("(")) {
// we are probably in a databinding, this is not very safe, but this should be ok
return attributeValueCode;
}
compiler.addImport("static " + I18n.class.getName() + ".t");
compiler.getEngine().registerI18nKey(attributeValueCode.replaceAll("\"", ""));
attributeValueCode = "t(" + attributeValueCode + ")";
}
return attributeValueCode;
}
/**
* Box a i18n key with code to be used as a i18n mnemonic.
*
* Note: Be ware : no test is done here to ensure we are on a
* i18neable attribute for an i18nable compiler.
*
* @param object the object to use
* @param attributeName the name of the attribute
* @param attributeValueCode the value code of the attribute value
* @param compiler the current used compile
* @return the surrender i18n call if attribute name is match the
* attributeValueCode otherwise
* @since 2.6.11
*/
public static String addI18nMnemonicInvocation(CompiledObject object,
String attributeName,
String attributeValueCode,
JAXXCompiler compiler) {
String stringValue = I18nHelper.addI18nInvocation(
object.getId(),
attributeName,
attributeValueCode,
compiler);
compiler.addImport(SwingUtil.class.getName());
return "{" + SwingUtil.class.getSimpleName() + ".getFirstCharAt(" + stringValue + ",'Z')}";
}
public static void tryToRegisterI18nInvocation(JAXXCompiler compiler, String code) {
int indexOf = code.indexOf("t(\"");
if (indexOf == -1) {
indexOf = code.indexOf("n(\"");
}
if (indexOf > -1) {
if (indexOf>0) {
char c = code.charAt(indexOf-1);
if (Character.isLetter(c) || Character.isDigit(c)) {
return;
}
}
int lastIndex = code.indexOf("\"", indexOf + 3);
if (lastIndex > -1) {
String i18nKey = code.substring(indexOf + 3, lastIndex);
if (compiler.getEngine().isVerbose()) {
log.info(String.format("Detect i18n key: %s in %s", i18nKey, code));
}
compiler.getEngine().registerI18nKey(i18nKey);
}
}
}
public static boolean isDoubleList(ClassDescriptor object) {
return DOUBLE_LIST_TYPES.contains(object.getName());
}
public static boolean isNewDoubleList(ClassDescriptor object) {
return "io.ultreia.java4all.jaxx.widgets.list.DoubleList".equals(object.getName());
}
private static final Set DOUBLE_LIST_TYPES = ImmutableSet.of(
"io.ultreia.java4all.jaxx.widgets.list.DoubleList",
"org.nuiton.jaxx.widgets.select.FilterableDoubleList",
"org.nuiton.jaxx.widgets.extension.editor.ReferentialDoubleListBeanEditor"
);
}