2 * Copyright (C) 2020 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.api
.service
.media
;
11 import java
.awt
.Point
;
12 import java
.net
.URISyntaxException
;
13 import java
.util
.ArrayList
;
14 import java
.util
.Collection
;
15 import java
.util
.List
;
16 import java
.util
.Optional
;
17 import java
.util
.regex
.Matcher
;
19 import org
.apache
.log4j
.Logger
;
21 import eu
.etaxonomy
.cdm
.common
.URI
;
22 import eu
.etaxonomy
.cdm
.model
.media
.ImageFile
;
23 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentation
;
24 import eu
.etaxonomy
.cdm
.model
.media
.MediaRepresentationPart
;
25 import eu
.etaxonomy
.cdm
.model
.metadata
.PreferencePredicate
;
28 * Creates new purely volatile {@link MediaRepresentation MediaRepresentations} objects based on
29 * a list of {@link MediaUriTransformation} rules. These rules are usually stored in the
30 * per data base {@link PreferencePredicate.MediaRepresentationTransformations MediaRepresentationTransformations} property
31 * (See also {@link MediaToolbox#readTransformations()}).
33 * These volatile {@link MediaRepresentation MediaRepresentations} objects must not be persisted!
35 * @author a.kohlbecker
38 public class MediaUriTransformationProcessor
{
40 private static final Logger logger
= Logger
.getLogger(MediaUriTransformationProcessor
.class);
42 private List
<MediaUriTransformation
> transformations
= new ArrayList
<>();
44 public void add(MediaUriTransformation transformation
) {
45 transformations
.add(transformation
);
48 public void addAll(Collection
<MediaUriTransformation
> trans
) {
49 transformations
.addAll(trans
);
53 * Applies the the transformations of this processor to the given URI.
54 * And returns the all the URLs which resulted from the transformations
55 * or an empty list if none was applicable.
58 * the URI to transform
60 public List
<URI
> applyTo(URI uri
) {
62 logger
.debug("original: " + uri
.toString());
63 String pathQueryFragment
= buildPathQueryFragment(uri
);
65 List
<URI
> newUris
= new ArrayList
<>();
66 for (MediaUriTransformation transformation
: transformations
) {
69 Optional
<URI
> newUri
= uriTransformation(uri
, pathQueryFragment
, transformation
);
70 newUri
.ifPresent(u
-> newUris
.add(u
));
71 } catch (URISyntaxException e
) {
79 private Optional
<URI
> uriTransformation(URI uri
, String pathQueryFragment
, MediaUriTransformation replacement
)
80 throws URISyntaxException
{
82 String newScheme
= uri
.getScheme();
83 String newHost
= uri
.getHost();
84 int newPort
= uri
.getPort();
85 String newPathQueryFragment
= pathQueryFragment
;
87 boolean isMatch
= true;
89 if (replacement
.getScheme() != null) {
90 Matcher m
= replacement
.getScheme().searchPattern().matcher(newScheme
);
92 newScheme
= m
.replaceAll(replacement
.getScheme().getReplace());
94 if (replacement
.getHost() != null) {
95 Matcher m
= replacement
.getHost().searchPattern().matcher(newHost
);
97 newHost
= m
.replaceAll(replacement
.getHost().getReplace());
101 if (replacement
.getPathQueryFragment() != null) {
102 Matcher m
= replacement
.getPathQueryFragment().searchPattern().matcher(newPathQueryFragment
);
104 newPathQueryFragment
= m
.replaceAll(replacement
.getPathQueryFragment().getReplace());
108 String newURIString
= newScheme
+ "://" + newHost
+ (newPort
> 0 ?
":" + String
.valueOf(newPort
) : "")
109 + newPathQueryFragment
;
111 URI newUri
= new URI(newURIString
);
112 logger
.debug("transformed: " + newUri
.toString());
113 return Optional
.of(newUri
);
115 return Optional
.empty();
119 protected String
buildPathQueryFragment(URI uri
) {
120 String pathQueryFragment
= uri
.getPath();
121 if (uri
.getQuery() != null) {
122 pathQueryFragment
+= "?" + uri
.getQuery();
124 if (uri
.getFragment() != null) {
125 pathQueryFragment
+= "#" + uri
.getFragment();
127 return pathQueryFragment
;
131 public List
<MediaRepresentation
> makeNewMediaRepresentationsFor(URI uri
) {
133 List
<MediaRepresentation
> repr
= new ArrayList
<>();
135 String pathQueryFragment
= buildPathQueryFragment(uri
);
137 for (MediaUriTransformation transformation
: transformations
) {
140 Optional
<URI
> newUri
= uriTransformation(uri
, pathQueryFragment
, transformation
);
141 if(newUri
.isPresent()) {
142 MediaRepresentation mRepresentation
= MediaRepresentation
.NewInstance(transformation
.getMimeType(), null);
143 MediaRepresentationPart part
;
144 if (transformation
.getMimeType() != null && transformation
.getMimeType().startsWith("image/")) {
145 part
= ImageFile
.NewInstance(newUri
.get(), null, transformation
.getHeight(), transformation
.getWidth());
147 part
= MediaRepresentationPart
.NewInstance(newUri
.get(), null);
149 mRepresentation
.addRepresentationPart(part
);
150 repr
.add(mRepresentation
);
153 } catch (URISyntaxException e
) {
161 public List
<MediaRepresentation
> makeNewMediaRepresentationsFor(MediaRepresentationPart part
) {
163 List
<MediaRepresentation
> repr
= new ArrayList
<>();
165 String pathQueryFragment
= buildPathQueryFragment(part
.getUri());
167 for (MediaUriTransformation transformation
: transformations
) {
170 Optional
<URI
> newUri
= uriTransformation(part
.getUri(), pathQueryFragment
, transformation
);
171 if (newUri
.isPresent()) {
172 MediaRepresentation mRepresentation
= MediaRepresentation
.NewInstance(transformation
.getMimeType(),
174 MediaRepresentationPart newPart
;
175 if (transformation
.getMimeType() != null && transformation
.getMimeType().startsWith("image/")) {
176 if (part
instanceof ImageFile
) {
177 ImageFile originalImageFile
= (ImageFile
) part
;
178 Point newSize
= calculateTargetSize(transformation
, originalImageFile
.getWidth(),
179 originalImageFile
.getHeight());
180 newPart
= ImageFile
.NewInstance(newUri
.get(), null, newSize
.y
, newSize
.x
);
182 newPart
= ImageFile
.NewInstance(newUri
.get(), null, transformation
.getHeight(),
183 transformation
.getWidth());
186 newPart
= MediaRepresentationPart
.NewInstance(newUri
.get(), null);
188 mRepresentation
.addRepresentationPart(newPart
);
189 repr
.add(mRepresentation
);
192 } catch (URISyntaxException e
) {
204 * @param originalWidth
205 * @param originalHeight
206 * @param calculateMaxExtend
209 protected Point
calculateTargetSize(MediaUriTransformation trans
, Integer originalWidth
, Integer originalHeight
) {
211 if (trans
.getWidth() == null && trans
.getHeight() == null) {
213 } else if (originalWidth
== null || originalHeight
== null) {
214 return new Point(trans
.getWidth(), trans
.getHeight());
216 if(trans
.getHeight() != null && trans
.getWidth() != null && !trans
.isMaxExtend()) {
218 return new Point(trans
.getWidth(), trans
.getHeight());
221 float originalAspectRatio
= ((float) originalWidth
/ (float) originalHeight
);
223 boolean widthIsLimiting
= trans
.getHeight() == null ||
224 trans
.getWidth() != null && trans
.getHeight() * originalAspectRatio
> trans
.getWidth();
225 if (widthIsLimiting
){
226 return new Point(trans
.getWidth(), Math
.round(trans
.getWidth() / originalAspectRatio
));
228 return new Point(Math
.round(trans
.getHeight() * originalAspectRatio
), trans
.getHeight());