/** * 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.dynamic.data.lists.internal.search; import com.liferay.dynamic.data.lists.model.DDLRecord; import com.liferay.dynamic.data.lists.model.DDLRecordSet; import com.liferay.dynamic.data.lists.model.DDLRecordSetConstants; import com.liferay.dynamic.data.lists.model.DDLRecordVersion; import com.liferay.dynamic.data.lists.service.DDLRecordLocalService; import com.liferay.dynamic.data.lists.service.DDLRecordSetLocalService; import com.liferay.dynamic.data.lists.service.DDLRecordVersionLocalService; import com.liferay.dynamic.data.mapping.model.DDMStructure; import com.liferay.dynamic.data.mapping.storage.DDMFormValues; import com.liferay.dynamic.data.mapping.storage.StorageEngine; import com.liferay.dynamic.data.mapping.util.DDMIndexer; import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery; import com.liferay.portal.kernel.dao.orm.DynamicQuery; import com.liferay.portal.kernel.dao.orm.IndexableActionableDynamicQuery; 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.exception.PortalException; import com.liferay.portal.kernel.language.LanguageUtil; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.search.BaseIndexer; import com.liferay.portal.kernel.search.BooleanClauseOccur; import com.liferay.portal.kernel.search.BooleanQuery; import com.liferay.portal.kernel.search.Document; import com.liferay.portal.kernel.search.Field; import com.liferay.portal.kernel.search.IndexWriterHelper; import com.liferay.portal.kernel.search.Indexer; import com.liferay.portal.kernel.search.SearchContext; import com.liferay.portal.kernel.search.SearchPermissionChecker; import com.liferay.portal.kernel.search.Summary; import com.liferay.portal.kernel.search.filter.BooleanFilter; import com.liferay.portal.kernel.search.filter.QueryFilter; import com.liferay.portal.kernel.service.ClassNameLocalService; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.LocaleUtil; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.workflow.WorkflowConstants; import java.io.Serializable; import java.util.Locale; import java.util.Set; import javax.portlet.PortletRequest; import javax.portlet.PortletResponse; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; /** * @author Marcellus Tavares */ @Component(immediate = true, service = Indexer.class) public class DDLRecordIndexer extends BaseIndexer<DDLRecord> { public static final String CLASS_NAME = DDLRecord.class.getName(); public DDLRecordIndexer() { setDefaultSelectedFieldNames( Field.COMPANY_ID, Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.UID); setDefaultSelectedLocalizedFieldNames(Field.DESCRIPTION, Field.TITLE); setPermissionAware(true); } @Override public String getClassName() { return CLASS_NAME; } @Override public BooleanFilter getFacetBooleanFilter( String className, SearchContext searchContext) throws Exception { BooleanFilter facetBooleanFilter = new BooleanFilter(); facetBooleanFilter.addTerm( Field.ENTRY_CLASS_NAME, DDLRecord.class.getName()); if (searchContext.getUserId() > 0) { facetBooleanFilter = searchPermissionChecker.getPermissionBooleanFilter( searchContext.getCompanyId(), searchContext.getGroupIds(), searchContext.getUserId(), DDLRecordSet.class.getName(), facetBooleanFilter, searchContext); } return facetBooleanFilter; } @Override public void postProcessContextBooleanFilter( BooleanFilter contextBooleanFilter, SearchContext searchContext) throws Exception { int status = GetterUtil.getInteger( searchContext.getAttribute(Field.STATUS), WorkflowConstants.STATUS_APPROVED); if (status != WorkflowConstants.STATUS_ANY) { contextBooleanFilter.addRequiredTerm(Field.STATUS, status); } long recordSetId = GetterUtil.getLong( searchContext.getAttribute("recordSetId")); if (recordSetId > 0) { contextBooleanFilter.addRequiredTerm("recordSetId", recordSetId); } long recordSetScope = GetterUtil.getLong( searchContext.getAttribute("recordSetScope"), DDLRecordSetConstants.SCOPE_DYNAMIC_DATA_LISTS); contextBooleanFilter.addRequiredTerm("recordSetScope", recordSetScope); addSearchClassTypeIds(contextBooleanFilter, searchContext); String ddmStructureFieldName = (String)searchContext.getAttribute( "ddmStructureFieldName"); Serializable ddmStructureFieldValue = searchContext.getAttribute( "ddmStructureFieldValue"); if (Validator.isNotNull(ddmStructureFieldName) && Validator.isNotNull(ddmStructureFieldValue)) { QueryFilter queryFilter = ddmIndexer.createFieldValueQueryFilter( ddmStructureFieldName, ddmStructureFieldValue, searchContext.getLocale()); contextBooleanFilter.add(queryFilter, BooleanClauseOccur.MUST); } } @Override public void postProcessSearchQuery( BooleanQuery searchQuery, BooleanFilter fullQueryBooleanFilter, SearchContext searchContext) throws Exception { addSearchTerm(searchQuery, searchContext, Field.USER_NAME, false); addDDMContentSearchTerm(searchQuery, searchContext); } protected void addDDMContent( DDLRecordVersion recordVersion, DDMFormValues ddmFormValues, Document document) throws Exception { Set<Locale> locales = ddmFormValues.getAvailableLocales(); for (Locale locale : locales) { StringBundler sb = new StringBundler(3); sb.append("ddmContent"); sb.append(StringPool.UNDERLINE); sb.append(LocaleUtil.toLanguageId(locale)); document.addText( sb.toString(), extractDDMContent(recordVersion, locale)); } } protected void addDDMContentSearchTerm( BooleanQuery searchQuery, SearchContext searchContext) throws Exception { Locale locale = searchContext.getLocale(); StringBundler sb = new StringBundler(3); sb.append("ddmContent"); sb.append(StringPool.UNDERLINE); sb.append(LocaleUtil.toLanguageId(locale)); addSearchTerm(searchQuery, searchContext, sb.toString(), false); } @Override protected void doDelete(DDLRecord ddlRecord) throws Exception { deleteDocument(ddlRecord.getCompanyId(), ddlRecord.getRecordId()); } @Override protected Document doGetDocument(DDLRecord ddlRecord) throws Exception { Document document = getBaseModelDocument(CLASS_NAME, ddlRecord); DDLRecordVersion recordVersion = ddlRecord.getRecordVersion(); DDLRecordSet recordSet = recordVersion.getRecordSet(); document.addKeyword( Field.CLASS_NAME_ID, classNameLocalService.getClassNameId(DDLRecordSet.class)); document.addKeyword(Field.CLASS_PK, recordSet.getRecordSetId()); document.addKeyword( Field.CLASS_TYPE_ID, recordVersion.getRecordSetId()); document.addKeyword(Field.RELATED_ENTRY, true); document.addKeyword(Field.STATUS, recordVersion.getStatus()); document.addKeyword(Field.VERSION, recordVersion.getVersion()); document.addKeyword("recordSetId", recordSet.getRecordSetId()); document.addKeyword("recordSetScope", recordSet.getScope()); DDMStructure ddmStructure = recordSet.getDDMStructure(); DDMFormValues ddmFormValues = storageEngine.getDDMFormValues( recordVersion.getDDMStorageId()); addDDMContent(recordVersion, ddmFormValues, document); ddmIndexer.addAttributes(document, ddmStructure, ddmFormValues); return document; } @Override protected Summary doGetSummary( Document document, Locale locale, String snippet, PortletRequest portletRequest, PortletResponse portletResponse) { long recordSetId = GetterUtil.getLong(document.get("recordSetId")); String title = getTitle(recordSetId, locale); Summary summary = createSummary( document, Field.TITLE, Field.DESCRIPTION); summary.setMaxContentLength(200); summary.setTitle(title); return summary; } @Override protected void doReindex(DDLRecord ddlRecord) throws Exception { Document document = getDocument(ddlRecord); indexWriterHelper.updateDocument( getSearchEngineId(), ddlRecord.getCompanyId(), document, isCommitImmediately()); } @Override protected void doReindex(String className, long classPK) throws Exception { DDLRecord record = ddlRecordLocalService.getRecord(classPK); doReindex(record); } @Override protected void doReindex(String[] ids) throws Exception { long companyId = GetterUtil.getLong(ids[0]); reindexRecords(companyId); } protected String extractDDMContent( DDLRecordVersion recordVersion, Locale locale) throws Exception { DDMFormValues ddmFormValues = storageEngine.getDDMFormValues( recordVersion.getDDMStorageId()); if (ddmFormValues == null) { return StringPool.BLANK; } DDLRecordSet recordSet = recordVersion.getRecordSet(); return ddmIndexer.extractIndexableAttributes( recordSet.getDDMStructure(), ddmFormValues, locale); } protected String getTitle(long recordSetId, Locale locale) { try { DDLRecordSet recordSet = ddlRecordSetLocalService.getRecordSet( recordSetId); DDMStructure ddmStructure = recordSet.getDDMStructure(); String ddmStructureName = ddmStructure.getName(locale); String recordSetName = recordSet.getName(locale); return LanguageUtil.format( locale, "new-x-for-list-x", new Object[] {ddmStructureName, recordSetName}, false); } catch (Exception e) { _log.error(e, e); } return StringPool.BLANK; } protected void reindexRecords(long companyId) throws Exception { final IndexableActionableDynamicQuery indexableActionableDynamicQuery = ddlRecordLocalService.getIndexableActionableDynamicQuery(); indexableActionableDynamicQuery.setAddCriteriaMethod( new ActionableDynamicQuery.AddCriteriaMethod() { @Override public void addCriteria(DynamicQuery dynamicQuery) { Property recordIdProperty = PropertyFactoryUtil.forName( "recordId"); DynamicQuery recordVersionDynamicQuery = ddlRecordVersionLocalService.dynamicQuery(); recordVersionDynamicQuery.setProjection( ProjectionFactoryUtil.property("recordId")); dynamicQuery.add( recordIdProperty.in(recordVersionDynamicQuery)); Property recordSetProperty = PropertyFactoryUtil.forName( "recordSetId"); DynamicQuery recordSetDynamicQuery = ddlRecordSetLocalService.dynamicQuery(); recordSetDynamicQuery.setProjection( ProjectionFactoryUtil.property("recordSetId")); Property scopeProperty = PropertyFactoryUtil.forName( "scope"); recordSetDynamicQuery.add( scopeProperty.in(_REINDEX_SCOPES)); dynamicQuery.add( recordSetProperty.in(recordSetDynamicQuery)); } }); indexableActionableDynamicQuery.setCompanyId(companyId); indexableActionableDynamicQuery.setPerformActionMethod( new ActionableDynamicQuery.PerformActionMethod<DDLRecord>() { @Override public void performAction(DDLRecord record) throws PortalException { try { Document document = getDocument(record); if (document != null) { indexableActionableDynamicQuery.addDocuments( document); } } catch (PortalException pe) { if (_log.isWarnEnabled()) { _log.warn( "Unable to index dynamic data lists record " + record.getRecordId(), pe); } } } }); indexableActionableDynamicQuery.setSearchEngineId(getSearchEngineId()); indexableActionableDynamicQuery.performActions(); } @Reference protected ClassNameLocalService classNameLocalService; @Reference protected DDLRecordLocalService ddlRecordLocalService; @Reference protected DDLRecordSetLocalService ddlRecordSetLocalService; @Reference protected DDLRecordVersionLocalService ddlRecordVersionLocalService; @Reference protected DDMIndexer ddmIndexer; @Reference protected IndexWriterHelper indexWriterHelper; @Reference protected SearchPermissionChecker searchPermissionChecker; @Reference protected StorageEngine storageEngine; private static final int[] _REINDEX_SCOPES = new int[] { DDLRecordSetConstants.SCOPE_DYNAMIC_DATA_LISTS, DDLRecordSetConstants.SCOPE_FORMS, DDLRecordSetConstants.SCOPE_KALEO_FORMS }; private static final Log _log = LogFactoryUtil.getLog( DDLRecordIndexer.class); }