/*******************************************************************************
* 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);
}
}
}
}