/* * 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.mapping.ui.editor; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Display; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.teiid.core.designer.util.StringUtilities; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelWorkspaceManager; import org.teiid.designer.mapping.factory.TreeMappingAdapter; import org.teiid.designer.metamodels.transformation.MappingClass; import org.teiid.designer.metamodels.transformation.StagingTable; import org.teiid.designer.metamodels.xml.util.XmlDocumentUtil; import org.teiid.designer.ui.PluginConstants; import org.teiid.designer.ui.UiPlugin; import org.teiid.designer.ui.common.graphics.GlobalUiColorManager; import org.teiid.designer.ui.common.util.UiUtil; import org.teiid.designer.ui.explorer.ModelExplorerLabelProvider; import org.teiid.designer.ui.viewsupport.MarkerUtilities; import org.teiid.designer.ui.viewsupport.ModelObjectUtilities; import org.teiid.designer.ui.viewsupport.ModelUtilities; /** * XmlDocumentModelObjectLabelProvider is a wrapper around EMF's ILabelProvider that colors EObject icons with virtual or physical * colors. It also supplies a specialized icon for Built-in Datatypes. jh Lyra enh: Creating this new subclass of * ModelObjectLabelProvider so that we can add custom behavior for the Xml Document Tree. Basically, we need to make this provider * aware of the details of the doc model so we can annotate certain nodes, for example anchor points. * * @since 8.0 */ public class XmlDocumentModelObjectLabelProvider extends ModelExplorerLabelProvider { private static final String SUFFIX_EXCLUDED = Util.getString("XmlDocumentModelObjectLabelProvider.suffixExcluded"); //$NON-NLS-1$ /** The color being replaced. */ private static final Color TEMP_COLOR = GlobalUiColorManager.getColor(new RGB(247, 247, 247)); private static final Color PHYSICAL_COLOR = GlobalUiColorManager.getColor(new RGB(0, 220, 225)); private static final Color VIRTUAL_COLOR = GlobalUiColorManager.getColor(new RGB(255, 204, 102)); static Color gray = null; private ILabelProvider delegate = null; private TreeMappingAdapter tmaMappingAdapter; private DocumentTreeController docTreeController; public XmlDocumentModelObjectLabelProvider() { super(); delegate = ModelUtilities.getAdapterFactoryLabelProvider(); } public XmlDocumentModelObjectLabelProvider( DocumentTreeController docTreeController ) { super(); delegate = ModelUtilities.getAdapterFactoryLabelProvider(); // jh Defect 21277: The state of backing maps was getting out of sync which appeared as // errors in the text labels produced by this provider. The fix is to // give this class a reference to DocumentTreeController so that he can // always get the latest copy of MappingAdapterFilter/TreeMappingAdapter. this.docTreeController = docTreeController; } /** * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object) */ @Override public Image getImage( Object theElement ) { Image result = null; if (theElement instanceof XSDSimpleTypeDefinition) { try { // Only care about built-in types, so just use the workspace DT Mgr ... if (ModelerCore.getWorkspaceDatatypeManager().isBuiltInDatatype((XSDSimpleTypeDefinition)theElement)) { result = UiPlugin.getDefault().getImage(PluginConstants.Images.BUILTIN_DATATYPE); } else { result = delegate.getImage(theElement); } } catch (Exception e) { result = delegate.getImage(theElement); } } else if (theElement instanceof EObject) { EObject eObj = (EObject)theElement; Image temp = delegate.getImage(theElement); boolean virtual = ModelObjectUtilities.isVirtual(eObj); String prefix = (virtual) ? "virtual." : "physical."; //$NON-NLS-1$ //$NON-NLS-2$ // image registry uses the base image hashCode as key String imageId = prefix + temp.hashCode(); UiPlugin plugin = UiPlugin.getDefault(); if (plugin.isImageRegistered(imageId)) { result = plugin.getImage(imageId); } else { result = UiUtil.createImage(temp, TEMP_COLOR, (virtual) ? VIRTUAL_COLOR : PHYSICAL_COLOR); plugin.registerPluginImage(imageId, result); } } else { result = delegate.getImage(theElement); } return result; } /** * Overloaded getImage necessary for finding icons for EObjects that are not inside a Model. Specifically, this method was * written for the New Child/Sibling menu items. * * @param theElement * @param modelType * @return * @since 4.2 */ public Image getImage( final EObject theElement, boolean isVirtual ) { Image result = null; if (theElement instanceof XSDSimpleTypeDefinition) { try { // Only care about built-in types, so just use the workspace DT Mgr ... if (ModelerCore.getWorkspaceDatatypeManager().isBuiltInDatatype(theElement)) { result = UiPlugin.getDefault().getImage(PluginConstants.Images.BUILTIN_DATATYPE); } else { result = delegate.getImage(theElement); } } catch (Exception e) { result = delegate.getImage(theElement); } } else { Image temp = delegate.getImage(theElement); String prefix = (isVirtual) ? "virtual." : "physical."; //$NON-NLS-1$ //$NON-NLS-2$ // image registry uses the base image hashCode as key String imageId = prefix + temp.hashCode(); UiPlugin plugin = UiPlugin.getDefault(); if (plugin.isImageRegistered(imageId)) { result = plugin.getImage(imageId); } else { result = UiUtil.createImage(temp, TEMP_COLOR, (isVirtual) ? VIRTUAL_COLOR : PHYSICAL_COLOR); plugin.registerPluginImage(imageId, result); } } return result; } /** * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) */ @Override public String getText( Object theElement ) { // System.out.println("\n[XmlDocumentModelObjectLabelProvider.getText] TOP; theElement: " + theElement ); // Thread.dumpStack(); /* * jh Lyra enh: for M1.3, we'll need to determine if the element is the * "anchor point" or "Mapping Root" of a MC; if so we tack * the MC name to the end of the text. Example: * () sequence - MC: book * Can we do the same for getImage()??? If we wish to tack * and MC icon onto the EMF icon ( '{}' for sequence, for example), * can we do that? Or can we create a second set of EMF icons that * combine the EMF designation with the MC icon and substitute the * appropriate one whenever a node is an MC root???? * Ask Dan F. * * Also consider these issues for M1.2: "Change icons in tree to * indicate multiplicity (use XSD icons). * */ String sText = StringUtilities.replaceWhitespace(delegate.getText(theElement), true); String sFinalText = sText; // System.out.println("[XmlDocumentModelObjectLabelProvider.getText] About to process: " + sText ); /* * jh Lyra enh: Determine if this node is the anchor of a Mapping Class. * If so, add the MC's name to the text of this node. */ if (theElement instanceof EObject) { // jh Defect 21277: Get MappingAdapterFilter from DocumentTreeController. tmaMappingAdapter = docTreeController.getMappingAdapterFilter().getMappingAdapter(); MappingClass mc = tmaMappingAdapter.getMappingClass((EObject)theElement); // if ( mc != null ) { // System.out.println("[XmlDocumentModelObjectLabelProvider.getText] we have an MC, will we use it?: " + mc.getName() // ); // } // we'll find a mapping class ONLY if this treenode is the mapping root element if (mc != null && mc.getName() != null && mc.getName().trim() != "") { //$NON-NLS-1$ String sMappingClassName = mc.getName(); sFinalText = sText + " [MC: " + sMappingClassName + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } else { // System.out.println("[XmlDocumentModelObjectLabelProvider.getText] NO MC:"); } // jh Lyra enh: TODO do the same for Staging Tables... StagingTable st = tmaMappingAdapter.getStagingTableForRootTreeNode((EObject)theElement); // if ( st != null ) { // System.out.println("[XmlDocumentModelObjectLabelProvider.getText] we have an ST, will we use it?: " + st.getName() // ); // } // we'll find a staging table ONLY if this treenode is mapped to a staging table // (a staging table can only be mapped to one element) if (st != null && st.getName() != null && st.getName().trim() != "") { //$NON-NLS-1$ String sStagingTableName = st.getName(); sFinalText = sText + " [ST: " + sStagingTableName + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } else { // System.out.println("[XmlDocumentModelObjectLabelProvider.getText] NO ST:"); } } // System.out.println("[XmlDocumentModelObjectLabelProvider.getText] About to return: " + sFinalText ); return sFinalText; } /** * @see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object, org.eclipse.jface.viewers.IDecoration) * @since 4.0 */ @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[] mrkrs = null; boolean errorOccurred = false; try { mrkrs = resrc.findMarkers(IMarker.PROBLEM, false, IResource.DEPTH_INFINITE); } catch (CoreException ex) { Util.log(ex); errorOccurred = true; } if (!errorOccurred) { final IMarker[] markers = mrkrs; ImageDescriptor decorationIcon = getDecorationIcon((EObject)element, resrc, markers); if (decorationIcon != null) { decoration.addOverlay(decorationIcon); } } // defect 19275 - fiddle with colors for certain nodes: // first, obtain gray from the system if we don't have it yet: if (gray == null) { Display.getDefault().syncExec(new Runnable() { @Override public void run() { gray = UiUtil.getSystemColor(SWT.COLOR_GRAY); } }); // endanon } // endif // check if this node is excluded or is part of a subtree that is: if (XmlDocumentUtil.isExcluded(element, true)) { decoration.setForegroundColor(gray); // also show [excluded] when actually set to this node: if (XmlDocumentUtil.isExcluded(element, false)) decoration.addSuffix(SUFFIX_EXCLUDED); } // endif } private ImageDescriptor getDecorationIcon( EObject element, IResource resrc, IMarker[] markers ) { ImageDescriptor icon = null; for (int ndx = markers.length; --ndx >= 0;) { IMarker marker = markers[ndx]; EObject targetEObject = ModelWorkspaceManager.getModelWorkspaceManager().getMarkerManager().getMarkedEObject(resrc, marker); boolean usable = ((element == targetEObject) || ModelObjectUtilities.isDescendant(element, targetEObject)); if (!usable) { continue; } final Object attr = MarkerUtilities.getMarkerAttribute(marker, 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(); } } return icon; } /** * 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. * @since 4.0 */ private IResource getResource( final Object element ) { if (element instanceof EObject) { IResource ir = null; ModelResource modelResource = ModelUtilities.getModelResourceForModelObject((EObject)element); if (modelResource != null) { ir = modelResource.getResource(); } return ir; } return null; } /** * Method to provide a way to get an image with the URL instead of EObject and to colorize it based on virtual vs physical. * * @param theElement * @param url * @return * @since 4.2 */ public Image getImage( EObject eObj, Object url ) { Image result = null; Image temp = ModelObjectUtilities.getImageFromObject(url); if (temp != null) { ModelResource modelResource = ModelUtilities.getModelResourceForModelObject(eObj); boolean virtual = (ModelUtilities.isVirtual(modelResource)); String prefix = (virtual) ? "virtual." : "physical."; //$NON-NLS-1$ //$NON-NLS-2$ // image registry uses the base image hashCode as key String imageId = prefix + temp.hashCode(); UiPlugin plugin = UiPlugin.getDefault(); if (plugin.isImageRegistered(imageId)) { result = plugin.getImage(imageId); } else { result = UiUtil.createImage(temp, TEMP_COLOR, (virtual) ? VIRTUAL_COLOR : PHYSICAL_COLOR); plugin.registerPluginImage(imageId, result); } } return result; } public void setTreeMappingAdapter( TreeMappingAdapter tmaMappingAdapter ) { this.tmaMappingAdapter = tmaMappingAdapter; } }