package rocks.inspectit.ui.rcp.dialog; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.collections.CollectionUtils; import org.eclipse.core.commands.Command; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.forms.ManagedForm; import org.eclipse.ui.forms.events.HyperlinkAdapter; import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.ExpandableComposite; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Hyperlink; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; import org.eclipse.ui.forms.widgets.TableWrapData; import org.eclipse.ui.forms.widgets.TableWrapLayout; import rocks.inspectit.shared.all.cmr.model.PlatformIdent; import rocks.inspectit.shared.all.cmr.model.SensorTypeIdent; import rocks.inspectit.shared.all.communication.DefaultData; import rocks.inspectit.shared.all.tracing.data.Span; import rocks.inspectit.ui.rcp.InspectIT; import rocks.inspectit.ui.rcp.InspectITImages; import rocks.inspectit.ui.rcp.composite.BreadcrumbTitleComposite; import rocks.inspectit.ui.rcp.details.DetailsGenerationFactory; import rocks.inspectit.ui.rcp.details.DetailsTable; import rocks.inspectit.ui.rcp.formatter.TextFormatter; import rocks.inspectit.ui.rcp.model.SensorTypeEnum; import rocks.inspectit.ui.rcp.repository.RepositoryDefinition; import rocks.inspectit.ui.rcp.util.AccessibleArrowImage; import rocks.inspectit.ui.rcp.util.ClipboardUtil; /** * The dialog that displays details of the element. * * @author Ivan Senic * */ public class DetailsDialog extends Dialog { /** * Maps of commands IDs and labels to display related to navigation. */ private static final Map<String, String> NAVIGATE_COMMANDS_IDS = new HashMap<>(); /** * Maps of commands IDs and labels to display related to navigation. */ private static final Map<String, String> ACTION_COMMANDS_IDS = new HashMap<>(); static { NAVIGATE_COMMANDS_IDS.put("rocks.inspectit.ui.rcp.commands.navigateToAggregatedSqlData", "Aggregated SQL Data"); NAVIGATE_COMMANDS_IDS.put("rocks.inspectit.ui.rcp.commands.navigateToAggregatedTimerData", "Aggregated Timer Data"); NAVIGATE_COMMANDS_IDS.put("rocks.inspectit.ui.rcp.commands.navigateToInvocations", "Invocation(s)"); NAVIGATE_COMMANDS_IDS.put("rocks.inspectit.ui.rcp.commands.navigateToStartMethodInvocations", "Only This Method Invocation(s)"); NAVIGATE_COMMANDS_IDS.put("rocks.inspectit.ui.rcp.commands.navigateToSingleExceptionType", "Exception Type"); NAVIGATE_COMMANDS_IDS.put("rocks.inspectit.ui.rcp.commands.navigateToGroupedExceptionType", "Grouped Exception View"); NAVIGATE_COMMANDS_IDS.put("rocks.inspectit.ui.rcp.commands.traceDetails", "Trace Details"); ACTION_COMMANDS_IDS.put("rocks.inspectit.ui.rcp.commands.copySqlQuery", "Copy SQL Query"); ACTION_COMMANDS_IDS.put("rocks.inspectit.ui.rcp.commands.copyLogMessage", "Copy Log Message"); ACTION_COMMANDS_IDS.put("rocks.inspectit.ui.rcp.commands.displayInChart", "Display in Chart"); ACTION_COMMANDS_IDS.put("org.eclipse.ui.file.save", "Save to Server"); } /** * Data to display the details for. */ private DefaultData defaultData; /** * Repository definition data belongs to. */ private RepositoryDefinition repositoryDefinition; /** * {@link ICommandService} for dealing with the commands to be displayed on the workflow menu. */ private ICommandService commandService; /** * Command that will be executed when dialog is closed. */ private Command commandOnClose; /** * Arrow image to display next to the command links. */ private Image arrow; /** * {@link BreadcrumbTitleComposite} for displaying on the top. */ private BreadcrumbTitleComposite breadcrumbTitleComposite; /** * List of created {@link DetailsTable}s. */ private List<DetailsTable> detailTables; /** * Default constructor. * * @param parentShell * {@link Shell} to create dialog on. * @param defaultData * {@link DefaultData} to create details for. * @param repositoryDefinition * {@link RepositoryDefinition} data belongs to. */ public DetailsDialog(Shell parentShell, DefaultData defaultData, RepositoryDefinition repositoryDefinition) { super(parentShell); this.defaultData = defaultData; this.repositoryDefinition = repositoryDefinition; commandService = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); arrow = new AccessibleArrowImage(true).createImage(); } /** * {@inheritDoc} */ @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText("Details"); } /** * {@inheritDoc} */ @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); } /** * {@inheritDoc} */ @Override protected void setShellStyle(int newShellStyle) { super.setShellStyle(SWT.CLOSE | SWT.MODELESS | SWT.BORDER | SWT.TITLE | SWT.RESIZE); setBlockOnOpen(false); } /** * {@inheritDoc} */ @Override protected Control createDialogArea(Composite parent) { Composite content = (Composite) super.createDialogArea(parent); content.setLayout(new FillLayout()); ((GridData) content.getLayoutData()).widthHint = 1050; ManagedForm managedForm = new ManagedForm(content); FormToolkit toolkit = managedForm.getToolkit(); ScrolledForm form = managedForm.getForm(); managedForm.getToolkit().decorateFormHeading(form.getForm()); breadcrumbTitleComposite = new BreadcrumbTitleComposite(form.getForm().getHead(), SWT.NONE); setDataForBreadcrumbTitleComposite(); form.setHeadClient(breadcrumbTitleComposite); Composite main = form.getBody(); TableWrapLayout mainLayout = new TableWrapLayout(); mainLayout.numColumns = 2; main.setLayout(mainLayout); // info section Composite info = toolkit.createComposite(main); info.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); TableWrapLayout infoLayout = new TableWrapLayout(); infoLayout.verticalSpacing = 20; info.setLayout(infoLayout); DetailsGenerationFactory generationFactory = InspectIT.getService(DetailsGenerationFactory.class); detailTables = generationFactory.createDetailComposites(defaultData, repositoryDefinition, info, toolkit); if (CollectionUtils.isNotEmpty(detailTables)) { for (DetailsTable detailsTable : detailTables) { detailsTable.getSection().setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); managedForm.addPart(detailsTable); } } // menu section Composite navigation = toolkit.createComposite(main); navigation.setData(defaultData); navigation.setLayoutData(new TableWrapData(TableWrapData.FILL)); navigation.setLayout(new GridLayout(1, false)); // navigate stuff Section navigateSection = toolkit.createSection(navigation, ExpandableComposite.TITLE_BAR); navigateSection.setText("Navigate To"); navigateSection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); Composite navigateComposite = toolkit.createComposite(navigateSection); navigateComposite.setLayout(new GridLayout(2, false)); navigateSection.setClient(navigateComposite); createLinks(navigateComposite, toolkit, NAVIGATE_COMMANDS_IDS); // actions stuff Section actionsSection = toolkit.createSection(navigation, ExpandableComposite.TITLE_BAR); actionsSection.setText("Actions"); actionsSection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); Composite actionsComposite = toolkit.createComposite(actionsSection); actionsComposite.setLayout(new GridLayout(2, false)); actionsSection.setClient(actionsComposite); // copy action manually toolkit.createLabel(actionsComposite, "", SWT.NONE).setImage(arrow); Hyperlink copyLink = toolkit.createHyperlink(actionsComposite, "Copy", SWT.WRAP); copyLink.addHyperlinkListener(new CopyHyperlinkListener()); copyLink.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); createLinks(actionsComposite, toolkit, ACTION_COMMANDS_IDS); return parent; } /** * Creates links for given commands on the parent composite. * * @param parent * Parent composite. * @param toolkit * {@link FormToolkit} to use. * @param commandMap * IDs of the commands to display. Only active ones will be displayed. */ private void createLinks(Composite parent, FormToolkit toolkit, Map<String, String> commandMap) { for (Map.Entry<String, String> entry : commandMap.entrySet()) { Command command = commandService.getCommand(entry.getKey()); if (command.isDefined() && (null != command.getHandler()) && command.getHandler().isEnabled()) { toolkit.createLabel(parent, "", SWT.NONE).setImage(arrow); Hyperlink link = toolkit.createHyperlink(parent, entry.getValue(), SWT.WRAP); link.addHyperlinkListener(new CommandHyperlinkListener(command)); link.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); } } } /** * Sets data for the {@link BreadcrumbTitleComposite}. */ private void setDataForBreadcrumbTitleComposite() { // repository breadcrumbTitleComposite.setRepositoryDefinition(repositoryDefinition); // agent PlatformIdent platformIdent = repositoryDefinition.getCachedDataService().getPlatformIdentForId(defaultData.getPlatformIdent()); if (null != platformIdent) { breadcrumbTitleComposite.setAgent(TextFormatter.getAgentDescription(platformIdent), InspectIT.getDefault().getImage(InspectITImages.IMG_AGENT)); } else { breadcrumbTitleComposite.setAgent("All Agents", InspectIT.getDefault().getImage(InspectITImages.IMG_AGENT)); } // sensor info if (0 != defaultData.getSensorTypeIdent()) { SensorTypeIdent sensorTypeIdent = repositoryDefinition.getCachedDataService().getSensorTypeIdentForId(defaultData.getSensorTypeIdent()); String fqn = sensorTypeIdent.getFullyQualifiedClassName(); SensorTypeEnum sensorTypeEnum = SensorTypeEnum.get(fqn); if (null != sensorTypeEnum) { breadcrumbTitleComposite.setGroup(sensorTypeEnum.getDisplayName(), sensorTypeEnum.getImage()); } } else if (defaultData instanceof Span) { // must be set explicitly as no sensor id is set with user spans breadcrumbTitleComposite.setGroup("Tracing SDK", null); } breadcrumbTitleComposite.setView("Details", null); } /** * {@inheritDoc} */ @Override public boolean close() { arrow.dispose(); breadcrumbTitleComposite.dispose(); return super.close(); } /** * Gets {@link #commandOnClose}. * * @return {@link #commandOnClose} */ public Command getCommandOnClose() { return commandOnClose; } /** * {@link HyperlinkAdapter} for setting the correct {@link DetailsDialog#commandOnClose} when * clicked. * * @author Ivan Senic * */ private class CommandHyperlinkListener extends HyperlinkAdapter { /** * Command. */ private Command command; /** * Default constructor. * * @param command * Command. */ public CommandHyperlinkListener(Command command) { this.command = command; } /** * {@inheritDoc} */ @Override public void linkActivated(HyperlinkEvent e) { DetailsDialog.this.commandOnClose = command; DetailsDialog.this.close(); } } /** * Hyperlink listener for the copy operation. * * @author Ivan Senic * */ private class CopyHyperlinkListener extends HyperlinkAdapter { /** * {@inheritDoc} */ @Override public void linkActivated(HyperlinkEvent e) { StringBuilder sb = new StringBuilder(); sb.append(breadcrumbTitleComposite.getCopyString()); sb.append("\n\n"); for (DetailsTable table : detailTables) { sb.append(table.getCopyString()); sb.append('\n'); } ClipboardUtil.textToClipboard(getShell().getDisplay(), sb.toString()); } } }