com.liferay.journal.internal.util.JournalConverterImpl Maven / Gradle / Ivy
/**
* SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
*/
package com.liferay.journal.internal.util;
import com.liferay.dynamic.data.mapping.form.field.type.constants.DDMFormFieldTypeConstants;
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.DDMStructure;
import com.liferay.dynamic.data.mapping.model.LocalizedValue;
import com.liferay.dynamic.data.mapping.storage.Field;
import com.liferay.dynamic.data.mapping.storage.Fields;
import com.liferay.dynamic.data.mapping.storage.constants.FieldConstants;
import com.liferay.dynamic.data.mapping.util.DDM;
import com.liferay.dynamic.data.mapping.util.DDMFieldsCounter;
import com.liferay.journal.exception.ArticleContentException;
import com.liferay.journal.util.JournalConverter;
import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.json.JSONException;
import com.liferay.portal.kernel.json.JSONFactory;
import com.liferay.portal.kernel.json.JSONUtil;
import com.liferay.portal.kernel.language.Language;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.SetUtil;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.xml.Document;
import com.liferay.portal.kernel.xml.DocumentException;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.kernel.xml.SAXReaderUtil;
import com.liferay.portal.kernel.xml.XMLUtil;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* @author Marcellus Tavares
* @author Bruno Basto
*/
@Component(service = JournalConverter.class)
public class JournalConverterImpl implements JournalConverter {
@Override
public String getContent(
DDMStructure ddmStructure, Fields ddmFields, long groupId)
throws Exception {
Document document = getDocument(ddmStructure, ddmFields, groupId);
try {
return XMLUtil.stripInvalidChars(document.formattedString());
}
catch (Exception exception) {
throw new ArticleContentException(
"Unable to read content with an XML parser", exception);
}
}
@Override
public Fields getDDMFields(DDMStructure ddmStructure, String content)
throws PortalException {
try {
Document document = SAXReaderUtil.read(content);
Fields ddmFields = new Fields();
ddmFields.put(
new Field(
ddmStructure.getStructureId(), DDM.FIELDS_DISPLAY_NAME,
StringPool.BLANK));
DDMForm ddmForm = ddmStructure.getDDMForm();
Element rootElement = document.getRootElement();
String[] availableLanguageIds = StringUtil.split(
rootElement.attributeValue("available-locales"));
String defaultLanguageId = rootElement.attributeValue(
"default-locale");
for (DDMFormField ddmFormField : ddmForm.getDDMFormFields()) {
_addDDMFields(
availableLanguageIds, defaultLanguageId, ddmFields,
ddmFormField, ddmStructure, rootElement);
}
return ddmFields;
}
catch (DocumentException documentException) {
throw new PortalException(documentException);
}
}
@Override
public Document getDocument(
DDMStructure ddmStructure, Fields ddmFields, long groupId)
throws Exception {
Document document = SAXReaderUtil.createDocument();
Element rootElement = document.addElement("root");
rootElement.addAttribute(
"available-locales", _getAvailableLocales(ddmFields));
Locale defaultLocale = ddmFields.getDefaultLocale();
if (!_language.isAvailableLocale(groupId, defaultLocale)) {
defaultLocale = LocaleUtil.getSiteDefault();
}
rootElement.addAttribute(
"default-locale", LocaleUtil.toLanguageId(defaultLocale));
rootElement.addAttribute("version", "1.0");
DDMFieldsCounter ddmFieldsCounter = new DDMFieldsCounter();
DDMForm ddmForm = ddmStructure.getDDMForm();
for (DDMFormField ddmFormField : ddmForm.getDDMFormFields()) {
_updateDynamicElementElement(
ddmFields, ddmFieldsCounter, ddmFormField, rootElement, -1);
}
return document;
}
private void _addDDMFields(
String[] availableLanguageIds, String defaultLanguageId,
Fields ddmFields, DDMFormField ddmFormField,
DDMStructure ddmStructure, Element element)
throws PortalException {
List dynamicElementElements = _getDynamicElementElements(
element, ddmFormField.getName());
if (dynamicElementElements == null) {
if (Objects.equals(
ddmFormField.getType(),
DDMFormFieldTypeConstants.FIELDSET)) {
_updateFieldsDisplay(
ddmFields, ddmFormField.getName(),
StringUtil.randomString());
}
_addNestedDDMFields(
availableLanguageIds, defaultLanguageId, ddmFields,
ddmFormField, ddmStructure, element);
return;
}
for (Element dynamicElementElement : dynamicElementElements) {
if (!ddmFormField.isTransient()) {
Field ddmField = _getField(
dynamicElementElement, ddmStructure, availableLanguageIds,
defaultLanguageId);
String fieldName = ddmField.getName();
Field existingDDMField = ddmFields.get(fieldName);
if (existingDDMField != null) {
for (Locale locale : ddmField.getAvailableLocales()) {
existingDDMField.addValues(
locale, ddmField.getValues(locale));
}
}
else {
ddmFields.put(ddmField);
}
}
_updateFieldsDisplay(
ddmFields, ddmFormField.getName(),
dynamicElementElement.attributeValue("instance-id"));
_addNestedDDMFields(
availableLanguageIds, defaultLanguageId, ddmFields,
ddmFormField, ddmStructure, dynamicElementElement);
}
}
private void _addMissingFieldValues(
Field ddmField, String defaultLanguageId,
Set missingLanguageIds) {
if (missingLanguageIds.isEmpty()) {
return;
}
Locale defaultLocale = LocaleUtil.fromLanguageId(defaultLanguageId);
Serializable fieldValue = ddmField.getValue(defaultLocale);
for (String missingLanguageId : missingLanguageIds) {
Locale missingLocale = LocaleUtil.fromLanguageId(missingLanguageId);
ddmField.setValue(missingLocale, fieldValue);
}
}
private void _addNestedDDMFields(
String[] availableLanguageIds, String defaultLanguageId,
Fields ddmFields, DDMFormField ddmFormField,
DDMStructure ddmStructure, Element element)
throws PortalException {
for (DDMFormField nestedDDMFormField :
ddmFormField.getNestedDDMFormFields()) {
_addDDMFields(
availableLanguageIds, defaultLanguageId, ddmFields,
nestedDDMFormField, ddmStructure, element);
}
}
private int _countFieldRepetition(
Fields ddmFields, String fieldName, String parentFieldName,
int parentOffset)
throws Exception {
Field fieldsDisplayField = ddmFields.get(DDM.FIELDS_DISPLAY_NAME);
String[] fieldsDisplayValues = _getDDMFieldsDisplayValues(
fieldsDisplayField);
int offset = -1;
int repetitions = 0;
for (String fieldDisplayName : fieldsDisplayValues) {
if (offset > parentOffset) {
break;
}
if (fieldDisplayName.equals(parentFieldName)) {
offset++;
}
if (fieldDisplayName.equals(fieldName) &&
(offset == parentOffset)) {
repetitions++;
}
}
return repetitions;
}
private String _getAvailableLocales(Fields ddmFields) {
Set availableLocales = ddmFields.getAvailableLocales();
Locale[] availableLocalesArray = new Locale[availableLocales.size()];
availableLocalesArray = availableLocales.toArray(availableLocalesArray);
String[] languageIds = LocaleUtil.toLanguageIds(availableLocalesArray);
return StringUtil.merge(languageIds);
}
private Serializable _getCheckboxMultipleValue(
DDMFormField ddmFormField, Element dynamicContentElement) {
DDMFormFieldOptions ddmFormFieldOptions =
(DDMFormFieldOptions)ddmFormField.getProperty("options");
Map options = ddmFormFieldOptions.getOptions();
if (options.size() == 1) {
if (GetterUtil.getBoolean(dynamicContentElement.getText())) {
Set> entrySet =
options.entrySet();
Iterator> iterator =
entrySet.iterator();
Map.Entry entry = iterator.next();
return JSONUtil.putAll(
entry.getKey()
).toString();
}
return StringPool.BLANK;
}
return FieldConstants.getSerializable(
ddmFormField.getDataType(), dynamicContentElement.getText());
}
private String[] _getDDMFieldsDisplayValues(Field ddmFieldsDisplayField)
throws Exception {
try {
DDMStructure ddmStructure = ddmFieldsDisplayField.getDDMStructure();
List fieldsDisplayValues = new ArrayList<>();
String[] values = _splitFieldsDisplayValue(ddmFieldsDisplayField);
for (String value : values) {
String fieldName = StringUtil.extractFirst(
value, DDM.INSTANCE_SEPARATOR);
if (ddmStructure.hasField(fieldName)) {
fieldsDisplayValues.add(fieldName);
}
}
return fieldsDisplayValues.toArray(new String[0]);
}
catch (Exception exception) {
throw new PortalException(exception);
}
}
private List _getDynamicElementElements(
Element element, String name) {
Element parentElement = _getParentElement(element, name);
if (parentElement == null) {
return null;
}
List dynamicElementElements = null;
for (Element dynamicElement :
parentElement.elements("dynamic-element")) {
if (!Objects.equals(dynamicElement.attributeValue("name"), name)) {
continue;
}
if (dynamicElementElements == null) {
dynamicElementElements = new ArrayList<>();
}
dynamicElementElements.add(dynamicElement);
}
return dynamicElementElements;
}
private Field _getField(
Element dynamicElementElement, DDMStructure ddmStructure,
String[] availableLanguageIds, String defaultLanguageId)
throws PortalException {
Field ddmField = new Field();
ddmField.setDDMStructureId(ddmStructure.getStructureId());
Locale defaultLocale = null;
if (defaultLanguageId == null) {
defaultLocale = LocaleUtil.getSiteDefault();
}
else {
defaultLocale = LocaleUtil.fromLanguageId(defaultLanguageId);
}
ddmField.setDefaultLocale(defaultLocale);
String name = dynamicElementElement.attributeValue("name");
if (!GetterUtil.getBoolean(
ddmStructure.getFieldProperty(name, "localizable"))) {
availableLanguageIds = StringPool.EMPTY_ARRAY;
}
ddmField.setName(name);
DDMFormField ddmFormField = ddmStructure.getDDMFormField(name);
Set missingLanguageIds = SetUtil.fromArray(
availableLanguageIds);
missingLanguageIds.remove(defaultLanguageId);
List dynamicContentElements = dynamicElementElement.elements(
"dynamic-content");
for (Element dynamicContentElement : dynamicContentElements) {
Locale locale = defaultLocale;
String languageId = dynamicContentElement.attributeValue(
"language-id");
if (Validator.isNotNull(languageId)) {
locale = LocaleUtil.fromLanguageId(languageId, true, false);
if (locale == null) {
continue;
}
missingLanguageIds.remove(languageId);
}
Serializable serializable = _getFieldValue(
ddmFormField, dynamicContentElement);
ddmField.addValue(locale, serializable);
}
_addMissingFieldValues(ddmField, defaultLanguageId, missingLanguageIds);
return ddmField;
}
private String _getFieldInstanceId(
Fields ddmFields, String fieldName, int index) {
Field fieldsDisplayField = ddmFields.get(DDM.FIELDS_DISPLAY_NAME);
String prefix = fieldName.concat(DDM.INSTANCE_SEPARATOR);
String[] fieldsDisplayValues = StringUtil.split(
(String)fieldsDisplayField.getValue());
for (String fieldsDisplayValue : fieldsDisplayValues) {
if (fieldsDisplayValue.startsWith(prefix)) {
index--;
if (index < 0) {
return StringUtil.extractLast(
fieldsDisplayValue, DDM.INSTANCE_SEPARATOR);
}
}
}
return null;
}
private Serializable _getFieldValue(
DDMFormField ddmFormField, Element dynamicContentElement) {
if (Objects.equals(
DDMFormFieldTypeConstants.CHECKBOX_MULTIPLE,
ddmFormField.getType())) {
return _getCheckboxMultipleValue(
ddmFormField, dynamicContentElement);
}
if (Objects.equals(
DDMFormFieldTypeConstants.SELECT, ddmFormField.getType())) {
return _getSelectValue(dynamicContentElement);
}
String value = dynamicContentElement.getText();
return FieldConstants.getSerializable(
LocaleUtil.ROOT,
LocaleUtil.fromLanguageId(
dynamicContentElement.attributeValue("language-id")),
ddmFormField.getDataType(), value.trim());
}
private Element _getParentElement(Element element, String name) {
for (Element dynamicElement : element.elements("dynamic-element")) {
if (Objects.equals(dynamicElement.attributeValue("name"), name)) {
return element;
}
Element parentElement = _getParentElement(dynamicElement, name);
if (parentElement != null) {
return parentElement;
}
}
return null;
}
private String _getSelectValue(Element dynamicContentElement) {
JSONArray jsonArray = _jsonFactory.createJSONArray();
List optionElements = dynamicContentElement.elements("option");
if (!optionElements.isEmpty()) {
for (Element optionElement : optionElements) {
jsonArray.put(optionElement.getText());
}
}
else {
jsonArray.put(dynamicContentElement.getText());
}
return jsonArray.toString();
}
private String[] _splitFieldsDisplayValue(Field fieldsDisplayField) {
String value = (String)fieldsDisplayField.getValue();
return StringUtil.split(value);
}
private void _updateContentDynamicElement(
int count, DDMFormField ddmFormField, Element dynamicElementElement,
Field field) {
for (Locale locale : field.getAvailableLocales()) {
Serializable fieldValue = field.getValue(locale, count);
if (fieldValue == null) {
fieldValue = field.getValue(field.getDefaultLocale(), count);
}
String valueString = StringPool.BLANK;
if (fieldValue != null) {
valueString = String.valueOf(fieldValue);
}
if (StringUtil.equals(valueString, DDM.FIELD_EMPTY_VALUE)) {
continue;
}
Element dynamicContentElement = dynamicElementElement.addElement(
"dynamic-content");
dynamicContentElement.addAttribute(
"language-id", LocaleUtil.toLanguageId(locale));
_updateDynamicContentValue(
ddmFormField, dynamicContentElement, ddmFormField.getName(),
ddmFormField.getType(), valueString.trim(),
ddmFormField.isMultiple());
}
}
private void _updateDynamicContentValue(
DDMFormField ddmFormField, Element dynamicContentElement,
String fieldName, String fieldType, String fieldValue,
boolean multiple) {
if (Objects.equals(
DDMFormFieldTypeConstants.CHECKBOX_MULTIPLE, fieldType)) {
try {
DDMFormFieldOptions ddmFormFieldOptions =
(DDMFormFieldOptions)ddmFormField.getProperty("options");
Map options =
ddmFormFieldOptions.getOptions();
if (options.size() > 1) {
dynamicContentElement.addCDATA(fieldValue);
return;
}
JSONArray fieldValueJSONArray = _jsonFactory.createJSONArray(
fieldValue);
if (fieldValueJSONArray.length() == 1) {
fieldValue = Boolean.TRUE.toString();
}
else {
fieldValue = StringPool.BLANK;
}
}
catch (PortalException portalException) {
if (_log.isDebugEnabled()) {
_log.debug(
"Unable to get dynamic data mapping form field for " +
fieldName,
portalException);
}
}
dynamicContentElement.addCDATA(fieldValue);
}
else if (Objects.equals(DDMFormFieldTypeConstants.SELECT, fieldType) &&
Validator.isNotNull(fieldValue)) {
JSONArray jsonArray = null;
try {
jsonArray = _jsonFactory.createJSONArray(fieldValue);
}
catch (JSONException jsonException) {
if (_log.isDebugEnabled()) {
_log.debug("Unable to parse object", jsonException);
}
return;
}
if (multiple) {
for (int i = 0; i < jsonArray.length(); i++) {
Element optionElement = dynamicContentElement.addElement(
"option");
optionElement.addCDATA(jsonArray.getString(i));
}
}
else {
dynamicContentElement.addCDATA(
StringUtil.merge(
JSONUtil.toStringArray(jsonArray),
StringPool.COMMA_AND_SPACE));
}
}
else {
dynamicContentElement.addCDATA(fieldValue);
}
}
private void _updateDynamicElementElement(
Fields ddmFields, DDMFieldsCounter ddmFieldsCounter,
DDMFormField ddmFormField, Element dynamicElementElement,
int parentOffset)
throws Exception {
String fieldName = ddmFormField.getName();
int count = ddmFieldsCounter.get(fieldName);
int repetitions = _countFieldRepetition(
ddmFields, fieldName, dynamicElementElement.attributeValue("name"),
parentOffset);
for (int i = 0; i < repetitions; i++) {
Element childDynamicElementElement =
dynamicElementElement.addElement("dynamic-element");
childDynamicElementElement.addAttribute(
"field-reference", ddmFormField.getFieldReference());
childDynamicElementElement.addAttribute(
"index-type", ddmFormField.getIndexType());
childDynamicElementElement.addAttribute(
"instance-id",
_getFieldInstanceId(ddmFields, fieldName, count + i));
childDynamicElementElement.addAttribute("name", fieldName);
childDynamicElementElement.addAttribute(
"type", ddmFormField.getType());
List nestedDDMFormFields =
ddmFormField.getNestedDDMFormFields();
Field field = ddmFields.get(fieldName);
if (!Objects.equals(
ddmFormField.getType(),
DDMFormFieldTypeConstants.FIELDSET) &&
!ddmFormField.isTransient() && (field != null)) {
_updateContentDynamicElement(
ddmFieldsCounter.get(fieldName), ddmFormField,
childDynamicElementElement, field);
}
else if (ListUtil.isNotEmpty(nestedDDMFormFields)) {
for (DDMFormField nestedDDMFormField : nestedDDMFormFields) {
_updateDynamicElementElement(
ddmFields, ddmFieldsCounter, nestedDDMFormField,
childDynamicElementElement, count + i);
}
}
ddmFieldsCounter.incrementKey(fieldName);
}
}
private void _updateFieldsDisplay(
Fields ddmFields, String fieldName, String instanceId) {
if (Validator.isNull(instanceId)) {
instanceId = StringUtil.randomString();
}
String fieldsDisplayValue = StringBundler.concat(
fieldName, DDM.INSTANCE_SEPARATOR, instanceId);
Field fieldsDisplayField = ddmFields.get(DDM.FIELDS_DISPLAY_NAME);
String[] fieldsDisplayValues = StringUtil.split(
(String)fieldsDisplayField.getValue());
fieldsDisplayValues = ArrayUtil.append(
fieldsDisplayValues, fieldsDisplayValue);
fieldsDisplayField.setValue(StringUtil.merge(fieldsDisplayValues));
}
private static final Log _log = LogFactoryUtil.getLog(
JournalConverterImpl.class);
@Reference
private JSONFactory _jsonFactory;
@Reference
private Language _language;
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy