Bug 533300: Module loading shall not re-wrap dependencies
fixed module wrapping
added support to display any wrapped instance in modules dropin
removed listModules() from environment
Change-Id: I1334682ec5790167b41523fb5a984c0eec90ce02
diff --git a/plugins/org.eclipse.ease.ui/src/org/eclipse/ease/ui/modules/ui/ModulesDragListener.java b/plugins/org.eclipse.ease.ui/src/org/eclipse/ease/ui/modules/ui/ModulesDragListener.java
index 401f03f..beb3f49 100644
--- a/plugins/org.eclipse.ease.ui/src/org/eclipse/ease/ui/modules/ui/ModulesDragListener.java
+++ b/plugins/org.eclipse.ease.ui/src/org/eclipse/ease/ui/modules/ui/ModulesDragListener.java
@@ -75,7 +75,7 @@
}
}
- private IStructuredSelection getSelection() {
+ protected IStructuredSelection getSelection() {
if (fTreeViewer != null)
return fTreeViewer.getStructuredSelection();
diff --git a/plugins/org.eclipse.ease.ui/src/org/eclipse/ease/ui/view/ModuleStackDropin.java b/plugins/org.eclipse.ease.ui/src/org/eclipse/ease/ui/view/ModuleStackDropin.java
index cd30d39..73c0335 100644
--- a/plugins/org.eclipse.ease.ui/src/org/eclipse/ease/ui/view/ModuleStackDropin.java
+++ b/plugins/org.eclipse.ease.ui/src/org/eclipse/ease/ui/view/ModuleStackDropin.java
@@ -32,6 +32,7 @@
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.graphics.Image;
@@ -79,14 +80,14 @@
if (inputElement instanceof IScriptEngine) {
final IEnvironment environment = IEnvironment.getEnvironment((IScriptEngine) inputElement);
if (environment != null) {
- final List<ModuleDefinition> loadedModules = new ArrayList<>();
- for (final Object element : new ArrayList<>(environment.getModules())) {
- final ModuleDefinition module = getDefinition(element);
- if (module != null)
- loadedModules.add(module);
+ final List<Object> loadedModules = new ArrayList<>();
+
+ for (final Object instance : new ArrayList<>(environment.getModules())) {
+ final ModuleDefinition definition = getDefinition(instance);
+ loadedModules.add((definition != null) ? definition : instance);
}
- return loadedModules.toArray(new ModuleDefinition[loadedModules.size()]);
+ return loadedModules.toArray();
}
}
@@ -103,6 +104,9 @@
if (element instanceof ModuleDefinition)
return ((ModuleDefinition) element).getName();
+ if (element != null)
+ return element.getClass().getCanonicalName();
+
return super.getText(element);
}
@@ -116,6 +120,9 @@
return Activator.getImage(Activator.PLUGIN_ID, "/icons/eobj16/module.png", true);
}
+ if (element != null)
+ return Activator.getImage(Activator.PLUGIN_ID, "/icons/eobj16/debug_java_class.png", true);
+
return super.getImage(element);
}
});
@@ -123,7 +130,15 @@
fModulesTable.setInput(fEngine);
fModulesTable.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY, new Transfer[] { LocalSelectionTransfer.getTransfer(), TextTransfer.getInstance() },
- new ModulesDragListener(fModulesTable));
+ new ModulesDragListener(fModulesTable) {
+ @Override
+ public void dragStart(DragSourceEvent event) {
+ super.dragStart(event);
+
+ final Object firstElement = getSelection().getFirstElement();
+ event.doit = (firstElement instanceof ModuleDefinition);
+ }
+ });
return composite;
}
diff --git a/plugins/org.eclipse.ease/src/org/eclipse/ease/modules/EnvironmentModule.java b/plugins/org.eclipse.ease/src/org/eclipse/ease/modules/EnvironmentModule.java
index 25e29b8..a674c31 100644
--- a/plugins/org.eclipse.ease/src/org/eclipse/ease/modules/EnvironmentModule.java
+++ b/plugins/org.eclipse.ease/src/org/eclipse/ease/modules/EnvironmentModule.java
@@ -19,7 +19,6 @@
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -38,7 +37,7 @@
import org.eclipse.ease.Logger;
import org.eclipse.ease.Script;
import org.eclipse.ease.modules.ModuleDefinition.ModuleDependency;
-import org.eclipse.ease.service.IScriptService;
+import org.eclipse.ease.modules.ModuleTracker.ModuleState;
import org.eclipse.ease.service.ScriptService;
import org.eclipse.ease.tools.ResourceTools;
import org.eclipse.swt.widgets.Display;
@@ -65,11 +64,13 @@
instance.wrap(instance, false);
}
+ private final ModuleTracker fModuleTracker = new ModuleTracker();
+
/** Loaded module instances. Used as cache so that each module instance gets created only once. Maps moduleID -> instance. */
- private final Map<ModuleDefinition, Object> fLoadedModuleInstances = new HashMap<>();
+ // private final Map<ModuleDefinition, Object> fLoadedModuleInstances = new HashMap<>();
/** Stores ordering of wrapped elements. Index 0 contains the newest element */
- private final List<Object> fWrappedElements = new ArrayList<>();
+ // private final List<Object> fWrappedElements = new ArrayList<>();
/** Stores beautified names of loaded modules. */
// private final Map<String, Object> fModuleNames = new HashMap<>();
@@ -83,45 +84,9 @@
private final ListenerList<IModuleCallbackProvider> fModuleCallbacks = new ListenerList<>();
public EnvironmentModule() {
- fLoadedModuleInstances.put(ModuleHelper.resolveModuleName(MODULE_NAME), this);
- }
-
- private Object createModuleInstance(final ModuleDefinition definition) {
-
- if (!fLoadedModuleInstances.containsKey(definition)) {
- if (definition.isDeprecated())
- printError("Module \"" + definition.getName() + "\" is deprecated. Consider updating your code.");
-
- loadModuleDependencies(definition);
- final Object instance = definition.createModuleInstance();
-
- // check that module class got initialized correctly
- if (instance == null)
- throw new RuntimeException("Could not create module instance, see workspace log for more details");
-
- if (instance instanceof IScriptModule)
- ((IScriptModule) instance).initialize(getScriptEngine(), this);
-
- fLoadedModuleInstances.put(definition, instance);
- }
-
- return fLoadedModuleInstances.get(definition);
- }
-
- private void loadModuleDependencies(ModuleDefinition parentModuleDefinition) {
-
- final IScriptService scriptService = ScriptService.getService();
-
- for (final ModuleDependency dependency : parentModuleDefinition.getDependencies()) {
- final ModuleDefinition requiredModule = scriptService.getModuleDefinition(dependency.getId());
-
- if (requiredModule == null)
- throw new RuntimeException("Could not resolve module dependency \"" + dependency.getId() + "\"");
-
- Object instance = fLoadedModuleInstances.get(requiredModule);
- if (instance == null)
- instance = createModuleInstance(requiredModule);
- }
+ final ModuleDefinition moduleDefinition = ModuleHelper.resolveModuleName(MODULE_NAME);
+ final ModuleState state = fModuleTracker.addModule(moduleDefinition);
+ state.setInstance(this);
}
@Override
@@ -132,33 +97,72 @@
if (definition == null)
throw new RuntimeException("Could not find module \"" + moduleIdentifier + "\"");
- Object module = fLoadedModuleInstances.get(definition);
- if (module == null) {
- // not loaded yet
- module = createModuleInstance(definition);
- }
+ final ModuleState moduleState = fModuleTracker.getOrCreateModuleState(definition);
+
+ if (!moduleState.isLoaded())
+ createModuleInstance(moduleState);
if (!useCustomNamespace)
wrapModuleDependencies(definition);
// create function wrappers
- return wrap(module, useCustomNamespace);
+ return wrap(moduleState.getInstance(), useCustomNamespace);
+ }
+
+ private Object createModuleInstance(final ModuleState state) {
+
+ final ModuleDefinition definition = state.getModuleDefinition();
+ if (definition != null) {
+ if (definition.isDeprecated())
+ printError("Module \"" + definition.getName() + "\" is deprecated. Consider updating your code.");
+
+ createModuleDependencies(definition);
+ final Object instance = definition.createModuleInstance();
+ state.setInstance(instance);
+
+ // check that module class got initialized correctly
+ if (instance == null)
+ throw new RuntimeException("Could not create module instance, see workspace log for more details");
+
+ if (instance instanceof IScriptModule)
+ ((IScriptModule) instance).initialize(getScriptEngine(), this);
+ }
+
+ return state.getInstance();
+ }
+
+ private void createModuleDependencies(ModuleDefinition parentModuleDefinition) {
+
+ for (final ModuleDependency dependency : parentModuleDefinition.getDependencies()) {
+ final ModuleDefinition dependencyDefinition = dependency.getDefinition();
+
+ if (dependencyDefinition == null)
+ throw new RuntimeException("Could not resolve module dependency \"" + dependency.getId() + "\"");
+
+ createModuleDependencies(dependencyDefinition);
+
+ final ModuleState dependencyState = fModuleTracker.getOrCreateModuleState(dependencyDefinition);
+ if (!dependencyState.isLoaded())
+ createModuleInstance(dependencyState);
+ }
}
/**
- * Find and wrap instances of module dependencies. All found dependencies (and dependencies of dependencies) are wrapped into the root scope.
+ * Find and wrap instances of module dependencies. All found dependencies (and dependencies of dependencies) are wrapped into the root scope if they were
+ * not wrapped before.
*
- * @param definition
+ * @param parentModuleDefinition
* parent definition to find dependencies for
*/
- private void wrapModuleDependencies(ModuleDefinition definition) {
- for (final ModuleDependency dependency : definition.getDependencies()) {
+ private void wrapModuleDependencies(ModuleDefinition parentModuleDefinition) {
+ for (final ModuleDependency dependency : parentModuleDefinition.getDependencies()) {
final ModuleDefinition dependencyDefinition = dependency.getDefinition();
+
wrapModuleDependencies(dependencyDefinition);
- final Object instance = fLoadedModuleInstances.get(dependencyDefinition);
- if (instance != null)
- wrap(instance, false);
+ final ModuleState dependencyState = fModuleTracker.getOrCreateModuleState(dependencyDefinition);
+ if (!dependencyState.isWrapped())
+ wrap(dependencyState.getInstance(), false);
}
}
@@ -176,7 +180,8 @@
if (definition == null)
return null;
- return fLoadedModuleInstances.get(definition);
+ final ModuleState moduleState = fModuleTracker.getModuleState(definition);
+ return (moduleState != null) ? moduleState.getInstance() : null;
}
/**
@@ -189,9 +194,11 @@
@SuppressWarnings("unchecked")
@Override
public <T extends Object, U extends Class<T>> T getModule(final U clazz) {
- for (final Object module : fLoadedModuleInstances.values()) {
- if (clazz.isAssignableFrom(module.getClass()))
- return (T) module;
+ for (final ModuleState state : fModuleTracker.getAvailableModules()) {
+ if (state.getInstance() != null) {
+ if (clazz.isAssignableFrom(state.getInstance().getClass()))
+ return (T) state.getInstance();
+ }
}
return null;
@@ -199,47 +206,7 @@
@Override
public List<Object> getModules() {
- return fWrappedElements.stream().filter(instance -> fLoadedModuleInstances.values().contains(instance)).collect(Collectors.toList());
- }
-
- /**
- * List all available (visible) modules. Returns a list of visible modules. Loaded modules are indicated.
- *
- * @return string containing module information
- */
- @WrapToScript
- public final String listModules() {
-
- final IScriptService scriptService = PlatformUI.getWorkbench().getService(IScriptService.class);
- final List<ModuleDefinition> moduleDefinitions = new ArrayList<>(scriptService.getAvailableModules());
-
- moduleDefinitions.sort((m1, m2) -> {
- return m1.getPath().toString().compareTo(m2.getPath().toString());
- });
-
- final StringBuilder output = new StringBuilder();
-
- // add header
- output.append("available modules\n=================\n\n");
-
- // add modules
- for (final ModuleDefinition definition : moduleDefinitions) {
-
- if (definition.isVisible()) {
- output.append('\t');
-
- output.append(definition.getPath().toString());
- if (fLoadedModuleInstances.containsKey(definition))
- output.append(" [LOADED]");
-
- output.append('\n');
- }
- }
-
- // write to default output
- print(output, true);
-
- return output.toString();
+ return fModuleTracker.getAvailableModules().stream().filter(state -> state.isLoaded()).map(state -> state.getInstance()).collect(Collectors.toList());
}
/**
@@ -329,8 +296,19 @@
// create function wrappers
final Object result = createWrappers(toBeWrapped, identifier, reloaded, useCustomNamespace);
- fWrappedElements.remove(toBeWrapped);
- fWrappedElements.add(0, toBeWrapped);
+ boolean isTrackedModule = false;
+ for (final ModuleState state : fModuleTracker.getAvailableModules()) {
+ if (toBeWrapped.equals(state.getInstance())) {
+ state.setWrapped(true);
+ isTrackedModule = true;
+ break;
+ }
+ }
+
+ if (!isTrackedModule) {
+ final ModuleState state = fModuleTracker.addInstance(toBeWrapped);
+ state.setWrapped(true);
+ }
// notify listeners
fireModuleEvent(toBeWrapped, reloaded ? IModuleListener.RELOADED : IModuleListener.LOADED);
diff --git a/plugins/org.eclipse.ease/src/org/eclipse/ease/modules/ModuleTracker.java b/plugins/org.eclipse.ease/src/org/eclipse/ease/modules/ModuleTracker.java
new file mode 100644
index 0000000..1d4cbc4
--- /dev/null
+++ b/plugins/org.eclipse.ease/src/org/eclipse/ease/modules/ModuleTracker.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Christian Pontesegger 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:
+ * Christian Pontesegger - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ease.modules;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ModuleTracker {
+
+ public class ModuleState {
+
+ private Object fInstance;
+ private ModuleDefinition fModuleDefinition;
+
+ private boolean fWrapped = false;
+
+ public void setInstance(Object instance) {
+ fInstance = instance;
+ pushUp();
+ }
+
+ public Object getInstance() {
+ return fInstance;
+ }
+
+ public void setModuleDefinition(ModuleDefinition moduleDefinition) {
+ fModuleDefinition = moduleDefinition;
+ }
+
+ public ModuleDefinition getModuleDefinition() {
+ return fModuleDefinition;
+ }
+
+ public boolean isLoaded() {
+ return fInstance != null;
+ }
+
+ public boolean isWrapped() {
+ return fWrapped;
+ }
+
+ public void setWrapped(boolean wrapped) {
+ fWrapped = wrapped;
+ pushUp();
+ }
+
+ private void pushUp() {
+ fAvailableModules.remove(this);
+ fAvailableModules.add(0, this);
+ }
+ }
+
+ private final List<ModuleState> fAvailableModules = new ArrayList<>();
+
+ public ModuleState addModule(ModuleDefinition definition) {
+ final ModuleState state = new ModuleState();
+ state.setModuleDefinition(definition);
+
+ fAvailableModules.add(0, state);
+
+ return state;
+ }
+
+ public ModuleState addInstance(Object instance) {
+ final ModuleState state = new ModuleState();
+
+ fAvailableModules.add(0, state);
+ state.setInstance(instance);
+
+ return state;
+ }
+
+ public ModuleState getModuleState(ModuleDefinition definition) {
+ for (final ModuleState state : fAvailableModules) {
+ if (state.getModuleDefinition() != null) {
+ if (definition.getId().equals(state.getModuleDefinition().getId()))
+ return state;
+ }
+ }
+
+ return null;
+ }
+
+ public ModuleState getOrCreateModuleState(ModuleDefinition definition) {
+ final ModuleState state = getModuleState(definition);
+
+ return (state != null) ? state : addModule(definition);
+ }
+
+ public List<ModuleState> getAvailableModules() {
+ return fAvailableModules;
+ }
+}