// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.fixAddresses;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.util.ArrayList;
import java.util.List;
import org.openstreetmap.josm.command.ChangePropertyCommand;
import org.openstreetmap.josm.command.Command;
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;
import org.openstreetmap.josm.tools.CheckParameterUtil;
/**
* The class OSMEntityBase provides a base implementation for the {@link IOSMEntity} interface.
*
* The implementation comprises
* <ol>
* <li>Handle change listeners
* <li>Links the corresponding OSM object
* <li>Tag handling
* </ol>
*/
public class OSMEntityBase implements IOSMEntity, Comparable<IOSMEntity> {
public static final String ANONYMOUS = tr("No name");
private static List<IAddressEditContainerListener> containerListeners = new ArrayList<>();
private List<ICommandListener> cmdListeners = new ArrayList<>();
protected OsmPrimitive osmObject;
public OSMEntityBase(OsmPrimitive osmObject) {
super();
this.osmObject = osmObject;
}
/**
* @param osmObject the osmObject to set
*/
protected void setOsmObject(OsmPrimitive osmObject) {
CheckParameterUtil.ensureParameterNotNull(osmObject, "osmObject");
this.osmObject = osmObject;
}
/**
* Adds a change listener.
* @param listener change listener
*/
public static void addChangedListener(IAddressEditContainerListener listener) {
CheckParameterUtil.ensureParameterNotNull(listener, "listener");
containerListeners.add(listener);
}
/**
* Removes a change listener.
* @param listener change listener
*/
public static void removeChangedListener(IAddressEditContainerListener listener) {
CheckParameterUtil.ensureParameterNotNull(listener, "listener");
containerListeners.remove(listener);
}
/**
* Notifies clients that the address container changed.
*/
protected static void fireEntityChanged(IOSMEntity entity) {
CheckParameterUtil.ensureParameterNotNull(entity, "entity");
for (IAddressEditContainerListener listener : containerListeners) {
listener.entityChanged(entity);
}
}
/**
* Adds a command listener.
* @param listener command listener
*/
@Override
public void addCommandListener(ICommandListener listener) {
CheckParameterUtil.ensureParameterNotNull(listener, "listener");
cmdListeners.add(listener);
}
/**
* Removes a command listener.
* @param listener command listener
*/
@Override
public void removeCommandListener(ICommandListener listener) {
CheckParameterUtil.ensureParameterNotNull(listener, "listener");
cmdListeners.remove(listener);
}
/**
* Notifies clients that an entity has issued a command.
*
* @param source the entity that issued the command.
* @param command the command to execute.
*/
protected void fireCommandIssued(Command command) {
CheckParameterUtil.ensureParameterNotNull(command, "command");
if (cmdListeners.size() == 0) {
throw new RuntimeException("Object has no TX context: " + this);
}
for (ICommandListener l : cmdListeners) {
l.commandIssued(this, command);
}
}
@Override
public OsmPrimitive getOsmObject() {
return osmObject;
}
@Override
public List<IOSMEntity> getChildren() {
return null;
}
@Override
/**
* Gets the name of the street or ANONYMOUS, if street has no name.
* @return
*/
public String getName() {
if (TagUtils.hasNameTag(osmObject)) {
return TagUtils.getNameValue(osmObject);
}
return "";
}
@Override
public boolean hasName() {
return TagUtils.hasNameTag(osmObject);
}
/**
* Internal helper method which changes the given property and
* puts the appropriate command {@link src.org.openstreetmap.josm.command.Command}
* into the undo/redo queue.
* @param tag The tag to change.
* @param newValue The new value for the tag.
* @param cmd The surrounding command sequence
*/
protected void setOSMTag(String tag, String newValue) {
CheckParameterUtil.ensureParameterNotNull(tag, "tag");
if (osmObject != null) {
String existingValue = osmObject.get(tag);
// Bugfix #9047: Keep existing values
if (!StringUtils.isNullOrEmpty(existingValue)) {
return;
}
if ((osmObject.hasKey(tag) && newValue == null) || newValue != null) {
fireCommandIssued(new ChangePropertyCommand(osmObject, tag, newValue));
fireEntityChanged(this);
}
}
}
/**
* Removes the given tag from the OSM object.
*
* @param tag the tag
*/
protected void removeOSMTag(String tag) {
CheckParameterUtil.ensureParameterNotNull(tag, "tag");
setOSMTag(tag, null); // a value of null removes the tag
}
@Override
public String toString() {
if (hasName()) {
return this.getClass().getName() + ": " + getName();
}
return this.getClass().getName() + ": " + ANONYMOUS;
}
@Override
public int compareTo(IOSMEntity o) {
if (o == null || !(o instanceof OSMEntityBase)) return -1;
return this.getName().compareTo(o.getName());
}
@Override
public void visit(IAllKnowingTrashHeap trashHeap, IProblemVisitor visitor) {
// do nothing
}
@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;
}
}