/* Copyright (C) 2006 Christian Schneider
*
* This file is part of Nomad.
*
* Nomad is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Nomad is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Nomad; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.sf.nmedit.jtheme.store;
import java.awt.Image;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import net.sf.nmedit.jtheme.JTContext;
import net.sf.nmedit.jtheme.JTException;
import net.sf.nmedit.jtheme.css.FakeRule;
import net.sf.nmedit.jtheme.image.ImageCache;
import net.sf.nmedit.jtheme.image.ImageResource;
import net.sf.nmedit.jtheme.store2.ComponentElement;
import net.sf.nmedit.jtheme.store2.DefaultStore;
import net.sf.nmedit.jtheme.store2.ModuleElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Element;
import org.w3c.dom.css.CSSRule;
import org.w3c.dom.css.CSSRuleList;
import org.w3c.dom.css.CSSStyleRule;
import org.w3c.dom.css.CSSStyleSheet;
public abstract class StorageContext
{
private transient Log log ;
private Log getLog()
{
if (log == null)
log = LogFactory.getLog(StorageContext.class);
return log;
}
public abstract JTContext getContext();
private Map<String, Class<? extends ComponentElement>> storeClassMap = new HashMap<String, Class<? extends ComponentElement>>();
private SoftReference<Map<String, Method>> storeMethodMap = null;
public abstract CSSStyleSheet getStyleSheet();
public abstract ImageCache getImageCache();
protected Map<String, CSSStyleRule> styleRuleMap = new HashMap<String, CSSStyleRule>();
private int idCounter = 1;
public String generateId()
{
return "#"+Integer.toHexString(idCounter++);
}
public abstract ImageResource getCachedImage(URL source);
public abstract ImageResource getCachedImage(String source);
public CSSStyleRule getStyleRule(String name)
{
CSSStyleRule rule = styleRuleMap.get(name);
if (rule != null) return FakeRule.isFake(rule) ? null : rule;
CSSStyleSheet css = getStyleSheet();
CSSRuleList list = css.getCssRules();
rule = null;
for (int i=0;i<list.getLength();i++)
{
CSSRule arule = list.item(i);
if (arule.getType() == CSSRule.STYLE_RULE)
{
CSSStyleRule srule = (CSSStyleRule) arule;
if (name.equals(srule.getSelectorText()))
{
// we found the rule
rule = srule;
break;
}
}
}
if (rule == null)
{
styleRuleMap.put(name, FakeRule.instance());
return null;
}
styleRuleMap.put(name, rule);
return rule;
}
public void installStore(String elementName, Class<? extends ComponentElement> storeClass)
{
storeClassMap.put(elementName, storeClass);
}
public Class<? extends ComponentElement> getStoreClass(String elementName)
{
Class<? extends ComponentElement> storeClass = storeClassMap.get(elementName);
if (storeClass == null)
storeClass = DefaultStore.class;
return storeClass;
}
public abstract ModuleElement getModuleStoreById(Object id);
public abstract ClassLoader getContextClassLoader();
private Map<String, Image> imageMap = new HashMap<String, Image>();
public Image getImage(String imageURL)
{
Image image = imageMap.get(imageURL);
if (image != null)
{
return image;
}
URL url =
getContextClassLoader()
.getResource(imageURL);
return (url != null) ? getImage(url) : null;
}
protected Image getImage(URL imageURL)
{
String key = imageURL.toString();
Image image = imageMap.get(key);
if (image == null)
{
try
{
image = ImageIO.read(imageURL);
imageMap.put(key, image);
}
catch (IOException e)
{
Log log = getLog();
if (log.isWarnEnabled())
{
log.warn("getImage("+imageURL+") failed",e);
}
}
}
return image;
}
public URL getContextResource(String name)
{
return getContextClassLoader().getResource(name);
}
public InputStream getContextResourceAsStream(String name)
{
return getContextClassLoader().getResourceAsStream(name);
}
protected Method getStoreCreateMethod(String elementName) throws JTException
{
Map<String, Method> map = null;
if (storeMethodMap != null)
{
map = storeMethodMap.get();
}
if (map == null)
{
map = new HashMap<String, Method>(160);
storeMethodMap = new SoftReference<Map<String,Method>>(map);
}
Method create = map.get(elementName);
if (create == null)
{
Class<? extends ComponentElement> storeClass = getStoreClass(elementName);
if (storeClass == null)
throw new JTException("No store for element: "+elementName);
try
{
create = storeClass.getDeclaredMethod("createElement", new Class<?>[]{StorageContext.class, Element.class});
}
catch (SecurityException e)
{
throw new JTException(e);
}
catch (NoSuchMethodException e)
{
throw new JTException("method createElement() not found in "+storeClass,e);
}
map.put(elementName, create);
}
return create;
}
public ComponentElement createStore(Element element)
throws JTException
{
/*
// fallback
Class<? extends JTComponent> jtclass = storeClassMap2.get(element.getName());
if (jtclass != null)
{
DefaultStore fb = new DefaultStore(this, element, jtclass);
return fb;
}*/
Method create = getStoreCreateMethod(element.getName());
try
{
ComponentElement store = (ComponentElement) create.invoke(null, new Object[] {this, element});
return store;
}
catch (IllegalArgumentException e)
{
throw new JTException("element "+element.getName(), e);
}
catch (IllegalAccessException e)
{
throw new JTException("element "+element.getName(), e);
}
catch (InvocationTargetException e)
{
throw new JTException("element "+element.getName(), e);
}
}
}