View Javadoc
1   /*
2    * #%L
3    * wcm.io
4    * %%
5    * Copyright (C) 2014 wcm.io
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package io.wcm.handler.media.spi;
21  
22  import java.util.Collections;
23  import java.util.EnumSet;
24  import java.util.List;
25  import java.util.Set;
26  
27  import org.jetbrains.annotations.NotNull;
28  import org.jetbrains.annotations.Nullable;
29  import org.osgi.annotation.versioning.ConsumerType;
30  
31  import com.day.cq.wcm.api.Page;
32  
33  import io.wcm.handler.media.MediaFileType;
34  import io.wcm.handler.media.MediaNameConstants;
35  import io.wcm.handler.media.markup.DummyImageMediaMarkupBuilder;
36  import io.wcm.handler.media.markup.MediaMarkupBuilderUtil;
37  import io.wcm.handler.media.markup.SimpleImageMediaMarkupBuilder;
38  import io.wcm.handler.mediasource.dam.AemRenditionType;
39  import io.wcm.handler.mediasource.dam.DamMediaSource;
40  import io.wcm.sling.commons.caservice.ContextAwareService;
41  
42  /**
43   * {@link MediaHandlerConfig} OSGi services provide application-specific configuration for media handling.
44   * Applications can set service properties or bundle headers as defined in {@link ContextAwareService} to apply this
45   * configuration only for resources that match the relevant resource paths.
46   */
47  @ConsumerType
48  public abstract class MediaHandlerConfig implements ContextAwareService {
49  
50    /**
51     * Default image quality for images with lossy compressions (e.g. JPEG).
52     */
53    public static final double DEFAULT_IMAGE_QUALITY = 0.85d;
54  
55    /**
56     * Default value for JPEG quality.
57     * @deprecated Use {@link #DEFAULT_IMAGE_QUALITY} instead.
58     */
59    @Deprecated(since = "2.0.0")
60    public static final double DEFAULT_JPEG_QUALITY = DEFAULT_IMAGE_QUALITY;
61  
62    private static final List<Class<? extends MediaSource>> DEFAULT_MEDIA_SOURCES = List.of(
63        DamMediaSource.class);
64  
65    private static final List<Class<? extends MediaMarkupBuilder>> DEFAULT_MEDIA_MARKUP_BUILDERS = List.of(
66        SimpleImageMediaMarkupBuilder.class,
67        DummyImageMediaMarkupBuilder.class);
68  
69    /**
70     * @return Supported media sources
71     */
72    public @NotNull List<Class<? extends MediaSource>> getSources() {
73      return DEFAULT_MEDIA_SOURCES;
74    }
75  
76    /**
77     * @return Available media markup builders
78     */
79    public @NotNull List<Class<? extends MediaMarkupBuilder>> getMarkupBuilders() {
80      return DEFAULT_MEDIA_MARKUP_BUILDERS;
81    }
82  
83    /**
84     * @return List of media metadata pre processors (optional). The processors are applied in list order.
85     */
86    public @NotNull List<Class<? extends MediaProcessor>> getPreProcessors() {
87      // no processors
88      return Collections.emptyList();
89    }
90  
91    /**
92     * @return List of media metadata post processors (optional). The processors are applied in list order.
93     */
94    public @NotNull List<Class<? extends MediaProcessor>> getPostProcessors() {
95      // no processors
96      return Collections.emptyList();
97    }
98  
99    /**
100    * Get the default quality for images.
101    * The meaning of the quality parameter for the different image formats is described in
102    * {@link com.day.image.Layer#write(String, double, java.io.OutputStream)}.
103    * @param contentType MIME-type of the output format
104    * @return Quality factor
105    */
106   public double getDefaultImageQuality(@Nullable String contentType) {
107     MediaFileType mediaFileType = MediaFileType.getByContentType(contentType);
108     if (mediaFileType != null && mediaFileType.isImageQualityPercentage()) {
109       return getDefaultImageQualityPercentage();
110     }
111     else if (mediaFileType == MediaFileType.GIF) {
112       return 256d; // 256 colors
113     }
114     // return quality "1" for all other mime types
115     return 1d;
116   }
117 
118   /**
119    * Get the default quality for images.
120    * This parameter only applies to images with lossy compression (e.g. JPEG).
121    * @return Quality percentage (0..1)
122    */
123   public double getDefaultImageQualityPercentage() {
124     return DEFAULT_IMAGE_QUALITY;
125   }
126 
127   /**
128    * With this switch it's possible to switch all used property and node names from (legacy) wcm.io
129    * Handler standard to Adobe Standard (as used e.g. in Adobe Core WCM Components) - e.g.
130    * using "fileReference" instead of property name "mediaRef" for the asset reference.
131    *
132    * <p>
133    * The benefit of the wcm.io Handler standard was that it supported storage multiple asset references
134    * in one single node - but this it not well supported by the Touch UI anyway, so it's not of much
135    * use nowadays.
136    * </p>
137    *
138    * <p>
139    * For new projects it is recommended to always use the Adobe standard names. But for backward compatibility
140    * the default values is false.
141    * </p>
142    * @return If true, Adobe standard property and node names are used.
143    */
144   public boolean useAdobeStandardNames() {
145     return false;
146   }
147 
148   /**
149    * @return Default property name for reference to media library item
150    */
151   public @NotNull String getMediaRefProperty() {
152     if (useAdobeStandardNames()) {
153       return MediaNameConstants.PN_MEDIA_REF_STANDARD;
154     }
155     else {
156       return MediaNameConstants.PN_MEDIA_REF;
157     }
158   }
159 
160   /**
161    * @return Default property name for cropping parameters
162    */
163   public @NotNull String getMediaCropProperty() {
164     if (useAdobeStandardNames()) {
165       return MediaNameConstants.PN_MEDIA_CROP_STANDARD;
166     }
167     else {
168       return MediaNameConstants.PN_MEDIA_CROP;
169     }
170   }
171 
172   /**
173    * @return Default property name for rotate parameter
174    */
175   public @NotNull String getMediaRotationProperty() {
176     if (useAdobeStandardNames()) {
177       return MediaNameConstants.PN_MEDIA_ROTATION_STANDARD;
178     }
179     else {
180       return MediaNameConstants.PN_MEDIA_ROTATION;
181     }
182   }
183 
184   /**
185    * @return Default property name for map parameter
186    */
187   public @NotNull String getMediaMapProperty() {
188     if (useAdobeStandardNames()) {
189       return MediaNameConstants.PN_MEDIA_MAP_STANDARD;
190     }
191     else {
192       return MediaNameConstants.PN_MEDIA_MAP;
193     }
194   }
195 
196   /**
197    * @return Default property name for media alt. text
198    */
199   public @NotNull String getMediaAltTextProperty() {
200     if (useAdobeStandardNames()) {
201       return MediaNameConstants.PN_MEDIA_ALTTEXT_STANDARD;
202     }
203     else {
204       return MediaNameConstants.PN_MEDIA_ALTTEXT;
205     }
206   }
207 
208   /**
209    * @return Default property name for forcing reading alt. text from DAM asset description
210    */
211   public @NotNull String getMediaForceAltTextFromAssetProperty() {
212     if (useAdobeStandardNames()) {
213       return MediaNameConstants.PN_MEDIA_FORCE_ALTTEXT_FROM_ASSET_STANDARD;
214     }
215     else {
216       return MediaNameConstants.PN_MEDIA_FORCE_ALTTEXT_FROM_ASSET;
217     }
218   }
219 
220   /**
221    * @return Default property name for marking image as "decorative" - requiring no alt. text
222    */
223   public @NotNull String getMediaIsDecorativeProperty() {
224     if (useAdobeStandardNames()) {
225       return MediaNameConstants.PN_MEDIA_IS_DECORATIVE_STANDARD;
226     }
227     else {
228       return MediaNameConstants.PN_MEDIA_IS_DECORATIVE;
229     }
230   }
231 
232   /**
233    * @return Default node name for inline media item stored in node within the content page
234    */
235   public @NotNull String getMediaInlineNodeName() {
236     if (useAdobeStandardNames()) {
237       return MediaNameConstants.NN_MEDIA_INLINE_STANDARD;
238     }
239     else {
240       return MediaNameConstants.NN_MEDIA_INLINE;
241     }
242   }
243 
244   /**
245    * @return If set to true, web renditions generated by AEM (with <code>cq5dam.web.</code> prefix) are
246    *         taken into account by default when trying to resolve the media request.
247    * @deprecated Use {@link #getIncludeAssetAemRenditionsByDefault()} instead.
248    */
249   @Deprecated(since = "2.0.0")
250   public boolean includeAssetWebRenditionsByDefault() {
251     return false;
252   }
253 
254   /**
255    * Set of renditions auto-generated by AEM (with <code>cq5dam.</code> prefix) which are taken into account
256    * by default when trying to resolve the media request.
257    * @return Set or rendition types
258    */
259   @SuppressWarnings("java:S1874") // ignore use of deprecated method
260   public @NotNull Set<AemRenditionType> getIncludeAssetAemRenditionsByDefault() {
261     if (includeAssetWebRenditionsByDefault()) {
262       return EnumSet.of(AemRenditionType.WEB_RENDITION, AemRenditionType.VIDEO_RENDITION);
263     }
264     else {
265       return EnumSet.of(AemRenditionType.VIDEO_RENDITION);
266     }
267   }
268 
269   /**
270    * Enforce to generate only virtual renditions.
271    *
272    * <p>
273    * By default, virtual renditions (rendered on-the-fly via <code>ImageFileServet</code>) are only
274    * generated if there is a need to re-scale or crop or transform an image. Otherwise direct references
275    * to renditions or original stored in DAM are returned when there is an direct match with the requested ratio and
276    * resolution.
277    * </p>
278    *
279    * <p>
280    * When this flag is set to <code>true</code>, even if there is a direct match a virtual rendition is returned.
281    * This ensures that the default quality setting e.g. for JPEG images is always respected, regardless
282    * in which quality the original images was uploaded.
283    * </p>
284    * @return Enforce always returning virtual renditions for images.
285    */
286   public boolean enforceVirtualRenditions() {
287     return false;
288   }
289 
290   /**
291    * @return Allowed editor types for image IPE (in-place editor).
292    *         By default, only the OOTB "image" editor type is supported.
293    */
294   public @NotNull Set<String> allowedIpeEditorTypes() {
295     return MediaMarkupBuilderUtil.DEFAULT_ALLOWED_IPE_EDITOR_TYPES;
296   }
297 
298   /**
299    * Get root path for picking assets using path field widgets.
300    * @param page Context page
301    * @return DAM root path
302    */
303   public @NotNull String getDamRootPath(@NotNull Page page) {
304     return "/content/dam";
305   }
306 
307 }