File : core/lib/GpxFactory.js

1
/*
2
Copyright - 2017 2023 - wwwouaiebe - Contact: https://www.ouaie.be/
3
4
This  program is free software;
5
you can redistribute it and/or modify it under the terms of the
6
GNU General Public License as published by the Free Software Foundation;
7
either version 3 of the License, or any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
*/
18
/*
19
Changes:
20
    - v4.0.0:
21
        - created from v3.6.0
22
Doc reviewed 202208
23
 */
24
25
import theDataSearchEngine from '../../data/DataSearchEngine.js';
26
import theTravelNotesData from '../../data/TravelNotesData.js';
27
import theUtilities from '../../core/uiLib/Utilities.js';
28
29
/* ------------------------------------------------------------------------------------------------------------------------- */
30
/**
31
This class is used to create gpx files
32
*/
33
/* ------------------------------------------------------------------------------------------------------------------------- */
34
35
class GpxFactory {
36
37
    /**
38
    The gpx string to write in the gpx file
39
    @type {String}
40
    */
41
42
    #gpxString;
43
44
    /**
45
    The time stamp added in the gpx
46
    @type {String}
47
    */
48
49
    #timeStamp;
50
51
    /**
52
    A reference to the Route for witch the gpx file is created
53
    @type {Route}
54
    */
55
56
    #route;
57
58
    /**
59
    Simple constant for gpx presentation
60
    @type {String}
61
    */
62
63
    static get #TAB0 ( ) { return '\n'; }
64
65
    /**
66
    Simple constant for gpx presentation
67
    @type {String}
68
    */
69
70
    static get #TAB1 ( ) { return '\n\t'; }
71
72
    /**
73
    Simple constant for gpx presentation
74
    @type {String}
75
    */
76
77
    static get #TAB2 ( ) { return '\n\t\t'; }
78
79
    /**
80
    Simple constant for gpx presentation
81
    @type {String}
82
    */
83
84
    static get #TAB3 ( ) { return '\n\t\t\t'; }
85
86
    /**
87
    Simple constant for gpx presentation
88
    @type {String}
89
    */
90
91
    static get #TAB4 ( ) { return '\n\t\t\t\t'; }
92
93
    /**
94
    Creates the header of the gpx file
95
    */
96
97
    #addHeader ( ) {
98
99
        // header
100
        this.#gpxString = '<?xml version="1.0"?>' + GpxFactory.#TAB0;
101
        this.#gpxString += '<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
102
        'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +
103
        'xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" ' +
104
        'version="1.1" creator="TravelNotes">';
105
    }
106
107
    /**
108
    Replace the chars &, ', ", < and > with entities
109
    @param {String} text The text containing reserved chars
110
    @return {String} The text with reserved chars replaced by entities
111
    */
112
113
    #replaceEntities ( text ) {
