dk.dma.epd.common.graphics.Resources.java Source code

Java tutorial

Introduction

Here is the source code for dk.dma.epd.common.graphics.Resources.java

Source

/* Copyright (c) 2011 Danish Maritime Authority.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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 CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dk.dma.epd.common.graphics;

import java.io.Serializable;
import java.net.URL;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import javax.swing.ImageIcon;

import org.apache.commons.lang.StringUtils;

/**
 * Utility class used to fetch resource URL's and image icons (more to come).
 * <p>
 * Examples:
 * <pre>
 *  Resources res = Resources.get(EPD.class, "images/vesselIcons");
 *  ImageIcon vesselWhite = res.getCachedImageIcon("white1_90.png");
 *  ImageIcon vesselBlue = res.getCachedImageIcon("blue1_90.png");
 *  ImageIcon img1 = Resources.get(EPDShip.class).getImageIcon("images/toolbar/zoom_mouse.png");
 *  ImageIcon img2 = res.from(EPDShip.class).folder("images/toolbar").getImageIcon("zoom_mouse.png");
 * </pre>
 */
public final class Resources {

    private static Map<CacheKey, Object> cache = new ConcurrentHashMap<>();
    Class<?> loaderClass;
    String folder;

    /**
     * Constructor
     * 
     * @param loaderClass class that defines the class-loader/jar-file to load from
     * @param folder the folder prefix
     */
    private Resources(Class<?> loaderClass, String folder) {

        from(loaderClass).folder(folder);
    }

    /***********************************/
    /********* Factory methods *********/
    /***********************************/

    /**
     * Returns a new instance of the {@code Resources} entity
     * <p>
     * The resources are loaded from the same class-path as the {@code Resources} class
     * 
     * @return a new {@code Resources} entity
     */
    public static Resources get() {
        return new Resources(null, null);
    }

    /**
     * Returns a new instance of the {@code Resources} entity with the given folder prefix.
     * <p>
     * The resources are loaded from the same class-path as the {@code Resources} class
     * 
     * @param folder the folder prefix
     * @return a new {@code Resources} entity
     */
    public static Resources get(String folder) {
        return new Resources(null, folder);
    }

    /**
     * Returns a new instance of the {@code Resources} entity with the given folder prefix.
     * <p>
     * The resources are loaded from the class-path of the {@code loaderClass} class
     * 
     * @param loaderClass class that defines the class-loader/jar-file to load from
     * @param folder the folder prefix
     * @return a new {@code Resources} entity
     */
    public static Resources get(Class<?> loaderClass, String folder) {
        return new Resources(loaderClass, folder);
    }

    /**
     * Returns a new instance of the {@code Resources} entity.
     * <p>
     * The resources are loaded from the class-path of the {@code loaderClass} class
     * 
     * @param loaderClass class that defines the class-loader/jar-file to load from
     * @return a new {@code Resources} entity
     */
    public static Resources get(Class<?> loaderClass) {
        return new Resources(loaderClass, null);
    }

    /**
     * Method chaining style of setting the loader-class
     * @param loaderClass the loader class
     */
    public Resources from(Class<?> loaderClass) {
        this.loaderClass = loaderClass;
        if (this.loaderClass == null) {
            this.loaderClass = Resources.class;
        }
        return this;
    }

    /**
     * Method chaining style of setting the loader-class
     * @param loaderClass the loader class
     */
    public Resources folder(String folder) {
        this.folder = StringUtils.defaultString(folder);
        if (!StringUtils.isBlank(this.folder) && !this.folder.endsWith("/")) {
            this.folder = this.folder + "/";
        }
        return this;
    }

    /********************************************/
    /********* Resource loading methods *********/
    /********************************************/

    /**
     * Returns a full bath based on the current folder prefix and the
     * given {@code path} parameter
     * 
     * @param path the resource path relative to the current folder
     * @return the full path
     */
    private String getFullPath(String path) {
        if (path.startsWith("/")) {
            path = path.substring(1);
        }
        return folder + path;
    }

    /**
     * Returns a URL for the resource given by the {@code path} parameter.
     * 
     * @param path the path to the resource
     * @return the resource
     */
    public URL getResource(String path) {
        Objects.requireNonNull(path);
        return getClass().getClassLoader().getResource(getFullPath(path));
    }

    /**
     * Returns a new {@linkplain ImageIcon} for the image given by the {@code path} parameter.
     * 
     * @param path the path to the resource
     * @return the {@linkplain ImageIcon} with the given path
     */
    public ImageIcon getImageIcon(String path) {
        Objects.requireNonNull(path);
        URL url = getResource(path);
        return (url == null) ? null : new ImageIcon(url);
    }

    /**
     * Returns a cached {@linkplain ImageIcon} for the image given by the {@code path} parameter.
     * 
     * @param path the path to the resource
     * @return the {@linkplain ImageIcon} with the given path
     */
    public ImageIcon getCachedImageIcon(String path) {
        Objects.requireNonNull(path);
        CacheKey key = new CacheKey(loaderClass, getFullPath(path));
        ImageIcon imageIcon = (ImageIcon) cache.get(key);
        if (cache.containsKey(key)) {
            return imageIcon;
        }
        imageIcon = new ImageIcon(getResource(path));
        cache.put(key, imageIcon);
        return imageIcon;
    }

    /**********************************/
    /********* Helper classes *********/
    /**********************************/

    /**
     * Defines a cache key used for caching resources by loaderClass, 
     * and a full resource path
     */
    private static class CacheKey implements Serializable {
        private static final long serialVersionUID = 1L;
        private Class<?> loaderClass;
        private String fullPath;

        /**
         * Constructor
         * @param loaderClass
         * @param url
         */
        public CacheKey(Class<?> loaderClass, String fullPath) {
            Objects.requireNonNull(loaderClass);
            Objects.requireNonNull(fullPath);
            this.loaderClass = loaderClass;
            this.fullPath = fullPath;
        }

        @Override
        public int hashCode() {
            return Objects.hash(loaderClass, fullPath);
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            CacheKey other = (CacheKey) obj;
            return loaderClass.equals(other.loaderClass) && fullPath.equals(other.fullPath);
        }

    }
}