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.portal.kernel.search;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
018    import com.liferay.portal.kernel.util.ArrayUtil;
019    import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
020    import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
021    import com.liferay.portal.kernel.util.FileUtil;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.LocaleUtil;
024    import com.liferay.portal.kernel.util.PropsKeys;
025    import com.liferay.portal.kernel.util.PropsUtil;
026    import com.liferay.portal.kernel.util.SetUtil;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.util.Validator;
030    
031    import java.io.File;
032    import java.io.FileInputStream;
033    import java.io.IOException;
034    import java.io.InputStream;
035    
036    import java.text.DateFormat;
037    import java.text.Format;
038    import java.text.ParseException;
039    
040    import java.util.Arrays;
041    import java.util.Date;
042    import java.util.HashMap;
043    import java.util.Locale;
044    import java.util.Map;
045    import java.util.Set;
046    
047    /**
048     * @author Brian Wing Shun Chan
049     * @author Bruno Farache
050     */
051    public class DocumentImpl implements Document {
052    
053            public static String getLocalizedName(Locale locale, String name) {
054                    if (locale == null) {
055                            return name;
056                    }
057    
058                    String languageId = LocaleUtil.toLanguageId(locale);
059    
060                    String localizedName = name.concat(StringPool.UNDERLINE).concat(
061                            languageId);
062    
063                    return localizedName;
064            }
065    
066            public static String getSortableFieldName(String name) {
067                    return name.concat(StringPool.UNDERLINE).concat(
068                            _SORTABLE_TEXT_FIELD_SUFFIX);
069            }
070    
071            public static boolean isSortableTextField(String name) {
072                    return _sortableTextFields.contains(name);
073            }
074    
075            public void add(Field field) {
076                    _fields.put(field.getName(), field);
077            }
078    
079            public void addDate(String name, Date value) {
080                    if (value == null) {
081                            return;
082                    }
083    
084                    addKeyword(name, _dateFormat.format(value));
085            }
086    
087            public void addFile(String name, byte[] bytes, String fileExt) {
088                    InputStream is = new UnsyncByteArrayInputStream(bytes);
089    
090                    addFile(name, is, fileExt);
091            }
092    
093            public void addFile(String name, File file, String fileExt)
094                    throws IOException {
095    
096                    InputStream is = new FileInputStream(file);
097    
098                    addFile(name, is, fileExt);
099            }
100    
101            public void addFile(String name, InputStream is, String fileExt) {
102                    addText(name, FileUtil.extractText(is, fileExt));
103            }
104    
105            public void addKeyword(String name, boolean value) {
106                    addKeyword(name, String.valueOf(value));
107            }
108    
109            public void addKeyword(String name, Boolean value) {
110                    addKeyword(name, String.valueOf(value));
111            }
112    
113            public void addKeyword(String name, boolean[] values) {
114                    if (values == null) {
115                            return;
116                    }
117    
118                    addKeyword(name, ArrayUtil.toStringArray(values));
119            }
120    
121            public void addKeyword(String name, Boolean[] values) {
122                    if (values == null) {
123                            return;
124                    }
125    
126                    addKeyword(name, ArrayUtil.toStringArray(values));
127            }
128    
129            public void addKeyword(String name, double value) {
130                    addKeyword(name, String.valueOf(value));
131            }
132    
133            public void addKeyword(String name, Double value) {
134                    addKeyword(name, String.valueOf(value));
135            }
136    
137            public void addKeyword(String name, double[] values) {
138                    if (values == null) {
139                            return;
140                    }
141    
142                    addKeyword(name, ArrayUtil.toStringArray(values));
143            }
144    
145            public void addKeyword(String name, Double[] values) {
146                    if (values == null) {
147                            return;
148                    }
149    
150                    addKeyword(name, ArrayUtil.toStringArray(values));
151            }
152    
153            public void addKeyword(String name, float value) {
154                    addKeyword(name, String.valueOf(value));
155            }
156    
157            public void addKeyword(String name, Float value) {
158                    addKeyword(name, String.valueOf(value));
159            }
160    
161            public void addKeyword(String name, float[] values) {
162                    if (values == null) {
163                            return;
164                    }
165    
166                    addKeyword(name, ArrayUtil.toStringArray(values));
167            }
168    
169            public void addKeyword(String name, Float[] values) {
170                    if (values == null) {
171                            return;
172                    }
173    
174                    addKeyword(name, ArrayUtil.toStringArray(values));
175            }
176    
177            public void addKeyword(String name, int value) {
178                    addKeyword(name, String.valueOf(value));
179            }
180    
181            public void addKeyword(String name, int[] values) {
182                    if (values == null) {
183                            return;
184                    }
185    
186                    addKeyword(name, ArrayUtil.toStringArray(values));
187            }
188    
189            public void addKeyword(String name, Integer value) {
190                    addKeyword(name, String.valueOf(value));
191            }
192    
193            public void addKeyword(String name, Integer[] values) {
194                    if (values == null) {
195                            return;
196                    }
197    
198                    addKeyword(name, ArrayUtil.toStringArray(values));
199            }
200    
201            public void addKeyword(String name, long value) {
202                    addKeyword(name, String.valueOf(value));
203            }
204    
205            public void addKeyword(String name, Long value) {
206                    addKeyword(name, String.valueOf(value));
207            }
208    
209            public void addKeyword(String name, long[] values) {
210                    if (values == null) {
211                            return;
212                    }
213    
214                    addKeyword(name, ArrayUtil.toStringArray(values));
215            }
216    
217            public void addKeyword(String name, Long[] values) {
218                    if (values == null) {
219                            return;
220                    }
221    
222                    addKeyword(name, ArrayUtil.toStringArray(values));
223            }
224    
225            public void addKeyword(String name, short value) {
226                    addKeyword(name, String.valueOf(value));
227            }
228    
229            public void addKeyword(String name, Short value) {
230                    addKeyword(name, String.valueOf(value));
231            }
232    
233            public void addKeyword(String name, short[] values) {
234                    if (values == null) {
235                            return;
236                    }
237    
238                    addKeyword(name, ArrayUtil.toStringArray(values));
239            }
240    
241            public void addKeyword(String name, Short[] values) {
242                    if (values == null) {
243                            return;
244                    }
245    
246                    addKeyword(name, ArrayUtil.toStringArray(values));
247            }
248    
249            public void addKeyword(String name, String value) {
250                    addKeyword(name, value, false);
251            }
252    
253            public void addKeyword(String name, String value, boolean lowerCase) {
254                    if (lowerCase && Validator.isNotNull(value)) {
255                            value = value.toLowerCase();
256                    }
257    
258                    Field field = new Field(name, value);
259    
260                    for (String fieldName : Field.UNSCORED_FIELD_NAMES) {
261                            if (name.equalsIgnoreCase(fieldName)) {
262                                    field.setBoost(0);
263                            }
264                    }
265    
266                    _fields.put(name, field);
267            }
268    
269            public void addKeyword(String name, String[] values) {
270                    if (values == null) {
271                            return;
272                    }
273    
274                    Field field = new Field(name, values);
275    
276                    _fields.put(name, field);
277            }
278    
279            public void addLocalizedKeyword(String name, Map<Locale, String> values) {
280                    if ((values == null) || values.isEmpty()) {
281                            return;
282                    }
283    
284                    Field field = new Field(name, values);
285    
286                    _fields.put(name, field);
287            }
288    
289            public void addLocalizedText(String name, Map<Locale, String> values) {
290                    if ((values == null) || values.isEmpty()) {
291                            return;
292                    }
293    
294                    Field field = new Field(name, values);
295    
296                    field.setTokenized(true);
297    
298                    _fields.put(name, field);
299            }
300    
301            /**
302             * @deprecated
303             */
304            public void addModifiedDate() {
305                    addModifiedDate(new Date());
306            }
307    
308            /**
309             * @deprecated
310             */
311            public void addModifiedDate(Date modifiedDate) {
312                    addDate(Field.MODIFIED, modifiedDate);
313            }
314    
315            public void addNumber(String name, double value) {
316                    addNumber(name, String.valueOf(value));
317            }
318    
319            public void addNumber(String name, Double value) {
320                    addNumber(name, String.valueOf(value));
321            }
322    
323            public void addNumber(String name, double[] values) {
324                    addNumber(name, ArrayUtil.toStringArray(values));
325            }
326    
327            public void addNumber(String name, Double[] values) {
328                    addNumber(name, String.valueOf(ArrayUtil.toStringArray(values)));
329            }
330    
331            public void addNumber(String name, float value) {
332                    addNumber(name, String.valueOf(value));
333            }
334    
335            public void addNumber(String name, Float value) {
336                    addNumber(name, String.valueOf(value));
337            }
338    
339            public void addNumber(String name, float[] values) {
340                    addNumber(name, ArrayUtil.toStringArray(values));
341            }
342    
343            public void addNumber(String name, Float[] values) {
344                    addNumber(name, ArrayUtil.toStringArray(values));
345            }
346    
347            public void addNumber(String name, int value) {
348                    addNumber(name, String.valueOf(value));
349            }
350    
351            public void addNumber(String name, int[] values) {
352                    addNumber(name, ArrayUtil.toStringArray(values));
353            }
354    
355            public void addNumber(String name, Integer value) {
356                    addNumber(name, String.valueOf(value));
357            }
358    
359            public void addNumber(String name, Integer[] values) {
360                    addNumber(name, ArrayUtil.toStringArray(values));
361            }
362    
363            public void addNumber(String name, long value) {
364                    addNumber(name, String.valueOf(value));
365            }
366    
367            public void addNumber(String name, Long value) {
368                    addNumber(name, String.valueOf(value));
369            }
370    
371            public void addNumber(String name, long[] values) {
372                    addNumber(name, ArrayUtil.toStringArray(values));
373            }
374    
375            public void addNumber(String name, Long[] values) {
376                    addNumber(name, ArrayUtil.toStringArray(values));
377            }
378    
379            public void addNumber(String name, String value) {
380                    if (Validator.isNotNull(value)) {
381                            Field field = new Field(name, value);
382    
383                            field.setNumeric(true);
384    
385                            _fields.put(name, field);
386                    }
387            }
388    
389            public void addNumber(String name, String[] values) {
390                    if (values == null) {
391                            return;
392                    }
393    
394                    Field field = new Field(name, values);
395    
396                    field.setNumeric(true);
397    
398                    _fields.put(name, field);
399            }
400    
401            public void addText(String name, String value) {
402                    if (Validator.isNull(value)) {
403                            return;
404                    }
405    
406                    Field field = new Field(name, value);
407    
408                    field.setTokenized(true);
409    
410                    _fields.put(name, field);
411    
412                    if (_sortableTextFields.contains(name)) {
413                            String truncatedValue = value;
414    
415                            if (value.length() > _SORTABLE_TEXT_FIELDS_TRUNCATED_LENGTH) {
416                                    truncatedValue = value.substring(
417                                            0, _SORTABLE_TEXT_FIELDS_TRUNCATED_LENGTH);
418                            }
419    
420                            addKeyword(getSortableFieldName(name), truncatedValue);
421                    }
422            }
423    
424            public void addText(String name, String[] values) {
425                    if (values == null) {
426                            return;
427                    }
428    
429                    Field field = new Field(name, values);
430    
431                    field.setTokenized(true);
432    
433                    _fields.put(name, field);
434            }
435    
436            public void addUID(String portletId, long field1) {
437                    addUID(portletId, String.valueOf(field1));
438            }
439    
440            public void addUID(String portletId, long field1, String field2) {
441                    addUID(portletId, String.valueOf(field1), field2);
442            }
443    
444            public void addUID(String portletId, Long field1) {
445                    addUID(portletId, field1.longValue());
446            }
447    
448            public void addUID(String portletId, Long field1, String field2) {
449                    addUID(portletId, field1.longValue(), field2);
450            }
451    
452            public void addUID(String portletId, String field1) {
453                    addUID(portletId, field1, null);
454            }
455    
456            public void addUID(String portletId, String field1, String field2) {
457                    addUID(portletId, field1, field2, null);
458            }
459    
460            public void addUID(
461                    String portletId, String field1, String field2, String field3) {
462    
463                    addUID(portletId, field1, field2, field3, null);
464            }
465    
466            public void addUID(
467                    String portletId, String field1, String field2, String field3,
468                    String field4) {
469    
470                    String uid = portletId + _UID_PORTLET + field1;
471    
472                    if (field2 != null) {
473                            uid += _UID_FIELD + field2;
474                    }
475    
476                    if (field3 != null) {
477                            uid += _UID_FIELD + field3;
478                    }
479    
480                    if (field4 != null) {
481                            uid += _UID_FIELD + field4;
482                    }
483    
484                    addKeyword(Field.UID, uid);
485            }
486    
487            public String get(Locale locale, String name) {
488                    if (locale == null) {
489                            return get(name);
490                    }
491    
492                    String localizedName = getLocalizedName(locale, name);
493    
494                    Field field = _fields.get(localizedName);
495    
496                    if (field == null) {
497                            field = _fields.get(name);
498                    }
499    
500                    if (field == null) {
501                            return StringPool.BLANK;
502                    }
503    
504                    return field.getValue();
505            }
506    
507            public String get(Locale locale, String name, String defaultName) {
508                    if (locale == null) {
509                            return get(name, defaultName);
510                    }
511    
512                    String localizedName = getLocalizedName(locale, name);
513    
514                    Field field = _fields.get(localizedName);
515    
516                    if (field == null) {
517                            localizedName = getLocalizedName(locale, defaultName);
518    
519                            field = _fields.get(localizedName);
520                    }
521    
522                    if (field == null) {
523                            return StringPool.BLANK;
524                    }
525    
526                    return field.getValue();
527            }
528    
529            public String get(String name) {
530                    Field field = _fields.get(name);
531    
532                    if (field == null) {
533                            return StringPool.BLANK;
534                    }
535    
536                    return field.getValue();
537            }
538    
539            public String get(String name, String defaultName) {
540                    Field field = _fields.get(name);
541    
542                    if (field == null) {
543                            return get(defaultName);
544                    }
545    
546                    return field.getValue();
547            }
548    
549            public Date getDate(String name) throws ParseException {
550                    DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
551                            _INDEX_DATE_FORMAT_PATTERN);
552    
553                    return dateFormat.parse(get(name));
554            }
555    
556            public Field getField(String name) {
557                    return _fields.get(name);
558            }
559    
560            public Map<String, Field> getFields() {
561                    return _fields;
562            }
563    
564            public String getPortletId() {
565                    String uid = getUID();
566    
567                    int pos = uid.indexOf(_UID_PORTLET);
568    
569                    return uid.substring(0, pos);
570            }
571    
572            public String getUID() {
573                    Field field = _fields.get(Field.UID);
574    
575                    if (field == null) {
576                            throw new RuntimeException("UID is not set");
577                    }
578    
579                    return field.getValue();
580            }
581    
582            public String[] getValues(String name) {
583                    Field field = _fields.get(name);
584    
585                    if (field == null) {
586                            return new String[] {StringPool.BLANK};
587                    }
588    
589                    return field.getValues();
590            }
591    
592            public void remove(String name) {
593                    _fields.remove(name);
594            }
595    
596            public void setFields(Map<String, Field> fields) {
597                    _fields = fields;
598            }
599    
600            @Override
601            public String toString() {
602                    StringBundler sb = new StringBundler();
603    
604                    sb.append(StringPool.OPEN_CURLY_BRACE);
605    
606                    boolean firstField = true;
607    
608                    for (Field field : _fields.values()) {
609                            if (!firstField) {
610                                    sb.append(StringPool.COMMA);
611                                    sb.append(StringPool.SPACE);
612                            }
613                            else {
614                                    firstField = false;
615                            }
616    
617                            sb.append(field.getName());
618                            sb.append(StringPool.EQUAL);
619                            sb.append(Arrays.toString(field.getValues()));
620                    }
621    
622                    sb.append(StringPool.CLOSE_CURLY_BRACE);
623    
624                    return sb.toString();
625            }
626    
627            private static final String _INDEX_DATE_FORMAT_PATTERN = PropsUtil.get(
628                    PropsKeys.INDEX_DATE_FORMAT_PATTERN);
629    
630            private static final String _SORTABLE_TEXT_FIELD_SUFFIX = "sortable";
631    
632            private static final int _SORTABLE_TEXT_FIELDS_TRUNCATED_LENGTH =
633                    GetterUtil.getInteger(
634                            PropsUtil.get(
635                                    PropsKeys.INDEX_SORTABLE_TEXT_FIELDS_TRUNCATED_LENGTH));
636    
637            private static final String _UID_FIELD = "_FIELD_";
638    
639            private static final String _UID_PORTLET = "_PORTLET_";
640    
641            private static Format _dateFormat =
642                    FastDateFormatFactoryUtil.getSimpleDateFormat(
643                            _INDEX_DATE_FORMAT_PATTERN);
644            private static Set<String> _sortableTextFields = SetUtil.fromArray(
645                    PropsUtil.getArray(PropsKeys.INDEX_SORTABLE_TEXT_FIELDS));
646    
647            private Map<String, Field> _fields = new HashMap<String, Field>();
648    
649    }