Package: BluetteGalleryAdapter
BluetteGalleryAdapter
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
BluetteGalleryAdapter(SiteNode, GalleryView, ModelFactory) |
|
|
|
|
|
||||||||||||||||||||
createImageLink(String, int) |
|
|
|
|
|
||||||||||||||||||||
getInlinedScript() |
|
|
|
|
|
||||||||||||||||||||
lambda$getInlinedScript$0(Key) |
|
|
|
|
|
||||||||||||||||||||
lambda$getInlinedScript$1(ResourceProperties, Key) |
|
|
|
|
|
||||||||||||||||||||
lambda$toAggregate$2(Key, Object) |
|
|
|
|
|
||||||||||||||||||||
prepare(GalleryViewController.GalleryItem, List, Template) |
|
|
|
|
|
||||||||||||||||||||
prepareCatalog(List) |
|
|
|
|
|
||||||||||||||||||||
prepareFallbackGallery(GalleryViewController.GalleryItem, List) |
|
|
|
|
|
||||||||||||||||||||
prepareFallbackLightbox(List) |
|
|
|
|
|
||||||||||||||||||||
prepareGallery(GalleryViewController.GalleryItem, List) |
|
|
|
|
|
||||||||||||||||||||
render(RenderContext) |
|
|
|
|
|
||||||||||||||||||||
static {...} |
|
|
|
|
|
||||||||||||||||||||
toAggregate(GalleryViewController.GalleryItem) |
|
|
|
|
|
||||||||||||||||||||
toAggregate(ResourceProperties, Key) |
|
|
|
|
|
Coverage
1: /*
2: * #%L
3: * *********************************************************************************************************************
4: *
5: * NorthernWind - lightweight CMS
6: * http://northernwind.tidalwave.it - git clone https://bitbucket.org/tidalwave/northernwind-src.git
7: * %%
8: * Copyright (C) 2011 - 2023 Tidalwave s.a.s. (http://tidalwave.it)
9: * %%
10: * *********************************************************************************************************************
11: *
12: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
13: * the License. You may obtain a copy of the License at
14: *
15: * http://www.apache.org/licenses/LICENSE-2.0
16: *
17: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
18: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
19: * specific language governing permissions and limitations under the License.
20: *
21: * *********************************************************************************************************************
22: *
23: *
24: * *********************************************************************************************************************
25: * #L%
26: */
27: package it.tidalwave.northernwind.frontend.ui.component.gallery.htmltemplate.bluette;
28:
29: import javax.annotation.Nonnegative;
30: import javax.annotation.Nonnull;
31: import java.util.List;
32: import java.util.Optional;
33: import it.tidalwave.util.Id;
34: import it.tidalwave.util.Key;
35: import it.tidalwave.northernwind.core.model.ModelFactory;
36: import it.tidalwave.northernwind.core.model.ResourcePath;
37: import it.tidalwave.northernwind.core.model.ResourceProperties;
38: import it.tidalwave.northernwind.core.model.Site;
39: import it.tidalwave.northernwind.core.model.SiteNode;
40: import it.tidalwave.northernwind.core.model.Template;
41: import it.tidalwave.northernwind.core.model.Template.Aggregate;
42: import it.tidalwave.northernwind.frontend.ui.RenderContext;
43: import it.tidalwave.northernwind.frontend.ui.component.htmltemplate.TextHolder;
44: import it.tidalwave.northernwind.frontend.ui.component.gallery.GalleryView;
45: import it.tidalwave.northernwind.frontend.ui.component.gallery.GalleryViewController.GalleryItem;
46: import it.tidalwave.northernwind.frontend.ui.component.gallery.spi.GalleryAdapterSupport;
47: import lombok.extern.slf4j.Slf4j;
48: import static it.tidalwave.northernwind.core.model.Template.Aggregates.toAggregates;
49:
50: /***********************************************************************************************************************
51: *
52: * @author Fabrizio Giudici
53: *
54: **********************************************************************************************************************/
55: @Slf4j
56: public class BluetteGalleryAdapter extends GalleryAdapterSupport
57: {
58: private static final Key<String> P_COPYRIGHT = Key.of("copyright", String.class);
59:
60: private static final Key<ResourcePath> P_BLUETTE_TEMPLATE_PATH = Key.of("bluettePath", ResourcePath.class);
61:
62: /** The path to the template for fallback rendering of a single gallery page, when JavaScript is not available. */
63: private static final Key<ResourcePath> P_BLUETTE_FALLBACK_TEMPLATE_PATH = Key.of("bluetteFallbackPath", ResourcePath.class);
64:
65: /** The path to the template for fallback rendering of the light box, when JavaScript is not available. */
66: private static final Key<ResourcePath> P_BLUETTE_LIGHTBOX_FALLBACK_TEMPLATE_PATH = Key.of("bluetteLightboxFallbackPath", ResourcePath.class);
67:
68: /** The path to the template for the script that redirects a page to the dynamic counterpart (with #!). */
69: private static final Key<ResourcePath> P_BLUETTE_REDIRECT_SCRIPT_TEMPLATE_PATH = Key.of("bluetteRedirectScriptPath", ResourcePath.class);
70:
71: /** The path to the template for the image catalog. */
72: private static final Key<ResourcePath> P_BLUETTE_CATALOG_TEMPLATE_PATH = Key.of("bluetteCatalogPath", ResourcePath.class);
73:
74: private static final Key<ResourcePath> P_BLUETTE_VARIABLES_TEMPLATE_PATH = Key.of("bluetteVariablesPath", ResourcePath.class);
75:
76: private static final Key<String> P_CATALOG_URL = Key.of("bluetteCatalogUrl", String.class);
77:
78: @Nonnull
79: private final Site site;
80:
81: @Nonnull
82: private final Template defaultTemplate;
83:
84: @Nonnull
85: private final Template fallbackTemplate;
86:
87: @Nonnull
88: private final Template lightboxFallbackTemplate;
89:
90: @Nonnull
91: private final Template redirectScriptTemplate;
92:
93: @Nonnull
94: private final Template catalogTemplate;
95:
96: @Nonnull
97: private final Template variablesTemplate;
98:
99: @Nonnull
100: private final ResourceProperties bluetteConfiguration;
101:
102: @Nonnull
103: private final ResourcePath baseUrl;
104:
105: @Nonnull
106: private final String copyright;
107:
108: private final int fallbackImageSize = 1280; // FIXME: parametrise size
109:
110: private final int fallbackThumbnailSize = 100; // FIXME: parametrise size
111:
112: private final ResourcePath lightboxSegmentUri = ResourcePath.of("lightbox");
113:
114: @Nonnull
115: private final String homeUrl;
116:
117: private String rendered = "";
118:
119: private boolean catalog;
120:
121: /*******************************************************************************************************************
122: *
123: *
124: *
125: ******************************************************************************************************************/
126: public BluetteGalleryAdapter (@Nonnull final SiteNode siteNode,
127: @Nonnull final GalleryView view,
128: @Nonnull final ModelFactory modelFactory)
129: {
130: super(siteNode, view, modelFactory);
131: this.site = siteNode.getSite();
132: bluetteConfiguration = siteNode.getPropertyGroup(new Id("bluetteConfiguration"));
133: baseUrl = siteNode.getRelativeUri().prependedWith(site.getContextPath());
134: homeUrl = site.createLink(ResourcePath.of("/blog")); // FIXME
135: copyright = bluetteConfiguration.getProperty(P_COPYRIGHT).orElse("");
136:
137: defaultTemplate = loadTemplate(P_BLUETTE_TEMPLATE_PATH, "Default.st");
138: fallbackTemplate = loadTemplate(P_BLUETTE_FALLBACK_TEMPLATE_PATH, "Fallback.st");
139: lightboxFallbackTemplate = loadTemplate(P_BLUETTE_LIGHTBOX_FALLBACK_TEMPLATE_PATH, "LightBoxFallback.st");
140: redirectScriptTemplate = loadTemplate(P_BLUETTE_REDIRECT_SCRIPT_TEMPLATE_PATH, "RedirectScript.st");
141: catalogTemplate = loadTemplate(P_BLUETTE_CATALOG_TEMPLATE_PATH, "Catalog.st");
142: variablesTemplate = loadTemplate(P_BLUETTE_VARIABLES_TEMPLATE_PATH, "Variables.st");
143: }
144:
145: /*******************************************************************************************************************
146: *
147: * {@inheritDoc}
148: *
149: ******************************************************************************************************************/
150: @Override @Nonnull
151: public String getInlinedScript()
152: {
153: final var link = site.createLink(siteNode.getRelativeUri().appendedWith("images.xml"));
154: final var properties = bluetteConfiguration.withProperty(P_CATALOG_URL, "'" + link + "'");
155: // FIXME: since key doesn't have dynamic type, we can't properly escape strings.
156: final var variables = properties.getKeys().stream()
157:• .filter(k -> k.getName().startsWith("bluette") || "logging".equals(k.getName()))
158: .flatMap(k -> toAggregate(properties, k).stream())
159: .collect(toAggregates("entries"));
160:
161: return variablesTemplate.render(variables) + "\n" + redirectScriptTemplate.render();
162: }
163:
164: /*******************************************************************************************************************
165: *
166: * {@inheritDoc}
167: *
168: ******************************************************************************************************************/
169: @Override
170: public void prepareCatalog (@Nonnull final List<? extends GalleryItem> items)
171: {
172: final var entries = items.stream().map(this::toAggregate).collect(toAggregates("entries"));
173: rendered = catalogTemplate.render(entries);
174: catalog = true;
175: }
176:
177: /*******************************************************************************************************************
178: *
179: * {@inheritDoc}
180: *
181: ******************************************************************************************************************/
182: // TODO: Could we manage #! params here and select the proper item?
183: @Override
184: public void prepareGallery (@Nonnull final GalleryItem item, @Nonnull final List<? extends GalleryItem> items)
185: {
186: prepare(item, items, defaultTemplate);
187: rendered = defaultTemplate.render();
188: }
189:
190: /*******************************************************************************************************************
191: *
192: * {@inheritDoc}
193: *
194: ******************************************************************************************************************/
195: @Override
196: public void prepareFallbackGallery (@Nonnull final GalleryItem item, @Nonnull final List<? extends GalleryItem> items)
197: {
198: prepare(item, items, fallbackTemplate);
199: rendered = fallbackTemplate.render();
200: }
201:
202: /*******************************************************************************************************************
203: *
204: * {@inheritDoc}
205: *
206: ******************************************************************************************************************/
207: @Override
208: public void prepareFallbackLightbox (@Nonnull final List<? extends GalleryItem> items)
209: {
210: final var entries = items.stream().map(this::toAggregate).collect(toAggregates("entries"));
211: final var redirectUrl = site.createLink(baseUrl.appendedWith("#!").appendedWith(lightboxSegmentUri)).replaceAll("/$", "");
212: redirectScriptTemplate.addAttribute("redirectUrl", redirectUrl);
213: lightboxFallbackTemplate.addAttribute("copyright", copyright);
214: rendered = lightboxFallbackTemplate.render(entries);
215: }
216:
217: /*******************************************************************************************************************
218: *
219: * {@inheritDoc}
220: *
221: ******************************************************************************************************************/
222: @Override
223: public void render (@Nonnull final RenderContext context)
224: {
225: final var textHolder = (TextHolder)view;
226:
227:• if (!catalog)
228: {
229: textHolder.addAttribute("content", rendered);
230: }
231: else
232: {
233: textHolder.setTemplate("$content$\n");
234: textHolder.setContent(rendered);
235: textHolder.setMimeType("text/xml");
236: }
237: }
238:
239: /*******************************************************************************************************************
240: *
241: *
242: ******************************************************************************************************************/
243: private void prepare (// final @Nonnull RenderContext context,
244: @Nonnull final GalleryItem item,
245: @Nonnull final List<? extends GalleryItem> items,
246: @Nonnull final Template template)
247: {
248: final var count = items.size();
249: final var index = items.indexOf(item);
250: final var prevIndex = (index - 1 + count) % count;
251: final var nextIndex = (index + 1) % count;
252:
253: final var imageId = item.getId().stringValue();
254: final var imageUrl = createImageLink(imageId, fallbackImageSize);
255:
256: final var redirectUrl = site.createLink(baseUrl.appendedWith("#!").appendedWith(imageId)).replaceAll("/$", "");
257: final var previousUrl = site.createLink(baseUrl.appendedWith(items.get(prevIndex).getId().stringValue()));
258: final var nextUrl = site.createLink(baseUrl.appendedWith(items.get(nextIndex).getId().stringValue()));
259: final var lightboxUrl = site.createLink(baseUrl.appendedWith(lightboxSegmentUri));
260:
261: template.addAttribute("caption", item.getDescription())
262: .addAttribute("previous", previousUrl)
263: .addAttribute("next", nextUrl)
264: .addAttribute("lightbox", lightboxUrl)
265: .addAttribute("home", homeUrl)
266: .addAttribute("imageId", imageId)
267: .addAttribute("imageUrl", imageUrl)
268: .addAttribute("copyright", copyright);
269:
270:• if (template != defaultTemplate)
271: {
272: redirectScriptTemplate.addAttribute("redirectUrl", redirectUrl);
273:
274: // context.setDynamicNodeProperty(PD_IMAGE_ID, imageId);
275: // FIXME: these should be dynamic properties
276: // siteNodeProperties.getProperty().ifPresent(id -> view.addAttribute("imageId", id));
277: // siteNodeProperties.getProperty(PD_URL).ifPresent(id -> view.addAttribute("url", id));
278: final var textHolder = (TextHolder)view;
279: textHolder.addAttribute("description", item.getDescription());
280: textHolder.addAttribute("imageId", imageId);
281: textHolder.addAttribute("imageUrl", imageUrl);
282: }
283: }
284:
285: /*******************************************************************************************************************
286: *
287: ******************************************************************************************************************/
288: @Nonnull
289: private Aggregate toAggregate (@Nonnull final GalleryItem item)
290: {
291: final var id = item.getId().stringValue();
292: final var link = site.createLink(baseUrl.appendedWith(id));
293: return Aggregate.of("id", id)
294: .with("link", link)
295: .with("url", createImageLink(id, fallbackThumbnailSize))
296: .with("title", item.getDescription().replaceAll("\n+", " "));
297: }
298:
299: /*******************************************************************************************************************
300: *
301: ******************************************************************************************************************/
302: @Nonnull
303: private static Optional<Aggregate> toAggregate (@Nonnull final ResourceProperties properties,
304: @Nonnull final Key<?> key)
305: {
306: // A space in front of [ ] makes them interpreted as a string and not a list.
307: return properties.getProperty(key).map(v -> Aggregate.of("name", key.stringValue()).with("value", v.toString().replace("[", " [")));
308: }
309:
310: /*******************************************************************************************************************
311: *
312: ******************************************************************************************************************/
313: @Nonnull
314: private String createImageLink (@Nonnull final String id, @Nonnegative final int size)
315: {
316: return site.createLink(ResourcePath.of(String.format("/media/stillimages/%d/%s.jpg", size, id)));
317: }
318: }