/**
* 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.validator.internal;
import com.liferay.dynamic.data.mapping.expression.DDMExpression;
import com.liferay.dynamic.data.mapping.expression.DDMExpressionException;
import com.liferay.dynamic.data.mapping.expression.DDMExpressionFactory;
import com.liferay.dynamic.data.mapping.form.field.type.DDMFormFieldTypeServicesTracker;
import com.liferay.dynamic.data.mapping.form.field.type.DDMFormFieldValueAccessor;
import com.liferay.dynamic.data.mapping.form.field.type.DDMFormFieldValueValidator;
import com.liferay.dynamic.data.mapping.model.DDMForm;
import com.liferay.dynamic.data.mapping.model.DDMFormField;
import com.liferay.dynamic.data.mapping.model.DDMFormFieldValidation;
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.dynamic.data.mapping.storage.FieldConstants;
import com.liferay.dynamic.data.mapping.validator.DDMFormValuesValidationException;
import com.liferay.dynamic.data.mapping.validator.DDMFormValuesValidationException.MustNotSetValue;
import com.liferay.dynamic.data.mapping.validator.DDMFormValuesValidationException.MustSetValidAvailableLocales;
import com.liferay.dynamic.data.mapping.validator.DDMFormValuesValidationException.MustSetValidDefaultLocale;
import com.liferay.dynamic.data.mapping.validator.DDMFormValuesValidationException.MustSetValidField;
import com.liferay.dynamic.data.mapping.validator.DDMFormValuesValidationException.MustSetValidValue;
import com.liferay.dynamic.data.mapping.validator.DDMFormValuesValidationException.MustSetValidValuesSize;
import com.liferay.dynamic.data.mapping.validator.DDMFormValuesValidationException.RequiredValue;
import com.liferay.dynamic.data.mapping.validator.DDMFormValuesValidator;
import com.liferay.portal.kernel.json.JSONFactory;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.MapUtil;
import com.liferay.portal.kernel.util.Validator;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
/**
* @author Marcellus Tavares
*/
@Component(immediate = true)
public class DDMFormValuesValidatorImpl implements DDMFormValuesValidator {
@Override
public void validate(DDMFormValues ddmFormValues)
throws DDMFormValuesValidationException {
DDMForm ddmForm = ddmFormValues.getDDMForm();
if (ddmForm == null) {
throw new NullPointerException("A DDM Form instance was never set");
}
traverseDDMFormFields(
ddmForm.getDDMFormFields(),
ddmFormValues.getDDMFormFieldValuesMap());
traverseDDMFormFieldValues(
ddmFormValues.getDDMFormFieldValues(),
ddmForm.getDDMFormFieldsMap(false));
}
@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY,
unbind = "removeDDMFormFieldValueValidator"
)
protected void addDDMFormFieldValueValidator(
DDMFormFieldValueValidator ddmFormFieldValueValidator,
Map<String, Object> properties) {
String type = MapUtil.getString(properties, "ddm.form.field.type.name");
if (Validator.isNull(type)) {
return;
}
_ddmFormFieldValueValidators.put(type, ddmFormFieldValueValidator);
}
protected boolean evaluateValidationExpression(
String expressionString, String ddmFormFieldName, String dataType,
String valueString)
throws DDMFormValuesValidationException {
if (Validator.isNull(valueString)) {
return true;
}
try {
DDMExpression<Boolean> ddmExpression =
_ddmExpressionFactory.createBooleanDDMExpression(
expressionString);
if (dataType.equals(FieldConstants.INTEGER)) {
ddmExpression.setIntegerVariableValue(
ddmFormFieldName, GetterUtil.getInteger(valueString));
}
else if (dataType.equals(FieldConstants.BOOLEAN)) {
ddmExpression.setBooleanVariableValue(
ddmFormFieldName, GetterUtil.getBoolean(valueString));
}
else {
ddmExpression.setStringVariableValue(
ddmFormFieldName, valueString);
}
return ddmExpression.evaluate();
}
catch (DDMExpressionException ddmee) {
throw new DDMFormValuesValidationException(ddmee);
}
}
protected List<DDMFormFieldValue> getDDMFormFieldValuesByFieldName(
Map<String, List<DDMFormFieldValue>> ddmFormFieldValuesMap,
String fieldName) {
List<DDMFormFieldValue> ddmFormFieldValues = ddmFormFieldValuesMap.get(
fieldName);
if (ddmFormFieldValues == null) {
return Collections.emptyList();
}
return ddmFormFieldValues;
}
protected void invokeDDMFormFieldValueValidator(
DDMFormField ddmFormField, DDMFormFieldValue ddmFormFieldValue)
throws DDMFormValuesValidationException {
DDMFormFieldValueValidator ddmFormFieldValueValidator =
_ddmFormFieldValueValidators.get(ddmFormField.getType());
if (ddmFormFieldValueValidator == null) {
return;
}
try {
ddmFormFieldValueValidator.validate(
ddmFormField, ddmFormFieldValue.getValue());
}
catch (Exception e) {
throw new MustSetValidValue(ddmFormField.getName(), e);
}
}
protected boolean isNull(
DDMFormField ddmFormField,
DDMFormFieldValueAccessor<?> ddmFormFieldValueAccessor, Value value,
Locale locale) {
if (ddmFormFieldValueAccessor == null) {
return Validator.isNull(value.getString(locale));
}
return ddmFormFieldValueAccessor.isEmpty(ddmFormField, value, locale);
}
protected boolean isNull(DDMFormField ddmFormField, Value value) {
if (value == null) {
return true;
}
DDMFormFieldValueAccessor<?> ddmFormFieldValueAccessor =
_ddmFormFieldTypeServicesTracker.getDDMFormFieldValueAccessor(
ddmFormField.getType());
for (Locale availableLocale : value.getAvailableLocales()) {
if (isNull(
ddmFormField, ddmFormFieldValueAccessor, value,
availableLocale)) {
return true;
}
}
return false;
}
protected void removeDDMFormFieldValueValidator(
DDMFormFieldValueValidator ddmFormFieldValueValidator,
Map<String, Objects> properties) {
String type = MapUtil.getString(properties, "ddm.form.field.type.name");
_ddmFormFieldValueValidators.remove(type);
}
@Reference(unbind = "-")
protected void setDDMExpressionFactory(
DDMExpressionFactory ddmExpressionFactory) {
_ddmExpressionFactory = ddmExpressionFactory;
}
@Reference(unbind = "-")
protected void setDDMFormFieldTypeServicesTracker(
DDMFormFieldTypeServicesTracker ddmFormFieldTypeServicesTracker) {
_ddmFormFieldTypeServicesTracker = ddmFormFieldTypeServicesTracker;
}
@Reference(unbind = "-")
protected void setJSONFactory(JSONFactory jsonFactory) {
_jsonFactory = jsonFactory;
}
protected void traverseDDMFormFields(
List<DDMFormField> ddmFormFields,
Map<String, List<DDMFormFieldValue>> ddmFormFieldValuesMap)
throws DDMFormValuesValidationException {
for (DDMFormField ddmFormField : ddmFormFields) {
List<DDMFormFieldValue> ddmFormFieldValues =
getDDMFormFieldValuesByFieldName(
ddmFormFieldValuesMap, ddmFormField.getName());
validateDDMFormFieldValues(ddmFormField, ddmFormFieldValues);
for (DDMFormFieldValue ddmFormFieldValue : ddmFormFieldValues) {
traverseDDMFormFields(
ddmFormField.getNestedDDMFormFields(),
ddmFormFieldValue.getNestedDDMFormFieldValuesMap());
}
}
}
protected void traverseDDMFormFieldValues(
List<DDMFormFieldValue> ddmFormFieldValues,
Map<String, DDMFormField> ddmFormFieldsMap)
throws DDMFormValuesValidationException {
for (DDMFormFieldValue ddmFormFieldValue : ddmFormFieldValues) {
DDMFormField ddmFormField = ddmFormFieldsMap.get(
ddmFormFieldValue.getName());
if (Validator.isNotNull(ddmFormField)) {
validateDDMFormFieldValue(
ddmFormFieldsMap.get(ddmFormFieldValue.getName()),
ddmFormFieldValue);
traverseDDMFormFieldValues(
ddmFormFieldValue.getNestedDDMFormFieldValues(),
ddmFormField.getNestedDDMFormFieldsMap());
}
}
}
protected void validateDDMFormFieldValidationExpression(
DDMFormField ddmFormField, Value value)
throws DDMFormValuesValidationException {
DDMFormFieldValidation ddmFormFieldValidation =
ddmFormField.getDDMFormFieldValidation();
if (ddmFormFieldValidation == null) {
return;
}
String validationExpression = ddmFormFieldValidation.getExpression();
if (Validator.isNull(validationExpression)) {
return;
}
for (Locale locale : value.getAvailableLocales()) {
boolean valid = evaluateValidationExpression(
validationExpression, ddmFormField.getName(),
ddmFormField.getDataType(), value.getString(locale));
if (!valid) {
throw new MustSetValidValue(ddmFormField.getName());
}
}
}
protected void validateDDMFormFieldValue(
DDMFormField ddmFormField, DDMFormFieldValue ddmFormFieldValue)
throws DDMFormValuesValidationException {
if (ddmFormField == null) {
throw new MustSetValidField(ddmFormFieldValue.getName());
}
DDMFormValues ddmFormValues = ddmFormFieldValue.getDDMFormValues();
validateDDMFormFieldValue(
ddmFormField, ddmFormValues.getAvailableLocales(),
ddmFormValues.getDefaultLocale(), ddmFormFieldValue.getValue());
invokeDDMFormFieldValueValidator(ddmFormField, ddmFormFieldValue);
traverseDDMFormFieldValues(
ddmFormFieldValue.getNestedDDMFormFieldValues(),
ddmFormField.getNestedDDMFormFieldsMap());
}
protected void validateDDMFormFieldValue(
DDMFormField ddmFormField, Set<Locale> availableLocales,
Locale defaultLocale, Value value)
throws DDMFormValuesValidationException {
if (Validator.isNull(ddmFormField.getDataType())) {
if (value != null) {
throw new MustNotSetValue(ddmFormField.getName());
}
}
else {
if ((value == null) ||
(ddmFormField.isRequired() && isNull(ddmFormField, value))) {
throw new RequiredValue(ddmFormField.getName());
}
if ((ddmFormField.isLocalizable() && !value.isLocalized()) ||
(!ddmFormField.isLocalizable() && value.isLocalized())) {
throw new MustSetValidValue(ddmFormField.getName());
}
validateDDMFormFieldValueLocales(
ddmFormField, availableLocales, defaultLocale, value);
validateDDMFormFieldValidationExpression(ddmFormField, value);
}
}
protected void validateDDMFormFieldValueLocales(
DDMFormField ddmFormField, Set<Locale> availableLocales,
Locale defaultLocale, Value value)
throws DDMFormValuesValidationException {
if (!value.isLocalized()) {
return;
}
if (!availableLocales.equals(value.getAvailableLocales())) {
throw new MustSetValidAvailableLocales(ddmFormField.getName());
}
if (!defaultLocale.equals(value.getDefaultLocale())) {
throw new MustSetValidDefaultLocale(ddmFormField.getName());
}
}
protected void validateDDMFormFieldValues(
DDMFormField ddmFormField,
List<DDMFormFieldValue> ddmFormFieldValues)
throws DDMFormValuesValidationException {
if (ddmFormField.isRequired() && ddmFormFieldValues.isEmpty()) {
throw new RequiredValue(ddmFormField.getName());
}
if (!ddmFormField.isRepeatable() && (ddmFormFieldValues.size() > 1)) {
throw new MustSetValidValuesSize(ddmFormField.getName());
}
}
private DDMExpressionFactory _ddmExpressionFactory;
private DDMFormFieldTypeServicesTracker _ddmFormFieldTypeServicesTracker;
private final Map<String, DDMFormFieldValueValidator>
_ddmFormFieldValueValidators = new ConcurrentHashMap<>();
private JSONFactory _jsonFactory;
}