/**
* 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.DDMExpressionException;
import com.liferay.dynamic.data.mapping.expression.DDMExpressionFactory;
import com.liferay.dynamic.data.mapping.model.DDMForm;
import com.liferay.dynamic.data.mapping.model.DDMFormField;
import com.liferay.dynamic.data.mapping.model.DDMFormFieldOptions;
import com.liferay.dynamic.data.mapping.model.DDMFormFieldType;
import com.liferay.dynamic.data.mapping.model.DDMFormFieldValidation;
import com.liferay.dynamic.data.mapping.model.DDMFormRule;
import com.liferay.dynamic.data.mapping.model.LocalizedValue;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustNotDuplicateFieldName;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetAvailableLocales;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetDefaultLocale;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetDefaultLocaleAsAvailableLocale;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetFieldType;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetFieldsForForm;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetOptionsForField;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetValidAvailableLocalesForProperty;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetValidCharactersForFieldName;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetValidCharactersForFieldType;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetValidDefaultLocaleForProperty;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetValidFormRuleExpression;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetValidIndexType;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetValidValidationExpression;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException.MustSetValidVisibilityExpression;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidator;
import com.liferay.portal.kernel.bean.BeanPropertiesUtil;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.MapUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* @author Marcellus Tavares
*/
@Component(immediate = true)
public class DDMFormValidatorImpl implements DDMFormValidator {
@Override
public void validate(DDMForm ddmForm) throws DDMFormValidationException {
validateDDMFormLocales(ddmForm);
List<DDMFormField> ddmFormFields = ddmForm.getDDMFormFields();
if (ddmFormFields.isEmpty()) {
throw new MustSetFieldsForForm();
}
validateDDMFormFields(
ddmFormFields, new HashSet<String>(), ddmForm.getAvailableLocales(),
ddmForm.getDefaultLocale());
validateDDMFormRules(ddmForm.getDDMFormRules());
}
@Reference(unbind = "-")
protected void setDDMExpressionFactory(
DDMExpressionFactory ddmExpressionFactory) {
_ddmExpressionFactory = ddmExpressionFactory;
}
protected void validateDDMExpression(
String expressionType, String ddmExpressionString)
throws DDMFormValidationException {
if (Validator.isNull(ddmExpressionString)) {
return;
}
try {
_ddmExpressionFactory.createBooleanDDMExpression(
ddmExpressionString);
}
catch (DDMExpressionException ddmee) {
throw new MustSetValidFormRuleExpression(
expressionType, ddmExpressionString, ddmee);
}
}
protected void validateDDMFormAvailableLocales(
Set<Locale> availableLocales, Locale defaultLocale)
throws DDMFormValidationException {
if ((availableLocales == null) || availableLocales.isEmpty()) {
throw new MustSetAvailableLocales();
}
if (!availableLocales.contains(defaultLocale)) {
throw new MustSetDefaultLocaleAsAvailableLocale(defaultLocale);
}
}
protected void validateDDMFormFieldIndexType(DDMFormField ddmFormField)
throws DDMFormValidationException {
if (!ArrayUtil.contains(
_ddmFormFieldIndexTypes, ddmFormField.getIndexType())) {
throw new MustSetValidIndexType(ddmFormField.getName());
}
}
protected void validateDDMFormFieldName(
DDMFormField ddmFormField, Set<String> ddmFormFieldNames)
throws DDMFormValidationException {
Matcher matcher = _ddmFormFieldNamePattern.matcher(
ddmFormField.getName());
if (!matcher.matches()) {
throw new MustSetValidCharactersForFieldName(
ddmFormField.getName());
}
if (ddmFormFieldNames.contains(
StringUtil.toLowerCase(ddmFormField.getName()))) {
throw new MustNotDuplicateFieldName(ddmFormField.getName());
}
ddmFormFieldNames.add(StringUtil.toLowerCase(ddmFormField.getName()));
}
protected void validateDDMFormFieldOptions(
DDMFormField ddmFormField, Set<Locale> ddmFormAvailableLocales,
Locale ddmFormDefaultLocale)
throws DDMFormValidationException {
String fieldType = ddmFormField.getType();
if (!fieldType.equals(DDMFormFieldType.CHECKBOX_MULTIPLE) &&
!fieldType.equals(DDMFormFieldType.RADIO) &&
!fieldType.equals(DDMFormFieldType.SELECT)) {
return;
}
String dataSourceType = GetterUtil.getString(
ddmFormField.getProperty("dataSourceType"), "manual");
if (!Objects.equals(dataSourceType, "manual")) {
return;
}
DDMFormFieldOptions ddmFormFieldOptions =
ddmFormField.getDDMFormFieldOptions();
Set<String> optionValues = Collections.emptySet();
if (ddmFormFieldOptions != null) {
optionValues = ddmFormFieldOptions.getOptionsValues();
}
if (optionValues.isEmpty()) {
throw new MustSetOptionsForField(ddmFormField.getName());
}
for (String optionValue : ddmFormFieldOptions.getOptionsValues()) {
LocalizedValue localizedValue = ddmFormFieldOptions.getOptionLabels(
optionValue);
validateDDMFormFieldPropertyValue(
ddmFormField.getName(), "options", localizedValue,
ddmFormAvailableLocales, ddmFormDefaultLocale);
}
}
protected void validateDDMFormFieldPropertyValue(
String fieldName, String propertyName, LocalizedValue propertyValue,
Set<Locale> ddmFormAvailableLocales, Locale ddmFormDefaultLocale)
throws DDMFormValidationException {
if (!ddmFormDefaultLocale.equals(propertyValue.getDefaultLocale())) {
throw new MustSetValidDefaultLocaleForProperty(
fieldName, propertyName);
}
if (!ddmFormAvailableLocales.equals(
propertyValue.getAvailableLocales())) {
throw new MustSetValidAvailableLocalesForProperty(
fieldName, propertyName);
}
}
protected void validateDDMFormFields(
List<DDMFormField> ddmFormFields, Set<String> ddmFormFieldNames,
Set<Locale> ddmFormAvailableLocales, Locale ddmFormDefaultLocale)
throws DDMFormValidationException {
for (DDMFormField ddmFormField : ddmFormFields) {
validateDDMFormFieldName(ddmFormField, ddmFormFieldNames);
validateDDMFormFieldType(ddmFormField);
validateDDMFormFieldIndexType(ddmFormField);
validateDDMFormFieldOptions(
ddmFormField, ddmFormAvailableLocales, ddmFormDefaultLocale);
validateOptionalDDMFormFieldLocalizedProperty(
ddmFormField, "label", ddmFormAvailableLocales,
ddmFormDefaultLocale);
validateOptionalDDMFormFieldLocalizedProperty(
ddmFormField, "predefinedValue", ddmFormAvailableLocales,
ddmFormDefaultLocale);
validateOptionalDDMFormFieldLocalizedProperty(
ddmFormField, "tip", ddmFormAvailableLocales,
ddmFormDefaultLocale);
validateDDMFormFieldValidationExpression(ddmFormField);
validateDDMFormFieldVisibilityExpression(ddmFormField);
validateDDMFormFields(
ddmFormField.getNestedDDMFormFields(), ddmFormFieldNames,
ddmFormAvailableLocales, ddmFormDefaultLocale);
}
}
protected void validateDDMFormFieldType(DDMFormField ddmFormField)
throws DDMFormValidationException {
if (Validator.isNull(ddmFormField.getType())) {
throw new MustSetFieldType(ddmFormField.getName());
}
Matcher matcher = _ddmFormFieldTypePattern.matcher(
ddmFormField.getType());
if (!matcher.matches()) {
throw new MustSetValidCharactersForFieldType(
ddmFormField.getType());
}
}
protected void validateDDMFormFieldValidationExpression(
DDMFormField ddmFormField)
throws DDMFormValidationException {
DDMFormFieldValidation ddmFormFieldValidation =
ddmFormField.getDDMFormFieldValidation();
if (ddmFormFieldValidation == null) {
return;
}
String validationExpression = ddmFormFieldValidation.getExpression();
if (Validator.isNull(validationExpression)) {
return;
}
try {
_ddmExpressionFactory.createBooleanDDMExpression(
validationExpression);
}
catch (DDMExpressionException ddmee) {
throw new MustSetValidValidationExpression(
ddmFormField.getName(), validationExpression);
}
}
protected void validateDDMFormFieldVisibilityExpression(
DDMFormField ddmFormField)
throws DDMFormValidationException {
String visibilityExpression = ddmFormField.getVisibilityExpression();
if (Validator.isNull(visibilityExpression)) {
return;
}
try {
_ddmExpressionFactory.createBooleanDDMExpression(
visibilityExpression);
}
catch (DDMExpressionException ddmee) {
throw new MustSetValidVisibilityExpression(
ddmFormField.getName(), visibilityExpression);
}
}
protected void validateDDMFormLocales(DDMForm ddmForm)
throws DDMFormValidationException {
Locale defaultLocale = ddmForm.getDefaultLocale();
if (defaultLocale == null) {
throw new MustSetDefaultLocale();
}
validateDDMFormAvailableLocales(
ddmForm.getAvailableLocales(), defaultLocale);
}
protected void validateDDMFormRule(DDMFormRule ddmFormRule)
throws DDMFormValidationException {
for (String action : ddmFormRule.getActions()) {
validateDDMExpression("action", action);
}
validateDDMExpression("condition", ddmFormRule.getCondition());
}
protected void validateDDMFormRules(List<DDMFormRule> ddmFormRules)
throws DDMFormValidationException {
for (DDMFormRule ddmFormRule : ddmFormRules) {
validateDDMFormRule(ddmFormRule);
}
}
protected void validateOptionalDDMFormFieldLocalizedProperty(
DDMFormField ddmFormField, String propertyName,
Set<Locale> ddmFormAvailableLocales, Locale ddmFormDefaultLocale)
throws DDMFormValidationException {
LocalizedValue propertyValue =
(LocalizedValue)BeanPropertiesUtil.getObject(
ddmFormField, propertyName);
if (MapUtil.isEmpty(propertyValue.getValues())) {
return;
}
validateDDMFormFieldPropertyValue(
ddmFormField.getName(), propertyName, propertyValue,
ddmFormAvailableLocales, ddmFormDefaultLocale);
}
private DDMExpressionFactory _ddmExpressionFactory;
private final String[] _ddmFormFieldIndexTypes =
new String[] {StringPool.BLANK, "keyword", "text"};
private final Pattern _ddmFormFieldNamePattern = Pattern.compile(
"([^\\p{Punct}|\\p{Space}$]|_)+");
private final Pattern _ddmFormFieldTypePattern = Pattern.compile(
"([^\\p{Punct}|\\p{Space}$]|[-_])+");
}