1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package io.wcm.handler.media;
21
22 import java.util.Arrays;
23 import java.util.HashMap;
24 import java.util.Map;
25 import java.util.Set;
26 import java.util.Objects;
27
28 import org.apache.commons.lang3.ArrayUtils;
29 import org.apache.commons.lang3.StringUtils;
30 import org.apache.commons.lang3.builder.EqualsBuilder;
31 import org.apache.commons.lang3.builder.HashCodeBuilder;
32 import org.apache.commons.lang3.builder.ToStringBuilder;
33 import org.apache.commons.lang3.builder.ToStringStyle;
34 import org.apache.sling.api.resource.ValueMap;
35 import org.apache.sling.api.wrappers.ValueMapDecorator;
36 import org.jetbrains.annotations.NotNull;
37 import org.jetbrains.annotations.Nullable;
38 import org.osgi.annotation.versioning.ProviderType;
39
40 import io.wcm.handler.media.format.MediaFormat;
41 import io.wcm.handler.media.markup.DragDropSupport;
42 import io.wcm.handler.media.markup.IPERatioCustomize;
43 import io.wcm.handler.mediasource.dam.AemRenditionType;
44 import io.wcm.handler.url.UrlMode;
45 import io.wcm.wcm.commons.contenttype.FileExtension;
46 import io.wcm.wcm.commons.util.AemObjectReflectionToStringBuilder;
47
48
49
50
51 @ProviderType
52 public final class MediaArgs implements Cloneable {
53
54 private MediaFormatOption[] mediaFormatOptions;
55 private boolean autoCrop;
56 private String[] fileExtensions;
57 private String enforceOutputFileExtension;
58 private UrlMode urlMode;
59 private long fixedWidth;
60 private long fixedHeight;
61 private boolean download;
62 private boolean contentDispositionAttachment;
63 private String altText;
64 private boolean forceAltValueFromAsset;
65 private boolean decorative;
66 private boolean dummyImage = true;
67 private String dummyImageUrl;
68 private Set<AemRenditionType> includeAssetAemRenditions;
69 private Boolean includeAssetThumbnails;
70 private Boolean includeAssetWebRenditions;
71 private ImageSizes imageSizes;
72 private PictureSource[] pictureSourceSets;
73 private Double imageQualityPercentage;
74 private DragDropSupport dragDropSupport = DragDropSupport.AUTO;
75 private IPERatioCustomize ipeRatioCustomize = IPERatioCustomize.AUTO;
76 private boolean dynamicMediaDisabled;
77 private boolean webOptimizedImageDeliveryDisabled;
78 private ValueMap properties;
79
80 private static final Set<String> ALLOWED_FORCED_FILE_EXTENSIONS = Set.of(
81 FileExtension.JPEG, FileExtension.PNG);
82
83
84
85
86 public MediaArgs() {
87
88 }
89
90
91
92
93 @SuppressWarnings("null")
94 public MediaArgs(@NotNull MediaFormat @NotNull... mediaFormats) {
95 mediaFormats(mediaFormats);
96 }
97
98
99
100
101 public MediaArgs(@NotNull String @NotNull... mediaFormatNames) {
102 mediaFormatNames(mediaFormatNames);
103 }
104
105
106
107
108
109 public MediaFormat @Nullable [] getMediaFormats() {
110 if (this.mediaFormatOptions != null) {
111 MediaFormat[] result = Arrays.stream(this.mediaFormatOptions)
112 .filter(option -> option.getMediaFormatName() == null)
113 .map(MediaFormatOption::getMediaFormat)
114 .toArray(size -> new MediaFormat[size]);
115 if (result.length > 0) {
116 return result;
117 }
118 }
119 return null;
120 }
121
122
123
124
125
126
127 public @NotNull MediaArgs mediaFormats(@Nullable MediaFormat @Nullable... values) {
128 if (values == null || values.length == 0) {
129 this.mediaFormatOptions = null;
130 }
131 else {
132 this.mediaFormatOptions = Arrays.stream(values)
133 .map(mediaFormat -> new MediaFormatOption(mediaFormat, false))
134 .toArray(size -> new MediaFormatOption[size]);
135 }
136 return this;
137 }
138
139
140
141
142
143
144 public @NotNull MediaArgs mandatoryMediaFormats(@NotNull MediaFormat @Nullable... values) {
145 if (values == null || values.length == 0) {
146 this.mediaFormatOptions = null;
147 }
148 else {
149 this.mediaFormatOptions = Arrays.stream(values)
150 .map(mediaFormat -> new MediaFormatOption(mediaFormat, true))
151 .toArray(size -> new MediaFormatOption[size]);
152 }
153 return this;
154 }
155
156
157
158
159
160
161 public @NotNull MediaArgs mediaFormat(MediaFormat value) {
162 if (value == null) {
163 this.mediaFormatOptions = null;
164 }
165 else {
166 this.mediaFormatOptions = new MediaFormatOption[] {
167 new MediaFormatOption(value, false)
168 };
169 }
170 return this;
171 }
172
173
174
175
176
177
178 public @NotNull MediaArgs mediaFormatsMandatory(boolean value) {
179 if (this.mediaFormatOptions != null) {
180 this.mediaFormatOptions = Arrays.stream(this.mediaFormatOptions)
181 .map(option -> option.withMandatory(value))
182 .toArray(size -> new MediaFormatOption[size]);
183 }
184 return this;
185 }
186
187
188
189
190
191 public String @Nullable [] getMediaFormatNames() {
192 if (this.mediaFormatOptions != null) {
193 String[] result = Arrays.stream(this.mediaFormatOptions)
194 .filter(option -> option.getMediaFormatName() != null)
195 .map(MediaFormatOption::getMediaFormatName)
196 .toArray(size -> new String[size]);
197 if (result.length > 0) {
198 return result;
199 }
200 }
201 return null;
202 }
203
204
205
206
207
208
209 public @NotNull MediaArgs mediaFormatNames(@NotNull String @Nullable... names) {
210 if (names == null || names.length == 0) {
211 this.mediaFormatOptions = null;
212 }
213 else {
214 this.mediaFormatOptions = Arrays.stream(names)
215 .map(name -> new MediaFormatOption(name, false))
216 .toArray(size -> new MediaFormatOption[size]);
217 }
218 return this;
219 }
220
221
222
223
224
225
226 public @NotNull MediaArgs mandatoryMediaFormatNames(@NotNull String @Nullable... names) {
227 if (names == null || names.length == 0) {
228 this.mediaFormatOptions = null;
229 }
230 else {
231 this.mediaFormatOptions = Arrays.stream(names)
232 .map(name -> new MediaFormatOption(name, true))
233 .toArray(size -> new MediaFormatOption[size]);
234 }
235 return this;
236 }
237
238
239
240
241
242
243 public @NotNull MediaArgs mediaFormatName(String name) {
244 if (name == null) {
245 this.mediaFormatOptions = null;
246 }
247 else {
248 this.mediaFormatOptions = new MediaFormatOption[] {
249 new MediaFormatOption(name, false)
250 };
251 }
252 return this;
253 }
254
255
256
257
258
259 public MediaFormatOption @Nullable [] getMediaFormatOptions() {
260 return this.mediaFormatOptions;
261 }
262
263
264
265
266
267
268 public @NotNull MediaArgs mediaFormatOptions(@NotNull MediaFormatOption @Nullable... values) {
269 if (values == null || values.length == 0) {
270 this.mediaFormatOptions = null;
271 }
272 else {
273 this.mediaFormatOptions = values;
274 }
275 return this;
276 }
277
278
279
280
281
282 public boolean isAutoCrop() {
283 return this.autoCrop;
284 }
285
286
287
288
289
290
291 public @NotNull MediaArgs autoCrop(boolean value) {
292 this.autoCrop = value;
293 return this;
294 }
295
296
297
298
299 public String @Nullable [] getFileExtensions() {
300 return this.fileExtensions;
301 }
302
303
304
305
306
307 public @NotNull MediaArgs fileExtensions(@NotNull String @Nullable... values) {
308 if (values == null || values.length == 0) {
309 this.fileExtensions = null;
310 }
311 else {
312 this.fileExtensions = values;
313 }
314 return this;
315 }
316
317
318
319
320
321 public @NotNull MediaArgs fileExtension(@Nullable String value) {
322 if (value == null) {
323 this.fileExtensions = null;
324 }
325 else {
326 this.fileExtensions = new String[] {
327 value
328 };
329 }
330 return this;
331 }
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347 public @Nullable String getEnforceOutputFileExtension() {
348 return this.enforceOutputFileExtension;
349 }
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366 public @NotNull MediaArgs enforceOutputFileExtension(@Nullable String value) {
367 if (!ALLOWED_FORCED_FILE_EXTENSIONS.contains(value)) {
368 throw new IllegalArgumentException("Allowed enforced output file extensions: "
369 + StringUtils.join(ALLOWED_FORCED_FILE_EXTENSIONS, ","));
370 }
371 this.enforceOutputFileExtension = value;
372 return this;
373 }
374
375
376
377
378 public @Nullable UrlMode getUrlMode() {
379 return this.urlMode;
380 }
381
382
383
384
385
386 public @NotNull MediaArgs urlMode(@Nullable UrlMode value) {
387 this.urlMode = value;
388 return this;
389 }
390
391
392
393
394
395 public long getFixedWidth() {
396 return this.fixedWidth;
397 }
398
399
400
401
402
403
404 public @NotNull MediaArgs fixedWidth(long value) {
405 this.fixedWidth = value;
406 return this;
407 }
408
409
410
411
412
413 public long getFixedHeight() {
414 return this.fixedHeight;
415 }
416
417
418
419
420
421
422 public @NotNull MediaArgs fixedHeight(long value) {
423 this.fixedHeight = value;
424 return this;
425 }
426
427
428
429
430
431
432
433 public @NotNull MediaArgs fixedDimension(long widthValue, long heightValue) {
434 this.fixedWidth = widthValue;
435 this.fixedHeight = heightValue;
436 return this;
437 }
438
439
440
441
442 public boolean isDownload() {
443 return this.download;
444 }
445
446
447
448
449
450 public @NotNull MediaArgs download(boolean value) {
451 this.download = value;
452 return this;
453 }
454
455
456
457
458 public boolean isContentDispositionAttachment() {
459 return this.contentDispositionAttachment;
460 }
461
462
463
464
465
466
467 public @NotNull MediaArgs contentDispositionAttachment(boolean value) {
468 this.contentDispositionAttachment = value;
469 return this;
470 }
471
472
473
474
475 public @Nullable String getAltText() {
476 return this.altText;
477 }
478
479
480
481
482
483
484
485 public @NotNull MediaArgs altText(@Nullable String value) {
486 this.altText = value;
487 return this;
488 }
489
490
491
492
493 public boolean isForceAltValueFromAsset() {
494 return this.forceAltValueFromAsset;
495 }
496
497
498
499
500
501
502 public @NotNull MediaArgs forceAltValueFromAsset(boolean value) {
503 this.forceAltValueFromAsset = value;
504 return this;
505 }
506
507
508
509
510 public boolean isDecorative() {
511 return this.decorative;
512 }
513
514
515
516
517
518 public @NotNull MediaArgs decorative(boolean value) {
519 this.decorative = value;
520 return this;
521 }
522
523
524
525
526 public boolean isDummyImage() {
527 return this.dummyImage;
528 }
529
530
531
532
533
534 public @NotNull MediaArgs dummyImage(boolean value) {
535 this.dummyImage = value;
536 return this;
537 }
538
539
540
541
542 public @Nullable String getDummyImageUrl() {
543 return this.dummyImageUrl;
544 }
545
546
547
548
549
550 public @NotNull MediaArgs dummyImageUrl(@Nullable String value) {
551 this.dummyImageUrl = value;
552 return this;
553 }
554
555
556
557
558
559 public @Nullable Set<AemRenditionType> getIncludeAssetAemRenditions() {
560 return this.includeAssetAemRenditions;
561 }
562
563
564
565
566
567
568 public @NotNull MediaArgs includeAssetAemRenditions(@Nullable Set<AemRenditionType> value) {
569 this.includeAssetAemRenditions = value;
570 return this;
571 }
572
573
574
575
576
577
578 @Deprecated(since = "2.0.0")
579 public @Nullable Boolean isIncludeAssetThumbnails() {
580 return this.includeAssetThumbnails;
581 }
582
583
584
585
586
587
588
589 @Deprecated(since = "2.0.0")
590 public @NotNull MediaArgs includeAssetThumbnails(boolean value) {
591 this.includeAssetThumbnails = value;
592 return this;
593 }
594
595
596
597
598
599
600
601 @Deprecated(since = "2.0.0")
602 public @Nullable Boolean isIncludeAssetWebRenditions() {
603 return this.includeAssetWebRenditions;
604 }
605
606
607
608
609
610
611
612 @Deprecated(since = "2.0.0")
613 public @NotNull MediaArgs includeAssetWebRenditions(boolean value) {
614 this.includeAssetWebRenditions = value;
615 return this;
616 }
617
618
619
620
621 public @Nullable ImageSizes getImageSizes() {
622 return this.imageSizes;
623 }
624
625
626
627
628
629 public @NotNull MediaArgs imageSizes(@Nullable ImageSizes value) {
630 this.imageSizes = value;
631 return this;
632 }
633
634
635
636
637 public PictureSource @Nullable [] getPictureSources() {
638 return this.pictureSourceSets;
639 }
640
641
642
643
644
645 public @NotNull MediaArgs pictureSources(@NotNull PictureSource @Nullable... value) {
646 this.pictureSourceSets = value;
647 return this;
648 }
649
650
651
652
653 public boolean isDynamicMediaDisabled() {
654 return this.dynamicMediaDisabled;
655 }
656
657
658
659
660
661 public @NotNull MediaArgs dynamicMediaDisabled(boolean value) {
662 this.dynamicMediaDisabled = value;
663 return this;
664 }
665
666
667
668
669 public boolean isWebOptimizedImageDeliveryDisabled() {
670 return this.webOptimizedImageDeliveryDisabled;
671 }
672
673
674
675
676
677 public @NotNull MediaArgs webOptimizedImageDeliveryDisabled(boolean value) {
678 this.webOptimizedImageDeliveryDisabled = value;
679 return this;
680 }
681
682
683
684
685 public @Nullable Double getImageQualityPercentage() {
686 return this.imageQualityPercentage;
687 }
688
689
690
691
692
693 public @NotNull MediaArgs imageQualityPercentage(@Nullable Double value) {
694 this.imageQualityPercentage = value;
695 return this;
696 }
697
698
699
700
701
702 public @NotNull DragDropSupport getDragDropSupport() {
703 return this.dragDropSupport;
704 }
705
706
707
708
709
710
711 public @NotNull MediaArgs dragDropSupport(@NotNull DragDropSupport value) {
712 this.dragDropSupport = value;
713 return this;
714 }
715
716
717
718
719 public IPERatioCustomize getIPERatioCustomize() {
720 return this.ipeRatioCustomize;
721 }
722
723
724
725
726
727 public @NotNull MediaArgs ipeRatioCustomize(@Nullable IPERatioCustomize value) {
728 this.ipeRatioCustomize = value;
729 return this;
730 }
731
732
733
734
735
736
737 public @NotNull MediaArgs properties(@NotNull Map<String, Object> map) {
738 getProperties().putAll(map);
739 return this;
740 }
741
742
743
744
745
746
747
748 public @NotNull MediaArgs property(@NotNull String key, @Nullable Object value) {
749 getProperties().put(key, value);
750 return this;
751 }
752
753
754
755
756
757 @NotNull
758 public ValueMap getProperties() {
759 if (this.properties == null) {
760 this.properties = new ValueMapDecorator(new HashMap<>());
761 }
762 return this.properties;
763 }
764
765 @Override
766 public int hashCode() {
767 return HashCodeBuilder.reflectionHashCode(this);
768 }
769
770 @Override
771 public boolean equals(Object obj) {
772 return EqualsBuilder.reflectionEquals(this, obj);
773 }
774
775 @Override
776 @SuppressWarnings("java:S3776")
777 public String toString() {
778 ToStringBuilder sb = new ToStringBuilder(this, ToStringStyle.NO_CLASS_NAME_STYLE);
779 if (mediaFormatOptions != null && mediaFormatOptions.length > 0) {
780 sb.append("mediaFormats", "[" + StringUtils.join(mediaFormatOptions, ", ") + "]");
781 }
782 if (autoCrop) {
783 sb.append("autoCrop", autoCrop);
784 }
785 if (fileExtensions != null && fileExtensions.length > 0) {
786 sb.append("fileExtensions", StringUtils.join(fileExtensions, ","));
787 }
788 if (enforceOutputFileExtension != null) {
789 sb.append("enforceOutputFileExtension", enforceOutputFileExtension);
790 }
791 if (urlMode != null) {
792 sb.append("urlMode", urlMode);
793 }
794 if (fixedWidth > 0) {
795 sb.append("fixedWidth", fixedWidth);
796 }
797 if (fixedHeight > 0) {
798 sb.append("fixedHeight", fixedHeight);
799 }
800 if (download) {
801 sb.append("download", download);
802 }
803 if (contentDispositionAttachment) {
804 sb.append("contentDispositionAttachment", contentDispositionAttachment);
805 }
806 if (altText != null) {
807 sb.append("altText", altText);
808 }
809 if (forceAltValueFromAsset) {
810 sb.append("forceAltValueFromAsset", forceAltValueFromAsset);
811 }
812 if (decorative) {
813 sb.append("decorative", decorative);
814 }
815 if (!dummyImage) {
816 sb.append("dummyImage ", dummyImage);
817 }
818 if (dummyImageUrl != null) {
819 sb.append("dummyImageUrl", dummyImageUrl);
820 }
821 if (includeAssetAemRenditions != null) {
822 sb.append("includeAssetAemRenditions", includeAssetAemRenditions);
823 }
824 if (includeAssetThumbnails != null) {
825 sb.append("includeAssetThumbnails", includeAssetThumbnails);
826 }
827 if (includeAssetWebRenditions != null) {
828 sb.append("includeAssetWebRenditions", includeAssetWebRenditions);
829 }
830 if (imageSizes != null) {
831 sb.append("imageSizes", imageSizes);
832 }
833 if (pictureSourceSets != null && pictureSourceSets.length > 0) {
834 sb.append("pictureSourceSets", "[" + StringUtils.join(pictureSourceSets, ",") + "]");
835 }
836 if (imageQualityPercentage != null) {
837 sb.append("imageQualityPercentage ", imageQualityPercentage);
838 }
839 if (dragDropSupport != DragDropSupport.AUTO) {
840 sb.append("dragDropSupport ", dragDropSupport);
841 }
842 if (ipeRatioCustomize != IPERatioCustomize.AUTO) {
843 sb.append("ipeRatioCustomize ", ipeRatioCustomize);
844 }
845 if (dynamicMediaDisabled) {
846 sb.append("dynamicMediaDisabled", dynamicMediaDisabled);
847 }
848 if (webOptimizedImageDeliveryDisabled) {
849 sb.append("webOptimizedImageDeliveryDisabled", webOptimizedImageDeliveryDisabled);
850 }
851 if (properties != null && !properties.isEmpty()) {
852 sb.append("properties", AemObjectReflectionToStringBuilder.filteredValueMap(properties));
853 }
854 return sb.build();
855 }
856
857
858
859
860
861 @Override
862 @SuppressWarnings({ "java:S2975", "java:S1182", "checkstyle:SuperCloneCheck" })
863 public MediaArgs clone() {
864 MediaArgs clone = new MediaArgs();
865
866 clone.mediaFormatOptions = ArrayUtils.clone(this.mediaFormatOptions);
867 clone.autoCrop = this.autoCrop;
868 clone.fileExtensions = ArrayUtils.clone(this.fileExtensions);
869 clone.enforceOutputFileExtension = this.enforceOutputFileExtension;
870 clone.urlMode = this.urlMode;
871 clone.fixedWidth = this.fixedWidth;
872 clone.fixedHeight = this.fixedHeight;
873 clone.download = this.download;
874 clone.contentDispositionAttachment = this.contentDispositionAttachment;
875 clone.altText = this.altText;
876 clone.forceAltValueFromAsset = this.forceAltValueFromAsset;
877 clone.decorative = this.decorative;
878 clone.dummyImage = this.dummyImage;
879 clone.dummyImageUrl = this.dummyImageUrl;
880 clone.includeAssetAemRenditions = this.includeAssetAemRenditions;
881 clone.includeAssetThumbnails = this.includeAssetThumbnails;
882 clone.includeAssetWebRenditions = this.includeAssetWebRenditions;
883 clone.imageSizes = this.imageSizes;
884 clone.pictureSourceSets = ArrayUtils.clone(this.pictureSourceSets);
885 clone.imageQualityPercentage = this.imageQualityPercentage;
886 clone.dragDropSupport = this.dragDropSupport;
887 clone.ipeRatioCustomize = this.ipeRatioCustomize;
888 clone.dynamicMediaDisabled = this.dynamicMediaDisabled;
889 clone.webOptimizedImageDeliveryDisabled = this.webOptimizedImageDeliveryDisabled;
890 if (this.properties != null) {
891 clone.properties = new ValueMapDecorator(new HashMap<>(this.properties));
892 }
893
894 return clone;
895 }
896
897
898
899
900 @ProviderType
901 public static final class MediaFormatOption {
902
903 private final MediaFormat mediaFormat;
904 private final String mediaFormatName;
905 private final boolean mandatory;
906
907
908
909
910
911 public MediaFormatOption(@Nullable MediaFormat mediaFormat, boolean mandatory) {
912 this.mediaFormat = mediaFormat;
913 this.mediaFormatName = null;
914 this.mandatory = mandatory;
915 }
916
917
918
919
920
921 public MediaFormatOption(@NotNull String mediaFormatName, boolean mandatory) {
922 this.mediaFormat = null;
923 this.mediaFormatName = mediaFormatName;
924 this.mandatory = mandatory;
925 }
926
927
928
929
930 public @Nullable MediaFormat getMediaFormat() {
931 return this.mediaFormat;
932 }
933
934
935
936
937 public @Nullable String getMediaFormatName() {
938 return this.mediaFormatName;
939 }
940
941
942
943
944 public boolean isMandatory() {
945 return this.mandatory;
946 }
947
948 @Override
949 public int hashCode() {
950 return HashCodeBuilder.reflectionHashCode(this);
951 }
952
953 @Override
954 public boolean equals(Object obj) {
955 return EqualsBuilder.reflectionEquals(this, obj);
956 }
957
958 @Override
959 public String toString() {
960 return mediaFormatToString(mediaFormat, mediaFormatName, mandatory);
961 }
962
963 @NotNull
964 MediaFormatOption withMandatory(boolean newMandatory) {
965 if (this.mediaFormat != null) {
966 return new MediaFormatOption(this.mediaFormat, newMandatory);
967 }
968 else {
969 return new MediaFormatOption(this.mediaFormatName, newMandatory);
970 }
971 }
972
973 static String mediaFormatToString(MediaFormat mediaFormat, String mediaFormatName, boolean mandatory) {
974 StringBuilder sb = new StringBuilder();
975 if (mediaFormat != null) {
976 sb.append(mediaFormat.toString());
977 }
978 else if (mediaFormatName != null) {
979 sb.append(mediaFormatName);
980 }
981 if (!mandatory) {
982 sb.append("[?]");
983 }
984 return sb.toString();
985 }
986
987 }
988
989
990
991
992 @ProviderType
993 public static final class ImageSizes {
994
995 private final @NotNull String sizes;
996 private final @NotNull WidthOption @NotNull [] widthOptions;
997
998
999
1000
1001
1002
1003 public ImageSizes(@NotNull String sizes, long @NotNull... widths) {
1004 this.sizes = sizes;
1005 this.widthOptions = Arrays.stream(widths)
1006 .distinct()
1007 .mapToObj(width -> new WidthOption(width, true))
1008 .toArray(WidthOption[]::new);
1009 }
1010
1011
1012
1013
1014
1015
1016 public ImageSizes(@NotNull String sizes, @NotNull WidthOption @NotNull... widthOptions) {
1017 this.sizes = sizes;
1018 this.widthOptions = widthOptions;
1019 }
1020
1021
1022
1023
1024
1025 public @NotNull String getSizes() {
1026 return this.sizes;
1027 }
1028
1029
1030
1031
1032 public @NotNull WidthOption @Nullable [] getWidthOptions() {
1033 return this.widthOptions;
1034 }
1035
1036
1037
1038
1039 public boolean hasDensityDescriptors() {
1040 return StringUtils.isEmpty(this.sizes) &&
1041 Arrays.stream(this.widthOptions).map(WidthOption::getDensity).anyMatch(Objects::nonNull);
1042 }
1043
1044 @Override
1045 public int hashCode() {
1046 return HashCodeBuilder.reflectionHashCode(this);
1047 }
1048
1049 @Override
1050 public boolean equals(Object obj) {
1051 return EqualsBuilder.reflectionEquals(this, obj);
1052 }
1053
1054 @Override
1055 @SuppressWarnings("null")
1056 public String toString() {
1057 ToStringBuilder sb = new ToStringBuilder(this, ToStringStyle.NO_CLASS_NAME_STYLE);
1058 sb.append("sizes", sizes);
1059 if (widthOptions != null && widthOptions.length > 0) {
1060 sb.append("widthOptions", StringUtils.join(widthOptions, ","));
1061 }
1062 return sb.build();
1063 }
1064
1065 }
1066
1067
1068
1069
1070 @ProviderType
1071 public static final class PictureSource {
1072
1073 private MediaFormat mediaFormat;
1074 private String mediaFormatName;
1075 private String media;
1076 private String sizes;
1077 private WidthOption[] widthOptions;
1078
1079
1080
1081
1082 public PictureSource(@NotNull MediaFormat mediaFormat) {
1083 this.mediaFormat = mediaFormat;
1084 }
1085
1086
1087
1088
1089 public PictureSource(@Nullable String mediaFormatName) {
1090 this.mediaFormatName = mediaFormatName;
1091 }
1092
1093 private static @NotNull WidthOption @NotNull [] toWidthOptions(long @NotNull... widths) {
1094 return Arrays.stream(widths)
1095 .distinct()
1096 .mapToObj(width -> new WidthOption(width, true))
1097 .toArray(WidthOption[]::new);
1098 }
1099
1100
1101
1102
1103 public @Nullable MediaFormat getMediaFormat() {
1104 return this.mediaFormat;
1105 }
1106
1107
1108
1109
1110 public @Nullable String getMediaFormatName() {
1111 return this.mediaFormatName;
1112 }
1113
1114
1115
1116
1117
1118 public PictureSource widthOptions(@NotNull WidthOption @NotNull... value) {
1119 this.widthOptions = value;
1120 return this;
1121 }
1122
1123
1124
1125
1126 public @NotNull WidthOption @Nullable [] getWidthOptions() {
1127 return this.widthOptions;
1128 }
1129
1130
1131
1132
1133
1134 public PictureSource widths(long @NotNull... value) {
1135 this.widthOptions = toWidthOptions(value);
1136 return this;
1137 }
1138
1139
1140
1141
1142
1143
1144 public PictureSource sizes(@Nullable String value) {
1145 this.sizes = value;
1146 return this;
1147 }
1148
1149
1150
1151
1152
1153 public @Nullable String getSizes() {
1154 return this.sizes;
1155 }
1156
1157
1158
1159
1160
1161
1162 public PictureSource media(@Nullable String value) {
1163 this.media = value;
1164 return this;
1165 }
1166
1167
1168
1169
1170
1171 public @Nullable String getMedia() {
1172 return this.media;
1173 }
1174
1175
1176
1177
1178 public boolean hasDensityDescriptors() {
1179 return StringUtils.isEmpty(this.sizes) &&
1180 Arrays.stream(this.widthOptions).map(WidthOption::getDensity).anyMatch(Objects::nonNull);
1181 }
1182
1183 @Override
1184 public int hashCode() {
1185 return HashCodeBuilder.reflectionHashCode(this);
1186 }
1187
1188 @Override
1189 public boolean equals(Object obj) {
1190 return EqualsBuilder.reflectionEquals(this, obj);
1191 }
1192
1193 @Override
1194 public String toString() {
1195 ToStringBuilder sb = new ToStringBuilder(this, ToStringStyle.NO_CLASS_NAME_STYLE);
1196 sb.append("mediaFormat", MediaFormatOption.mediaFormatToString(mediaFormat, mediaFormatName, true));
1197 if (media != null) {
1198 sb.append("media", media);
1199 }
1200 if (sizes != null) {
1201 sb.append("sizes", sizes);
1202 }
1203 if (widthOptions != null && widthOptions.length > 0) {
1204 sb.append("widthOptions", StringUtils.join(widthOptions, ","));
1205 }
1206 return sb.build();
1207 }
1208
1209 }
1210
1211
1212
1213
1214 @ProviderType
1215 public static final class WidthOption {
1216
1217 private final long width;
1218 private final boolean mandatory;
1219 private final String density;
1220
1221
1222
1223
1224 public WidthOption(long width) {
1225 this(width, null, true);
1226 }
1227
1228
1229
1230
1231
1232 public WidthOption(long width, @Nullable String density) {
1233 this(width, density, true);
1234 }
1235
1236
1237
1238
1239
1240 public WidthOption(long width, boolean mandatory) {
1241 this(width, null, mandatory);
1242 }
1243
1244
1245
1246
1247
1248
1249 public WidthOption(long width, @Nullable String density, boolean mandatory) {
1250 this.width = width;
1251 this.mandatory = mandatory;
1252 this.density = density;
1253 }
1254
1255
1256
1257
1258 public long getWidth() {
1259 return this.width;
1260 }
1261
1262
1263
1264
1265 public boolean isMandatory() {
1266 return this.mandatory;
1267 }
1268
1269
1270
1271
1272 public @Nullable String getDensity() {
1273 return density;
1274 }
1275
1276
1277
1278
1279 public @NotNull String getWidthDescriptor() {
1280 return String.format("%dw", this.width);
1281 }
1282
1283
1284
1285
1286 public @NotNull String getDensityDescriptor() {
1287 if (StringUtils.isEmpty(this.density) || StringUtils.equalsIgnoreCase(this.density, "1x")) {
1288 return StringUtils.EMPTY;
1289 }
1290 return this.density;
1291 }
1292
1293 @Override
1294 public int hashCode() {
1295 return HashCodeBuilder.reflectionHashCode(this);
1296 }
1297
1298 @Override
1299 public boolean equals(Object obj) {
1300 return EqualsBuilder.reflectionEquals(this, obj);
1301 }
1302
1303 @Override
1304 public String toString() {
1305 StringBuilder sb = new StringBuilder();
1306 sb.append(Long.toString(width));
1307 if (density != null) {
1308 sb.append(":").append(density);
1309 }
1310 if (!mandatory) {
1311 sb.append("?");
1312 }
1313 return sb.toString();
1314 }
1315
1316 }
1317
1318 }