Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressEditContainer.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressEditContainer.java	(revision 23960)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressEditContainer.java	(revision 23961)
@@ -63,4 +63,9 @@
 	private List<AddressNode> unresolvedAddresses = new ArrayList<AddressNode>(100);
 	private List<AddressNode> incompleteAddresses = new ArrayList<AddressNode>(100);
+	
+	private HashMap<String, StreetNode> shadowStreetDict = new HashMap<String, StreetNode>(100); 
+	private List<AddressNode> shadowUnresolvedAddresses = new ArrayList<AddressNode>(100);
+	private List<AddressNode> shadowIncompleteAddresses = new ArrayList<AddressNode>(100);
+	
 	private HashMap<String, AddressNode> addressCache = new HashMap<String, AddressNode>();
 	private HashSet<Node> visitedNodes = new HashSet<Node>();
@@ -145,9 +150,9 @@
 			if (!assignAddressToStreet(aNode)) {
 				// Assignment failed: Street is not known (yet) -> add to 'unresolved' list 
-				unresolvedAddresses.add(aNode);
+				shadowUnresolvedAddresses.add(aNode);
 			}
 
 			if (!aNode.isComplete()) {
-				incompleteAddresses.add(aNode);
+				shadowIncompleteAddresses.add(aNode);
 			}
 		} else {
@@ -181,4 +186,9 @@
 	}
 
