/* 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 */ /* * Created on Dec 10, 2006 */ package net.sf.nmedit.jpatch; import java.awt.Image; import java.awt.Toolkit; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.ref.SoftReference; import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.xml.sax.InputSource; import net.sf.nmedit.jpatch.impl.PBasicModuleDescriptor; import net.sf.nmedit.jpatch.js.JSContext; import net.sf.nmedit.jpatch.transform.PTTransformations; import net.sf.nmedit.nmutils.PluginObjectInputStream; public class ModuleDescriptions implements Iterable<PModuleDescriptor> { private PSignalTypes signalTypes; private Map<String,PTypes<PType>> types = new HashMap<String, PTypes<PType>>(); private Map<Object, PModuleDescriptor> moduleMap = new HashMap<Object, PModuleDescriptor>(127); private ClassLoader loader; protected PTTransformations transformations; protected PModuleMetrics metrics; private SoftReference<Map<ImageSource, Image>> imageCacheReference; private JSContext jscontext; private DocumentationSrc documentationSrc; final class DocumentationSrc { private String lang; private String src; private Map<String, String> documentation = null; private boolean triedParsing = false; public DocumentationSrc(String lang, String src) { this.lang = lang; this.src = src; } void loadDocumentation() { if (triedParsing) return; triedParsing = true; ClassLoader loader = ModuleDescriptions.this.getModuleDescriptionsClassLoader(); if (loader == null) loader = ModuleDescriptions.this.getClass().getClassLoader(); try { InputStream is = loader.getResourceAsStream(src); documentation = PModuleDocumentationParser.build(new InputSource(is)); } catch (Exception e) { Log log = LogFactory.getLog(DocumentationSrc.class); if (log.isErrorEnabled()) log.trace(e); } } public String getDocumentationForKey(Object componentId) { loadDocumentation(); return documentation != null ? documentation.get(componentId) : null; } } public ModuleDescriptions(ClassLoader resourceClassLoader) { this.loader = resourceClassLoader; jscontext = new JSContext(); } public String getDocumentationFor(PModuleDescriptor module) { if (documentationSrc == null) return null; return documentationSrc.getDocumentationForKey(module.getComponentId()); } void setDocumentationSrc(String lang, String src) { this.documentationSrc = new DocumentationSrc(lang, src); } public JSContext getJSContext() { return jscontext; } private Map<ImageSource, Image> getImageCache() { Map<ImageSource, Image> cache = (imageCacheReference != null) ? imageCacheReference.get() : null; if (cache == null) { cache = new HashMap<ImageSource, Image>(); imageCacheReference = new SoftReference<Map<ImageSource,Image>>(cache); } return cache; } protected ClassLoader getResourceClassLoader() { return loader == null ? getClass().getClassLoader() : loader; } public URL getImageURL(ImageSource source) { return getResourceClassLoader().getResource(source.getSource()); } public Image getImage(ImageSource source) { Map<ImageSource, Image> cache = getImageCache(); Image image = cache.get(source); if (image == null) { URL url = getResourceClassLoader().getResource(source.getSource()); if (url != null) { image = Toolkit.getDefaultToolkit().getImage(url); cache.put(source, image); } } return image; } public void writeCache(ObjectOutputStream out) throws IOException { // signals out.writeObject(signalTypes); // types out.writeInt(types.size()); for (Entry<String, PTypes<PType>> e: types.entrySet()) { out.writeObject(e.getKey()); out.writeObject(e.getValue()); } // modules out.writeInt(moduleMap.size()); for (PModuleDescriptor m : moduleMap.values()) { out.writeObject(m); } } public void writeCache(File cache) throws FileNotFoundException, IOException { ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(cache))); try { writeCache(out); } finally { out.flush(); out.close(); } } @SuppressWarnings("unchecked") public void readCache(ObjectInputStream in) throws IOException, ClassNotFoundException { // signals signalTypes = (PSignalTypes) in.readObject(); int size; // types size = in.readInt(); for (int i=0;i<size;i++) { String key = (String) in.readObject(); PTypes<PType> t = (PTypes) in.readObject(); types.put(key, t); } // modules size = in.readInt(); for (int i=0;i<size;i++) { PModuleDescriptor d = (PModuleDescriptor) in.readObject(); ((PBasicModuleDescriptor)d).setModuleDescriptions(this); moduleMap.put(d.getComponentId(), d); } } public void readCache(File cache) throws FileNotFoundException, IOException, ClassNotFoundException { readCache(cache, getClass().getClassLoader()); } public void readCache(File cache, ClassLoader loader) throws FileNotFoundException, IOException, ClassNotFoundException { ObjectInputStream in = new PluginObjectInputStream(loader, new BufferedInputStream(new FileInputStream(cache))); try { readCache(in); } finally { in.close(); } } public PModuleMetrics getMetrics() { return metrics; } public PTTransformations getTransformations() { return transformations; } public ClassLoader getModuleDescriptionsClassLoader() { if (loader == null) return getClass().getClassLoader(); return loader; } public PSignalTypes getDefinedSignals() { return signalTypes; } public int getModuleCount() { return moduleMap.size(); } public void add( PModuleDescriptor module ) { moduleMap.put(module.getComponentId(), module); } public PModuleDescriptor getModuleById(Object id) { return moduleMap.get(id); } public void setSignals( PSignalTypes signalTypes ) { this.signalTypes = signalTypes; } public void addType( PTypes<PType> type ) { types.put(type.getName(), type); } public PTypes<PType> getType( String name ) { return types.get(name); } public PModuleDescriptor[] modulesByCategory(String categoryName) { List<PModuleDescriptor> modules = null; for (PModuleDescriptor mod : this) { if (categoryName.equals(mod.getCategory())) { if (modules == null) modules = new LinkedList<PModuleDescriptor>(); modules.add(mod); } } if (modules == null || modules.isEmpty()) return new PModuleDescriptor[0]; return modules.toArray(new PModuleDescriptor[modules.size()]); } public Iterator<PModuleDescriptor> iterator() { return moduleMap.values().iterator(); } public void setTransformations(PTTransformations t) { this.transformations = t; } }