/**
* 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.portlet.asset.service.impl;
import com.liferay.asset.kernel.exception.NoSuchLinkException;
import com.liferay.asset.kernel.model.AssetEntry;
import com.liferay.asset.kernel.model.AssetLink;
import com.liferay.asset.kernel.model.AssetLinkConstants;
import com.liferay.asset.kernel.model.adapter.StagedAssetLink;
import com.liferay.exportimport.kernel.lar.PortletDataContext;
import com.liferay.exportimport.kernel.lar.StagedModelDataHandlerUtil;
import com.liferay.exportimport.kernel.lar.StagedModelType;
import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
import com.liferay.portal.kernel.dao.orm.Criterion;
import com.liferay.portal.kernel.dao.orm.Disjunction;
import com.liferay.portal.kernel.dao.orm.DynamicQuery;
import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
import com.liferay.portal.kernel.dao.orm.ExportActionableDynamicQuery;
import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
import com.liferay.portal.kernel.dao.orm.Property;
import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
import com.liferay.portal.kernel.dao.orm.QueryPos;
import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil;
import com.liferay.portal.kernel.dao.orm.SQLQuery;
import com.liferay.portal.kernel.dao.orm.Session;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.model.adapter.ModelAdapterUtil;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portlet.asset.service.base.AssetLinkLocalServiceBaseImpl;
import com.liferay.util.dao.orm.CustomSQLUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* This class implements the methods needed to handle AssetLinks, the entity
* that relates different assets in the portal.
*
* The basic information stored for every link includes both assets entry IDs,
* the userId, the link type and the link's weight.
*
* @author Brian Wing Shun Chan
* @author Juan Fernández
*/
public class AssetLinkLocalServiceImpl extends AssetLinkLocalServiceBaseImpl {
/**
* Adds a new asset link.
*
* @param userId the primary key of the link's creator
* @param entryId1 the primary key of the first asset entry
* @param entryId2 the primary key of the second asset entry
* @param type the link type. Acceptable values include {@link
* AssetLinkConstants#TYPE_RELATED} which is a bidirectional
* relationship and {@link AssetLinkConstants#TYPE_CHILD} which is a
* unidirectional relationship. For more information see {@link
* AssetLinkConstants}
* @param weight the weight of the relationship, allowing precedence
* ordering of links
* @return the asset link
*/
@Override
public AssetLink addLink(
long userId, long entryId1, long entryId2, int type, int weight)
throws PortalException {
User user = userPersistence.findByPrimaryKey(userId);
Date now = new Date();
long linkId = counterLocalService.increment();
AssetLink link = assetLinkPersistence.create(linkId);
link.setCompanyId(user.getCompanyId());
link.setUserId(user.getUserId());
link.setUserName(user.getFullName());
link.setCreateDate(now);
link.setEntryId1(entryId1);
link.setEntryId2(entryId2);
link.setType(type);
link.setWeight(weight);
assetLinkPersistence.update(link);
if (AssetLinkConstants.isTypeBi(type)) {
long linkId2 = counterLocalService.increment();
AssetLink link2 = assetLinkPersistence.create(linkId2);
link2.setCompanyId(user.getCompanyId());
link2.setUserId(user.getUserId());
link2.setUserName(user.getFullName());
link2.setCreateDate(now);
link2.setEntryId1(entryId2);
link2.setEntryId2(entryId1);
link2.setType(type);
link2.setWeight(weight);
assetLinkPersistence.update(link2);
}
return link;
}
@Override
public void deleteGroupLinks(long groupId) {
Session session = assetLinkPersistence.openSession();
try {
String sql = CustomSQLUtil.get(_DELETE_BY_ASSET_ENTRY_GROUP_ID);
SQLQuery sqlQuery = session.createSynchronizedSQLQuery(sql);
QueryPos qPos = QueryPos.getInstance(sqlQuery);
qPos.add(groupId);
qPos.add(groupId);
sqlQuery.executeUpdate();
}
finally {
assetLinkPersistence.closeSession(session);
assetLinkPersistence.clearCache();
}
}
/**
* Deletes the asset link.
*
* @param link the asset link
*/
@Override
public void deleteLink(AssetLink link) {
if (AssetLinkConstants.isTypeBi(link.getType())) {
try {
assetLinkPersistence.removeByE_E_T(
link.getEntryId2(), link.getEntryId1(), link.getType());
}
catch (NoSuchLinkException nsle) {
if (_log.isWarnEnabled()) {
_log.warn("Unable to delete asset link", nsle);
}
}
}
assetLinkPersistence.remove(link);
}
/**
* Deletes the asset link.
*
* @param linkId the primary key of the asset link
*/
@Override
public void deleteLink(long linkId) throws PortalException {
AssetLink link = assetLinkPersistence.findByPrimaryKey(linkId);
deleteLink(link);
}
/**
* Deletes all links associated with the asset entry.
*
* @param entryId the primary key of the asset entry
*/
@Override
public void deleteLinks(long entryId) {
for (AssetLink link : assetLinkPersistence.findByE1(entryId)) {
deleteLink(link);
}
for (AssetLink link : assetLinkPersistence.findByE2(entryId)) {
deleteLink(link);
}
}
/**
* Delete all links that associate the two asset entries.
*
* @param entryId1 the primary key of the first asset entry
* @param entryId2 the primary key of the second asset entry
*/
@Override
public void deleteLinks(long entryId1, long entryId2) {
List<AssetLink> links = assetLinkPersistence.findByE_E(
entryId1, entryId2);
for (AssetLink link : links) {
deleteLink(link);
}
}
/**
* Returns all the asset links whose first entry ID is the given entry ID.
*
* @param entryId the primary key of the asset entry
* @return the asset links whose first entry ID is the given entry ID
*/
@Override
public List<AssetLink> getDirectLinks(long entryId) {
return getDirectLinks(entryId, true);
}
@Override
public List<AssetLink> getDirectLinks(
long entryId, boolean excludeInvisibleLinks) {
List<AssetLink> assetLinks = assetLinkPersistence.findByE1(entryId);
return filterAssetLinks(assetLinks, excludeInvisibleLinks);
}
/**
* Returns all the asset links of the given link type whose first entry ID
* is the given entry ID.
*
* @param entryId the primary key of the asset entry
* @param typeId the link type. Acceptable values include {@link
* AssetLinkConstants#TYPE_RELATED} which is a bidirectional
* relationship and {@link AssetLinkConstants#TYPE_CHILD} which is a
* unidirectional relationship. For more information see {@link
* AssetLinkConstants}
* @return the asset links of the given link type whose first entry ID is
* the given entry ID
*/
@Override
public List<AssetLink> getDirectLinks(long entryId, int typeId) {
return getDirectLinks(entryId, typeId, true);
}
@Override
public List<AssetLink> getDirectLinks(
long entryId, int typeId, boolean excludeInvisibleLinks) {
List<AssetLink> assetLinks = assetLinkPersistence.findByE1_T(
entryId, typeId);
return filterAssetLinks(assetLinks, excludeInvisibleLinks);
}
@Override
public ExportActionableDynamicQuery getExportActionbleDynamicQuery(
final PortletDataContext portletDataContext) {
final ExportActionableDynamicQuery exportActionableDynamicQuery =
new ExportActionableDynamicQuery();
exportActionableDynamicQuery.setAddCriteriaMethod(
new ActionableDynamicQuery.AddCriteriaMethod() {
@Override
public void addCriteria(DynamicQuery dynamicQuery) {
Criterion createDateCriterion =
portletDataContext.getDateRangeCriteria("createDate");
if (createDateCriterion != null) {
dynamicQuery.add(createDateCriterion);
}
DynamicQuery assetEntryDynamicQuery =
DynamicQueryFactoryUtil.forClass(
AssetEntry.class, "assetEntry", getClassLoader());
assetEntryDynamicQuery.setProjection(
ProjectionFactoryUtil.alias(
ProjectionFactoryUtil.property(
"assetEntry.entryId"),
"assetEntry.assetEntryId"));
Property groupIdProperty = PropertyFactoryUtil.forName(
"groupId");
Criterion groupIdCriterion = groupIdProperty.eq(
portletDataContext.getScopeGroupId());
assetEntryDynamicQuery.add(groupIdCriterion);
Disjunction disjunction =
RestrictionsFactoryUtil.disjunction();
Property entryId1Property = PropertyFactoryUtil.forName(
"entryId1");
Property entryId2Property = PropertyFactoryUtil.forName(
"entryId2");
disjunction.add(
entryId1Property.in(assetEntryDynamicQuery));
disjunction.add(
entryId2Property.in(assetEntryDynamicQuery));
dynamicQuery.add(disjunction);
}
});
exportActionableDynamicQuery.setBaseLocalService(this);
exportActionableDynamicQuery.setClassLoader(getClassLoader());
exportActionableDynamicQuery.setCompanyId(
portletDataContext.getCompanyId());
exportActionableDynamicQuery.setModelClass(AssetLink.class);
exportActionableDynamicQuery.setPerformActionMethod(
new ActionableDynamicQuery.PerformActionMethod<AssetLink>() {
@Override
public void performAction(AssetLink assetLink)
throws PortalException {
StagedAssetLink stagedAssetLink = ModelAdapterUtil.adapt(
assetLink, AssetLink.class, StagedAssetLink.class);
StagedModelDataHandlerUtil.exportStagedModel(
portletDataContext, stagedAssetLink);
}
});
exportActionableDynamicQuery.setPrimaryKeyPropertyName("linkId");
exportActionableDynamicQuery.setStagedModelType(
new StagedModelType(StagedModelType.class));
return exportActionableDynamicQuery;
}
/**
* Returns all the asset links whose first or second entry ID is the given
* entry ID.
*
* @param entryId the primary key of the asset entry
* @return the asset links whose first or second entry ID is the given entry
* ID
*/
@Override
public List<AssetLink> getLinks(long entryId) {
List<AssetLink> e1Links = assetLinkPersistence.findByE1(entryId);
List<AssetLink> e2Links = assetLinkPersistence.findByE2(entryId);
List<AssetLink> links = new ArrayList<>(
e1Links.size() + e2Links.size());
links.addAll(e1Links);
links.addAll(e2Links);
return links;
}
/**
* Returns all the asset links of the given link type whose first or second
* entry ID is the given entry ID.
*
* @param entryId the primary key of the asset entry
* @param typeId the link type. Acceptable values include {@link
* AssetLinkConstants#TYPE_RELATED} which is a bidirectional
* relationship and {@link AssetLinkConstants#TYPE_CHILD} which is a
* unidirectional relationship. For more information see {@link
* AssetLinkConstants}
* @return the asset links of the given link type whose first or second
* entry ID is the given entry ID
*/
@Override
public List<AssetLink> getLinks(long entryId, int typeId) {
List<AssetLink> e1Links = assetLinkPersistence.findByE1_T(
entryId, typeId);
List<AssetLink> e2Links = assetLinkPersistence.findByE2_T(
entryId, typeId);
List<AssetLink> links = new ArrayList<>(
e1Links.size() + e2Links.size());
links.addAll(e1Links);
links.addAll(e2Links);
return links;
}
/**
* Returns all the asset links of the given link type whose second entry ID
* is the given entry ID.
*
* @param entryId the primary key of the asset entry
* @param typeId the link type. Acceptable values include {@link
* AssetLinkConstants#TYPE_RELATED} which is a bidirectional
* relationship and {@link AssetLinkConstants#TYPE_CHILD} which is a
* unidirectional relationship. For more information see {@link
* AssetLinkConstants}
* @return the asset links of the given link type whose second entry ID is
* the given entry ID
*/
@Override
public List<AssetLink> getReverseLinks(long entryId, int typeId) {
return assetLinkPersistence.findByE2_T(entryId, typeId);
}
@Override
public AssetLink updateLink(
long userId, long entryId1, long entryId2, int typeId, int weight)
throws PortalException {
AssetLink assetLink = assetLinkPersistence.fetchByE_E_T(
entryId1, entryId2, typeId);
if (assetLink == null) {
return addLink(userId, entryId1, entryId2, typeId, weight);
}
assetLink.setWeight(weight);
assetLinkPersistence.update(assetLink);
return assetLink;
}
/**
* Updates all links of the asset entry, replacing them with links
* associating the asset entry with the asset entries of the given link
* entry IDs.
*
* <p>
* If no link exists with a given link entry ID, a new link is created
* associating the current asset entry with the asset entry of that link
* entry ID. An existing link is deleted if either of its entry IDs is not
* contained in the given link entry IDs.
* </p>
*
* @param userId the primary key of the user updating the links
* @param entryId the primary key of the asset entry to be managed
* @param linkEntryIds the primary keys of the asset entries to be linked
* with the asset entry to be managed
* @param typeId the type of the asset links to be created. Acceptable
* values include {@link AssetLinkConstants#TYPE_RELATED} which is a
* bidirectional relationship and {@link
* AssetLinkConstants#TYPE_CHILD} which is a unidirectional
* relationship. For more information see {@link AssetLinkConstants}
*/
@Override
public void updateLinks(
long userId, long entryId, long[] linkEntryIds, int typeId)
throws PortalException {
if (linkEntryIds == null) {
return;
}
List<AssetLink> links = getLinks(entryId, typeId);
for (AssetLink link : links) {
if (((link.getEntryId1() == entryId) &&
!ArrayUtil.contains(linkEntryIds, link.getEntryId2())) ||
((link.getEntryId2() == entryId) &&
!ArrayUtil.contains(linkEntryIds, link.getEntryId1()))) {
deleteLink(link);
}
}
for (long assetLinkEntryId : linkEntryIds) {
if (assetLinkEntryId != entryId) {
AssetLink link = assetLinkPersistence.fetchByE_E_T(
entryId, assetLinkEntryId, typeId);
if (link == null) {
addLink(userId, entryId, assetLinkEntryId, typeId, 0);
}
}
}
}
protected List<AssetLink> filterAssetLinks(
List<AssetLink> assetLinks, boolean excludeInvisibleLinks) {
if (assetLinks.isEmpty() || !excludeInvisibleLinks) {
return assetLinks;
}
List<AssetLink> filteredAssetLinks = new ArrayList<>(assetLinks.size());
for (AssetLink assetLink : assetLinks) {
AssetEntry assetEntry = assetEntryPersistence.fetchByPrimaryKey(
assetLink.getEntryId2());
if ((assetEntry != null) && assetEntry.isVisible()) {
filteredAssetLinks.add(assetLink);
}
}
assetLinks = Collections.unmodifiableList(filteredAssetLinks);
return assetLinks;
}
private static final String _DELETE_BY_ASSET_ENTRY_GROUP_ID =
AssetLinkLocalServiceImpl.class.getName() +
".deleteByAssetEntryGroupId";
private static final Log _log = LogFactoryUtil.getLog(
AssetLinkLocalServiceImpl.class);
}