diff options
| author | Mickael LANOE | 2015-03-13 09:12:32 +0000 |
|---|---|---|
| committer | Pierre-Charles David | 2015-03-16 08:11:05 +0000 |
| commit | 978364d972ad0d8540cc69c13ecd4eabacb91ea2 (patch) | |
| tree | 9834a5f68551c2609cdca4a390f16ee9898697fd | |
| parent | e149d983d7d6fb7d66572ec6a173861613ad3943 (diff) | |
| download | org.eclipse.sirius-978364d972ad0d8540cc69c13ecd4eabacb91ea2.tar.gz org.eclipse.sirius-978364d972ad0d8540cc69c13ecd4eabacb91ea2.tar.xz org.eclipse.sirius-978364d972ad0d8540cc69c13ecd4eabacb91ea2.zip | |
[432133] Correctly detect semantic roots for XSD-based models
Fix NPE in DAnalysisSessionImpl.findSemanticRoot(Resource).
Fix NotificationQuery to detect XSD modification. The code is based on
https://bugs.eclipse.org/bugs/show_bug.cgi?id=432133#c40
Bug: 432133
Change-Id: Ibd4ce5273184ccc484279349ba798f49686f6bde
Signed-off-by: Mickael LANOE <mickael.lanoe@obeo.fr>
2 files changed, 79 insertions, 31 deletions
diff --git a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/query/NotificationQuery.java b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/query/NotificationQuery.java index 2b7de05db5..4ebdf62172 100644 --- a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/query/NotificationQuery.java +++ b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/query/NotificationQuery.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 THALES GLOBAL SERVICES. + * Copyright (c) 2011, 2015 THALES GLOBAL SERVICES. * 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 @@ -11,8 +11,12 @@ package org.eclipse.sirius.common.tools.api.query; import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EcorePackage; import com.google.common.base.Preconditions; @@ -65,11 +69,44 @@ public class NotificationQuery { private boolean isContainedThroughTransientFeature(EObject obj) { EObject current = obj; while (current.eContainer() != null) { - if (current.eContainingFeature().isTransient()) { + if (current.eContainingFeature().isTransient() && !isFeatureMap(current.eContainer())) { return true; } current = current.eContainer(); } return false; } + + /** + * Return true if the EObject is a feature map as defined in section 3.5 of + * https + * ://www.eclipse.org/modeling/emf/docs/overviews/XMLSchemaToEcoreMapping + * .pdf + * + * @param obj + * object to test + * @return true if the EObject is a feature map + */ + private boolean isFeatureMap(EObject obj) { + + EAnnotation annotation = obj.eClass().getEAnnotation("http:///org/eclipse/emf/ecore/util/ExtendedMetaData"); + if (annotation != null && annotation.getDetails() != null) { + String kind = annotation.getDetails().get("kind"); + // Is it sufficient to test kind.equals("mixed")? + if ("mixed".equals(kind)) { + // If not (or just to be safe), check if type is + // EFeatureMapEntry + + // Not exactly sure the difference between getEAllAttributes + // and getEAttributes. + EList<EAttribute> attribs = obj.eClass().getEAllAttributes(); + for (EAttribute eAttribute : attribs) { + if (eAttribute.getEType().equals(EcorePackage.eINSTANCE.getEFeatureMapEntry())) { + return true; + } + } + } + } + return false; + } } diff --git a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/business/internal/session/danalysis/DAnalysisSessionImpl.java b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/business/internal/session/danalysis/DAnalysisSessionImpl.java index 4f23151848..6ba030c977 100644 --- a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/business/internal/session/danalysis/DAnalysisSessionImpl.java +++ b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/business/internal/session/danalysis/DAnalysisSessionImpl.java @@ -601,6 +601,7 @@ public class DAnalysisSessionImpl extends DAnalysisSessionEObjectImpl implements private EObject findSemanticRoot(final Resource res) { EObject root = res.getContents().get(0); + /* * Attempt to determine if the eCore model was generated from XSD by * inspecting the annotation on the root. XSD->ECore will use the @@ -609,35 +610,45 @@ public class DAnalysisSessionImpl extends DAnalysisSessionEObjectImpl implements * Element name), and have a 'kind' of 'mixed'. */ EClass eCls = root.eClass(); - for (EAnnotation annotation : eCls.getEAnnotations()) { - boolean isExtMetadata = "http:///org/eclipse/emf/ecore/util/ExtendedMetaData".equals(annotation.getSource()); - if (isExtMetadata) { - EMap<String, String> details = annotation.getDetails(); - if (details.containsKey("name") && details.get("name").length() == 0 && details.containsKey("kind") && "mixed".equals(details.get("kind"))) { - /* - * Step over the "mixed", "xMLNSPrefixMap", and - * "xSISchemaLocation" features of the injected DocumentRoot - * found in an XSD generated ECore model Excerpts from - * https://www .eclipse.org/modeling/emf/docs/overviews/ - * XMLSchemaToEcoreMapping .pdf (section 1.5) ... The - * document root EClass looks like one corresponding to a - * mixed complex type (see section 3.4) including a "mixed" - * feature, and derived implementations for the other - * features in the class. This allows it to maintain - * comments and white space that appears in the document, - * before the root element. A document root class contains - * two more EMap features, both String to String, to record - * the namespace to prefix mappings (xMLNSPrefixMap) and - * xsi:schemaLocation mappings (xSISchemaLocation) of an XML - * instance document. - */ - for (int featureID = 0; featureID < eCls.getFeatureCount(); featureID++) { - EStructuralFeature eFeature = eCls.getEStructuralFeature(featureID); - String name = eFeature.getName(); - if (!"mixed".equals(name) && !"xMLNSPrefixMap".equals(name) && !"xSISchemaLocation".equals(name)) { - root = (EObject) root.eGet(eFeature); - break; - } + boolean isXSD = Iterables.any(eCls.getEAnnotations(), new Predicate<EAnnotation>() { + + @Override + public boolean apply(EAnnotation annotation) { + boolean isExtMetadata = "http:///org/eclipse/emf/ecore/util/ExtendedMetaData".equals(annotation.getSource()); + if (isExtMetadata) { + EMap<String, String> details = annotation.getDetails(); + if (details.containsKey("name") && details.get("name").isEmpty() && details.containsKey("kind") && "mixed".equals(details.get("kind"))) { + return true; + } + } + return false; + } + }); + + if (isXSD) { + /* + * Step over the "mixed", "xMLNSPrefixMap", and "xSISchemaLocation" + * features of the injected DocumentRoot found in an XSD generated + * ECore model Excerpts from https://www + * .eclipse.org/modeling/emf/docs/overviews/ XMLSchemaToEcoreMapping + * .pdf (section 1.5) ... The document root EClass looks like one + * corresponding to a mixed complex type (see section 3.4) including + * a "mixed" feature, and derived implementations for the other + * features in the class. This allows it to maintain comments and + * white space that appears in the document, before the root + * element. A document root class contains two more EMap features, + * both String to String, to record the namespace to prefix mappings + * (xMLNSPrefixMap) and xsi:schemaLocation mappings + * (xSISchemaLocation) of an XML instance document. + */ + for (int featureID = 0; featureID < eCls.getFeatureCount(); featureID++) { + EStructuralFeature eFeature = eCls.getEStructuralFeature(featureID); + String name = eFeature.getName(); + if (!"mixed".equals(name) && !"xMLNSPrefixMap".equals(name) && !"xSISchemaLocation".equals(name)) { + Object obj = root.eGet(eFeature); + if (obj instanceof EObject) { + root = (EObject) obj; + break; } } } |
