/* * Copyright (c) 2012 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.ui.instancevalidation.report; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.xml.namespace.QName; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.DecorationOverlayIcon; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ITreeSelection; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.FilteredTree; import org.eclipse.ui.dialogs.PatternFilter; import org.eclipse.ui.views.properties.PropertySheet; import com.google.common.collect.Iterators; import eu.esdihumboldt.hale.common.core.report.Message; import eu.esdihumboldt.hale.common.instance.extension.validation.report.InstanceValidationMessage; import eu.esdihumboldt.hale.common.instance.model.InstanceReference; import eu.esdihumboldt.hale.common.schema.model.Definition; import eu.esdihumboldt.hale.ui.instancevalidation.InstanceValidationUIPlugin; import eu.esdihumboldt.hale.ui.selection.InstanceSelection; import eu.esdihumboldt.hale.ui.selection.impl.DefaultInstanceSelection; import eu.esdihumboldt.hale.ui.service.instance.InstanceService; import eu.esdihumboldt.hale.ui.util.viewer.tree.TreePathFilteredTree; import eu.esdihumboldt.hale.ui.util.viewer.tree.TreePathPatternFilter; import eu.esdihumboldt.hale.ui.views.data.TransformedDataView; import eu.esdihumboldt.hale.ui.views.report.properties.details.extension.CustomReportDetailsPage; /** * Custom report details page for instance validation reports. * * @author Kai Schwierczek */ public class InstanceValidationReportDetailsPage implements CustomReportDetailsPage { private TreeViewer treeViewer; private InstanceValidationReportDetailsContentProvider contentProvider; private Image reportImage; /** * @see CustomReportDetailsPage#createControls(Composite) */ @Override public Control createControls(Composite parent) { // filtered tree sets itself GridData, so set layout to gridlayout parent.setLayout(GridLayoutFactory.fillDefaults().create()); // create pattern filter for FilteredTree PatternFilter filter = new TreePathPatternFilter(); filter.setIncludeLeadingWildcard(true); // create FilteredTree FilteredTree filteredTree = new TreePathFilteredTree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL, filter, true); treeViewer = filteredTree.getViewer(); // set content provider contentProvider = new InstanceValidationReportDetailsContentProvider(); treeViewer.setContentProvider(contentProvider); // set label provider treeViewer.setLabelProvider( new InstanceValidationReportDetailsLabelProvider(contentProvider)); // set comparator treeViewer.setComparator(new ViewerComparator() { /** * @see org.eclipse.jface.viewers.ViewerComparator#category(java.lang.Object) */ @Override public int category(Object element) { if (element instanceof QName || element instanceof Definition<?>) return 0; // Path else if (element instanceof String) return 1; // Category else return 2; // InstanceValidationMessage } }); // add menu on right-click MenuManager menuMgr = new MenuManager(); Menu menu = menuMgr.createContextMenu(treeViewer.getTree()); menuMgr.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(IMenuManager manager) { if (getValidSelection() == null) return; // selection is valid, offer link to transformed data view manager.add(new ShowExampleAction()); } }); // remove previous menus menuMgr.setRemoveAllWhenShown(true); // add menu to tree treeViewer.getTree().setMenu(menu); treeViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { showSelectionInDataView(); } }); Image noReportBaseImage = InstanceValidationUIPlugin.getDefault().getImageRegistry() .get(InstanceValidationUIPlugin.IMG_INSTANCE_VALIDATION); reportImage = new DecorationOverlayIcon(noReportBaseImage, PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( ISharedImages.IMG_DEC_FIELD_WARNING), IDecoration.BOTTOM_LEFT).createImage(); return filteredTree; } /** * @see CustomReportDetailsPage#setInput(Collection, MessageType) */ @Override public void setInput(Collection<? extends Message> messages, MessageType type) { treeViewer.setInput(messages); // initially expand all levels treeViewer.expandAll(); } /** * Returns a valid instance selection for the current selection of the tree * viewer. Returns <code>null</code> if there is none. * * @return a valid instance selection for the current selection of the tree * viewer or <code>null</code> */ private InstanceSelection getValidSelection() { ISelection viewerSelection = treeViewer.getSelection(); if (!(viewerSelection instanceof ITreeSelection) || viewerSelection.isEmpty()) return null; ITreeSelection treeSelection = (ITreeSelection) treeViewer.getSelection(); TreePath firstPath = treeSelection.getPaths()[0]; // XXX use all paths // instead of first // only? InstanceValidationMessage firstMessage; Iterator<InstanceValidationMessage> restIter; if (firstPath.getLastSegment() instanceof InstanceValidationMessage) { firstMessage = (InstanceValidationMessage) firstPath.getLastSegment(); restIter = Iterators.emptyIterator(); } else { Collection<InstanceValidationMessage> messages = contentProvider .getMessages(treeSelection.getPaths()[0]); if (messages.isEmpty()) return null; // shouldn't happen, but doesn't really matter restIter = messages.iterator(); firstMessage = restIter.next(); } InstanceService is = PlatformUI.getWorkbench().getService(InstanceService.class); // check first message for valid instance reference if (firstMessage.getInstanceReference() == null || is.getInstance(firstMessage.getInstanceReference()) == null) return null; Set<InstanceReference> references = new HashSet<InstanceReference>(); references.add(firstMessage.getInstanceReference()); while (restIter.hasNext()) references.add(restIter.next().getInstanceReference()); return new DefaultInstanceSelection(references.toArray()); } /** * Shows the current selection (if valid) in the transformed data view. */ private void showSelectionInDataView() { InstanceSelection selection = getValidSelection(); if (selection != null) { IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getActivePage(); // pin the property sheet if possible IViewReference ref = page.findViewReference(IPageLayout.ID_PROP_SHEET); if (ref != null) { IViewPart part = ref.getView(true); if (part instanceof PropertySheet) ((PropertySheet) part).setPinned(true); } // show transformed data view with selection if possible try { TransformedDataView transformedDataView = (TransformedDataView) page .showView(TransformedDataView.ID); transformedDataView.showSelection(selection, reportImage); } catch (PartInitException e) { // if it's not there, we cannot do anything } } } /** * @see CustomReportDetailsPage#dispose() */ @Override public void dispose() { if (reportImage != null) { reportImage.dispose(); } } /** * Action that opens the transformed data view with example instances * selected here. */ private final class ShowExampleAction extends Action { /** * Default constructor. */ private ShowExampleAction() { super("Show example instances in Transformed data view"); } /** * @see org.eclipse.jface.action.Action#run() */ @Override public void run() { showSelectionInDataView(); } } }