Community
Participate
Working Groups
Build Identifier: M20110210-1200 When using the XMLNSPrefixMap that is created in some XML Schema based Ecore models, I would like to selectively remove certain entries from the map by first getting an iterator on the entrySet and then using Iterator.remove(). Under certain circumstances, the entry returned by iterator.next() is null. Reproducible: Always Steps to Reproduce: 1. Create a new XMLTypeDocumentRoot instance using XMLTypeFactory 2. Add entries to its XMLNSPrefixMap 3. Get an iterator on entrySet 4. Iterate over entries and selectively remove using iterator.remove() XMLTypeDocumentRoot root = XMLTypeFactory.eINSTANCE.createXMLTypeDocumentRoot(); EMap<String, String> map = root.getXMLNSPrefixMap(); map.put("_1", "urn:hl7-org:v3"); map.put("ns0", "http://www.openhealthtools.org/mdht/uml/cda/toc"); map.put("ns1", "http://www.openhealthtools.org/mdht/uml/cda/hitsp"); map.put("ns2", "http://www.openhealthtools.org/mdht/uml/cda/ccd"); map.put("ns3", "http://www.openhealthtools.org/mdht/uml/cda/ihe"); map.put("xsi", "http://www.w3.org/2001/XMLSchema-instance"); map.put("ns4", "http://www.openhealthtools.org/mdht/uml/hl7/datatypes"); System.out.println("entrySet size before: " + map.entrySet().size()); System.out.println("entrySet before: " + map.entrySet()); Iterator<Entry<String, String>> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next(); if (entry.getKey().equals("ns3")) { System.out.println("Attempting to remove: " + entry); iterator.remove(); System.out.println("Successfully removed: " + entry); } } System.out.println("entrySet size after: " + map.entrySet().size()); System.out.println("entrySet after: " + map.entrySet()); In this example, I add 7 entries to the prefix map. I would expect that when iterating over the entry set that every entry would be non-null but depending on what I select to remove, I sometimes get an NPE. The behavior also seems to depend on the cardinality of the entrySet. Odd cardinality fails, even cardinality succeeds.
One possible workaround is to collect the keys for removal and then remove them afterwards with removeKey: System.out.println("entrySet size before: " + map.entrySet().size()); System.out.println("entrySet before: " + map.entrySet()); List<String> keys = new ArrayList<String>(); for (Map.Entry<String, String> entry : map.entrySet()) { if (entry.getKey().equals("ns3")) { keys.add(entry.getKey()); } } for (String key : keys) { System.out.println("Attempting to remove entry with key: " + key); map.removeKey(key); System.out.println("Successfully removed entry with key: " + key); } System.out.println("entrySet size after: " + map.entrySet().size()); System.out.println("entrySet after: " + map.entrySet());
Created attachment 205443 [details] Patches to address the issue. After the remove, if the next entry is in the same slot's list, the index into that slot needs to be reduced...
Ed: Thanks for the quick response! JT
The fixes are committed to CVS for 2.8.
The changes are available in builds.