1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2015 Marius-Valeriu Stanciu <stanciumarius94@gmail.com>
4 //
5 
6 // Self
7 #include "osm/OsmPlacemarkData.h"
8 
9 // Marble
10 #include "GeoDataExtendedData.h"
11 
12 #include <QXmlStreamAttributes>
13 
14 namespace Marble
15 {
16 
qHash(Marble::OsmIdentifier ident,uint seed)17 inline uint qHash(Marble::OsmIdentifier ident, uint seed)
18 {
19     return ::qHash(ident.id, seed) ^ ::qHash((int)ident.type, seed);
20 }
21 
OsmPlacemarkData()22 OsmPlacemarkData::OsmPlacemarkData():
23     m_id( 0 )
24 {
25     // nothing to do
26 }
27 
id() const28 qint64 OsmPlacemarkData::id() const
29 {
30     return m_id;
31 }
32 
oid() const33 qint64 OsmPlacemarkData::oid() const
34 {
35     auto const value = m_tags.value(QStringLiteral("mx:oid")).toLong();
36     return value > 0 ? value : m_id;
37 }
38 
changeset() const39 QString OsmPlacemarkData::changeset() const
40 {
41     return m_tags.value(QStringLiteral("mx:changeset"));
42 }
43 
version() const44 QString OsmPlacemarkData::version() const
45 {
46     return m_tags.value(QStringLiteral("mx:version"));
47 }
48 
uid() const49 QString OsmPlacemarkData::uid() const
50 {
51     return m_tags.value(QStringLiteral("mx:uid"));
52 }
53 
isVisible() const54 QString OsmPlacemarkData::isVisible() const
55 {
56     return m_tags.value(QStringLiteral("mx:visible"));
57 }
58 
user() const59 QString OsmPlacemarkData::user() const
60 {
61     return m_tags.value(QStringLiteral("mx:user"));
62 }
63 
timestamp() const64 QString OsmPlacemarkData::timestamp() const
65 {
66     return m_tags.value(QStringLiteral("mx:timestamp"));
67 }
68 
action() const69 QString OsmPlacemarkData::action() const
70 {
71     return m_tags.value(QStringLiteral("mx:action"));
72 }
73 
setId(qint64 id)74 void OsmPlacemarkData::setId( qint64 id )
75 {
76     m_id = id;
77 }
78 
setVersion(const QString & version)79 void OsmPlacemarkData::setVersion( const QString& version )
80 {
81     m_tags[QStringLiteral("mx:version")] = version;
82 }
83 
setChangeset(const QString & changeset)84 void OsmPlacemarkData::setChangeset( const QString& changeset )
85 {
86     m_tags[QStringLiteral("mx:changeset")] = changeset;
87 }
88 
setUid(const QString & uid)89 void OsmPlacemarkData::setUid( const QString& uid )
90 {
91     m_tags[QStringLiteral("mx:uid")] = uid;
92 }
93 
setVisible(const QString & visible)94 void OsmPlacemarkData::setVisible( const QString& visible )
95 {
96     m_tags[QStringLiteral("mx:visible")] = visible;
97 }
98 
setUser(const QString & user)99 void OsmPlacemarkData::setUser( const QString& user )
100 {
101    m_tags[QStringLiteral("mx:user")] = user;
102 }
103 
setTimestamp(const QString & timestamp)104 void OsmPlacemarkData::setTimestamp( const QString& timestamp )
105 {
106     m_tags[QStringLiteral("mx:timestamp")] = timestamp;
107 }
108 
setAction(const QString & action)109 void OsmPlacemarkData::setAction( const QString& action )
110 {
111     m_tags[QStringLiteral("mx:action")] = action;
112 }
113 
114 
115 
tagValue(const QString & key) const116 QString OsmPlacemarkData::tagValue( const QString& key ) const
117 {
118     return m_tags.value( key );
119 }
120 
addTag(const QString & key,const QString & value)121 void OsmPlacemarkData::addTag( const QString& key, const QString& value )
122 {
123     m_tags.insert( key, value );
124 }
125 
removeTag(const QString & key)126 void OsmPlacemarkData::removeTag( const QString &key )
127 {
128     m_tags.remove( key );
129 }
130 
containsTag(const QString & key,const QString & value) const131 bool OsmPlacemarkData::containsTag( const QString &key, const QString &value ) const
132 {
133     auto const iter = m_tags.constFind(key);
134     return iter == m_tags.constEnd() ? false : iter.value() == value;
135 }
136 
containsTagKey(const QString & key) const137 bool OsmPlacemarkData::containsTagKey( const QString &key ) const
138 {
139     return m_tags.contains( key );
140 }
141 
findTag(const QString & key) const142 QHash<QString, QString>::const_iterator OsmPlacemarkData::findTag(const QString &key) const
143 {
144     return m_tags.constFind(key);
145 }
146 
tagsBegin() const147 QHash< QString, QString >::const_iterator OsmPlacemarkData::tagsBegin() const
148 {
149     return m_tags.begin();
150 }
151 
tagsEnd() const152 QHash< QString, QString >::const_iterator OsmPlacemarkData::tagsEnd() const
153 {
154     return m_tags.constEnd();
155 }
156 
157 
158 
159 
160 
nodeReference(const GeoDataCoordinates & coordinates)161 OsmPlacemarkData &OsmPlacemarkData::nodeReference( const GeoDataCoordinates &coordinates )
162 {
163     return m_nodeReferences[ coordinates ];
164 }
165 
nodeReference(const GeoDataCoordinates & coordinates) const166 OsmPlacemarkData OsmPlacemarkData::nodeReference( const GeoDataCoordinates &coordinates ) const
167 {
168     return m_nodeReferences.value( coordinates );
169 }
170 
addNodeReference(const GeoDataCoordinates & key,const OsmPlacemarkData & value)171 void OsmPlacemarkData::addNodeReference( const GeoDataCoordinates &key, const OsmPlacemarkData &value )
172 {
173     m_nodeReferences.insert( key, value );
174 }
175 
removeNodeReference(const GeoDataCoordinates & key)176 void OsmPlacemarkData::removeNodeReference( const GeoDataCoordinates &key )
177 {
178     m_nodeReferences.remove( key );
179 }
180 
containsNodeReference(const GeoDataCoordinates & key) const181 bool OsmPlacemarkData::containsNodeReference( const GeoDataCoordinates &key ) const
182 {
183     return m_nodeReferences.contains( key );
184 }
185 
changeNodeReference(const GeoDataCoordinates & oldKey,const GeoDataCoordinates & newKey)186 void OsmPlacemarkData::changeNodeReference( const GeoDataCoordinates &oldKey, const GeoDataCoordinates &newKey )
187 {
188     m_nodeReferences.insert( newKey, m_nodeReferences.value( oldKey ) );
189     m_nodeReferences.remove( oldKey );
190 }
191 
nodeReferences()192 QHash<GeoDataCoordinates, OsmPlacemarkData> &OsmPlacemarkData::nodeReferences()
193 {
194     return m_nodeReferences;
195 }
196 
nodeReferencesBegin() const197 QHash< GeoDataCoordinates, OsmPlacemarkData >::const_iterator OsmPlacemarkData::nodeReferencesBegin() const
198 {
199     return m_nodeReferences.begin();
200 }
201 
nodeReferencesEnd() const202 QHash< GeoDataCoordinates, OsmPlacemarkData >::const_iterator OsmPlacemarkData::nodeReferencesEnd() const
203 {
204     return m_nodeReferences.constEnd();
205 }
206 
207 
memberReference(int key)208 OsmPlacemarkData &OsmPlacemarkData::memberReference( int key )
209 {
210     return m_memberReferences[ key ];
211 }
212 
memberReference(int key) const213 OsmPlacemarkData OsmPlacemarkData::memberReference( int key ) const
214 {
215     return m_memberReferences.value( key );
216 }
217 
218 
addMemberReference(int key,const OsmPlacemarkData & value)219 void OsmPlacemarkData::addMemberReference( int key, const OsmPlacemarkData &value )
220 {
221     m_memberReferences.insert( key, value );
222 }
223 
removeMemberReference(int key)224 void OsmPlacemarkData::removeMemberReference( int key )
225 {
226     // If an inner boundary is deleted, all indexes higher than the deleted one
227     // must be lowered by 1 to keep order.
228     QHash< int, OsmPlacemarkData > newHash;
229     QHash< int, OsmPlacemarkData >::iterator it = m_memberReferences.begin();
230     QHash< int, OsmPlacemarkData >::iterator end = m_memberReferences.end();
231 
232     for ( ; it != end; ++it ) {
233         if ( it.key() > key ) {
234             newHash.insert( it.key() - 1, it.value() );
235         }
236         else if ( it.key() < key ) {
237             newHash.insert( it.key(), it.value() );
238         }
239     }
240     m_memberReferences = newHash;
241 }
242 
containsMemberReference(int key) const243 bool OsmPlacemarkData::containsMemberReference( int key ) const
244 {
245     return m_memberReferences.contains( key );
246 }
247 
memberReferences()248 QHash<int, OsmPlacemarkData> &OsmPlacemarkData::memberReferences()
249 {
250     return m_memberReferences;
251 }
252 
memberReferencesBegin() const253 QHash< int, OsmPlacemarkData >::const_iterator OsmPlacemarkData::memberReferencesBegin() const
254 {
255     return m_memberReferences.begin();
256 }
257 
memberReferencesEnd() const258 QHash< int, OsmPlacemarkData >::const_iterator OsmPlacemarkData::memberReferencesEnd() const
259 {
260     return m_memberReferences.constEnd();
261 }
262 
addRelation(qint64 id,OsmType type,const QString & role)263 void OsmPlacemarkData::addRelation( qint64 id, OsmType type, const QString &role )
264 {
265     m_relationReferences.insert( { id, type }, role );
266 }
267 
removeRelation(qint64 id)268 void OsmPlacemarkData::removeRelation( qint64 id )
269 {
270     /// ### this is wrong and just done this way for backward behavior compatible
271     /// ### this method should probably take type as an additional argument
272     m_relationReferences.remove( { id, OsmType::Node } );
273     m_relationReferences.remove( { id, OsmType::Way } );
274     m_relationReferences.remove( { id, OsmType::Relation } );
275 }
276 
containsRelation(qint64 id) const277 bool OsmPlacemarkData::containsRelation( qint64 id ) const
278 {
279     /// ### this is wrong and just done this way for backward behavior compatible
280     /// ### this method should probably take type as an additional argument
281     return m_relationReferences.contains( { id, OsmType::Node } )
282         || m_relationReferences.contains( { id, OsmType::Way } )
283         || m_relationReferences.contains( { id, OsmType::Relation } );
284 }
285 
relationReferencesBegin() const286 QHash< OsmIdentifier, QString >::const_iterator OsmPlacemarkData::relationReferencesBegin() const
287 {
288     return m_relationReferences.begin();
289 }
290 
relationReferencesEnd() const291 QHash< OsmIdentifier, QString >::const_iterator OsmPlacemarkData::relationReferencesEnd() const
292 {
293     return m_relationReferences.constEnd();
294 }
295 
isNull() const296 bool OsmPlacemarkData::isNull() const
297 {
298     return !m_id;
299 }
300 
isEmpty() const301 bool OsmPlacemarkData::isEmpty() const
302 {
303     return m_tags.isEmpty() &&
304             m_nodeReferences.isEmpty() &&
305             m_memberReferences.isEmpty() &&
306             m_relationReferences.isEmpty();
307 }
308 
fromParserAttributes(const QXmlStreamAttributes & attributes)309 OsmPlacemarkData OsmPlacemarkData::fromParserAttributes( const QXmlStreamAttributes &attributes )
310 {
311     OsmPlacemarkData osmData;
312     osmData.setId(attributes.value(QLatin1String("id")).toLongLong());
313     osmData.setVersion(attributes.value(QLatin1String("version")).toString());
314     osmData.setChangeset(attributes.value(QLatin1String("changeset")).toString());
315     osmData.setUser(attributes.value(QLatin1String("user")).toString());
316     osmData.setUid(attributes.value(QLatin1String("uid")).toString());
317     osmData.setVisible(attributes.value(QLatin1String("visible")).toString());
318     osmData.setTimestamp(attributes.value(QLatin1String("timestamp")).toString());
319     osmData.setAction(attributes.value(QLatin1String("action")).toString());
320     return osmData;
321 }
322 
nodeType() const323 const char *OsmPlacemarkData::nodeType() const
324 {
325     return "OsmPlacemarkDataType";
326 }
327 
328 }
329