| /* |
| * Copyright (c) 2014, 2015 Eike Stepper (Berlin, Germany) 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: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.oomph.setup.internal.core.util; |
| |
| import org.eclipse.oomph.base.util.BaseUtil; |
| import org.eclipse.oomph.setup.CatalogSelection; |
| import org.eclipse.oomph.setup.Index; |
| import org.eclipse.oomph.setup.ProductCatalog; |
| import org.eclipse.oomph.setup.Scope; |
| import org.eclipse.oomph.setup.SetupFactory; |
| import org.eclipse.oomph.setup.SetupPackage; |
| import org.eclipse.oomph.setup.Stream; |
| import org.eclipse.oomph.setup.internal.core.SetupContext; |
| import org.eclipse.oomph.setup.internal.core.SetupCorePlugin; |
| |
| import org.eclipse.emf.common.util.BasicEMap; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.EMap; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.InternalEObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.util.InternalEList; |
| |
| import java.beans.PropertyChangeListener; |
| import java.beans.PropertyChangeSupport; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public class CatalogManager |
| { |
| public static final String PROPERTY_INDEX = "PROPERTY_INDEX"; |
| |
| private Index index; |
| |
| private CatalogSelection selection; |
| |
| private PropertyChangeSupport propertyChangeSupport; |
| |
| public CatalogManager() |
| { |
| selection = SetupFactory.eINSTANCE.createCatalogSelection(); |
| Resource selectionResource = Resource.Factory.Registry.INSTANCE.getFactory(SetupContext.CATALOG_SELECTION_SETUP_URI) |
| .createResource(SetupContext.CATALOG_SELECTION_SETUP_URI); |
| selectionResource.getContents().add(selection); |
| } |
| |
| public void addPropertyChangeListener(PropertyChangeListener listener) |
| { |
| getPropertyChangeSupport().addPropertyChangeListener(listener); |
| } |
| |
| public void removePropertyChangeListener(PropertyChangeListener listener) |
| { |
| getPropertyChangeSupport().removePropertyChangeListener(listener); |
| } |
| |
| private synchronized PropertyChangeSupport getPropertyChangeSupport() |
| { |
| if (propertyChangeSupport == null) |
| { |
| propertyChangeSupport = new PropertyChangeSupport(this); |
| } |
| |
| return propertyChangeSupport; |
| } |
| |
| public Index getIndex() |
| { |
| return index; |
| } |
| |
| public CatalogSelection getSelection() |
| { |
| return selection; |
| } |
| |
| public List<? extends Scope> getCatalogs(boolean product) |
| { |
| if (index == null) |
| { |
| return Collections.emptyList(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| List<? extends Scope> result = (List<? extends Scope>)index |
| .eGet(product ? SetupPackage.Literals.INDEX__PRODUCT_CATALOGS : SetupPackage.Literals.INDEX__PROJECT_CATALOGS); |
| return result; |
| } |
| |
| public List<? extends Scope> getSelectedCatalogs(boolean product) |
| { |
| @SuppressWarnings("unchecked") |
| List<? extends Scope> result = (List<? extends Scope>)selection |
| .eGet(product ? SetupPackage.Literals.CATALOG_SELECTION__PRODUCT_CATALOGS : SetupPackage.Literals.CATALOG_SELECTION__PROJECT_CATALOGS); |
| return result; |
| } |
| |
| public void selectCatalog(boolean product, Scope scope, boolean on) |
| { |
| @SuppressWarnings("unchecked") |
| InternalEList<Scope> list = (InternalEList<Scope>)selection |
| .eGet(product ? SetupPackage.Literals.CATALOG_SELECTION__PRODUCT_CATALOGS : SetupPackage.Literals.CATALOG_SELECTION__PROJECT_CATALOGS); |
| |
| boolean changed = on ? list.add(scope) : list.remove(scope); |
| if (changed) |
| { |
| saveSelection(); |
| } |
| } |
| |
| public void indexLoaded(Index index) |
| { |
| if (index == null) |
| { |
| return; |
| } |
| |
| Index oldIndex = this.index; |
| this.index = index; |
| |
| // Load the local selection into the same resource set as the index, but only if the local selection exists. |
| ResourceSet resourceSet = index.eResource().getResourceSet(); |
| if (resourceSet.getURIConverter().exists(SetupContext.CATALOG_SELECTION_SETUP_URI, null)) |
| { |
| // Load local selection file |
| Resource selectionResource = BaseUtil.loadResourceSafely(resourceSet, SetupContext.CATALOG_SELECTION_SETUP_URI); |
| CatalogSelection selection = (CatalogSelection)EcoreUtil.getObjectByType(selectionResource.getContents(), SetupPackage.Literals.CATALOG_SELECTION); |
| |
| // Ensure that all proxies are resolved and then remove the loaded selection from its resource. |
| EcoreUtil.resolveAll(selectionResource); |
| selectionResource.getContents().clear(); |
| |
| // Add the managed selection to that same resource so it's proxies can resolve. |
| selectionResource.getContents().add(this.selection); |
| |
| // Update the maps so they're hashed by the resolved proxies. |
| updateProxyKeyedMap(this.selection.getDefaultProductVersions()); |
| updateProxyKeyedMap(this.selection.getDefaultStreams()); |
| |
| if (selection != null) |
| { |
| // Copy over all the features of the loaded selection to the managed selection. |
| this.selection.getDefaultProductVersions().putAll(selection.getDefaultProductVersions()); |
| this.selection.getDefaultStreams().putAll(selection.getDefaultStreams()); |
| EList<Stream> selectedStreams = this.selection.getSelectedStreams(); |
| selectedStreams.clear(); |
| selectedStreams.addAll(selection.getSelectedStreams()); |
| populateSelectedProductCatalogs(this.selection, index); |
| populateSelectedProjectCatalogs(this.selection, index); |
| } |
| |
| // Filter out any proxies that remain in the managed selection. |
| filterProxies(this.selection.getDefaultProductVersions()); |
| filterProxies(this.selection.getDefaultStreams()); |
| filterProxies(this.selection.getProductCatalogs()); |
| filterProxies(this.selection.getProjectCatalogs()); |
| |
| // If the managed selection's product catalog is empty, fill it with all available product catalogs from the index. |
| if (this.selection.getProductCatalogs().isEmpty()) |
| { |
| this.selection.getProductCatalogs().addAll(index.getProductCatalogs()); |
| } |
| |
| // If the managed selection's project catalog is empty, fill it with all available project catalogs from the index. |
| if (this.selection.getProjectCatalogs().isEmpty()) |
| { |
| this.selection.getProjectCatalogs().addAll(index.getProjectCatalogs()); |
| } |
| } |
| else |
| { |
| // Add the managed selection's resource to the index's resource set. |
| Resource selectionResource = selection.eResource(); |
| resourceSet.getResources().add(selectionResource); |
| |
| populateSelectedProductCatalogs(selection, index); |
| populateSelectedProjectCatalogs(selection, index); |
| |
| saveSelection(); |
| } |
| |
| getPropertyChangeSupport().firePropertyChange(PROPERTY_INDEX, oldIndex, this.index); |
| } |
| |
| private void populateSelectedProductCatalogs(CatalogSelection selection, Index index) |
| { |
| EList<ProductCatalog> productCatalogs = selection.getProductCatalogs(); |
| for (ProductCatalog productCatalog : index.getProductCatalogs()) |
| { |
| URI uri = EcoreUtil.getURI(productCatalog); |
| if (!"catalog".equals(uri.scheme()) && !SelfProductCatalogURIHandlerImpl.SELF_PRODUCT_CATALOG_NAME.equals(productCatalog.getName())) |
| { |
| productCatalogs.add(productCatalog); |
| } |
| } |
| } |
| |
| private void populateSelectedProjectCatalogs(CatalogSelection selection, Index index) |
| { |
| selection.getProjectCatalogs().addAll(index.getProjectCatalogs()); |
| } |
| |
| private <K extends EObject, V extends EObject> void updateProxyKeyedMap(EMap<K, V> eMap) |
| { |
| EMap<K, V> originalEMap = new BasicEMap<K, V>(eMap.map()); |
| eMap.clear(); |
| eMap.putAll(originalEMap); |
| } |
| |
| private <K extends EObject, V extends EObject> void filterProxies(EMap<K, V> eMap) |
| { |
| for (Iterator<Map.Entry<K, V>> it = eMap.iterator(); it.hasNext();) |
| { |
| Map.Entry<K, V> entry = it.next(); |
| K key = entry.getKey(); |
| V value = entry.getValue(); |
| |
| if (key == null || key.eIsProxy() || value == null || value.eIsProxy()) |
| { |
| it.remove(); |
| } |
| } |
| } |
| |
| private void filterProxies(EList<? extends EObject> list) |
| { |
| for (Iterator<? extends EObject> it = list.iterator(); it.hasNext();) |
| { |
| if (it.next().eIsProxy()) |
| { |
| it.remove(); |
| } |
| } |
| } |
| |
| public void saveSelection() |
| { |
| // Check if any containers are proxies. |
| // In this case save will fail. |
| // This case should only happen if we're trying to save while reloading the index and in that case we don't need to save. |
| for (EObject eObject : selection.eCrossReferences()) |
| { |
| InternalEObject internalEObject = (InternalEObject)eObject; |
| for (InternalEObject eContainer = internalEObject.eInternalContainer(); eContainer != null; eContainer = eContainer.eInternalContainer()) |
| { |
| if (eContainer.eIsProxy()) |
| { |
| return; |
| } |
| } |
| } |
| |
| try |
| { |
| selection.eResource().save(null); |
| } |
| catch (Exception ex) |
| { |
| SetupCorePlugin.INSTANCE.log(ex); |
| } |
| } |
| } |