diff options
author | dtenev | 2011-07-04 05:53:00 +0000 |
---|---|---|
committer | dtenev | 2011-07-04 05:53:00 +0000 |
commit | f3087086d0e0df49efbe74bf7a4bcd7dca7807a1 (patch) | |
tree | b83f9b9216ac5beb72da319f10c8e8bc093ad244 | |
parent | a857f6d86e8f18ffd7a29c9c2c4a4289c484173e (diff) | |
download | org.eclipse.webtools.incubator.sieditor-gitIgnoreChanges.tar.gz org.eclipse.webtools.incubator.sieditor-gitIgnoreChanges.tar.xz org.eclipse.webtools.incubator.sieditor-gitIgnoreChanges.zip |
Apply patch from bugzilla: Bug 341179 - StackOverflow in AttributesReconcileAdapter while manually editing xml schema docgitIgnoreChanges
-rw-r--r-- | plugins/org.eclipse.wst.sse.sieditor.model/api/org/eclipse/wst/sse/sieditor/model/reconcile/adapters/AttributesReconcileAdapter.java | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/plugins/org.eclipse.wst.sse.sieditor.model/api/org/eclipse/wst/sse/sieditor/model/reconcile/adapters/AttributesReconcileAdapter.java b/plugins/org.eclipse.wst.sse.sieditor.model/api/org/eclipse/wst/sse/sieditor/model/reconcile/adapters/AttributesReconcileAdapter.java index ac2cd1b..635b75b 100644 --- a/plugins/org.eclipse.wst.sse.sieditor.model/api/org/eclipse/wst/sse/sieditor/model/reconcile/adapters/AttributesReconcileAdapter.java +++ b/plugins/org.eclipse.wst.sse.sieditor.model/api/org/eclipse/wst/sse/sieditor/model/reconcile/adapters/AttributesReconcileAdapter.java @@ -36,11 +36,12 @@ import org.eclipse.xsd.impl.XSDImportImpl; import org.eclipse.xsd.util.XSDConstants; import org.w3c.dom.Attr; import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; import org.eclipse.wst.sse.sieditor.model.reconcile.adapters.componentsource.IConcreteComponentSource; import org.eclipse.wst.sse.sieditor.model.utils.EmfXsdUtils; - /** * Subclass of the {@link AbstractModelReconcileAdapter}. This adapter is * responsible for the fixing of problems caused by DOM element attributes @@ -171,11 +172,23 @@ public class AttributesReconcileAdapter extends AbstractModelReconcileAdapter { final String prefix = getPrefix(attr); if (newValue == null) { /* - * the new value is null, so we need to remove the prefix/namespace + * The new value is null, so we need to remove the prefix/namespace * from the EMF model map. In some cases (on undo/redo) the EMF - * didn't do that + * didn't do that. + * + * We also need to check the number of times this attribute is + * appearing in the schema element's body, because we don't want to + * update the map if more than one attribute with the same name + * exists. This is causing an unwanted DOM update of all the + * attribute values with the same name, instead of just the + * currently edited one. + * + * Please note here that the currently edited attribute is already + * removed from DOM and that's why we check if the current count is + * zero */ - if (xsdSchema.getQNamePrefixToNamespaceMap().containsKey(prefix)) { + if (countAttributeWithSameName(attr.getName(), xsdSchema.getElement()) == 0 + && xsdSchema.getQNamePrefixToNamespaceMap().containsKey(prefix)) { xsdSchema.getQNamePrefixToNamespaceMap().remove(prefix); } /* @@ -188,11 +201,14 @@ public class AttributesReconcileAdapter extends AbstractModelReconcileAdapter { * we have non-null value, so we must be updating existing * namespace, or adding a new one */ - if (/* - * XSDConstants.isSchemaForSchemaNamespace(attr.getValue()) && - */!attr.getValue().equals(xsdSchema.getQNamePrefixToNamespaceMap().get(prefix))) { - // add the namespace to the map - xsdSchema.getQNamePrefixToNamespaceMap().put(prefix, attr.getValue()); + final String newNamespaceValue = attr.getValue(); + final String oldNamespaceValue = xsdSchema.getQNamePrefixToNamespaceMap().get(prefix); + + // we should not be updating the map when there are more than one + // attribute with same name in the element + if (countAttributeWithSameName(attr.getName(), xsdSchema.getElement()) <= 1 + && !newNamespaceAndOldNamespaceAreTheSame(newNamespaceValue, oldNamespaceValue)) { + xsdSchema.getQNamePrefixToNamespaceMap().put(prefix, newNamespaceValue); } /* * notify for the change anyway, since we want to run the @@ -202,6 +218,37 @@ public class AttributesReconcileAdapter extends AbstractModelReconcileAdapter { } } + /** + * @return the number of times the given attribute name is appearing in the + * element attributes collection. + */ + private int countAttributeWithSameName(final String attributeName, final Element element) { + final NamedNodeMap attributes = element.getAttributes(); + final int attributesSize = attributes.getLength(); + + int count = 0; + for (int i = 0; i < attributesSize; i++) { + final Node item = attributes.item(i); + if (attributeName.equals(item.getNodeName())) { + count++; + } + } + return count; + } + + private boolean newNamespaceAndOldNamespaceAreTheSame(final String newNamespaceValue, final String oldNamespaceValue) { + if (newNamespaceValue == null && oldNamespaceValue == null) { + return true; + } + if (oldNamespaceValue == null && newNamespaceValue.isEmpty()) { + // generally, "null" namespace and empty one will be treated the + // same + return true; + } + // XSDConstants.isSchemaForSchemaNamespace(attr.getValue()) && + return newNamespaceValue.equals(oldNamespaceValue); + } + private void processParameterOrderAttribute(final INodeNotifier notifier, final String attributeName) { if (WSDLConstants.PARAMETER_ORDER_ATTRIBUTE.equals(attributeName)) { /* we need to check if we are updating a part name */ @@ -300,7 +347,7 @@ public class AttributesReconcileAdapter extends AbstractModelReconcileAdapter { final EObject eObject = concreteComponentSource.getConcreteComponentFor((Element) notifier); ((XSDFeature)eObject).setLexicalValue((String)newValue); eObject.eNotify(new ENotificationImpl((InternalEObject) eObject, Notification.SET, XSDPackage.XSD_FEATURE__VALUE, null, - newValue)); + newValue)); } } } |