001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020 package org.apache.isis.viewer.scimpi.servlet;
021
022 import java.net.MalformedURLException;
023 import java.net.URL;
024 import java.util.HashMap;
025 import java.util.Iterator;
026 import java.util.Map;
027 import java.util.Set;
028
029 import javax.servlet.ServletContext;
030
031 import org.apache.isis.core.commons.debug.DebugString;
032 import org.apache.isis.core.commons.exceptions.IsisException;
033 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
034 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
035 import org.apache.log4j.Logger;
036
037 /**
038 * ImageLookup provides an efficient way of finding the most suitable image to use. It ensures that an image is always
039 * available, providing a default image if needed. All requests are cached to improve performance.
040 */
041 // TODO allow for multiple extension types
042 public class ImageLookup {
043 private static final Logger LOG = Logger.getLogger(ImageLookup.class);
044 private static final String UNKNOWN_IMAGE = "Default";
045 private static final String[] EXTENSIONS = { "png", "gif", "jpg", "jpeg" };
046 private static final Map images = new HashMap();
047 private static String imageDirectory;
048 // private static String unknownImageFile;
049 private static ServletContext context;
050
051 public static void setImageDirectory(final ServletContext context, String imageDirectory) {
052 LOG.debug("image directory required for: " + imageDirectory);
053 ImageLookup.context = context;
054 imageDirectory = (imageDirectory.startsWith("/") ? "" : "/") + imageDirectory + "/";
055 final Set resourcePaths = context.getResourcePaths(imageDirectory);
056 if (resourcePaths == null || resourcePaths.size() == 0) {
057 throw new IsisException("No image directory found: " + imageDirectory);
058 }
059 LOG.info("image directory set to: " + imageDirectory);
060 ImageLookup.imageDirectory = imageDirectory;
061 }
062
063 public static void debug(final DebugString debug) {
064 debug.appendTitle("Image Lookup");
065 debug.indent();
066 final Iterator keys = images.keySet().iterator();
067 while (keys.hasNext()) {
068 final Object key = keys.next();
069 final Object value = images.get(key);
070 debug.appendln(key + " -> " + value);
071 }
072 debug.unindent();
073 }
074
075 private static String imageFile(final String imageName, final String contextPath) {
076 for (final String element : EXTENSIONS) {
077 URL resource;
078 try {
079 final String imagePath = imageDirectory + imageName + "." + element;
080 resource = context.getResource(imagePath);
081 if (resource != null) {
082 LOG.debug("image found at " + contextPath + imagePath);
083 return contextPath + imagePath;
084 }
085 final URL onClasspath = ImageLookup.class.getResource(imagePath);
086 if (onClasspath != null) {
087 LOG.debug("image found on classpath " + onClasspath);
088 return contextPath + imagePath;
089 }
090 } catch (final MalformedURLException ignore) {
091 }
092 }
093 return null;
094 }
095
096 private static String findImage(final ObjectSpecification specification, final String contextPath) {
097 String path = findImageFor(specification, contextPath);
098 if (path == null) {
099 path = imageFile(UNKNOWN_IMAGE, contextPath);
100 }
101 return path;
102 }
103
104 private static String findImageFor(final ObjectSpecification specification, final String contextPath) {
105 final String name = specification.getShortIdentifier();
106 final String fileName = imageFile(name, contextPath);
107 if (fileName != null) {
108 images.put(name, fileName);
109 return fileName;
110 } else {
111 for (final ObjectSpecification interfaceSpec : specification.interfaces()) {
112 final String path = findImageFor(interfaceSpec, contextPath);
113 if (path != null) {
114 return path;
115 }
116 }
117 final ObjectSpecification superclass = specification.superclass();
118 if (superclass != null) {
119 return findImageFor(superclass, contextPath);
120 } else {
121 return null;
122 }
123 }
124 }
125
126 /**
127 * For an object, the icon name from the object is return if it is not null, otherwise the specification is used to
128 * look up a suitable image name.
129 *
130 * @param contextPath
131 *
132 * @see ObjectAdapter#getIconName()
133 * @see #imagePath(ObjectSpecification)
134 */
135 /*
136 * public static String imagePath(ObjectAdapter object) { String iconName = object.getIconName(); if (iconName !=
137 * null) { return imagePath(iconName); } else { return imagePath(object.getSpecification()); } }
138 */
139 public static String imagePath(final ObjectSpecification specification, final String contextPath) {
140 final String name = specification.getShortIdentifier();
141 final String imageName = (String) images.get(name);
142 if (imageName != null) {
143 return imageName;
144 } else {
145 return findImage(specification, contextPath);
146 }
147 }
148
149 /*
150 * public static String imagePath(String name) { String imageName = (String) images.get(name); if (imageName !=
151 * null) { return (String) imageName; } else { String fileName = imageFile(name); return fileName == null ?
152 * unknownImageFile : fileName; } }
153 */
154
155 public static String imagePath(final ObjectAdapter object, final String contextPath) {
156 final String name = object.getIconName();
157 final String imageName = (String) images.get(name);
158 if (imageName != null) {
159 return imageName;
160 } else {
161 final String imageFile = imageFile(name, contextPath);
162 if (imageFile != null) {
163 return imageFile;
164 } else {
165 return findImage(object.getSpecification(), contextPath);
166 }
167 }
168 }
169 }