internal static SimpleChangeSet ConvertToSimple(Osm.Xml.v0_6.modify modify) { // create change set record. SimpleChangeSet change_set = new SimpleChangeSet(); // create change record. SimpleChange change = new SimpleChange(); change.Type = SimpleChangeType.Modify; change.OsmGeo = new List<SimpleOsmGeo>(); // add all relations to the list. if (modify.relation != null) { foreach (Osm.Xml.v0_6.relation osm_geo in modify.relation) { change.OsmGeo.Add(XmlSimpleConverter.ConvertToSimple(osm_geo)); } } // add all ways to the list. if (modify.way != null) { foreach (Osm.Xml.v0_6.way osm_geo in modify.way) { change.OsmGeo.Add(XmlSimpleConverter.ConvertToSimple(osm_geo)); } } // add all nodes to the list. if (modify.node != null) { foreach (Osm.Xml.v0_6.node osm_geo in modify.node) { change.OsmGeo.Add(XmlSimpleConverter.ConvertToSimple(osm_geo)); } } // add change to changeset change_set.Changes = new List<SimpleChange>(); change_set.Changes.Add(change); return change_set; }
/// <summary> /// Applies a change to the target. /// </summary> /// <param name="change"></param> public abstract void ApplyChange(SimpleChangeSet change);
/// <summary> /// Returns true if any part of this changeset exists inside the bounding box. /// </summary> /// <param name="simpleChangeSet"></param> /// <returns></returns> private bool IsInsideBox(SimpleChangeSet simpleChangeSet) { // keep a list of tested relation to prevent circular references from hanging this process. _tested_relations = new List<long>(); // keep all the objects that could not be checked and check them later. List<SimpleOsmGeo> objects_not_checked = new List<SimpleOsmGeo>(); // loop over all objects inside this box and if they are nodes they can be checked. foreach (SimpleChange change in simpleChangeSet.Changes) { foreach (SimpleOsmGeo geo in change.OsmGeo) { if (geo is SimpleNode) { SimpleNode node = geo as SimpleNode; GeoCoordinate coord = new GeoCoordinate(node.Latitude.Value, node.Longitude.Value); if (_box.IsInsideAny(new OsmSharp.Tools.Math.PointF2D[] { coord })) { return true; } } else { objects_not_checked.Add(geo as SimpleOsmGeo); } } } // try all ways. foreach (SimpleOsmGeo geo in objects_not_checked) { if (geo is SimpleWay && (geo as SimpleWay).Nodes != null) { OsmSharp.Osm.Way way = _data_source.GetWay(geo.Id.Value); if (way != null && way.Nodes != null) { foreach (Osm.Node node in way.Nodes) { if (node != null) { // only if the node is found if (_box.IsInsideAny(new OsmSharp.Tools.Math.PointF2D[] { node.Coordinate })) { return true; } } } } } } // try all relations. foreach (SimpleOsmGeo geo in objects_not_checked) { if (geo is SimpleRelation) { if (!_tested_relations.Contains(geo.Id.Value)) { _tested_relations.Add(geo.Id.Value); if (this.IsInsideBoxRelation((geo as SimpleRelation).Members)) { return true; } } } } return false; }
/// <summary> /// Filters the geo objects in the changeset and omits the ones not inside the bb. /// </summary> /// <param name="simpleChangeSet"></param> /// <returns></returns> private KeyValuePair<SimpleChangeSet, GeoCoordinateBox> FilterChanges(SimpleChangeSet simpleChangeSet) { List<GeoCoordinate> changes_coordinates = new List<GeoCoordinate>(); SimpleChangeSet filtered_changeset = new SimpleChangeSet(); filtered_changeset.Changes = new List<SimpleChange>(); // keep a list of tested relation to prevent circular references from hanging this process. _tested_relations = new List<long>(); // keep all the objects that could not be checked and check them later. List<KeyValuePair<SimpleOsmGeo, SimpleChange>> objects_not_checked = new List<KeyValuePair<SimpleOsmGeo, SimpleChange>>(); // loop over all objects inside this box and if they are nodes they can be checked. HashSet<long> nodes_inside = new HashSet<long>(); // keep track of all the nodes inside for quick checks later! foreach (SimpleChange change in simpleChangeSet.Changes) { // keep the changed nodes that are ok for the filter. List<SimpleOsmGeo> nodes_changed = new List<SimpleOsmGeo>(); // loop over all objects in this set and keep the nodes. foreach (SimpleOsmGeo geo in change.OsmGeo) { if (geo is SimpleNode) { SimpleNode node = geo as SimpleNode; GeoCoordinate coord = new GeoCoordinate(node.Latitude.Value, node.Longitude.Value); if (_box.IsInsideAny(new OsmSharp.Tools.Math.PointF2D[] { coord })) { nodes_changed.Add(node); nodes_inside.Add(node.Id.Value); changes_coordinates.Add(coord); } } else { objects_not_checked.Add(new KeyValuePair<SimpleOsmGeo,SimpleChange>(geo as SimpleOsmGeo,change)); } } // are there changes in the nodes? if (nodes_changed.Count > 0) { SimpleChange nodes_change = new SimpleChange(); nodes_change.OsmGeo = nodes_changed; nodes_change.Type = change.Type; filtered_changeset.Changes.Add(nodes_change); } } // try all ways. HashSet<long> ways_inside = new HashSet<long>(); // keep the ways inside for quick checks later! foreach(KeyValuePair<SimpleOsmGeo,SimpleChange> change_pair in objects_not_checked) { SimpleOsmGeo geo = change_pair.Key; SimpleChange change = change_pair.Value; // keep the changed ways that are ok for the filter. List<SimpleOsmGeo> ways_changed = new List<SimpleOsmGeo>(); // detect if the way is part of the filter! if (geo is SimpleWay && (geo as SimpleWay).Nodes != null) { // try the cached nodes. foreach (long node_id in (geo as SimpleWay).Nodes) { if (nodes_inside.Contains(node_id)) { ways_changed.Add(geo); ways_inside.Add(geo.Id.Value); break; } } // first try to load the complete way. OsmSharp.Osm.Way way = _data_source.GetWay(geo.Id.Value); if (way != null && way.Nodes != null) { foreach (Osm.Node node in way.Nodes) { if (node != null) { // only if the node is found changes_coordinates.Add(node.Coordinate); if (_box.IsInsideAny(new OsmSharp.Tools.Math.PointF2D[] { node.Coordinate })) { changes_coordinates.Add(node.Coordinate); ways_changed.Add(geo); ways_inside.Add(geo.Id.Value); break; } } } } if (change.Type == SimpleChangeType.Delete && way != null && (way.Nodes == null || way.Nodes.Count == 0)) { // alway delete empty ways! ways_changed.Add(geo); ways_inside.Add(geo.Id.Value); } // second try to load the nodes individually. foreach (long node_id in (geo as SimpleWay).Nodes) { OsmSharp.Osm.Node node = _data_source.GetNode(node_id); if (node != null) { // only if the node is found if (_box.IsInsideAny(new OsmSharp.Tools.Math.PointF2D[] { node.Coordinate })) { changes_coordinates.Add(node.Coordinate); ways_changed.Add(geo); ways_inside.Add(geo.Id.Value); break; } } } } // are there changes in the nodes? if (ways_changed.Count > 0) { SimpleChange ways_change = new SimpleChange(); ways_change.OsmGeo = ways_changed; ways_change.Type = change.Type; filtered_changeset.Changes.Add(ways_change); } } // try all relations. foreach(KeyValuePair<SimpleOsmGeo,SimpleChange> change_pair in objects_not_checked) { SimpleOsmGeo geo = change_pair.Key; SimpleChange change = change_pair.Value; // keep the changed ways that are ok for the filter. List<SimpleOsmGeo> relations_changed = new List<SimpleOsmGeo>(); // test all relations. if (geo is SimpleRelation) { if (!_tested_relations.Contains(geo.Id.Value)) { _tested_relations.Add(geo.Id.Value); if (this.IsInsideBoxRelation((geo as SimpleRelation).Members,nodes_inside,ways_inside)) { relations_changed.Add(geo); } } } // are there changes in the nodes? if (relations_changed.Count > 0) { SimpleChange relations_change = new SimpleChange(); relations_change.OsmGeo = relations_changed; relations_change.Type = change.Type; filtered_changeset.Changes.Add(relations_change); } } // create bounding box of the found changes! GeoCoordinateBox box = null; if (changes_coordinates.Count > 0) { box = new GeoCoordinateBox(changes_coordinates); } return new KeyValuePair<SimpleChangeSet, GeoCoordinateBox>(filtered_changeset, box); }
/// <summary> /// Move to the next object. /// </summary> /// <returns></returns> public override bool MoveNext() { // move to the next change available. while (this.Source.MoveNext()) { // convert the changeset to only data withing this bb! KeyValuePair<SimpleChangeSet,GeoCoordinateBox> changes_inside = this.FilterChanges(this.Source.Current()); if (changes_inside.Key.Changes.Count > 0) { // some data in this changeset is ok! OsmSharp.Tools.Output.OutputStreamHost.WriteLine(string.Empty); OsmSharp.Tools.Output.OutputStreamHost.Write("Changeset accepted:"); // set the converted changeset as the current one! _current = changes_inside.Key; // report to the listener. if (_listener != null && changes_inside.Value != null) { _listener.ReportChangeDetected(changes_inside.Value); } return true; } } _current = null; return false; }
/// <summary> /// Moves to the next changeset. /// </summary> /// <returns></returns> public override bool MoveNext() { while (_reader.Read()) { if (_reader.NodeType == XmlNodeType.Element && (_reader.Name == "modify" || _reader.Name == "create"||_reader.Name == "delete")) { // create a stream for only this element. string name = _reader.Name; string next_element = _reader.ReadOuterXml(); XmlReader reader = XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(next_element))); object osm_obj = null; // select type of element. switch (name) { case "delete": osm_obj = _ser_delete.Deserialize(reader); if (osm_obj is OsmSharp.Osm.Xml.v0_6.delete) { _next = XmlSimpleConverter.ConvertToSimple(osm_obj as OsmSharp.Osm.Xml.v0_6.delete); return true; } break; case "modify": osm_obj = _ser_modify.Deserialize(reader); if (osm_obj is OsmSharp.Osm.Xml.v0_6.modify) { _next = XmlSimpleConverter.ConvertToSimple(osm_obj as OsmSharp.Osm.Xml.v0_6.modify); return true; } break; case "create": osm_obj = _ser_create.Deserialize(reader); if (osm_obj is OsmSharp.Osm.Xml.v0_6.create) { _next = XmlSimpleConverter.ConvertToSimple(osm_obj as OsmSharp.Osm.Xml.v0_6.create); return true; } break; } } } _next = null; return false; }
/// <summary> /// Initializes this changeset source. /// </summary> public override void Initialize() { _next = null; _ser_create = new XmlSerializer(typeof(Osm.Xml.v0_6.create)); _ser_modify = new XmlSerializer(typeof(Osm.Xml.v0_6.modify)); _ser_delete = new XmlSerializer(typeof(Osm.Xml.v0_6.delete)); XmlReaderSettings settings = new XmlReaderSettings(); settings.CloseInput = true; settings.CheckCharacters = false; settings.IgnoreComments = true; settings.IgnoreProcessingInstructions = true; if (_stream != null) { _reader = XmlReader.Create(_stream, settings); } else { TextReader text_reader = new StreamReader(new FileInfo(_file_name).OpenRead(), Encoding.UTF8); _reader = XmlReader.Create(text_reader, settings); } }
/// <summary> /// Applies a change. /// </summary> /// <param name="change"></param> public override void ApplyChange(SimpleChangeSet change) { }
public override void ApplyChange(SimpleChangeSet change) { throw new NotSupportedException(); }
/// <summary> /// Apply the given changeset. /// </summary> /// <param name="change_set"></param> public override void ApplyChange(SimpleChangeSet change_set) { if (change_set != null && change_set.Changes != null) { foreach (SimpleChange change in change_set.Changes) { switch (change.Type) { case SimpleChangeType.Create: foreach (SimpleOsmGeo geo in change.OsmGeo) { // start applying the simplechange. OracleTransaction trans = _connection.BeginTransaction(); try { if (geo is SimpleNode) { this.Create(geo as SimpleNode); OsmSharp.Tools.Output.OutputStreamHost.Write("+(n:{0})", geo.Id.Value); } else if (geo is SimpleWay) { this.Create(geo as SimpleWay); OsmSharp.Tools.Output.OutputStreamHost.Write("+(w:{0})", geo.Id.Value); } else if (geo is SimpleRelation) { this.Create(geo as SimpleRelation); OsmSharp.Tools.Output.OutputStreamHost.Write("+(r:{0})", geo.Id.Value); } trans.Commit(); } catch (OracleException ex) { trans.Rollback(); if (!_pragmatic) { throw ex; } else { OsmSharp.Tools.Output.OutputStreamHost.Write("+(E:{0}-{1})", geo.Id.Value,geo.Type.ToString()); } } } break; case SimpleChangeType.Delete: foreach (SimpleOsmGeo geo in change.OsmGeo) { // start applying the simplechange. OracleTransaction trans = _connection.BeginTransaction(); try { if (geo is SimpleNode) { this.Delete(geo as SimpleNode); OsmSharp.Tools.Output.OutputStreamHost.Write("-(n:{0})", geo.Id.Value); } else if (geo is SimpleWay) { this.Delete(geo as SimpleWay); OsmSharp.Tools.Output.OutputStreamHost.Write("-(w:{0})", geo.Id.Value); } else if (geo is SimpleRelation) { this.Delete(geo as SimpleRelation); OsmSharp.Tools.Output.OutputStreamHost.Write("-(r:{0})", geo.Id.Value); } trans.Commit(); } catch (OracleException ex) { trans.Rollback(); if (!_pragmatic) { throw ex; } else { OsmSharp.Tools.Output.OutputStreamHost.Write("-(E:{0}-{1})", geo.Id.Value, geo.Type.ToString()); } } } break; case SimpleChangeType.Modify: foreach (SimpleOsmGeo geo in change.OsmGeo) { // start applying the simplechange. OracleTransaction trans = _connection.BeginTransaction(); try { if (geo is SimpleNode) { this.Modify(geo as SimpleNode); OsmSharp.Tools.Output.OutputStreamHost.Write("/(n:{0})", geo.Id.Value); } else if (geo is SimpleWay) { this.Modify(geo as SimpleWay); OsmSharp.Tools.Output.OutputStreamHost.Write("/(w:{0})", geo.Id.Value); } else if (geo is SimpleRelation) { this.Modify(geo as SimpleRelation); OsmSharp.Tools.Output.OutputStreamHost.Write("/(r:{0})", geo.Id.Value); } trans.Commit(); } catch (OracleException ex) { trans.Rollback(); if (!_pragmatic) { throw ex; } else { OsmSharp.Tools.Output.OutputStreamHost.Write("/(E:{0}-{1})", geo.Id.Value, geo.Type.ToString()); } } } break; } } } }
/// <summary> /// Converts an API v6 xml osmChange object to a SimpleChange object. /// </summary> /// <param name="osm_change"></param> /// <returns></returns> private SimpleChangeSet Convertv6XmlChanges(OsmSharp.Osm.Xml.v0_6.osmChange osm_change) { List<SimpleChange> changes = new List<SimpleChange>(); if (osm_change.create != null) { for (int idx = 0; idx < osm_change.create.Length; idx++) { OsmSharp.Osm.Xml.v0_6.create create = osm_change.create[idx]; List<SimpleOsmGeo> changed_objects = new List<SimpleOsmGeo>(); if (create.node != null) { // change represents a change in a node. for (int node_idx = 0; node_idx < create.node.Length; node_idx++) { changed_objects.Add(this.Convertv6XmlNode(create.node[node_idx])); } } if (create.way != null) { // change represents a change in a way. for (int way_idx = 0; way_idx < create.way.Length; way_idx++) { changed_objects.Add(this.Convertv6XmlWay(create.way[way_idx])); } } if (create.relation != null) { // change represents a change in a relation. for (int relation_idx = 0; relation_idx < create.relation.Length; relation_idx++) { changed_objects.Add(this.Convertv6XmlRelation(create.relation[relation_idx])); } } if (changed_objects.Count > 0) { // there are actually changed objects. changes.Add(new SimpleChange() { OsmGeo = changed_objects, Type = SimpleChangeType.Create }); } } } SimpleChangeSet simple_change_set = new SimpleChangeSet(); simple_change_set.Changes = changes; return simple_change_set; }
/// <summary> /// Apply a changeset to the database. /// </summary> /// <param name="change"></param> public override void ApplyChange(SimpleChangeSet change) { throw new NotSupportedException("Relation are not supported in the redis target!"); }