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 DictionaryItem from './DictionaryItem.js'; |
26 | import { NOT_FOUND, ZERO, ONE } from '../../main/Constants.js'; |
27 | |
28 | /* ------------------------------------------------------------------------------------------------------------------------- */ |
29 | /** |
30 | This class contains the OsmSearch dictionary and methods to perform changes in the dictionary |
31 | |
32 | See DictionaryItem for dictionary items |
33 | |
34 | See theOsmSearchDictionary for the one and only one instance of this class |
35 | */ |
36 | /* ------------------------------------------------------------------------------------------------------------------------- */ |
37 | |
38 | class OsmSearchDictionary { |
39 | |
40 | /** |
41 | the root item of the dictionary |
42 | @type {DictionaryItem} |
43 | */ |
44 | |
45 | #dictionary; |
46 | |
47 | /** |
48 | A map with the all the DictionaryItem created, selectable by their objId |
49 | @type {Map} |
50 | */ |
51 | |
52 | #itemsMap; |
53 | |
54 | /** |
55 | the currentItem treated by the #parseLine method |
56 | @type {DictionaryItem} |
57 | */ |
58 | |
59 | #currentItem; |
60 | |
61 | /** |
62 | Array used to store a reference to the items property of the DictionaryItem Objects |
63 | and so build the tree. |
64 | @type {Array.<Array.<DictionaryItem>>} |
65 | */ |
66 | |
67 | #itemsArray; |
68 | |
69 | /** |
70 | Split a line from the csv file into cells and add a DictionaryItem or a filterTag to the dictionary |
71 | @param {String} line A line of the csv file that will be parsed |
72 | */ |
73 | |
74 | #parseLine ( line ) { |
75 | |
76 | // split the linres into cells |
77 | const cells = line.split ( ';' ); |
78 | |
79 | // removing empty cells at the end of the line |
80 | while ( '' === cells [ cells.length - ONE ] ) { |
81 | cells.pop ( ); |
82 | } |
83 | |
84 | // The cell position in line. Used to build the tree |
85 | let cellPos = ZERO; |
86 | |
87 | // An array with filterTags objects used to filter the osm elements. See DictionaryItem |
88 | const filterTags = []; |
89 | cells.forEach ( |
90 | cell => { |
91 | if ( '' !== cell ) { |
92 | |
93 | // The cell contains something |
94 | if ( NOT_FOUND === cell.indexOf ( '=' ) ) { |
95 | |
96 | // The cell don't contains the = char. A new DictionaryItem is created |
97 | this.#currentItem = new DictionaryItem ( cell ); |
98 | |
99 | // The item is added to the itemsMap |
100 | this.#itemsMap.set ( this.#currentItem.objId, this.#currentItem ); |
101 | |
102 | this.#itemsArray [ cellPos ].push ( this.#currentItem ); |
103 | this.#itemsArray [ cellPos + ONE ] = this.#currentItem.items; |
104 | } |
105 | else { |
106 | |
107 | // Each cell is splited into a key and a value |
108 | let keyAndValue = cell.split ( '=' ); |
109 | |
110 | if ( 'element' === keyAndValue [ ZERO ] ) { |
111 | |
112 | // Only one elementType is acceptable for this item |
113 | this.#currentItem.setElementType ( keyAndValue [ ONE ] ); |
114 | } |
115 | else { |
116 | |
117 | // A filterTag object is created... |
118 | let filterTag = {}; |
119 | |
120 | // ...and a property added to the object. The property name is the key found in the cell |
121 | // and the property value is the value found in the cell, except when the value is * |
122 | filterTag [ keyAndValue [ ZERO ] ] = |
123 | '*' === keyAndValue [ ONE ] ? null : keyAndValue [ ONE ]; |
124 | |
125 | // ...and the filterTag object pushed in the array |
126 | filterTags.push ( filterTag ); |
127 | } |
128 | } |
129 | } |
130 | cellPos ++; |
131 | } |
132 | ); |
133 | if ( ZERO !== filterTags.length ) { |
134 | this.#currentItem.filterTagsArray.push ( filterTags ); |
135 | } |
136 | } |
137 | |
138 | /** |
139 | Mark as expanded an item and all the childrens |
140 | @param {DictionaryItem} item The item to mark as expanded |
141 | */ |
142 | |
143 | #expand ( item ) { |
144 | item.items.forEach ( |
145 | subItem => { this.#expand ( subItem ); } |
146 | ); |
147 | item.isExpanded = true; |
148 | } |
149 | |
150 | /** |
151 | Mark as not expanded an item and all the childrens |
152 | @param {DictionaryItem} item The item to mark as not expanded |
153 | */ |
154 | |
155 | #collapse ( item ) { |
156 | item.items.forEach ( |
157 | subItem => { this.#collapse ( subItem ); } |
158 | ); |
159 | item.isExpanded = false; |
160 | } |
161 | |
162 | /** |
163 | The constructor |
164 | */ |
165 | |
166 | constructor ( ) { |
167 | this.#dictionary = new DictionaryItem ( '', true ); |
168 | this.#itemsMap = new Map ( ); |
169 | this.#itemsMap.set ( this.#dictionary.objId, this.#dictionary ); |
170 | this.#itemsArray = [ this.#dictionary.items ]; |
171 | Object.freeze ( this ); |
172 | } |
173 | |
174 | /** |
175 | The dictionary |
176 | @type {DictionaryItem} |
177 | */ |
178 | |
179 | get dictionary ( ) { return this.#dictionary; } |
180 | |
181 | /** |
182 | Parse the content of the TravelNotesSearchDictionaryXX.csv and build a tree of DictionaryItem |
183 | with this content |
184 | @param {String} dictionaryTextContent The content of the TravelNotesSearchDictionaryXX.csv file |
185 | */ |
186 | |
187 | parseDictionary ( dictionaryTextContent ) { |
188 | |
189 | // split the dictionary content into lines and analyse each line |
190 | dictionaryTextContent.split ( /\r\n|\r|\n/ ).forEach ( |
191 | line => { |
192 | if ( '' !== line ) { |
193 | this.#parseLine ( line ); |
194 | } |
195 | } |
196 | ); |
197 | } |
198 | |
199 | /** |
200 | Mark as selected/not selected an item identified by it's objId and all the chidrens of this item |
201 | @param {Number} itemObjId The objId of the item |
202 | @param {Boolean} isSelected The value to set for isSelected |
203 | */ |
204 | |
205 | selectItem ( itemObjId, isSelected ) { |
206 | this.#itemsMap.get ( itemObjId ).isSelected = isSelected; |
207 | } |
208 | |
209 | /** |
210 | Mark the complete dictionary as not selected |
211 | */ |
212 | |
213 | unselectAll ( ) { |
214 | this.#dictionary.isSelected = false; |
215 | } |
216 | |
217 | /** |
218 | Mark as expanded an item identified by it's objId |
219 | @param {Number} itemObjId The objId of the item |
220 | */ |
221 | |
222 | expandItem ( itemObjId ) { |
223 | let item = this.#itemsMap.get ( itemObjId ); |
224 | item.isExpanded = ! item.isExpanded; |
225 | } |
226 | |
227 | /** |
228 | Mark the complete dictionary as expanded |
229 | */ |
230 | |
231 | expand ( ) { |
232 | this.#expand ( this.#dictionary ); |
233 | } |
234 | |
235 | /** |
236 | Mark the complete dictionary except the root item as not expanded |
237 | */ |
238 | |
239 | collapse ( ) { |
240 | this.#dictionary.items.forEach ( |
241 | item => this.#collapse ( item ) |
242 | ); |
243 | } |
244 | |
245 | } |
246 | |
247 | /* ------------------------------------------------------------------------------------------------------------------------- */ |
248 | /** |
249 | The one and only one instance of OsmSearchDictionary class |
250 | @type {OsmSearchDictionary} |
251 | */ |
252 | /* ------------------------------------------------------------------------------------------------------------------------- */ |
253 | |
254 | const theOsmSearchDictionary = new OsmSearchDictionary ( ); |
255 | |
256 | export default theOsmSearchDictionary; |
257 | |
258 | /* --- End of file --------------------------------------------------------------------------------------------------------- */ |
259 |