001/* 002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 * $Id$ 018 */ 019 020package org.nuxeo.ecm.webapp.tree; 021 022import java.util.HashMap; 023import java.util.List; 024import java.util.Map; 025 026import org.apache.commons.logging.Log; 027import org.apache.commons.logging.LogFactory; 028import org.nuxeo.ecm.core.api.DocumentModel; 029import org.nuxeo.ecm.core.api.Filter; 030import org.nuxeo.ecm.core.api.Sorter; 031import org.nuxeo.ecm.core.api.tree.DefaultDocumentTreeFilter; 032import org.nuxeo.ecm.core.api.tree.DefaultDocumentTreeSorter; 033import org.nuxeo.ecm.core.api.tree.DocumentTreeFilter; 034import org.nuxeo.ecm.core.api.tree.DocumentTreeSorter; 035import org.nuxeo.runtime.model.ComponentContext; 036import org.nuxeo.runtime.model.ComponentInstance; 037import org.nuxeo.runtime.model.DefaultComponent; 038 039/** 040 * Component for tree service, handing registries for trees managing {@link DocumentModel} object. 041 * 042 * @author Anahide Tchertchian 043 */ 044// TODO: refactor to use only one registry 045public class TreeManagerImpl extends DefaultComponent implements TreeManager { 046 047 private static final long serialVersionUID = 1L; 048 049 public static final String NAME = TreeManager.class.getName(); 050 051 public static final String PLUGIN_EXTENSION_POINT = "plugin"; 052 053 private static final Log log = LogFactory.getLog(TreeManager.class); 054 055 protected Map<String, Filter> filters; 056 057 protected Map<String, Filter> leafFilters; 058 059 protected Map<String, Sorter> sorters; 060 061 protected Map<String, String> pageProviderNames; 062 063 @SuppressWarnings("unchecked") 064 @Override 065 public <T> T getAdapter(Class<T> adapter) { 066 if (adapter.isAssignableFrom(TreeManager.class)) { 067 return (T) this; 068 } 069 return null; 070 } 071 072 @Override 073 public void activate(ComponentContext context) { 074 super.activate(context); 075 filters = new HashMap<String, Filter>(); 076 leafFilters = new HashMap<String, Filter>(); 077 sorters = new HashMap<String, Sorter>(); 078 pageProviderNames = new HashMap<String, String>(); 079 } 080 081 @Override 082 public void deactivate(ComponentContext context) { 083 filters = null; 084 leafFilters = null; 085 sorters = null; 086 pageProviderNames = null; 087 super.deactivate(context); 088 } 089 090 @Override 091 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 092 if (PLUGIN_EXTENSION_POINT.equals(extensionPoint)) { 093 TreeManagerPluginDescriptor plugin = (TreeManagerPluginDescriptor) contribution; 094 String name = plugin.getName(); 095 // filter 096 if (filters.containsKey(name)) { 097 // FIXME handle merge? 098 log.info("Overriding filter for plugin " + name); 099 filters.remove(name); 100 } 101 log.info("Registering filter for plugin " + name); 102 filters.put(name, buildFilter(plugin)); 103 // leaf filter 104 if (leafFilters.containsKey(name)) { 105 // FIXME handle merge? 106 log.info("Overriding leaf filter for plugin " + name); 107 leafFilters.remove(name); 108 } 109 log.info("Registering leaf filter for plugin " + name); 110 leafFilters.put(name, buildLeafFilter(plugin)); 111 // sorter 112 if (sorters.containsKey(name)) { 113 // FIXME handle merge? 114 log.info("Overriding sorter for plugin " + name); 115 sorters.remove(name); 116 } 117 log.info("Registering sorter for plugin " + name); 118 sorters.put(name, buildSorter(plugin)); 119 120 // page provider 121 if (pageProviderNames.containsKey(name)) { 122 // FIXME handle merge? 123 log.info("Overriding page provider for plugin " + name); 124 pageProviderNames.remove(name); 125 } 126 log.info("Registering page provider for plugin " + name); 127 pageProviderNames.put(name, plugin.getPageProvider()); 128 } 129 } 130 131 @Override 132 public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 133 if (PLUGIN_EXTENSION_POINT.equals(extensionPoint)) { 134 TreeManagerPluginDescriptor plugin = (TreeManagerPluginDescriptor) contribution; 135 String name = plugin.getName(); 136 // filter 137 if (filters.containsKey(name)) { 138 log.info("Unregistering filter for plugin " + name); 139 filters.remove(name); 140 } 141 // leaf filter 142 if (leafFilters.containsKey(name)) { 143 log.info("Unregistering leaf filter for plugin " + name); 144 leafFilters.remove(name); 145 } 146 // sorter 147 if (sorters.containsKey(name)) { 148 log.info("Unregistering sorter for plugin " + name); 149 sorters.remove(name); 150 } 151 // page provider 152 if (pageProviderNames.containsKey(name)) { 153 log.info("Unregistering page provider for plugin " + name); 154 pageProviderNames.remove(name); 155 } 156 } 157 } 158 159 protected Filter buildFilter(TreeManagerPluginDescriptor plugin) { 160 Filter filter = null; 161 162 List<String> includedFacets = plugin.getIncludedFacets(); 163 List<String> excludedFacets = plugin.getExcludedFacets(); 164 List<String> excludedTypes = plugin.getExcludedTypes(); 165 166 String filterClass = plugin.getFilterClassName(); 167 if (filterClass == null || "".equals(filterClass)) { 168 if ((includedFacets == null || includedFacets.isEmpty()) 169 && (excludedFacets == null || excludedFacets.isEmpty()) 170 && (excludedTypes == null || excludedTypes.isEmpty())) { 171 return null; 172 } 173 // built-in filter 174 filter = new DefaultDocumentTreeFilter(); 175 } else { 176 // custom filter 177 try { 178 Object instance = TreeManagerImpl.class.getClassLoader().loadClass(filterClass).newInstance(); 179 if (instance instanceof Filter) { 180 filter = (Filter) instance; 181 } else { 182 log.error(String.format("Class %s should follow %s interface", filterClass, Filter.class.getName())); 183 } 184 } catch (ReflectiveOperationException e) { 185 log.error(e, e); 186 } 187 } 188 189 // setup config when possible 190 if (filter instanceof DocumentTreeFilter) { 191 DocumentTreeFilter treeFilter = (DocumentTreeFilter) filter; 192 treeFilter.setIncludedFacets(includedFacets); 193 treeFilter.setExcludedFacets(excludedFacets); 194 treeFilter.setExcludedTypes(excludedTypes); 195 } 196 197 return filter; 198 } 199 200 protected Filter buildLeafFilter(TreeManagerPluginDescriptor plugin) { 201 String leafFilterClass = plugin.getLeafFilterClassName(); 202 if (leafFilterClass == null || "".equals(leafFilterClass)) { 203 return null; 204 } 205 try { 206 Object instance = TreeManagerImpl.class.getClassLoader().loadClass(leafFilterClass).newInstance(); 207 if (instance instanceof Filter) { 208 return (Filter) instance; 209 } else { 210 log.error(String.format("Class %s should follow %s interface", leafFilterClass, Filter.class.getName())); 211 } 212 } catch (ReflectiveOperationException e) { 213 log.error(e, e); 214 } 215 return null; 216 } 217 218 protected Sorter buildSorter(TreeManagerPluginDescriptor plugin) { 219 Sorter sorter = null; 220 221 String sortPropertyPath = plugin.getSortPropertyPath(); 222 223 String sorterClass = plugin.getSorterClassName(); 224 if (sorterClass == null || "".equals(sorterClass)) { 225 if (sortPropertyPath == null || "".equals(sortPropertyPath)) { 226 return null; 227 } 228 // built-in sorter 229 sorter = new DefaultDocumentTreeSorter(); 230 } else { 231 // custom sorter 232 try { 233 Object instance = TreeManagerImpl.class.getClassLoader().loadClass(sorterClass).newInstance(); 234 if (instance instanceof Sorter) { 235 sorter = (Sorter) instance; 236 } else { 237 log.error(String.format("Class %s should follow %s interface", sorterClass, Sorter.class.getName())); 238 } 239 } catch (ReflectiveOperationException e) { 240 log.error(e, e); 241 } 242 } 243 244 // setup config when possible 245 if (sorter instanceof DocumentTreeSorter) { 246 DocumentTreeSorter treeSorter = (DocumentTreeSorter) sorter; 247 treeSorter.setSortPropertyPath(sortPropertyPath); 248 } 249 250 return sorter; 251 } 252 253 public Filter getFilter(String pluginName) { 254 return filters.get(pluginName); 255 } 256 257 public Filter getLeafFilter(String pluginName) { 258 return leafFilters.get(pluginName); 259 } 260 261 public Sorter getSorter(String pluginName) { 262 return sorters.get(pluginName); 263 } 264 265 @Override 266 public String getPageProviderName(String pluginName) { 267 return pageProviderNames.get(pluginName); 268 } 269 270}