All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.dynamic.data.mapping.service.impl.DDMStructureLocalServiceImpl Maven / Gradle / Ivy

The newest version!
/**
 * 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.dynamic.data.mapping.service.impl;

import com.liferay.depot.group.provider.SiteConnectedGroupGroupProvider;
import com.liferay.dynamic.data.mapping.constants.DDMStructureConstants;
import com.liferay.dynamic.data.mapping.constants.DDMTemplateConstants;
import com.liferay.dynamic.data.mapping.exception.DuplicateDDMStructureExternalReferenceCodeException;
import com.liferay.dynamic.data.mapping.exception.InvalidParentStructureException;
import com.liferay.dynamic.data.mapping.exception.InvalidStructureVersionException;
import com.liferay.dynamic.data.mapping.exception.NoSuchStructureException;
import com.liferay.dynamic.data.mapping.exception.NoSuchStructureLayoutException;
import com.liferay.dynamic.data.mapping.exception.RequiredStructureException;
import com.liferay.dynamic.data.mapping.exception.StructureDefinitionException;
import com.liferay.dynamic.data.mapping.exception.StructureDuplicateElementException;
import com.liferay.dynamic.data.mapping.exception.StructureDuplicateStructureKeyException;
import com.liferay.dynamic.data.mapping.exception.StructureNameException;
import com.liferay.dynamic.data.mapping.internal.constants.DDMDestinationNames;
import com.liferay.dynamic.data.mapping.internal.search.util.DDMSearchUtil;
import com.liferay.dynamic.data.mapping.internal.util.DDMFormTemplateSynchonizer;
import com.liferay.dynamic.data.mapping.io.DDMFormDeserializer;
import com.liferay.dynamic.data.mapping.io.DDMFormDeserializerDeserializeRequest;
import com.liferay.dynamic.data.mapping.io.DDMFormDeserializerDeserializeResponse;
import com.liferay.dynamic.data.mapping.io.DDMFormSerializer;
import com.liferay.dynamic.data.mapping.io.DDMFormSerializerSerializeRequest;
import com.liferay.dynamic.data.mapping.io.DDMFormSerializerSerializeResponse;
import com.liferay.dynamic.data.mapping.model.DDMDataProviderInstance;
import com.liferay.dynamic.data.mapping.model.DDMDataProviderInstanceLink;
import com.liferay.dynamic.data.mapping.model.DDMForm;
import com.liferay.dynamic.data.mapping.model.DDMFormField;
import com.liferay.dynamic.data.mapping.model.DDMFormLayout;
import com.liferay.dynamic.data.mapping.model.DDMFormRule;
import com.liferay.dynamic.data.mapping.model.DDMStructure;
import com.liferay.dynamic.data.mapping.model.DDMStructureLayout;
import com.liferay.dynamic.data.mapping.model.DDMStructureTable;
import com.liferay.dynamic.data.mapping.model.DDMStructureVersion;
import com.liferay.dynamic.data.mapping.model.DDMTemplate;
import com.liferay.dynamic.data.mapping.security.permission.DDMPermissionSupport;
import com.liferay.dynamic.data.mapping.service.DDMDataProviderInstanceLinkLocalService;
import com.liferay.dynamic.data.mapping.service.DDMDataProviderInstanceLocalService;
import com.liferay.dynamic.data.mapping.service.DDMStructureLayoutLocalService;
import com.liferay.dynamic.data.mapping.service.DDMStructureVersionLocalService;
import com.liferay.dynamic.data.mapping.service.DDMTemplateLocalService;
import com.liferay.dynamic.data.mapping.service.base.DDMStructureLocalServiceBaseImpl;
import com.liferay.dynamic.data.mapping.service.persistence.DDMDataProviderInstanceLinkPersistence;
import com.liferay.dynamic.data.mapping.service.persistence.DDMStructureLayoutPersistence;
import com.liferay.dynamic.data.mapping.service.persistence.DDMStructureLinkPersistence;
import com.liferay.dynamic.data.mapping.service.persistence.DDMStructureVersionPersistence;
import com.liferay.dynamic.data.mapping.service.persistence.DDMTemplatePersistence;
import com.liferay.dynamic.data.mapping.util.DDM;
import com.liferay.dynamic.data.mapping.util.DDMDataDefinitionConverter;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidationException;
import com.liferay.dynamic.data.mapping.validator.DDMFormValidator;
import com.liferay.exportimport.kernel.lar.ExportImportThreadLocal;
import com.liferay.journal.model.JournalArticle;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMap;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMapFactory;
import com.liferay.petra.sql.dsl.DSLFunctionFactoryUtil;
import com.liferay.petra.sql.dsl.DSLQueryFactoryUtil;
import com.liferay.petra.sql.dsl.Table;
import com.liferay.petra.sql.dsl.expression.Predicate;
import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.aop.AopService;
import com.liferay.portal.dao.orm.custom.sql.CustomSQL;
import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.exception.LocaleException;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.json.JSONFactory;
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.messaging.Message;
import com.liferay.portal.kernel.messaging.MessageBus;
import com.liferay.portal.kernel.model.ResourceConstants;
import com.liferay.portal.kernel.model.SystemEventConstants;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.module.service.Snapshot;
import com.liferay.portal.kernel.search.DDMStructureIndexer;
import com.liferay.portal.kernel.search.Indexable;
import com.liferay.portal.kernel.search.IndexableType;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.security.auth.CompanyThreadLocal;
import com.liferay.portal.kernel.service.ClassNameLocalService;
import com.liferay.portal.kernel.service.ResourceLocalService;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.service.UserLocalService;
import com.liferay.portal.kernel.service.permission.ModelPermissions;
import com.liferay.portal.kernel.systemevent.SystemEvent;
import com.liferay.portal.kernel.transaction.TransactionCommitCallbackUtil;
import com.liferay.portal.kernel.transaction.Transactional;
import com.liferay.portal.kernel.util.Constants;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.GroupThreadLocal;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.MapUtil;
import com.liferay.portal.kernel.util.OrderByComparator;
import com.liferay.portal.kernel.util.Portal;
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.workflow.WorkflowConstants;

import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

/**
 * Provides the local service for accessing, adding, deleting, and updating
 * dynamic data mapping (DDM) structures.
 *
 * 

* DDM structures (structures) are used in Liferay to store structured content * like document types, dynamic data definitions, or web contents. *

* *

* Structures support inheritance via parent structures. They also support * multi-language names and descriptions. *

* *

* Structures can be related to many models in Liferay, such as those for web * contents, dynamic data lists, and documents. This relationship can be * established via the model's class name ID. *

* * @author Brian Wing Shun Chan * @author Bruno Basto * @author Marcellus Tavares * @author Juan Fernández */ @Component( property = "model.class.name=com.liferay.dynamic.data.mapping.model.DDMStructure", service = AopService.class ) public class DDMStructureLocalServiceImpl extends DDMStructureLocalServiceBaseImpl { @Override public DDMStructure addStructure( long userId, long groupId, long classNameId, Map nameMap, Map descriptionMap, DDMForm ddmForm, DDMFormLayout ddmFormLayout, String storageType, ServiceContext serviceContext) throws PortalException { return addStructure( null, userId, groupId, DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID, classNameId, null, nameMap, descriptionMap, ddmForm, ddmFormLayout, storageType, DDMStructureConstants.TYPE_DEFAULT, serviceContext); } @Override public DDMStructure addStructure( long userId, long groupId, String parentStructureKey, long classNameId, String structureKey, Map nameMap, Map descriptionMap, DDMForm ddmForm, DDMFormLayout ddmFormLayout, String storageType, int type, ServiceContext serviceContext) throws PortalException { DDMStructure parentStructure = fetchStructure( groupId, classNameId, parentStructureKey); long parentStructureId = DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID; if (parentStructure != null) { parentStructureId = parentStructure.getStructureId(); } return addStructure( null, userId, groupId, parentStructureId, classNameId, structureKey, nameMap, descriptionMap, ddmForm, ddmFormLayout, storageType, type, serviceContext); } @Indexable(type = IndexableType.REINDEX) @Override public DDMStructure addStructure( String externalReferenceCode, long userId, long groupId, long parentStructureId, long classNameId, String structureKey, Map nameMap, Map descriptionMap, DDMForm ddmForm, DDMFormLayout ddmFormLayout, String storageType, int type, ServiceContext serviceContext) throws PortalException { // Structure User user = _userLocalService.getUser(userId); if (Validator.isNull(structureKey)) { structureKey = String.valueOf(counterLocalService.increment()); } else { structureKey = StringUtil.toUpperCase(structureKey.trim()); } if (classNameId == _classNameLocalService.getClassNameId( JournalArticle.class)) { long parentStructureLayoutId = 0; if (parentStructureId > 0) { DDMStructure ddmStructure = fetchDDMStructure( parentStructureId); parentStructureLayoutId = ddmStructure.getDefaultDDMStructureLayoutId(); } ddmForm = _ddmDataDefinitionConverter.convertDDMFormDataDefinition( ddmForm, parentStructureId, parentStructureLayoutId); if (ddmFormLayout != null) { ddmFormLayout = _ddmDataDefinitionConverter. convertDDMFormLayoutDataDefinition( ddmForm, ddmFormLayout); } } _validateExternalReferenceCode( externalReferenceCode, 0, groupId, classNameId); _validate( groupId, parentStructureId, classNameId, structureKey, nameMap, ddmForm); DDMStructure structure = _addStructure( externalReferenceCode, user, groupId, parentStructureId, classNameId, structureKey, nameMap, descriptionMap, ddmForm, storageType, type, serviceContext); // Resources if (serviceContext.isAddGroupPermissions() || serviceContext.isAddGuestPermissions()) { addStructureResources( structure, serviceContext.isAddGroupPermissions(), serviceContext.isAddGuestPermissions()); } else { addStructureResources( structure, serviceContext.getModelPermissions()); } // Structure version DDMStructureVersion structureVersion = _addStructureVersion( user, structure, DDMStructureConstants.VERSION_DEFAULT, serviceContext); // Structure layout if (ddmFormLayout != null) { DDMStructureLayout structureLayout = _ddmStructureLayoutLocalService.addStructureLayout( userId, groupId, structureVersion.getStructureVersionId(), ddmFormLayout, serviceContext); structureLayout.setClassNameId(structure.getClassNameId()); structureLayout.setStructureLayoutKey(structure.getStructureKey()); _ddmStructureLayoutLocalService.updateDDMStructureLayout( structureLayout); } // Data provider instance links _addDataProviderInstanceLinks( groupId, structure.getStructureId(), ddmForm); return structure; } @Indexable(type = IndexableType.REINDEX) @Override public DDMStructure addStructure( String externalReferenceCode, long userId, long groupId, long parentStructureId, long classNameId, String structureKey, Map nameMap, Map descriptionMap, String definition, String storageType, ServiceContext serviceContext) throws PortalException { User user = _userLocalService.getUser(userId); if (Validator.isNull(structureKey)) { structureKey = String.valueOf(counterLocalService.increment()); } else { structureKey = StringUtil.toUpperCase(structureKey.trim()); } _validateExternalReferenceCode( externalReferenceCode, 0, groupId, classNameId); DDMStructure structure = ddmStructurePersistence.create( counterLocalService.increment()); structure.setUuid(serviceContext.getUuid()); structure.setExternalReferenceCode(externalReferenceCode); structure.setGroupId(groupId); structure.setCompanyId(user.getCompanyId()); structure.setUserId(user.getUserId()); structure.setUserName(user.getFullName()); structure.setVersionUserId(user.getUserId()); structure.setVersionUserName(user.getFullName()); structure.setCreateDate(new Date()); structure.setModifiedDate(new Date()); structure.setParentStructureId(parentStructureId); structure.setClassNameId(classNameId); structure.setStructureKey(structureKey); structure.setVersion(DDMStructureConstants.VERSION_DEFAULT); structure.setNameMap(nameMap); structure.setDescriptionMap(descriptionMap); structure.setDefinition(definition); structure.setStorageType(storageType); structure.setType(DDMStructureConstants.TYPE_DEFAULT); structure = ddmStructurePersistence.update(structure); _addStructureVersion( user, structure, DDMStructureConstants.VERSION_DEFAULT, serviceContext); return structure; } /** * Adds the resources to the structure. * * @param structure the structure to add resources to * @param addGroupPermissions whether to add group permissions * @param addGuestPermissions whether to add guest permissions */ @Override public void addStructureResources( DDMStructure structure, boolean addGroupPermissions, boolean addGuestPermissions) throws PortalException { String resourceName = _ddmPermissionSupport.getStructureModelResourceName( structure.getClassName()); _resourceLocalService.addResources( structure.getCompanyId(), structure.getGroupId(), structure.getUserId(), resourceName, structure.getStructureId(), false, addGroupPermissions, addGuestPermissions); } /** * Adds the model resources with the permissions to the structure. * * @param structure the structure to add resources to * @param modelPermissions the model permissions to be added */ @Override public void addStructureResources( DDMStructure structure, ModelPermissions modelPermissions) throws PortalException { String resourceName = _ddmPermissionSupport.getStructureModelResourceName( structure.getClassName()); _resourceLocalService.addModelResources( structure.getCompanyId(), structure.getGroupId(), structure.getUserId(), resourceName, structure.getStructureId(), modelPermissions); } /** * Copies a structure, creating a new structure with all the values * extracted from the original one. The new structure supports a new name * and description. * * @param userId the primary key of the structure's creator/owner * @param sourceStructureId the primary key of the structure to be copied * @param nameMap the new structure's locales and localized names * @param descriptionMap the new structure's locales and localized * descriptions * @param serviceContext the service context to be applied. Can set the * UUID, creation date, modification date, guest permissions, and * group permissions for the structure. * @return the new structure */ @Indexable(type = IndexableType.REINDEX) @Override public DDMStructure copyStructure( long userId, long sourceStructureId, Map nameMap, Map descriptionMap, ServiceContext serviceContext) throws PortalException { // Structure User user = _userLocalService.getUser(userId); DDMStructure sourceStructure = ddmStructurePersistence.findByPrimaryKey( sourceStructureId); String structureKey = String.valueOf(counterLocalService.increment()); _validate( sourceStructure.getGroupId(), sourceStructure.getParentStructureId(), sourceStructure.getClassNameId(), structureKey, nameMap, sourceStructure.getDDMForm()); DDMStructure targetStructure = _addStructure( null, user, sourceStructure.getGroupId(), sourceStructure.getParentStructureId(), sourceStructure.getClassNameId(), structureKey, nameMap, descriptionMap, sourceStructure.getDDMForm(), sourceStructure.getStorageType(), sourceStructure.getType(), serviceContext); // Resources _resourceLocalService.copyModelResources( sourceStructure.getCompanyId(), _ddmPermissionSupport.getStructureModelResourceName( sourceStructure.getClassName()), sourceStructure.getPrimaryKey(), targetStructure.getPrimaryKey()); // Structure version DDMStructureVersion structureVersion = _addStructureVersion( user, targetStructure, DDMStructureConstants.VERSION_DEFAULT, serviceContext); // Structure layout if (sourceStructure.getDDMFormLayout() != null) { _ddmStructureLayoutLocalService.addStructureLayout( userId, sourceStructure.getGroupId(), targetStructure.getClassNameId(), targetStructure.getStructureKey(), structureVersion.getStructureVersionId(), sourceStructure.getDDMFormLayout(), serviceContext); } // Data provider instance links _addDataProviderInstanceLinks( sourceStructure.getGroupId(), targetStructure.getStructureId(), sourceStructure.getDDMForm()); return targetStructure; } @Indexable(type = IndexableType.REINDEX) @Override public DDMStructure copyStructure( long userId, long sourceStructureId, ServiceContext serviceContext) throws PortalException { DDMStructure sourceStructure = ddmStructurePersistence.findByPrimaryKey( sourceStructureId); return copyStructure( userId, sourceStructureId, sourceStructure.getNameMap(), sourceStructure.getDescriptionMap(), serviceContext); } /** * Deletes the structure and its resources. * *

* Before deleting the structure, this method verifies whether the structure * is required by another entity. If it is needed, an exception is thrown. *

* * @param structure the structure to be deleted */ @Indexable(type = IndexableType.DELETE) @Override @SystemEvent(type = SystemEventConstants.TYPE_DELETE) public DDMStructure deleteStructure(DDMStructure structure) throws PortalException { if (!GroupThreadLocal.isDeleteInProcess()) { int count = _ddmStructureLinkPersistence.countByStructureId( structure.getStructureId()); if (count > 0) { throw new RequiredStructureException. MustNotDeleteStructureReferencedByStructureLinks( structure.getStructureId()); } count = ddmStructurePersistence.countByParentStructureId( structure.getStructureId()); if (count > 0) { throw new RequiredStructureException. MustNotDeleteStructureThatHasChild( structure.getStructureId()); } count = _ddmTemplatePersistence.countByClassPK( structure.getStructureId()); if (count > 0) { throw new RequiredStructureException. MustNotDeleteStructureReferencedByTemplates( structure.getStructureId()); } } // Structure ddmStructurePersistence.remove(structure); // Data provider instance links _ddmDataProviderInstanceLinkPersistence.removeByStructureId( structure.getStructureId()); // Structure links _ddmStructureLinkPersistence.removeByStructureId( structure.getStructureId()); // Structure versions List structureVersions = _ddmStructureVersionLocalService.getStructureVersions( structure.getStructureId()); for (DDMStructureVersion structureVersion : structureVersions) { try { _ddmStructureLayoutPersistence.removeByStructureVersionId( structureVersion.getStructureVersionId()); } catch (NoSuchStructureLayoutException noSuchStructureLayoutException) { if (_log.isDebugEnabled()) { _log.debug(noSuchStructureLayoutException); } } _ddmStructureVersionPersistence.remove(structureVersion); } // Resources String resourceName = _ddmPermissionSupport.getStructureModelResourceName( structure.getClassName()); _resourceLocalService.deleteResource( structure.getCompanyId(), resourceName, ResourceConstants.SCOPE_INDIVIDUAL, structure.getStructureId()); return structure; } /** * Deletes the structure and its resources. * *

* Before deleting the structure, the system verifies whether the structure * is required by another entity. If it is needed, an exception is thrown. *

* * @param structureId the primary key of the structure to be deleted */ @Override public void deleteStructure(long structureId) throws PortalException { DDMStructure structure = ddmStructurePersistence.findByPrimaryKey( structureId); ddmStructureLocalService.deleteStructure(structure); } /** * Deletes the matching structure and its resources. * *

* Before deleting the structure, the system verifies whether the structure * is required by another entity. If it is needed, an exception is thrown. *

* * @param groupId the primary key of the group * @param classNameId the primary key of the class name for the structure's * related model * @param structureKey the unique string identifying the structure */ @Override public void deleteStructure( long groupId, long classNameId, String structureKey) throws PortalException { structureKey = _getStructureKey(structureKey); DDMStructure structure = ddmStructurePersistence.findByG_C_S( groupId, classNameId, structureKey); ddmStructureLocalService.deleteStructure(structure); } /** * Deletes all the structures of the group. * *

* Before deleting the structures, the system verifies whether each * structure is required by another entity. If any of the structures are * needed, an exception is thrown. *

* * @param groupId the primary key of the group */ @Override public void deleteStructures(long groupId) throws PortalException { List structures = ddmStructurePersistence.findByGroupId( groupId); _deleteStructures(structures); } @Override public void deleteStructures(long groupId, long classNameId) throws PortalException { List structures = ddmStructurePersistence.findByG_C( groupId, classNameId); _deleteStructures(structures); } /** * Returns the structure with the ID. * * @param structureId the primary key of the structure * @return the structure with the structure ID, or null if a * matching structure could not be found */ @Override public DDMStructure fetchStructure(long structureId) { return ddmStructurePersistence.fetchByPrimaryKey(structureId); } /** * Returns the structure matching the class name ID, structure key, and * group. * * @param groupId the primary key of the group * @param classNameId the primary key of the class name for the structure's * related model * @param structureKey the unique string identifying the structure * @return the matching structure, or null if a matching * structure could not be found */ @Override public DDMStructure fetchStructure( long groupId, long classNameId, String structureKey) { structureKey = _getStructureKey(structureKey); return ddmStructurePersistence.fetchByG_C_S( groupId, classNameId, structureKey); } /** * Returns the structure matching the class name ID, structure key, and * group, optionally searching ancestor sites (that have sharing enabled) * and global scoped sites. * *

* This method first searches in the group. If the structure is still not * found and includeAncestorStructures is set to * true, this method searches the group's ancestor sites (that * have sharing enabled) and lastly searches global scoped sites. *

* * @param groupId the primary key of the group * @param classNameId the primary key of the class name for the structure's * related model * @param structureKey the unique string identifying the structure * @param includeAncestorStructures whether to include ancestor sites (that * have sharing enabled) and include global scoped sites in the * search * @return the matching structure, or null if a matching * structure could not be found */ @Override public DDMStructure fetchStructure( long groupId, long classNameId, String structureKey, boolean includeAncestorStructures) { structureKey = _getStructureKey(structureKey); DDMStructure structure = ddmStructurePersistence.fetchByG_C_S( groupId, classNameId, structureKey); if (structure != null) { return structure; } if (!includeAncestorStructures) { return null; } for (long ancestorSiteGroupId : _getAncestorSiteAndDepotGroupIds(groupId)) { structure = ddmStructurePersistence.fetchByG_C_S( ancestorSiteGroupId, classNameId, structureKey); if (structure != null) { return structure; } } return null; } @Override public DDMStructure fetchStructureByExternalReferenceCode( String externalReferenceCode, long groupId, long classNameId) { return ddmStructurePersistence.fetchByERC_G_C( externalReferenceCode, groupId, classNameId); } @Override public DDMStructure fetchStructureByUuidAndGroupId( String uuid, long groupId, boolean includeAncestorStructures) { DDMStructure structure = ddmStructurePersistence.fetchByUUID_G( uuid, groupId); if (structure != null) { return structure; } if (!includeAncestorStructures) { return null; } for (long ancestorSiteGroupId : _getAncestorSiteAndDepotGroupIds(groupId)) { structure = ddmStructurePersistence.fetchByUUID_G( uuid, ancestorSiteGroupId); if (structure != null) { return structure; } } return null; } @Override public List getChildrenStructures(long parentStructureId) { return ddmStructurePersistence.findByParentStructureId( parentStructureId); } /** * Returns all the structures matching the class name ID. * * @param companyId the primary key of the structure's company * @param classNameId the primary key of the class name for the structure's * related model * @return the structures matching the class name ID */ @Override public List getClassStructures( long companyId, long classNameId) { return ddmStructurePersistence.findByC_C(companyId, classNameId); } /** * Returns a range of all the structures matching the class name ID. * *

* Useful when paginating results. Returns a maximum of end - * start instances. start and end are not * primary keys, they are indexes in the result set. Thus, 0 * refers to the first result in the set. Setting both start * and end to {@link QueryUtil#ALL_POS} will return the full * result set. *

* * @param companyId the primary key of the structure's company * @param classNameId the primary key of the class name for the structure's * related model * @param start the lower bound of the range of structures to return * @param end the upper bound of the range of structures to return (not * inclusive) * @return the range of matching structures */ @Override public List getClassStructures( long companyId, long classNameId, int start, int end) { return ddmStructurePersistence.findByC_C( companyId, classNameId, start, end); } /** * Returns all the structures matching the class name ID ordered by the * comparator. * * @param companyId the primary key of the structure's company * @param classNameId the primary key of the class name for the structure's * related model * @param orderByComparator the comparator to order the structures * (optionally null) * @return the matching structures ordered by the comparator */ @Override public List getClassStructures( long companyId, long classNameId, OrderByComparator orderByComparator) { return ddmStructurePersistence.findByC_C( companyId, classNameId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, orderByComparator); } /** * Returns the structure with the ID. * * @param structureId the primary key of the structure * @return the structure with the ID */ @Override public DDMStructure getStructure(long structureId) throws PortalException { return ddmStructurePersistence.findByPrimaryKey(structureId); } /** * Returns the structure matching the class name ID, structure key, and * group. * * @param groupId the primary key of the structure's group * @param classNameId the primary key of the class name for the structure's * related model * @param structureKey the unique string identifying the structure * @return the matching structure */ @Override public DDMStructure getStructure( long groupId, long classNameId, String structureKey) throws PortalException { structureKey = _getStructureKey(structureKey); return ddmStructurePersistence.findByG_C_S( groupId, classNameId, structureKey); } /** * Returns the structure matching the class name ID, structure key, and * group, optionally searching ancestor sites (that have sharing enabled) * and global scoped sites. * *

* This method first searches in the group. If the structure is still not * found and includeAncestorStructures is set to * true, this method searches the group's ancestor sites (that * have sharing enabled) and lastly searches global scoped sites. *

* * @param groupId the primary key of the structure's group * @param classNameId the primary key of the class name for the structure's * related model * @param structureKey the unique string identifying the structure * @param includeAncestorStructures whether to include ancestor sites (that * have sharing enabled) and include global scoped sites in the * search in the search * @return the matching structure */ @Override public DDMStructure getStructure( long groupId, long classNameId, String structureKey, boolean includeAncestorStructures) throws PortalException { structureKey = _getStructureKey(structureKey); DDMStructure structure = ddmStructurePersistence.fetchByG_C_S( groupId, classNameId, structureKey); if (structure != null) { return structure; } if (!includeAncestorStructures) { throw new NoSuchStructureException( "No DDMStructure exists with the structure key " + structureKey); } for (long curGroupId : _getAncestorSiteAndDepotGroupIds(groupId)) { structure = ddmStructurePersistence.fetchByG_C_S( curGroupId, classNameId, structureKey); if (structure != null) { return structure; } } throw new NoSuchStructureException( "No DDMStructure exists with the structure key " + structureKey + " in the ancestor groups"); } /** * Returns all the structures matching the group, name, and description. * * @param groupId the primary key of the structure's group * @param name the structure's name * @param description the structure's description * @return the matching structures */ @Override public List getStructure( long groupId, String name, String description) { return ddmStructurePersistence.findByG_N_D(groupId, name, description); } @Override public DDMStructure getStructureByExternalReferenceCode( String externalReferenceCode, long groupId, long classNameId) throws PortalException { return ddmStructurePersistence.findByERC_G_C( externalReferenceCode, groupId, classNameId); } @Override @Transactional(enabled = false) public DDMForm getStructureDDMForm(DDMStructure structure) throws PortalException { return _deserializeJSONDDMForm(structure.getDefinition()); } /** * Returns all the structures present in the system. * * @return the structures present in the system */ @Override public List getStructures() { return ddmStructurePersistence.findAll(); } /** * Returns all the structures present in the group. * * @param groupId the primary key of the group * @return the structures present in the group */ @Override public List getStructures(long groupId) { return ddmStructurePersistence.findByGroupId(groupId); } /** * Returns a range of all the structures belonging to the group. * *

* Useful when paginating results. Returns a maximum of end - * start instances. start and end are not * primary keys, they are indexes in the result set. Thus, 0 * refers to the first result in the set. Setting both start * and end to {@link QueryUtil#ALL_POS} will return the full * result set. *

* * @param groupId the primary key of the group * @param start the lower bound of the range of structures to return * @param end the upper bound of the range of structures to return (not * inclusive) * @return the range of matching structures */ @Override public List getStructures(long groupId, int start, int end) { return ddmStructurePersistence.findByGroupId(groupId, start, end); } /** * Returns all the structures matching class name ID and group. * * @param groupId the primary key of the group * @param classNameId the primary key of the class name for the structure's * related model * @return the matching structures */ @Override public List getStructures(long groupId, long classNameId) { return ddmStructurePersistence.findByG_C(groupId, classNameId); } /** * Returns a range of all the structures that match the class name ID and * group. * *

* Useful when paginating results. Returns a maximum of end - * start instances. start and end are not * primary keys, they are indexes in the result set. Thus, 0 * refers to the first result in the set. Setting both start * and end to {@link QueryUtil#ALL_POS} will return the full * result set. *

* * @param groupId the primary key of the group * @param classNameId the primary key of the class name for the structure's * related model * @param start the lower bound of the range of structures to return * @param end the upper bound of the range of structures to return (not * inclusive) * @return the range of matching structures */ @Override public List getStructures( long groupId, long classNameId, int start, int end) { return ddmStructurePersistence.findByG_C( groupId, classNameId, start, end); } /** * Returns an ordered range of all the structures matching the class name ID * and group. * *

* Useful when paginating results. Returns a maximum of end - * start instances. start and end are not * primary keys, they are indexes in the result set. Thus, 0 * refers to the first result in the set. Setting both start * and end to {@link QueryUtil#ALL_POS} will return the full * result set. *

* * @param groupId the primary key of the group * @param classNameId the primary key of the class name for the structure's * related model * @param start the lower bound of the range of structures to return * @param end the upper bound of the range of structures to return (not * inclusive) * @param orderByComparator the comparator to order the structures * (optionally null) * @return the range of matching structures ordered by the comparator */ @Override public List getStructures( long groupId, long classNameId, int start, int end, OrderByComparator orderByComparator) { return ddmStructurePersistence.findByG_C( groupId, classNameId, start, end, orderByComparator); } @Override public List getStructures( long companyId, long[] groupIds, long classNameId, int start, int end, OrderByComparator orderByComparator) { return getStructures( companyId, groupIds, classNameId, StringPool.BLANK, WorkflowConstants.STATUS_ANY, start, end, orderByComparator); } @Override public List getStructures( long companyId, long[] groupIds, long classNameId, String keywords, int status, int start, int end, OrderByComparator orderByComparator) { Table tempDDMStructureTable = DSLQueryFactoryUtil.selectDistinct( DDMStructureTable.INSTANCE.structureId ).from( DDMStructureTable.INSTANCE ).where( _getPredicate(companyId, groupIds, classNameId, keywords) ).as( "tempDDMStructure", DDMStructureTable.INSTANCE ); return ddmStructurePersistence.dslQuery( DSLQueryFactoryUtil.select( DDMStructureTable.INSTANCE ).from( tempDDMStructureTable ).innerJoinON( DDMStructureTable.INSTANCE, DDMStructureTable.INSTANCE.structureId.eq( tempDDMStructureTable.getColumn("structureId", Long.class)) ).orderBy( DDMStructureTable.INSTANCE, orderByComparator ).limit( start, end )); } @Override public List getStructures( long groupId, String name, String description) { return ddmStructurePersistence.findByG_N_D(groupId, name, description); } /** * Returns all the structures belonging to the groups. * * @param groupIds the primary keys of the groups * @return the structures belonging to the groups */ @Override public List getStructures(long[] groupIds) { return ddmStructurePersistence.findByGroupId(groupIds); } /** * Returns all the structures matching the class name ID and belonging to * the groups. * * @param groupIds the primary keys of the groups * @param classNameId the primary key of the class name for the structure's * related model * @return the matching structures */ @Override public List getStructures(long[] groupIds, long classNameId) { return ddmStructurePersistence.findByG_C(groupIds, classNameId); } /** * Returns a range of all the structures matching the class name ID and * belonging to the groups. * *

* Useful when paginating results. Returns a maximum of end - * start instances. start and end are not * primary keys, they are indexes in the result set. Thus, 0 * refers to the first result in the set. Setting both start * and end to {@link QueryUtil#ALL_POS} will return the full * result set. *

* * @param groupIds the primary keys of the groups * @param classNameId the primary key of the class name for the structure's * related model * @param start the lower bound of the range of structures to return * @param end the upper bound of the range of structures to return (not * inclusive) * @return the range of matching structures */ @Override public List getStructures( long[] groupIds, long classNameId, int start, int end) { return ddmStructurePersistence.findByG_C( groupIds, classNameId, start, end); } @Override public List getStructures( long[] groupIds, long classNameId, OrderByComparator orderByComparator) { return ddmStructurePersistence.findByG_C( groupIds, classNameId, QueryUtil.ALL_POS, QueryUtil.ALL_POS, orderByComparator); } /** * Returns an ordered range of all the structures matching the group, class * name ID, name, and description. * *

* Useful when paginating results. Returns a maximum of end - * start instances. start and end are not * primary keys, they are indexes in the result set. Thus, 0 * refers to the first result in the set. Setting both start * and end to {@link QueryUtil#ALL_POS} will return the full * result set. *

* * @param groupIds the primary keys of the groups * @param classNameId the primary key of the class name for the structure's * related model * @param name the name keywords * @param description the description keywords * @param start the lower bound of the range of structures to return * @param end the upper bound of the range of structures to return (not * inclusive) * @param orderByComparator the comparator to order the structures * (optionally null) * @return the range of matching structures ordered by the comparator */ @Override public List getStructures( long[] groupIds, long classNameId, String name, String description, int start, int end, OrderByComparator orderByComparator) { return ddmStructurePersistence.findByG_C_N_D( groupIds, classNameId, name, description, start, end, orderByComparator); } /** * Returns the number of structures belonging to the group. * * @param groupId the primary key of the group * @return the number of structures belonging to the group */ @Override public int getStructuresCount(long groupId) { return ddmStructurePersistence.countByGroupId(groupId); } /** * Returns the number of structures matching the class name ID and group. * * @param groupId the primary key of the group * @param classNameId the primary key of the class name for the structure's * related model * @return the number of matching structures */ @Override public int getStructuresCount(long groupId, long classNameId) { return ddmStructurePersistence.countByG_C(groupId, classNameId); } @Override public int getStructuresCount( long companyId, long[] groupIds, long classNameId, String keywords, int status) { return ddmStructurePersistence.dslQueryCount( DSLQueryFactoryUtil.countDistinct( DDMStructureTable.INSTANCE.structureId ).from( DDMStructureTable.INSTANCE ).where( _getPredicate(companyId, groupIds, classNameId, keywords) )); } /** * Returns the number of structures matching the class name ID and belonging * to the groups. * * @param groupIds the primary keys of the groups * @param classNameId the primary key of the class name for the structure's * related model * @return the number of matching structures */ @Override public int getStructuresCount(long[] groupIds, long classNameId) { return ddmStructurePersistence.countByG_C(groupIds, classNameId); } @Override public boolean hasStructure( long groupId, long classNameId, String structureKey) { structureKey = _getStructureKey(structureKey); int count = ddmStructurePersistence.countByG_C_S( groupId, classNameId, structureKey); if (count == 0) { return false; } return true; } @Override public String prepareLocalizedDefinitionForImport( DDMStructure structure, Locale defaultImportLocale) { DDMForm ddmForm = _ddm.updateDDMFormDefaultLocale( structure.getDDMForm(), defaultImportLocale); return _serializeJSONDDMForm(ddmForm); } @Override public void revertStructure( long userId, long structureId, String version, ServiceContext serviceContext) throws PortalException { DDMStructureVersion structureVersion = _ddmStructureVersionLocalService.getStructureVersion( structureId, version); if (!structureVersion.isApproved()) { throw new InvalidStructureVersionException( "Unable to revert from an unapproved file version"); } DDMStructure structure = structureVersion.getStructure(); serviceContext.setAttribute("majorVersion", Boolean.TRUE); serviceContext.setAttribute( "status", WorkflowConstants.STATUS_APPROVED); serviceContext.setCommand(Constants.REVERT); ddmStructureLocalService.updateStructure( userId, structure.getGroupId(), structureVersion.getParentStructureId(), structure.getClassNameId(), structure.getStructureKey(), structureVersion.getNameMap(), structureVersion.getDescriptionMap(), structureVersion.getDDMForm(), structureVersion.getDDMFormLayout(), serviceContext); } @Override public List search( long companyId, long[] groupIds, long classNameId, long classPK, String keywords, int start, int end, OrderByComparator orderByComparator) throws PortalException { SearchContext searchContext = DDMSearchUtil.buildStructureSearchContext( _ddmPermissionSupport, companyId, groupIds, classNameId, classPK, keywords, keywords, StringPool.BLANK, null, WorkflowConstants.STATUS_ANY, start, end, orderByComparator); return DDMSearchUtil.doSearch( searchContext, DDMStructure.class, ddmStructurePersistence::findByPrimaryKey); } /** * Returns an ordered range of all the structures matching the groups and * class name IDs, and matching the keywords in the structure names and * descriptions. * *

* Useful when paginating results. Returns a maximum of end - * start instances. start and end are not * primary keys, they are indexes in the result set. Thus, 0 * refers to the first result in the set. Setting both start * and end to {@link QueryUtil#ALL_POS} will return the full * result set. *

* * @param companyId the primary key of the structure's company * @param groupIds the primary keys of the groups * @param classNameId the primary key of the class name of the model the * structure is related to * @param keywords the keywords (space separated), which may occur in the * structure's name or description (optionally null) * @param start the lower bound of the range of structures to return * @param end the upper bound of the range of structures to return (not * inclusive) * @param orderByComparator the comparator to order the structures * (optionally null) * @return the range of matching structures ordered by the comparator */ @Override public List search( long companyId, long[] groupIds, long classNameId, String keywords, int status, int start, int end, OrderByComparator orderByComparator) { SearchContext searchContext = DDMSearchUtil.buildStructureSearchContext( _ddmPermissionSupport, companyId, groupIds, classNameId, null, keywords, keywords, StringPool.BLANK, null, status, start, end, orderByComparator); return DDMSearchUtil.doSearch( searchContext, DDMStructure.class, ddmStructurePersistence::findByPrimaryKey); } /** * Returns an ordered range of all the structures matching the groups, class * name IDs, name keyword, description keyword, storage type, and type. * *

* Useful when paginating results. Returns a maximum of end - * start instances. start and end are not * primary keys, they are indexes in the result set. Thus, 0 * refers to the first result in the set. Setting both start * and end to {@link QueryUtil#ALL_POS} will return the full * result set. *

* * @param companyId the primary key of the structure's company * @param groupIds the primary keys of the groups * @param classNameId the primary key of the class name of the model the * structure is related to * @param name the name keywords * @param description the description keywords * @param storageType the structure's storage type. It can be "xml" or * "expando". For more information, see {@link StorageType}. * @param type the structure's type. For more information, see {@link * DDMStructureConstants}. * @param andOperator whether every field must match its keywords, or just * one field * @param start the lower bound of the range of structures to return * @param end the upper bound of the range of structures to return (not * inclusive) * @param orderByComparator the comparator to order the structures * (optionally null) * @return the range of matching structures ordered by the comparator */ @Override public List search( long companyId, long[] groupIds, long classNameId, String name, String description, String storageType, int type, int status, boolean andOperator, int start, int end, OrderByComparator orderByComparator) { SearchContext searchContext = DDMSearchUtil.buildStructureSearchContext( _ddmPermissionSupport, companyId, groupIds, classNameId, null, name, description, storageType, type, status, start, end, orderByComparator); return DDMSearchUtil.doSearch( searchContext, DDMStructure.class, ddmStructurePersistence::findByPrimaryKey); } @Override public int searchCount( long companyId, long[] groupIds, long classNameId, long classPK, String keywords) throws PortalException { SearchContext searchContext = DDMSearchUtil.buildStructureSearchContext( _ddmPermissionSupport, companyId, groupIds, classNameId, classPK, keywords, keywords, StringPool.BLANK, null, WorkflowConstants.STATUS_ANY, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null); return DDMSearchUtil.doSearchCount(searchContext, DDMStructure.class); } /** * Returns the number of structures matching the groups and class name IDs, * and matching the keywords in the structure names and descriptions. * * @param companyId the primary key of the structure's company * @param groupIds the primary keys of the groups * @param classNameId the primary key of the class name of the model the * structure is related to * @param keywords the keywords (space separated), which may occur in the * structure's name or description (optionally null) * @return the number of matching structures */ @Override public int searchCount( long companyId, long[] groupIds, long classNameId, String keywords, int status) { SearchContext searchContext = DDMSearchUtil.buildStructureSearchContext( _ddmPermissionSupport, companyId, groupIds, classNameId, null, keywords, keywords, StringPool.BLANK, null, status, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null); return DDMSearchUtil.doSearchCount(searchContext, DDMStructure.class); } /** * Returns the number of structures matching the groups, class name IDs, * name keyword, description keyword, storage type, and type * * @param companyId the primary key of the structure's company * @param groupIds the primary keys of the groups * @param classNameId * @param name the name keywords * @param description the description keywords * @param storageType the structure's storage type. It can be "xml" or * "expando". For more information, see {@link StorageType}. * @param type the structure's type. For more information, see {@link * DDMStructureConstants}. * @param andOperator whether every field must match its keywords, or just * one field * @return the number of matching structures */ @Override public int searchCount( long companyId, long[] groupIds, long classNameId, String name, String description, String storageType, int type, int status, boolean andOperator) { SearchContext searchContext = DDMSearchUtil.buildStructureSearchContext( _ddmPermissionSupport, companyId, groupIds, classNameId, null, name, description, storageType, type, status, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null); return DDMSearchUtil.doSearchCount(searchContext, DDMStructure.class); } @Indexable(type = IndexableType.REINDEX) @Override public DDMStructure updateStructure( long userId, long structureId, DDMForm ddmForm, DDMFormLayout ddmFormLayout, ServiceContext serviceContext) throws PortalException { DDMStructure structure = ddmStructurePersistence.findByPrimaryKey( structureId); return _updateStructure( userId, structure.getParentStructureId(), structure.getNameMap(), structure.getDescriptionMap(), ddmForm, ddmFormLayout, serviceContext, structure); } @Indexable(type = IndexableType.REINDEX) @Override public DDMStructure updateStructure( long userId, long groupId, long parentStructureId, long classNameId, String structureKey, Map nameMap, Map descriptionMap, DDMForm ddmForm, DDMFormLayout ddmFormLayout, ServiceContext serviceContext) throws PortalException { structureKey = _getStructureKey(structureKey); DDMStructure structure = ddmStructurePersistence.findByG_C_S( groupId, classNameId, structureKey); return _updateStructure( userId, parentStructureId, nameMap, descriptionMap, ddmForm, ddmFormLayout, serviceContext, structure); } @Indexable(type = IndexableType.REINDEX) @Override public DDMStructure updateStructure( long userId, long structureId, long parentStructureId, Map nameMap, Map descriptionMap, DDMForm ddmForm, DDMFormLayout ddmFormLayout, ServiceContext serviceContext) throws PortalException { DDMStructure structure = ddmStructurePersistence.findByPrimaryKey( structureId); return _updateStructure( userId, parentStructureId, nameMap, descriptionMap, ddmForm, ddmFormLayout, serviceContext, structure); } @Indexable(type = IndexableType.REINDEX) @Override public DDMStructure updateStructure( String externalReferenceCode, long userId, long structureId, long groupId, long parentStructureId, long classNameId, String structureKey, Map nameMap, Map descriptionMap, String definition, ServiceContext serviceContext) throws PortalException { _validateExternalReferenceCode( externalReferenceCode, structureId, groupId, classNameId); DDMStructure structure = ddmStructurePersistence.findByPrimaryKey( structureId); structure.setExternalReferenceCode(externalReferenceCode); User user = _userLocalService.getUser(userId); structure.setUserId(userId); structure.setParentStructureId(parentStructureId); if (Validator.isNotNull(structureKey)) { structureKey = StringUtil.toUpperCase(structureKey.trim()); _validateStructureKey( structureId, structure.getGroupId(), structure.getClassNameId(), structureKey); structure.setStructureKey(structureKey); } DDMStructureVersion latestStructureVersion = _ddmStructureVersionLocalService.getLatestStructureVersion( structure.getStructureId()); structure.setVersion(latestStructureVersion.getVersion()); structure.setVersionUserId(user.getUserId()); structure.setVersionUserName(user.getFullName()); structure.setModifiedDate(new Date()); structure.setNameMap( nameMap, LocaleUtil.fromLanguageId(structure.getDefaultLanguageId())); structure.setDescriptionMap(descriptionMap); structure.setDefinition(definition); structure = ddmStructurePersistence.update(structure); _reindexStructure(structure, serviceContext); return structure; } @Activate protected void activate(BundleContext bundleContext) { _serviceTrackerMap = ServiceTrackerMapFactory.openSingleValueMap( bundleContext, DDMStructureIndexer.class, "ddm.structure.indexer.class.name"); } private void _addDataProviderInstanceLinks( long groupId, long structureId, DDMForm ddmForm) { Set dataProviderInstanceIds = _getDataProviderInstanceIds( groupId, ddmForm); for (Long dataProviderInstanceId : dataProviderInstanceIds) { _ddmDataProviderInstanceLinkLocalService. addDataProviderInstanceLink( dataProviderInstanceId, structureId); } } private DDMStructure _addStructure( String externalReferenceCode, User user, long groupId, long parentStructureId, long classNameId, String structureKey, Map nameMap, Map descriptionMap, DDMForm ddmForm, String storageType, int type, ServiceContext serviceContext) throws PortalException { DDMStructure structure = ddmStructurePersistence.create( counterLocalService.increment()); structure.setUuid(serviceContext.getUuid()); structure.setExternalReferenceCode(externalReferenceCode); structure.setGroupId(groupId); structure.setCompanyId(user.getCompanyId()); structure.setUserId(user.getUserId()); structure.setUserName(user.getFullName()); structure.setVersionUserId(user.getUserId()); structure.setVersionUserName(user.getFullName()); structure.setParentStructureId(parentStructureId); structure.setClassNameId(classNameId); structure.setStructureKey(structureKey); structure.setVersion(DDMStructureConstants.VERSION_DEFAULT); structure.setNameMap(nameMap, ddmForm.getDefaultLocale()); structure.setDescriptionMap(descriptionMap, ddmForm.getDefaultLocale()); structure.setDefinition(_serializeJSONDDMForm(ddmForm)); structure.setStorageType(storageType); structure.setType(type); return ddmStructurePersistence.update(structure); } private DDMStructureVersion _addStructureVersion( User user, DDMStructure structure, String version, ServiceContext serviceContext) { DDMStructureVersion structureVersion = _ddmStructureVersionPersistence.create( counterLocalService.increment()); structureVersion.setGroupId(structure.getGroupId()); structureVersion.setCompanyId(structure.getCompanyId()); structureVersion.setUserId(user.getUserId()); structureVersion.setUserName(user.getFullName()); structureVersion.setCreateDate(structure.getModifiedDate()); structureVersion.setStructureId(structure.getStructureId()); structureVersion.setVersion(version); structureVersion.setParentStructureId(structure.getParentStructureId()); structureVersion.setName(structure.getName()); structureVersion.setDescription(structure.getDescription()); structureVersion.setDefinition(structure.getDefinition()); structureVersion.setStorageType(structure.getStorageType()); structureVersion.setType(structure.getType()); structureVersion.setStatus( GetterUtil.getInteger( serviceContext.getAttribute("status"), WorkflowConstants.STATUS_APPROVED)); structureVersion.setStatusByUserId(user.getUserId()); structureVersion.setStatusByUserName(user.getFullName()); structureVersion.setStatusDate(structure.getModifiedDate()); return _ddmStructureVersionPersistence.update(structureVersion); } private Set _deleteStructures(List structures) throws PortalException { if (ListUtil.isEmpty(structures)) { return Collections.emptySet(); } Set deletedStructureIds = new HashSet<>(); for (DDMStructure structure : structures) { if (deletedStructureIds.contains(structure.getStructureId())) { continue; } if (!GroupThreadLocal.isDeleteInProcess()) { List childDDMStructures = ddmStructurePersistence.findByParentStructureId( structure.getStructureId()); deletedStructureIds.addAll( _deleteStructures(childDDMStructures)); } ddmStructureLocalService.deleteStructure(structure); deletedStructureIds.add(structure.getStructureId()); } return deletedStructureIds; } private DDMForm _deserializeDDMForm( String content, DDMFormDeserializer ddmFormDeserializer) { DDMFormDeserializerDeserializeRequest.Builder builder = DDMFormDeserializerDeserializeRequest.Builder.newBuilder(content); DDMFormDeserializerDeserializeResponse ddmFormDeserializerDeserializeResponse = ddmFormDeserializer.deserialize(builder.build()); return ddmFormDeserializerDeserializeResponse.getDDMForm(); } private DDMForm _deserializeJSONDDMForm(String content) { return _deserializeDDMForm(content, _jsonDDMFormDeserializer); } private long[] _getAncestorSiteAndDepotGroupIds(long groupId) { SiteConnectedGroupGroupProvider siteConnectedGroupGroupProvider = _siteConnectedGroupGroupProviderSnapshot.get(); try { if (siteConnectedGroupGroupProvider == null) { return _portal.getAncestorSiteGroupIds(groupId); } return siteConnectedGroupGroupProvider. getAncestorSiteAndDepotGroupIds(groupId, true); } catch (PortalException portalException) { _log.error(portalException); return new long[0]; } } private Set _getDataProviderInstanceIds( long groupId, DDMForm ddmForm) { Set dataProviderInstanceIds = new HashSet<>(); Map ddmFormFieldsMap = ddmForm.getDDMFormFieldsMap(true); for (DDMFormField ddmFormField : ddmFormFieldsMap.values()) { long[] ddmDataProviderInstanceIds = _getDDMDataProviderInstanceIds( ddmFormField.getProperty("ddmDataProviderInstanceId")); for (long ddmDataProviderInstanceId : ddmDataProviderInstanceIds) { if (ddmDataProviderInstanceId > 0) { dataProviderInstanceIds.add(ddmDataProviderInstanceId); } } } for (DDMFormRule ddmFormRule : ddmForm.getDDMFormRules()) { Set ddmFormDataProviderInstanceIds = _getDataProviderInstanceIds(groupId, ddmFormRule); dataProviderInstanceIds.addAll(ddmFormDataProviderInstanceIds); } return dataProviderInstanceIds; } private Set _getDataProviderInstanceIds( long groupId, DDMFormRule ddmFormRule) { List actions = ddmFormRule.getActions(); if (ListUtil.isEmpty(actions)) { return Collections.emptySet(); } Set dataProviderInstanceIds = new HashSet<>(); for (String action : actions) { Matcher matcher = _callFunctionPattern.matcher(action); while (matcher.find()) { String dataProviderUuid = matcher.group(1); DDMDataProviderInstance dataProviderInstance = _ddmDataProviderInstanceLocalService. fetchDDMDataProviderInstanceByUuidAndGroupId( dataProviderUuid, groupId); if (dataProviderInstance != null) { dataProviderInstanceIds.add( dataProviderInstance.getDataProviderInstanceId()); } } } return dataProviderInstanceIds; } private long[] _getDDMDataProviderInstanceIds(JSONArray jsonArray) { long[] ddmDataProviderInstanceIds = new long[jsonArray.length()]; for (int i = 0; i < jsonArray.length(); i++) { ddmDataProviderInstanceIds[i] = jsonArray.getLong(i); } return ddmDataProviderInstanceIds; } private long[] _getDDMDataProviderInstanceIds( Object ddmDataProviderInstanceId) { if (ddmDataProviderInstanceId instanceof JSONArray) { JSONArray jsonArray = (JSONArray)ddmDataProviderInstanceId; return _getDDMDataProviderInstanceIds(jsonArray); } else if (ddmDataProviderInstanceId instanceof String) { try { JSONArray jsonArray = _jsonFactory.createJSONArray( (String)ddmDataProviderInstanceId); return _getDDMDataProviderInstanceIds(jsonArray); } catch (Exception exception) { if (_log.isDebugEnabled()) { _log.debug(exception); } } } long ddmDataProviderInstanceIdLong = GetterUtil.getLong( ddmDataProviderInstanceId); if (ddmDataProviderInstanceIdLong > 0) { return new long[] {ddmDataProviderInstanceIdLong}; } return GetterUtil.DEFAULT_LONG_VALUES; } private Set _getDDMFormFieldsNames(DDMForm ddmForm) { Map ddmFormFieldsMap = ddmForm.getDDMFormFieldsMap(true); if (MapUtil.isEmpty(ddmFormFieldsMap)) { return Collections.emptySet(); } Set ddmFormFieldsNames = new HashSet<>(); for (String ddmFormFieldName : ddmFormFieldsMap.keySet()) { ddmFormFieldsNames.add(StringUtil.toLowerCase(ddmFormFieldName)); } return ddmFormFieldsNames; } private String _getNextVersion(String version, boolean majorVersion) { int[] versionParts = StringUtil.split(version, StringPool.PERIOD, 0); if (majorVersion) { versionParts[0]++; versionParts[1] = 0; } else { versionParts[1]++; } return versionParts[0] + StringPool.PERIOD + versionParts[1]; } private DDMForm _getParentDDMForm(long parentStructureId) { DDMStructure parentStructure = ddmStructurePersistence.fetchByPrimaryKey(parentStructureId); if (parentStructure == null) { return null; } return parentStructure.getFullHierarchyDDMForm(); } private Predicate _getPredicate( long companyId, long[] groupIds, long classNameId, String keywords) { Predicate predicate = DDMStructureTable.INSTANCE.companyId.eq( companyId ).and( DDMStructureTable.INSTANCE.classNameId.eq(classNameId) ).and( DDMStructureTable.INSTANCE.type.eq(0) ); Predicate groupIdsPredicate = null; for (long groupId : groupIds) { Predicate groupIdPredicate = DDMStructureTable.INSTANCE.groupId.eq( groupId); if (groupIdsPredicate == null) { groupIdsPredicate = groupIdPredicate; } else { groupIdsPredicate = groupIdsPredicate.or(groupIdPredicate); } } if (groupIdsPredicate != null) { predicate = predicate.and(groupIdsPredicate.withParentheses()); } Predicate keywordsPredicate = null; for (String keyword : _customSQL.keywords(keywords, true)) { if (keyword == null) { continue; } Predicate keywordPredicate = DSLFunctionFactoryUtil.lower( DSLFunctionFactoryUtil.castText(DDMStructureTable.INSTANCE.name) ).like( keyword ).or( DSLFunctionFactoryUtil.lower( DSLFunctionFactoryUtil.castClobText( DDMStructureTable.INSTANCE.description) ).like( keyword ) ); if (keywordsPredicate == null) { keywordsPredicate = keywordPredicate; } else { keywordsPredicate = keywordsPredicate.or(keywordPredicate); } } if (keywordsPredicate != null) { predicate = predicate.and(keywordsPredicate.withParentheses()); } return predicate; } private String _getStructureKey(String structureKey) { if (structureKey != null) { structureKey = structureKey.trim(); return StringUtil.toUpperCase(structureKey); } return StringPool.BLANK; } private List _getStructureTemplates( DDMStructure structure, String type) { return _ddmTemplateLocalService.getTemplates( structure.getGroupId(), _classNameLocalService.getClassNameId(DDMStructure.class), structure.getStructureId(), type); } private void _reindexStructure( DDMStructure structure, ServiceContext serviceContext) throws PortalException { if (!serviceContext.isIndexingEnabled()) { return; } DDMStructureIndexer ddmStructureIndexer = _serviceTrackerMap.getService( structure.getClassName()); if (ddmStructureIndexer == null) { return; } TransactionCommitCallbackUtil.registerCallback( () -> { Message message = new Message(); message.put("ddmStructureIndexer", ddmStructureIndexer); message.put("structureId", structure.getStructureId()); _messageBus.sendMessage( DDMDestinationNames.DDM_STRUCTURE_REINDEX, message); return null; }); } private String _serializeJSONDDMForm(DDMForm ddmForm) { DDMFormSerializerSerializeRequest.Builder builder = DDMFormSerializerSerializeRequest.Builder.newBuilder(ddmForm); DDMFormSerializerSerializeResponse ddmFormSerializerSerializeResponse = _jsonDDMFormSerializer.serialize(builder.build()); return ddmFormSerializerSerializeResponse.getContent(); } private void _syncStructureTemplatesFields(DDMStructure structure) { TransactionCommitCallbackUtil.registerCallback( () -> { DDMFormTemplateSynchonizer ddmFormTemplateSynchonizer = new DDMFormTemplateSynchonizer( structure.getDDMForm(), _jsonDDMFormDeserializer, _jsonDDMFormSerializer, _ddmTemplateLocalService); List templates = _getStructureTemplates( structure, DDMTemplateConstants.TEMPLATE_TYPE_FORM); ddmFormTemplateSynchonizer.setDDMFormTemplates(templates); ddmFormTemplateSynchonizer.synchronize(); return null; }); } private void _updateDataProviderInstanceLinks( long groupId, long structureId, DDMForm ddmForm) { Set dataProviderInstanceIds = _getDataProviderInstanceIds( groupId, ddmForm); List dataProviderInstanceLinks = _ddmDataProviderInstanceLinkLocalService. getDataProviderInstanceLinks(structureId); for (DDMDataProviderInstanceLink dataProviderInstanceLink : dataProviderInstanceLinks) { if (dataProviderInstanceIds.remove( dataProviderInstanceLink.getDataProviderInstanceId())) { continue; } _ddmDataProviderInstanceLinkLocalService. deleteDataProviderInstanceLink(dataProviderInstanceLink); } for (Long dataProviderInstanceId : dataProviderInstanceIds) { _ddmDataProviderInstanceLinkLocalService. addDataProviderInstanceLink( dataProviderInstanceId, structureId); } } private DDMStructure _updateStructure( long userId, long parentStructureId, Map nameMap, Map descriptionMap, DDMForm ddmForm, DDMFormLayout ddmFormLayout, ServiceContext serviceContext, DDMStructure structure) throws PortalException { // Structure User user = _userLocalService.getUser(userId); DDMForm parentDDMForm = _getParentDDMForm(parentStructureId); _validateParentStructure(structure.getStructureId(), parentStructureId); _validate(nameMap, parentDDMForm, ddmForm); structure.setUserId(userId); structure.setParentStructureId(parentStructureId); DDMStructureVersion latestStructureVersion = _ddmStructureVersionLocalService.getLatestStructureVersion( structure.getStructureId()); boolean updateVersion = false; if (latestStructureVersion.getStatus() == WorkflowConstants.STATUS_DRAFT) { updateVersion = true; } boolean majorVersion = GetterUtil.getBoolean( serviceContext.getAttribute("majorVersion")); String version = _getNextVersion( latestStructureVersion.getVersion(), majorVersion); if (!updateVersion) { structure.setVersionUserId(user.getUserId()); structure.setVersionUserName(user.getFullName()); structure.setVersion(version); } structure.setNameMap(nameMap, ddmForm.getDefaultLocale()); structure.setDescriptionMap(descriptionMap, ddmForm.getDefaultLocale()); structure.setDefinition(_serializeJSONDDMForm(ddmForm)); // Structure version DDMStructureVersion structureVersion; if (updateVersion) { latestStructureVersion.setDefinition(structure.getDefinition()); latestStructureVersion.setStatus( GetterUtil.getInteger( serviceContext.getAttribute("status"), WorkflowConstants.STATUS_APPROVED)); latestStructureVersion.setStatusByUserId(user.getUserId()); latestStructureVersion.setStatusByUserName(user.getFullName()); latestStructureVersion.setStatusDate(structure.getModifiedDate()); structureVersion = _ddmStructureVersionPersistence.update( latestStructureVersion); } else { structureVersion = _addStructureVersion( user, structure, version, serviceContext); } // Structure layout // Explicitly pop UUID from service context to ensure no lingering // values remain there from other components (e.g. Journal) serviceContext.getUuid(); _ddmStructureLayoutLocalService.addStructureLayout( structureVersion.getUserId(), structureVersion.getGroupId(), structureVersion.getStructureVersionId(), ddmFormLayout, serviceContext); if (!structureVersion.isApproved() && structureVersion.isPending()) { return structure; } structure = ddmStructurePersistence.update(structure); // Structure templates _syncStructureTemplatesFields(structure); // Data provider instance links _updateDataProviderInstanceLinks( structure.getGroupId(), structure.getStructureId(), ddmForm); // Indexer _reindexStructure(structure, serviceContext); return structure; } private void _validate(DDMForm ddmForm) throws PortalException { if (ExportImportThreadLocal.isImportInProcess()) { return; } _ddmFormValidator.validate(ddmForm); } private void _validate(DDMForm parentDDMForm, DDMForm ddmForm) throws PortalException { if (ExportImportThreadLocal.isImportInProcess()) { return; } Set commonDDMFormFieldNames = SetUtil.intersect( _getDDMFormFieldsNames(parentDDMForm), _getDDMFormFieldsNames(ddmForm)); if (!commonDDMFormFieldNames.isEmpty()) { throw new StructureDuplicateElementException( "Duplicate dynamic data mapping form field names: " + StringUtil.merge(commonDDMFormFieldNames)); } } private void _validate( long groupId, long parentStructureId, long classNameId, String structureKey, Map nameMap, DDMForm ddmForm) throws PortalException { if (ExportImportThreadLocal.isImportInProcess()) { return; } structureKey = _getStructureKey(structureKey); DDMStructure structure = ddmStructurePersistence.fetchByG_C_S( groupId, classNameId, structureKey); if (structure != null) { StructureDuplicateStructureKeyException structureDuplicateStructureKeyException = new StructureDuplicateStructureKeyException(); structureDuplicateStructureKeyException.setStructureKey( structure.getStructureKey()); throw structureDuplicateStructureKeyException; } _validate(nameMap, _getParentDDMForm(parentStructureId), ddmForm); } private void _validate( Map nameMap, DDMForm parentDDMForm, DDMForm ddmForm) throws PortalException { try { if (ExportImportThreadLocal.isImportInProcess()) { return; } _validate(nameMap, ddmForm.getDefaultLocale()); _validate(ddmForm); if (parentDDMForm != null) { _validate(parentDDMForm, ddmForm); } } catch (DDMFormValidationException ddmFormValidationException) { throw ddmFormValidationException; } catch (LocaleException localeException) { throw localeException; } catch (StructureDuplicateElementException structureDuplicateElementException) { throw structureDuplicateElementException; } catch (StructureNameException structureNameException) { throw structureNameException; } catch (StructureDefinitionException structureDefinitionException) { throw structureDefinitionException; } catch (Exception exception) { throw new StructureDefinitionException(exception); } } private void _validate( Map nameMap, Locale contentDefaultLocale) throws PortalException { if (ExportImportThreadLocal.isImportInProcess()) { return; } String name = nameMap.get(contentDefaultLocale); if (Validator.isNull(name)) { throw new StructureNameException( "Name is null for locale " + contentDefaultLocale.getDisplayName()); } if (!_language.isAvailableLocale(contentDefaultLocale)) { LocaleException localeException = new LocaleException( LocaleException.TYPE_CONTENT, StringBundler.concat( "The locale ", contentDefaultLocale, " is not available in company ", CompanyThreadLocal.getCompanyId())); localeException.setSourceAvailableLocales( Collections.singleton(contentDefaultLocale)); localeException.setTargetAvailableLocales( _language.getAvailableLocales()); throw localeException; } } private void _validateExternalReferenceCode( String externalReferenceCode, long structureId, long groupId, long classNameId) { if (Validator.isNull(externalReferenceCode)) { return; } DDMStructure structure = ddmStructurePersistence.fetchByERC_G_C( externalReferenceCode, groupId, classNameId); if ((structure != null) && (structure.getStructureId() != structureId)) { throw new DuplicateDDMStructureExternalReferenceCodeException( StringBundler.concat( "Duplicate dynamic data mapping structure external ", "reference code \"", externalReferenceCode, "\" for class name ID \"", classNameId, "\" in group \"", groupId, "\"")); } } private void _validateParentStructure( long structureId, long parentStructureId) throws PortalException { if (ExportImportThreadLocal.isImportInProcess()) { return; } while (parentStructureId != 0) { DDMStructure parentStructure = ddmStructurePersistence.fetchByPrimaryKey(parentStructureId); if (structureId == parentStructure.getStructureId()) { throw new InvalidParentStructureException(); } parentStructureId = parentStructure.getParentStructureId(); } } private void _validateStructureKey( long structureId, long groupId, long classNameId, String structureKey) throws PortalException { DDMStructure structure = ddmStructurePersistence.fetchByG_C_S( groupId, classNameId, structureKey); if ((structure == null) || (structure.getStructureId() == structureId)) { return; } StructureDuplicateStructureKeyException structureDuplicateStructureKeyException = new StructureDuplicateStructureKeyException(); structureDuplicateStructureKeyException.setStructureKey( structure.getStructureKey()); throw structureDuplicateStructureKeyException; } private static final Log _log = LogFactoryUtil.getLog( DDMStructureLocalServiceImpl.class); private static final Pattern _callFunctionPattern = Pattern.compile( "call\\(\\s*\'([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-" + "[0-9a-f]{12})\'\\s*,\\s*\'(.*)\'\\s*,\\s*\'(.*)\'\\s*\\)"); private static final Snapshot _siteConnectedGroupGroupProviderSnapshot = new Snapshot<>( DDMStructureLocalServiceImpl.class, SiteConnectedGroupGroupProvider.class, null, true); @Reference private ClassNameLocalService _classNameLocalService; @Reference private CustomSQL _customSQL; @Reference private DDM _ddm; @Reference private DDMDataDefinitionConverter _ddmDataDefinitionConverter; @Reference private DDMDataProviderInstanceLinkLocalService _ddmDataProviderInstanceLinkLocalService; @Reference private DDMDataProviderInstanceLinkPersistence _ddmDataProviderInstanceLinkPersistence; @Reference private DDMDataProviderInstanceLocalService _ddmDataProviderInstanceLocalService; @Reference private DDMFormValidator _ddmFormValidator; @Reference private DDMPermissionSupport _ddmPermissionSupport; @Reference private DDMStructureLayoutLocalService _ddmStructureLayoutLocalService; @Reference private DDMStructureLayoutPersistence _ddmStructureLayoutPersistence; @Reference private DDMStructureLinkPersistence _ddmStructureLinkPersistence; @Reference private DDMStructureVersionLocalService _ddmStructureVersionLocalService; @Reference private DDMStructureVersionPersistence _ddmStructureVersionPersistence; @Reference private DDMTemplateLocalService _ddmTemplateLocalService; @Reference private DDMTemplatePersistence _ddmTemplatePersistence; @Reference(target = "(ddm.form.deserializer.type=json)") private DDMFormDeserializer _jsonDDMFormDeserializer; @Reference(target = "(ddm.form.serializer.type=json)") private DDMFormSerializer _jsonDDMFormSerializer; @Reference private JSONFactory _jsonFactory; @Reference private Language _language; @Reference private MessageBus _messageBus; @Reference private Portal _portal; @Reference private ResourceLocalService _resourceLocalService; private ServiceTrackerMap _serviceTrackerMap; @Reference private UserLocalService _userLocalService; }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy