diff --git a/Kieker.WebGUI/.settings/org.eclipse.jdt.ui.prefs b/Kieker.WebGUI/.settings/org.eclipse.jdt.ui.prefs
index e8289876c66750599f4fa14d9eb344c4825c6f54..87c76d67bf85f8da9bcb0e45752ae626df9934e1 100644
--- a/Kieker.WebGUI/.settings/org.eclipse.jdt.ui.prefs
+++ b/Kieker.WebGUI/.settings/org.eclipse.jdt.ui.prefs
@@ -89,7 +89,7 @@ sp_cleanup.never_use_blocks=false
 sp_cleanup.never_use_parentheses_in_expressions=false
 sp_cleanup.on_save_use_additional_actions=true
 sp_cleanup.organize_imports=true
-sp_cleanup.qualify_static_field_accesses_with_declaring_class=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
 sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
 sp_cleanup.qualify_static_member_accesses_with_declaring_class=true
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/domain/ComponentListContainer.java b/Kieker.WebGUI/src/main/java/kieker/webgui/domain/ComponentListContainer.java
index 79f4ba60f1b3b0a105fb6dd2bbf6eb3e94626f0b..2b0aaa86e52e085bd7a4312f589f957d9e7cb7b3 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/domain/ComponentListContainer.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/domain/ComponentListContainer.java
@@ -15,6 +15,7 @@
  ***************************************************************************/
 package kieker.webgui.domain;
 
+import java.util.Collections;
 import java.util.List;
 
 import kieker.webgui.domain.pluginDecorators.FilterDecorator;
