Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMickael LANOE2015-03-13 09:12:32 +0000
committerPierre-Charles David2015-03-16 08:11:05 +0000
commit978364d972ad0d8540cc69c13ecd4eabacb91ea2 (patch)
tree9834a5f68551c2609cdca4a390f16ee9898697fd
parente149d983d7d6fb7d66572ec6a173861613ad3943 (diff)
downloadorg.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>
-rw-r--r--plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/query/NotificationQuery.java41
-rw-r--r--plugins/org.eclipse.sirius/src/org/eclipse/sirius/business/internal/session/danalysis/DAnalysisSessionImpl.java69
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;
}
}
}

Back to the top