blob: 924aebd06064852ce1911233fddf32aa4a82801b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2009 Markus Herrmannsdoerfer.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Markus Herrmannsdoerfer - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.edapt.internal.declaration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.edapt.declaration.DeclarationFactory;
import org.eclipse.emf.edapt.declaration.Library;
import org.eclipse.emf.edapt.declaration.LibraryImplementation;
import org.eclipse.emf.edapt.declaration.Operation;
import org.eclipse.emf.edapt.declaration.OperationImplementation;
import org.eclipse.emf.edapt.internal.common.LoggingUtils;
import org.eclipse.emf.edapt.spi.migration.MigrationPlugin;
/**
* Registry for all operations (singleton). A set of operations is registered as
* a Eclipse extension.
*
* @author herrmama
* @author $Author$
* @version $Rev$
* @levd.rating YELLOW Hash: 5D6B6EEEA0BB217D3762F008E642AA6F
*/
public class OperationRegistry {
/** Singleton instance. */
private static OperationRegistry instance;
/** All registered operations identified by name. */
private Map<String, Operation> operations;
/** Operations that need to be performed before an operation. */
private Map<Operation, List<Operation>> beforeOperations;
/** Operations that need to be performed after an operation. */
private Map<Operation, List<Operation>> afterOperations;
/** List of registered operation containers. */
private Library rootLibrary;
/** Private default constructor. */
private OperationRegistry() {
registerLibrary();
initDependencies();
}
/** Initialize the dependencies between the operations. */
private void initDependencies() {
for (final Operation operation : getOperations()) {
if (operation.getBefore() != null) {
final Operation before = getOperation(operation.getBefore());
addBefore(operation, before);
}
if (operation.getAfter() != null) {
final Operation after = getOperation(operation.getAfter());
addAfter(operation, after);
}
}
}
/** Get the operations that need to be performed before an operation. */
public List<Operation> getBefore(Operation operation) {
final List<Operation> operations = beforeOperations.get(operation);
if (operations == null) {
return Collections.emptyList();
}
return operations;
}
/**
* Add a dependency saying that an operation needs to be performed before an
* operation.
*/
private void addBefore(Operation operation, Operation before) {
List<Operation> operations = beforeOperations.get(before);
if (operations == null) {
operations = new ArrayList<Operation>();
beforeOperations.put(before, operations);
}
operations.add(operation);
}
/** Get the operations that need to be performed after an operation. */
public List<Operation> getAfter(Operation operation) {
final List<Operation> operations = afterOperations.get(operation);
if (operations == null) {
return Collections.emptyList();
}
return operations;
}
/**
* Add a dependency saying that an operation needs to be performed after an
* operation.
*/
private void addAfter(Operation operation, Operation after) {
List<Operation> operations = afterOperations.get(after);
if (operations == null) {
operations = new ArrayList<Operation>();
afterOperations.put(after, operations);
}
operations.add(operation);
}
/** Register the operations defined by extensions. */
private void registerLibrary() {
operations = new HashMap<String, Operation>();
beforeOperations = new HashMap<Operation, List<Operation>>();
afterOperations = new HashMap<Operation, List<Operation>>();
rootLibrary = DeclarationFactory.eINSTANCE.createLibrary();
rootLibrary.setName("root"); //$NON-NLS-1$
rootLibrary.setLabel("Root library"); //$NON-NLS-1$
rootLibrary.setDescription("Root library of the operation registry"); //$NON-NLS-1$
if (Platform.isRunning()) {
final IExtensionRegistry extensionRegistry = Platform
.getExtensionRegistry();
final IConfigurationElement[] configurationElements = extensionRegistry
.getConfigurationElementsFor("org.eclipse.emf.edapt.operations"); //$NON-NLS-1$
for (int i = 0, n = configurationElements.length; i < n; i++) {
final IConfigurationElement configurationElement = configurationElements[i];
register(configurationElement);
}
} else {
registerLibrary(BaseLibrary.class);
}
}
/** Register a configuration element. */
@SuppressWarnings("unchecked")
private void register(IConfigurationElement configurationElement) {
try {
final Class c = configurationElement.createExecutableExtension("class") //$NON-NLS-1$
.getClass();
if ("operation".equals(configurationElement.getName())) { //$NON-NLS-1$
registerOperation(c);
} else if ("library".equals(configurationElement.getName())) { //$NON-NLS-1$
registerLibrary(c);
}
} catch (final CoreException e) {
// do not register operations that are declared erroneously.
}
}
/** Register the implementation of an operation. */
public void registerOperation(Class<? extends OperationImplementation> c) {
final Operation operation = new OperationExtractor().extractOperation(c);
if (operation != null) {
initOperation(operation);
rootLibrary.getOperations().add(operation);
}
}
/**
* Register one operation (if the name is not already occupied by another
* operation).
*/
private void initOperation(Operation operation) {
final String name = operation.getName();
if (operations.get(name) != null) {
LoggingUtils.logError(MigrationPlugin.getPlugin(),
"Duplicate operation name: " + name); //$NON-NLS-1$
}
operations.put(name, operation);
}
/** Register the implementation of a library. */
public void registerLibrary(Class<? extends LibraryImplementation> c) {
final Library library = new LibraryExtractor().extractLibrary(c);
if (library != null) {
initLibrary(library);
rootLibrary.getLibraries().add(library);
}
}
/** Register the operations provided by a library. */
private void initLibrary(Library library) {
for (final Operation operation : library.getOperations()) {
initOperation(operation);
}
for (final Library subLibrary : library.getLibraries()) {
initLibrary(subLibrary);
}
}
/** Getter for instance. */
public static OperationRegistry getInstance() {
if (instance == null) {
instance = new OperationRegistry();
}
return instance;
}
/** Get a list of all operations. */
public Collection<Operation> getOperations() {
return operations.values();
}
/** Get an operation by name. */
public Operation getOperation(String name) {
return operations.get(name);
}
/** Get the root libraries. */
public List<Library> getRootLibraries() {
return new ArrayList<Library>(rootLibrary.getLibraries());
}
/** Get the root operations. */
public List<Operation> getRootOperations() {
return new ArrayList<Operation>(rootLibrary.getOperations());
}
}