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.search.geolocation.GeoLocationPoint;
019 import com.liferay.portal.kernel.util.ArrayUtil;
020 import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
021 import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
022 import com.liferay.portal.kernel.util.FileUtil;
023 import com.liferay.portal.kernel.util.GetterUtil;
024 import com.liferay.portal.kernel.util.LocaleUtil;
025 import com.liferay.portal.kernel.util.LocalizationUtil;
026 import com.liferay.portal.kernel.util.PropsKeys;
027 import com.liferay.portal.kernel.util.PropsUtil;
028 import com.liferay.portal.kernel.util.SetUtil;
029 import com.liferay.portal.kernel.util.StringBundler;
030 import com.liferay.portal.kernel.util.StringPool;
031 import com.liferay.portal.kernel.util.StringUtil;
032 import com.liferay.portal.kernel.util.Validator;
033
034 import java.io.File;
035 import java.io.FileInputStream;
036 import java.io.IOException;
037 import java.io.InputStream;
038
039 import java.math.BigDecimal;
040
041 import java.text.DateFormat;
042 import java.text.Format;
043 import java.text.ParseException;
044
045 import java.util.Arrays;
046 import java.util.Collection;
047 import java.util.Collections;
048 import java.util.Date;
049 import java.util.HashMap;
050 import java.util.Locale;
051 import java.util.Map;
052 import java.util.Set;
053
054
058 public class DocumentImpl implements Document {
059
060 public static String getLocalizedName(Locale locale, String name) {
061 if (locale == null) {
062 return name;
063 }
064
065 String languageId = LocaleUtil.toLanguageId(locale);
066
067 return getLocalizedName(languageId, name);
068 }
069
070 public static String getLocalizedName(String languageId, String name) {
071 return LocalizationUtil.getLocalizedName(name, languageId);
072 }
073
074 public static String getSortableFieldName(String name) {
075 return name.concat(StringPool.UNDERLINE).concat(_SORTABLE_FIELD_SUFFIX);
076 }
077
078 public static String getSortFieldName(Sort sort, String scoreFieldName) {
079 if (sort.getType() == Sort.SCORE_TYPE) {
080 return scoreFieldName;
081 }
082
083 String fieldName = sort.getFieldName();
084
085 if (DocumentImpl.isSortableFieldName(fieldName)) {
086 return fieldName;
087 }
088
089 if ((sort.getType() == Sort.STRING_TYPE) &&
090 !DocumentImpl.isSortableTextField(fieldName)) {
091
092 return scoreFieldName;
093 }
094
095 return DocumentImpl.getSortableFieldName(fieldName);
096 }
097
098 public static boolean isSortableFieldName(String name) {
099 return name.endsWith(_SORTABLE_FIELD_SUFFIX);
100 }
101
102 public static boolean isSortableTextField(String name) {
103 return _defaultSortableTextFields.contains(name);
104 }
105
106 @Override
107 public void add(Field field) {
108 _fields.put(field.getName(), field);
109 }
110
111 @Override
112 public void addDate(String name, Date value) {
113 if (value == null) {
114 return;
115 }
116
117 addDate(name, new Date[] {value});
118 }
119
120 @Override
121 public void addDate(String name, Date[] values) {
122 if (values == null) {
123 return;
124 }
125
126 if (_dateFormat == null) {
127 _dateFormat = FastDateFormatFactoryUtil.getSimpleDateFormat(
128 _INDEX_DATE_FORMAT_PATTERN);
129 }
130
131 String[] dates = new String[values.length];
132 Long[] datesTime = new Long[values.length];
133
134 for (int i = 0; i < values.length; i++) {
135 dates[i] = _dateFormat.format(values[i]);
136 datesTime[i] = values[i].getTime();
137 }
138
139 createSortableNumericField(name, false, datesTime);
140
141 addKeyword(name, dates);
142 }
143
144 @Override
145 public void addFile(String name, byte[] bytes, String fileExt) {
146 InputStream is = new UnsyncByteArrayInputStream(bytes);
147
148 addFile(name, is, fileExt);
149 }
150
151 @Override
152 public void addFile(String name, File file, String fileExt)
153 throws IOException {
154
155 InputStream is = new FileInputStream(file);
156
157 addFile(name, is, fileExt);
158 }
159
160 @Override
161 public void addFile(String name, InputStream is, String fileExt) {
162 addText(name, FileUtil.extractText(is, fileExt));
163 }
164
165 @Override
166 public void addFile(
167 String name, InputStream is, String fileExt, int maxStringLength) {
168
169 addText(name, FileUtil.extractText(is, fileExt, maxStringLength));
170 }
171
172 @Override
173 public void addGeoLocation(double latitude, double longitude) {
174 Field field = new Field(Field.GEO_LOCATION);
175
176 field.setGeoLocationPoint(new GeoLocationPoint(latitude, longitude));
177
178 add(field);
179 }
180
181 @Override
182 public void addKeyword(String name, boolean value) {
183 addKeyword(name, String.valueOf(value));
184 }
185
186 @Override
187 public void addKeyword(String name, Boolean value) {
188 addKeyword(name, String.valueOf(value));
189 }
190
191 @Override
192 public void addKeyword(String name, boolean[] values) {
193 if (values == null) {
194 return;
195 }
196
197 addKeyword(name, ArrayUtil.toStringArray(values));
198 }
199
200 @Override
201 public void addKeyword(String name, Boolean[] values) {
202 if (values == null) {
203 return;
204 }
205
206 addKeyword(name, ArrayUtil.toStringArray(values));
207 }
208
209 @Override
210 public void addKeyword(String name, double value) {
211 addKeyword(name, String.valueOf(value));
212 }
213
214 @Override
215 public void addKeyword(String name, Double value) {
216 addKeyword(name, String.valueOf(value));
217 }
218
219 @Override
220 public void addKeyword(String name, double[] values) {
221 if (values == null) {
222 return;
223 }
224
225 addKeyword(name, ArrayUtil.toStringArray(values));
226 }
227
228 @Override
229 public void addKeyword(String name, Double[] 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, float value) {
239 addKeyword(name, String.valueOf(value));
240 }
241
242 @Override
243 public void addKeyword(String name, Float value) {
244 addKeyword(name, String.valueOf(value));
245 }
246
247 @Override
248 public void addKeyword(String name, float[] values) {
249 if (values == null) {
250 return;
251 }
252
253 addKeyword(name, ArrayUtil.toStringArray(values));
254 }
255
256 @Override
257 public void addKeyword(String name, Float[] 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, int value) {
267 addKeyword(name, String.valueOf(value));
268 }
269
270 @Override
271 public void addKeyword(String name, int[] values) {
272 if (values == null) {
273 return;
274 }
275
276 addKeyword(name, ArrayUtil.toStringArray(values));
277 }
278
279 @Override
280 public void addKeyword(String name, Integer value) {
281 addKeyword(name, String.valueOf(value));
282 }
283
284 @Override
285 public void addKeyword(String name, Integer[] values) {
286 if (values == null) {
287 return;
288 }
289
290 addKeyword(name, ArrayUtil.toStringArray(values));
291 }
292
293 @Override
294 public void addKeyword(String name, long value) {
295 addKeyword(name, String.valueOf(value));
296 }
297
298 @Override
299 public void addKeyword(String name, Long value) {
300 addKeyword(name, String.valueOf(value));
301 }
302
303 @Override
304 public void addKeyword(String name, long[] values) {
305 if (values == null) {
306 return;
307 }
308
309 addKeyword(name, ArrayUtil.toStringArray(values));
310 }
311
312 @Override
313 public void addKeyword(String name, Long[] values) {
314 if (values == null) {
315 return;
316 }
317
318 addKeyword(name, ArrayUtil.toStringArray(values));
319 }
320
321 @Override
322 public void addKeyword(String name, short value) {
323 addKeyword(name, String.valueOf(value));
324 }
325
326 @Override
327 public void addKeyword(String name, Short value) {
328 addKeyword(name, String.valueOf(value));
329 }
330
331 @Override
332 public void addKeyword(String name, short[] values) {
333 if (values == null) {
334 return;
335 }
336
337 addKeyword(name, ArrayUtil.toStringArray(values));
338 }
339
340 @Override
341 public void addKeyword(String name, Short[] values) {
342 if (values == null) {
343 return;
344 }
345
346 addKeyword(name, ArrayUtil.toStringArray(values));
347 }
348
349 @Override
350 public void addKeyword(String name, String value) {
351 addKeyword(name, value, false);
352 }
353
354 @Override
355 public void addKeyword(String name, String value, boolean lowerCase) {
356 createKeywordField(name, value, lowerCase);
357
358 createSortableKeywordField(name, value);
359 }
360
361 @Override
362 public void addKeyword(String name, String[] values) {
363 if (values == null) {
364 return;
365 }
366
367 createField(name, values);
368 }
369
370 @Override
371 public void addKeywordSortable(String name, Boolean value) {
372 String valueString = String.valueOf(value);
373
374 createKeywordField(name, valueString, false);
375
376 createSortableTextField(name, valueString);
377 }
378
379 @Override
380 public void addKeywordSortable(String name, Boolean[] values) {
381 if (values == null) {
382 return;
383 }
384
385 String[] valuesString = ArrayUtil.toStringArray(values);
386
387 createField(name, valuesString);
388
389 createSortableTextField(name, valuesString);
390 }
391
392 @Override
393 public void addKeywordSortable(String name, String value) {
394 createKeywordField(name, value, false);
395
396 createSortableTextField(name, value);
397 }
398
399 @Override
400 public void addKeywordSortable(String name, String[] values) {
401 createField(name, values);
402
403 createSortableTextField(name, values);
404 }
405
406 @Override
407 public void addLocalizedKeyword(String name, Map<Locale, String> values) {
408 addLocalizedKeyword(name, values, false);
409 }
410
411 @Override
412 public void addLocalizedKeyword(
413 String name, Map<Locale, String> values, boolean lowerCase) {
414
415 if ((values == null) || values.isEmpty()) {
416 return;
417 }
418
419 if (lowerCase) {
420 Map<Locale, String> lowerCaseValues = new HashMap<>(values.size());
421
422 for (Map.Entry<Locale, String> entry : values.entrySet()) {
423 String value = GetterUtil.getString(entry.getValue());
424
425 lowerCaseValues.put(
426 entry.getKey(), StringUtil.toLowerCase(value));
427 }
428
429 values = lowerCaseValues;
430 }
431
432 createField(name, values);
433 }
434
435 @Override
436 public void addLocalizedKeyword(
437 String name, Map<Locale, String> values, boolean lowerCase,
438 boolean sortable) {
439
440 if ((values == null) || values.isEmpty()) {
441 return;
442 }
443
444 if (lowerCase) {
445 Map<Locale, String> lowerCaseValues = new HashMap<>(values.size());
446
447 for (Map.Entry<Locale, String> entry : values.entrySet()) {
448 String value = GetterUtil.getString(entry.getValue());
449
450 lowerCaseValues.put(
451 entry.getKey(), StringUtil.toLowerCase(value));
452 }
453
454 values = lowerCaseValues;
455 }
456
457 createField(name, values, sortable);
458 }
459
460 @Override
461 public void addLocalizedText(String name, Map<Locale, String> values) {
462 if ((values == null) || values.isEmpty()) {
463 return;
464 }
465
466 Field field = createField(name, values);
467
468 field.setTokenized(true);
469 }
470
471 @Override
472 public void addNumber(String name, BigDecimal value) {
473 createNumberField(name, value);
474 }
475
476 @Override
477 public void addNumber(String name, BigDecimal[] values) {
478 createNumberField(name, values);
479 }
480
481 @Override
482 public void addNumber(String name, double value) {
483 createNumberField(name, Double.valueOf(value));
484 }
485
486 @Override
487 public void addNumber(String name, Double value) {
488 createNumberField(name, value);
489 }
490
491 @Override
492 public void addNumber(String name, double[] values) {
493 if (values == null) {
494 return;
495 }
496
497 createNumberField(name, ArrayUtil.toArray(values));
498 }
499
500 @Override
501 public void addNumber(String name, Double[] values) {
502 createNumberField(name, values);
503 }
504
505 @Override
506 public void addNumber(String name, float value) {
507 createNumberField(name, Float.valueOf(value));
508 }
509
510 @Override
511 public void addNumber(String name, Float value) {
512 createNumberField(name, value);
513 }
514
515 @Override
516 public void addNumber(String name, float[] values) {
517 if (values == null) {
518 return;
519 }
520
521 createNumberField(name, ArrayUtil.toArray(values));
522 }
523
524 @Override
525 public void addNumber(String name, Float[] values) {
526 createNumberField(name, values);
527 }
528
529 @Override
530 public void addNumber(String name, int value) {
531 createNumberField(name, Integer.valueOf(value));
532 }
533
534 @Override
535 public void addNumber(String name, int[] values) {
536 if (values == null) {
537 return;
538 }
539
540 createNumberField(name, ArrayUtil.toArray(values));
541 }
542
543 @Override
544 public void addNumber(String name, Integer value) {
545 createNumberField(name, value);
546 }
547
548 @Override
549 public void addNumber(String name, Integer[] values) {
550 createNumberField(name, values);
551 }
552
553 @Override
554 public void addNumber(String name, long value) {
555 createNumberField(name, Long.valueOf(value));
556 }
557
558 @Override
559 public void addNumber(String name, Long value) {
560 createNumberField(name, value);
561 }
562
563 @Override
564 public void addNumber(String name, long[] values) {
565 if (values == null) {
566 return;
567 }
568
569 createNumberField(name, ArrayUtil.toArray(values));
570 }
571
572 @Override
573 public void addNumber(String name, Long[] values) {
574 createNumberField(name, values);
575 }
576
577 @Override
578 public void addNumber(String name, String value) {
579 createNumberField(name, Long.valueOf(value));
580 }
581
582 @Override
583 public void addNumber(String name, String[] values) {
584 if (values == null) {
585 return;
586 }
587
588 Long[] longs = new Long[values.length];
589
590 for (int i = 0; i < values.length; i++) {
591 longs[i] = Long.valueOf(values[i]);
592 }
593
594 createNumberField(name, longs);
595 }
596
597 @Override
598 public void addNumberSortable(String name, BigDecimal value) {
599 createNumberFieldWithTypedSortable(name, value);
600 }
601
602 @Override
603 public void addNumberSortable(String name, BigDecimal[] values) {
604 createNumberFieldWithTypedSortable(name, values);
605 }
606
607 @Override
608 public void addNumberSortable(String name, Double value) {
609 createNumberFieldWithTypedSortable(name, value);
610 }
611
612 @Override
613 public void addNumberSortable(String name, Double[] values) {
614 createNumberFieldWithTypedSortable(name, values);
615 }
616
617 @Override
618 public void addNumberSortable(String name, Float value) {
619 createNumberFieldWithTypedSortable(name, value);
620 }
621
622 @Override
623 public void addNumberSortable(String name, Float[] values) {
624 createNumberFieldWithTypedSortable(name, values);
625 }
626
627 @Override
628 public void addNumberSortable(String name, Integer value) {
629 createNumberFieldWithTypedSortable(name, value);
630 }
631
632 @Override
633 public void addNumberSortable(String name, Integer[] values) {
634 createNumberFieldWithTypedSortable(name, values);
635 }
636
637 @Override
638 public void addNumberSortable(String name, Long value) {
639 createNumberFieldWithTypedSortable(name, value);
640 }
641
642 @Override
643 public void addNumberSortable(String name, Long[] values) {
644 createNumberFieldWithTypedSortable(name, values);
645 }
646
647 @Override
648 public void addText(String name, String value) {
649 if (Validator.isNull(value)) {
650 return;
651 }
652
653 Field field = createField(name, value);
654
655 field.setTokenized(true);
656
657 createSortableKeywordField(name, value);
658 }
659
660 @Override
661 public void addText(String name, String[] values) {
662 if (values == null) {
663 return;
664 }
665
666 Field field = createField(name, values);
667
668 field.setTokenized(true);
669
670 createSortableKeywordField(name, values);
671 }
672
673 @Override
674 public void addTextSortable(String name, String value) {
675 if (Validator.isNull(value)) {
676 return;
677 }
678
679 Field field = createField(name, value);
680
681 field.setTokenized(true);
682
683 createSortableTextField(name, value);
684 }
685
686 @Override
687 public void addTextSortable(String name, String[] values) {
688 if (values == null) {
689 return;
690 }
691
692 Field field = createField(name, values);
693
694 field.setTokenized(true);
695
696 createSortableTextField(name, values);
697 }
698
699 @Override
700 public void addUID(String portletId, long field1) {
701 addUID(portletId, String.valueOf(field1));
702 }
703
704 @Override
705 public void addUID(String portletId, long field1, String field2) {
706 addUID(portletId, String.valueOf(field1), field2);
707 }
708
709 @Override
710 public void addUID(String portletId, Long field1) {
711 addUID(portletId, field1.longValue());
712 }
713
714 @Override
715 public void addUID(String portletId, Long field1, String field2) {
716 addUID(portletId, field1.longValue(), field2);
717 }
718
719 @Override
720 public void addUID(String portletId, String field1) {
721 addUID(portletId, field1, null);
722 }
723
724 @Override
725 public void addUID(String portletId, String field1, String field2) {
726 addUID(portletId, field1, field2, null);
727 }
728
729 @Override
730 public void addUID(
731 String portletId, String field1, String field2, String field3) {
732
733 addUID(portletId, field1, field2, field3, null);
734 }
735
736 @Override
737 public void addUID(
738 String portletId, String field1, String field2, String field3,
739 String field4) {
740
741 String uid = portletId + _UID_PORTLET + field1;
742
743 if (field2 != null) {
744 uid += _UID_FIELD + field2;
745 }
746
747 if (field3 != null) {
748 uid += _UID_FIELD + field3;
749 }
750
751 if (field4 != null) {
752 uid += _UID_FIELD + field4;
753 }
754
755 addKeyword(Field.UID, uid);
756 }
757
758 @Override
759 public Object clone() {
760 DocumentImpl documentImpl = new DocumentImpl();
761
762 documentImpl.setSortableTextFields(_sortableTextFields);
763
764 return documentImpl;
765 }
766
767 @Override
768 public String get(Locale locale, String name) {
769 if (locale == null) {
770 return get(name);
771 }
772
773 String localizedName = getLocalizedName(locale, name);
774
775 Field field = getField(localizedName);
776
777 if (field == null) {
778 field = getField(name);
779 }
780
781 if (field == null) {
782 return StringPool.BLANK;
783 }
784
785 return field.getValue();
786 }
787
788 @Override
789 public String get(Locale locale, String name, String defaultName) {
790 if (locale == null) {
791 return get(name, defaultName);
792 }
793
794 String localizedName = getLocalizedName(locale, name);
795
796 Field field = getField(localizedName);
797
798 if (field == null) {
799 localizedName = getLocalizedName(locale, defaultName);
800
801 field = getField(localizedName);
802 }
803
804 if (field == null) {
805 return StringPool.BLANK;
806 }
807
808 return field.getValue();
809 }
810
811 @Override
812 public String get(String name) {
813 Field field = getField(name);
814
815 if (field == null) {
816 return StringPool.BLANK;
817 }
818
819 return field.getValue();
820 }
821
822 @Override
823 public String get(String name, String defaultName) {
824 Field field = getField(name);
825
826 if (field == null) {
827 return get(defaultName);
828 }
829
830 return field.getValue();
831 }
832
833 @Override
834 public Date getDate(String name) throws ParseException {
835 DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
836 _INDEX_DATE_FORMAT_PATTERN);
837
838 return dateFormat.parse(get(name));
839 }
840
841 @Override
842 public Field getField(String name) {
843 return doGetField(name, false);
844 }
845
846 @Override
847 public Map<String, Field> getFields() {
848 return _fields;
849 }
850
851 @Override
852 public String getPortletId() {
853 String uid = getUID();
854
855 int pos = uid.indexOf(_UID_PORTLET);
856
857 return uid.substring(0, pos);
858 }
859
860 @Override
861 public String getUID() {
862 Field field = getField(Field.UID);
863
864 if (field == null) {
865 throw new RuntimeException("UID is not set");
866 }
867
868 return field.getValue();
869 }
870
871 @Override
872 public String[] getValues(String name) {
873 Field field = getField(name);
874
875 if (field == null) {
876 return new String[] {StringPool.BLANK};
877 }
878
879 return field.getValues();
880 }
881
882 @Override
883 public boolean hasField(String name) {
884 if (_fields.containsKey(name)) {
885 return true;
886 }
887
888 return false;
889 }
890
891 @Override
892 public boolean isDocumentSortableTextField(String name) {
893 return _sortableTextFields.contains(name);
894 }
895
896 @Override
897 public void remove(String name) {
898 _fields.remove(name);
899 }
900
901 public void setFields(Map<String, Field> fields) {
902 _fields = fields;
903 }
904
905 @Override
906 public void setSortableTextFields(String[] sortableTextFields) {
907 _sortableTextFields = SetUtil.fromArray(sortableTextFields);
908 }
909
910 @Override
911 public String toString() {
912 StringBundler sb = new StringBundler(5 * _fields.size());
913
914 toString(sb, _fields.values());
915
916 return sb.toString();
917 }
918
919 protected Field createField(String name) {
920 return doGetField(name, true);
921 }
922
923 protected Field createField(
924 String name, boolean sortable, String... values) {
925
926 Field field = createField(name);
927
928 field.setSortable(sortable);
929 field.setValues(values);
930
931 return field;
932 }
933
934 protected Field createField(
935 String name, Map<Locale, String> localizedValues) {
936
937 return createField(name, localizedValues, false);
938 }
939
940 protected Field createField(
941 String name, Map<Locale, String> localizedValues, boolean sortable) {
942
943 Field field = createField(name);
944
945 field.setLocalizedValues(localizedValues);
946 field.setSortable(sortable);
947
948 return field;
949 }
950
951 protected Field createField(String name, String... values) {
952 return createField(name, false, values);
953 }
954
955 protected void createKeywordField(
956 String name, String value, boolean lowerCase) {
957
958 if (lowerCase && Validator.isNotNull(value)) {
959 value = StringUtil.toLowerCase(value);
960 }
961
962 createField(name, value);
963 }
964
965 protected void createNumberField(
966 String name, boolean typify, Number value) {
967
968 if (value == null) {
969 return;
970 }
971
972 String valueString = String.valueOf(value);
973
974 createSortableNumericField(name, typify, valueString, value.getClass());
975
976 createField(name, valueString);
977 }
978
979 protected <T extends Number & Comparable<? super T>> void createNumberField(
980 String name, boolean typify, T... values) {
981
982 if (values == null) {
983 return;
984 }
985
986 createSortableNumericField(name, typify, values);
987
988 createField(name, ArrayUtil.toStringArray(values));
989 }
990
991 protected void createNumberField(String name, Number value) {
992 createNumberField(name, false, value);
993 }
994
995 protected <T extends Number & Comparable<? super T>> void createNumberField(
996 String name, T... values) {
997
998 createNumberField(name, false, values);
999 }
1000
1001 protected void createNumberFieldWithTypedSortable(
1002 String name, Number value) {
1003
1004 createNumberField(name, true, value);
1005 }
1006
1007 protected <T extends Number & Comparable<? super T>> void
1008 createNumberFieldWithTypedSortable(String name, T... values) {
1009
1010 createNumberField(name, true, values);
1011 }
1012
1013 protected void createSortableKeywordField(String name, String value) {
1014 if (isDocumentSortableTextField(name)) {
1015 createSortableTextField(name, value);
1016 }
1017 }
1018
1019 protected void createSortableKeywordField(String name, String[] values) {
1020 if (isDocumentSortableTextField(name)) {
1021 createSortableTextField(name, values);
1022 }
1023 }
1024
1025 protected void createSortableNumericField(
1026 String name, boolean typify, String value,
1027 Class<? extends Number> clazz) {
1028
1029 if (typify) {
1030 name = name.concat(StringPool.UNDERLINE).concat("Number");
1031 }
1032
1033 Field field = createField(getSortableFieldName(name), value);
1034
1035 field.setNumeric(true);
1036 field.setNumericClass(clazz);
1037 }
1038
1039 protected <T extends Number & Comparable<? super T>> void
1040 createSortableNumericField(String name, boolean typify, T... values) {
1041
1042 if ((values == null) || (values.length == 0)) {
1043 return;
1044 }
1045
1046 T minValue = Collections.min(Arrays.asList(values));
1047
1048 createSortableNumericField(
1049 name, typify, String.valueOf(minValue), minValue.getClass());
1050 }
1051
1052 protected void createSortableTextField(String name, String value) {
1053 String truncatedValue = value;
1054
1055 if (value.length() > _SORTABLE_TEXT_FIELDS_TRUNCATED_LENGTH) {
1056 truncatedValue = value.substring(
1057 0, _SORTABLE_TEXT_FIELDS_TRUNCATED_LENGTH);
1058 }
1059
1060 createKeywordField(getSortableFieldName(name), truncatedValue, true);
1061 }
1062
1063 protected void createSortableTextField(String name, String[] values) {
1064 if (values.length == 0) {
1065 return;
1066 }
1067
1068 createSortableTextField(name, Collections.min(Arrays.asList(values)));
1069 }
1070
1071 protected Field doGetField(String name, boolean createIfNew) {
1072 Field field = _fields.get(name);
1073
1074 if ((field == null) && createIfNew) {
1075 field = new Field(name);
1076
1077 _fields.put(name, field);
1078 }
1079
1080 return field;
1081 }
1082
1083 protected void setSortableTextFields(Set<String> sortableTextFields) {
1084 _sortableTextFields = sortableTextFields;
1085 }
1086
1087 protected void toString(StringBundler sb, Collection<Field> fields) {
1088 sb.append(StringPool.OPEN_CURLY_BRACE);
1089
1090 boolean firstField = true;
1091
1092 for (Field field : fields) {
1093 if (!firstField) {
1094 sb.append(StringPool.COMMA);
1095 sb.append(StringPool.SPACE);
1096 }
1097 else {
1098 firstField = false;
1099 }
1100
1101 if (field.hasChildren()) {
1102 sb.append(field.getName());
1103 sb.append(StringPool.COLON);
1104
1105 toString(sb, field.getFields());
1106 }
1107 else {
1108 sb.append(field.getName());
1109 sb.append(StringPool.EQUAL);
1110 sb.append(Arrays.toString(field.getValues()));
1111 }
1112 }
1113
1114 sb.append(StringPool.CLOSE_CURLY_BRACE);
1115 }
1116
1117 private static final String _INDEX_DATE_FORMAT_PATTERN = PropsUtil.get(
1118 PropsKeys.INDEX_DATE_FORMAT_PATTERN);
1119
1120 private static final String _SORTABLE_FIELD_SUFFIX = "sortable";
1121
1122 private static final int _SORTABLE_TEXT_FIELDS_TRUNCATED_LENGTH =
1123 GetterUtil.getInteger(
1124 PropsUtil.get(
1125 PropsKeys.INDEX_SORTABLE_TEXT_FIELDS_TRUNCATED_LENGTH));
1126
1127 private static final String _UID_FIELD = "_FIELD_";
1128
1129 private static final String _UID_PORTLET = "_PORTLET_";
1130
1131 private static Format _dateFormat;
1132 private static final Set<String> _defaultSortableTextFields =
1133 SetUtil.fromArray(
1134 PropsUtil.getArray(PropsKeys.INDEX_SORTABLE_TEXT_FIELDS));
1135
1136 private Map<String, Field> _fields = new HashMap<>();
1137 private Set<String> _sortableTextFields = _defaultSortableTextFields;
1138
1139 }