/******************************************************************************* * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Exadel, Inc. and Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.common.model.ui.views.navigator; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IProject; import org.jboss.tools.common.model.XFilteredTree; import org.jboss.tools.common.model.XModel; import org.jboss.tools.common.model.event.XModelTreeListener; import org.jboss.tools.common.model.project.IModelNature; import org.jboss.tools.common.model.ui.ModelUIPlugin; import org.jboss.tools.common.model.util.EclipseResourceUtil; import org.jboss.tools.common.model.util.ModelFeatureFactory; /** * This cache is needed because content provider used in * common navigator is stateless, and each call to its method * needs to restore instance of XFilteredTree. It would take * too much time to create it each time anew. * @author glory */ public class FilteredTreesCache { static FilteredTreesCache instance = new FilteredTreesCache(); public static FilteredTreesCache getInstance() { return instance; } Map<String, Map<XModel,XFilteredTree>> map = new HashMap<String, Map<XModel,XFilteredTree>>(); private FilteredTreesCache() {} /** * Takes existing tree instance from cache or creates one if needed. * @param name * @param model * @return */ public XFilteredTree getFilteredTree(String name, XModel model) { if(name == null || model == null) return null; Map<XModel,XFilteredTree> nmap = getNamedMap(name); XFilteredTree result = nmap.get(model); if(result == null) { result = createTree(name, model); if(result != null) nmap.put(model, result); } return result; } Map<XModel,XFilteredTree> getNamedMap(String name) { Map<XModel,XFilteredTree> nmap = map.get(name); if(nmap == null) { nmap = new HashMap<XModel, XFilteredTree>(); map.put(name, nmap); } return nmap; } public void remove(XModel model) { if(model == null) return; Collection<Map<XModel,XFilteredTree>> i1 = map.values(); for (Map<XModel,XFilteredTree> m: i1) { m.remove(model); for (XModelTreeListener l : listeners) { model.removeModelTreeListener(l); } } } XFilteredTree createTree(String name, XModel model) { if(model == null || name == null) return null; String classname = model.getMetaData().getMapping("FilteredTrees").getValue(name); //$NON-NLS-1$ XFilteredTree result = null; try { result = (XFilteredTree)ModelFeatureFactory.getInstance().createFeatureInstance(classname); } catch (ClassCastException e) { ModelUIPlugin.getPluginLog().logError(e); return null; } result.setModel(model); if(result.getRoot() == null) { result = null; IProject p = EclipseResourceUtil.getProject(model.getRoot()); IModelNature nature = EclipseResourceUtil.getModelNature(p); if(nature != null) { ModelUIPlugin.getPluginLog().logInfo("Red Hat Project " + p.getName() + " is corrupted."); //$NON-NLS-1$ //$NON-NLS-2$ } } return result; } Set<XModelTreeListener> listeners = new HashSet<XModelTreeListener>(); /** * Registers listener with this cache. * Using this cache by stateless content providers * makes it necessary to register listener with it, * rather than just add it to model. Then, by * unregistering the listener while disposing content * provider, we can be sure that the listener is removed * from all models to which it has been added. * @param listener * @param model */ public void addListener(XModelTreeListener listener, XModel model) { listeners.add(listener); model.addModelTreeListener(listener); } /** * Unregisters listener from this cache. * The listener is removed from all models * to which it has been added. **/ public void removeListener(XModelTreeListener listener) { listeners.remove(listener); Collection<Map<XModel,XFilteredTree>> i1 = map.values(); for (Map<XModel,XFilteredTree> m: i1) { Collection<XFilteredTree> i2 = m.values(); for (XFilteredTree t : i2) { XModel model = t.getRoot().getModel(); if(model != null) model.removeModelTreeListener(listener); } } } }