114
        return ( text.replaceAll ( '&', '&' )
115
            .replaceAll ( /\u0027/g, ''' )
116
            .replaceAll ( /"/g, '"' )
117
            .replaceAll ( /</g, '<' )
118
            .replaceAll ( />/g, '>' )
119
        );
120
    }
121
122
    /**
123
    Add the waypoints to the gpx file
124
    */
125
126
    #addWayPoints ( ) {
127
        const wayPointsIterator = this.#route.wayPoints.iterator;
128
        while ( ! wayPointsIterator.done ) {
129
            this.#gpxString +=
130
                GpxFactory.#TAB1 + '<wpt lat="' + wayPointsIterator.value.lat + '" lon="' + wayPointsIterator.value.lng + '">' +
131
                GpxFactory.#TAB2 + this.#timeStamp +
132
                GpxFactory.#TAB2 + '<name>' + this.#replaceEntities ( wayPointsIterator.value.fullName ) + '</name>' +
133
                GpxFactory.#TAB1 + '</wpt>';
134
135
        }
136
    }
137
138
    /**
139
    Add the route to the gpx file
140
    */
141
142
    #addRoute ( ) {
143
        this.#gpxString += GpxFactory.#TAB1 + '<rte>';
144
        this.#gpxString += GpxFactory.#TAB2 + '<name>' + this.#replaceEntities ( this.#route.computedName ) + '</name>';
145
        const maneuverIterator = this.#route.itinerary.maneuvers.iterator;
146
        while ( ! maneuverIterator.done ) {
147
            const wayPoint = this.#route.itinerary.itineraryPoints.getAt (
148
                maneuverIterator.value.itineraryPointObjId
149
            );
150
            this.#gpxString +=
151
                GpxFactory.#TAB2 + '<rtept lat="' + wayPoint.lat + '" lon="' + wayPoint.lng + '">' +
152
                GpxFactory.#TAB3 + this.#timeStamp +
153
                GpxFactory.#TAB3 + '<desc>' + this.#replaceEntities ( maneuverIterator.value.instruction ) + '</desc>' +
154
                GpxFactory.#TAB2 + '</rtept>';
155
        }
156
        this.#gpxString += GpxFactory.#TAB1 + '</rte>';
157
    }
158
159
    /**
160
    Add the track to the gpx file
161
    */
162
163
    #addTrack ( ) {
164
        this.#gpxString += GpxFactory.#TAB1 + '<trk>';
165
        this.#gpxString += GpxFactory.#TAB2 + '<name>' + this.#replaceEntities ( this.#route.computedName ) + '</name>';
166
        this.#gpxString += GpxFactory.#TAB2 + '<trkseg>';
167
        const itineraryPointsIterator = this.#route.itinerary.itineraryPoints.iterator;
168
        while ( ! itineraryPointsIterator.done ) {
169
            this.#gpxString +=
170
                GpxFactory.#TAB3 +
171
                '<trkpt lat="' + itineraryPointsIterator.value.lat + '" lon="' + itineraryPointsIterator.value.lng + '">' +
172
                GpxFactory.#TAB4 + this.#timeStamp +
173
                GpxFactory.#TAB4 + '<ele>' + itineraryPointsIterator.value.elev + '</ele>' +
174
                GpxFactory.#TAB3 + '</trkpt>';
175
        }
176
        this.#gpxString += GpxFactory.#TAB2 + '</trkseg>';
177
        this.#gpxString += GpxFactory.#TAB1 + '</trk>';
178
    }
179
180
    /**
181
    Add the footer to the gpx file
182
    */
183
184
    #addFooter ( ) {
185
        this.#gpxString += GpxFactory.#TAB0 + '</gpx>';
186
    }
187
188
    /**
189
    Save the gpx string to a file
190
    */
191
192
    #saveGpxToFile ( ) {
193
        let fileName =
194
            ( '' === theTravelNotesData.travel.name ? '' : theTravelNotesData.travel.name + ' - ' ) + this.#route.computedName;
195
        if ( '' === fileName ) {
196
            fileName = 'TravelNote';
197
        }
198
        fileName += '.gpx';
199
        theUtilities.saveFile ( fileName, this.#gpxString, 'application/xml' );
200
    }
201
202
    /**
203
    The constructor
204
    */
205
206
    constructor ( ) {
207
        Object.freeze ( this );
208
    }
209
210
    /**
211
    Transform a route into a gpx file
212
    @param {Number} routeObjId the objId of the route to save in a gpx file
213
    */
214
215
    routeToGpx ( routeObjId ) {
216
        this.#route = theDataSearchEngine.getRoute ( routeObjId );
217
        if ( ! this.#route ) {
218
            return;
219
        }
220
        this.#timeStamp = '<time>' + new Date ( ).toISOString ( ) + '</time>';
221
222
        this.#addHeader ( );
223
        this.#addWayPoints ( );
224
        this.#addRoute ( );
225
        this.#addTrack ( );
226
        this.#addFooter ( );
227
        this.#saveGpxToFile ( );
228
    }
229
}
230
231
export default GpxFactory;
232
233
/* --- End of file --------------------------------------------------------------------------------------------------------- */
234