/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library 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 2.1 of the License, or (at your option) * any later version. * * This library 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 Lesser General Public License for more * details. */ package com.liferay.dynamic.data.mapping.util; import com.liferay.dynamic.data.mapping.annotations.DDMForm; import com.liferay.dynamic.data.mapping.annotations.DDMFormField; import com.liferay.dynamic.data.mapping.model.DDMFormFieldOptions; import com.liferay.dynamic.data.mapping.model.DDMFormFieldValidation; import com.liferay.dynamic.data.mapping.model.LocalizedValue; import com.liferay.portal.kernel.language.LanguageUtil; import com.liferay.portal.kernel.util.AggregateResourceBundle; import com.liferay.portal.kernel.util.ArrayUtil; import com.liferay.portal.kernel.util.PortalClassLoaderUtil; import com.liferay.portal.kernel.util.ResourceBundleUtil; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.Objects; import java.util.ResourceBundle; import java.util.Set; /** * @author Marcellus Tavares */ public class DDMFormFieldFactoryHelper { public DDMFormFieldFactoryHelper(Method method) { _method = method; _ddmFormField = method.getAnnotation(DDMFormField.class); } public com.liferay.dynamic.data.mapping.model.DDMFormField createDDMFormField() { String name = getDDMFormFieldName(); String type = getDDMFormFieldType(); com.liferay.dynamic.data.mapping.model.DDMFormField ddmFormField = new com.liferay.dynamic.data.mapping.model.DDMFormField(name, type); Map<String, Object> properties = getProperties(); for (Map.Entry<String, Object> entry : properties.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); if (isLocalizableValue((String)value)) { value = getPropertyValue(value); } ddmFormField.setProperty(key, value); } ddmFormField.setDataType(getDDMFormFieldDataType()); ddmFormField.setDDMFormFieldOptions(getDDMFormFieldOptions()); ddmFormField.setDDMFormFieldValidation(getDDMFormFieldValidation()); ddmFormField.setLabel(getDDMFormFieldLabel()); ddmFormField.setLocalizable(isDDMFormFieldLocalizable()); ddmFormField.setPredefinedValue(getDDMFormFieldPredefinedValue()); ddmFormField.setRepeatable(isDDMFormFieldRepeatable()); ddmFormField.setRequired(isDDMFormFieldRequired()); ddmFormField.setTip(getDDMFormFieldTip()); ddmFormField.setVisibilityExpression( getDDMFormFieldVisibilityExpression()); if (Objects.equals(type, "fieldset")) { com.liferay.dynamic.data.mapping.model.DDMForm nestedDDMForm = _getNestedDDMForm(); ddmFormField.setNestedDDMFormFields( nestedDDMForm.getDDMFormFields()); } return ddmFormField; } protected void collectResourceBundles( Class<?> clazz, List<ResourceBundle> resourceBundles, Locale locale) { for (Class<?> interfaceClass : clazz.getInterfaces()) { collectResourceBundles(interfaceClass, resourceBundles, locale); } String resourceBundleBaseName = getResourceBundleBaseName(clazz); if (Validator.isNull(resourceBundleBaseName)) { return; } try { ResourceBundle resourceBundle = ResourceBundleUtil.getBundle( resourceBundleBaseName, locale, clazz.getClassLoader()); if (resourceBundle != null) { resourceBundles.add(resourceBundle); } } catch (MissingResourceException mre) { } } protected LocalizedValue createLocalizedValue(String property) { LocalizedValue localizedValue = new LocalizedValue(_defaultLocale); if (Validator.isNull(property)) { return localizedValue; } if (isLocalizableValue(property)) { String languageKey = extractLanguageKey(property); for (Locale availableLocale : _availableLocales) { localizedValue.addString( availableLocale, getLocalizedValue(availableLocale, languageKey)); } } else { localizedValue.addString(_defaultLocale, property); } return localizedValue; } protected String extractLanguageKey(String value) { return StringUtil.extractLast(value, StringPool.PERCENT); } protected String getDDMFormFieldDataType() { if (Validator.isNotNull(_ddmFormField.dataType())) { return _ddmFormField.dataType(); } Class<?> returnType = _getReturnType(); if (returnType.isAnnotationPresent(DDMForm.class)) { return StringPool.BLANK; } if (returnType.isAssignableFrom(boolean.class) || returnType.isAssignableFrom(Boolean.class)) { return "boolean"; } else if (returnType.isAssignableFrom(double.class) || returnType.isAssignableFrom(Double.class)) { return "double"; } else if (returnType.isAssignableFrom(float.class) || returnType.isAssignableFrom(Float.class)) { return "float"; } else if (returnType.isAssignableFrom(int.class) || returnType.isAssignableFrom(Integer.class)) { return "integer"; } else if (returnType.isAssignableFrom(long.class) || returnType.isAssignableFrom(Long.class)) { return "long"; } else if (returnType.isAssignableFrom(short.class) || returnType.isAssignableFrom(Short.class)) { return "short"; } else { return "string"; } } protected LocalizedValue getDDMFormFieldLabel() { return createLocalizedValue(_ddmFormField.label()); } protected String getDDMFormFieldName() { if (Validator.isNotNull(_ddmFormField.name())) { return _ddmFormField.name(); } return _method.getName(); } protected DDMFormFieldOptions getDDMFormFieldOptions() { DDMFormFieldOptions ddmFormFieldOptions = new DDMFormFieldOptions(); ddmFormFieldOptions.setDefaultLocale(_defaultLocale); String[] optionLabels = _ddmFormField.optionLabels(); String[] optionValues = _ddmFormField.optionValues(); if (ArrayUtil.isEmpty(optionLabels) || ArrayUtil.isEmpty(optionValues)) { return ddmFormFieldOptions; } for (int i = 0; i < optionLabels.length; i++) { String optionLabel = optionLabels[i]; if (isLocalizableValue(optionLabel)) { String languageKey = extractLanguageKey(optionLabel); ddmFormFieldOptions.addOptionLabel( optionValues[i], _defaultLocale, getLocalizedValue(_defaultLocale, languageKey)); } else { ddmFormFieldOptions.addOptionLabel( optionValues[i], _defaultLocale, optionLabel); } } return ddmFormFieldOptions; } protected LocalizedValue getDDMFormFieldPredefinedValue() { LocalizedValue localizedValue = new LocalizedValue(_defaultLocale); String predefinedValue = _ddmFormField.predefinedValue(); String fieldType = getDDMFormFieldType(); if (Validator.isNotNull(predefinedValue)) { localizedValue.addString(_defaultLocale, predefinedValue); } else if (fieldType.equals("checkbox")) { localizedValue.addString(_defaultLocale, Boolean.FALSE.toString()); } return localizedValue; } protected LocalizedValue getDDMFormFieldTip() { return createLocalizedValue(_ddmFormField.tip()); } protected String getDDMFormFieldType() { if (Validator.isNotNull(_ddmFormField.type())) { return _ddmFormField.type(); } Class<?> returnType = _getReturnType(); if (returnType.isAnnotationPresent(DDMForm.class)) { return "fieldset"; } if (returnType.isAssignableFrom(boolean.class) || returnType.isAssignableFrom(Boolean.class)) { return "checkbox"; } return "text"; } protected DDMFormFieldValidation getDDMFormFieldValidation() { DDMFormFieldValidation ddmFormFieldValidation = new DDMFormFieldValidation(); if (Validator.isNotNull(_ddmFormField.validationExpression())) { ddmFormFieldValidation.setExpression( _ddmFormField.validationExpression()); } if (Validator.isNotNull(_ddmFormField.validationErrorMessage())) { String validationErrorMessage = _ddmFormField.validationErrorMessage(); if (isLocalizableValue(validationErrorMessage)) { String languageKey = extractLanguageKey(validationErrorMessage); validationErrorMessage = getLocalizedValue( _defaultLocale, languageKey); } ddmFormFieldValidation.setErrorMessage(validationErrorMessage); } return ddmFormFieldValidation; } protected String getDDMFormFieldVisibilityExpression() { if (Validator.isNotNull(_ddmFormField.visibilityExpression())) { return _ddmFormField.visibilityExpression(); } return StringUtil.toUpperCase(StringPool.TRUE); } protected String getLocalizedValue(Locale locale, String value) { ResourceBundle resourceBundle = getResourceBundle(locale); return LanguageUtil.get(resourceBundle, value); } protected Map<String, Object> getProperties() { Map<String, Object> propertiesMap = new HashMap<>(); for (String property : _ddmFormField.properties()) { String key = StringUtil.extractFirst(property, StringPool.EQUAL); String value = StringUtil.extractLast(property, StringPool.EQUAL); propertiesMap.put(key, value); } return propertiesMap; } protected LocalizedValue getPropertyValue(Object value) { LocalizedValue localizedValue = new LocalizedValue(_defaultLocale); if (Validator.isNull(value)) { return localizedValue; } String valueString = (String)value; if (isLocalizableValue(valueString)) { String languageKey = extractLanguageKey(valueString); localizedValue.addString( _defaultLocale, getLocalizedValue(_defaultLocale, languageKey)); } else { localizedValue.addString(_defaultLocale, valueString); } return localizedValue; } protected ResourceBundle getResourceBundle(Locale locale) { List<ResourceBundle> resourceBundles = new ArrayList<>(); ResourceBundle portalResourceBundle = ResourceBundleUtil.getBundle( "content.Language", locale, PortalClassLoaderUtil.getClassLoader()); resourceBundles.add(portalResourceBundle); collectResourceBundles( _method.getDeclaringClass(), resourceBundles, locale); ResourceBundle[] resourceBundlesArray = resourceBundles.toArray( new ResourceBundle[resourceBundles.size()]); return new AggregateResourceBundle(resourceBundlesArray); } protected String getResourceBundleBaseName(Class<?> clazz) { if (!clazz.isAnnotationPresent(DDMForm.class)) { return null; } DDMForm ddmForm = clazz.getAnnotation(DDMForm.class); if (Validator.isNotNull(ddmForm.localization())) { return ddmForm.localization(); } return "content.Language"; } protected boolean isDDMFormFieldLocalizable() { Class<?> returnType = _method.getReturnType(); if (returnType.isAssignableFrom(LocalizedValue.class)) { return true; } return false; } protected boolean isDDMFormFieldRepeatable() { Class<?> returnType = _method.getReturnType(); if (returnType.isArray()) { return true; } return false; } protected boolean isDDMFormFieldRequired() { return _ddmFormField.required(); } protected boolean isLocalizableValue(String value) { if (StringUtil.startsWith(value, StringPool.PERCENT)) { return true; } return false; } protected void setAvailableLocales(Set<Locale> availableLocales) { _availableLocales = availableLocales; } protected void setDefaultLocale(Locale defaultLocale) { _defaultLocale = defaultLocale; } private com.liferay.dynamic.data.mapping.model.DDMForm _getNestedDDMForm() { Class<?> returnType = _getReturnType(); return DDMFormFactory.create(returnType); } private Class<?> _getReturnType() { Class<?> returnType = _method.getReturnType(); if (returnType.isArray()) { returnType = returnType.getComponentType(); } return returnType; } private Set<Locale> _availableLocales; private final DDMFormField _ddmFormField; private Locale _defaultLocale; private final Method _method; }