Subversion Repositories eFlore/Applications.cel

Rev

Rev 596 | Rev 729 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 596 Rev 633
1
package org.tela_botanica.client.modeles;
1
package org.tela_botanica.client.modeles;
2
 
2
 
3
import java.util.HashMap;
3
import java.util.HashMap;
4
import java.util.Iterator;
4
import java.util.Iterator;
5
import java.util.Set;
5
import java.util.Set;
6
 
6
 
7
import com.google.gwt.json.client.JSONObject;
7
import com.google.gwt.json.client.JSONObject;
8
 
8
 
9
/**
9
/**
10
 * 
10
 * 
11
 * Classe representant une image du carnet, elle ne contient pas d'image à
11
 * Classe representant une image du carnet, elle ne contient pas d'image à
12
 * proprement parler mais plutôt les informations associées ainsi que l'url
12
 * proprement parler mais plutôt les informations associées ainsi que l'url
13
 * distante. C'est une table de hachage qui contient des paires propriété/valeur
13
 * distante. C'est une table de hachage qui contient des paires propriété/valeur
14
 * 
14
 * 
15
 */
15
 */
16
public class ImageCarnet extends HashMap<String, String> {
16
public class ImageCarnet extends HashMap<String, String> {
17
 
17
 
18
	/**
18
	/**
19
	 * 
19
	 * 
20
	 */
20
	 */
21
	private static final long serialVersionUID = -6220175386957259859L;
21
	private static final long serialVersionUID = -6220175386957259859L;
22
 
22
 
23
	/**
23
	/**
24
	 * Constructeur avec un objet JSON
24
	 * Constructeur avec un objet JSON
25
	 * 
25
	 * 
26
	 * @param image
26
	 * @param image
27
	 */
27
	 */
28
	public ImageCarnet(JSONObject image) {
28
	public ImageCarnet(JSONObject image) {
29
		// l'objet JSON est une table de hachage
29
		// l'objet JSON est une table de hachage
30
		Set<String> im = image.keySet();
30
		Set<String> im = image.keySet();
31
 
31
 
32
		// on la parcourt pour chaque clé
32
		// on la parcourt pour chaque clé
33
		for (Iterator<String> iterator = im.iterator(); iterator.hasNext();) {
33
		for (Iterator<String> iterator = im.iterator(); iterator.hasNext();) {
34
 
34
 
35
			// si elle est associée à une valeur, on l'ajoute
35
			// si elle est associée à une valeur, on l'ajoute
36
			String key = iterator.next();
36
			String key = iterator.next();
37
			if (image.get(key).isString() != null) {
37
			if (image.get(key).isString() != null) {
38
				String valeur = image.get(key).isString().stringValue();
38
				String valeur = image.get(key).isString().stringValue();
39
				this.put(key, valeur);
39
				this.put(key, valeur);
40
			} else {
40
			} else {
41
				// sinon on ajoute la clé avec une valeur vide
41
				// sinon on ajoute la clé avec une valeur vide
42
				String valeur = " ";
42
				String valeur = " ";
43
				this.put(key, valeur);
43
				this.put(key, valeur);
44
			}
44
			}
45
 
45
 
46
		}
46
		}
47
 
47
 
48
	}
48
	}
49
 
49
 
50
	/**
50
	/**
51
	 * Surcharge de toString qui affiche toutes les propriétés de l'image
51
	 * Surcharge de toString qui affiche toutes les propriétés de l'image
52
	 */
52
	 */
53
 
53
 
54
	public String toString() {
54
	public String toString() {
55
		String valeur = " ";
55
		String valeur = " ";
56
 
56
 
57
		for (Iterator<String> iterator = this.keySet().iterator(); iterator
57
		for (Iterator<String> iterator = this.keySet().iterator(); iterator
58
				.hasNext();) {
58
				.hasNext();) {
59
 
59
 
60
			String key = iterator.next();
60
			String key = iterator.next();
61
			if (this.get(key) != null) {
61
			if (this.get(key) != null) {
62
				valeur += "cle : " + key + " valeur :" + this.get(key) + "\n";
62
				valeur += "cle : " + key + " valeur :" + this.get(key) + "\n";
63
			}
63
			}
64
 
64
 
65
		}
65
		}
66
 
66
 
67
		return valeur;
67
		return valeur;
68
	}
68
	}
69
 
69
 
70
	/**
70
	/**
71
	 * Pour éviter que l'on traite des valeurs nulles à l'affichage on passe par
71
	 * Pour éviter que l'on traite des valeurs nulles à l'affichage on passe par
72
	 * cette fonction qui retire les charactères nuls qui font planter
72
	 * cette fonction qui retire les charactères nuls qui font planter
73
	 * l'affichage, il ne faut pas utiliser get directement
73
	 * l'affichage, il ne faut pas utiliser get directement
74
	 * 
74
	 * 
75
	 * @param cle
75
	 * @param cle
76
	 * @return la valeur associée à la clé
76
	 * @return la valeur associée à la clé
77
	 */
77
	 */
78
	public String renvoyerValeurCorrecte(String cle) {
78
	public String renvoyerValeurCorrecte(String cle) {
79
		if (this.containsKey((cle))) {
79
		if (this.containsKey((cle))) {
80
			String valeur = this.get(cle);
80
			String valeur = this.get(cle);
81
			if (valeur.equals("null") || valeur == null) {
81
			if (valeur.equals("null") || valeur == null) {
82
				return " ";
82
				return " ";
83
			} else {
83
			} else {
84
				char nullChar = '\u0000';
84
				char nullChar = '\u0000';
85
				String sNull = "" + nullChar;
85
				String sNull = "" + nullChar;
86
				valeur = valeur.replaceAll(sNull, "");
86
				valeur = valeur.replaceAll(sNull, "");
87
				return valeur;
87
				return valeur;
88
			}
88
			}
89
		} else {
89
		} else {
90
			return " ";
90
			return " ";
91
		}
91
		}
92
	}
92
	}
93
 
93
 
94
	/**
94
	/**
95
	 * Acesseur pour l'id de l'image
95
	 * Acesseur pour l'id de l'image
96
	 * 
96
	 * 
97
	 * @return l'id de l'image
97
	 * @return l'id de l'image
98
	 */
98
	 */
99
	public String getId() {
99
	public String getId() {
100
 
100
 
101
		return renvoyerValeurCorrecte("ci_id_image");
101
		return renvoyerValeurCorrecte("ci_id_image");
102
	}
102
	}
103
 
103
 
104
	/**
104
	/**
105
	 * Acesseur pour le numero d'ordre de l'image
105
	 * Acesseur pour le numero d'ordre de l'image
106
	 * 
106
	 * 
107
	 * @return l'ordre de l'image
107
	 * @return l'ordre de l'image
108
	 */
108
	 */
109
	public String getOrdre() {
109
	public String getOrdre() {
110
 
110
 
111
		return renvoyerValeurCorrecte("ci_ordre");
111
		return renvoyerValeurCorrecte("ci_ordre");
112
	}
112
	}
113
 
113
 
114
	/**
114
	/**
115
	 * Base de l'url serveur pour les images
115
	 * Base de l'url serveur pour les images
116
	 * 
116
	 * 
117
	 * @return url racine pour les images
117
	 * @return url racine pour les images
118
	 */
118
	 */
119
	public String getBaseUrl() {
119
	public String getBaseUrl() {
120
		return Configuration.getImageBaseUrl() ;
120
		return Configuration.getImageBaseUrl() ;
121
	}
121
	}
122
 
122
 
123
	/**
123
	/**
124
	 * Renvoie le nom de base du fichier image et ses sous dossier
124
	 * Renvoie le nom de base du fichier image et ses sous dossier
125
	 * 
125
	 * 
126
	 * @return le nom de base du fichier de type (XXX_XXX_XXX), et ses sous
126
	 * @return le nom de base du fichier de type (XXX_XXX_XXX), et ses sous
127
	 *         dossier
127
	 *         dossier
128
	 */
128
	 */
129
	public String[] getBaseFileName() {
129
	public String[] getBaseFileName() {
130
		String id = getId();
130
		String id = getId();
131
 
131
 
132
		int maxZeros = 9 - id.length();
132
		int maxZeros = 9 - id.length();
133
 
133
 
134
		for (int i = 0; i < maxZeros; i++) {
134
		for (int i = 0; i < maxZeros; i++) {
135
			id = "0" + id;
135
			id = "0" + id;
136
		}
136
		}
137
 
137
 
138
		String dossierNv1 = id.substring(0, 3);
138
		String dossierNv1 = id.substring(0, 3);
139
		String dossierNv2 = id.substring(3, 6);
139
		String dossierNv2 = id.substring(3, 6);
140
		String fichierNv = id.substring(6, 9);
140
		String fichierNv = id.substring(6, 9);
141
 
141
 
142
		String nomFichier = dossierNv1 + "_" + dossierNv2 + "_" + fichierNv;
142
		String nomFichier = dossierNv1 + "_" + dossierNv2 + "_" + fichierNv;
143
 
143
 
144
		String[] infosFichier = { nomFichier, dossierNv1, dossierNv2 };
144
		String[] infosFichier = { nomFichier, dossierNv1, dossierNv2 };
145
		
145
		
146
		return infosFichier;
146
		return infosFichier;
147
	}
147
	}
-
 
148
	
-
 
149
	private String getUrlFormat(String format) {
-
 
150
		
-
 
151
		String[] infosFichier = getBaseFileName();
-
 
152
 
-
 
153
		return getBaseUrl() + infosFichier[1] + "/" + infosFichier[2] + "/"+format+"/"
-
 
154
				+ infosFichier[0] + "_"+format+".jpg";
-
 
155
	}
148
	
156
	
149
	/**
157
	/**
150
	 * Renvoie le chemin et nom du fichier format original
158
	 * Renvoie le chemin et nom du fichier format original
151
	 * 
159
	 * 
152
	 * @return le chemin du fichier grand original
160
	 * @return le chemin du fichier grand original
153
	 */
161
	 */
154
	public String getOUrl() {
162
	public String getUrlFormatOriginal() {
155
 
-
 
156
		String[] infosFichier = getBaseFileName();
-
 
157
 
163
 
158
		return getBaseUrl() + infosFichier[1] + "/" + infosFichier[2] + "/O/"
-
 
159
				+ infosFichier[0] + "_O.jpg";
164
		return getUrlFormat(Configuration.getFormatOriginal());
160
	}
165
	}
161
 
166
 
162
	/**
167
	/**
163
	 * Renvoie le chemin et nom du fichier grand format
168
	 * Renvoie le chemin et nom du fichier grand format
164
	 * 
169
	 * 
165
	 * @return le chemin du fichier grand format
170
	 * @return le chemin du fichier grand format
166
	 */
171
	 */
167
	public String getLUrl() {
172
	public String getUrlFormatZoom() {
168
 
173
 
169
		String[] infosFichier = getBaseFileName();
-
 
170
 
-
 
171
		return getBaseUrl() + infosFichier[1] + "/" + infosFichier[2] + "/X3L/"
-
 
172
				+ infosFichier[0] + "_X3L.jpg";
174
		return getUrlFormat(Configuration.getFormatZoom());
173
	}
175
	}
174
 
176
 
175
	/**
177
	/**
176
	 * Renvoie le chemin et nom du fichier petit format
178
	 * Renvoie le chemin et nom du fichier petit format
177
	 * 
179
	 * 
178
	 * @return le chemin du fichier petit format
180
	 * @return le chemin du fichier petit format
179
	 */
181
	 */
180
	public String getSUrl() {
182
	public String getUrlFormatGalerie() {
181
 
-
 
182
		String[] infosFichier = getBaseFileName();
-
 
183
 
183
 
184
		return getBaseUrl() + infosFichier[1] + "/" + infosFichier[2] + "/S/"
-
 
185
				+ infosFichier[0] + "_S.jpg";
184
		return getUrlFormat(Configuration.getFormatGalerie());
186
	}
185
	}
187
 
186
 
188
	/**
187
	/**
189
	 * Renvoie le chemin et nom du fichier moyen format
188
	 * Renvoie le chemin et nom du fichier moyen format
190
	 * 
189
	 * 
191
	 * @return le chemin du fichier moyen format
190
	 * @return le chemin du fichier moyen format
192
	 */
191
	 */
193
	public String getMUrl() {
192
	public String getUrlFormatListe() {
194
 
-
 
195
		String[] infosFichier = getBaseFileName();
-
 
196
 
193
 
197
		return getBaseUrl() + infosFichier[1] + "/" + infosFichier[2] + "/M/"
-
 
198
				+ infosFichier[0] + "_M.jpg";
194
		return getUrlFormat(Configuration.getFormatListe());
199
	}
195
	}
200
 
196
 
201
	/**
197
	/**
202
	 * Renvoie la taille de l'image
198
	 * Renvoie la taille de l'image
203
	 * 
199
	 * 
204
	 * @return un tableau de deux string contenant la hauteur puis la largeur
200
	 * @return un tableau de deux string contenant la hauteur puis la largeur
205
	 */
201
	 */
206
	public String[] getTailleImage() {
202
	public String[] getTailleImage() {
207
		String[] XY = { renvoyerValeurCorrecte("ci_meta_height"),
203
		String[] XY = { renvoyerValeurCorrecte("ci_meta_height"),
208
				renvoyerValeurCorrecte("ci_meta_width") };
204
				renvoyerValeurCorrecte("ci_meta_width") };
209
		return XY;
205
		return XY;
210
	}
206
	}
211
 
207
 
212
	public String[] getNote() {
208
	public String[] getNote() {
213
		String[] note = { renvoyerValeurCorrecte("ci_note_image") };
209
		String[] note = { renvoyerValeurCorrecte("ci_note_image") };
214
		return note;
210
		return note;
215
	}
211
	}
216
 
212
 
217
	/**
213
	/**
218
	 * Renvoie la date exif associée à l'image
214
	 * Renvoie la date exif associée à l'image
219
	 * 
215
	 * 
220
	 * @return la date associée à l'image
216
	 * @return la date associée à l'image
221
	 */
217
	 */
222
	public String getDate() {
218
	public String getDate() {
223
 
219
 
224
		if(renvoyerValeurCorrecte("ci_meta_date").equals("00/00/0000"))
220
		if(renvoyerValeurCorrecte("ci_meta_date").equals("00/00/0000"))
225
		{
221
		{
226
			return "" ;
222
			return "" ;
227
		}
223
		}
228
		return renvoyerValeurCorrecte("ci_meta_date");
224
		return renvoyerValeurCorrecte("ci_meta_date");
229
	}
225
	}
230
 
226
 
231
	/**
227
	/**
232
	 * Renvoie la ville associée à l'image
228
	 * Renvoie la ville associée à l'image
233
	 * 
229
	 * 
234
	 * @return la ville iptc
230
	 * @return la ville iptc
235
	 */
231
	 */
236
	public Object getIptcCity() {
232
	public Object getIptcCity() {
237
 
233
 
238
		return renvoyerValeurCorrecte("ci_meta_iptc_city");
234
		return renvoyerValeurCorrecte("ci_meta_iptc_city");
239
	}
235
	}
240
 
236
 
241
	/**
237
	/**
242
	 * Renvoie le fabricant de l'appareil
238
	 * Renvoie le fabricant de l'appareil
243
	 * 
239
	 * 
244
	 * @return le fabricant
240
	 * @return le fabricant
245
	 */
241
	 */
246
	public String getMake() {
242
	public String getMake() {
247
 
243
 
248
		return renvoyerValeurCorrecte("ci_meta_make");
244
		return renvoyerValeurCorrecte("ci_meta_make");
249
	}
245
	}
250
 
246
 
251
	/**
247
	/**
252
	 * Renvoie le modele de l'appareil
248
	 * Renvoie le modele de l'appareil
253
	 * 
249
	 * 
254
	 * @return le modele
250
	 * @return le modele
255
	 */
251
	 */
256
	public String getModel() {
252
	public String getModel() {
257
 
253
 
258
		return renvoyerValeurCorrecte("ci_meta_model");
254
		return renvoyerValeurCorrecte("ci_meta_model");
259
	}
255
	}
260
 
256
 
261
	/**
257
	/**
262
	 * Renvoie un tableau nom / valeur de toutes les metadonnées Iptc
258
	 * Renvoie un tableau nom / valeur de toutes les metadonnées Iptc
263
	 * 
259
	 * 
264
	 * @return les métadonnées iptc
260
	 * @return les métadonnées iptc
265
	 */
261
	 */
266
	public String[][] getMetadonnesIptc() {
262
	public String[][] getMetadonnesIptc() {
267
 
263
 
268
		String[][] metaIptc = new String[14][2];
264
		String[][] metaIptc = new String[14][2];
269
		int elem = 0;
265
		int elem = 0;
270
 
266
 
271
		for (Iterator<String> it = this.keySet().iterator(); it.hasNext();) {
267
		for (Iterator<String> it = this.keySet().iterator(); it.hasNext();) {
272
 
268
 
273
			String key = it.next();
269
			String key = it.next();
274
 
270
 
275
			// on filtre le "ci"
271
			// on filtre le "ci"
276
			String type[] = key.split("_", 3);
272
			String type[] = key.split("_", 3);
277
 
273
 
278
			// si c'est une metadonnee exif ou iptc
274
			// si c'est une metadonnee exif ou iptc
279
			if (type[1].equals("meta")) {
275
			if (type[1].equals("meta")) {
280
				String[] genre = type[2].split("_", 2);
276
				String[] genre = type[2].split("_", 2);
281
				if (genre[0].equals("iptc")) {
277
				if (genre[0].equals("iptc")) {
282
					String nom = genre[1];
278
					String nom = genre[1];
283
					metaIptc[elem][0] = nom;
279
					metaIptc[elem][0] = nom;
284
					metaIptc[elem][1] = renvoyerValeurCorrecte(key);
280
					metaIptc[elem][1] = renvoyerValeurCorrecte(key);
285
					elem++;
281
					elem++;
286
				}
282
				}
287
 
283
 
288
			}
284
			}
289
 
285
 
290
		}
286
		}
291
 
287
 
292
		return metaIptc;
288
		return metaIptc;
293
	}
289
	}
294
 
290
 
295
	/**
291
	/**
296
	 * Renvoie un tableau nom / valeur de toutes les metadonnées Exif
292
	 * Renvoie un tableau nom / valeur de toutes les metadonnées Exif
297
	 * 
293
	 * 
298
	 * @return les métadonnées Exif
294
	 * @return les métadonnées Exif
299
	 */
295
	 */
300
	public String[][] getMetadonnesExif() {
296
	public String[][] getMetadonnesExif() {
301
 
297
 
302
		String[][] metaExif = new String[31][2];
298
		String[][] metaExif = new String[31][2];
303
		int elem = 0;
299
		int elem = 0;
304
 
300
 
305
		for (Iterator<String> it = this.keySet().iterator(); it.hasNext();) {
301
		for (Iterator<String> it = this.keySet().iterator(); it.hasNext();) {
306
 
302
 
307
			String key = it.next();
303
			String key = it.next();
308
 
304
 
309
			// on filtre le "ci"
305
			// on filtre le "ci"
310
			String type[] = key.split("_", 3);
306
			String type[] = key.split("_", 3);
311
 
307
 
312
			// si c'est une metadonnee exif ou iptc
308
			// si c'est une metadonnee exif ou iptc
313
			if (type[1].equals("meta")) {
309
			if (type[1].equals("meta")) {
314
				String[] genre = type[2].split("_", 2);
310
				String[] genre = type[2].split("_", 2);
315
				if (genre[0].equals("exif")) {
311
				if (genre[0].equals("exif")) {
316
					String nom = genre[1];
312
					String nom = genre[1];
317
					metaExif[elem][0] = nom;
313
					metaExif[elem][0] = nom;
318
					metaExif[elem][1] = renvoyerValeurCorrecte(key);
314
					metaExif[elem][1] = renvoyerValeurCorrecte(key);
319
					elem++;
315
					elem++;
320
				}
316
				}
321
 
317
 
322
			}
318
			}
323
 
319
 
324
		}
320
		}
325
 
321
 
326
		return metaExif;
322
		return metaExif;
327
 
323
 
328
	}
324
	}
329
 
325
 
330
	/**
326
	/**
331
	 * Renvoie un tableau nom / valeur contenant les infos générales
327
	 * Renvoie un tableau nom / valeur contenant les infos générales
332
	 * 
328
	 * 
333
	 * @return les infos générales
329
	 * @return les infos générales
334
	 */
330
	 */
335
	public String[][] getInfoGenerales() {
331
	public String[][] getInfoGenerales() {
336
 
332
 
337
		String[][] metaGen = new String[2][2];
333
		String[][] metaGen = new String[2][2];
338
 
334
 
339
		metaGen[0][0] = "ci_meta_comment";
335
		metaGen[0][0] = "ci_meta_comment";
340
		metaGen[0][1] = this.renvoyerValeurCorrecte("ci_meta_comment");
336
		metaGen[0][1] = this.renvoyerValeurCorrecte("ci_meta_comment");
341
 
337
 
342
		metaGen[1][0] = "ci_meta_date";
338
		metaGen[1][0] = "ci_meta_date";
343
		metaGen[1][1] = this.renvoyerValeurCorrecte("ci_meta_date");
339
		metaGen[1][1] = this.renvoyerValeurCorrecte("ci_meta_date");
344
 
340
 
345
		return metaGen;
341
		return metaGen;
346
	}
342
	}
347
 
343
 
348
	/**
344
	/**
349
	 * Renvoie une string contenant les mots clés séparés par des ','
345
	 * Renvoie une string contenant les mots clés séparés par des ','
350
	 * 
346
	 * 
351
	 * @return les mots clés
347
	 * @return les mots clés
352
	 */
348
	 */
353
	public String getMotsCles() {
349
	public String getMotsCles() {
354
 
350
 
355
		return renvoyerValeurCorrecte("ci_meta_mots_cles");
351
		return renvoyerValeurCorrecte("ci_meta_mots_cles");
356
	}
352
	}
357
 
353
 
358
	/**
354
	/**
359
	 * Met à jour le commenentaire et la date
355
	 * Met à jour le commenentaire et la date
360
	 * 
356
	 * 
361
	 * @param commentaires
357
	 * @param commentaires
362
	 *            le nouveau commentaire
358
	 *            le nouveau commentaire
363
	 * @param date
359
	 * @param date
364
	 *            la nouvelle date
360
	 *            la nouvelle date
365
	 */
361
	 */
366
	public void miseAJourInfoGenerales(String commentaires, String date,
362
	public void miseAJourInfoGenerales(String commentaires, String date,
367
			String note) {
363
			String note) {
368
		put("ci_meta_comment", commentaires);
364
		put("ci_meta_comment", commentaires);
369
		put("ci_note_image", note);
365
		put("ci_note_image", note);
370
		put("ci_meta_date", date);
366
		put("ci_meta_date", date);
371
	}
367
	}
372
 
368
 
373
	/**
369
	/**
374
	 * Met à jour les mots clés
370
	 * Met à jour les mots clés
375
	 * 
371
	 * 
376
	 * @param motsClesEnCours
372
	 * @param motsClesEnCours
377
	 *            la liste de mots clés séparés par des ','
373
	 *            la liste de mots clés séparés par des ','
378
	 */
374
	 */
379
	public void mettreAjourMotsCles(String motsClesEnCours) {
375
	public void mettreAjourMotsCles(String motsClesEnCours) {
380
 
376
 
381
		put("ci_meta_mots_cles", motsClesEnCours);
377
		put("ci_meta_mots_cles", motsClesEnCours);
382
 
378
 
383
	}
379
	}
384
	
380
	
385
	public void mettreAjourObsAssociees(String idsObsAssociees) {
381
	public void mettreAjourObsAssociees(String idsObsAssociees) {
386
		put("ci_ce_observation", idsObsAssociees);
382
		put("ci_ce_observation", idsObsAssociees);
387
	}
383
	}
388
	
384
	
389
	/**
385
	/**
390
	 * Accesseur pour le nom original
386
	 * Accesseur pour le nom original
391
	 * 
387
	 * 
392
	 * @return le nom orginal de l'image
388
	 * @return le nom orginal de l'image
393
	 */
389
	 */
394
	public String getNomOriginal() {
390
	public String getNomOriginal() {
395
		return renvoyerValeurCorrecte("ci_nom_original");
391
		return renvoyerValeurCorrecte("ci_nom_original");
396
	}
392
	}
397
	
393
	
398
	public String getIdsObsAssociees() {
394
	public String getIdsObsAssociees() {
-
 
395
		
399
		return renvoyerValeurCorrecte("ci_ce_observation");
396
		String observationsAssociees = renvoyerValeurCorrecte("ci_ce_observation");
-
 
397
		observationsAssociees = observationsAssociees.replaceAll("null", "");
-
 
398
		
-
 
399
		return observationsAssociees;
400
	}
400
	}
401
 
401
 
402
}
402
}