001    /**
002     * Copyright (c) 2000-2013 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.portal.search.lucene;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.search.Document;
020    import com.liferay.portal.kernel.search.DocumentImpl;
021    import com.liferay.portal.kernel.search.Field;
022    import com.liferay.portal.kernel.search.IndexWriter;
023    import com.liferay.portal.kernel.search.SearchContext;
024    import com.liferay.portal.kernel.search.SearchException;
025    import com.liferay.portal.kernel.util.LocaleUtil;
026    import com.liferay.portal.kernel.util.Validator;
027    
028    import java.io.IOException;
029    
030    import java.util.Collection;
031    import java.util.Locale;
032    import java.util.Map;
033    
034    import org.apache.lucene.index.Term;
035    
036    /**
037     * @author Bruno Farache
038     * @author Brian Wing Shun Chan
039     * @author Allen Chiang
040     * @author Alex Wallace
041     */
042    public class LuceneIndexWriterImpl implements IndexWriter {
043    
044            @Override
045            public void addDocument(SearchContext searchContext, Document document)
046                    throws SearchException {
047    
048                    try {
049                            LuceneHelperUtil.addDocument(
050                                    searchContext.getCompanyId(), _getLuceneDocument(document));
051    
052                            if (_log.isDebugEnabled()) {
053                                    _log.debug("Added document " + document.get(Field.UID));
054                            }
055                    }
056                    catch (IOException ioe) {
057                            throw new SearchException(ioe);
058                    }
059            }
060    
061            @Override
062            public void addDocuments(
063                            SearchContext searchContext, Collection<Document> documents)
064                    throws SearchException {
065    
066                    for (Document document : documents) {
067                            addDocument(searchContext, document);
068                    }
069            }
070    
071            @Override
072            public void deleteDocument(SearchContext searchContext, String uid)
073                    throws SearchException {
074    
075                    try {
076                            LuceneHelperUtil.deleteDocuments(
077                                    searchContext.getCompanyId(), new Term(Field.UID, uid));
078    
079                            if (_log.isDebugEnabled()) {
080                                    _log.debug("Deleted document " + uid);
081                            }
082                    }
083                    catch (IOException ioe) {
084                            throw new SearchException(ioe);
085                    }
086            }
087    
088            @Override
089            public void deleteDocuments(
090                            SearchContext searchContext, Collection<String> uids)
091                    throws SearchException {
092    
093                    for (String uid : uids) {
094                            deleteDocument(searchContext, uid);
095                    }
096            }
097    
098            @Override
099            public void deletePortletDocuments(
100                            SearchContext searchContext, String portletId)
101                    throws SearchException {
102    
103                    try {
104                            LuceneHelperUtil.deleteDocuments(
105                                    searchContext.getCompanyId(), new Term(Field.PORTLET_ID,
106                                    portletId));
107                    }
108                    catch (IOException ioe) {
109                            throw new SearchException(ioe);
110                    }
111            }
112    
113            @Override
114            public void updateDocument(SearchContext searchContext, Document document)
115                    throws SearchException {
116    
117                    try {
118                            LuceneHelperUtil.updateDocument(
119                                    searchContext.getCompanyId(),
120                                    new Term(Field.UID, document.getUID()),
121                                    _getLuceneDocument(document));
122    
123                            if (_log.isDebugEnabled()) {
124                                    _log.debug("Updated document " + document.get(Field.UID));
125                            }
126                    }
127                    catch (IOException ioe) {
128                            throw new SearchException(ioe);
129                    }
130            }
131    
132            @Override
133            public void updateDocuments(
134                            SearchContext searchContext, Collection<Document> documents)
135                    throws SearchException {
136    
137                    for (Document document : documents) {
138                            updateDocument(searchContext, document);
139                    }
140            }
141    
142            private void _addLuceneFieldable(
143                    org.apache.lucene.document.Document luceneDocument, String name,
144                    boolean numeric, Class<? extends Number> numericClass,
145                    boolean tokenized, float boost, String value) {
146    
147                    org.apache.lucene.document.Fieldable luceneFieldable = null;
148    
149                    if (numeric) {
150                            luceneFieldable = LuceneFields.getNumber(name, value, numericClass);
151                    }
152                    else {
153                            if (tokenized) {
154                                    luceneFieldable = LuceneFields.getText(name, value);
155                            }
156                            else {
157                                    luceneFieldable = LuceneFields.getKeyword(name, value);
158                            }
159                    }
160    
161                    luceneFieldable.setBoost(boost);
162    
163                    luceneDocument.add(luceneFieldable);
164            }
165    
166            private org.apache.lucene.document.Document _getLuceneDocument(
167                    Document document) {
168    
169                    org.apache.lucene.document.Document luceneDocument =
170                            new org.apache.lucene.document.Document();
171    
172                    Collection<Field> fields = document.getFields().values();
173    
174                    for (Field field : fields) {
175                            String name = field.getName();
176                            boolean numeric = field.isNumeric();
177                            Class<? extends Number> numericClass = field.getNumericClass();
178                            boolean tokenized = field.isTokenized();
179                            float boost = field.getBoost();
180    
181                            if (!field.isLocalized()) {
182                                    for (String value : field.getValues()) {
183                                            if (Validator.isNull(value)) {
184                                                    continue;
185                                            }
186    
187                                            _addLuceneFieldable(
188                                                    luceneDocument, name, numeric, numericClass, tokenized,
189                                                    boost, value);
190                                    }
191                            }
192                            else {
193                                    Map<Locale, String> localizedValues =
194                                            field.getLocalizedValues();
195    
196                                    for (Map.Entry<Locale, String> entry :
197                                                    localizedValues.entrySet()) {
198    
199                                            String value = entry.getValue();
200    
201                                            if (Validator.isNull(value)) {
202                                                    continue;
203                                            }
204    
205                                            Locale locale = entry.getKey();
206    
207                                            String languageId = LocaleUtil.toLanguageId(locale);
208    
209                                            String defaultLanguageId = LocaleUtil.toLanguageId(
210                                                    LocaleUtil.getDefault());
211    
212                                            if (languageId.equals(defaultLanguageId)) {
213                                                    _addLuceneFieldable(
214                                                            luceneDocument, name, numeric, numericClass,
215                                                            tokenized, boost, value);
216                                            }
217    
218                                            String localizedName = DocumentImpl.getLocalizedName(
219                                                    locale, name);
220    
221                                            _addLuceneFieldable(
222                                                    luceneDocument, localizedName, numeric, numericClass,
223                                                    tokenized, boost, value);
224                                    }
225                            }
226    
227                    }
228    
229                    return luceneDocument;
230            }
231    
232            private static Log _log = LogFactoryUtil.getLog(
233                    LuceneIndexWriterImpl.class);
234    
235    }