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