
com.liferay.change.tracking.service.impl.CTCollectionLocalServiceImpl Maven / Gradle / Ivy
/**
* 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.change.tracking.service.impl;
import com.liferay.change.tracking.closure.CTClosure;
import com.liferay.change.tracking.closure.CTClosureFactory;
import com.liferay.change.tracking.conflict.ConflictInfo;
import com.liferay.change.tracking.constants.CTConstants;
import com.liferay.change.tracking.exception.CTCollectionDescriptionException;
import com.liferay.change.tracking.exception.CTCollectionNameException;
import com.liferay.change.tracking.exception.CTEnclosureException;
import com.liferay.change.tracking.exception.CTLocalizedException;
import com.liferay.change.tracking.internal.CTEnclosureUtil;
import com.liferay.change.tracking.internal.CTServiceCopier;
import com.liferay.change.tracking.internal.CTServiceRegistry;
import com.liferay.change.tracking.internal.closure.Node;
import com.liferay.change.tracking.internal.conflict.CTConflictChecker;
import com.liferay.change.tracking.internal.conflict.ConstraintResolverConflictInfo;
import com.liferay.change.tracking.internal.conflict.ModificationConflictInfo;
import com.liferay.change.tracking.internal.helper.CTTableMapperHelper;
import com.liferay.change.tracking.internal.reference.TableReferenceDefinitionManager;
import com.liferay.change.tracking.internal.resolver.ConstraintResolverKey;
import com.liferay.change.tracking.mapping.CTMappingTableInfo;
import com.liferay.change.tracking.model.CTAutoResolutionInfo;
import com.liferay.change.tracking.model.CTCollection;
import com.liferay.change.tracking.model.CTEntry;
import com.liferay.change.tracking.model.CTPreferences;
import com.liferay.change.tracking.model.CTProcess;
import com.liferay.change.tracking.model.CTSchemaVersion;
import com.liferay.change.tracking.service.CTEntryLocalService;
import com.liferay.change.tracking.service.CTPreferencesLocalService;
import com.liferay.change.tracking.service.CTProcessLocalService;
import com.liferay.change.tracking.service.CTSchemaVersionLocalService;
import com.liferay.change.tracking.service.base.CTCollectionLocalServiceBaseImpl;
import com.liferay.change.tracking.service.persistence.CTAutoResolutionInfoPersistence;
import com.liferay.change.tracking.service.persistence.CTCommentPersistence;
import com.liferay.change.tracking.service.persistence.CTEntryPersistence;
import com.liferay.change.tracking.service.persistence.CTMessagePersistence;
import com.liferay.change.tracking.service.persistence.CTPreferencesPersistence;
import com.liferay.change.tracking.service.persistence.CTProcessPersistence;
import com.liferay.change.tracking.spi.display.CTDisplayRenderer;
import com.liferay.change.tracking.spi.resolver.ConstraintResolver;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMap;
import com.liferay.osgi.service.tracker.collections.map.ServiceTrackerMapFactory;
import com.liferay.petra.lang.SafeCloseable;
import com.liferay.petra.string.CharPool;
import com.liferay.petra.string.StringBundler;
import com.liferay.petra.string.StringPool;
import com.liferay.petra.string.StringUtil;
import com.liferay.portal.aop.AopService;
import com.liferay.portal.kernel.change.tracking.CTCollectionThreadLocal;
import com.liferay.portal.kernel.change.tracking.CTColumnResolutionType;
import com.liferay.portal.kernel.dao.jdbc.CurrentConnection;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.ClassName;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.model.ModelHintsUtil;
import com.liferay.portal.kernel.model.ResourceConstants;
import com.liferay.portal.kernel.search.IndexWriterHelper;
import com.liferay.portal.kernel.search.Indexer;
import com.liferay.portal.kernel.search.IndexerRegistry;
import com.liferay.portal.kernel.service.ClassNameLocalService;
import com.liferay.portal.kernel.service.GroupLocalService;
import com.liferay.portal.kernel.service.ResourceLocalService;
import com.liferay.portal.kernel.service.change.tracking.CTService;
import com.liferay.portal.kernel.transaction.TransactionCommitCallbackUtil;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.OrderByComparator;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.workflow.WorkflowConstants;
import com.liferay.portal.search.model.uid.UIDFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
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.Deactivate;
import org.osgi.service.component.annotations.Reference;
/**
* @author Brian Wing Shun Chan
* @author Daniel Kocsis
* @author Preston Crary
*/
@Component(
property = "model.class.name=com.liferay.change.tracking.model.CTCollection",
service = AopService.class
)
public class CTCollectionLocalServiceImpl
extends CTCollectionLocalServiceBaseImpl {
@Override
public CTCollection addCTCollection(
long companyId, long userId, String name, String description)
throws PortalException {
_validate(name, description);
long ctCollectionId = counterLocalService.increment(
CTCollection.class.getName());
CTCollection ctCollection = ctCollectionPersistence.create(
ctCollectionId);
ctCollection.setCompanyId(companyId);
ctCollection.setUserId(userId);
CTSchemaVersion latestCTSchemaVersion =
_ctSchemaVersionLocalService.getLatestCTSchemaVersion(companyId);
ctCollection.setSchemaVersionId(
latestCTSchemaVersion.getSchemaVersionId());
ctCollection.setName(name);
ctCollection.setDescription(description);
ctCollection.setStatus(WorkflowConstants.STATUS_DRAFT);
ctCollection = ctCollectionPersistence.update(ctCollection);
_resourceLocalService.addResources(
ctCollection.getCompanyId(), 0, ctCollection.getUserId(),
CTCollection.class.getName(), ctCollection.getCtCollectionId(),
false, false, false);
return ctCollection;
}
@Override
public Map> checkConflicts(
CTCollection ctCollection)
throws PortalException {
Map> conflictInfoMap = new HashMap<>();
List ctEntries = _ctEntryPersistence.findByCtCollectionId(
ctCollection.getCtCollectionId());
Map> ctConflictCheckers = new HashMap<>();
for (CTEntry ctEntry : ctEntries) {
CTConflictChecker> ctConflictChecker =
ctConflictCheckers.computeIfAbsent(
ctEntry.getModelClassNameId(),
modelClassNameId -> {
CTService> ctService =
_ctServiceRegistry.getCTService(modelClassNameId);
if (ctService == null) {
throw new SystemException(
StringBundler.concat(
"Unable to check conflicts for ",
ctCollection.getName(),
" because service for ", modelClassNameId,
" is missing"));
}
return new CTConflictChecker<>(
_classNameLocalService,
_constraintResolverServiceTrackerMap,
_ctDisplayRendererServiceTrackerMap,
_ctEntryLocalService, ctService, modelClassNameId,
ctCollection.getCtCollectionId(),
_tableReferenceDefinitionManager,
CTConstants.CT_COLLECTION_ID_PRODUCTION);
});
ctConflictChecker.addCTEntry(ctEntry);
}
try (SafeCloseable safeCloseable =
CTCollectionThreadLocal.setCTCollectionIdWithSafeCloseable(
ctCollection.getCtCollectionId())) {
for (Map.Entry> entry :
ctConflictCheckers.entrySet()) {
CTConflictChecker> ctConflictChecker = entry.getValue();
List conflictInfos = ctConflictChecker.check();
if (!conflictInfos.isEmpty()) {
conflictInfoMap.put(entry.getKey(), conflictInfos);
}
}
}
// Exclude created CTAutoResolutionInfos
List ctAutoResolutionInfos =
_ctAutoResolutionInfoPersistence.findByCtCollectionId(
ctCollection.getCtCollectionId());
for (Map.Entry> entry :
conflictInfoMap.entrySet()) {
for (ConflictInfo conflictInfo : entry.getValue()) {
if (!conflictInfo.isResolved()) {
continue;
}
CTAutoResolutionInfo ctAutoResolutionInfo =
_ctAutoResolutionInfoPersistence.create(
counterLocalService.increment(
CTAutoResolutionInfo.class.getName()));
ctAutoResolutionInfo.setCompanyId(ctCollection.getCompanyId());
ctAutoResolutionInfo.setCreateDate(new Date());
ctAutoResolutionInfo.setCtCollectionId(
ctCollection.getCtCollectionId());
ctAutoResolutionInfo.setModelClassNameId(entry.getKey());
ctAutoResolutionInfo.setSourceModelClassPK(
conflictInfo.getSourcePrimaryKey());
ctAutoResolutionInfo.setTargetModelClassPK(
conflictInfo.getTargetPrimaryKey());
if (conflictInfo instanceof ConstraintResolverConflictInfo) {
ConstraintResolverConflictInfo
constraintResolverConflictInfo =
(ConstraintResolverConflictInfo)conflictInfo;
ConstraintResolver> constraintResolver =
constraintResolverConflictInfo.getConstraintResolver();
ctAutoResolutionInfo.setConflictIdentifier(
StringUtil.merge(
constraintResolver.getUniqueIndexColumnNames(),
StringPool.COMMA));
constraintResolverConflictInfo.setCtAutoResolutionInfoId(
ctAutoResolutionInfo.getCtAutoResolutionInfoId());
}
else if (conflictInfo instanceof ModificationConflictInfo) {
ModificationConflictInfo resolvedModificationConflictInfo =
(ModificationConflictInfo)conflictInfo;
resolvedModificationConflictInfo.setCtAutoResolutionInfoId(
ctAutoResolutionInfo.getCtAutoResolutionInfoId());
ctAutoResolutionInfo.setConflictIdentifier(
ModificationConflictInfo.class.getName());
}
_ctAutoResolutionInfoPersistence.update(ctAutoResolutionInfo);
}
}
for (CTAutoResolutionInfo ctAutoResolutionInfo :
ctAutoResolutionInfos) {
List conflictInfos = conflictInfoMap.computeIfAbsent(
ctAutoResolutionInfo.getModelClassNameId(),
key -> new ArrayList<>());
if (Objects.equals(
ctAutoResolutionInfo.getConflictIdentifier(),
ModificationConflictInfo.class.getName())) {
ModificationConflictInfo resolvedModificationConflictInfo =
new ModificationConflictInfo(
ctAutoResolutionInfo.getSourceModelClassPK(), true);
resolvedModificationConflictInfo.setCtAutoResolutionInfoId(
ctAutoResolutionInfo.getCtAutoResolutionInfoId());
conflictInfos.add(resolvedModificationConflictInfo);
}
else {
List uniqueIndexes = StringUtil.split(
ctAutoResolutionInfo.getConflictIdentifier(),
CharPool.COMMA);
ClassName className = _classNameLocalService.getClassName(
ctAutoResolutionInfo.getModelClassNameId());
ConstraintResolver> constraintResolver =
_constraintResolverServiceTrackerMap.getService(
new ConstraintResolverKey(
className.getValue(),
uniqueIndexes.toArray(new String[0])));
if (constraintResolver != null) {
ConstraintResolverConflictInfo
constraintResolverConflictInfo =
new ConstraintResolverConflictInfo(
constraintResolver, true,
ctAutoResolutionInfo.getSourceModelClassPK(),
ctAutoResolutionInfo.getTargetModelClassPK());
constraintResolverConflictInfo.setCtAutoResolutionInfoId(
ctAutoResolutionInfo.getCtAutoResolutionInfoId());
conflictInfos.add(constraintResolverConflictInfo);
}
}
}
return conflictInfoMap;
}
@Override
public void deleteCompanyCTCollections(long companyId)
throws PortalException {
List ctCollections =
ctCollectionPersistence.findByCompanyId(companyId);
for (CTCollection ctCollection : ctCollections) {
deleteCTCollection(ctCollection);
}
}
@Override
public void deleteCTAutoResolutionInfo(long ctAutoResolutionInfoId) {
CTAutoResolutionInfo ctAutoResolutionInfo =
_ctAutoResolutionInfoPersistence.fetchByPrimaryKey(
ctAutoResolutionInfoId);
if (ctAutoResolutionInfo != null) {
_ctAutoResolutionInfoPersistence.remove(ctAutoResolutionInfo);
}
}
@Override
public CTCollection deleteCTCollection(CTCollection ctCollection)
throws PortalException {
_ctServiceRegistry.onBeforeRemove(ctCollection.getCtCollectionId());
try {
for (CTTableMapperHelper ctTableMapperHelper :
_ctServiceRegistry.getCTTableMapperHelpers()) {
ctTableMapperHelper.delete(ctCollection.getCtCollectionId());
}
}
catch (Exception exception) {
throw new SystemException(exception);
}
List ctEntries = _ctEntryPersistence.findByCtCollectionId(
ctCollection.getCtCollectionId());
Set modelClassNameIds = new HashSet<>();
for (CTEntry ctEntry : ctEntries) {
modelClassNameIds.add(ctEntry.getModelClassNameId());
}
for (long modelClassNameId : modelClassNameIds) {
CTService> ctService = _ctServiceRegistry.getCTService(
modelClassNameId);
if (ctService == null) {
if (_log.isWarnEnabled()) {
_log.warn(
"No CTService found for classNameId " +
modelClassNameId);
}
continue;
}
ctService.updateWithUnsafeFunction(
ctPersistence -> {
Connection connection = _currentConnection.getConnection(
ctPersistence.getDataSource());
try (PreparedStatement preparedStatement =
connection.prepareStatement(
StringBundler.concat(
"delete from ",
ctPersistence.getTableName(),
" where ctCollectionId = ",
ctCollection.getCtCollectionId()))) {
return preparedStatement.executeUpdate();
}
catch (Exception exception) {
throw new SystemException(exception);
}
});
}
_ctAutoResolutionInfoPersistence.removeByCtCollectionId(
ctCollection.getCtCollectionId());
_ctCommentPersistence.removeByCtCollectionId(
ctCollection.getCtCollectionId());
for (CTEntry ctEntry : ctEntries) {
_ctEntryPersistence.remove(ctEntry);
}
_ctMessagePersistence.removeByCtCollectionId(
ctCollection.getCtCollectionId());
List ctProcesses =
_ctProcessPersistence.findByCtCollectionId(
ctCollection.getCtCollectionId());
for (CTProcess ctProcess : ctProcesses) {
_ctProcessLocalService.deleteCTProcess(ctProcess);
}
Group group = _groupLocalService.fetchGroup(
ctCollection.getCompanyId(),
_classNameLocalService.getClassNameId(CTCollection.class),
ctCollection.getCtCollectionId());
if (group != null) {
_groupLocalService.deleteGroup(group);
}
_resourceLocalService.deleteResource(
ctCollection.getCompanyId(), CTCollection.class.getName(),
ResourceConstants.SCOPE_INDIVIDUAL,
ctCollection.getCtCollectionId());
int count = ctCollectionPersistence.countBySchemaVersionId(
ctCollection.getSchemaVersionId());
if (count == 1) {
CTSchemaVersion ctSchemaVersion =
_ctSchemaVersionLocalService.fetchCTSchemaVersion(
ctCollection.getSchemaVersionId());
if ((ctSchemaVersion != null) &&
!_ctSchemaVersionLocalService.isLatestCTSchemaVersion(
ctSchemaVersion, true)) {
_ctSchemaVersionLocalService.deleteCTSchemaVersion(
ctSchemaVersion);
}
}
return ctCollectionPersistence.remove(ctCollection);
}
@Override
public void discardCTEntries(
long ctCollectionId, long modelClassNameId, long modelClassPK,
boolean force)
throws PortalException {
CTCollection ctCollection = ctCollectionPersistence.findByPrimaryKey(
ctCollectionId);
if (!force &&
(ctCollection.getStatus() != WorkflowConstants.STATUS_DRAFT) &&
(ctCollection.getStatus() != WorkflowConstants.STATUS_PENDING)) {
throw new PortalException(
"Change tracking collection " + ctCollection + " is read only");
}
Map> ctEntriesMap = new HashMap<>();
List discardCTEntries =
ctCollectionLocalService.getDiscardCTEntries(
ctCollectionId, modelClassNameId, modelClassPK);
for (CTEntry ctEntry : discardCTEntries) {
List ctEntries = ctEntriesMap.computeIfAbsent(
ctEntry.getModelClassNameId(), key -> new ArrayList<>());
ctEntries.add(ctEntry);
}
for (Map.Entry> entry : ctEntriesMap.entrySet()) {
_discardCTEntries(ctCollection, entry.getKey(), entry.getValue());
}
}
@Override
public void discardCTEntry(
long ctCollectionId, long modelClassNameId, long modelClassPK,
boolean force)
throws PortalException {
CTCollection ctCollection = ctCollectionPersistence.findByPrimaryKey(
ctCollectionId);
if (!force &&
(ctCollection.getStatus() != WorkflowConstants.STATUS_DRAFT) &&
(ctCollection.getStatus() != WorkflowConstants.STATUS_PENDING)) {
throw new PortalException(
"Change tracking collection " + ctCollection + " is read only");
}
CTClosure ctClosure = _ctClosureFactory.create(
ctCollection.getCtCollectionId());
Map> enclosureMap = CTEnclosureUtil.getEnclosureMap(
ctClosure, modelClassNameId, modelClassPK);
for (Map.Entry entry :
CTEnclosureUtil.getEnclosureParentEntries(
ctClosure, enclosureMap)) {
long classNameId = entry.getKey();
long classPK = entry.getValue();
int count = _ctEntryPersistence.countByC_MCNI_MCPK(
ctCollectionId, classNameId, classPK);
if (count > 0) {
throw new CTEnclosureException(
StringBundler.concat(
"{classNameId=", classNameId, ", classPK=", classPK,
", ctCollectionId=", ctCollectionId, "}"));
}
}
for (Map.Entry> enclosureEntry :
enclosureMap.entrySet()) {
long classNameId = enclosureEntry.getKey();
Set classPKs = enclosureEntry.getValue();
List ctEntries = new ArrayList<>(classPKs.size());
for (long classPK : classPKs) {
CTEntry ctEntry = _ctEntryPersistence.fetchByC_MCNI_MCPK(
ctCollectionId, classNameId, classPK);
if (ctEntry != null) {
ctEntries.add(ctEntry);
}
}
if (ctEntries.isEmpty()) {
continue;
}
_discardCTEntries(ctCollection, classNameId, ctEntries);
}
}
@Override
public List getCTCollections(
long companyId, int status, int start, int end,
OrderByComparator orderByComparator) {
if (status == WorkflowConstants.STATUS_ANY) {
return ctCollectionPersistence.findByCompanyId(
companyId, start, end, orderByComparator);
}
return ctCollectionPersistence.findByC_S(
companyId, status, start, end, orderByComparator);
}
@Override
public List getCTMappingTableInfos(
long ctCollectionId) {
List ctMappingTableInfos = new ArrayList<>();
for (CTTableMapperHelper ctTableMapperHelper :
_ctServiceRegistry.getCTTableMapperHelpers()) {
CTMappingTableInfo ctMappingTableInfo =
ctTableMapperHelper.getCTMappingTableInfo(ctCollectionId);
if (ctMappingTableInfo != null) {
ctMappingTableInfos.add(ctMappingTableInfo);
}
}
return ctMappingTableInfos;
}
@Override
public List getDiscardCTEntries(
long ctCollectionId, long modelClassNameId, long modelClassPK) {
CTClosure ctClosure = _ctClosureFactory.create(ctCollectionId);
Set nodes = new HashSet<>();
int rootCount = _ctEntryPersistence.countByC_MCNI_MCPK(
ctCollectionId, modelClassNameId, modelClassPK);
if (rootCount == 0) {
Map> pksMap = ctClosure.getChildPKsMap(
modelClassNameId, modelClassPK);
Deque>> queue =
new LinkedList<>(pksMap.entrySet());
Map.Entry> entry = null;
while ((entry = queue.poll()) != null) {
long classNameId = entry.getKey();
for (long classPK : entry.getValue()) {
int count = _ctEntryPersistence.countByC_MCNI_MCPK(
ctCollectionId, classNameId, classPK);
if (count == 0) {
Map> childPKsMap =
ctClosure.getChildPKsMap(classNameId, classPK);
if (!childPKsMap.isEmpty()) {
queue.addAll(childPKsMap.entrySet());
}
}
else {
nodes.add(new Node(classNameId, classPK));
}
}
}
}
else {
nodes.add(new Node(modelClassNameId, modelClassPK));
}
Map> discardRootsMap = new HashMap<>();
CTEnclosureUtil.visitParentEntries(
ctClosure,
(classNameId, classPK, backtraceEntries) -> {
if (!nodes.contains(new Node(classNameId, classPK))) {
return false;
}
long previousModelClassNameId = classNameId;
Iterator> iterator =
backtraceEntries.iterator();
Map.Entry highestRequiredBacktraceEntry = null;
while (iterator.hasNext()) {
Map.Entry backtraceEntry = iterator.next();
long backtraceClassNameId = backtraceEntry.getKey();
long backtraceClassPK = backtraceEntry.getValue();
Set classPKs = discardRootsMap.get(
backtraceClassNameId);
if ((classPKs != null) &&
classPKs.contains(backtraceClassPK)) {
break;
}
CTEntry ctEntry = _ctEntryPersistence.fetchByC_MCNI_MCPK(
ctCollectionId, backtraceClassNameId, backtraceClassPK);
if ((ctEntry == null) ||
((ctEntry.getChangeType() !=
CTConstants.CT_CHANGE_TYPE_DELETION) &&
_tableReferenceDefinitionManager.isChildModelOptional(
previousModelClassNameId, backtraceClassNameId))) {
break;
}
highestRequiredBacktraceEntry = backtraceEntry;
previousModelClassNameId = backtraceClassNameId;
}
if (highestRequiredBacktraceEntry != null) {
Set classPKs = discardRootsMap.computeIfAbsent(
highestRequiredBacktraceEntry.getKey(),
key -> new HashSet<>());
classPKs.add(highestRequiredBacktraceEntry.getValue());
}
return true;
});
if (discardRootsMap.isEmpty()) {
discardRootsMap.put(
modelClassNameId, Collections.singleton(modelClassPK));
}
Map> discardEnclosureMap =
CTEnclosureUtil.getEnclosureMap(
ctClosure, discardRootsMap.entrySet());
List ctEntries = new ArrayList<>(discardEnclosureMap.size());
for (Map.Entry> entry :
discardEnclosureMap.entrySet()) {
for (long classPK : entry.getValue()) {
CTEntry ctEntry = _ctEntryPersistence.fetchByC_MCNI_MCPK(
ctCollectionId, entry.getKey(), classPK);
if (ctEntry != null) {
ctEntries.add(ctEntry);
}
}
}
return ctEntries;
}
@Override
public boolean isCTEntryEnclosed(
long ctCollectionId, long modelClassNameId, long modelClassPK) {
CTClosure ctClosure = _ctClosureFactory.create(ctCollectionId);
Map> enclosureMap = CTEnclosureUtil.getEnclosureMap(
ctClosure, modelClassNameId, modelClassPK);
for (Map.Entry entry :
CTEnclosureUtil.getEnclosureParentEntries(
ctClosure, enclosureMap)) {
int count = _ctEntryPersistence.countByC_MCNI_MCPK(
ctCollectionId, entry.getKey(), entry.getValue());
if (count > 0) {
return false;
}
}
return true;
}
@Override
public CTCollection undoCTCollection(
long ctCollectionId, long userId, String name, String description)
throws PortalException {
CTCollection undoCTCollection =
ctCollectionPersistence.findByPrimaryKey(ctCollectionId);
if (undoCTCollection.getStatus() != WorkflowConstants.STATUS_APPROVED) {
throw new CTLocalizedException(
StringBundler.concat(
"Unable to undo ", undoCTCollection.getName(),
" because it is not published"),
"unable-to-revert-x-because-it-is-not-published",
undoCTCollection.getName());
}
if (!_ctSchemaVersionLocalService.isLatestCTSchemaVersion(
undoCTCollection.getSchemaVersionId())) {
throw new CTLocalizedException(
StringBundler.concat(
"Unable to undo ", undoCTCollection.getName(),
" because it is out of date with the current release"),
"unable-to-revert-x-because-it-is-out-of-date-with-the-" +
"current-release",
undoCTCollection.getName());
}
CTCollection newCTCollection = addCTCollection(
undoCTCollection.getCompanyId(), userId, name, description);
CTPreferences ctPreferences =
_ctPreferencesLocalService.getCTPreferences(
undoCTCollection.getCompanyId(), userId);
ctPreferences.setCtCollectionId(newCTCollection.getCtCollectionId());
ctPreferences.setPreviousCtCollectionId(
CTConstants.CT_COLLECTION_ID_PRODUCTION);
_ctPreferencesPersistence.update(ctPreferences);
List publishedCTEntries =
_ctEntryPersistence.findByCtCollectionId(
undoCTCollection.getCtCollectionId());
Map> ctServiceCopiers = new HashMap<>();
long batchCounter = counterLocalService.increment(
CTEntry.class.getName(), publishedCTEntries.size());
batchCounter -= publishedCTEntries.size();
for (CTEntry publishedCTEntry : publishedCTEntries) {
long modelClassNameId = publishedCTEntry.getModelClassNameId();
if (!ctServiceCopiers.containsKey(modelClassNameId)) {
CTService> ctService = _ctServiceRegistry.getCTService(
modelClassNameId);
if (ctService == null) {
throw new CTLocalizedException(
StringBundler.concat(
"Unable to undo ", undoCTCollection.getName(),
" because service for ", modelClassNameId,
" is missing"),
"unable-to-revert-x-because-service-for-x-is-missing",
undoCTCollection.getName(),
publishedCTEntry.getModelClassNameId());
}
ctServiceCopiers.put(
modelClassNameId,
new CTServiceCopier<>(
ctService, undoCTCollection.getCtCollectionId(),
newCTCollection.getCtCollectionId()));
}
CTEntry ctEntry = _ctEntryPersistence.create(++batchCounter);
ctEntry.setCompanyId(newCTCollection.getCompanyId());
ctEntry.setUserId(newCTCollection.getUserId());
ctEntry.setCtCollectionId(newCTCollection.getCtCollectionId());
ctEntry.setModelClassNameId(modelClassNameId);
ctEntry.setModelClassPK(publishedCTEntry.getModelClassPK());
ctEntry.setModelMvccVersion(publishedCTEntry.getModelMvccVersion());
int changeType = publishedCTEntry.getChangeType();
if (changeType == CTConstants.CT_CHANGE_TYPE_ADDITION) {
changeType = CTConstants.CT_CHANGE_TYPE_DELETION;
}
else if (changeType == CTConstants.CT_CHANGE_TYPE_DELETION) {
changeType = CTConstants.CT_CHANGE_TYPE_ADDITION;
}
ctEntry.setChangeType(changeType);
_ctEntryPersistence.update(ctEntry);
}
try {
for (CTServiceCopier> ctServiceCopier :
ctServiceCopiers.values()) {
ctServiceCopier.copy();
}
for (CTTableMapperHelper ctTableMapperHelper :
_ctServiceRegistry.getCTTableMapperHelpers()) {
ctTableMapperHelper.undo(
undoCTCollection.getCtCollectionId(),
newCTCollection.getCtCollectionId());
}
}
catch (Exception exception) {
throw new SystemException(exception);
}
_ctServiceRegistry.onAfterCopy(undoCTCollection, newCTCollection);
return newCTCollection;
}
@Override
public CTCollection updateCTCollection(
long userId, long ctCollectionId, String name, String description)
throws PortalException {
_validate(name, description);
CTCollection ctCollection = ctCollectionPersistence.findByPrimaryKey(
ctCollectionId);
Date modifiedDate = new Date();
ctCollection.setModifiedDate(modifiedDate);
ctCollection.setName(name);
ctCollection.setDescription(description);
ctCollection.setStatusByUserId(userId);
ctCollection.setStatusDate(modifiedDate);
return ctCollectionPersistence.update(ctCollection);
}
@Activate
protected void activate(BundleContext bundleContext) {
_constraintResolverServiceTrackerMap =
ServiceTrackerMapFactory.openSingleValueMap(
bundleContext,
(Class>)
(Class>)ConstraintResolver.class,
null,
(serviceReference, emitter) -> {
ConstraintResolver> constraintResolver =
bundleContext.getService(serviceReference);
emitter.emit(
new ConstraintResolverKey(
constraintResolver.getModelClass(),
constraintResolver.getUniqueIndexColumnNames()));
});
_ctDisplayRendererServiceTrackerMap =
ServiceTrackerMapFactory.openSingleValueMap(
bundleContext,
(Class>)(Class>)CTDisplayRenderer.class,
null,
(serviceReference, emitter) -> {
CTDisplayRenderer> ctDisplayRenderer =
bundleContext.getService(serviceReference);
Class> modelClass = ctDisplayRenderer.getModelClass();
emitter.emit(modelClass.getName());
});
}
@Deactivate
@Override
protected void deactivate() {
super.deactivate();
_constraintResolverServiceTrackerMap.close();
_ctDisplayRendererServiceTrackerMap.close();
}
private void _discardCTEntries(
CTCollection ctCollection, long classNameId, List ctEntries) {
CTService> ctService = _ctServiceRegistry.getCTService(classNameId);
ctService.updateWithUnsafeFunction(
ctPersistence -> {
Set primaryKeyNames = ctPersistence.getCTColumnNames(
CTColumnResolutionType.PK);
if (primaryKeyNames.size() != 1) {
throw new IllegalArgumentException(
StringBundler.concat(
"{primaryKeyNames=", primaryKeyNames,
", tableName=", ctPersistence.getTableName(), "}"));
}
Iterator iterator = primaryKeyNames.iterator();
String primaryKeyName = iterator.next();
StringBundler sb = new StringBundler(
(2 * ctEntries.size()) + 7);
sb.append("delete from ");
sb.append(ctPersistence.getTableName());
sb.append(" where ctCollectionId = ");
sb.append(ctCollection.getCtCollectionId());
sb.append(" and ");
sb.append(primaryKeyName);
sb.append(" in (");
for (CTEntry ctEntry : ctEntries) {
sb.append(ctEntry.getModelClassPK());
sb.append(", ");
}
sb.setStringAt(")", sb.index() - 1);
Connection connection = _currentConnection.getConnection(
ctPersistence.getDataSource());
try (PreparedStatement preparedStatement =
connection.prepareStatement(sb.toString())) {
preparedStatement.executeUpdate();
}
catch (Exception exception) {
throw new SystemException(exception);
}
for (String mappingTableName :
ctPersistence.getMappingTableNames()) {
sb.setStringAt(mappingTableName, 1);
try (PreparedStatement preparedStatement =
connection.prepareStatement(sb.toString())) {
preparedStatement.executeUpdate();
}
catch (Exception exception) {
throw new SystemException(exception);
}
}
return null;
});
List modelClassPKs = new ArrayList<>(ctEntries.size());
for (CTEntry ctEntry : ctEntries) {
modelClassPKs.add(ctEntry.getModelClassPK());
_ctEntryPersistence.remove(ctEntry);
}
for (CTAutoResolutionInfo ctAutoResolutionInfo :
_ctAutoResolutionInfoPersistence.findByC_MCNI_SMCPK(
ctCollection.getCtCollectionId(), classNameId,
ArrayUtil.toLongArray(modelClassPKs))) {
_ctAutoResolutionInfoPersistence.remove(ctAutoResolutionInfo);
}
Indexer> indexer = _indexerRegistry.getIndexer(
ctService.getModelClass());
if (indexer != null) {
TransactionCommitCallbackUtil.registerCallback(
() -> {
List uids = new ArrayList<>(ctEntries.size());
for (CTEntry ctEntry : ctEntries) {
if (ctEntry.getChangeType() !=
CTConstants.CT_CHANGE_TYPE_DELETION) {
uids.add(
_uidFactory.getUID(
indexer.getClassName(),
ctEntry.getModelClassPK(),
ctEntry.getCtCollectionId()));
}
}
_indexWriterHelper.deleteDocuments(
indexer.getSearchEngineId(),
ctCollection.getCompanyId(), uids,
indexer.isCommitImmediately());
return null;
});
}
}
private void _validate(String name, String description)
throws PortalException {
if (Validator.isNull(name)) {
throw new CTCollectionNameException();
}
int nameMaxLength = ModelHintsUtil.getMaxLength(
CTCollection.class.getName(), "name");
if (name.length() > nameMaxLength) {
throw new CTCollectionNameException("Name is too long");
}
int descriptionMaxLength = ModelHintsUtil.getMaxLength(
CTCollection.class.getName(), "description");
if ((description != null) &&
(description.length() > descriptionMaxLength)) {
throw new CTCollectionDescriptionException(
"Description is too long");
}
}
private static final Log _log = LogFactoryUtil.getLog(
CTCollectionLocalServiceImpl.class);
@Reference
private ClassNameLocalService _classNameLocalService;
private ServiceTrackerMap>
_constraintResolverServiceTrackerMap;
@Reference
private CTAutoResolutionInfoPersistence _ctAutoResolutionInfoPersistence;
@Reference
private CTClosureFactory _ctClosureFactory;
@Reference
private CTCommentPersistence _ctCommentPersistence;
private ServiceTrackerMap>
_ctDisplayRendererServiceTrackerMap;
@Reference
private CTEntryLocalService _ctEntryLocalService;
@Reference
private CTEntryPersistence _ctEntryPersistence;
@Reference
private CTMessagePersistence _ctMessagePersistence;
@Reference
private CTPreferencesLocalService _ctPreferencesLocalService;
@Reference
private CTPreferencesPersistence _ctPreferencesPersistence;
@Reference
private CTProcessLocalService _ctProcessLocalService;
@Reference
private CTProcessPersistence _ctProcessPersistence;
@Reference
private CTSchemaVersionLocalService _ctSchemaVersionLocalService;
@Reference
private CTServiceRegistry _ctServiceRegistry;
@Reference
private CurrentConnection _currentConnection;
@Reference
private GroupLocalService _groupLocalService;
@Reference
private IndexerRegistry _indexerRegistry;
@Reference
private IndexWriterHelper _indexWriterHelper;
@Reference
private ResourceLocalService _resourceLocalService;
@Reference
private TableReferenceDefinitionManager _tableReferenceDefinitionManager;
@Reference
private UIDFactory _uidFactory;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy