/**
* 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.persistence.impl;
import com.liferay.asset.kernel.model.AssetCategory;
import com.liferay.asset.kernel.model.AssetEntry;
import com.liferay.asset.kernel.service.persistence.AssetCategoryUtil;
import com.liferay.asset.kernel.service.persistence.AssetEntryFinder;
import com.liferay.asset.kernel.service.persistence.AssetEntryQuery;
import com.liferay.portal.kernel.dao.orm.QueryPos;
import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.dao.orm.SQLQuery;
import com.liferay.portal.kernel.dao.orm.Session;
import com.liferay.portal.kernel.dao.orm.Type;
import com.liferay.portal.kernel.dao.orm.WildcardMode;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.model.Layout;
import com.liferay.portal.kernel.util.CalendarUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.util.PropsValues;
import com.liferay.portlet.asset.model.impl.AssetEntryImpl;
import com.liferay.portlet.documentlibrary.service.persistence.impl.DLFileEntryFinderImpl;
import com.liferay.portlet.documentlibrary.service.persistence.impl.DLFolderFinderImpl;
import com.liferay.util.dao.orm.CustomSQLUtil;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
/**
* @author Brian Wing Shun Chan
* @author Jorge Ferrer
* @author Shuyang Zhou
*/
public class AssetEntryFinderImpl
extends AssetEntryFinderBaseImpl implements AssetEntryFinder {
public static final String FIND_BY_AND_CATEGORY_IDS =
AssetEntryFinder.class.getName() + ".findByAndCategoryIds";
public static final String FIND_BY_AND_TAG_IDS =
AssetEntryFinder.class.getName() + ".findByAndTagIds";
public static final String FIND_BY_CLASS_NAME_ID =
AssetEntryFinder.class.getName() + ".findByClassNameId";
@Override
public int countEntries(AssetEntryQuery entryQuery) {
Session session = null;
try {
session = openSession();
SQLQuery q = buildAssetQuerySQL(entryQuery, true, session);
Iterator<Long> itr = q.iterate();
if (itr.hasNext()) {
Long count = itr.next();
if (count != null) {
return count.intValue();
}
}
return 0;
}
catch (Exception e) {
throw new SystemException(e);
}
finally {
closeSession(session);
}
}
@Override
public List<AssetEntry> findByDLFileEntryC_T(
long classNameId, String treePath) {
Session session = null;
try {
session = openSession();
String sql = CustomSQLUtil.get(FIND_BY_CLASS_NAME_ID);
sql = StringUtil.replace(
sql, "[$JOIN$]",
CustomSQLUtil.get(
DLFileEntryFinderImpl.JOIN_AE_BY_DL_FILE_ENTRY));
sql = StringUtil.replace(
sql, "[$WHERE$]", "DLFileEntry.treePath LIKE ? AND");
SQLQuery q = session.createSynchronizedSQLQuery(sql);
QueryPos qPos = QueryPos.getInstance(q);
qPos.add(
CustomSQLUtil.keywords(treePath, WildcardMode.TRAILING)[0]);
qPos.add(classNameId);
q.addEntity(AssetEntryImpl.TABLE_NAME, AssetEntryImpl.class);
return q.list(true);
}
catch (Exception e) {
throw new SystemException(e);
}
finally {
closeSession(session);
}
}
@Override
public List<AssetEntry> findByDLFolderC_T(
long classNameId, String treePath) {
Session session = null;
try {
session = openSession();
String sql = CustomSQLUtil.get(FIND_BY_CLASS_NAME_ID);
sql = StringUtil.replace(
sql, "[$JOIN$]",
CustomSQLUtil.get(DLFolderFinderImpl.JOIN_AE_BY_DL_FOLDER));
sql = StringUtil.replace(
sql, "[$WHERE$]", "DLFolder.treePath LIKE ? AND");
SQLQuery q = session.createSynchronizedSQLQuery(sql);
QueryPos qPos = QueryPos.getInstance(q);
qPos.add(
CustomSQLUtil.keywords(treePath, WildcardMode.TRAILING)[0]);
qPos.add(classNameId);
q.addEntity(AssetEntryImpl.TABLE_NAME, AssetEntryImpl.class);
return q.list(true);
}
catch (Exception e) {
throw new SystemException(e);
}
finally {
closeSession(session);
}
}
@Override
public List<AssetEntry> findEntries(AssetEntryQuery entryQuery) {
Session session = null;
try {
session = openSession();
SQLQuery q = buildAssetQuerySQL(entryQuery, false, session);
return (List<AssetEntry>)QueryUtil.list(
q, getDialect(), entryQuery.getStart(), entryQuery.getEnd());
}
catch (Exception e) {
throw new SystemException(e);
}
finally {
closeSession(session);
}
}
protected void buildAllCategoriesSQL(long[] categoryIds, StringBundler sb) {
String findByAndCategoryIdsSQL = CustomSQLUtil.get(
FIND_BY_AND_CATEGORY_IDS);
sb.append(" AND (");
for (int i = 0; i < categoryIds.length; i++) {
String sql = null;
if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
List<Long> treeCategoryIds = getSubcategoryIds(categoryIds[i]);
if (treeCategoryIds.size() > 1) {
sql = StringUtil.replace(
findByAndCategoryIdsSQL, "[$CATEGORY_ID$]",
StringUtil.merge(treeCategoryIds));
}
}
if (sql == null) {
sql = StringUtil.replace(
findByAndCategoryIdsSQL, " IN ([$CATEGORY_ID$])",
" = " + categoryIds[i]);
}
sb.append(sql);
if ((i + 1) < categoryIds.length) {
sb.append(" AND ");
}
}
sb.append(StringPool.CLOSE_PARENTHESIS);
}
protected void buildAllTagsSQL(long[][] tagIds, StringBundler sb) {
sb.append(" AND AssetEntry.entryId IN (");
for (int i = 0; i < tagIds.length; i++) {
String sql = CustomSQLUtil.get(FIND_BY_AND_TAG_IDS);
sql = StringUtil.replace(sql, "[$TAG_ID$]", getTagIds(tagIds[i]));
sb.append(sql);
if ((i + 1) < tagIds.length) {
sb.append(" AND AssetEntry.entryId IN (");
}
}
for (int i = 0; i < tagIds.length; i++) {
if ((i + 1) < tagIds.length) {
sb.append(StringPool.CLOSE_PARENTHESIS);
}
}
sb.append(StringPool.CLOSE_PARENTHESIS);
}
protected void buildAnyCategoriesSQL(long[] categoryIds, StringBundler sb) {
String sql = CustomSQLUtil.get(FIND_BY_AND_CATEGORY_IDS);
String categoryIdsString = null;
if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
List<Long> categoryIdsList = new ArrayList<>();
for (long categoryId : categoryIds) {
categoryIdsList.addAll(getSubcategoryIds(categoryId));
}
if (categoryIdsList.isEmpty()) {
return;
}
categoryIdsString = StringUtil.merge(categoryIdsList);
}
else {
categoryIdsString = StringUtil.merge(categoryIds);
}
sb.append(" AND (");
sb.append(
StringUtil.replace(sql, "[$CATEGORY_ID$]", categoryIdsString));
sb.append(StringPool.CLOSE_PARENTHESIS);
}
protected String buildAnyTagsSQL(long[] tagIds, StringBundler sb) {
sb.append(" AND (");
for (int i = 0; i < tagIds.length; i++) {
sb.append("AssetTag.tagId = ");
sb.append(tagIds[i]);
if ((i + 1) != tagIds.length) {
sb.append(" OR ");
}
}
sb.append(StringPool.CLOSE_PARENTHESIS);
return sb.toString();
}
protected SQLQuery buildAssetQuerySQL(
AssetEntryQuery entryQuery, boolean count, Session session) {
StringBundler sb = new StringBundler(52);
if (count) {
sb.append(
"SELECT COUNT(DISTINCT AssetEntry.entryId) AS COUNT_VALUE ");
}
else {
sb.append("SELECT {AssetEntry.*} ");
boolean selectRatings = false;
String orderByCol1 = entryQuery.getOrderByCol1();
String orderByCol2 = entryQuery.getOrderByCol2();
if (orderByCol1.equals("ratings") ||
orderByCol2.equals("ratings")) {
selectRatings = true;
sb.append(", TEMP_TABLE.averageScore ");
}
sb.append("FROM (SELECT DISTINCT AssetEntry.entryId ");
if (selectRatings) {
sb.append(", RatingsStats.averageScore ");
}
}
sb.append("FROM AssetEntry ");
if (entryQuery.getAnyTagIds().length > 0) {
sb.append("INNER JOIN AssetEntries_AssetTags ON ");
sb.append("(AssetEntries_AssetTags.entryId = ");
sb.append("AssetEntry.entryId) INNER JOIN AssetTag ON ");
sb.append("(AssetTag.tagId = AssetEntries_AssetTags.tagId) ");
}
if (entryQuery.getLinkedAssetEntryId() > 0) {
sb.append("INNER JOIN AssetLink ON (AssetEntry.entryId = ");
sb.append("AssetLink.entryId1) OR (AssetEntry.entryId = ");
sb.append("AssetLink.entryId2)");
}
if (entryQuery.getOrderByCol1().equals("ratings") ||
entryQuery.getOrderByCol2().equals("ratings")) {
sb.append(" LEFT JOIN RatingsStats ON (RatingsStats.classNameId ");
sb.append("= AssetEntry.classNameId) AND (RatingsStats.classPK ");
sb.append("= AssetEntry.classPK)");
}
sb.append("WHERE ");
int whereIndex = sb.index();
if (entryQuery.getLinkedAssetEntryId() > 0) {
sb.append(" AND ((AssetLink.entryId1 = ?) OR (AssetLink.entryId2 ");
sb.append("= ?)) AND (AssetEntry.entryId != ?)");
}
if (entryQuery.isListable() != null) {
sb.append(" AND (listable = ?)");
}
if (entryQuery.isVisible() != null) {
sb.append(" AND (visible = ?)");
}
if (entryQuery.isExcludeZeroViewCount()) {
sb.append(" AND (AssetEntry.viewCount > 0)");
}
// Keywords
if (Validator.isNotNull(entryQuery.getKeywords())) {
sb.append(" AND ((AssetEntry.userName LIKE ?) OR ");
sb.append("(AssetEntry.title LIKE ?) OR (AssetEntry.description ");
sb.append("LIKE ?))");
}
else if (Validator.isNotNull(entryQuery.getUserName()) ||
Validator.isNotNull(entryQuery.getTitle()) ||
Validator.isNotNull(entryQuery.getDescription())) {
sb.append(" AND (");
boolean requiresOperator = false;
if (Validator.isNotNull(entryQuery.getUserName())) {
sb.append("(AssetEntry.userName LIKE ?)");
requiresOperator = true;
}
if (Validator.isNotNull(entryQuery.getTitle())) {
if (requiresOperator) {
sb.append(entryQuery.isAndOperator() ? " AND " : " OR ");
}
sb.append("(AssetEntry.title LIKE ?)");
requiresOperator = true;
}
if (Validator.isNotNull(entryQuery.getDescription())) {
if (requiresOperator) {
sb.append(entryQuery.isAndOperator() ? " AND " : " OR ");
}
sb.append("(AssetEntry.description LIKE ?)");
}
sb.append(")");
}
// Layout
Layout layout = entryQuery.getLayout();
if (layout != null) {
sb.append(" AND (AssetEntry.layoutUuid = ?)");
}
// Category conditions
if (entryQuery.getAllCategoryIds().length > 0) {
buildAllCategoriesSQL(entryQuery.getAllCategoryIds(), sb);
}
if (entryQuery.getAnyCategoryIds().length > 0) {
buildAnyCategoriesSQL(entryQuery.getAnyCategoryIds(), sb);
}
if (entryQuery.getNotAllCategoryIds().length > 0) {
buildNotAllCategoriesSQL(entryQuery.getNotAllCategoryIds(), sb);
}
if (entryQuery.getNotAnyCategoryIds().length > 0) {
buildNotAnyCategoriesSQL(entryQuery.getNotAnyCategoryIds(), sb);
}
// Asset entry subtypes
if (entryQuery.getClassTypeIds().length > 0) {
buildClassTypeIdsSQL(entryQuery.getClassTypeIds(), sb);
}
// Tag conditions
if (entryQuery.getAllTagIds().length > 0) {
buildAllTagsSQL(entryQuery.getAllTagIdsArray(), sb);
}
if (entryQuery.getAnyTagIds().length > 0) {
buildAnyTagsSQL(entryQuery.getAnyTagIds(), sb);
}
if (entryQuery.getNotAllTagIds().length > 0) {
buildNotAllTagsSQL(entryQuery.getNotAllTagIdsArray(), sb);
}
if (entryQuery.getNotAnyTagIds().length > 0) {
buildNotAnyTagsSQL(entryQuery.getNotAnyTagIds(), sb);
}
// Other conditions
sb.append(
getDates(
entryQuery.getPublishDate(), entryQuery.getExpirationDate()));
sb.append(getGroupIds(entryQuery.getGroupIds()));
sb.append(getClassNameIds(entryQuery.getClassNameIds()));
if (!count) {
sb.append(") TEMP_TABLE INNER JOIN AssetEntry AssetEntry ON ");
sb.append("TEMP_TABLE.entryId = AssetEntry.entryId ORDER BY ");
if (entryQuery.getOrderByCol1().equals("ratings")) {
sb.append("TEMP_TABLE.averageScore");
}
else {
sb.append("AssetEntry.");
sb.append(entryQuery.getOrderByCol1());
}
sb.append(StringPool.SPACE);
sb.append(entryQuery.getOrderByType1());
if (Validator.isNotNull(entryQuery.getOrderByCol2()) &&
!entryQuery.getOrderByCol1().equals(
entryQuery.getOrderByCol2())) {
if (entryQuery.getOrderByCol2().equals("ratings")) {
sb.append(", TEMP_TABLE.averageScore");
}
else {
sb.append(", AssetEntry.");
sb.append(entryQuery.getOrderByCol2());
}
sb.append(StringPool.SPACE);
sb.append(entryQuery.getOrderByType2());
}
}
if (sb.index() > whereIndex) {
String where = sb.stringAt(whereIndex);
if (where.startsWith(" AND")) {
sb.setStringAt(where.substring(4), whereIndex);
}
}
String sql = sb.toString();
SQLQuery q = session.createSynchronizedSQLQuery(sql);
if (count) {
q.addScalar(COUNT_COLUMN_NAME, Type.LONG);
}
else {
q.addEntity("AssetEntry", AssetEntryImpl.class);
}
QueryPos qPos = QueryPos.getInstance(q);
if (entryQuery.getLinkedAssetEntryId() > 0) {
qPos.add(entryQuery.getLinkedAssetEntryId());
qPos.add(entryQuery.getLinkedAssetEntryId());
qPos.add(entryQuery.getLinkedAssetEntryId());
}
if (entryQuery.isListable() != null) {
qPos.add(entryQuery.isListable());
}
if (entryQuery.isVisible() != null) {
qPos.add(entryQuery.isVisible());
}
if (Validator.isNotNull(entryQuery.getKeywords())) {
qPos.add(
StringUtil.quote(entryQuery.getKeywords(), StringPool.PERCENT));
qPos.add(
StringUtil.quote(entryQuery.getKeywords(), StringPool.PERCENT));
qPos.add(
StringUtil.quote(entryQuery.getKeywords(), StringPool.PERCENT));
}
else {
if (Validator.isNotNull(entryQuery.getUserName())) {
qPos.add(
StringUtil.quote(
entryQuery.getUserName(), StringPool.PERCENT));
}
if (Validator.isNotNull(entryQuery.getTitle())) {
qPos.add(
StringUtil.quote(
entryQuery.getTitle(), StringPool.PERCENT));
}
if (Validator.isNotNull(entryQuery.getDescription())) {
qPos.add(
StringUtil.quote(
entryQuery.getDescription(), StringPool.PERCENT));
}
}
if (layout != null) {
qPos.add(layout.getUuid());
}
setDates(
qPos, entryQuery.getPublishDate(), entryQuery.getExpirationDate());
qPos.add(entryQuery.getGroupIds());
qPos.add(entryQuery.getClassNameIds());
return q;
}
protected void buildClassTypeIdsSQL(long[] classTypeIds, StringBundler sb) {
sb.append(" AND (");
for (int i = 0; i < classTypeIds.length; i++) {
sb.append(" AssetEntry.classTypeId = ");
sb.append(classTypeIds[i]);
if ((i + 1) < classTypeIds.length) {
sb.append(" OR ");
}
else {
sb.append(StringPool.CLOSE_PARENTHESIS);
}
}
}
protected void buildNotAllCategoriesSQL(
long[] categoryIds, StringBundler sb) {
String findByAndCategoryIdsSQL = CustomSQLUtil.get(
FIND_BY_AND_CATEGORY_IDS);
sb.append(" AND (");
for (int i = 0; i < categoryIds.length; i++) {
sb.append("NOT ");
String sql = null;
if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
List<Long> treeCategoryIds = getSubcategoryIds(categoryIds[i]);
if (treeCategoryIds.size() > 1) {
sql = StringUtil.replace(
findByAndCategoryIdsSQL, "[$CATEGORY_ID$]",
StringUtil.merge(treeCategoryIds));
}
}
if (sql == null) {
sql = StringUtil.replace(
findByAndCategoryIdsSQL, " IN ([$CATEGORY_ID$])",
" = " + categoryIds[i]);
}
sb.append(sql);
if ((i + 1) < categoryIds.length) {
sb.append(" OR ");
}
}
sb.append(StringPool.CLOSE_PARENTHESIS);
}
protected void buildNotAllTagsSQL(long[][] tagIds, StringBundler sb) {
sb.append(" AND (");
for (int i = 0; i < tagIds.length; i++) {
sb.append("AssetEntry.entryId NOT IN (");
String sql = CustomSQLUtil.get(FIND_BY_AND_TAG_IDS);
sql = StringUtil.replace(sql, "[$TAG_ID$]", getTagIds(tagIds[i]));
sb.append(sql);
sb.append(StringPool.CLOSE_PARENTHESIS);
if (((i + 1) < tagIds.length) && (tagIds[i + 1].length > 0)) {
sb.append(" OR ");
}
}
sb.append(StringPool.CLOSE_PARENTHESIS);
}
protected void buildNotAnyCategoriesSQL(
long[] notCategoryIds, StringBundler sb) {
sb.append(" AND (NOT ");
String sql = CustomSQLUtil.get(FIND_BY_AND_CATEGORY_IDS);
String notCategoryIdsString = null;
if (PropsValues.ASSET_CATEGORIES_SEARCH_HIERARCHICAL) {
List<Long> notCategoryIdsList = new ArrayList<>();
for (long notCategoryId : notCategoryIds) {
notCategoryIdsList.addAll(getSubcategoryIds(notCategoryId));
}
notCategoryIdsString = StringUtil.merge(notCategoryIdsList);
}
else {
notCategoryIdsString = StringUtil.merge(notCategoryIds);
}
sb.append(
StringUtil.replace(sql, "[$CATEGORY_ID$]", notCategoryIdsString));
sb.append(StringPool.CLOSE_PARENTHESIS);
}
protected String buildNotAnyTagsSQL(long[] notTagIds, StringBundler sb) {
sb.append(" AND (");
for (int i = 0; i < notTagIds.length; i++) {
sb.append("AssetEntry.entryId NOT IN (");
String sql = CustomSQLUtil.get(FIND_BY_AND_TAG_IDS);
sql = StringUtil.replace(sql, "[$TAG_ID$]", getTagIds(notTagIds));
sb.append(sql);
sb.append(StringPool.CLOSE_PARENTHESIS);
if ((i + 1) < notTagIds.length) {
sb.append(" AND ");
}
}
sb.append(StringPool.CLOSE_PARENTHESIS);
return sb.toString();
}
protected String getClassNameIds(long[] classNameIds) {
if (classNameIds.length == 0) {
return StringPool.BLANK;
}
StringBundler sb = new StringBundler(classNameIds.length + 1);
sb.append(" AND (AssetEntry.classNameId = ?");
for (int i = 0; i < (classNameIds.length - 1); i++) {
sb.append(" OR AssetEntry.classNameId = ?");
}
sb.append(StringPool.CLOSE_PARENTHESIS);
return sb.toString();
}
protected String getDates(Date publishDate, Date expirationDate) {
StringBundler sb = new StringBundler(4);
if (publishDate != null) {
sb.append(" AND (AssetEntry.publishDate IS NULL OR ");
sb.append("AssetEntry.publishDate < ?)");
}
if (expirationDate != null) {
sb.append(" AND (AssetEntry.expirationDate IS NULL OR ");
sb.append("AssetEntry.expirationDate > ?)");
}
return sb.toString();
}
protected String getGroupIds(long[] groupIds) {
if (groupIds.length == 0) {
return StringPool.BLANK;
}
StringBundler sb = new StringBundler(groupIds.length + 1);
sb.append(" AND (AssetEntry.groupId = ?");
for (int i = 0; i < (groupIds.length - 1); i++) {
sb.append(" OR AssetEntry.groupId = ?");
}
sb.append(StringPool.CLOSE_PARENTHESIS);
return sb.toString();
}
protected List<Long> getSubcategoryIds(long parentCategoryId) {
AssetCategory parentAssetCategory = AssetCategoryUtil.fetchByPrimaryKey(
parentCategoryId);
if (parentAssetCategory == null) {
return Collections.emptyList();
}
return ListUtil.toList(
AssetCategoryUtil.getDescendants(parentAssetCategory),
AssetCategory.CATEGORY_ID_ACCESSOR);
}
protected String getTagIds(long[] tagIds) {
StringBundler sb = new StringBundler((tagIds.length * 3) - 1);
for (int i = 0; i < tagIds.length; i++) {
sb.append("tagId = ");
sb.append(tagIds[i]);
if ((i + 1) != tagIds.length) {
sb.append(" OR ");
}
}
return sb.toString();
}
protected void setDates(
QueryPos qPos, Date publishDate, Date expirationDate) {
if (publishDate != null) {
Timestamp publishDate_TS = CalendarUtil.getTimestamp(publishDate);
qPos.add(publishDate_TS);
}
if (expirationDate != null) {
Timestamp expirationDate_TS = CalendarUtil.getTimestamp(
expirationDate);
qPos.add(expirationDate_TS);
}
}
}