001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.layer.geoimage.viewers.projections; 003 004import java.util.EnumMap; 005import java.util.Map; 006import java.util.Objects; 007import java.util.stream.Collectors; 008 009import org.openstreetmap.josm.data.imagery.street_level.Projections; 010import org.openstreetmap.josm.tools.JosmRuntimeException; 011 012/** 013 * A class that holds a registry of viewers for image projections 014 * @since 18246 015 */ 016public final class ImageProjectionRegistry { 017 private static final EnumMap<Projections, Class<? extends IImageViewer>> DEFAULT_VIEWERS = new EnumMap<>(Projections.class); 018 019 // Register the default viewers 020 static { 021 try { 022 registerViewer(Perspective.class); 023 registerViewer(Equirectangular.class); 024 } catch (ReflectiveOperationException e) { 025 throw new JosmRuntimeException(e); 026 } 027 } 028 029 private ImageProjectionRegistry() { 030 // Prevent instantiations 031 } 032 033 /** 034 * Register a new viewer 035 * @param clazz The class to register. The class <i>must</i> have a no args constructor 036 * @return {@code true} if something changed 037 * @throws ReflectiveOperationException if there is no no-args constructor, or it is not visible to us. 038 */ 039 public static boolean registerViewer(Class<? extends IImageViewer> clazz) throws ReflectiveOperationException { 040 Objects.requireNonNull(clazz, "null classes are hard to instantiate"); 041 final IImageViewer object = clazz.getConstructor().newInstance(); 042 boolean changed = false; 043 for (Projections projections : object.getSupportedProjections()) { 044 changed = clazz.equals(DEFAULT_VIEWERS.put(projections, clazz)) || changed; 045 } 046 return changed; 047 } 048 049 /** 050 * Remove a viewer 051 * @param clazz The class to remove. 052 * @return {@code true} if something changed 053 */ 054 public static boolean removeViewer(Class<? extends IImageViewer> clazz) { 055 boolean changed = false; 056 for (Projections projections : DEFAULT_VIEWERS.entrySet().stream() 057 .filter(entry -> entry.getValue().equals(clazz)).map(Map.Entry::getKey) 058 .collect(Collectors.toList())) { 059 changed = DEFAULT_VIEWERS.remove(projections, clazz) || changed; 060 } 061 return changed; 062 } 063 064 /** 065 * Get the viewer for a specific projection type 066 * @param projection The projection to view 067 * @return The class to use 068 */ 069 public static Class<? extends IImageViewer> getViewer(Projections projection) { 070 return DEFAULT_VIEWERS.getOrDefault(projection, DEFAULT_VIEWERS.getOrDefault(Projections.UNKNOWN, Perspective.class)); 071 } 072}