/** * Copyright (c) 2011, 2012 Gunnar Wagenknecht and others. * All rights reserved. * * This program and the accompanying materials are 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: * Gunnar Wagenknecht - initial API and implementation */ package org.eclipse.gyrex.admin.ui.internal.pages.registry; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.eclipse.gyrex.admin.ui.internal.AdminUiActivator; import org.eclipse.gyrex.common.lifecycle.IShutdownParticipant; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.RegistryFactory; import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker; import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler; import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A registry for contributed admin pages */ public class AdminPageRegistry implements IExtensionChangeHandler { private static final String ELEMENT_PAGE = "page"; private static final String ELEMENT_CATEGORY = "category"; private static final String EP_PAGES = "pages"; private static final Logger LOG = LoggerFactory.getLogger(AdminPageRegistry.class); private static final AdminPageRegistry instance = new AdminPageRegistry(); /** * Returns the shared instance. * * @return the instance */ public static AdminPageRegistry getInstance() { return instance; } private final ConcurrentMap<String, PageContribution> pagesById = new ConcurrentHashMap<String, PageContribution>(); private final ConcurrentMap<String, CategoryContribution> categoriesById = new ConcurrentHashMap<String, CategoryContribution>(4); private volatile Map<String, Set<PageContribution>> pagesByCategoryId; private AdminPageRegistry() { final IExtensionRegistry registry = RegistryFactory.getRegistry(); if (null == registry) throw new IllegalStateException("Extension registry is not available!"); // get extension point final IExtensionPoint extensionPoint = registry.getExtensionPoint(AdminUiActivator.SYMBOLIC_NAME, EP_PAGES); if (null == extensionPoint) throw new IllegalStateException("Admin pages extension point not found!"); // register tracker final IExtensionTracker tracker = new ExtensionTracker(registry); tracker.registerHandler(this, ExtensionTracker.createExtensionPointFilter(extensionPoint)); AdminUiActivator.getInstance().addShutdownParticipant(new IShutdownParticipant() { @Override public void shutdown() throws Exception { tracker.close(); } }); // initial population final IExtension[] extensions = extensionPoint.getExtensions(); for (final IExtension extension : extensions) { addExtension(tracker, extension); } } @Override public void addExtension(final IExtensionTracker tracker, final IExtension extension) { final IConfigurationElement[] elements = extension.getConfigurationElements(); for (final IConfigurationElement element : elements) { if (StringUtils.equals(ELEMENT_PAGE, element.getName())) { final PageContribution page = new PageContribution(element); final String id = page.getId(); if (null == pagesById.putIfAbsent(id, page)) { rebuildCategories(); } else { LOG.warn("Ignoring duplicate page {} contributed by {}", id, extension.getContributor().getName()); } } else if (StringUtils.equals(ELEMENT_CATEGORY, element.getName())) { final CategoryContribution category = new CategoryContribution(element); final String id = category.getId(); if (null != categoriesById.putIfAbsent(id, category)) { LOG.warn("Ignoring duplicate category {} contributed by {}", id, extension.getContributor().getName()); } } } } public List<CategoryContribution> getCategories() { if (categoriesById.isEmpty()) return Collections.emptyList(); return new ArrayList<CategoryContribution>(categoriesById.values()); } public PageContribution getPage(final String id) { return pagesById.get(id); } public List<PageContribution> getPages(final CategoryContribution category) { final Map<String, Set<PageContribution>> mappings = pagesByCategoryId; if ((mappings == null) || mappings.isEmpty()) return Collections.emptyList(); final Set<PageContribution> children = mappings.get(category.getId()); if ((children == null) || children.isEmpty()) return Collections.emptyList(); // return a copy return new ArrayList<PageContribution>(children); } public CategoryContribution getParent(final PageContribution page) { if (null == page.getCategoryId()) return null; // return a copy return categoriesById.get(page.getCategoryId()); } public boolean hasPages(final CategoryContribution category) { if (category == null) return false; final Map<String, Set<PageContribution>> mappings = pagesByCategoryId; if (mappings == null) return false; final Set<PageContribution> children = mappings.get(category.getId()); return (children != null) && !children.isEmpty(); } private void rebuildCategories() { final Map<String, Set<PageContribution>> mappings = new HashMap<String, Set<PageContribution>>(); final Collection<PageContribution> values = pagesById.values(); for (final PageContribution page : values) { if (!mappings.containsKey(page.getCategoryId())) { mappings.put(page.getCategoryId(), new HashSet<PageContribution>(1)); } mappings.get(page.getCategoryId()).add(page); } pagesByCategoryId = mappings; } @Override public void removeExtension(final IExtension extension, final Object[] objects) { final IConfigurationElement[] elements = extension.getConfigurationElements(); for (final IConfigurationElement element : elements) { if (StringUtils.equals(ELEMENT_PAGE, element.getName())) { final String id = element.getAttribute("id"); final PageContribution page = pagesById.remove(id); if (page != null) { rebuildCategories(); } } } } }