// This software is released into the Public Domain. See copying.txt for details.
package org.openstreetmap.osmosis.core.domain.v0_6;
import java.util.Collection;
import java.util.Date;
import org.openstreetmap.osmosis.core.domain.common.SimpleTimestampContainer;
import org.openstreetmap.osmosis.core.domain.common.TimestampContainer;
import org.openstreetmap.osmosis.core.store.StoreClassRegister;
import org.openstreetmap.osmosis.core.store.StoreReader;
import org.openstreetmap.osmosis.core.store.StoreWriter;
import org.openstreetmap.osmosis.core.util.FixedPrecisionCoordinateConvertor;
/**
* A data class representing a single OSM node.
*
* @author Brett Henderson
*/
public class Node extends Entity implements Comparable<Node> {
private double latitude;
private double longitude;
/**
* Creates a new instance.
*
* @param id
* The unique identifier.
* @param version
* The version of the entity.
* @param timestamp
* The last updated timestamp.
* @param user
* The user that last modified this entity.
* @param changesetId
* The id of the changeset that this version of the entity was created by.
* @param latitude
* The geographic latitude.
* @param longitude
* The geographic longitude.
* @deprecated As of 0.40, replaced by Node(entityData, latitude, longitude).
*/
public Node(
long id, int version, Date timestamp, OsmUser user, long changesetId, double latitude, double longitude) {
// Chain to the more-specific constructor
this(id, version, new SimpleTimestampContainer(timestamp), user, changesetId, latitude, longitude);
}
/**
* Creates a new instance.
*
* @param id
* The unique identifier.
* @param version
* The version of the entity.
* @param timestampContainer
* The container holding the timestamp in an alternative timestamp representation.
* @param user
* The name of the user that last modified this entity.
* @param changesetId
* The id of the changeset that this version of the entity was created by.
* @param latitude
* The geographic latitude.
* @param longitude
* The geographic longitude.
* @deprecated As of 0.40, replaced by Node(entityData, latitude, longitude).
*/
public Node(long id, int version, TimestampContainer timestampContainer, OsmUser user, long changesetId,
double latitude, double longitude) {
super(id, version, timestampContainer, user, changesetId);
init(latitude, longitude);
}
/**
* Creates a new instance.
*
* @param entityData
* The common entity data.
* @param latitude
* The geographic latitude.
* @param longitude
* The geographic longitude.
*/
public Node(CommonEntityData entityData, double latitude, double longitude) {
super(entityData);
init(latitude, longitude);
}
/**
* Creates a new instance.
*
* @param id
* The unique identifier.
* @param version
* The version of the entity.
* @param timestamp
* The last updated timestamp.
* @param user
* The user that last modified this entity.
* @param changesetId
* The id of the changeset that this version of the entity was created by.
* @param tags
* The tags to apply to the object.
* @param latitude
* The geographic latitude.
* @param longitude
* The geographic longitude.
* @deprecated As of 0.40, replaced by Node(entityData, latitude, longitude).
*/
public Node(long id, int version, Date timestamp, OsmUser user, long changesetId, Collection<Tag> tags,
double latitude, double longitude) {
// Chain to the more-specific constructor
this(id, version, new SimpleTimestampContainer(timestamp), user, changesetId, tags, latitude, longitude);
}
/**
* Creates a new instance.
*
* @param id
* The unique identifier.
* @param version
* The version of the entity.
* @param timestampContainer
* The container holding the timestamp in an alternative timestamp representation.
* @param user
* The name of the user that last modified this entity.
* @param changesetId
* The id of the changeset that this version of the entity was created by.
* @param tags
* The tags to apply to the object.
* @param latitude
* The geographic latitude.
* @param longitude
* The geographic longitude.
* @deprecated As of 0.40, replaced by Node(entityData, latitude, longitude).
*/
public Node(long id, int version, TimestampContainer timestampContainer, OsmUser user, long changesetId,
Collection<Tag> tags, double latitude, double longitude) {
super(id, version, timestampContainer, user, changesetId, tags);
init(latitude, longitude);
}
/**
* Creates a new instance.
*
* @param originalNode
* The node to clone from.
*/
private Node(Node originalNode) {
super(originalNode);
init(originalNode.latitude, originalNode.longitude);
}
/**
* Initializes non-collection attributes.
*
* @param newLatitude
* The geographic latitude.
* @param newLongitude
* The geographic longitude.
*/
private void init(double newLatitude, double newLongitude) {
this.latitude = newLatitude;
this.longitude = newLongitude;
}
/**
* Creates a new instance.
*
* @param sr
* The store to read state from.
* @param scr
* Maintains the mapping between classes and their identifiers within the store.
*/
public Node(StoreReader sr, StoreClassRegister scr) {
super(sr, scr);
this.latitude = FixedPrecisionCoordinateConvertor.convertToDouble(sr.readInteger());
this.longitude = FixedPrecisionCoordinateConvertor.convertToDouble(sr.readInteger());
}
/**
* {@inheritDoc}
*/
@Override
public void store(StoreWriter sw, StoreClassRegister scr) {
super.store(sw, scr);
sw.writeInteger(FixedPrecisionCoordinateConvertor.convertToFixed(latitude));
sw.writeInteger(FixedPrecisionCoordinateConvertor.convertToFixed(longitude));
}
/**
* {@inheritDoc}
*/
@Override
public EntityType getType() {
return EntityType.Node;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object o) {
if (o instanceof Node) {
return compareTo((Node) o) == 0;
} else {
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
/*
* As per the hashCode definition, this doesn't have to be unique it just has to return the
* same value for any two objects that compare equal. Using both id and version will provide
* a good distribution of values but is simple to calculate.
*/
return (int) getId() + getVersion();
}
/**
* Compares this node to the specified node. The node comparison is based on
* a comparison of id, version, latitude, longitude, timestamp and tags in
* that order.
*
* @param comparisonNode
* The node to compare to.
* @return 0 if equal, < 0 if considered "smaller", and > 0 if
* considered "bigger".
*/
public int compareTo(Node comparisonNode) {
if (this.getId() < comparisonNode.getId()) {
return -1;
}
if (this.getId() > comparisonNode.getId()) {
return 1;
}
if (this.getVersion() < comparisonNode.getVersion()) {
return -1;
}
if (this.getVersion() > comparisonNode.getVersion()) {
return 1;
}
if (this.latitude < comparisonNode.latitude) {
return -1;
}
if (this.latitude > comparisonNode.latitude) {
return 1;
}
if (this.longitude < comparisonNode.longitude) {
return -1;
}
if (this.longitude > comparisonNode.longitude) {
return 1;
}
if (this.getTimestamp() == null && comparisonNode.getTimestamp() != null) {
return -1;
}
if (this.getTimestamp() != null && comparisonNode.getTimestamp() == null) {
return 1;
}
if (this.getTimestamp() != null && comparisonNode.getTimestamp() != null) {
int result;
result = this.getTimestamp().compareTo(comparisonNode.getTimestamp());
if (result != 0) {
return result;
}
}
return compareTags(comparisonNode.getTags());
}
/**
* Gets the latitude.
*
* @return The latitude.
*/
public double getLatitude() {
return latitude;
}
/**
* Sets the latitude.
*
* @param latitude
* The latitude.
*/
public void setLatitude(double latitude) {
assertWriteable();
this.latitude = latitude;
}
/**
* Gets the longitude.
*
* @return The longitude.
*/
public double getLongitude() {
return longitude;
}
/**
* Sets the longitude.
*
* @param longitude
* The longitude.
*/
public void setLongitude(double longitude) {
assertWriteable();
this.longitude = longitude;
}
/**
* {@inheritDoc}
*/
@Override
public Node getWriteableInstance() {
if (isReadOnly()) {
return new Node(this);
} else {
return this;
}
}
/**
* ${@inheritDoc}.
*/
@Override
public String toString() {
String name = null;
Collection<Tag> tags = getTags();
for (Tag tag : tags) {
if (tag.getKey() != null && tag.getKey().equalsIgnoreCase("name")) {
name = tag.getValue();
break;
}
}
if (name != null) {
return "Node(id=" + getId() + ", #tags=" + getTags().size() + ", name='" + name + "')";
}
return "Node(id=" + getId() + ", #tags=" + getTags().size() + ")";
}
}