Skip to contentMethod: getMap(ResourceProperties, Key)
1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * NorthernWind - lightweight CMS
5: * http://tidalwave.it/projects/northernwind
6: *
7: * Copyright (C) 2011 - 2025 Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/northernwind-src
22: * git clone https://github.com/tidalwave-it/northernwind-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.northernwind.frontend.media.impl;
27:
28: import javax.annotation.Nonnull;
29: import javax.inject.Inject;
30: import java.util.HashMap;
31: import java.util.List;
32: import java.util.Map;
33: import java.util.TreeMap;
34: import org.springframework.beans.factory.annotation.Configurable;
35: import it.tidalwave.util.Key;
36: import it.tidalwave.image.EditableImage;
37: import it.tidalwave.image.metadata.Directory;
38: import it.tidalwave.image.metadata.EXIF;
39: import it.tidalwave.image.metadata.IPTC;
40: import it.tidalwave.image.metadata.TIFF;
41: import it.tidalwave.image.metadata.XMP;
42: import it.tidalwave.northernwind.core.model.ResourceProperties;
43: import it.tidalwave.northernwind.frontend.media.impl.interpolator.MetadataInterpolator.Context;
44: import it.tidalwave.northernwind.frontend.media.impl.interpolator.MetadataInterpolatorFactory;
45: import lombok.AllArgsConstructor;
46: import lombok.ToString;
47: import lombok.extern.slf4j.Slf4j;
48: import static java.util.Collections.emptyList;
49: import static it.tidalwave.util.FunctionalCheckedExceptionWrappers.*;
50: import static it.tidalwave.northernwind.frontend.media.impl.EmbeddedMediaMetadataProvider.*;
51:
52: /***************************************************************************************************************************************************************
53: *
54: * A default implementation of {@link Metadata}.
55: *
56: * @author Fabrizio Giudici
57: *
58: **************************************************************************************************************************************************************/
59: @Configurable @AllArgsConstructor @ToString @Slf4j
60: class DefaultMetadata implements Metadata
61: {
62: @Nonnull
63: private final String mediaName;
64:
65: @Nonnull
66: private final EditableImage image;
67:
68: @Inject
69: private MetadataInterpolatorFactory interpolatorFactory;
70:
71: /***********************************************************************************************************************************************************
72: *
73: **********************************************************************************************************************************************************/
74: public DefaultMetadata (@Nonnull final String mediaName, @Nonnull final EditableImage image)
75: {
76: this.mediaName = mediaName;
77: this.image = image;
78: }
79:
80: /***********************************************************************************************************************************************************
81: * {@inheritDoc}
82: **********************************************************************************************************************************************************/
83: @Override @Nonnull
84: public <T extends Directory> T getDirectory (@Nonnull final Class<T> metadataClass)
85: {
86: return image.getMetadata(metadataClass).orElseGet(_s(() -> metadataClass.getConstructor().newInstance()));
87: }
88:
89: /***********************************************************************************************************************************************************
90: * {@inheritDoc}
91: **********************************************************************************************************************************************************/
92: @Override @Nonnull
93: public String interpolateString (@Nonnull final String template,
94: @Nonnull final ResourceProperties properties)
95: {
96: if (log.isDebugEnabled())
97: {
98: log();
99: }
100:
101: // FIXME: use format as an interpolated string to get properties both from EXIF and IPTC
102: // final String string = formatted(iptc.getObject(517, String.class));
103: final var context = new Context(this, getMap(properties, P_CAMERA_IDS), getMap(properties, P_LENS_IDS));
104:
105: var result = template;
106:
107: for (final var interpolator : interpolatorFactory.getInterpolators())
108: {
109: if (result.contains("$" + interpolator.getMacro() + "$"))
110: {
111: result = interpolator.interpolate(result, context);
112: }
113: }
114:
115: return result;
116: }
117:
118: /***********************************************************************************************************************************************************
119: *
120: **********************************************************************************************************************************************************/
121: private void log()
122: {
123: final var tiff = image.getMetadata(TIFF.class).orElseGet(TIFF::new);
124: final var exif = image.getMetadata(EXIF.class).orElseGet(EXIF::new);
125: final var iptc = image.getMetadata(IPTC.class).orElseGet(IPTC::new);
126: final var xmp = image.getMetadata(XMP.class).orElseGet(XMP::new);
127: final Map<String, String> xmpProperties = new TreeMap<>(xmp.getXmpProperties());
128:
129: tiff.forEachTag(t -> log.debug("{}: TIFF[{}]: {}", mediaName, t.getName(), tiff.getRaw(t.getCode())));
130: exif.forEachTag(t -> log.debug("{}: EXIF[{}]: {}", mediaName, t.getName(), exif.getRaw(t.getCode())));
131: iptc.forEachTag(t -> log.debug("{}: IPTC[{}]: {}", mediaName, t.getName(), iptc.getRaw(t.getCode())));
132: xmp.forEachTag(t -> log.debug("{}: XMP[{}]: {}", mediaName, t.getName(), xmp.getRaw(t.getCode())));
133: xmpProperties.forEach((k, v) -> log.debug("XMPprop({}).{}: {}", mediaName, k, v));
134: }
135:
136: /***********************************************************************************************************************************************************
137: *
138: **********************************************************************************************************************************************************/
139: @Nonnull
140: private static Map<String, String> getMap (@Nonnull final ResourceProperties siteNodeProperties,
141: @Nonnull final Key<List<String>> key)
142: {
143: final var properties = siteNodeProperties.getGroup(P_GROUP_ID);
144: final Map<String, String> lensMap = new HashMap<>();
145:
146:• for (final var s : properties.getProperty(key).orElse(emptyList()))
147: {
148: final var split = s.split(":");
149: lensMap.put(split[0].trim(), split[1].trim());
150: }
151:
152: return lensMap;
153: }
154: }