001    /**
002     * Copyright (c) 2000-present 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.dynamicdatamapping.util;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.json.JSONArray;
019    import com.liferay.portal.kernel.json.JSONFactoryUtil;
020    import com.liferay.portal.kernel.language.LanguageUtil;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.search.Document;
024    import com.liferay.portal.kernel.util.ArrayUtil;
025    import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.HtmlUtil;
028    import com.liferay.portal.kernel.util.LocaleUtil;
029    import com.liferay.portal.kernel.util.PropsKeys;
030    import com.liferay.portal.kernel.util.PropsUtil;
031    import com.liferay.portal.kernel.util.StringBundler;
032    import com.liferay.portal.kernel.util.StringPool;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
035    import com.liferay.portlet.dynamicdatamapping.storage.DDMFormValues;
036    import com.liferay.portlet.dynamicdatamapping.storage.Field;
037    import com.liferay.portlet.dynamicdatamapping.storage.Fields;
038    
039    import java.io.Serializable;
040    
041    import java.math.BigDecimal;
042    
043    import java.text.Format;
044    
045    import java.util.Date;
046    import java.util.Locale;
047    import java.util.Set;
048    
049    /**
050     * @author Alexander Chow
051     */
052    public class DDMIndexerImpl implements DDMIndexer {
053    
054            @Override
055            public void addAttributes(
056                    Document document, DDMStructure ddmStructure,
057                    DDMFormValues ddmFormValues) {
058    
059                    long groupId = GetterUtil.getLong(
060                            document.get(com.liferay.portal.kernel.search.Field.GROUP_ID));
061    
062                    Set<Locale> locales = LanguageUtil.getAvailableLocales(groupId);
063    
064                    Fields fields = toFields(ddmStructure, ddmFormValues);
065    
066                    for (Field field : fields) {
067                            try {
068                                    String indexType = ddmStructure.getFieldProperty(
069                                            field.getName(), "indexType");
070    
071                                    if (Validator.isNull(indexType)) {
072                                            continue;
073                                    }
074    
075                                    for (Locale locale : locales) {
076                                            String name = encodeName(
077                                                    ddmStructure.getStructureId(), field.getName(), locale);
078    
079                                            Serializable value = field.getValue(locale);
080    
081                                            if (value instanceof BigDecimal) {
082                                                    document.addNumberSortable(name, (BigDecimal)value);
083                                            }
084                                            else if (value instanceof BigDecimal[]) {
085                                                    document.addNumberSortable(name, (BigDecimal[])value);
086                                            }
087                                            else if (value instanceof Boolean) {
088                                                    document.addKeywordSortable(name, (Boolean)value);
089                                            }
090                                            else if (value instanceof Boolean[]) {
091                                                    document.addKeywordSortable(name, (Boolean[])value);
092                                            }
093                                            else if (value instanceof Date) {
094                                                    document.addDate(name, (Date)value);
095                                            }
096                                            else if (value instanceof Date[]) {
097                                                    document.addDate(name, (Date[])value);
098                                            }
099                                            else if (value instanceof Double) {
100                                                    document.addNumberSortable(name, (Double)value);
101                                            }
102                                            else if (value instanceof Double[]) {
103                                                    document.addNumberSortable(name, (Double[])value);
104                                            }
105                                            else if (value instanceof Integer) {
106                                                    document.addNumberSortable(name, (Integer)value);
107                                            }
108                                            else if (value instanceof Integer[]) {
109                                                    document.addNumberSortable(name, (Integer[])value);
110                                            }
111                                            else if (value instanceof Long) {
112                                                    document.addNumberSortable(name, (Long)value);
113                                            }
114                                            else if (value instanceof Long[]) {
115                                                    document.addNumberSortable(name, (Long[])value);
116                                            }
117                                            else if (value instanceof Float) {
118                                                    document.addNumberSortable(name, (Float)value);
119                                            }
120                                            else if (value instanceof Float[]) {
121                                                    document.addNumberSortable(name, (Float[])value);
122                                            }
123                                            else if (value instanceof Number[]) {
124                                                    Number[] numbers = (Number[])value;
125    
126                                                    Double[] doubles = new Double[numbers.length];
127    
128                                                    for (int i = 0; i < numbers.length; i++) {
129                                                            doubles[i] = numbers[i].doubleValue();
130                                                    }
131    
132                                                    document.addNumberSortable(name, doubles);
133                                            }
134                                            else if (value instanceof Object[]) {
135                                                    String[] valuesString = ArrayUtil.toStringArray(
136                                                            (Object[])value);
137    
138                                                    if (indexType.equals("keyword")) {
139                                                            document.addKeywordSortable(name, valuesString);
140                                                    }
141                                                    else {
142                                                            document.addTextSortable(name, valuesString);
143                                                    }
144                                            }
145                                            else {
146                                                    String valueString = String.valueOf(value);
147    
148                                                    String type = field.getType();
149    
150                                                    if (type.equals(DDMImpl.TYPE_RADIO) ||
151                                                            type.equals(DDMImpl.TYPE_SELECT)) {
152    
153                                                            JSONArray jsonArray =
154                                                                    JSONFactoryUtil.createJSONArray(valueString);
155    
156                                                            String[] stringArray = ArrayUtil.toStringArray(
157                                                                    jsonArray);
158    
159                                                            if (indexType.equals("keyword")) {
160                                                                    document.addKeywordSortable(name, stringArray);
161                                                            }
162                                                            else {
163                                                                    document.addTextSortable(name, stringArray);
164                                                            }
165                                                    }
166                                                    else {
167                                                            if (type.equals(DDMImpl.TYPE_DDM_TEXT_HTML)) {
168                                                                    valueString = HtmlUtil.extractText(valueString);
169                                                            }
170    
171                                                            if (indexType.equals("keyword")) {
172                                                                    document.addKeywordSortable(name, valueString);
173                                                            }
174                                                            else {
175                                                                    document.addTextSortable(name, valueString);
176                                                            }
177                                                    }
178                                            }
179                                    }
180                            }
181                            catch (Exception e) {
182                                    if (_log.isWarnEnabled()) {
183                                            _log.warn(e, e);
184                                    }
185                            }
186                    }
187            }
188    
189            @Override
190            public String encodeName(long ddmStructureId, String fieldName) {
191                    return encodeName(ddmStructureId, fieldName, null);
192            }
193    
194            @Override
195            public String encodeName(
196                    long ddmStructureId, String fieldName, Locale locale) {
197    
198                    StringBundler sb = new StringBundler(7);
199    
200                    sb.append(DDM_FIELD_PREFIX);
201                    sb.append(ddmStructureId);
202                    sb.append(DDM_FIELD_SEPARATOR);
203                    sb.append(fieldName);
204    
205                    if (locale != null) {
206                            sb.append(StringPool.UNDERLINE);
207                            sb.append(LocaleUtil.toLanguageId(locale));
208                    }
209    
210                    return sb.toString();
211            }
212    
213            @Override
214            public String extractIndexableAttributes(
215                    DDMStructure ddmStructure, DDMFormValues ddmFormValues, Locale locale) {
216    
217                    Format dateFormat = FastDateFormatFactoryUtil.getSimpleDateFormat(
218                            PropsUtil.get(PropsKeys.INDEX_DATE_FORMAT_PATTERN));
219    
220                    StringBundler sb = new StringBundler();
221    
222                    Fields fields = toFields(ddmStructure, ddmFormValues);
223    
224                    for (Field field : fields) {
225                            try {
226                                    String indexType = ddmStructure.getFieldProperty(
227                                            field.getName(), "indexType");
228    
229                                    if (Validator.isNull(indexType)) {
230                                            continue;
231                                    }
232    
233                                    Serializable value = field.getValue(locale);
234    
235                                    if ((value instanceof Boolean) || (value instanceof Number)) {
236                                            sb.append(value);
237                                            sb.append(StringPool.SPACE);
238                                    }
239                                    else if (value instanceof Date) {
240                                            sb.append(dateFormat.format(value));
241                                            sb.append(StringPool.SPACE);
242                                    }
243                                    else if (value instanceof Date[]) {
244                                            Date[] dates = (Date[])value;
245    
246                                            for (Date date : dates) {
247                                                    sb.append(dateFormat.format(date));
248                                                    sb.append(StringPool.SPACE);
249                                            }
250                                    }
251                                    else if (value instanceof Object[]) {
252                                            Object[] values = (Object[])value;
253    
254                                            for (Object object : values) {
255                                                    sb.append(object);
256                                                    sb.append(StringPool.SPACE);
257                                            }
258                                    }
259                                    else {
260                                            String valueString = String.valueOf(value);
261    
262                                            String type = field.getType();
263    
264                                            if (type.equals(DDMImpl.TYPE_RADIO) ||
265                                                    type.equals(DDMImpl.TYPE_SELECT)) {
266    
267                                                    JSONArray jsonArray = JSONFactoryUtil.createJSONArray(
268                                                            valueString);
269    
270                                                    String[] stringArray = ArrayUtil.toStringArray(
271                                                            jsonArray);
272    
273                                                    sb.append(stringArray);
274                                                    sb.append(StringPool.SPACE);
275                                            }
276                                            else {
277                                                    if (type.equals(DDMImpl.TYPE_DDM_TEXT_HTML)) {
278                                                            valueString = HtmlUtil.extractText(valueString);
279                                                    }
280    
281                                                    sb.append(valueString);
282                                                    sb.append(StringPool.SPACE);
283                                            }
284                                    }
285                            }
286                            catch (Exception e) {
287                                    if (_log.isWarnEnabled()) {
288                                            _log.warn(e, e);
289                                    }
290                            }
291                    }
292    
293                    return sb.toString();
294            }
295    
296            protected Fields toFields(
297                    DDMStructure ddmStructure, DDMFormValues ddmFormValues) {
298    
299                    try {
300                            return DDMFormValuesToFieldsConverterUtil.convert(
301                                    ddmStructure, ddmFormValues);
302                    }
303                    catch (PortalException pe) {
304                            _log.error("Unable to convert DDMFormValues to Fields", pe);
305                    }
306    
307                    return new Fields();
308            }
309    
310            private static final Log _log = LogFactoryUtil.getLog(DDMIndexerImpl.class);
311    
312    }