/** * Copyright (C) 2008-2011 Daniel Senff * * This program 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. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package de.danielsenff.imageflow.controller; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import javax.swing.JOptionPane; import javax.swing.tree.DefaultTreeModel; import de.danielsenff.imageflow.ImageFlow; import de.danielsenff.imageflow.controller.BasicUnitXMLLoader.UnitDelegateInfo; import de.danielsenff.imageflow.models.delegates.Delegate; import de.danielsenff.imageflow.models.delegates.UnitDelegate; import de.danielsenff.imageflow.models.delegates.UnitMutableTreeNode; /** * Controller for reading and managing {@link UnitDelegate}s. * @author senff * */ public class DelegatesController { /** * folder, which contains the unit xml descriptions * TODO not hardcoded ... */ public static String unitFolder = "xml_units/"; /** * folder containing the icons which might be referenced in the xml descriptions * TODO not hardcoded ... */ public static String unitIconFolder = "xml_icons"; private static DelegatesController controller; /** * Used to create the unit insert menu */ public DefaultTreeModel delegatesTreeModel; /** * All unique UnitDelegates names. */ protected HashSet<String> delegateNames; /** * All UnitDelegates mapped by unique name. */ protected HashMap<String, Delegate> delegatesMapByName; /** * All UnitDelegates mapped by File Path. * TODO check consistency */ protected HashMap<String, Delegate> delegatesMapByPath; protected UnitMutableTreeNode top; private Hashtable<String, UnitDelegateInfo> unitEntries; /** * The URL from where the initial units have been loaded. */ public URL resourcesBase; protected DelegatesController() { this.delegatesMapByName = new HashMap<String, Delegate>(); this.delegatesMapByPath = new HashMap<String, Delegate>(); this.delegateNames = new HashSet<String>(); this.unitEntries = new Hashtable<String, UnitDelegateInfo>(); this.top = new UnitMutableTreeNode("Insert unit"); this.delegatesTreeModel = new DefaultTreeModel(top); } /** * Initialize the DelegatesModel and load the available unit xml definitions. */ public void initializeDelegatesModel() { String unitsLocation = ""; try { // try to load xml units from surrounding jar by default unitsLocation = getClassResourceBase(); setResourcesBase(DelegatesController.class.getClassLoader().getResource(unitsLocation)); if (resourcesBase != null && resourcesBase.openConnection().getContentLength() > 0) { readDelegatesFromURL(top, resourcesBase); } else throw new IOException("The resource has no content!"); // see if there is a unit xml folder and load those as well File unitFolderFile = new File(getAbsolutePathToUnitFolder()); if(unitFolderFile.exists()) { readDelegatesFromFolder(top, unitFolderFile.toURI().toURL()); } } catch (MalformedURLException e) { JOptionPane.showMessageDialog(ImageFlow.getApplication().getMainFrame(), "The URL " + unitsLocation + " is malformed. No units have been found.", "No unit defintions found", JOptionPane.WARNING_MESSAGE); } catch (IOException e) { JOptionPane.showMessageDialog(ImageFlow.getApplication().getMainFrame(), "The resource " + unitsLocation + " is missing. No units have been found.", "No unit defintions found", JOptionPane.WARNING_MESSAGE); } } private void readDelegatesFromURL(UnitMutableTreeNode node, URL url) throws RuntimeException, MalformedURLException { UnitDelegateLoader loader = UnitXMLLoaderFactory.createUnitXMLLoaderByProtocol(url.getProtocol()); loader.readDelegates(node, url); } private void readDelegatesFromFolder(UnitMutableTreeNode node, URL url) throws RuntimeException, MalformedURLException { UnitDelegateLoader loader = UnitXMLLoaderFactory.createFolderUnitXMLLoader(); loader.readDelegates(node, url); } /** * {@link DelegatesController} is a Singleton, * this returns the available Instance. * @return */ public static DelegatesController getInstance() { if(controller == null) { controller = new DelegatesController(); } return controller; } /** * Name of the folder that can contain customized Unit descriptions. * @return */ public static String getUnitFolderName() { return unitFolder; } public static String getUnitIconFolderName() { return unitIconFolder; } /** * Gets the base path of the resources contained in this jar. */ public static String getClassResourceBase() { return DelegatesController.class.getName().replace(".", "/") + ".class"; } /** * Gets the resource base url of the initially loaded units. * This could be a folder or a jar file. * @return */ public URL getResourcesBase() { return resourcesBase; } /** * Sets the resource base path by taking a URL and * removing its relative parts. */ private void setResourcesBase(URL path) throws MalformedURLException { String protocol = path.getProtocol(); if (protocol.equals("file")) { resourcesBase = new URL(path, getAbsolutePathToUnitFolder()); } else if (protocol.equals("jar")) { resourcesBase = new URL(path, "/"); } } public static String getAbsolutePathToWorkingFolder() { return System.getProperty("user.dir") + File.separator; } /** * Returns the absolute path to the executed jar and a folder of a given name. * @param folderName * @return */ public static String getAbsolutePathToFolder(String folderName) { return System.getProperty("user.dir") + File.separator + folderName; } /** * Returns the absolute path to the xml units folder. * @param folderName * @return */ public static String getAbsolutePathToUnitFolder() { return getAbsolutePathToFolder(getUnitFolderName()); } /** * Find a UnitDelegate by unique name. * @param unitName * @return */ public UnitDelegate getDelegate(final String unitName) { UnitDelegate unitDelegate = null; for (final Delegate delegate : mapDelegatesByName().values()) { if(delegate instanceof UnitDelegate) { unitDelegate = (UnitDelegate) delegate; if (unitDelegate.getName().equals(unitName)) return unitDelegate; } } return null; } public Dictionary<String, UnitDelegateInfo> getUnitEntries() { return this.unitEntries; } /** * Get a list of all Units that can be added to the workflow. * @return */ public HashMap<String, Delegate> mapDelegatesByName() { return delegatesMapByName; } public HashMap<String, Delegate> mapDelegatesByPath() { return delegatesMapByPath; } public HashSet<String> getDelegateNames() { return delegateNames; } /** * Get a TreeModel with the delegates and their tree structure * @return */ public DefaultTreeModel getDelegatesModel() { return delegatesTreeModel; } public void addDelegate(final UnitDelegate delegate) { this.delegatesMapByName.put(delegate.getName(), delegate); this.delegatesMapByPath.put(delegate.getXMLPath(), delegate); this.delegateNames.add(delegate.getName()); } public void replaceDelegate(UnitDelegate delegate) { this.delegatesMapByName.put(delegate.getName(), delegate); this.delegatesMapByPath.put(delegate.getXMLPath(), delegate); } }