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.log4j.Logger;
032
033 import org.apache.isis.core.commons.debug.DebugString;
034 import org.apache.isis.core.commons.exceptions.IsisException;
035 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
036 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
037
038 /**
039 * ImageLookup provides an efficient way of finding the most suitable image to
040 * use. It ensures that an image is always available, providing a default image
041 * if needed. All requests are cached to improve performance.
042 */
043 // TODO allow for multiple extension types
044 public class ImageLookup {
045 private static final Logger LOG = Logger.getLogger(ImageLookup.class);
046 private static final String UNKNOWN_IMAGE = "Default";
047 private static final String[] EXTENSIONS = { "png", "gif", "jpg", "jpeg" };
048 private static final Map images = new HashMap();
049 private static String imageDirectory;
050 // private static String unknownImageFile;
051 private static ServletContext context;
052
053 public static void setImageDirectory(final ServletContext context, String imageDirectory) {
054 LOG.debug("image directory required for: " + imageDirectory);
055 ImageLookup.context = context;
056 imageDirectory = (imageDirectory.startsWith("/") ? "" : "/") + imageDirectory + "/";
057 final Set resourcePaths = context.getResourcePaths(imageDirectory);
058 if (resourcePaths == null || resourcePaths.size() == 0) {
059 throw new IsisException("No image directory found: " + imageDirectory);
060 }
061 LOG.info("image directory set to: " + imageDirectory);
062 ImageLookup.imageDirectory = imageDirectory;
063 }
064
065 public static void debug(final DebugString debug) {
066 debug.appendTitle("Image Lookup");
067 debug.indent();
068 final Iterator keys = images.keySet().iterator();
069 while (keys.hasNext()) {
070 final Object key = keys.next();
071 final Object value = images.get(key);
072 debug.appendln(key + " -> " + value);
073 }
074 debug.unindent();
075 }
076
077 private static String imageFile(final String imageName, final String contextPath) {
078 for (final String element : EXTENSIONS) {
079 URL resource;
080 try {
081 final String imagePath = imageDirectory + imageName + "." + element;
082 resource = context.getResource(imagePath);
083 if (resource != null) {
084 LOG.debug("image found at " + contextPath + imagePath);
085 return contextPath + imagePath;
086 }
087 final URL onClasspath = ImageLookup.class.getResource(imagePath);
088 if (onClasspath != null) {
089 LOG.debug("image found on classpath " + onClasspath);
090 return contextPath + imagePath;
091 }
092 } catch (final MalformedURLException ignore) {
093 }
094 }
095 return null;
096 }
097
098 private static String findImage(final ObjectSpecification specification, final String contextPath) {
099 String path = findImageFor(specification, contextPath);
100 if (path == null) {
101 path = imageFile(UNKNOWN_IMAGE, contextPath);
102 }
103 return path;
104 }
105
106 private static String findImageFor(final ObjectSpecification specification, final String contextPath) {
107 final String name = specification.getShortIdentifier();
108 final String fileName = imageFile(name, contextPath);
109 if (fileName != null) {
110 images.put(name, fileName);
111 return fileName;
112 } else {
113 for (final ObjectSpecification interfaceSpec : specification.interfaces()) {
114 final String path = findImageFor(interfaceSpec, contextPath);
115 if (path != null) {
116 return path;
117 }
118 }
119 final ObjectSpecification superclass = specification.superclass();
120 if (superclass != null) {
121 return findImageFor(superclass, contextPath);
122 } else {
123 return null;
124 }
125 }
126 }
127
128 /**
129 * For an object, the icon name from the object is return if it is not null,
130 * otherwise the specification is used to look up a suitable image name.
131 *
132 * @param contextPath
133 *
134 * @see ObjectAdapter#getIconName()
135 * @see #imagePath(ObjectSpecification)
136 */
137 /*
138 * public static String imagePath(ObjectAdapter object) { String iconName =
139 * object.getIconName(); if (iconName != null) { return imagePath(iconName);
140 * } else { return imagePath(object.getSpecification()); } }
141 */
142 public static String imagePath(final ObjectSpecification specification, final String contextPath) {
143 final String name = specification.getShortIdentifier();
144 final String imageName = (String) images.get(name);
145 if (imageName != null) {
146 return imageName;
147 } else {
148 return findImage(specification, contextPath);
149 }
150 }
151
152 /*
153 * public static String imagePath(String name) { String imageName = (String)
154 * images.get(name); if (imageName != null) { return (String) imageName; }
155 * else { String fileName = imageFile(name); return fileName == null ?
156 * unknownImageFile : fileName; } }
157 */
158
159 public static String imagePath(final ObjectAdapter object, final String contextPath) {
160 final String name = object.getIconName();
161 final String imageName = (String) images.get(name);
162 if (imageName != null) {
163 return imageName;
164 } else {
165 final String imageFile = imageFile(name, contextPath);
166 if (imageFile != null) {
167 return imageFile;
168 } else {
169 return findImage(object.getSpecification(), contextPath);
170 }
171 }
172 }
173 }