+	/**
+	 * Creates the node from an OSM way instance.
+	 *
+	 * @param w the w
+	 */
 	private void createNodeFromWay(Way w) {
 		StreetSegmentNode newSegment = NodeFactory.createNodeFromWay(w);
@@ -189,9 +199,9 @@
 			
 			StreetNode sNode = null;
-			if (streetDict.containsKey(name)) {
-				sNode = streetDict.get(name);
-			} else {
+			if (shadowStreetDict.containsKey(name)) { // street exists?
+				sNode = shadowStreetDict.get(name);
+			} else { // new street name -> add to dict
 				sNode = new StreetNode(w);
-				streetDict.put(name, sNode);
+				shadowStreetDict.put(name, sNode);
 			}
 			
@@ -242,14 +252,28 @@
 	}
 	
+	/**
+	 * Gets the unresolved (addresses without valid street name) addresses.
+	 *
+	 * @return the unresolved addresses
+	 */
 	public List<AddressNode> getUnresolvedAddresses() {
 		return unresolvedAddresses;
 	}
 
+	/**
+	 * Gets the list with incomplete addresses.
+	 *
+	 * @return the incomplete addresses
+	 */
 	public List<AddressNode> getIncompleteAddresses() {
 		return incompleteAddresses;
 	}
 
-	public List<StreetNode> getStreetList() {
-		
+	/**
+	 * Gets the street list.
+	 *
+	 * @return the street list
+	 */
+	public List<StreetNode> getStreetList() {		
 		ArrayList<StreetNode> sortedList = new ArrayList<StreetNode>(streetDict.values());
 		Collections.sort(sortedList);
@@ -257,8 +281,16 @@
 	}
 
+	/**
+	 * Gets all addresses without valid street.
+	 * @return
+	 */
 	public List<AddressNode> getUnresolvedItems() {
 		return unresolvedAddresses;
 	}
 
+	/**
+	 * Gets the tags used in the data layer.
+	 * @return
+	 */
 	public HashSet<String> getTags() {
 		return tags;
@@ -363,22 +395,33 @@
 		if (osmData == null || osmData.isEmpty())
 			return;
-		
-		clearData();
-		for (OsmPrimitive osmPrimitive : osmData) {
-			osmPrimitive.visit(this);
-		}
-		
-		resolveAddresses();
-		
-		Collections.sort(incompleteAddresses);
-		Collections.sort(unresolvedAddresses);
-		
-		fireContainerChanged();
+
+		synchronized (this) {
+			clearData();
+			for (OsmPrimitive osmPrimitive : osmData) {
+				osmPrimitive.visit(this);
+			}
+
+			resolveAddresses();
+			// sort lists
+			Collections.sort(shadowIncompleteAddresses);
+			Collections.sort(shadowIncompleteAddresses);
+
+			// put results from shadow copy into real lists
+			incompleteAddresses = new ArrayList<AddressNode>(shadowIncompleteAddresses);
+			unresolvedAddresses = new ArrayList<AddressNode>(shadowUnresolvedAddresses);
+			streetDict = new HashMap<String, StreetNode>(shadowStreetDict);
+			// remove temp data
+			shadowStreetDict.clear();
+			shadowUnresolvedAddresses.clear();
+			shadowIncompleteAddresses.clear();
+			// update clients
+			fireContainerChanged();
+		}
 	}
 	
 	public void clearData() {
-		streetDict.clear();
-		unresolvedAddresses.clear();
-		incompleteAddresses.clear();
+		shadowStreetDict.clear();
+		shadowUnresolvedAddresses.clear();
+		shadowIncompleteAddresses.clear();
 		visitedNodes.clear();
 		visitedWays.clear();
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressFinderThread.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressFinderThread.java	(revision 23960)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressFinderThread.java	(revision 23961)
@@ -14,5 +14,10 @@
 package org.openstreetmap.josm.plugins.fixAddresses;
 
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.ConcurrentModificationException;
+import java.util.List;
 
 import org.openstreetmap.josm.Main;
@@ -24,55 +29,36 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.io.OsmTransferException;
+import org.xml.sax.SAXException;
 
-public class AddressFinderThread implements Runnable, Visitor {
-	private AddressNode addressNode;
+public class AddressFinderThread extends PleaseWaitRunnable implements Visitor {
+	private AddressEditContainer container;
 	private double minDist;
 	private Node nearestNode;
-	private Node osmAddressNode;
+	private AddressNode curAddressNode;
 	private boolean isRunning = false;
 	private String nearestName = null;
 	private String currentName = null;
+	private boolean cancelled;
 	
 	/**
-	 * @param addressNode
+	 * @param AddressEditContainer
 	 */
-	public AddressFinderThread(AddressNode addressNode) {
-		super();
-		setAddressNode(addressNode);		
+	public AddressFinderThread(AddressEditContainer AddressEditContainer, String title) {
+		super(title != null ? title : tr("Searching"));
+		setAddressEditContainer(AddressEditContainer);		
 	}
 
-	public AddressFinderThread() {
-		this(null);
-	}
-
-	public void setAddressNode(AddressNode addressNode) {
+	public void setAddressEditContainer(AddressEditContainer AddressEditContainer) {
 		if (isRunning) {
 			throw new ConcurrentModificationException();
 		}
-		this.addressNode = addressNode;
-		if (addressNode != null && addressNode.getOsmObject() instanceof Node) {
-			osmAddressNode = (Node) addressNode.getOsmObject();
-		}
+		this.container = AddressEditContainer;		
 	}
 
-	public AddressNode getAddressNode() {
-		return addressNode;
+	public AddressEditContainer getAddressEditContainer() {
+		return container;
 	}
-	
-	public double getMinDist() {
-		return minDist;
-	}
-
-	public Node getNearestNode() {
-		return nearestNode;
-	}
-
-	/**
-	 * @return the nearestName
-	 */
-	public String getGuessedName() {
-		return nearestName;
-	}
-
 	/**
 	 * @return the isRunning
@@ -82,32 +68,17 @@
 	}
 
-	@Override
-	public void run() {
-		if (Main.main.getCurrentDataSet() == null || osmAddressNode == null) return;
-
-		isRunning = true;
-		synchronized(this) {			
-			try {
-				minDist = Double.MAX_VALUE;
-				for (OsmPrimitive osmPrimitive : Main.main.getCurrentDataSet().getWays()) {
-					osmPrimitive.visit(this);
-				}
-				
-				if (nearestName != null) {
-					addressNode.setGuessedStreetName(nearestName);
-				}
-			} finally {
-				isRunning = false;
-			}
-		}
-	}
-
-
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.data.osm.visitor.Visitor#visit(org.openstreetmap.josm.data.osm.Node)
+	 */
 	@Override
 	public void visit(Node n) {
 		if (n == null) return;
+		if (curAddressNode == null) return;
 
 		// If the coordinates are null, we are screwed anyway
-		double dist = osmAddressNode.getCoor().greatCircleDistance(n.getCoor());
+		LatLon ll = curAddressNode.getCoor();
+		if (ll == null) return;
+		
+		double dist = ll.greatCircleDistance(n.getCoor());
 		
 		if (dist < minDist) {
@@ -118,5 +89,7 @@
 	}
 
-
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.data.osm.visitor.Visitor#visit(org.openstreetmap.josm.data.osm.Way)
+	 */
 	@Override
 	public void visit(Way w) {
@@ -128,21 +101,88 @@
 		for (Node node : w.getNodes()) {
 			visit(node);
-		}
-		
+		}		
 	}
 
-
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.data.osm.visitor.Visitor#visit(org.openstreetmap.josm.data.osm.Relation)
+	 */
 	@Override
 	public void visit(Relation e) {
-		// TODO Auto-generated method stub
-		
+		// nothing to do yet		
 	}
 
-
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.data.osm.visitor.Visitor#visit(org.openstreetmap.josm.data.osm.Changeset)
+	 */
 	@Override
 	public void visit(Changeset cs) {
-		// TODO Auto-generated method stub
-		
+		// nothing to do yet
 	}
 
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.gui.PleaseWaitRunnable#cancel()
+	 */
+	@Override
+	protected void cancel() {
+		cancelled = true;		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.gui.PleaseWaitRunnable#finish()
+	 */
+	@Override
+	protected void finish() {
+		// nothing to do yet
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.gui.PleaseWaitRunnable#realRun()
+	 */
+	@Override
+	protected void realRun() throws SAXException, IOException,
+			OsmTransferException {
+		if (Main.main.getCurrentDataSet() == null || container == null) return;
+
+		isRunning = true;
+		cancelled = false;
+		
+		progressMonitor.subTask(tr("Searching") + "...");
+		
+		try {
+			progressMonitor.setTicksCount(container.getNumberOfUnresolvedAddresses());
+			
+			List<AddressNode> shadowCopy = new ArrayList<AddressNode>(container.getUnresolvedAddresses());
+			for (AddressNode aNode : shadowCopy) {					
+				minDist = Double.MAX_VALUE;
+				curAddressNode = aNode;
+				
+				// check for cancel
+				if (cancelled) {
+					break;
+				}
+
+				// visit osm data
+				for (OsmPrimitive osmPrimitive : Main.main.getCurrentDataSet().getWays()) {
+					if (cancelled) {
+						break;
+					}
+					osmPrimitive.visit(this);
+
+				}
+				
+				// we found something
+				if (nearestName != null) {
+					progressMonitor.subTask(String.format("%s: %s (%4.1f m)", tr("Guess"), nearestName, minDist));
+					aNode.setGuessedStreetName(nearestName);
+					nearestName = null;
+				}
+				// report progress
+				progressMonitor.worked(1);				
+			}
+			// request container update
+			container.invalidate();
+		} finally {
+			isRunning = false;
+		}
+	}
 }
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressNode.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressNode.java	(revision 23960)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/AddressNode.java	(revision 23961)
@@ -75,5 +75,5 @@
 	public void setGuessedStreetName(String guessedStreetName) {
 		this.guessedStreetName = guessedStreetName;
-		fireEntityChanged(this);
+		//fireEntityChanged(this);
 	}
 	
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/INodeEntity.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/INodeEntity.java	(revision 23960)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/INodeEntity.java	(revision 23961)
@@ -16,5 +16,13 @@
 import java.util.List;
 
+import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+
+/**
+ * Base interface for all node entities. A node entity is a lightweight wrapper
+ * around OSM objects in order to ease up some tasks like tag handling.
+ * @author Oliver Wieland <oliver.wieland@online.de>
+ * 
+ */
 
 public interface INodeEntity extends Comparable<INodeEntity> {
@@ -42,3 +50,11 @@
 	 */
 	public List<INodeEntity> getChildren();
+	
+	/**
+	 * Gets the coordinate of the node. If the the underlying object is a
+	 * node, it just returns the node coordinate. For ways and areas, this 
+	 * method returns the coordinate of the center (balance point). 
+	 * @return
+	 */
+	public LatLon getCoor();
 }
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/NodeEntityBase.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/NodeEntityBase.java	(revision 23960)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/NodeEntityBase.java	(revision 23961)
@@ -21,6 +21,9 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.command.ChangeCommand;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.BBox;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Way;
 
 public class NodeEntityBase implements INodeEntity, Comparable<INodeEntity> {
@@ -126,4 +129,7 @@
 	}
 
+	/* (non-Javadoc)
+	 * @see java.lang.Comparable#compareTo(java.lang.Object)
+	 */
 	@Override
 	public int compareTo(INodeEntity o) {
@@ -132,4 +138,22 @@
 	}
 
-	
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.fixAddresses.INodeEntity#getCoor()
+	 */
+	@Override
+	public LatLon getCoor() {
+		OsmPrimitive osm = getOsmObject();
+		if (osm == null) return null;
+		
+		if (osm instanceof Node) {
+			return ((Node)osm).getCoor();
+		// way: return center
+		} else if (osm instanceof Way) {
+			Way w = (Way) osm;
+			BBox bb = w.getBBox();
+			return bb.getBottomRight().getCenter(bb.getTopLeft());
+		}
+		// relations??
+		return null;
+	}
 }
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AddressEditTableModel.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AddressEditTableModel.java	(revision 23960)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/AddressEditTableModel.java	(revision 23961)
@@ -36,10 +36,14 @@
 	@Override
 	public void containerChanged(AddressEditContainer container) {
-		fireTableDataChanged();
+		fireTableDataChanged(); // update model
 	}
 
 	@Override
 	public void entityChanged(INodeEntity entity) {
-		fireTableDataChanged();
+		int row = getRowOfEntity(entity);
+		if (row != -1) { // valid row? -> update model
+			System.out.println("Update row " + row);
+			fireTableRowsUpdated(row, row);
+		} // else we don't do anything
 	}
 	
@@ -50,3 +54,10 @@
 	 */
 	public abstract INodeEntity getEntityOfRow(int row);
+	
+	/**
+	 * Gets the row for the given node entity or -1; if the model does not contain the entity.
+	 * @param entity The entity to get the row for.
+	 * @return
+	 */
+	public abstract int getRowOfEntity(INodeEntity entity);
 }
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/GuessAddressDataAction.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/GuessAddressDataAction.java	(revision 23960)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/GuessAddressDataAction.java	(revision 23961)
@@ -16,7 +16,7 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.util.ArrayList;
 import java.util.List;
 
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.plugins.fixAddresses.AddressEditContainer;
 import org.openstreetmap.josm.plugins.fixAddresses.AddressFinderThread;
@@ -47,4 +47,7 @@
 	}
 
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.fixAddresses.gui.AbstractAddressEditAction#updateEnabledState(org.openstreetmap.josm.plugins.fixAddresses.AddressEditContainer)
+	 */
 	@Override
 	protected void updateEnabledState(AddressEditContainer container) {
@@ -52,4 +55,7 @@
 	}
 
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.fixAddresses.gui.AbstractAddressEditAction#addressEditActionPerformed(org.openstreetmap.josm.plugins.fixAddresses.AddressEditContainer)
+	 */
 	@Override
 	public void addressEditActionPerformed(AddressEditContainer container) {
@@ -60,4 +66,7 @@
 	}
 
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.fixAddresses.gui.AbstractAddressEditAction#addressEditActionPerformed(org.openstreetmap.josm.plugins.fixAddresses.gui.AddressEditSelectionEvent)
+	 */
 	@Override
 	public void addressEditActionPerformed(AddressEditSelectionEvent ev) {
@@ -65,5 +74,5 @@
 		
 		// guess tags for selected addresses only
-		internalGuessAddresses(ev.getSelectedUnresolvedAddresses());
+		internalGuessAddresses(ev.getSelectedUnresolvedAddresses());		
 	}
 	
@@ -73,35 +82,5 @@
 	 */
 	private void internalGuessAddresses(List<AddressNode> nodes) {
-		// setup thread pool
-		for (int i = 0; i < threads.length; i++) {
-			threads[i] = new AddressFinderThread();
-		}
-		
-		// work on a shadowed copy
-		List<AddressNode> addrNodes = new ArrayList<AddressNode>(nodes);
-		for (AddressNode aNode : addrNodes) {
-			if (aNode.hasStreetName()) continue;
-			
-			while(!scheduleNode(aNode)) {
-				try {
-					Thread.sleep(100);
-				} catch (InterruptedException e) {
-					return;
-				}
-			}
-		}
-		container.containerChanged(container);
+		Main.worker.submit(new AddressFinderThread(container, tr("Guess street names")));		
 	}
-
-	private boolean scheduleNode(AddressNode aNode) {
-		for (int i = 0; i < threads.length; i++) {
-			if (!threads[i].isRunning()) {
-				threads[i].setAddressNode(aNode);
-				threads[i].run();
-				return true;
-			}
-		}
-		return false;
-	}
-
 }
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/IncompleteAddressesTableModel.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/IncompleteAddressesTableModel.java	(revision 23960)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/IncompleteAddressesTableModel.java	(revision 23961)
@@ -105,8 +105,17 @@
 			return null;
 		}
-		if (row < 0 || row > addressContainer.getNumberOfIncompleteAddresses()) {
+		if (row < 0 || row >= addressContainer.getNumberOfIncompleteAddresses()) {
 			return null;
 		}
 		return addressContainer.getIncompleteAddresses().get(row);
 	}
+
+	@Override
+	public int getRowOfEntity(INodeEntity entity) {
+		if (addressContainer == null || addressContainer.getIncompleteAddresses() == null) {
+			return -1;
+		}
+		
+		return addressContainer.getIncompleteAddresses().indexOf(entity);
+	}
 }
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/StreetTableModel.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/StreetTableModel.java	(revision 23960)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/StreetTableModel.java	(revision 23961)
@@ -111,8 +111,17 @@
 			return null;
 		}
-		if (row < 0 || row > addressContainer.getNumberOfStreets()) {
+		if (row < 0 || row >= addressContainer.getNumberOfStreets()) {
 			return null;
 		}
 		return addressContainer.getStreetList().get(row);	
 	}
+	
+	@Override
+	public int getRowOfEntity(INodeEntity entity) {
+		if (addressContainer == null || addressContainer.getStreetList() == null) {
+			return -1;
+		}
+		
+		return addressContainer.getStreetList().indexOf(entity);
+	}
 }
Index: /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/UnresolvedAddressesTableModel.java
===================================================================
--- /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/UnresolvedAddressesTableModel.java	(revision 23960)
+++ /applications/editors/josm/plugins/FixAddresses/src/org/openstreetmap/josm/plugins/fixAddresses/gui/UnresolvedAddressesTableModel.java	(revision 23961)
@@ -147,8 +147,17 @@
 			return null;
 		}
-		if (row < 0 || row > addressContainer.getNumberOfUnresolvedAddresses()) {
+		if (row < 0 || row >= addressContainer.getNumberOfUnresolvedAddresses()) {
 			return null;
 		}
 		return addressContainer.getUnresolvedAddresses().get(row);	
 	}
+	
+	@Override
+	public int getRowOfEntity(INodeEntity entity) {
+		if (addressContainer == null || addressContainer.getUnresolvedAddresses() == null) {
+			return -1;
+		}
+		
+		return addressContainer.getUnresolvedAddresses().indexOf(entity);
+	}
 }
