blob: 887b4cfcb7c55326c221346e2610adc8505dd4e2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2017 Mia-Software.
* 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:
* Grégoire Dupé (Mia-Software) - Bug 477657 - The catalog manager should be able to manage workspace model
* Thomas Cicognani (Mia-Software) - Bug 483684 - NullPointerException on CatalogManager
* Thomas Cicognani (Mia-Software) - Bug 482887 - CatalogManager create files with to long name
* Grégoire Dupé (Mia-Software) - Bug 482887 - CatalogManager create files with too long name
* Grégoire Dupé (Mia-Software) - Bug 516254 - CatalogManager must not return workspace entries from closed project
*******************************************************************************/
package org.eclipse.modisco.facet.util.emf.core.internal.catalog.v2;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IProject;
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.Platform;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.modisco.facet.util.core.Logger;
import org.eclipse.modisco.facet.util.emf.catalog.metamodel.internal.v1_1.catalog.CatalogFactory;
import org.eclipse.modisco.facet.util.emf.catalog.metamodel.internal.v1_1.catalog.InstallAndWokspaceCatalog;
import org.eclipse.modisco.facet.util.emf.core.catalog.ICatalogManager;
import org.eclipse.modisco.facet.util.emf.core.catalog.ICatalogManagerConfiguration;
import org.eclipse.modisco.facet.util.emf.core.internal.Activator;
import org.osgi.framework.Bundle;
final class CatalogManager implements ICatalogManager, Adapter {
private static final String MODEL_DECL_EXT_PT = "org.eclipse.modisco.facet.util.emf.core.modeldeclaration"; //$NON-NLS-1$
private static final String FILE = "file"; //$NON-NLS-1$
private final Map<Resource, Bundle> resourceToBundle = new HashMap<Resource, Bundle>();
private final ICatalogManagerConfiguration catalogMgrconfig;
private InstallAndWokspaceCatalog catalog;
private final ResourceSet resourceSet;
private final String catalogId;
private Resource resource;
public CatalogManager(final ICatalogManagerConfiguration catalogMgrconfig,
final ResourceSet resourceSet, final String catalogId) {
this.resourceSet = resourceSet;
this.catalogMgrconfig = catalogMgrconfig;
this.catalogId = catalogId;
URI uri;
if (catalogId == null) {
final String uriStr = String.format("tmp://%s", //$NON-NLS-1$
this.getClass().getName());
uri = URI.createURI(uriStr);
} else {
final String uriStr = String.format("platform:/meta/%s/%s.xmi", //$NON-NLS-1$
Activator.getDefault().getBundle().getSymbolicName(),
catalogId);
uri = URI.createURI(uriStr);
}
if (catalogId == null) {
this.resource = this.resourceSet.createResource(uri);
} else {
try {
this.resource = this.resourceSet.getResource(uri, true);
} catch (org.eclipse.emf.common.util.WrappedException e) {
if (!(e.getCause() instanceof FileNotFoundException)) {
Logger.logError(e, Activator.getDefault());
}
this.resource = this.resourceSet.createResource(uri);
}
}
if ((!this.resource.getContents().isEmpty())
&& this.resource.getContents().get(0) instanceof InstallAndWokspaceCatalog) {
this.catalog = (InstallAndWokspaceCatalog) this.resource.getContents().get(0);
removeNotResolvedProxy(this.catalog.getWorkspaceEntries());
removeNotResolvedProxy(this.catalog.getInstalledEntries());
} else {
this.catalog = CatalogFactory.eINSTANCE.createInstallAndWokspaceCatalog();
EmfCommandUtils.executeAdd(this.resource, this.catalog);
}
initRegisteredEntries();
CatalogListenerFactory.adaptResource(this.catalog, this.resource);
}
private void removeNotResolvedProxy(final EList<EObject> eObjects) {
final List<EObject> toBeRemoved = new ArrayList<EObject>();
for (EObject entry : eObjects) {
if (entry.eIsProxy()) {
toBeRemoved.add(entry);
}
}
EmfCommandUtils.executeRemove(eObjects, toBeRemoved, this.resource);
}
private void initRegisteredEntries() {
final IExtensionRegistry registry = Platform.getExtensionRegistry();
final IExtensionPoint modelDeclExtPoint = registry
.getExtensionPoint(CatalogManager.MODEL_DECL_EXT_PT);
if (modelDeclExtPoint != null) {
for (IExtension ext : modelDeclExtPoint.getExtensions()) {
for (IConfigurationElement configElt : ext.getConfigurationElements()) {
final String filePath = configElt.getAttribute(CatalogManager.FILE);
if (filePath != null) {
final String pluginName = ext.getNamespaceIdentifier();
final Bundle bundle = Platform.getBundle(pluginName);
final URI uri = URI.createPlatformPluginURI(pluginName
+ "/" + filePath, false); //$NON-NLS-1$
try {
final Resource resource = this.resourceSet.getResource(uri, true);
this.resourceToBundle.put(resource, bundle);
for (EObject root : resource.getContents()) {
this.onInstalledModelFound(root);
}
} catch (Exception e) {
Logger.logError(e, Activator.getDefault());
}
}
}
}
}
}
private void onInstalledModelFound(final EObject root) {
if (this.catalogMgrconfig.canBeManaged(root) && this.catalogMgrconfig.isValid(root)) {
this.catalog.getInstalledEntries().add(root);
}
}
public <T> List<T> getEntries(final Class<T> expectedClass) {
final List<T> result = new ArrayList<T>();
final List<T> filteredEntries = getInstalledEntries(expectedClass);
result.addAll(filteredEntries);
final List<T> wsEntriesFiltered = getWsEntries(expectedClass);
result.addAll(wsEntriesFiltered);
return result;
}
public <T> List<T> getWsEntries(final Class<T> expectedClass) {
final List<T> result = new ArrayList<T>();
for (EObject eObject : this.catalog.getWorkspaceEntries()) {
if (expectedClass.isInstance(eObject)
&& EmfUtils.isDataAccessible(eObject)) {
@SuppressWarnings("unchecked")
/*
* @SuppressWarnings("unchecked"): gdupe> Checked by the call of
* 'isInstance' in the 'if' statement
*/
final T tObject = (T) eObject;
result.add(tObject);
}
}
return result;
}
public <T> List<T> getInstalledEntries(final Class<T> expectedClass) {
final List<T> result = new ArrayList<T>();
for (EObject eObject : this.catalog.getInstalledEntries()) {
if (expectedClass.isInstance(eObject)) {
@SuppressWarnings("unchecked")
/*
* @SuppressWarnings("unchecked"): gdupe> Checked by the call of
* 'isInstance' in the 'if' statement
*/
final T tObject = (T) eObject;
result.add(tObject);
}
}
return result;
}
public boolean addWsEntry(final EObject entry) {
boolean result = false;
if (this.catalogMgrconfig.canBeManaged(entry)
&& this.catalogMgrconfig.isValid(entry)) {
this.catalog.getWorkspaceEntries().add(entry);
result = true;
}
return result;
}
public void removeWsEntry(final EObject entry) {
this.catalog.getWorkspaceEntries().remove(entry);
}
public void removeAllWsEntries(final IProject project) {
final List<EObject> toBeRemoved = new ArrayList<EObject>();
final List<EObject> wsEntries = getWsEntries(EObject.class);
for (EObject registered : wsEntries) {
final Resource eResource = registered.eResource();
if (eResource == null || registered.eIsProxy()) {
/*
* Case where it is impossible to get the Resource (e.g. the
* linked object [registered] was deleted)
*/
toBeRemoved.add(registered);
} else {
final URI uri = eResource.getURI();
final String uriStr = uri.toString();
if (uriStr
.startsWith("platform:/resource/" + project.getName())) { //$NON-NLS-1$
toBeRemoved.add(registered);
}
}
}
this.catalog.getWorkspaceEntries().removeAll(toBeRemoved);
}
public String getCatalogId() {
return this.catalogId;
}
public void notifyChanged(final Notification notification) {
// Nothing to do
}
public Notifier getTarget() {
return this.resourceSet;
}
public void setTarget(final Notifier newTarget) {
// Nothing to do
}
public boolean isAdapterForType(final Object type) {
return type == ICatalogManager.class;
}
}