diff --git a/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar b/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar index a22e9259ac09ea61734a8572dcb7a5ffb51ed708..33fdb36f47c2c25a769b05f2af7de1c507d9cd2c 100644 Binary files a/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar and b/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar differ diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/CurrentAnalysisEditorBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/CurrentAnalysisEditorBean.java index 06cc778e2f879a20670d8a88d29ce4fa26516a23..f6bb70a485a157eef3234cee2761b96231136905 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/CurrentAnalysisEditorBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/CurrentAnalysisEditorBean.java @@ -26,9 +26,12 @@ import java.lang.reflect.Modifier; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Queue; import javax.faces.application.FacesMessage; import javax.faces.application.FacesMessage.Severity; @@ -70,6 +73,8 @@ import kieker.webgui.common.exception.LibraryAlreadyExistingException; import kieker.webgui.common.exception.NewerProjectException; import org.primefaces.event.FileUploadEvent; +import org.primefaces.model.DefaultTreeNode; +import org.primefaces.model.TreeNode; import org.primefaces.model.UploadedFile; import org.eclipse.emf.common.util.EList; @@ -109,17 +114,20 @@ public final class CurrentAnalysisEditorBean { */ private long timeStamp; /** - * This list contains the available repositories for the current project. + * This list contains the available repositories for the current project. The list is from the type Class<?> to allow a modular algorithm for the tree + * assembling. */ - private final List<Class<AbstractRepository>> availableRepositories = Collections.synchronizedList(new ArrayList<Class<AbstractRepository>>()); + private final List<Class<?>> availableRepositories = Collections.synchronizedList(new ArrayList<Class<?>>()); /** - * This list contains the available filters for the current project. + * This list contains the available filters for the current project. The list is from the type Class<?> to allow a modular algorithm for the tree + * assembl */ - private final List<Class<AbstractFilterPlugin>> availableFilters = Collections.synchronizedList(new ArrayList<Class<AbstractFilterPlugin>>()); + private final List<Class<?>> availableFilters = Collections.synchronizedList(new ArrayList<Class<?>>()); /** - * This list contains the available readers for the current project. + * This list contains the available readers for the current project. The list is from the type Class<?> to allow a modular algorithm for the tree + * assembl */ - private final List<Class<AbstractReaderPlugin>> availableReaders = Collections.synchronizedList(new ArrayList<Class<AbstractReaderPlugin>>()); + private final List<Class<?>> availableReaders = Collections.synchronizedList(new ArrayList<Class<?>>()); /** * This map contains the mapping between the plugins and their ID. */ @@ -207,6 +215,48 @@ public final class CurrentAnalysisEditorBean { } } + public TreeNode getAvailableComponentsAsRoot() { + // Create the necessary roots + final TreeNode root = new DefaultTreeNode("Root", null); + final TreeNode readerRoot = new DefaultTreeNode("Reader", root); + final TreeNode filterRoot = new DefaultTreeNode("Filter", root); + final TreeNode repositoryRoot = new DefaultTreeNode("Repository", root); + + // Fill the tree + CurrentAnalysisEditorBean.assembleTree(readerRoot, this.availableReaders, "readerLeaf"); + CurrentAnalysisEditorBean.assembleTree(filterRoot, this.availableFilters, "filterLeaf"); + CurrentAnalysisEditorBean.assembleTree(repositoryRoot, this.availableRepositories, "repositoryLeaf"); + + return root; + } + + private static void assembleTree(final TreeNode root, final List<Class<?>> clazzList, final String leafName) { + final HashMap<String, TreeNode> map = new HashMap<String, TreeNode>(); + + for (final Class<?> clazz : clazzList) { + // Get the single components of the class name + final String className = clazz.getName(); + final String[] nameComponents = className.split("\\."); + final int compLen = nameComponents.length; + final StringBuilder fullQualifiedName = new StringBuilder(); + + TreeNode parent = root; + for (int i = 0; i < (compLen - 1); i++) { + fullQualifiedName.append(nameComponents[i]); + // Get the correct node if it exists already or create it if necessary + TreeNode node = map.get(fullQualifiedName.toString()); + + if (node == null) { + node = new DefaultTreeNode(nameComponents[i], parent); + map.put(fullQualifiedName.toString(), node); + } + + parent = node; + } + new DefaultTreeNode(leafName, clazz, parent); + } + } + /** * This method initializes the hash maps of the plugins, the ports and the repositories. The maps are cleaned beforehand. */ @@ -281,10 +331,10 @@ public final class CurrentAnalysisEditorBean { if (!Modifier.isAbstract(plugin.getModifiers())) { // The following cast results in the unchecked-cast-warnings, but we know that the cast should be correct. if (AbstractFilterPlugin.class.isAssignableFrom(plugin)) { - this.availableFilters.add((Class<AbstractFilterPlugin>) plugin); + this.availableFilters.add(plugin); } else { if (AbstractReaderPlugin.class.isAssignableFrom(plugin)) { - this.availableReaders.add((Class<AbstractReaderPlugin>) plugin); + this.availableReaders.add(plugin); } } } @@ -449,7 +499,7 @@ public final class CurrentAnalysisEditorBean { * * @return A list with all readers. */ - public final List<Class<AbstractReaderPlugin>> getAvailableReaders() { + public final List<Class<?>> getAvailableReaders() { return this.availableReaders; } @@ -458,7 +508,7 @@ public final class CurrentAnalysisEditorBean { * * @return A list with all filter. */ - public final List<Class<AbstractFilterPlugin>> getAvailableFilters() { + public final List<Class<?>> getAvailableFilters() { return this.availableFilters; } @@ -467,7 +517,7 @@ public final class CurrentAnalysisEditorBean { * * @return A list with all repositories. */ - public final List<Class<AbstractRepository>> getAvailableRepositories() { + public final List<Class<?>> getAvailableRepositories() { return this.availableRepositories; } @@ -504,7 +554,7 @@ public final class CurrentAnalysisEditorBean { * @param plugin * The plugin to be filled. */ - private void fillDisplays(final Class<AbstractPlugin> clazz, final MIPlugin plugin) { + private boolean fillDisplays(final Class<AbstractPlugin> clazz, final MIPlugin plugin) { synchronized (this) { try { // Try to instantiate the given class, using the special constructor of Kieker. @@ -516,18 +566,23 @@ public final class CurrentAnalysisEditorBean { mDisplay.setName(displayName); plugin.getDisplays().add(mDisplay); } + return true; } catch (final InstantiationException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the displays of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the displays of the plugin."); + return false; } catch (final IllegalAccessException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the displays of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the displays of the plugin."); + return false; } catch (final InvocationTargetException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the displays of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the displays of the plugin."); + return false; } catch (final NoSuchMethodException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the displays of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the displays of the plugin."); + return false; } } } @@ -541,7 +596,7 @@ public final class CurrentAnalysisEditorBean { * @param plugin * The plugin to be filled. */ - private void fillPorts(final Class<AbstractPlugin> clazz, final MIPlugin plugin) { + private boolean fillPorts(final Class<AbstractPlugin> clazz, final MIPlugin plugin) { synchronized (this) { try { // Try to instantiate the given class, using the special constructor of Kieker. @@ -576,18 +631,24 @@ public final class CurrentAnalysisEditorBean { plugin.getRepositories().add(mConnector); } + return true; + } catch (final InstantiationException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the ports of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the ports of the plugin."); + return false; } catch (final IllegalAccessException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the ports of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the ports of the plugin."); + return false; } catch (final InvocationTargetException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the ports of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the ports of the plugin."); + return false; } catch (final NoSuchMethodException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the ports of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the ports of the plugin."); + return false; } } } @@ -601,7 +662,7 @@ public final class CurrentAnalysisEditorBean { * @param repository * The repository to be filled. */ - private void fillProperties(final Class<AbstractRepository> clazz, final MIRepository repository) { + private boolean fillProperties(final Class<AbstractRepository> clazz, final MIRepository repository) { try { // Try to instantiate the given class, using the special constructor of Kieker. final AbstractRepository repositoryInstance = clazz.getConstructor(Configuration.class).newInstance(new Configuration()); @@ -610,18 +671,23 @@ public final class CurrentAnalysisEditorBean { repository.getProperties().addAll(this.extractProperties(configuration)); + return true; } catch (final InstantiationException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the properties of the repository.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the properties of the repository."); + return false; } catch (final IllegalAccessException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the properties of the repository.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the properties of the repository."); + return false; } catch (final InvocationTargetException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the properties of the repository.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the properties of the repository."); + return false; } catch (final NoSuchMethodException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the properties of the repository.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the properties of the repository."); + return false; } } @@ -634,7 +700,7 @@ public final class CurrentAnalysisEditorBean { * @param plugin * The plugin to be filled. */ - private void fillProperties(final Class<AbstractPlugin> clazz, final MIPlugin plugin) { + private boolean fillProperties(final Class<AbstractPlugin> clazz, final MIPlugin plugin) { try { // Try to instantiate the given class, using the special constructor of Kieker. final AbstractPlugin pluginInstance = clazz.getConstructor(Configuration.class).newInstance(new Configuration()); @@ -643,18 +709,23 @@ public final class CurrentAnalysisEditorBean { plugin.getProperties().addAll(this.extractProperties(configuration)); + return true; } catch (final InstantiationException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the properties of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the properties of the plugin."); + return false; } catch (final IllegalAccessException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the properties of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the properties of the plugin."); + return false; } catch (final InvocationTargetException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the properties of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the properties of the plugin."); + return false; } catch (final NoSuchMethodException ex) { CurrentAnalysisEditorBean.LOG.error("An errcor occured while loading the properties of the plugin.", ex); CurrentAnalysisEditorBean.showMessage(FacesMessage.SEVERITY_ERROR, "An errcor occured while loading the properties of the plugin."); + return false; } } @@ -696,12 +767,14 @@ public final class CurrentAnalysisEditorBean { repository.setClassname(clazz.getName()); repository.setName(clazz.getSimpleName()); - this.fillProperties(clazz, repository); - - synchronized (this) { - // Add it to the project - this.project.getRepositories().add(repository); - this.repositoryMap.get(repository); + final boolean check = this.fillProperties(clazz, repository); + // Make sure that everything has been loaded correctly. If something went wrong, we don't add the component to our model + if (check) { + synchronized (this) { + // Add it to the project + this.project.getRepositories().add(repository); + this.repositoryMap.get(repository); + } } } @@ -722,27 +795,31 @@ public final class CurrentAnalysisEditorBean { plugin.setClassname(clazz.getName()); plugin.setName(clazz.getSimpleName()); - this.fillProperties(clazz, plugin); - this.fillPorts(clazz, plugin); - this.fillDisplays(clazz, plugin); + boolean check = true; + check &= this.fillProperties(clazz, plugin); + check &= this.fillPorts(clazz, plugin); + check &= this.fillDisplays(clazz, plugin); - synchronized (this) { - // Add it to the project and don't forget to add the ports. - this.project.getPlugins().add(plugin); - this.pluginMap.get(plugin); - for (final MIPort port : plugin.getOutputPorts()) { - this.portMap.get(port); - } - if (plugin instanceof MIFilter) { - for (final MIPort port : ((MIFilter) plugin).getInputPorts()) { + // Make sure that everything has been loaded correctly. If something went wrong, we don't add the component to our model + if (check) { + synchronized (this) { + // Add it to the project and don't forget to add the ports. + this.project.getPlugins().add(plugin); + this.pluginMap.get(plugin); + for (final MIPort port : plugin.getOutputPorts()) { this.portMap.get(port); } - } + if (plugin instanceof MIFilter) { + for (final MIPort port : ((MIFilter) plugin).getInputPorts()) { + this.portMap.get(port); + } + } - // Make sure the user can edit the repository connections. - final EList<MIRepositoryConnector> mConnectors = plugin.getRepositories(); - for (final MIRepositoryConnector mConnector : mConnectors) { - this.filter2repositoryConnections.add(new ConnectionFilterToRepository(plugin, mConnector.getRepository(), mConnector)); + // Make sure the user can edit the repository connections. + final EList<MIRepositoryConnector> mConnectors = plugin.getRepositories(); + for (final MIRepositoryConnector mConnector : mConnectors) { + this.filter2repositoryConnections.add(new ConnectionFilterToRepository(plugin, mConnector.getRepository(), mConnector)); + } } } } diff --git a/Kieker.WebGUI/src/main/webapp/AnalysisEditor.xhtml b/Kieker.WebGUI/src/main/webapp/AnalysisEditor.xhtml index 7616d2f0514b5ee1116049aea94978722e502718..babc0391c28879acf2219f186482afd51af917fe 100644 --- a/Kieker.WebGUI/src/main/webapp/AnalysisEditor.xhtml +++ b/Kieker.WebGUI/src/main/webapp/AnalysisEditor.xhtml @@ -167,6 +167,32 @@ </ui:repeat> </p:tab> </p:accordionPanel> + <p:tree id="docTree" value="#{currentAnalysisEditorBean.availableComponentsAsRoot}" var="elem"> + <p:treeNode type="default"> + <h:outputText value="#{elem}" /> + </p:treeNode> + + <p:treeNode type="filterLeaf"> + <h:form> + <p:commandLink id="filterLink" value="#{elem.simpleName}" action="#{currentAnalysisEditorBean.addPlugin(elem)}" update=":centerForm :messages"/><br/> + <p:tooltip style="font-size: 15px" for="filterLink" value="#{currentAnalysisEditorBean.getDescription(elem)}"/> + </h:form> + </p:treeNode> + + <p:treeNode type="readerLeaf"> + <h:form> + <p:commandLink id="readerLink1" value="#{elem.simpleName}" action="#{currentAnalysisEditorBean.addPlugin(elem)}" update=":centerForm :messages"/><br/> + <p:tooltip style="font-size: 15px" for="readerLink1" value="#{currentAnalysisEditorBean.getDescription(elem)}"/> + </h:form> + </p:treeNode> + + <p:treeNode type="repositoryLeaf"> + <h:form> + <p:commandLink id="repositoryLink" value="#{elem.simpleName}" action="#{currentAnalysisEditorBean.addRepository(elem)}" update=":centerForm :messages"/><br/> + <p:tooltip style="font-size: 15px" for="repositoryLink" value="#{currentAnalysisEditorBean.getDescription(elem)}"/> + </h:form> + </p:treeNode> + </p:tree> </h:form> </p:layoutUnit> <!-- ******************************************************************************** -->