@@ -30,6 +31,10 @@ import kieker.webgui.domain.pluginDecorators.RepositoryDecorator;
  */
 public class ComponentListContainer {
 
+	/** This constant represents an immutable and empty container. */
+	public static final ComponentListContainer EMPTY_CONTAINER = new ComponentListContainer(Collections.<ReaderDecorator>emptyList(),
+			Collections.<FilterDecorator>emptyList(), Collections.<RepositoryDecorator>emptyList());
+
 	private final List<ReaderDecorator> readers;
 	private final List<FilterDecorator> filters;
 	private final List<RepositoryDecorator> repositories;
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/FSProjectDAOImpl.java b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/FSProjectDAOImpl.java
index 4e448541b51e581100493c0e88508fc378473926..13c7f1507f0590cc2196b270d21c587c890809e6 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/FSProjectDAOImpl.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/FSProjectDAOImpl.java
@@ -887,6 +887,11 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener {
 
 	}
 
+	/**
+	 * A simple function to convert repository classes to model instances.
+	 * 
+	 * @author Nils Christian Ehmke
+	 */
 	private class ConvertRepositoryClass2ModelInstanceFunction implements Function<Class<AbstractRepository>, RepositoryDecorator> {
 
 		private final ClassAndMethodContainer classAndMethodContainer;
@@ -906,6 +911,11 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener {
 
 	}
 
+	/**
+	 * A simple function to convert reader classes to model instances.
+	 * 
+	 * @author Nils Christian Ehmke
+	 */
 	private class ConvertReaderClass2ModelInstanceFunction implements Function<Class<AbstractReaderPlugin>, ReaderDecorator> {
 
 		private final ClassAndMethodContainer classAndMethodContainer;
@@ -925,6 +935,11 @@ public class FSProjectDAOImpl implements IProjectDAO, ReleaseListener {
 
 	}
 
+	/**
+	 * A simple function to convert filter classes to model instances.
+	 * 
+	 * @author Nils Christian Ehmke
+	 */
 	private class ConvertFilterClass2ModelInstanceFunction implements Function<Class<AbstractFilterPlugin>, FilterDecorator> {
 
 		private final ClassAndMethodContainer classAndMethodContainer;
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/Class2ModelInstanceConverter.java b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/Class2ModelInstanceConverter.java
index 9cd4a18fe676ef8484f75f995099587772888d72..c2753c05e45c9aa987b2dd099e51c4b690262b65 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/Class2ModelInstanceConverter.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/persistence/impl/util/Class2ModelInstanceConverter.java
@@ -34,6 +34,7 @@ import kieker.analysis.model.analysisMetaModel.MIPlugin;
 import kieker.analysis.model.analysisMetaModel.MIProperty;
 import kieker.analysis.model.analysisMetaModel.MIReader;
 import kieker.analysis.model.analysisMetaModel.MIRepository;
+import kieker.analysis.model.analysisMetaModel.MIRepositoryConnector;
 import kieker.analysis.plugin.AbstractPlugin;
 import kieker.analysis.plugin.filter.AbstractFilterPlugin;
 import kieker.analysis.plugin.reader.AbstractReaderPlugin;
@@ -122,6 +123,7 @@ public class Class2ModelInstanceConverter {
 		final Collection<MIInputPort> inputPorts = new ArrayList<MIInputPort>();
 		final Collection<MIOutputPort> outputPorts = new ArrayList<MIOutputPort>();
 		final Collection<MIDisplay> displays = new ArrayList<MIDisplay>();
+		final Collection<MIRepositoryConnector> repositories = new ArrayList<MIRepositoryConnector>();
 		final Map<String, String> propertyDescriptions = new HashMap<String, String>();
 		final Map<String, String> displayDescriptions = new HashMap<String, String>();
 		String description = "";
@@ -131,14 +133,15 @@ public class Class2ModelInstanceConverter {
 		try {
 			description = this.fillDescription(clazz, classAndMethodContainer);
 			dependency = this.fillDependency(clazz, classAndMethodContainer);
-
 			this.fillProperties(clazz, classAndMethodContainer, properties, propertyDescriptions);
 			plugin.getProperties().addAll(properties);
 			if ((type == Type.Filter) || (type == Type.Reader)) {
 				this.fillOutputPorts((Class<AbstractPlugin>) clazz, classAndMethodContainer, outputPorts, (MIPlugin) plugin);
 				this.fillDisplays((Class<AbstractPlugin>) clazz, classAndMethodContainer, displays, displayDescriptions);
+				this.fillRepositories((Class<AbstractPlugin>) clazz, classAndMethodContainer, repositories);
 				((MIPlugin) plugin).getOutputPorts().addAll(outputPorts);
 				((MIPlugin) plugin).getDisplays().addAll(displays);
+				((MIPlugin) plugin).getRepositories().addAll(repositories);
 				if (type == Type.Filter) {
 					this.fillInputPorts((Class<AbstractFilterPlugin>) clazz, classAndMethodContainer, inputPorts, (MIFilter) plugin);
 					((MIFilter) plugin).getInputPorts().addAll(inputPorts);
@@ -255,6 +258,19 @@ public class Class2ModelInstanceConverter {
 		}
 	}
 
+	private void fillRepositories(final Class<? extends AbstractPlugin> clazz, final ClassAndMethodContainer classAndMethodContainer,
+			final Collection<MIRepositoryConnector> repositories) {
+		final Annotation annotation = this.getSuitableAnnotation(clazz, classAndMethodContainer);
+		final Annotation[] repositoryPortAnnotations = (Annotation[]) new Mirror().on(annotation).invoke().method("repositoryPorts").withoutArgs();
+
+		for (final Annotation repositoryPortAnnotation : repositoryPortAnnotations) {
+			final MIRepositoryConnector newConnector = Class2ModelInstanceConverter.FACTORY.createRepositoryConnector();
+			newConnector.setName((String) new Mirror().on(repositoryPortAnnotation).invoke().method("name").withoutArgs());
+
+			repositories.add(newConnector);
+		}
+	}
+
 	private String fillDependency(final Class<? extends AbstractAnalysisComponent> clazz, final ClassAndMethodContainer classAndMethodContainer) {
 		final Annotation annotation = this.getSuitableAnnotation(clazz, classAndMethodContainer);
 		return (String) new Mirror().on(annotation).invoke().method("dependencies").withoutArgs();
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/IProjectService.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/IProjectService.java
index ec59a5855acfaa1985fe3061d23e3ba354e41f62..638ee087aa4100da522d1233a63b7a2376fa0dc8 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/service/IProjectService.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/IProjectService.java
@@ -61,6 +61,9 @@ public interface IProjectService {
 	@PreAuthorize("hasAnyRole('User', 'Administrator')")
 	public void addProject(final String projectName, final String username) throws ProjectAlreadyExistingException, IOException;
 
+	/**
+	 * Updates the displays of all analyses.
+	 */
 	public void updateAllAnalyses();
 
 	/**
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/ACManager.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/ACManager.java
index afc376759a357088401959c53e1734872154d197..412b0062c23ae9e122d0dd64f329eb46b1c6f534 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/ACManager.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/ACManager.java
@@ -223,10 +223,16 @@ public class ACManager {
 		return retState;
 	}
 
+	/**
+	 * Updates the displays from the given project.
+	 * 
+	 * @param projectName
+	 *            The project to update.
+	 */
 	public void updateDisplays(final String projectName) {
-		if (this.analyses.containsKey(projectName)) {
-			this.analyses.get(projectName).updateDisplays();
-		}
+		// if (this.analyses.containsKey(projectName)) {
+		// this.analyses.get(projectName).updateDisplays();
+		// }
 	}
 
 }
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java
index b8d71dcc4b7dc10900109dbbae10831bc6adc0c6..a5c9778b32ddcc37f53ae1d853f868e4f8b27d37 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/service/impl/util/Analysis.java
@@ -18,8 +18,6 @@ package kieker.webgui.service.impl.util;
 
 import java.io.File;
 import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
 
 import kieker.analysis.AnalysisController;
 import kieker.common.logging.Log;
@@ -47,8 +45,8 @@ public class Analysis {
 	private final Object analysisController;
 	private final Object analysisControllerThread;
 
-	private final Map<String, Map<String, Object>> displayObjects = new HashMap<String, Map<String, Object>>();
-	private final Map<String, Map<String, Method>> displayMethods = new HashMap<String, Map<String, Method>>();
+	// private final Map<String, Map<String, Object>> displayObjects = new HashMap<String, Map<String, Object>>();
+	// private final Map<String, Map<String, Method>> displayMethods = new HashMap<String, Map<String, Method>>();
 
 	/**
 	 * Creates a new instance of this class using the given parameters.
@@ -152,7 +150,7 @@ public class Analysis {
 				AnalysisController.class.getName());
 	}
 
-	public void updateDisplays() {
+	// public void updateDisplays() {
 
-	}
+	// }
 }
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/application/GlobalPropertiesBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/application/GlobalPropertiesBean.java
index 99af78d6662504d279a1c7d6137082a5319bb919..ae7975738fd37a1b9fb683bd3b63b4178cdf7d58 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/application/GlobalPropertiesBean.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/application/GlobalPropertiesBean.java
@@ -18,12 +18,15 @@ package kieker.webgui.web.beans.application;
 
 import java.io.Serializable;
 import java.util.Locale;
+import java.util.Map;
 import java.util.ResourceBundle;
 
 import javax.faces.application.FacesMessage;
 import javax.faces.application.FacesMessage.Severity;
 import javax.faces.context.FacesContext;
 
+import kieker.common.record.AbstractMonitoringRecord;
+
 import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Component;
 
@@ -217,4 +220,28 @@ public class GlobalPropertiesBean implements Serializable {
 		FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, "", msg));
 	}
 
+	/**
+	 * This method reads parameters from the request parameter map of the current context. The parameters are converted to actual objects, based on the given types.
+	 * It is assumed (but not checked) that both arrays have the same size.
+	 * 
+	 * @param parameterNames
+	 *            The name of the parameters within the request parameter map.
+	 * @param types
+	 *            The actual types of the parameters. The method will try to convert the strings to those types.
+	 * 
+	 * @return An array containing the actual parameter objects.
+	 */
+	public static Object[] convertObjectsFromParameterMap(final String[] parameterNames, final Class<?>[] types) {
+		final int numberOfObjects = parameterNames.length;
+		final Map<String, String> parameterMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
+		final String[] parameters = new String[numberOfObjects];
+
+		for (int i = 0; i < numberOfObjects; i++) {
+			parameters[i] = parameterMap.get(parameterNames[i]);
+
+		}
+
+		// We can borrow a method from the Kieker framework to convert the strings
+		return AbstractMonitoringRecord.fromStringArrayToTypedArray(parameters, types);
+	}
 }
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorBean.java
index 9661a3e7781860ad43640d861a07ebaf22eb21d6..f6ee5a48a6ac6377af6514fedb8879829e12aeb3 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorBean.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorBean.java
@@ -18,7 +18,6 @@ package kieker.webgui.web.beans.view;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -67,9 +66,10 @@ import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Component;
 
 /**
- * The {@link CurrentAnalysisEditorBean} contains the necessary data behind an instance of the analysis editor. It provides various methods to manipulate the current
- * project, as the analysis editor is the most important part of the whole application. The connection to the graph within the editor is done via another bean (the
- * {@link CurrentAnalysisEditorGraphBean}).<br>
+ * This bean contains the necessary data behind an instance of the analysis editor. It provides various methods to manipulate the current project with respect to the
+ * analysis components. The connection to the graph within the editor is done with {@link CurrentAnalysisEditorGraphBean}. <br>
+ * </br>
+ * 
  * The class is a Spring managed bean with view scope to make sure that one user (even in one session) can open multiple projects at a time without causing any
  * problems.
  * 
@@ -79,16 +79,23 @@ import org.springframework.stereotype.Component;
 @Scope("view")
 public class CurrentAnalysisEditorBean {
 
+	private static final MIAnalysisMetaModelFactory MODEL_FACTORY = MAnalysisMetaModelFactory.eINSTANCE;
 	private static final Log LOG = LogFactory.getLog(CurrentAnalysisEditorBean.class);
-	private static final MIAnalysisMetaModelFactory FACTORY = MAnalysisMetaModelFactory.eINSTANCE;
+
+	private static final String[] PARAMETER_NAMES_SAVE_PROJECT = { "overwriteNewerProject", "layoutString" };
+	private static final Class<?>[] PARAMETER_TYPES_SAVE_PROJECT = { Boolean.class, String.class };
+
+	private static final String JS_CMD_SHOW_FORCE_SAVE_DIALOG = "forceSaveDlg.show()";
 
 	private MIAnalysisComponent globalConfigurationInstance;
-	private ComponentListContainer availableComponents;
 	private MIAnalysisComponent selectedComponent;
-	private boolean unsavedModifications;
 	private MIProject project;
+
+	private ComponentListContainer availableComponents;
+
+	private boolean unsavedModifications;
 	private String projectName;
-	private long timeStamp;
+	private long timeStampFromLastSaving;
 
 	@Autowired
 	private CurrentAnalysisEditorGraphBean currentAnalysisEditorGraphBean;
@@ -100,14 +107,12 @@ public class CurrentAnalysisEditorBean {
 	private ProjectsBean projectsBean;
 	@Autowired
 	private UserBean userBean;
-	private String currentLayout;
 
 	/**
 	 * Creates a new instance of this class. <b>Do not call this constructor manually. It will only be accessed by Spring.</b>
 	 */
 	public CurrentAnalysisEditorBean() {
-		this.availableComponents = new ComponentListContainer(Collections.<ReaderDecorator>emptyList(), Collections.<FilterDecorator>emptyList(),
-				Collections.<RepositoryDecorator>emptyList());
+		this.availableComponents = ComponentListContainer.EMPTY_CONTAINER;
 	}
 
 	/**
@@ -116,77 +121,111 @@ public class CurrentAnalysisEditorBean {
 	 */
 	public void initialize() {
 		try {
-			// Make sure that the initialization will only be done for the init request. During all other requests, the method call have to be ignored.
+			// Make sure that the initialization will only be done for the initial request. During all other requests, the method call has to be ignored.
 			if (!FacesContext.getCurrentInstance().isPostback()) {
-				// Load the project itself
-				this.project = this.projectsBean.openProject(this.projectName);
-				// Remember the current time! This is important for the later comparison of the time stamps.
-				this.resetTimeStamp();
-				// Add the libraries within the lib-folder to the current model
-				this.initializeModelLibraries();
-				// Load the available readers, filters and repositories
+				this.loadProject();
+				this.enrichProjectWithLibraries();
 				this.reloadAvailableComponents();
 
-				this.unsavedModifications = false;
+				this.clearModificationsFlag();
+				this.resetTimeStampFromLastSaving();
 			}
 		} catch (final ProjectLoadException ex) {
 			CurrentAnalysisEditorBean.LOG.error("An error occured while loading the project.", ex);
-			// FacesContext.getCurrentInstance().getApplication().getNavigationHandler().handleNavigation(FacesContext.getCurrentInstance(), null,
-			// "projectOverview");
 			GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_ERROR, this.globalPropertiesBean.getMsgProjectLoadingException());
 		} catch (final NullPointerException ex) {
-			// This exception can occur, when a property has not been initialized
+			// This exception can occur when a property has not been initialized
 			CurrentAnalysisEditorBean.LOG.error("An error occured while loading the project.", ex);
-			// FacesContext.getCurrentInstance().getApplication().getNavigationHandler().handleNavigation(FacesContext.getCurrentInstance(), null,
-			// "projectOverview");
 			GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_ERROR, this.globalPropertiesBean.getMsgProjectLoadingException());
 		}
 	}
 
 	/**
-	 * This method takes all libraries from the lib-folder and adds them to the in-memory-model.
-	 * 
-	 * @throws ProjectLoadException
-	 *             If something went wrong during the loading of the libraries.
+	 * This method initializes the graph by delivering the necessary JavaScript commands to the client. It prints all current existing plugins, repositories and
+	 * their connections.
 	 */
-	private void initializeModelLibraries() throws ProjectLoadException {
-		try {
-			final List<String> libs = this.projectService.listAllLibraries(this.projectName);
-			// Add them, but remove all existing dependencies so far to avoid double entries. This also makes sure that the model - after it has been opened -
-			// points just to valid dependencies (and to all of them).
-			this.project.getDependencies().clear();
-			for (final String lib : libs) {
-				final MIDependency dep = CurrentAnalysisEditorBean.FACTORY.createDependency();
-				dep.setFilePath(lib);
-				this.project.getDependencies().add(dep);
+	public void initializeGraph() {
+		// Make sure that the currentAnalysisEditorGraphBean knows "this" as well.
+		this.currentAnalysisEditorGraphBean.setCurrentAnalysisEditorBean(this);
+
+		// Initialize the graph
+		this.currentAnalysisEditorGraphBean.declareGraph();
+
+		// Initialize the component for the project configuration
+		this.initializeGlobalConfigurationInstance();
+		this.currentAnalysisEditorGraphBean.addGlobalConfigurationInstance(this.globalConfigurationInstance);
+
+		// Initialize the reader, filter and repositories
+		for (final MIPlugin plugin : this.project.getPlugins()) {
+			if (plugin instanceof MIReader) {
+				this.currentAnalysisEditorGraphBean.addReader((MIReader) plugin);
+			} else {
+				this.currentAnalysisEditorGraphBean.addFilter((MIFilter) plugin);
 			}
-		} catch (final ProjectNotExistingException ex) {
-			throw new ProjectLoadException("The project does not exist.", ex);
 		}
+
+		for (final MIRepository repository : this.project.getRepositories()) {
+			this.currentAnalysisEditorGraphBean.addRepository(repository);
+		}
+
+		// Now initialize the connections between filters...
+		for (final MIPlugin plugin : this.project.getPlugins()) {
+			for (final MIOutputPort oPort : plugin.getOutputPorts()) {
+				for (final MIInputPort iPort : oPort.getSubscribers()) {
+					this.currentAnalysisEditorGraphBean.addConnection(plugin, iPort.getParent(), oPort, iPort);
+				}
+			}
+		}
+
+		// ...and between filters and repositories
+		for (final MIPlugin plugin : this.project.getPlugins()) {
+			for (final MIRepositoryConnector rPort : plugin.getRepositories()) {
+				// It is possible that the connected repository is null, if it hasn't been set yet. Check this.
+				if (rPort.getRepository() != null) {
+					this.currentAnalysisEditorGraphBean.addConnection(plugin, rPort.getRepository(), rPort);
+				}
+			}
+		}
+
+		// Initialize the mouse click and the edge constraint listeners
+		this.currentAnalysisEditorGraphBean.initListeners();
+		this.currentAnalysisEditorGraphBean.initEdgeConstraints();
+
+		// Now we have to set the default grid size and color of the user
+		this.currentAnalysisEditorGraphBean.setGridColor(this.userBean.getGridColor());
+		this.currentAnalysisEditorGraphBean.setGridSize(this.userBean.getGridSize());
+
+		// Perform either an initial auto layout or use the saved layout - if it exists
+		final String layout = this.projectService.getAnalysisLayout(this.projectName);
+
+		if (layout != null) {
+			this.currentAnalysisEditorGraphBean.loadLayout(layout);
+		} else {
+			this.currentAnalysisEditorGraphBean.startAutoLayout();
+		}
+
+		// Make sure that guests cannot modify the graph
+		this.currentAnalysisEditorGraphBean.checkReadOnlyForGuests();
 	}
 
 	/**
-	 * This method is the handler for the file upload. It tries to upload the given file and informs the user via the growl-component.
+	 * This method is the handler for the file upload. It tries to upload the given file as a library and informs the user via the growl-component.
 	 * 
 	 * @param event
 	 *            The upload event.
 	 */
-	public void handleFileUpload(final FileUploadEvent event) {
-		// Get the file from the event
-		final UploadedFile file = event.getFile();
-
+	public void handleLibraryFileUpload(final FileUploadEvent event) {
 		try {
-			// Use the file system manager to upload the new file
-			final MIDependency lib;
-			this.projectService.uploadLibrary(file, this.projectName);
+			final UploadedFile uploadedFile = event.getFile();
+
+			// Delegate the task to upload the library
+			this.projectService.uploadLibrary(uploadedFile, this.projectName);
+
+			// Seems like it worked. We can add the library to our model and inform the user.
 			GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_INFO, this.globalPropertiesBean.getMsgLibraryUploaded());
-			// As it seem to have worked, we can add the library to our model.
-			lib = CurrentAnalysisEditorBean.FACTORY.createDependency();
-			lib.setFilePath(file.getFileName());
-			this.project.getDependencies().add(lib);
-			// Update our class loader and the available plugins & repositories
+			this.enrichProjectWithLibrary(uploadedFile.getFileName());
 
-			// We have to reinitialize the tool palette completely! This is necessary as some of the already existing classes could need the newly loaded classes.
+			// We have to reinitialize the available components! This is necessary as some of the already existing classes could need the newly loaded classes.
 			this.reloadAvailableComponents();
 
 			this.setModificationsFlag();
@@ -206,18 +245,16 @@ public class CurrentAnalysisEditorBean {
 	}
 
 	/**
-	 * Removes the library with the given name and reloads the classes and the classloader. Furthermore the tool palette will be reinitalized.
+	 * Removes the library with the given name and reloads the available components.
 	 * 
 	 * @param name
 	 *            The name of the library to be removed.
 	 */
 	public void deleteLibrary(final String name) {
 		try {
+			// Delegate the task
 			if (this.projectService.deleteLibrary(this.projectName, name)) {
-				// We have to reinitialize the tool palette completely! This is necessary as some of the already existing classes could need the newly loaded
-				// classes.
 				this.reloadAvailableComponents();
-
 				this.setModificationsFlag();
 			}
 		} catch (final IOException ex) {
@@ -227,46 +264,7 @@ public class CurrentAnalysisEditorBean {
 	}
 
 	/**
-	 * This method loads the list of available readers, filters and repositories, using the current libraries within the model.
-	 */
-	private void reloadAvailableComponents() {
-		this.availableComponents = this.projectService.getAvailableComponents(this.projectName);
-	}
-
-	public MIProject getProject() {
-		return this.project;
-	}
-
-	public void setProjectName(final String newName) {
-		// Remember the given parameters
-		this.projectName = newName;
-	}
-
-	public String getProjectName() {
-		return this.projectName;
-	}
-
-	public ComponentListContainer getAvailableComponents() {
-		return this.availableComponents;
-	}
-
-	/**
-	 * This method sets the time stamp to the current system time.
-	 */
-	public void resetTimeStamp() {
-		this.timeStamp = System.currentTimeMillis();
-	}
-
-	public long getTimeStamp() {
-		return this.timeStamp;
-	}
-
-	public MIAnalysisComponent getSelectedPlugin() {
-		return this.selectedComponent;
-	}
-
-	/**
-	 * This method delivers the available libraries of this project as a pair of strings. The first element is always the kieker-library.
+	 * This method delivers the available libraries of this project. The first element is always the kieker-library.
 	 * 
 	 * @return The available libraries.
 	 */
@@ -287,30 +285,30 @@ public class CurrentAnalysisEditorBean {
 
 	/**
 	 * This method tries to save the current project and informs the user about success or fail. There should be two parameters within the request parameter map
-	 * (layoutString and overwriteNewerProject) as this method is called via javascript.
+	 * (layoutString and overwriteNewerProject) as this method is called technically from JavaScript.
 	 */
 	public void saveProject() {
 		// Get the parameters
-		final Map<String, String> paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
-		this.currentLayout = paramMap.get("layoutString");
-		final boolean overwriteNewerProject = Boolean.parseBoolean(paramMap.get("overwriteNewerProject"));
+		final Object[] parameters = GlobalPropertiesBean.convertObjectsFromParameterMap(PARAMETER_NAMES_SAVE_PROJECT, PARAMETER_TYPES_SAVE_PROJECT);
+		final boolean overwriteNewerProject = (Boolean) parameters[0];
+		final String currentLayout = (String) parameters[1];
 
-		// Convert the global component property to project properties
+		// Add the project configuration to the project, as those are stored within the global configuration component.
 		this.project.getProperties().clear();
 		for (final MIProperty mProperty : this.globalConfigurationInstance.getProperties()) {
-			final MIProperty mCopy = CurrentAnalysisEditorBean.FACTORY.createProperty();
+			final MIProperty mCopy = MODEL_FACTORY.createProperty();
 			mCopy.setName(mProperty.getName());
 			mCopy.setValue(mProperty.getValue());
+
 			this.project.getProperties().add(mCopy);
 		}
 
 		try {
-			this.projectService.saveProject(this.projectName, this.project, this.timeStamp, overwriteNewerProject, this.userBean.getUsername(), this.currentLayout,
-					null);
+			this.projectService.saveProject(this.projectName, this.project, this.timeStampFromLastSaving, overwriteNewerProject, this.userBean.getUsername(),
+					currentLayout, null);
 			GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_INFO, this.globalPropertiesBean.getMsgProjectSaved());
-			// Update the time stamp!
-			this.resetTimeStamp();
 
+			this.resetTimeStampFromLastSaving();
 			this.clearModificationsFlag();
 		} catch (final IOException ex) {
 			CurrentAnalysisEditorBean.LOG.error("An error occured while saving the project.", ex);
@@ -319,7 +317,7 @@ public class CurrentAnalysisEditorBean {
 			CurrentAnalysisEditorBean.LOG.info("The project has been modified externally in the meanwhile.", ex);
 			GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_WARN, this.globalPropertiesBean.getMsgProjectModified());
 			// Give the user the possibility to force-save the project
-			RequestContext.getCurrentInstance().execute("forceSaveDlg.show()");
+			RequestContext.getCurrentInstance().execute(JS_CMD_SHOW_FORCE_SAVE_DIALOG);
 		} catch (final ProjectNotExistingException ex) {
 			CurrentAnalysisEditorBean.LOG.error("The project does not exist.", ex);
 			GlobalPropertiesBean.showMessage(FacesMessage.SEVERITY_ERROR, this.globalPropertiesBean.getMsgProjectNotExistingException());
@@ -327,14 +325,14 @@ public class CurrentAnalysisEditorBean {
 	}
 
 	/**
-	 * This method adds a new repository to the current model, using the given instance of {@code RepositoryContainer} for it.
+	 * This method adds a new repository to the current model, using the given container to create it.
 	 * 
 	 * @param container
 	 *            The container which delivers the copy of the repository.
 	 */
 	public void addRepository(final RepositoryDecorator container) {
 		// Create a new instance for the model
-		final MIRepository repository = container.newCopy(CurrentAnalysisEditorBean.FACTORY);
+		final MIRepository repository = container.newCopy(CurrentAnalysisEditorBean.MODEL_FACTORY);
 
 		// Add it to the project - and to the graph
 		this.project.getRepositories().add(repository);
@@ -343,9 +341,15 @@ public class CurrentAnalysisEditorBean {
 		this.setModificationsFlag();
 	}
 
+	/**
+	 * This method adds a new reader to the current model, using the given container to create it.
+	 * 
+	 * @param container
+	 *            The container which delivers the copy of the reader.
+	 */
 	public void addReader(final ReaderDecorator container) {
 		// Create a new instance for the model
-		final MIPlugin plugin = container.newCopy(CurrentAnalysisEditorBean.FACTORY);
+		final MIPlugin plugin = container.newCopy(CurrentAnalysisEditorBean.MODEL_FACTORY);
 
 		// Add it to the project - and to the graph
 		this.project.getPlugins().add(plugin);
@@ -355,14 +359,14 @@ public class CurrentAnalysisEditorBean {
 	}
 
 	/**
-	 * This method adds a new plugin to the current model, using the given instance of {@code PluginContainer} for it.
+	 * This method adds a new filter to the current model, using the given container to create it.
 	 * 
 	 * @param container
-	 *            The container which delivers the copy of the plugin.
+	 *            The container which delivers the copy of the filter.
 	 */
 	public void addFilter(final FilterDecorator container) {
 		// Create a new instance for the model
-		final MIPlugin plugin = container.newCopy(CurrentAnalysisEditorBean.FACTORY);
+		final MIPlugin plugin = container.newCopy(CurrentAnalysisEditorBean.MODEL_FACTORY);
 
 		// Add it to the project - and to the graph
 		this.project.getPlugins().add(plugin);
@@ -371,39 +375,12 @@ public class CurrentAnalysisEditorBean {
 		this.setModificationsFlag();
 	}
 
-	/**
-	 * This method sets the property {@link CurrentAnalysisEditorBean#unsavedModifications} to false and refreshes the necessary components within the analysis
-	 * editor to make this visible.
-	 */
-	private void clearModificationsFlag() {
-		this.unsavedModifications = false;
-		RequestContext.getCurrentInstance().update("menuForm");
-	}
-
-	/**
-	 * This method sets the property {@link CurrentAnalysisEditorBean#unsavedModifications} to true and refreshes the necessary components within the analysis editor
-	 * to make this visible.
-	 */
-	private void setModificationsFlag() {
-		this.unsavedModifications = true;
-		RequestContext.getCurrentInstance().update("menuForm");
-	}
-
-	/**
-	 * Getter for the property {@link CurrentAnalysisEditorBean#unsavedModifications}.
-	 * 
-	 * @return The current value of the property.
-	 */
-	public boolean isUnsavedModification() {
-		return this.unsavedModifications;
-	}
-
 	/**
 	 * This method delivers the properties of the currently selected plugin, but it adds also the name- and the class-properties as a string to the list. The first
-	 * element is always the classname, the second one is always the pluginname.
+	 * element is always the class name, the second one is always the plugin name. If the currently selected component is the global configuration instance though,
+	 * those properties will not be added.
 	 * 
-	 * @return A list with all properties of the plugin plus the name- and class-properties. If no plugin is selected, the list of the selected repository is
-	 *         delivered.
+	 * @return A list with all properties of the plugin plus the name- and class-properties.
 	 */
 	public List<Object> getAdvancedPluginProperties() {
 		final List<Object> result = new ArrayList<Object>();
@@ -420,25 +397,25 @@ public class CurrentAnalysisEditorBean {
 		return result;
 	}
 
-	public boolean isGlobalConfigComponentSelected() {
-		return this.selectedComponent == this.globalConfigurationInstance;
-	}
-
 	/**
-	 * Delivers a human readable description of the given property.
+	 * Delivers a human readable description of the given property.<br>
+	 * 
+	 * </br> The current implementation is not very fast, as it searches through all available components. If
+	 * necessary this method can be modified in order to run faster (for example by using hash maps).
 	 * 
 	 * @param component
 	 *            The parent of the property.
 	 * @param property
 	 *            The property name.
+	 * 
 	 * @return A human readable description and a substitution if there is no description.
 	 */
 	public String getDescription(final MIAnalysisComponent component, final String property) {
+		final String className = component.getClassname();
 		AbstractAnalysisComponentDecorator<? extends MIAnalysisComponent> container = null;
 
 		// Find the container which contains the component
 		if (component instanceof MIReader) {
-			final String className = ((MIReader) component).getClassname();
 			for (final ReaderDecorator reader : this.availableComponents.getReaders()) {
 				if (reader.getClassname().equals(className)) {
 					container = reader;
@@ -446,7 +423,6 @@ public class CurrentAnalysisEditorBean {
 				}
 			}
 		} else if (component instanceof MIFilter) {
-			final String className = ((MIFilter) component).getClassname();
 			for (final FilterDecorator filter : this.availableComponents.getFilters()) {
 				if (filter.getClassname().equals(className)) {
 					container = filter;
@@ -454,7 +430,6 @@ public class CurrentAnalysisEditorBean {
 				}
 			}
 		} else {
-			final String className = ((MIRepository) component).getClassname();
 			for (final RepositoryDecorator repository : this.availableComponents.getRepositories()) {
 				if (repository.getClassname().equals(className)) {
 					container = repository;
@@ -472,113 +447,6 @@ public class CurrentAnalysisEditorBean {
 		return "No description available.";
 	}
 
-	/**
-	 * This method should be called if the grid color has been modified.
-	 * 
-	 * @param event
-	 *            The change event.
-	 */
-	public void gridColorListener(final ValueChangeEvent event) {
-		this.currentAnalysisEditorGraphBean.setGridColor((String) event.getNewValue());
-	}
-
-	/**
-	 * This method should be called if the grid size has been modified.
-	 * 
-	 * @param event
-	 *            The change event.
-	 */
-	public void gridSizeListener(final ValueChangeEvent event) {
-		this.currentAnalysisEditorGraphBean.setGridSize((Integer) event.getNewValue());
-	}
-
-	/**
-	 * This method initializes the modified jit-graph by delivering the necessary javascript commands to the client. It prints all current existing plugins,
-	 * repositories and their connections. All further components will be added mostly by other methods.
-	 */
-	public void initializeGraph() {
-		this.initializeGlobalConfigurationInstance();
-
-		// Make sure that the currentAnalysisEditorGraphBean knows "this" as well.
-		this.currentAnalysisEditorGraphBean.setCurrentAnalysisEditorBean(this);
-
-		// Initialize the graph
-		this.currentAnalysisEditorGraphBean.declareGraph();
-
-		// Initialize the reader, filter and repositories
-		for (final MIPlugin plugin : this.project.getPlugins()) {
-			if (plugin instanceof MIReader) {
-				this.currentAnalysisEditorGraphBean.addReader((MIReader) plugin);
-			} else {
-				this.currentAnalysisEditorGraphBean.addFilter((MIFilter) plugin);
-			}
-		}
-
-		for (final MIRepository repository : this.project.getRepositories()) {
-			this.currentAnalysisEditorGraphBean.addRepository(repository);
-		}
-
-		// Now initialize the connections between filters...
-		for (final MIPlugin plugin : this.project.getPlugins()) {
-			for (final MIOutputPort oPort : plugin.getOutputPorts()) {
-				for (final MIInputPort iPort : oPort.getSubscribers()) {
-					this.currentAnalysisEditorGraphBean.addConnection(plugin, iPort.getParent(), oPort, iPort);
-				}
-			}
-		}
-
-		// ...and between filters and repositories
-		for (final MIPlugin plugin : this.project.getPlugins()) {
-			for (final MIRepositoryConnector rPort : plugin.getRepositories()) {
-				// It is possible that the connected repository is null, if it hasn't been set yet. Check this.
-				if (rPort.getRepository() != null) {
-					this.currentAnalysisEditorGraphBean.addConnection(plugin, rPort.getRepository(), rPort);
-				}
-			}
-		}
-
-		this.currentAnalysisEditorGraphBean.initListeners();
-		this.currentAnalysisEditorGraphBean.addEdgeConstraints();
-
-		// Now we have to set the default grid size and color of the user
-		this.currentAnalysisEditorGraphBean.setGridColor(this.userBean.getGridColor());
-		this.currentAnalysisEditorGraphBean.setGridSize(this.userBean.getGridSize());
-
-		// Perform either an initial auto layout or use the saved layout - if it exists
-		final String layout = this.projectService.getAnalysisLayout(this.projectName);
-
-		if (layout != null) {
-			this.currentAnalysisEditorGraphBean.loadLayout(layout);
-		} else {
-			this.currentAnalysisEditorGraphBean.startAutoLayout();
-		}
-
-		this.currentAnalysisEditorGraphBean.checkReadOnlyForGuests();
-	}
-
-	private void initializeGlobalConfigurationInstance() {
-		this.globalConfigurationInstance = CurrentAnalysisEditorBean.FACTORY.createFilter();
-
-		final kieker.analysis.annotation.AnalysisController annotation = AnalysisController.class.getAnnotation(kieker.analysis.annotation.AnalysisController.class);
-		final Property[] properties = annotation.configuration();
-		final Map<String, String> propertyMap = new HashMap<String, String>();
-
-		for (final Property property : properties) {
-			propertyMap.put(property.name(), property.defaultValue());
-		}
-
-		for (final MIProperty mProperty : this.project.getProperties()) {
-			propertyMap.put(mProperty.getName(), mProperty.getValue());
-		}
-
-		for (final Map.Entry<String, String> property : propertyMap.entrySet()) {
-			final MIProperty mProperty = CurrentAnalysisEditorBean.FACTORY.createProperty();
-			mProperty.setName(property.getKey());
-			mProperty.setValue(property.getValue());
-			this.globalConfigurationInstance.getProperties().add(mProperty);
-		}
-	}
-
 	/**
 	 * This method should be called if a node (plugin, repository) has been selected.
 	 * 
@@ -690,8 +558,129 @@ public class CurrentAnalysisEditorBean {
 		this.setModificationsFlag();
 	}
 
-	public MIAnalysisComponent getGlobalConfigurationComponent() {
-		return this.globalConfigurationInstance;
+	/**
+	 * This method should be called if the grid color has been modified.
+	 * 
+	 * @param event
+	 *            The change event.
+	 */
+	public void gridColorListener(final ValueChangeEvent event) {
+		this.currentAnalysisEditorGraphBean.setGridColor((String) event.getNewValue());
+	}
+
+	/**
+	 * This method should be called if the grid size has been modified.
+	 * 
+	 * @param event
+	 *            The change event.
+	 */
+	public void gridSizeListener(final ValueChangeEvent event) {
+		this.currentAnalysisEditorGraphBean.setGridSize((Integer) event.getNewValue());
+	}
+
+	public boolean isUnsavedModification() {
+		return this.unsavedModifications;
+	}
+
+	public boolean isGlobalConfigComponentSelected() {
+		return this.selectedComponent == this.globalConfigurationInstance;
+	}
+
+	public MIAnalysisComponent getSelectedPlugin() {
+		return this.selectedComponent;
+	}
+
+	public MIProject getProject() {
+		return this.project;
+	}
+
+	public void setProjectName(final String projectName) {
+		this.projectName = projectName;
+	}
+
+	public String getProjectName() {
+		return this.projectName;
+	}
+
+	public ComponentListContainer getAvailableComponents() {
+		return this.availableComponents;
+	}
+
+	private void reloadAvailableComponents() {
+		this.availableComponents = this.projectService.getAvailableComponents(this.projectName);
+	}
+
+	private void loadProject() {
+		this.project = this.projectsBean.openProject(this.projectName);
+	}
+
+	private void enrichProjectWithLibraries() throws ProjectLoadException {
+		try {
+			// Run through all libraries within the lib folder of the project and add them to the project. Removing all existing dependencies beforehand makes sure
+			// that we avoid double entries. And it avoids the problem with invalid dependencies
+			this.project.getDependencies().clear();
+			final List<String> libraries = this.projectService.listAllLibraries(this.projectName);
+
+			for (final String library : libraries) {
+				this.enrichProjectWithLibrary(library);
+			}
+
+		} catch (final ProjectNotExistingException ex) {
+			throw new ProjectLoadException("The project does not exist.", ex);
+		}
+	}
+
+	private void enrichProjectWithLibrary(final String fileName) {
+		final MIDependency mDependency = MODEL_FACTORY.createDependency();
+		mDependency.setFilePath(fileName);
+
+		this.project.getDependencies().add(mDependency);
+	}
+
+	private void resetTimeStampFromLastSaving() {
+		this.timeStampFromLastSaving = System.currentTimeMillis();
+	}
+
+	/**
+	 * This method sets the property {@link CurrentAnalysisEditorBean#unsavedModifications} to false and refreshes the necessary components within the analysis
+	 * editor to make this visible.
+	 */
+	private void clearModificationsFlag() {
+		this.unsavedModifications = false;
+		RequestContext.getCurrentInstance().update("menuForm");
+	}
+
+	/**
+	 * This method sets the property {@link CurrentAnalysisEditorBean#unsavedModifications} to true and refreshes the necessary components within the analysis editor
+	 * to make this visible.
+	 */
+	private void setModificationsFlag() {
+		this.unsavedModifications = true;
+		RequestContext.getCurrentInstance().update("menuForm");
+	}
+
+	private void initializeGlobalConfigurationInstance() {
+		this.globalConfigurationInstance = MODEL_FACTORY.createFilter();
+
+		final kieker.analysis.annotation.AnalysisController annotation = AnalysisController.class.getAnnotation(kieker.analysis.annotation.AnalysisController.class);
+		final Property[] properties = annotation.configuration();
+		final Map<String, String> propertyMap = new HashMap<String, String>();
+
+		for (final Property property : properties) {
+			propertyMap.put(property.name(), property.defaultValue());
+		}
+
+		for (final MIProperty mProperty : this.project.getProperties()) {
+			propertyMap.put(mProperty.getName(), mProperty.getValue());
+		}
+
+		for (final Map.Entry<String, String> property : propertyMap.entrySet()) {
+			final MIProperty mProperty = MODEL_FACTORY.createProperty();
+			mProperty.setName(property.getKey());
+			mProperty.setValue(property.getValue());
+
+			this.globalConfigurationInstance.getProperties().add(mProperty);
+		}
 	}
 
 }
diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java
index fce9de8ca5d572b51f6e3f1b7e81d7ebbdf105d7..b1d76118bdb4aae0094c3db8b4f50eaad3201f01 100644
--- a/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java
+++ b/Kieker.WebGUI/src/main/java/kieker/webgui/web/beans/view/CurrentAnalysisEditorGraphBean.java
@@ -16,10 +16,6 @@
 
 package kieker.webgui.web.beans.view;
 
-import java.util.Map;
-
-import javax.faces.context.FacesContext;
-
 import kieker.analysis.model.analysisMetaModel.MIAnalysisComponent;
 import kieker.analysis.model.analysisMetaModel.MIFilter;
 import kieker.analysis.model.analysisMetaModel.MIInputPort;
@@ -46,8 +42,9 @@ import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Component;
 
 /**
- * The {@link CurrentAnalysisEditorGraphBean} contains the necessary data behind an graph of the analysis editor. It provides various methods to manipulate the
- * current graph.<br>
+ * This bean contains the necessary data behind an graph of the analysis editor. It provides various methods to manipulate the current graph.<br>
+ * </br>
+ * 
  * The class is a Spring managed bean with view scope to make sure that one user (even in one session) can open multiple projects at a time without causing any
  * problems.
  * 
@@ -59,17 +56,20 @@ public class CurrentAnalysisEditorGraphBean {
 
 	private static final Log LOG = LogFactory.getLog(CurrentAnalysisEditorGraphBean.class);
 
-	private static final String PARAM_NAME_ID = "ID";
-	private static final String PARAM_NAME_NODES = "nodes";
-	private static final String PARAM_NAME_EDGES = "edges";
-	private static final String PARAM_NAME_TARGET_PORT_ID = "targetPortID";
-	private static final String PARAM_NAME_SOURCE_PORT_ID = "sourcePortID";
+	private static final String[] PARAMETER_NAMES_AUTO_LAYOUT = { "nodes", "edges" };
+	private static final Class<?>[] PARAMETER_TYPES_AUTO_LAYOUT = { String.class, String.class };
+
+	private static final String[] PARAMETER_NAMES_ADD_AND_REMOVE_EDGES = { "sourcePortID", "targetPortID" };
+	private static final Class<?>[] PARAMETER_TYPES_ADD_AND_REMOVE_EDGES = { String.class, String.class };
+
+	private static final String[] PARAMETER_NAMES_CLICK_AND_REMOVE_NODES = { "ID" };
+	private static final Class<?>[] PARAMETER_TYPES_CLICK_AND_REMOVE_NODEST = { String.class };
 
 	/*
 	 * The following are a lot of code fragments which are used for the interaction with the flow editor. For details look at the API description of the flow editor
 	 * itself.
 	 */
-	private static final String JS_CMD_CREATE_GRAPH_VAR = "var graph = GraphFlow()";
+	private static final String JS_CMD_CREATE_GRAPH_VARIABLE = "var graph = GraphFlow()";
 	private static final String JS_CMD_ADD_EDGE_CONSTRAINTS = "graph.addEdgeConstraints()";
 
 	private static final String JS_CMD_SET_GLOBAL_ICON = "graph.setNodeIcon('Global', '../img/graphIcons/ProjectConfiguration.png', true)";
@@ -78,19 +78,28 @@ public class CurrentAnalysisEditorGraphBean {
 	private static final String JS_CMD_SET_REPOSITORY_ICON = "graph.setNodeIcon('Repository', '../img/graphIcons/RepositoryIcon.png', true)";
 
 	private static final String JS_CMD_ADD_CLICK_NODE_LISTENER = "graph.addListener('onClick', nodeClickListener)";
+	private static final String JS_CMD_ADD_ENTER_NODE_LISTENER = "graph.addListener('onMouseEnter', nodeEnterListener)";
 	private static final String JS_CMD_ADD_REMOVE_NODE_LISTENER = "graph.addListener('onRemoveNode', nodeRemoveListener)";
 	private static final String JS_CMD_ADD_CREATE_EDGE_LISTENER = "graph.addListener('onCreateEdge', edgeCreateListener)";
 	private static final String JS_CMD_ADD_REMOVE_EDGE_LISTENER = "graph.addListener('onRemoveEdge', edgeRemoveListener)";
 	private static final String JS_CMD_ADD_AUTO_LAYOUT_LISTENER = "graph.addListener('autoLayout', autoLayoutListener)";
-	private static final String JS_CMD_NODE = "{'id':'%s', 'name':'%s', 'nodeClass':'%s', 'tooltip':'%s'}";
-	private static final String JS_CMD_PORT = "{'name':'%s','id':'%s', 'tooltip':'%s'}";
+	private static final String JS_TEMPLATE_NODE = "{'id':'%s', 'name':'%s', 'nodeClass':'%s', 'tooltip':'%s'}";
+	private static final String JS_TEMPLATE_PORT = "{'name':'%s','id':'%s', 'tooltip':'%s'}";
+
+	private static final String JS_CMD_CREATE_GRAPH_CENTER_VARIABLE = "var center = graph.getScreenCenter()";
+
+	private static final Object REPOSITORY_INPUT_PORT = "R";
+	private static final String JS_PORT_TYPE_INPUT = "inputPort";
 
-	private static final String JS_CMD_PORT_TYPE_INPUT = "inputPort";
 	private static final String JS_CMD_ADD_EDGE = "graph.addEdge('%s', '%s', '%s', false, false)";
-	private static final String JS_CMD_ADD_FILTER = "var center = graph.getScreenCenter(); graph.addNode(center.x, center.y, %s,[%s],[%s],[%s],'Filter', false)";
-	private static final String JS_CMD_ADD_READER = "var center = graph.getScreenCenter(); graph.addNode(center.x, center.y, %s,[%s],null,[%s], 'Reader', false)";
-	private static final String JS_CMD_ADD_REPOSITORY = "var center = graph.getScreenCenter(); graph.addNode(center.x, center.y, %s, null, [%s], null, 'Repository',false)";
-	private static final String JS_CMD_ADD_GLOBAL_COMPONENT = "var center = graph.getScreenCenter(); graph.addNode(center.x, center.y, {'id':'%s', 'name':'%s', 'nodeClass':'', 'tooltip':'%s'}, null, null, null, 'Global', false); graph.setNodeData('%s.close', {'$visible' : false});";
+
+	private static final String JS_CMD_ADD_FILTER = JS_CMD_CREATE_GRAPH_CENTER_VARIABLE + "; graph.addNode(center.x,center.y,%s,[%s],[%s],[%s],'Filter',false)";
+	private static final String JS_CMD_ADD_READER = JS_CMD_CREATE_GRAPH_CENTER_VARIABLE + "; graph.addNode(center.x,center.y,%s,[%s],null,[%s],'Reader',false)";
+	private static final String JS_CMD_ADD_REPOSITORY = JS_CMD_CREATE_GRAPH_CENTER_VARIABLE
+			+ "; graph.addNode(center.x,center.y, %s,null, [%s],null,'Repository',false)";
+	private static final String JS_CMD_ADD_GLOBAL_COMPONENT = JS_CMD_CREATE_GRAPH_CENTER_VARIABLE
+			+ "; graph.addNode(center.x,center.y,{'id':'%s','name':'%s','nodeClass':'','tooltip':'%s'}, null, null, null, 'Global', false)"
+			+ "; graph.setNodeData('%s.close', {'$visible' : false});";
 
 	private static final String JS_CMD_ENABLE_GRID = "graph.setGridVisible(true, false)";
 	private static final String JS_CMD_DISABLE_GRID = "graph.setGridVisible(false, false)";
@@ -105,10 +114,8 @@ public class CurrentAnalysisEditorGraphBean {
 	private static final String JS_CMD_LOAD_FROM_LAYOUT = "graph.loadPositions('%s')";
 	private static final String JS_CMD_RENAME_NODE = "graph.setNodeData('%s', {'name' : '%s'})";
 
-	private static final Object REPOSITORY_INPUT_PORT = "R";
-
 	private final Registry<MIRepositoryConnector> repositoryPortMap = new Registry<MIRepositoryConnector>();
-	private final Registry<MIPort> portMap = new Registry<MIPort>();
+	private final Registry<MIPort> filterPortMap = new Registry<MIPort>();
 	private final Registry<MIAnalysisComponent> componentMap = new Registry<MIAnalysisComponent>();
 
 	private CurrentAnalysisEditorBean currentAnalysisEditorBean;
@@ -133,69 +140,46 @@ public class CurrentAnalysisEditorGraphBean {
 	 * Declares the the graph variable.
 	 */
 	public void declareGraph() {
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_CREATE_GRAPH_VAR);
+		RequestContext.getCurrentInstance().execute(JS_CMD_CREATE_GRAPH_VARIABLE);
 
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_SET_FILTER_ICON);
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_SET_REPOSITORY_ICON);
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_SET_READER_ICON);
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_SET_GLOBAL_ICON);
-
-		// Create an MIAnalysisComponent instance, which represents the global configuration of the project
-		final MIAnalysisComponent globalComponent = this.currentAnalysisEditorBean.getGlobalConfigurationComponent();
-		final int id = this.componentMap.get(globalComponent);
-		RequestContext.getCurrentInstance()
-				.execute(
-						String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_GLOBAL_COMPONENT, "id" + id,
-								this.globalPropertiesBean.getGlobalConfigurationComponentName(), this.globalPropertiesBean.getGlobalConfigurationComponentName(),
-								"id" + id));
+		RequestContext.getCurrentInstance().execute(JS_CMD_SET_FILTER_ICON);
+		RequestContext.getCurrentInstance().execute(JS_CMD_SET_REPOSITORY_ICON);
+		RequestContext.getCurrentInstance().execute(JS_CMD_SET_READER_ICON);
+		RequestContext.getCurrentInstance().execute(JS_CMD_SET_GLOBAL_ICON);
 	}
 
 	/**
 	 * Initializes the listeners for the graph.
 	 */
 	public void initListeners() {
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_CLICK_NODE_LISTENER);
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_AUTO_LAYOUT_LISTENER);
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_REMOVE_NODE_LISTENER);
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_CREATE_EDGE_LISTENER);
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_REMOVE_EDGE_LISTENER);
+		RequestContext.getCurrentInstance().execute(JS_CMD_ADD_CLICK_NODE_LISTENER);
+		RequestContext.getCurrentInstance().execute(JS_CMD_ADD_ENTER_NODE_LISTENER);
 
-		RequestContext.getCurrentInstance().execute("graph.addListener('onMouseEnter', function() {graph.setMouseCursor('pointer')})");
-	}
+		RequestContext.getCurrentInstance().execute(JS_CMD_ADD_AUTO_LAYOUT_LISTENER);
 
-	/**
-	 * This method initializes the auto layout of the graph, resulting in a javascript event, delivering the necessary information about the graph.
-	 */
-	public void startAutoLayout() {
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_START_AUTO_LAYOUT);
+		RequestContext.getCurrentInstance().execute(JS_CMD_ADD_REMOVE_NODE_LISTENER);
+		RequestContext.getCurrentInstance().execute(JS_CMD_ADD_CREATE_EDGE_LISTENER);
+		RequestContext.getCurrentInstance().execute(JS_CMD_ADD_REMOVE_EDGE_LISTENER);
 	}
 
 	/**
-	 * This method uses the given parameters (via request parameter map) to calculate a new layout for the graph and use this layout.
+	 * Adds the edge constraints to the graph.
 	 */
-	public void autoLayout() {
-		try {
-			// Get the parameters
-			final Map<String, String> paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
-
-			final String nodes = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_NODES);
-			final String edges = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_EDGES);
-
-			// Calculate the layout
-			final String newLayout = this.layouter.layoutGraph(nodes, edges);
-
-			// Now use it
-			RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_LOAD_FROM_LAYOUT, newLayout));
-		} catch (final GraphLayoutException ex) {
-			CurrentAnalysisEditorGraphBean.LOG.warn("Autolayout failed.", ex);
-		}
+	public void initEdgeConstraints() {
+		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_EDGE_CONSTRAINTS);
 	}
 
 	/**
-	 * Adds the edge constraints to the graph.
+	 * Adds a non removable component to the graph, which can be used to edit project configurations.
+	 * 
+	 * @param globalConfigurationInstance
+	 *            The global configuration instance.
 	 */
-	public void addEdgeConstraints() {
-		RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_EDGE_CONSTRAINTS);
+	public void addGlobalConfigurationInstance(final MIAnalysisComponent globalConfigurationInstance) {
+		final String name = this.globalPropertiesBean.getGlobalConfigurationComponentName();
+		final int id = this.componentMap.get(globalConfigurationInstance);
+
+		RequestContext.getCurrentInstance().execute(String.format(JS_CMD_ADD_GLOBAL_COMPONENT, "id" + id, name, name, "id" + id));
 	}
 
 	/**
@@ -205,7 +189,7 @@ public class CurrentAnalysisEditorGraphBean {
 	 *            The filter which should be added to the graph.
 	 */
 	public void addFilter(final MIFilter filter) {
-		RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_FILTER, this.assembleGraphString(filter),
+		RequestContext.getCurrentInstance().execute(String.format(JS_CMD_ADD_FILTER, this.assembleGraphString(filter),
 				this.assembleGraphRepositoryPortString(filter.getRepositories()), this.assembleGraphInputPortString(filter),
 				this.assembleGraphOutputPortString(filter)));
 	}
@@ -217,7 +201,7 @@ public class CurrentAnalysisEditorGraphBean {
 	 *            The reader which should be added to the graph.
 	 */
 	public void addReader(final MIReader reader) {
-		RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_READER, this.assembleGraphString(reader),
+		RequestContext.getCurrentInstance().execute(String.format(JS_CMD_ADD_READER, this.assembleGraphString(reader),
 				this.assembleGraphRepositoryPortString(reader.getRepositories()), this.assembleGraphOutputPortString(reader)));
 	}
 
@@ -228,10 +212,33 @@ public class CurrentAnalysisEditorGraphBean {
 	 *            The repository which should be added to the graph.
 	 */
 	public void addRepository(final MIRepository repository) {
-		final String repoPort = String.format(CurrentAnalysisEditorGraphBean.JS_CMD_PORT, CurrentAnalysisEditorGraphBean.JS_CMD_PORT_TYPE_INPUT,
-				CurrentAnalysisEditorGraphBean.REPOSITORY_INPUT_PORT, "N/A");
-		RequestContext.getCurrentInstance().execute(
-				String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_REPOSITORY, this.assembleGraphString(repository), repoPort));
+		final String repoPort = String.format(JS_TEMPLATE_PORT, JS_PORT_TYPE_INPUT, REPOSITORY_INPUT_PORT, "N/A");
+		RequestContext.getCurrentInstance().execute(String.format(JS_CMD_ADD_REPOSITORY, this.assembleGraphString(repository), repoPort));
+	}
+
+	/**
+	 * This method initializes the auto layout of the graph, resulting in a JavaScript event, delivering the necessary information about the graph.
+	 */
+	public void startAutoLayout() {
+		RequestContext.getCurrentInstance().execute(JS_CMD_START_AUTO_LAYOUT);
+	}
+
+	/**
+	 * This method uses the given parameters (via request parameter map) to calculate a new layout for the graph and use this layout.
+	 */
+	public void autoLayout() {
+		try {
+			// Get the parameters
+			final Object[] parameters = GlobalPropertiesBean.convertObjectsFromParameterMap(PARAMETER_NAMES_AUTO_LAYOUT, PARAMETER_TYPES_AUTO_LAYOUT);
+			final String nodes = (String) parameters[0];
+			final String edges = (String) parameters[1];
+
+			// Calculate the layout and use it
+			final String newLayout = this.layouter.layoutGraph(nodes, edges);
+			RequestContext.getCurrentInstance().execute(String.format(JS_CMD_LOAD_FROM_LAYOUT, newLayout));
+		} catch (final GraphLayoutException ex) {
+			CurrentAnalysisEditorGraphBean.LOG.warn("Autolayout failed.", ex);
+		}
 	}
 
 	/**
@@ -247,7 +254,7 @@ public class CurrentAnalysisEditorGraphBean {
 	 *            The input port.
 	 */
 	public void addConnection(final MIPlugin source, final MIPlugin destination, final MIOutputPort outputPort, final MIInputPort inputPort) {
-		RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_EDGE, this.assembleGraphPortID(source, outputPort),
+		RequestContext.getCurrentInstance().execute(String.format(JS_CMD_ADD_EDGE, this.assembleGraphPortID(source, outputPort),
 				this.assembleGraphPortID(destination, inputPort), ""));
 	}
 
@@ -262,145 +269,19 @@ public class CurrentAnalysisEditorGraphBean {
 	 *            The repository port.
 	 */
 	public void addConnection(final MIPlugin source, final MIRepository destination, final MIRepositoryConnector port) {
-		RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_ADD_EDGE, this.assembleGraphPortID(source, port),
+		RequestContext.getCurrentInstance().execute(String.format(JS_CMD_ADD_EDGE, this.assembleGraphPortID(source, port),
 				this.assembleGraphPortID(destination), ""));
 	}
 
-	/**
-	 * This method assembles the string containing the given ports.
-	 * 
-	 * @param ports
-	 *            The ports to be used within the string command.
-	 * @return A string containing the JS commands to create the ports.
-	 */
-	private String assembleGraphPortString(final EList<? extends MIPort> ports) {
-		final StringBuilder builder = new StringBuilder();
-		final int len = ports.size();
-
-		for (int i = 0; i < len; i++) {
-			final MIPort port = ports.get(i);
-
-			if (i != 0) {
-				builder.append(',');
-			}
-
-			builder.append(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_PORT, CurrentAnalysisEditorGraphBean.simpleEscape(port.getName()),
-					this.portMap.get(port), CurrentAnalysisEditorGraphBean.simpleEscape(port.getName())));
-		}
-
-		return builder.toString();
-
-	}
-
-	/**
-	 * This method assembles the string containing the available repository ports of the given plugin.
-	 * 
-	 * @param ports
-	 *            The ports which will be used.
-	 * @return A string containing the JS commands to create the repository ports.
-	 */
-	private String assembleGraphRepositoryPortString(final EList<MIRepositoryConnector> ports) {
-		final StringBuilder builder = new StringBuilder();
-		final int len = ports.size();
-
-		for (int i = 0; i < len; i++) {
-			final MIRepositoryConnector port = ports.get(i);
-
-			if (i != 0) {
-				builder.append(',');
-			}
-
-			builder.append(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_PORT, CurrentAnalysisEditorGraphBean.simpleEscape(port.getName()),
-					this.repositoryPortMap.get(port), CurrentAnalysisEditorGraphBean.simpleEscape(port.getName())));
-		}
-
-		return builder.toString();
-	}
-
-	/**
-	 * This method assembles the string containing the available input ports of the given filter.
-	 * 
-	 * @param filter
-	 *            The filter whose input ports will be used.
-	 * @return A string containing the JS commands to create the input ports.
-	 */
-	private String assembleGraphInputPortString(final MIFilter filter) {
-		return this.assembleGraphPortString(filter.getInputPorts());
-	}
-
-	/**
-	 * This method assembles the string containing the available output ports of the given plugin.
-	 * 
-	 * @param plugin
-	 *            The plugin whose output ports will be used.
-	 * @return A string containing the JS commands to create the output ports.
-	 */
-	private String assembleGraphOutputPortString(final MIPlugin plugin) {
-		return this.assembleGraphPortString(plugin.getOutputPorts());
-	}
-
-	/**
-	 * This method assembles the ID of the port for the graph based on the given parameters.
-	 * 
-	 * @param plugin
-	 *            The parent plugin of the port.
-	 * @param port
-	 *            The port itself.
-	 * @return The ID for the port within the graph
-	 */
-	private String assembleGraphPortID(final MIPlugin plugin, final MIPort port) {
-		return "id" + this.componentMap.get(plugin) + "." + this.portMap.get(port);
-	}
-
-	/**
-	 * This method assembles the ID of the port for the graph based on the given parameters.
-	 * 
-	 * @param plugin
-	 *            The parent plugin of the port.
-	 * @param port
-	 *            The port itself.
-	 * @return The ID for the port within the graph
-	 */
-	private Object assembleGraphPortID(final MIPlugin plugin, final MIRepositoryConnector port) {
-		return "id" + this.componentMap.get(plugin) + "." + this.repositoryPortMap.get(port);
-	}
-
-	/**
-	 * This method assembles the ID of the port for the graph based on the given parameters.
-	 * 
-	 * @param repository
-	 *            The parent repository of the port.
-	 * @return The ID for the port within the graph
-	 */
-	private Object assembleGraphPortID(final MIRepository repository) {
-		return "id" + this.componentMap.get(repository) + "." + CurrentAnalysisEditorGraphBean.REPOSITORY_INPUT_PORT;
-	}
-
-	/**
-	 * Assembles a human-readable string of the given repository or plugin, which can also be used as a graph ID.
-	 * 
-	 * @param component
-	 *            The component whose ID should be delivered.
-	 * @return A human readable ID.
-	 */
-	private String assembleGraphString(final MIAnalysisComponent component) {
-		final String name = component.getName();
-		final String className = component.getClassname();
-		final String shortName = className.substring(className.lastIndexOf('.') + 1);
-
-		return String.format(CurrentAnalysisEditorGraphBean.JS_CMD_NODE, "id" + this.componentMap.get(component),
-				CurrentAnalysisEditorGraphBean.simpleEscape(name), CurrentAnalysisEditorGraphBean.simpleEscape(shortName),
-				CurrentAnalysisEditorGraphBean.simpleEscape(className));
-	}
-
 	/**
 	 * This is the action which can be called from the javascript code to show that a node has been clicked. It informs the connected
 	 * {@link CurrentAnalysisEditorBean} about this.
 	 */
 	public void nodeClicked() {
 		// Get the parameters
-		final Map<String, String> paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
-		final String clickedNodeID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_ID);
+		final Object[] parameters = GlobalPropertiesBean.convertObjectsFromParameterMap(PARAMETER_NAMES_CLICK_AND_REMOVE_NODES,
+				PARAMETER_TYPES_CLICK_AND_REMOVE_NODEST);
+		final String clickedNodeID = (String) parameters[0];
 
 		if (clickedNodeID.isEmpty()) {
 			// Deselect
@@ -425,8 +306,11 @@ public class CurrentAnalysisEditorGraphBean {
 	 */
 	public void nodeRemoved() {
 		// Get the parameters
-		final Map<String, String> paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
-		final String clickedNodeID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_ID);
+
+		final Object[] parameters = GlobalPropertiesBean.convertObjectsFromParameterMap(PARAMETER_NAMES_CLICK_AND_REMOVE_NODES,
+				PARAMETER_TYPES_CLICK_AND_REMOVE_NODEST);
+		final String clickedNodeID = (String) parameters[0];
+
 		// Now search the correct node
 		try {
 			final MIAnalysisComponent selectedNode = this.componentMap.get(Integer.parseInt(clickedNodeID.substring(2)));
@@ -445,26 +329,24 @@ public class CurrentAnalysisEditorGraphBean {
 	 */
 	public void edgeCreated() {
 		// Get the parameters
-		final Map<String, String> paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
-
-		final String sourcePortID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_SOURCE_PORT_ID).split("\\.")[1];
-		final String targetPortID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_TARGET_PORT_ID).split("\\.")[1];
+		final Object[] parameters = GlobalPropertiesBean.convertObjectsFromParameterMap(PARAMETER_NAMES_ADD_AND_REMOVE_EDGES, PARAMETER_TYPES_ADD_AND_REMOVE_EDGES);
+		final String sourcePortID = ((String) parameters[0]).split("\\.")[1];
+		final String targetPortID = ((String) parameters[1]).split("\\.")[1];
 
 		// Now search the correct components
 		try {
-			if (CurrentAnalysisEditorGraphBean.REPOSITORY_INPUT_PORT.equals(targetPortID)) {
+			if (REPOSITORY_INPUT_PORT.equals(targetPortID)) {
 				// This is a special case: An edge between a filter and a repository
 				final MIRepositoryConnector sourcePort = this.repositoryPortMap.get(Integer.parseInt(sourcePortID));
-				final String targetID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_TARGET_PORT_ID).split("\\.")[0];
+				final String targetID = ((String) parameters[1]).split("\\.")[0];
 				final MIAnalysisComponent targetRepo = this.componentMap.get(Integer.parseInt(targetID.substring(2)));
-
 				if ((sourcePort != null) && (targetRepo instanceof MIRepository) && (this.currentAnalysisEditorBean != null)) {
 					this.currentAnalysisEditorBean.edgeCreated(sourcePort, (MIRepository) targetRepo);
 				}
 			} else {
 				// This is the normal case: An edge between two filters
-				final MIPort sourcePort = this.portMap.get(Integer.parseInt(sourcePortID));
-				final MIPort targetPort = this.portMap.get(Integer.parseInt(targetPortID));
+				final MIPort sourcePort = this.filterPortMap.get(Integer.parseInt(sourcePortID));
+				final MIPort targetPort = this.filterPortMap.get(Integer.parseInt(targetPortID));
 
 				if ((sourcePort != null) && (targetPort != null) && (this.currentAnalysisEditorBean != null)) {
 					this.currentAnalysisEditorBean.edgeCreated((MIOutputPort) sourcePort, (MIInputPort) targetPort);
@@ -482,25 +364,24 @@ public class CurrentAnalysisEditorGraphBean {
 	 */
 	public void edgeRemoved() {
 		// Get the parameters
-		final Map<String, String> paramMap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
-
-		final String sourcePortID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_SOURCE_PORT_ID).split("\\.")[1];
-		final String targetPortID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_TARGET_PORT_ID).split("\\.")[1];
+		final Object[] parameters = GlobalPropertiesBean.convertObjectsFromParameterMap(PARAMETER_NAMES_ADD_AND_REMOVE_EDGES, PARAMETER_TYPES_ADD_AND_REMOVE_EDGES);
+		final String sourcePortID = ((String) parameters[0]).split("\\.")[1];
+		final String targetPortID = ((String) parameters[1]).split("\\.")[1];
 
 		// Now search the correct components
 		try {
 			if (CurrentAnalysisEditorGraphBean.REPOSITORY_INPUT_PORT.equals(targetPortID)) {
 				// This is a special case: An edge between a filter and a repository
 				final MIRepositoryConnector sourcePort = this.repositoryPortMap.get(Integer.parseInt(sourcePortID));
-				final String targetID = paramMap.get(CurrentAnalysisEditorGraphBean.PARAM_NAME_TARGET_PORT_ID).split("\\.")[0];
+				final String targetID = ((String) parameters[1]).split("\\.")[0];
 				final MIAnalysisComponent targetRepo = this.componentMap.get(Integer.parseInt(targetID.substring(2)));
 				if ((sourcePort != null) && (targetRepo instanceof MIRepository) && (this.currentAnalysisEditorBean != null)) {
 					this.currentAnalysisEditorBean.edgeRemoved(sourcePort, (MIRepository) targetRepo);
 				}
 			} else {
 				// This is the normal case: An edge between two filters
-				final MIPort sourcePort = this.portMap.get(Integer.parseInt(sourcePortID));
-				final MIPort targetPort = this.portMap.get(Integer.parseInt(targetPortID));
+				final MIPort sourcePort = this.filterPortMap.get(Integer.parseInt(sourcePortID));
+				final MIPort targetPort = this.filterPortMap.get(Integer.parseInt(targetPortID));
 
 				if ((sourcePort != null) && (targetPort != null) && (this.currentAnalysisEditorBean != null)) {
 					this.currentAnalysisEditorBean.edgeRemoved((MIOutputPort) sourcePort, (MIInputPort) targetPort);
@@ -586,22 +467,7 @@ public class CurrentAnalysisEditorGraphBean {
 	 */
 	public void checkReadOnlyForGuests() {
 		if ("Guest".equals(this.userBean.getUserrole())) {
-			RequestContext.getCurrentInstance().execute(CurrentAnalysisEditorGraphBean.JS_CMD_SET_READ_ONLY);
-		}
-	}
-
-	/**
-	 * This method escapes the given string by removing the character ' from the string. This is necessary as the character could destroy the flow editor.
-	 * 
-	 * @param str
-	 *            The string to be escaped.
-	 * @return The escaped string.
-	 */
-	private static final String simpleEscape(final String str) {
-		if (str != null) {
-			return str.replaceAll("\'", "");
-		} else {
-			return str;
+			RequestContext.getCurrentInstance().execute(JS_CMD_SET_READ_ONLY);
 		}
 	}
 
@@ -624,7 +490,149 @@ public class CurrentAnalysisEditorGraphBean {
 	 *            The new layout for the graph.
 	 */
 	public void loadLayout(final String layout) {
-		RequestContext.getCurrentInstance().execute(String.format(CurrentAnalysisEditorGraphBean.JS_CMD_LOAD_FROM_LAYOUT, layout));
+		RequestContext.getCurrentInstance().execute(String.format(JS_CMD_LOAD_FROM_LAYOUT, layout));
+	}
+
+	/**
+	 * This method assembles the string containing the given ports.
+	 * 
+	 * @param ports
+	 *            The ports to be used within the string command.
+	 * @return A string containing the JS commands to create the ports.
+	 */
+	private String assembleGraphPortString(final EList<? extends MIPort> ports) {
+		final StringBuilder builder = new StringBuilder();
+		final int len = ports.size();
+
+		for (int i = 0; i < len; i++) {
+			final MIPort port = ports.get(i);
+
+			if (i != 0) {
+				builder.append(',');
+			}
+
+			builder.append(String.format(JS_TEMPLATE_PORT, CurrentAnalysisEditorGraphBean.simpleEscape(port.getName()), this.filterPortMap.get(port),
+					CurrentAnalysisEditorGraphBean.simpleEscape(port.getName())));
+		}
+
+		return builder.toString();
+
+	}
+
+	/**
+	 * This method assembles the string containing the available repository ports of the given plugin.
+	 * 
+	 * @param ports
+	 *            The ports which will be used.
+	 * @return A string containing the JS commands to create the repository ports.
+	 */
+	private String assembleGraphRepositoryPortString(final EList<MIRepositoryConnector> ports) {
+		final StringBuilder builder = new StringBuilder();
+		final int len = ports.size();
+
+		for (int i = 0; i < len; i++) {
+			final MIRepositoryConnector port = ports.get(i);
+
+			if (i != 0) {
+				builder.append(',');
+			}
+
+			builder.append(String.format(JS_TEMPLATE_PORT, CurrentAnalysisEditorGraphBean.simpleEscape(port.getName()), this.repositoryPortMap.get(port),
+					CurrentAnalysisEditorGraphBean.simpleEscape(port.getName())));
+		}
+
+		return builder.toString();
+	}
+
+	/**
+	 * This method assembles the string containing the available input ports of the given filter.
+	 * 
+	 * @param filter
+	 *            The filter whose input ports will be used.
+	 * @return A string containing the JS commands to create the input ports.
+	 */
+	private String assembleGraphInputPortString(final MIFilter filter) {
+		return this.assembleGraphPortString(filter.getInputPorts());
+	}
+
+	/**
+	 * This method assembles the string containing the available output ports of the given plugin.
+	 * 
+	 * @param plugin
+	 *            The plugin whose output ports will be used.
+	 * @return A string containing the JS commands to create the output ports.
+	 */
+	private String assembleGraphOutputPortString(final MIPlugin plugin) {
+		return this.assembleGraphPortString(plugin.getOutputPorts());
+	}
+
+	/**
+	 * This method assembles the ID of the port for the graph based on the given parameters.
+	 * 
+	 * @param plugin
+	 *            The parent plugin of the port.
+	 * @param port
+	 *            The port itself.
+	 * @return The ID for the port within the graph
+	 */
+	private String assembleGraphPortID(final MIPlugin plugin, final MIPort port) {
+		return "id" + this.componentMap.get(plugin) + "." + this.filterPortMap.get(port);
+	}
+
+	/**
+	 * This method assembles the ID of the port for the graph based on the given parameters.
+	 * 
+	 * @param plugin
+	 *            The parent plugin of the port.
+	 * @param port
+	 *            The port itself.
+	 * @return The ID for the port within the graph
+	 */
+	private Object assembleGraphPortID(final MIPlugin plugin, final MIRepositoryConnector port) {
+		return "id" + this.componentMap.get(plugin) + "." + this.repositoryPortMap.get(port);
+	}
+
+	/**
+	 * This method assembles the ID of the port for the graph based on the given parameters.
+	 * 
+	 * @param repository
+	 *            The parent repository of the port.
+	 * @return The ID for the port within the graph
+	 */
+	private Object assembleGraphPortID(final MIRepository repository) {
+		return "id" + this.componentMap.get(repository) + "." + REPOSITORY_INPUT_PORT;
+	}
+
+	/**
+	 * Assembles a human-readable string of the given repository or plugin, which can also be used as a graph ID.
+	 * 
+	 * @param component
+	 *            The component whose ID should be delivered.
+	 * @return A human readable ID.
+	 */
+	private String assembleGraphString(final MIAnalysisComponent component) {
+		final String name = component.getName();
+		final String className = component.getClassname();
+		final String shortName = className.substring(className.lastIndexOf('.') + 1);
+
+		return String.format(JS_TEMPLATE_NODE, "id" + this.componentMap.get(component),
+				CurrentAnalysisEditorGraphBean.simpleEscape(name), CurrentAnalysisEditorGraphBean.simpleEscape(shortName),
+				CurrentAnalysisEditorGraphBean.simpleEscape(className));
+	}
+
+	/**
+	 * This method escapes the given string by removing the character ' from the string. This is necessary as the character could destroy the flow editor.
+	 * 
+	 * @param str
+	 *            The string to be escaped.
+	 * @return The escaped string.
+	 */
+	private static final String simpleEscape(final String str) {
+		if (str != null) {
+			return str.replaceAll("\'", "");
+		} else {
+			return str;
+		}
 	}
 
 }
diff --git a/Kieker.WebGUI/src/main/webapp/dialogs/AnalysisEditorPageDialogs.xhtml b/Kieker.WebGUI/src/main/webapp/dialogs/AnalysisEditorPageDialogs.xhtml
index e135e206ddd32be9a0104ac07c3bd4ead6f5fcf9..51c82964879b4488623cba63f196b15299968bd9 100644
--- a/Kieker.WebGUI/src/main/webapp/dialogs/AnalysisEditorPageDialogs.xhtml
+++ b/Kieker.WebGUI/src/main/webapp/dialogs/AnalysisEditorPageDialogs.xhtml
@@ -30,7 +30,7 @@
             <br />
             <br />
             <h:form enctype="multipart/form-data">
-                <p:fileUpload label="#{localizedMessages.choose}" cancelLabel="#{localizedMessages.cancel}" auto="true" allowTypes="/(\.|\/)(jar)$/"  sizeLimit="104857600" mode="advanced" fileUploadListener="#{currentAnalysisEditorBean.handleFileUpload}" update=":dependenciesForm :messages :toolpalette"/>
+                <p:fileUpload label="#{localizedMessages.choose}" cancelLabel="#{localizedMessages.cancel}" auto="true" allowTypes="/(\.|\/)(jar)$/"  sizeLimit="104857600" mode="advanced" fileUploadListener="#{currentAnalysisEditorBean.handleLibraryFileUpload}" update=":dependenciesForm :messages :toolpalette"/>
             </h:form>
         </div>
         <hr/>
diff --git a/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml b/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml
index 60dc14524db25c3a494057c918cc01510efbea26..b76f59c8c7d93511776eb031629e1a0cd1f1671b 100644
--- a/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml
+++ b/Kieker.WebGUI/src/main/webapp/pages/AnalysisEditorPage.xhtml
@@ -39,7 +39,11 @@
             </ui:define>
 
             <ui:define name="js">
-                <script>            
+                <script>     
+                    nodeEnterListener = function() {
+                        graph.setMouseCursor('pointer');
+                    }
+                    
                     nodeClickListener = function(node, info, e) {
                         nodeClickCommand([{name : 'ID', value : node.id}]);
                         markNode(node, '#FF0000');