001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.softwarecatalog.util;
016    
017    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
018    import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
019    import com.liferay.portal.kernel.dao.orm.Projection;
020    import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
021    import com.liferay.portal.kernel.dao.orm.ProjectionList;
022    import com.liferay.portal.kernel.dao.orm.Property;
023    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
024    import com.liferay.portal.kernel.search.BaseIndexer;
025    import com.liferay.portal.kernel.search.BooleanClauseOccur;
026    import com.liferay.portal.kernel.search.BooleanQuery;
027    import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
028    import com.liferay.portal.kernel.search.Document;
029    import com.liferay.portal.kernel.search.Field;
030    import com.liferay.portal.kernel.search.SearchContext;
031    import com.liferay.portal.kernel.search.SearchEngineUtil;
032    import com.liferay.portal.kernel.search.Summary;
033    import com.liferay.portal.kernel.util.GetterUtil;
034    import com.liferay.portal.kernel.util.HtmlUtil;
035    import com.liferay.portal.kernel.util.StringBundler;
036    import com.liferay.portal.kernel.util.StringPool;
037    import com.liferay.portal.kernel.util.Validator;
038    import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
039    import com.liferay.portal.util.PortalUtil;
040    import com.liferay.portal.util.PortletKeys;
041    import com.liferay.portlet.softwarecatalog.model.SCProductEntry;
042    import com.liferay.portlet.softwarecatalog.model.SCProductVersion;
043    import com.liferay.portlet.softwarecatalog.service.SCProductEntryLocalServiceUtil;
044    
045    import java.util.ArrayList;
046    import java.util.Collection;
047    import java.util.List;
048    import java.util.Locale;
049    
050    import javax.portlet.PortletURL;
051    
052    /**
053     * @author Jorge Ferrer
054     * @author Brian Wing Shun Chan
055     * @author Harry Mark
056     * @author Bruno Farache
057     * @author Raymond Augé
058     */
059    public class SCIndexer extends BaseIndexer {
060    
061            public static final String[] CLASS_NAMES = {SCProductEntry.class.getName()};
062    
063            public static final String PORTLET_ID = PortletKeys.SOFTWARE_CATALOG;
064    
065            public SCIndexer() {
066                    setStagingAware(false);
067            }
068    
069            public String[] getClassNames() {
070                    return CLASS_NAMES;
071            }
072    
073            public String getPortletId() {
074                    return PORTLET_ID;
075            }
076    
077            protected void addReindexCriteria(
078                    DynamicQuery dynamicQuery, long companyId) {
079    
080                    Property property = PropertyFactoryUtil.forName("companyId");
081    
082                    dynamicQuery.add(property.eq(companyId));
083            }
084    
085            @Override
086            protected void doDelete(Object obj) throws Exception {
087                    SCProductEntry productEntry = (SCProductEntry)obj;
088    
089                    deleteDocument(
090                            productEntry.getCompanyId(), productEntry.getProductEntryId());
091            }
092    
093            @Override
094            protected Document doGetDocument(Object obj) throws Exception {
095                    SCProductEntry productEntry = (SCProductEntry)obj;
096    
097                    Document document = getBaseModelDocument(PORTLET_ID, productEntry);
098    
099                    StringBundler sb = new StringBundler(15);
100    
101                    String longDescription = HtmlUtil.extractText(
102                            productEntry.getLongDescription());
103    
104                    sb.append(longDescription);
105    
106                    sb.append(StringPool.SPACE);
107                    sb.append(productEntry.getPageURL());
108                    sb.append(StringPool.SPACE);
109                    sb.append(productEntry.getRepoArtifactId());
110                    sb.append(StringPool.SPACE);
111                    sb.append(productEntry.getRepoGroupId());
112                    sb.append(StringPool.SPACE);
113    
114                    String shortDescription = HtmlUtil.extractText(
115                            productEntry.getShortDescription());
116    
117                    sb.append(shortDescription);
118    
119                    sb.append(StringPool.SPACE);
120                    sb.append(productEntry.getType());
121                    sb.append(StringPool.SPACE);
122                    sb.append(productEntry.getUserId());
123                    sb.append(StringPool.SPACE);
124    
125                    String userName = PortalUtil.getUserName(
126                            productEntry.getUserId(), productEntry.getUserName());
127    
128                    sb.append(userName);
129    
130                    document.addText(Field.CONTENT, sb.toString());
131    
132                    document.addText(Field.TITLE, productEntry.getName());
133                    document.addKeyword(Field.TYPE, productEntry.getType());
134    
135                    String version = StringPool.BLANK;
136    
137                    SCProductVersion latestProductVersion = productEntry.getLatestVersion();
138    
139                    if (latestProductVersion != null) {
140                            version = latestProductVersion.getVersion();
141                    }
142    
143                    document.addKeyword(Field.VERSION, version);
144    
145                    document.addText("longDescription", longDescription);
146                    document.addText("pageURL", productEntry.getPageURL());
147                    document.addKeyword("repoArtifactId", productEntry.getRepoArtifactId());
148                    document.addKeyword("repoGroupId", productEntry.getRepoGroupId());
149                    document.addText("shortDescription", shortDescription);
150    
151                    return document;
152            }
153    
154            @Override
155            protected Summary doGetSummary(
156                    Document document, Locale locale, String snippet,
157                    PortletURL portletURL) {
158    
159                    String productEntryId = document.get(Field.ENTRY_CLASS_PK);
160    
161                    portletURL.setParameter(
162                            "struts_action", "/software_catalog/view_product_entry");
163                    portletURL.setParameter("productEntryId", productEntryId);
164    
165                    Summary summary = createSummary(document, Field.TITLE, Field.CONTENT);
166    
167                    summary.setMaxContentLength(200);
168                    summary.setPortletURL(portletURL);
169    
170                    return summary;
171            }
172    
173            @Override
174            protected void doReindex(Object obj) throws Exception {
175                    SCProductEntry productEntry = (SCProductEntry)obj;
176    
177                    Document document = getDocument(productEntry);
178    
179                    SearchEngineUtil.updateDocument(
180                            getSearchEngineId(), productEntry.getCompanyId(), document);
181            }
182    
183            @Override
184            protected void doReindex(String className, long classPK) throws Exception {
185                    SCProductEntry productEntry =
186                            SCProductEntryLocalServiceUtil.getProductEntry(classPK);
187    
188                    doReindex(productEntry);
189            }
190    
191            @Override
192            protected void doReindex(String[] ids) throws Exception {
193                    long companyId = GetterUtil.getLong(ids[0]);
194    
195                    reindexProductEntries(companyId);
196            }
197    
198            @Override
199            protected String getPortletId(SearchContext searchContext) {
200                    return PORTLET_ID;
201            }
202    
203            @Override
204            protected void postProcessFullQuery(
205                            BooleanQuery fullQuery, SearchContext searchContext)
206                    throws Exception {
207    
208                    String type = (String)searchContext.getAttribute("type");
209    
210                    if (Validator.isNotNull(type)) {
211                            BooleanQuery searchQuery = BooleanQueryFactoryUtil.create(
212                                    searchContext);
213    
214                            searchQuery.addRequiredTerm("type", type);
215    
216                            fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
217                    }
218            }
219    
220            protected void reindexProductEntries(long companyId) throws Exception {
221                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
222                            SCProductEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
223    
224                    Projection minProductEntryIdProjection = ProjectionFactoryUtil.min(
225                            "productEntryId");
226                    Projection maxProductEntryIdProjection = ProjectionFactoryUtil.max(
227                            "productEntryId");
228    
229                    ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
230    
231                    projectionList.add(minProductEntryIdProjection);
232                    projectionList.add(maxProductEntryIdProjection);
233    
234                    dynamicQuery.setProjection(projectionList);
235    
236                    addReindexCriteria(dynamicQuery, companyId);
237    
238                    List<Object[]> results = SCProductEntryLocalServiceUtil.dynamicQuery(
239                            dynamicQuery);
240    
241                    Object[] minAndMaxProductEntryIds = results.get(0);
242    
243                    if ((minAndMaxProductEntryIds[0] == null) ||
244                            (minAndMaxProductEntryIds[1] == null)) {
245    
246                            return;
247                    }
248    
249                    long minProductEntryId = (Long)minAndMaxProductEntryIds[0];
250                    long maxProductEntryId = (Long)minAndMaxProductEntryIds[1];
251    
252                    long startProductEntryId = minProductEntryId;
253                    long endProductEntryId = startProductEntryId + DEFAULT_INTERVAL;
254    
255                    while (startProductEntryId <= maxProductEntryId) {
256                            reindexProductEntries(
257                                    companyId, startProductEntryId, endProductEntryId);
258    
259                            startProductEntryId = endProductEntryId;
260                            endProductEntryId += DEFAULT_INTERVAL;
261                    }
262            }
263    
264            protected void reindexProductEntries(
265                            long companyId, long startProductEntryId, long endProductEntryId)
266                    throws Exception {
267    
268                    DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(
269                            SCProductEntry.class, PACLClassLoaderUtil.getPortalClassLoader());
270    
271                    Property property = PropertyFactoryUtil.forName("productEntryId");
272    
273                    dynamicQuery.add(property.ge(startProductEntryId));
274                    dynamicQuery.add(property.lt(endProductEntryId));
275    
276                    addReindexCriteria(dynamicQuery, companyId);
277    
278                    List<SCProductEntry> productEntries =
279                            SCProductEntryLocalServiceUtil.dynamicQuery(dynamicQuery);
280    
281                    if (productEntries.isEmpty()) {
282                            return;
283                    }
284    
285                    Collection<Document> documents = new ArrayList<Document>(
286                            productEntries.size());
287    
288                    for (SCProductEntry productEntry : productEntries) {
289                            Document document = getDocument(productEntry);
290    
291                            documents.add(document);
292                    }
293    
294                    SearchEngineUtil.updateDocuments(
295                            getSearchEngineId(), companyId, documents);
296            }
297    
298    }