diff --git a/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar b/Kieker.WebGUI/lib/kieker-1.6-SNAPSHOT_emf.jar index 3af732c1e3ebf8682eeb9b22f53f7e466e11f80d..1226fc8a09fb8bb0570d5a8abf6d61b9fa8cd500 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/application/ProjectsBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/application/ProjectsBean.java index e735c37128ed61b7172800025a05759245e6fc55..5968a7f3b81696861c2ff58a367d30d605a86c99 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/application/ProjectsBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/application/ProjectsBean.java @@ -19,6 +19,8 @@ ***************************************************************************/ package kieker.webgui.beans.application; +import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.List; import java.util.Observable; @@ -27,12 +29,17 @@ import javax.faces.bean.ApplicationScoped; import javax.faces.bean.ManagedBean; import javax.faces.context.FacesContext; +import kieker.analysis.display.HtmlText; +import kieker.analysis.display.Image; +import kieker.analysis.display.PlainText; +import kieker.analysis.display.annotation.Display; import kieker.analysis.model.analysisMetaModel.MIDependency; import kieker.analysis.model.analysisMetaModel.MIPlugin; import kieker.analysis.model.analysisMetaModel.MIProject; import kieker.analysis.model.analysisMetaModel.impl.MAnalysisMetaModelFactory; import kieker.analysis.plugin.AbstractPlugin; import kieker.analysis.plugin.annotation.Plugin; +import kieker.analysis.repository.AbstractRepository; import kieker.webgui.common.FileManager; import org.primefaces.context.RequestContext; @@ -172,15 +179,88 @@ public class ProjectsBean extends Observable { } } - public String getDescription(final Class<? super AbstractPlugin> pluginClass) { - Plugin annotation = pluginClass.getAnnotation(Plugin.class); - if (annotation == null || annotation.description().isEmpty()) { - return "No description available"; - } else { - return annotation.description(); - } - } - + /** + * This method can be used to get the description of an {@link AbstractPlugin}- or an {@link AbstractRepository}-class. The description is read via the + * annotation. + * + * @param clazz + * The class whose description should be extracted. + * @return The description for the class or a substitute if none is available. + */ + public String getDescription(final Class<?> clazz) { + final Plugin annotation = clazz.getAnnotation(Plugin.class); + if (annotation == null || annotation.description().isEmpty()) { + return "No description available"; + } else { + return annotation.description(); + } + } + + public List<Widget> getWidgets(final Class<?> clazz) { + // TODO Cache + final List<Widget> widgets = new ArrayList<ProjectsBean.Widget>(); + if (clazz != null) { + // Run through all methods and check them + final Method[] methods = clazz.getMethods(); + for (final Method method : methods) { + // If the method does have the right annotation, we use it. + final Display displayAnnot = method.getAnnotation(Display.class); + if (displayAnnot != null) { + // Get the correct type of the method + final Class<?> returnType = method.getReturnType(); + final Widget.WidgetType type; + // TODO This should be done better. + if (returnType.isAssignableFrom(PlainText.class) && PlainText.class.isAssignableFrom(returnType)) { + type = Widget.WidgetType.PlainText; + } else { + if (returnType.isAssignableFrom(HtmlText.class) && HtmlText.class.isAssignableFrom(returnType)) { + type = Widget.WidgetType.HtmlText; + } else { + if (returnType.isAssignableFrom(Image.class) && Image.class.isAssignableFrom(returnType)) { + type = Widget.WidgetType.Image; + } else { + // Unknown type! + continue; + } + } + } + + final Widget widget = new Widget(method, type, displayAnnot.name()); + widgets.add(widget); + } + } + } + return widgets; + } + + public static class Widget { + private final Method widgetMethod; + private final WidgetType type; + private final String name; + + public static enum WidgetType { + PlainText, HtmlText, Image + } + + public Widget(final Method widgetMethod, final WidgetType type, final String name) { + this.widgetMethod = widgetMethod; + this.type = type; + this.name = name; + } + + public Method getWidgetMethod() { + return this.widgetMethod; + } + + public WidgetType getType() { + return this.type; + } + + public String getName() { + return this.name; + } + } + /** * This helper class is a wrapper for a project and can be send to the observers as a message that a project just has been removed. It contains * the removed project. diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/request/StringToIDBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/request/StringToIDBean.java index c842a9c5d433f65292fe6ff0860aa647728a01c2..78b84789b47914f03b3a25ed365bbfee54e6d063 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/request/StringToIDBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/request/StringToIDBean.java @@ -48,6 +48,6 @@ public class StringToIDBean { * @return The given string without space characters. */ public String stringToID(final String string) { - return string.replace(" ", ""); + return string.replace(" ", "").replace("$", "").replace("@", ""); } } diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/AnalysisControllerBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/AnalysisControllerBean.java index 8fa3f4f78a00e2d34268c953e30c480f4d251245..1996b79128a98ec4d8bf9b061fd2cd153e3df6c2 100644 --- a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/AnalysisControllerBean.java +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/AnalysisControllerBean.java @@ -19,9 +19,8 @@ ***************************************************************************/ package kieker.webgui.beans.session; -import java.io.File; -import java.io.IOException; import java.util.HashMap; +import java.util.Map; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; @@ -55,8 +54,8 @@ public class AnalysisControllerBean { * The controller instance stored within this bean. */ private AnalysisController controller; - private HashMap<MIPlugin, AbstractPlugin> pluginMap; - private HashMap<MIRepository, AbstractRepository> repositoryMap; + private Map<MIPlugin, AbstractPlugin> pluginMap; + private Map<MIRepository, AbstractRepository> repositoryMap; /** * Creates a new instance of this class. @@ -65,6 +64,14 @@ public class AnalysisControllerBean { // No code necessary. } + public Map<MIPlugin, AbstractPlugin> getPluginMap() { + return this.pluginMap; + } + + public Map<MIRepository, AbstractRepository> getRepositoryMap() { + return this.repositoryMap; + } + /** * Delivers the controller stored within this bean. * @@ -94,11 +101,12 @@ public class AnalysisControllerBean { if (mProject != null) { try { // Try to create the controller. - final AnalysisController.AnalysisControllerWithMapping controllerAndMapping = AnalysisController.createAnalysisController(mProject, PluginClassLoader.getInstance()); + final AnalysisController.AnalysisControllerWithMapping controllerAndMapping = AnalysisController.createAnalysisController(mProject, + PluginClassLoader.getInstance()); // Extract everything that is necessary. - this.controller = controllerAndMapping.getController(); - this.pluginMap = controllerAndMapping.getPluginMap(); - this.repositoryMap = controllerAndMapping.getRepositoryMap(); + this.controller = controllerAndMapping.getController(); + this.pluginMap = controllerAndMapping.getPluginMap(); + this.repositoryMap = controllerAndMapping.getRepositoryMap(); } catch (final NullPointerException ex) { AnalysisControllerBean.LOG.error("Could not create analysis controller.", ex); } catch (final AnalysisConfigurationException ex) { diff --git a/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/DashboardBean.java b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/DashboardBean.java new file mode 100644 index 0000000000000000000000000000000000000000..4ba2fc9ae2e41bcb9a10d37d4f0daf8ff622462c --- /dev/null +++ b/Kieker.WebGUI/src/main/java/kieker/webgui/beans/session/DashboardBean.java @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright 2012 by + * + Christian-Albrechts-University of Kiel + * + Department of Computer Science + * + Software Engineering Group + * and others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ***************************************************************************/ +package kieker.webgui.beans.session; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import javax.faces.bean.ManagedBean; +import javax.faces.bean.SessionScoped; +import javax.faces.context.FacesContext; + +import kieker.webgui.beans.application.ProjectsBean; +import kieker.webgui.beans.request.StringToIDBean; + +import org.primefaces.model.DashboardColumn; +import org.primefaces.model.DashboardModel; +import org.primefaces.model.DefaultDashboardColumn; +import org.primefaces.model.DefaultDashboardModel; + +/** + * + * @author Nils Christian Ehmke + */ +@ManagedBean +@SessionScoped +public class DashboardBean implements Serializable { + + private final DashboardModel model; + private final List<ProjectsBean.Widget> widgets; + + public DashboardBean() { + this.model = new DefaultDashboardModel(); + this.widgets = new ArrayList<ProjectsBean.Widget>(); + + final DashboardColumn column1 = new DefaultDashboardColumn(); + final DashboardColumn column2 = new DefaultDashboardColumn(); + final DashboardColumn column3 = new DefaultDashboardColumn(); + + this.model.addColumn(column1); + this.model.addColumn(column2); + this.model.addColumn(column3); + } + + public DashboardModel getModel() { + return this.model; + } + + public void addWidget(final ProjectsBean.Widget widget) { + final FacesContext context = FacesContext.getCurrentInstance(); + final StringToIDBean idBean = context.getApplication().evaluateExpressionGet(context, "#{stringToIDBean}", StringToIDBean.class); + synchronized (this.widgets) { + this.widgets.add(widget); + this.model.getColumn(0).addWidget(idBean.stringToID(widget.toString())); + } + } + + public List<ProjectsBean.Widget> getWidgets() { + return this.widgets; + } +} diff --git a/Kieker.WebGUI/src/main/webapp/handleAnalysis.css b/Kieker.WebGUI/src/main/webapp/handleAnalysis.css index c59c077bfff0a0c6f6f032fd1c8ded9ba2cd8b9c..0bb60d77c5fdae3ee61386549dab9575a2c0af1d 100644 --- a/Kieker.WebGUI/src/main/webapp/handleAnalysis.css +++ b/Kieker.WebGUI/src/main/webapp/handleAnalysis.css @@ -24,6 +24,10 @@ font-size: 15px; } +.ui-layout-west { + font-size: 15px; +} + .ui-datatable { font-size: 15px; } diff --git a/Kieker.WebGUI/src/main/webapp/handleAnalysis.xhtml b/Kieker.WebGUI/src/main/webapp/handleAnalysis.xhtml index c18e4d588c2189325cd29e8c25d729d26d42cf28..792a458b3e666c799ca791b5c0b10e0ca224e0aa 100644 --- a/Kieker.WebGUI/src/main/webapp/handleAnalysis.xhtml +++ b/Kieker.WebGUI/src/main/webapp/handleAnalysis.xhtml @@ -45,35 +45,24 @@ </c:when> <c:otherwise> - <p:layoutUnit position="center" > + <p:layoutUnit position="center"> <h:form id="centerForm"> - <div class="canvas" id="mainCanvas" style="width: auto; height: 500px"> - <c:forEach items="#{selectedProjectBean.selectedProject.plugins}" var="plugin"> - <div class="ui-panel ui-widget ui-widget-content ui-corner-all block draggable" id="#{stringToIDBean.stringToID(plugin)}"> - <div class="ui-panel-titlebar ui-widget-header ui-corner-all"> - <h:outputText style="font-weight: bold" value="#{plugin.name}"/> - </div> - <p:commandLink ajax="true" value="Show Data"/> - </div> - </c:forEach> - </div> + <ui:repeat value="#{dashboardBean.widgets}" var="widget"> + <p:panel id="widget" header="#{widget.name}"> + + </p:panel> + <p:poll interval="2" update="widget"/> + </ui:repeat> </h:form> </p:layoutUnit> - <p:layoutUnit position="east" size="300" resizable="true" collapsible="true" header="Plugin"> - <h:form > - <p:accordionPanel multiple="true" activeIndex=""> - <p:tab title="Details"> - <p:scrollPanel style="height: 150px"> - </p:scrollPanel> - </p:tab> - <p:tab title="Log"> - <p:scrollPanel style="height: 150px"> - </p:scrollPanel> - </p:tab> - <p:tab title="Visualization"> - <p:outputPanel style="height: 150px; width: 150px"> - </p:outputPanel> + <p:layoutUnit style="overflow:visible;" position="west" size="200" resizable="true" collapsible="true" header="Plugins"> + <h:form id="pluginsForm"> + <p:accordionPanel value="#{analysisControllerBean.pluginMap.keySet().toArray()}" var="plugin" multiple="true" activeIndex=""> + <p:tab title="#{plugin.name}"> + <ui:repeat value="#{projectsBean.getWidgets(analysisControllerBean.pluginMap.get(plugin).getClass())}" var="widget"> + <p:commandLink value="#{widget.name}" ajax="true" update=":centerForm" action="#{dashboardBean.addWidget(widget)}"/><br/> + </ui:repeat> </p:tab> </p:accordionPanel> </h:form> @@ -81,7 +70,7 @@ <p:layoutUnit position="south" header="Analysis Control" resizable="true" collapsible="true"> <h:form id="analysisForm"> - <p:commandButton value="Instantiate Analysis" action="#{analysisControllerBean.instantiate(selectedProjectBean.selectedProject)}" update=":analysisForm:analysisStateText"/> + <p:commandButton value="Instantiate Analysis" action="#{analysisControllerBean.instantiate(selectedProjectBean.selectedProject)}" update=":analysisForm:analysisStateText :pluginsForm"/> <p:commandButton id="startAnalysisButton" value="Start Analysis" async="true" action="#{analysisControllerBean.controller.run()}" disabled="#{empty analysisControllerBean.controller}"/> <p:commandButton id="stopAnalysisButton" value="Stop Analysis" async="true" action="#{analysisControllerBean.controller.terminate()}" disabled="#{empty analysisControllerBean.controller}"/> <p:spacer height="0px" width="150px"/>