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