/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.ui.navigator.model;
import static org.teiid.designer.ui.UiConstants.Util;
import static org.teiid.designer.ui.navigator.model.ModelNavigatorMessages.genericDiagramLabel;
import static org.teiid.designer.ui.navigator.model.ModelNavigatorMessages.genericTransformationLabel;
import static org.teiid.designer.ui.navigator.model.ModelNavigatorMessages.problemMarkerBrackets;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ILightweightLabelDecorator;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.navigator.IDescriptionProvider;
import org.eclipse.xsd.XSDAttributeUse;
import org.eclipse.xsd.XSDParticle;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.extension.ExtensionPlugin;
import org.teiid.designer.extension.definition.ModelExtensionAssistant;
import org.teiid.designer.extension.definition.ModelObjectExtensionAssistant;
import org.teiid.designer.extension.registry.ModelExtensionRegistry;
import org.teiid.designer.metamodels.diagram.Diagram;
import org.teiid.designer.metamodels.transformation.TransformationMappingRoot;
import org.teiid.designer.ui.PluginConstants;
import org.teiid.designer.ui.UiPlugin;
import org.teiid.designer.ui.viewsupport.DiagramLabelProvider;
import org.teiid.designer.ui.viewsupport.ExtendedModelObjectLabelProvider;
import org.teiid.designer.ui.viewsupport.IExtendedModelObject;
import org.teiid.designer.ui.viewsupport.ImportContainer;
import org.teiid.designer.ui.viewsupport.MarkerUtilities;
import org.teiid.designer.ui.viewsupport.ModelIdentifier;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
public class ModelNavigatorLabelProvider extends LabelProvider implements IDescriptionProvider, ILightweightLabelDecorator,
PluginConstants.Images {
private final ILabelProvider defaultProvider;
private final DiagramLabelProvider diagramLabelProvider;
private final IBaseLabelProvider eventSource;
private final ExtendedModelObjectLabelProvider extendedModelObjectLabelProvider;
final ListenerList myListeners = new ListenerList(ListenerList.IDENTITY);
private final IResourceChangeListener resrcChgListener;
public ModelNavigatorLabelProvider() {
this.eventSource = this;
this.defaultProvider = new WorkbenchLabelProvider();
// Add listener for model validation completion events
this.resrcChgListener = new IResourceChangeListener() {
/**
* {@inheritDoc}
*
* @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
*/
@Override
public void resourceChanged( final IResourceChangeEvent event ) {
final Display display = Display.getDefault();
if (display.isDisposed()) {
return;
}
// Don't do any work if ther are no listeners.... :)
if (myListeners.isEmpty()) {
return;
}
final IMarkerDelta[] deltas = event.findMarkerDeltas(null, true);
if ((deltas != null) && (deltas.length > 0)) {
Set resources = new HashSet();
for (IMarkerDelta delta : deltas) {
resources.add(delta.getResource());
}
final Object[] resourcesToUpdate = resources.toArray();
display.asyncExec(new Runnable() {
/**
* {@inheritDoc}
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
changeLabel(resourcesToUpdate);
}
});
}
}
};
ModelerCore.getWorkspace().addResourceChangeListener(this.resrcChgListener);
this.diagramLabelProvider = new DiagramLabelProvider();
this.extendedModelObjectLabelProvider = new ExtendedModelObjectLabelProvider();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.BaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
*/
@Override
public void addListener( ILabelProviderListener listener ) {
super.addListener(listener);
// Method declared on IBaseLabelProvider. Defect 23509 - we need to keep track of # of listeners in this class because super
// does not have a getter
myListeners.add(listener);
}
void changeLabel( Object[] resourcesToUpdate ) {
fireLabelProviderChanged(new LabelProviderChangedEvent(getLabelProviderChangedEventSource(), resourcesToUpdate));
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object, org.eclipse.jface.viewers.IDecoration)
*/
@Override
public void decorate( final Object element,
final IDecoration decoration ) {
final Display display = Display.getDefault();
if (display.isDisposed()) {
return;
}
final IResource resrc = getResource(element);
if ((resrc == null) || !resrc.exists() || ((resrc instanceof IProject) && !((IProject)resrc).isOpen())) {
return;
}
IMarker[] markers = null;
boolean errorOccurred = false;
try {
markers = resrc.findMarkers(IMarker.PROBLEM, false, IResource.DEPTH_INFINITE);
} catch (CoreException ex) {
Util.log(ex);
errorOccurred = true;
}
if (!errorOccurred) {
ImageDescriptor decorationIcon = getDecorationIcon(markers);
if (decorationIcon != null) {
decoration.addOverlay(decorationIcon);
}
}
try {
// add suffix for special warnings:
IMarker[] problems = resrc.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO);
for (IMarker marker : problems) {
String value = marker.getAttribute(ModelerCore.MARKER_PROBLEM_DECORATOR_TEXT, null);
if (value != null) {
decoration.addSuffix(problemMarkerBrackets);
break;
}
}
} catch (CoreException ex) {
Util.log(ex);
}
// Lastly, decorate with Extension if applicable
if (element instanceof IFile) {
File file = ((IFile)element).getLocation().toFile();
ModelExtensionRegistry registry = ExtensionPlugin.getInstance().getRegistry();
try {
for (String namespacePrefix : registry.getAllNamespacePrefixes()) {
ModelExtensionAssistant assistant = registry.getModelExtensionAssistant(namespacePrefix);
if ((assistant instanceof ModelObjectExtensionAssistant)
&& ((ModelObjectExtensionAssistant)assistant).hasExtensionProperties(file)) {
decoration.addOverlay(UiPlugin.getDefault().getExtensionDecoratorImage(), IDecoration.TOP_LEFT);
break;
}
}
} catch (Exception e) {
Util.log(e);
}
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.BaseLabelProvider#dispose()
*/
@Override
public void dispose() {
if (this.resrcChgListener != null) {
ModelerCore.getWorkspace().removeResourceChangeListener(this.resrcChgListener);
}
}
private ImageDescriptor getDecorationIcon( IMarker[] markers ) {
ImageDescriptor icon = null;
final boolean startedTxn = ModelerCore.startTxn(false, false, null, this);
boolean succeeded = false;
try {
for (int ndx = markers.length; --ndx >= 0;) {
final Object attr = MarkerUtilities.getMarkerAttribute(markers[ndx], IMarker.SEVERITY); // markers[ndx].getAttribute(IMarker.SEVERITY);
if (attr == null) {
continue;
}
// Asserting attr is an Integer...
final int severity = ((Integer)attr).intValue();
if (severity == IMarker.SEVERITY_ERROR) {
icon = UiPlugin.getDefault().getErrorDecoratorImage();
break;
}
if ((icon == null) && (severity == IMarker.SEVERITY_WARNING)) {
icon = UiPlugin.getDefault().getWarningDecoratorImage();
}
}
succeeded = true;
} finally {
if (startedTxn) {
if (succeeded)
ModelerCore.commitTxn();
else
ModelerCore.rollbackTxn();
}
}
return icon;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.navigator.IDescriptionProvider#getDescription(java.lang.Object)
*/
@Override
public String getDescription( Object element ) {
if (element instanceof EObject) {
String description;
EObject eObj = (EObject)element;
if (eObj instanceof ENamedElement) {
description = eObj.eClass().getName() + ": " + ((ENamedElement)eObj).getName(); //$NON-NLS-1$
} else if (eObj instanceof XSDParticle) {
description = ((XSDParticle)eObj).getTerm().eClass().getName();
} else if (eObj instanceof XSDAttributeUse) {
description = ((XSDAttributeUse)eObj).getAttributeDeclaration().eClass().getName();
} else {
description = eObj.eClass().getName();
}
return description + ": " + ModelerCore.getModelEditor().getModelRelativePathIncludingModel(eObj); //$NON-NLS-1$
}
if (element instanceof ImportContainer) {
return ((ImportContainer)element).toString();
}
if (element instanceof IExtendedModelObject) {
return ((IExtendedModelObject)element).getStatusLabel();
}
return getText(element);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
*/
@Override
public Image getImage( Object element ) {
Image result = null;
final boolean startedTxn = ModelerCore.startTxn(false, false, null, this);
boolean succeeded = false;
try {
if (element instanceof Diagram) {
result = this.diagramLabelProvider.getImage(element);
if (result == null) {
result = UiPlugin.getDefault().getImage("icons/full/obj16/Diagram.gif"); //$NON-NLS-1$
}
}
else if (element instanceof ImportContainer) {
result = UiPlugin.getDefault().getImage(IMPORT_CONTAINER);
}
else if (element instanceof EObject) {
if (element instanceof TransformationMappingRoot)
result = UiPlugin.getDefault().getImage("icons/full/obj16/Transform.gif"); //$NON-NLS-1$
else
result = ModelUtilities.getEMFLabelProvider().getImage(element);
} else if (element instanceof IFile && ModelUtilities.isModelFile((IFile)element) && ((IFile)element).exists()) {
result = ModelIdentifier.getModelImage((IResource)element);
} else {
result = this.extendedModelObjectLabelProvider.getImage(element);
}
if (result == null) {
result = this.defaultProvider.getImage(element);
}
succeeded = true;
} catch (final Exception err) {
Util.log(err);
} finally {
if (startedTxn) {
if (succeeded)
ModelerCore.commitTxn();
else
ModelerCore.rollbackTxn();
}
}
if (result != null)
return result;
else
return super.getImage(element);
}
public IBaseLabelProvider getLabelProviderChangedEventSource() {
return this.eventSource;
}
/**
* Returns the resource for the specified element, or null if there is no resource associated with it.
*
* @param element The element for which to find an associated resource
* @return The resource for the specified element; may be null.
*/
private IResource getResource( final Object element ) {
if (element instanceof IResource) {
return (IResource)element;
}
if (element instanceof IAdaptable) {
return (IResource)((IAdaptable)element).getAdapter(IResource.class);
}
return null;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
*/
@Override
public String getText( Object element ) {
String result = null;
final boolean startedTxn = ModelerCore.startTxn(false, false, null, this);
boolean succeeded = false;
try {
if (element instanceof Diagram) {
result = this.diagramLabelProvider.getText(element);
if (result == null) {
result = genericDiagramLabel;
}
}
else if (element instanceof ImportContainer) {
result = element.toString();
}
else if (element instanceof EObject) {
if (element instanceof TransformationMappingRoot) {
result = genericTransformationLabel;
}
else {
ILabelProvider p = ModelUtilities.getEMFLabelProvider();
result = p.getText(element);
}
} else {
result = this.extendedModelObjectLabelProvider.getText(element);
}
if (result == null)
result = this.defaultProvider.getText(element);
succeeded = true;
} finally {
if (startedTxn) {
if (succeeded)
ModelerCore.commitTxn();
else
ModelerCore.rollbackTxn();
}
}
return result;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.viewers.BaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
*/
@Override
public void removeListener( ILabelProviderListener listener ) {
super.removeListener(listener);
// Method declared on IBaseLabelProvider. Defect 23509 - we need to keep track of # of listeners in this class because super
// does not have a getter
this.myListeners.remove(listener);
}
}