/******************************************************************************* * Copyright (c) 2001, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Naoki Akiyama, Fujitsu - Bug 244901 - Cannot set xsd:annotation to * xsd:redefine by Properties view. *******************************************************************************/ package org.eclipse.wst.xsd.ui.internal.common.util; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Stack; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.DecorationOverlayIcon; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory; import org.eclipse.wst.sse.core.internal.format.IStructuredFormatProcessor; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; import org.eclipse.wst.xml.core.internal.provisional.format.FormatProcessorXML; import org.eclipse.wst.xsd.ui.internal.adt.design.ImageOverlayDescriptor; import org.eclipse.wst.xsd.ui.internal.common.properties.sections.AbstractSection; import org.eclipse.wst.xsd.ui.internal.editor.XSDEditorPlugin; import org.eclipse.xsd.XSDAnnotation; import org.eclipse.xsd.XSDAttributeDeclaration; import org.eclipse.xsd.XSDAttributeGroupDefinition; import org.eclipse.xsd.XSDAttributeUse; import org.eclipse.xsd.XSDComplexTypeContent; import org.eclipse.xsd.XSDComplexTypeDefinition; import org.eclipse.xsd.XSDConcreteComponent; import org.eclipse.xsd.XSDElementDeclaration; import org.eclipse.xsd.XSDEnumerationFacet; import org.eclipse.xsd.XSDFacet; import org.eclipse.xsd.XSDFactory; import org.eclipse.xsd.XSDFeature; import org.eclipse.xsd.XSDIdentityConstraintDefinition; import org.eclipse.xsd.XSDImport; import org.eclipse.xsd.XSDInclude; import org.eclipse.xsd.XSDModelGroup; import org.eclipse.xsd.XSDModelGroupDefinition; import org.eclipse.xsd.XSDNamedComponent; import org.eclipse.xsd.XSDNotationDeclaration; import org.eclipse.xsd.XSDParticle; import org.eclipse.xsd.XSDRedefine; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.eclipse.xsd.XSDTypeDefinition; import org.eclipse.xsd.XSDWildcard; import org.eclipse.xsd.XSDXPathDefinition; import org.eclipse.xsd.util.XSDConstants; import org.w3c.dom.Element; import org.w3c.dom.Node; public class XSDCommonUIUtils { public XSDCommonUIUtils() { super(); } public static Image getUpdatedImage(XSDConcreteComponent input, Image baseImage, boolean isReadOnly) { XSDAnnotation xsdAnnotation = getInputXSDAnnotation(input, false); if (xsdAnnotation != null) { if (xsdAnnotation.getApplicationInformation().size() > 0) { // Will use the class name appended by the read only state as the name of the image. // There is a disabled and an enabled version of each baseImage, so we can't simply // use the component name as the name of the image String imageName = input.getClass().getName() + isReadOnly; Image newImage = XSDEditorPlugin.getDefault().getImageRegistry().get(imageName); if (newImage == null) { ImageOverlayDescriptor ovr = new ImageOverlayDescriptor(baseImage, isReadOnly); newImage = ovr.getImage(); XSDEditorPlugin.getDefault().getImageRegistry().put(imageName, newImage); } return newImage; } } return baseImage; } public static XSDAnnotation getInputXSDAnnotation(XSDConcreteComponent input, boolean createIfNotExist) { XSDAnnotation xsdAnnotation = null; XSDFactory factory = XSDFactory.eINSTANCE; if (input instanceof XSDAttributeDeclaration) { XSDAttributeDeclaration xsdComp = (XSDAttributeDeclaration) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDAttributeGroupDefinition) { XSDAttributeGroupDefinition xsdComp = (XSDAttributeGroupDefinition) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDElementDeclaration) { XSDElementDeclaration xsdComp = (XSDElementDeclaration) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDNotationDeclaration) { XSDNotationDeclaration xsdComp = (XSDNotationDeclaration) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDXPathDefinition) { XSDXPathDefinition xsdComp = (XSDXPathDefinition) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDModelGroup) { XSDModelGroup xsdComp = (XSDModelGroup) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDModelGroupDefinition) { XSDModelGroupDefinition xsdComp = (XSDModelGroupDefinition) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDIdentityConstraintDefinition) { XSDIdentityConstraintDefinition xsdComp = (XSDIdentityConstraintDefinition) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDWildcard) { XSDWildcard xsdComp = (XSDWildcard) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDSchema) { XSDSchema xsdComp = (XSDSchema) input; List list = xsdComp.getAnnotations(); if (list.size() > 0) { xsdAnnotation = (XSDAnnotation) list.get(0); } else { if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); if (xsdComp.getContents() != null) { xsdComp.getContents().add(0, xsdAnnotation); } } } return xsdAnnotation; } else if (input instanceof XSDFacet) { XSDFacet xsdComp = (XSDFacet) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDTypeDefinition) { XSDTypeDefinition xsdComp = (XSDTypeDefinition) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDInclude) { XSDInclude xsdComp = (XSDInclude) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDImport) { XSDImport xsdComp = (XSDImport) input; xsdAnnotation = xsdComp.getAnnotation(); if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); xsdComp.setAnnotation(xsdAnnotation); } } else if (input instanceof XSDRedefine) { XSDRedefine xsdComp = (XSDRedefine) input; List contents = xsdComp.getContents(); for (int i = 0; i < contents.size(); i++) { Object content = contents.get(i); if (content instanceof XSDAnnotation) { xsdAnnotation = (XSDAnnotation) content; break; } } if (createIfNotExist && xsdAnnotation == null) { xsdAnnotation = factory.createXSDAnnotation(); contents.add(0, xsdAnnotation); } return xsdAnnotation; } else if (input instanceof XSDAnnotation) { xsdAnnotation = (XSDAnnotation) input; } if (createIfNotExist) { formatAnnotation(xsdAnnotation); } return xsdAnnotation; } private static void formatAnnotation(XSDAnnotation annotation) { Element element = annotation.getElement(); formatChild(element); } public static void formatChild(Node child) { if (child instanceof IDOMNode) { IDOMModel model = ((IDOMNode) child).getModel(); try { // tell the model that we are about to make a big model change model.aboutToChangeModel(); IStructuredFormatProcessor formatProcessor = new FormatProcessorXML(); formatProcessor.formatNode(child); } finally { // tell the model that we are done with the big model change model.changedModel(); } } } public static String createUniqueElementName(String prefix, List elements) { ArrayList usedNames = new ArrayList(); for (Iterator i = elements.iterator(); i.hasNext();) { usedNames.add(getDisplayName((XSDNamedComponent) i.next())); } int i = 1; String testName = prefix; while (usedNames.contains(testName)) { testName = prefix + i++; } return testName; } public static String createUniqueEnumerationValue(String prefix, List elements) { ArrayList usedNames = new ArrayList(); for (Iterator i = elements.iterator(); i.hasNext();) { usedNames.add(((XSDEnumerationFacet) i.next()).getLexicalValue()); } int i = 1; String testName = prefix; while (usedNames.contains(testName)) { testName = prefix + i++; } return testName; } public static String getDisplayName(XSDNamedComponent component) { if (component instanceof XSDTypeDefinition) return getDisplayNameFromXSDType((XSDTypeDefinition) component); if (component instanceof XSDFeature) { XSDFeature feature = (XSDFeature) component; if (feature.getName() != null) return feature.getName(); else if (feature.getResolvedFeature() != null && feature.getResolvedFeature().getName() != null) return feature.getResolvedFeature().getName(); } return component.getName(); } public static String getDisplayNameFromXSDType(XSDTypeDefinition type) { return getDisplayNameFromXSDType(type, true); } public static String getDisplayNameFromXSDType(XSDTypeDefinition type, boolean returnPrimitiveParents) { if (type == null) return null; if (type.getName() == null || type.getName().length() == 0) { if (returnPrimitiveParents && isPrimitiveType(type)) { return getDisplayNameFromXSDType(type.getBaseType()); } EObject container = type.eContainer(); while (container != null) { if (container instanceof XSDNamedComponent && ((XSDNamedComponent) container).getName() != null) { return ((XSDNamedComponent) container).getName(); } container = container.eContainer(); } return null; } else return type.getName(); } public static boolean isPrimitiveType(XSDTypeDefinition type) { if (type instanceof XSDComplexTypeDefinition) return false; XSDTypeDefinition baseType = null; if (type != null) { baseType = type.getBaseType(); XSDTypeDefinition origType = baseType; // KC: although invalid, we need to // prevent cycles and to avoid an // infinite loop while (baseType != null && !XSDConstants.isAnySimpleType(baseType) && !XSDConstants.isAnyType(baseType) && origType != baseType) { type = baseType; baseType = type.getBaseType(); } baseType = type; } else { return false; } return (XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001.equals(baseType.getTargetNamespace())); } public static XSDSimpleTypeDefinition getAnonymousSimpleType(XSDFeature input, XSDSimpleTypeDefinition xsdSimpleTypeDefinition) { XSDSimpleTypeDefinition anonymousSimpleType = null; XSDTypeDefinition localType = null; if (input instanceof XSDElementDeclaration) { localType = ((XSDElementDeclaration) input).getAnonymousTypeDefinition(); } else if (input instanceof XSDAttributeDeclaration) { localType = ((XSDAttributeDeclaration) input).getAnonymousTypeDefinition(); } if (localType instanceof XSDSimpleTypeDefinition) { anonymousSimpleType = (XSDSimpleTypeDefinition) localType; } return anonymousSimpleType; } // bug246036 - check for cyclic groups. We should refactor out this static class. private static Stack visitedGroups = new Stack(); public static void resetVisitedGroupsStack() { visitedGroups.clear(); } public static List getChildElements(XSDModelGroup group) { List children = new ArrayList(); visitedGroups.push(group); if (group == null) return children; for (Iterator i = group.getContents().iterator(); i.hasNext();) { XSDParticle next = (XSDParticle) i.next(); if (next.getContent() instanceof XSDFeature) { if (children.contains(next.getContent())) break; children.add(next.getContent()); } else if (next.getTerm() instanceof XSDModelGroup) { if (!visitedGroups.contains(group)) children.addAll(getChildElements((XSDModelGroup) next.getTerm())); } } visitedGroups.pop(); return children; } public static List getAllAttributes(XSDComplexTypeDefinition xsdComplexType) { List attributes = getChildElements(xsdComplexType); attributes.addAll(getChildAttributes(xsdComplexType)); return attributes; } public static List getAllAttributes(XSDModelGroupDefinition xsdModelGroupDefinition) { List attributes = getChildElements(xsdModelGroupDefinition); return attributes; } public static List getInheritedAttributes(XSDComplexTypeDefinition ct) { List attrs = new ArrayList(); XSDTypeDefinition parent = ct.getBaseTypeDefinition(); if (parent != null && parent instanceof XSDComplexTypeDefinition && ct.isSetDerivationMethod()) { attrs.addAll(getAllAttributes((XSDComplexTypeDefinition) parent)); if (! ct.isCircular()) attrs.addAll(getInheritedAttributes((XSDComplexTypeDefinition) parent)); } return attrs; } public static List getChildElements(XSDComplexTypeDefinition ct) { return getChildElements(getModelGroup(ct)); } public static List getChildElements(XSDModelGroupDefinition xsdModelGroupDefinition) { return getChildElements(xsdModelGroupDefinition.getModelGroup()); } public static XSDModelGroup getModelGroup(XSDComplexTypeDefinition cType) { XSDParticle particle = cType.getComplexType(); if (particle == null || particle.eContainer() != cType) return null; Object particleContent = particle.getContent(); XSDModelGroup group = null; if (particleContent instanceof XSDModelGroupDefinition) group = ((XSDModelGroupDefinition) particleContent).getResolvedModelGroupDefinition().getModelGroup(); else if (particleContent instanceof XSDModelGroup) group = (XSDModelGroup) particleContent; if (group == null) return null; if (group.getContents().isEmpty() || group.eResource() != cType.eResource()) { XSDComplexTypeContent content = cType.getContent(); if (content instanceof XSDParticle) group = (XSDModelGroup) ((XSDParticle) content).getContent(); } return group; } public static List getChildAttributes(XSDComplexTypeDefinition ct) { EList attrContents = ct.getAttributeContents(); List attrs = new ArrayList(); for (int i = 0; i < attrContents.size(); i++) { Object next = attrContents.get(i); if (next instanceof XSDAttributeUse) { attrs.add(((XSDAttributeUse) next).getContent().getResolvedAttributeDeclaration()); } else if (next instanceof XSDAttributeGroupDefinition) { //XSDAttributeGroupDefinition attrGroup = (XSDAttributeGroupDefinition) next; } } return attrs; } public static Image getImageWithErrorOverlay(XSDConcreteComponent input, Image baseImage, boolean isReadOnly) { Image extensionImage = getUpdatedImage(input, baseImage, isReadOnly); ImageDescriptor errorOverlay = XSDEditorPlugin.getImageDescriptor("icons/ovr16/error_ovr.gif"); //$NON-NLS-1$ if (baseImage == extensionImage) { String imageName = input.getClass().getName() + "_error_" + isReadOnly; Image newImage = XSDEditorPlugin.getDefault().getImageRegistry().get(imageName); if (newImage == null) { DecorationOverlayIcon ovr = new DecorationOverlayIcon(baseImage, errorOverlay, IDecoration.TOP_LEFT); newImage = ovr.createImage(); XSDEditorPlugin.getDefault().getImageRegistry().put(imageName, newImage); } return newImage; } else { String imageName = input.getClass().getName() + "_extension_error_" + isReadOnly; Image newImage = XSDEditorPlugin.getDefault().getImageRegistry().get(imageName); if (newImage == null) { DecorationOverlayIcon ovr = new DecorationOverlayIcon(extensionImage, errorOverlay, IDecoration.TOP_LEFT); newImage = ovr.createImage(); XSDEditorPlugin.getDefault().getImageRegistry().put(imageName, newImage); } return newImage; } } public static CCombo getNewPropertiesCombo(Composite composite, TabbedPropertySheetWidgetFactory widgetFactory, AbstractSection listener, String[] items, String helpID) { CCombo combo = widgetFactory.createCCombo(composite); combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); combo.setEditable(false); combo.setItems(items); combo.addSelectionListener(listener); PlatformUI.getWorkbench().getHelpSystem().setHelp(combo, helpID); return combo; } public static CLabel getNewPropertiesLabel(Composite composite, TabbedPropertySheetWidgetFactory widgetFactory, String labelText) { // Create label CLabel label; label = widgetFactory.createCLabel(composite, labelText); GridData data = new GridData(); data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_BEGINNING; data.grabExcessHorizontalSpace = false; label.setLayoutData(data); return label; } }