/**
* 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.DDMFormField;
import com.liferay.dynamic.data.mapping.model.DDMFormFieldType;
import com.liferay.dynamic.data.mapping.model.LocalizedValue;
import com.liferay.dynamic.data.mapping.model.Value;
import com.liferay.dynamic.data.mapping.storage.DDMFormFieldValue;
import com.liferay.dynamic.data.mapping.storage.DDMFormValues;
import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.json.JSONException;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.ProxyUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
/**
* @author Marcellus Tavares
*/
public class DDMFormInstanceFactory {
public static <T> T create(Class<T> clazz, DDMFormValues ddmFormValues) {
return create(clazz, ddmFormValues, ddmFormValues.getDefaultLocale());
}
public static <T> T create(
Class<T> clazz, DDMFormValues ddmFormValues, Locale locale) {
Object proxy = ProxyUtil.newProxyInstance(
clazz.getClassLoader(), new Class<?>[] {clazz},
new DDMFormInstanceInvocationHandler<>(
clazz, ddmFormValues, locale));
return clazz.cast(proxy);
}
private static class DDMFormInstanceInvocationHandler<T>
implements InvocationHandler {
public DDMFormInstanceInvocationHandler(
T clazz, DDMFormValues ddmFormValues, Locale locale) {
_clazz = clazz;
_ddmFormValues = ddmFormValues;
_ddmFormFieldValuesMap = ddmFormValues.getDDMFormFieldValuesMap();
_locale = locale;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if (!method.isAnnotationPresent(DDMFormField.class)) {
return null;
}
DDMFormFieldFactoryHelper ddmFormFieldFactoryHelper =
new DDMFormFieldFactoryHelper(method);
List<DDMFormFieldValue> ddmFormFieldValues =
_ddmFormFieldValuesMap.get(
ddmFormFieldFactoryHelper.getDDMFormFieldName());
if (ListUtil.isEmpty(ddmFormFieldValues)) {
LocalizedValue predefinedValue =
ddmFormFieldFactoryHelper.getDDMFormFieldPredefinedValue();
return convert(
method.getReturnType(),
ddmFormFieldFactoryHelper.getDDMFormFieldType(),
predefinedValue.getString(_locale));
}
else {
return convert(
method.getReturnType(),
ddmFormFieldFactoryHelper.getDDMFormFieldType(),
ddmFormFieldValues);
}
}
protected Object convert(
Class<?> returnType, String ddmFormFieldType,
List<DDMFormFieldValue> ddmFormFieldValues) {
if (returnType.isArray()) {
return toArray(
returnType.getComponentType(), ddmFormFieldType,
ddmFormFieldValues);
}
return toPrimitive(
returnType, ddmFormFieldType, ddmFormFieldValues.get(0));
}
protected Object convert(
Class<?> returnType, String ddmFormFieldType,
String predefinedValue) {
if (returnType.isArray()) {
return Array.newInstance(returnType.getComponentType(), 0);
}
if ((returnType == boolean.class) ||
(returnType == Boolean.class)) {
return GetterUtil.getBoolean(predefinedValue);
}
if ((returnType == double.class) || (returnType == Double.class)) {
return GetterUtil.getDouble(predefinedValue);
}
if ((returnType == float.class) || (returnType == Float.class)) {
return GetterUtil.getFloat(predefinedValue);
}
if ((returnType == int.class) || (returnType == Integer.class)) {
return GetterUtil.getInteger(predefinedValue);
}
if ((returnType == long.class) || (returnType == Long.class)) {
return GetterUtil.getLong(predefinedValue);
}
if ((returnType == short.class) || (returnType == Short.class)) {
return GetterUtil.getShort(predefinedValue);
}
if ((returnType == String.class) &&
Validator.isNotNull(predefinedValue)) {
return toString(ddmFormFieldType, predefinedValue);
}
return null;
}
protected String joinJSONArrayString(String valueString) {
if (Validator.isNull(valueString)) {
return valueString;
}
try {
JSONArray jsonArray = JSONFactoryUtil.createJSONArray(
valueString);
StringBundler sb = new StringBundler(jsonArray.length() * 2);
for (int i = 0; i < jsonArray.length(); i++) {
sb.append(jsonArray.getString(i));
sb.append(StringPool.COMMA);
}
if (sb.length() > 0) {
sb.setIndex(sb.index() - 1);
}
return sb.toString();
}
catch (JSONException jsone) {
return valueString;
}
}
protected Object toArray(
Class<?> returnType, String ddmFormFieldType,
List<DDMFormFieldValue> ddmFormFieldValues) {
Object array = Array.newInstance(
returnType, ddmFormFieldValues.size());
int i = 0;
for (DDMFormFieldValue ddmFormFieldValue : ddmFormFieldValues) {
Array.set(
array, i++,
toPrimitive(
returnType, ddmFormFieldType, ddmFormFieldValue));
}
return array;
}
protected boolean toBoolean(Value value) {
return Boolean.valueOf(value.getString(_locale));
}
protected double toDouble(Value value) {
return Double.valueOf(value.getString(_locale));
}
protected Object toDynamicForm(
Class<?> clazz, DDMFormFieldValue ddmFormFieldValue) {
DDMFormValues ddmFormValues = new DDMFormValues(
DDMFormFactory.create(clazz));
ddmFormValues.setAvailableLocales(
_ddmFormValues.getAvailableLocales());
ddmFormValues.setDefaultLocale(_ddmFormValues.getDefaultLocale());
ddmFormValues.setDDMFormFieldValues(
ddmFormFieldValue.getNestedDDMFormFieldValues());
Object proxy = ProxyUtil.newProxyInstance(
clazz.getClassLoader(), new Class<?>[] {clazz},
new DDMFormInstanceInvocationHandler<>(
clazz, ddmFormValues, _locale));
return clazz.cast(proxy);
}
protected float toFloat(Value value) {
return Float.valueOf(value.getString(_locale));
}
protected int toInteger(Value value) {
return Integer.valueOf(value.getString(_locale));
}
protected long toLong(Value value) {
return Long.valueOf(value.getString(_locale));
}
protected Object toPrimitive(
Class<?> returnType, String ddmFormFieldType,
DDMFormFieldValue ddmFormFieldValue) {
Value value = ddmFormFieldValue.getValue();
if ((returnType == boolean.class) ||
(returnType == Boolean.class)) {
return toBoolean(value);
}
if ((returnType == double.class) || (returnType == Double.class)) {
return toDouble(value);
}
if ((returnType == float.class) || (returnType == Float.class)) {
return toFloat(value);
}
if ((returnType == int.class) || (returnType == Integer.class)) {
return toInteger(value);
}
if ((returnType == long.class) || (returnType == Long.class)) {
return toLong(value);
}
if ((returnType == short.class) || (returnType == Short.class)) {
return toShort(value);
}
if (returnType == String.class) {
return toString(ddmFormFieldType, value.getString(_locale));
}
return toDynamicForm(returnType, ddmFormFieldValue);
}
protected short toShort(Value value) {
return Short.valueOf(value.getString(_locale));
}
protected String toString(String ddmFormFieldType, String valueString) {
if (Objects.equals(ddmFormFieldType, DDMFormFieldType.SELECT)) {
return joinJSONArrayString(valueString);
}
return valueString;
}
private final T _clazz;
private final Map<String, List<DDMFormFieldValue>>
_ddmFormFieldValuesMap;
private final DDMFormValues _ddmFormValues;
private final Locale _locale;
}
}