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    * <p>
132    * The benefit of the wcm.io Handler standard was that it supported storage multiple asset references
133    * in one single node - but this it not well supported by the Touch UI anyway, so it's not of much
134    * use nowadays.
135    * </p>
136    * <p>
137    * For new projects it is recommended to always use the Adobe standard names. But for backward compatibility
138    * the default values is false.
139    * </p>
140    * @return If true, Adobe standard property and node names are used.
141    */
142   public boolean useAdobeStandardNames() {
143     return false;
144   }
145 
146   /**
147    * @return Default property name for reference to media library item
148    */
149   public @NotNull String getMediaRefProperty() {
150     if (useAdobeStandardNames()) {
151       return MediaNameConstants.PN_MEDIA_REF_STANDARD;
152     }
153     else {
154       return MediaNameConstants.PN_MEDIA_REF;
155     }
156   }
157 
158   /**
159    * @return Default property name for cropping parameters
160    */
161   public @NotNull String getMediaCropProperty() {
162     if (useAdobeStandardNames()) {
163       return MediaNameConstants.PN_MEDIA_CROP_STANDARD;
164     }
165     else {
166       return MediaNameConstants.PN_MEDIA_CROP;
167     }
168   }
169 
170   /**
171    * @return Default property name for rotate parameter
172    */
173   public @NotNull String getMediaRotationProperty() {
174     if (useAdobeStandardNames()) {
175       return MediaNameConstants.PN_MEDIA_ROTATION_STANDARD;
176     }
177     else {
178       return MediaNameConstants.PN_MEDIA_ROTATION;
179     }
180   }
181 
182   /**
183    * @return Default property name for map parameter
184    */
185   public @NotNull String getMediaMapProperty() {
186     if (useAdobeStandardNames()) {
187       return MediaNameConstants.PN_MEDIA_MAP_STANDARD;
188     }
189     else {
190       return MediaNameConstants.PN_MEDIA_MAP;
191     }
192   }
193 
194   /**
195    * @return Default property name for media alt. text
196    */
197   public @NotNull String getMediaAltTextProperty() {
198     if (useAdobeStandardNames()) {
199       return MediaNameConstants.PN_MEDIA_ALTTEXT_STANDARD;
200     }
201     else {
202       return MediaNameConstants.PN_MEDIA_ALTTEXT;
203     }
204   }
205 
206   /**
207    * @return Default property name for forcing reading alt. text from DAM asset description
208    */
209   public @NotNull String getMediaForceAltTextFromAssetProperty() {
210     if (useAdobeStandardNames()) {
211       return MediaNameConstants.PN_MEDIA_FORCE_ALTTEXT_FROM_ASSET_STANDARD;
212     }
213     else {
214       return MediaNameConstants.PN_MEDIA_FORCE_ALTTEXT_FROM_ASSET;
215     }
216   }
217 
218   /**
219    * @return Default property name for marking image as "decorative" - requiring no alt. text
220    */
221   public @NotNull String getMediaIsDecorativeProperty() {
222     if (useAdobeStandardNames()) {
223       return MediaNameConstants.PN_MEDIA_IS_DECORATIVE_STANDARD;
224     }
225     else {
226       return MediaNameConstants.PN_MEDIA_IS_DECORATIVE;
227     }
228   }
229 
230   /**
231    * @return Default node name for inline media item stored in node within the content page
232    */
233   public @NotNull String getMediaInlineNodeName() {
234     if (useAdobeStandardNames()) {
235       return MediaNameConstants.NN_MEDIA_INLINE_STANDARD;
236     }
237     else {
238       return MediaNameConstants.NN_MEDIA_INLINE;
239     }
240   }
241 
242   /**
243    * @return If set to true, web renditions generated by AEM (with <code>cq5dam.web.</code> prefix) are
244    *         taken into account by default when trying to resolve the media request.
245    * @deprecated Use {@link #getIncludeAssetAemRenditionsByDefault()} instead.
246    */
247   @Deprecated(since = "2.0.0")
248   public boolean includeAssetWebRenditionsByDefault() {
249     return false;
250   }
251 
252   /**
253    * Set of renditions auto-generated by AEM (with <code>cq5dam.</code> prefix) which are taken into account
254    * by default when trying to resolve the media request.
255    * @return Set or rendition types
256    */
257   @SuppressWarnings("java:S1874") // ignore use of deprecated method
258   public @NotNull Set<AemRenditionType> getIncludeAssetAemRenditionsByDefault() {
259     if (includeAssetWebRenditionsByDefault()) {
260       return EnumSet.of(AemRenditionType.WEB_RENDITION, AemRenditionType.VIDEO_RENDITION);
261     }
262     else {
263       return EnumSet.of(AemRenditionType.VIDEO_RENDITION);
264     }
265   }
266 
267   /**
268    * Enforce to generate only virtual renditions.
269    * <p>
270    * By default, virtual renditions (rendered on-the-fly via <code>ImageFileServet</code>) are only
271    * generated if there is a need to re-scale or crop or transform an image. Otherwise direct references
272    * to renditions or original stored in DAM are returned when there is an direct match with the requested ratio and
273    * resolution.
274    * </p>
275    * <p>
276    * When this flag is set to <code>true</code>, even if there is a direct match a virtual rendition is returned.
277    * This ensures that the default quality setting e.g. for JPEG images is always respected, regardless
278    * in which quality the original images was uploaded.
279    * </p>
280    * @return Enforce always returning virtual renditions for images.
281    */
282   public boolean enforceVirtualRenditions() {
283     return false;
284   }
285 
286   /**
287    * @return Allowed editor types for image IPE (in-place editor).
288    *         By default, only the OOTB "image" editor type is supported.
289    */
290   public @NotNull Set<String> allowedIpeEditorTypes() {
291     return MediaMarkupBuilderUtil.DEFAULT_ALLOWED_IPE_EDITOR_TYPES;
292   }
293 
294   /**
295    * Get root path for picking assets using path field widgets.
296    * @param page Context page
297    * @return DAM root path
298    */
299   public @NotNull String getDamRootPath(@NotNull Page page) {
300     return "/content/dam";
301   }
302 
303 }