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