Bonjour,
J'ai un problème assez gênant: je perd des données... Je m'explique mais c'est un peu long.
J'ai des TypeMesure qui contienent des Mesures qui sont liées à des DateMesures, des ProfondeurMesure, des PositionMesure et un paramètre physique.
Les TypeMesure ont aussi 2 attributs qui me servent par la suite (numéro de cast et numéro de station).
Or j'ai besoin d'imprimer les mesures par ordre de date, puis de position et ainsi de suite dans un fichier. Mes données étant dans une base de données (Postgre) avec hybernate/spring au milieu.
Donc le service web me donne tous les TypeMesure (une List en fait) qu'il souhaite imprimer et moi je me débrouille.
Voilà à quoi ressemble le code de la méthode principale:
La méthode prepareData (qui construit la map de maps)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 /** * Ecrit l'ensemble des données dans le fichier. * * @param typeMesure les type mesure à ecrire. * @throws IOException si problème avec les fichiers */ void writeData(List<TypeMesure> typeMesure) throws IOException { TreeMap<DateMesure, TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>> map = prepareData(typeMesure); boolean writeFirstLine = true; // on iter sur la map pour savoir ce qu'on écrit ou pas for (DateMesure dateMesure : map.navigableKeySet()) { TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>> treeMapDateMesure = map .get(dateMesure); for (PositionMesure positionMesure : treeMapDateMesure .navigableKeySet()) { TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>> treeMapPositionMesure = treeMapDateMesure .get(positionMesure); // /!\ BUG // treeMapPositionMesure peut être null ici // /!\ BUG for (ProfondeurMesure profondeurMesure : treeMapPositionMesure .navigableKeySet()) { TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>> treeMapProfondeurMesure = treeMapPositionMesure .get(profondeurMesure); for (Integer castCourrant : treeMapProfondeurMesure .navigableKeySet()) { TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>> treeMapCastCourrant = treeMapProfondeurMesure .get(castCourrant); for (Integer stationCourrant : treeMapCastCourrant .navigableKeySet()) { // on imprime les données // mais c'est pas le problème if (writeFirstLine) { writeFirstLine = false; } } } } } } }
La méthode qui construit les map intermédiaires si besoin, et retourne la dernière map, là où sont ajoutée les données.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 /** * Prépare les données sous une forme plus manipulable par la suite. * * @param typeMesureList la liste des type mesure à manipuler * @return la map */ TreeMap<DateMesure, TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>> prepareData( List<TypeMesure> typeMesureList) { // On commence par trier les donner dans des liste (pour les éléments // commun) et dans une map pour toutes les mesures qu'on pourrai // rencontrer. // DateMesure -> PositionMesure -> ProfondeurMesure -> NumCast -> // NumStation -> ParamPhy -> Mesure TreeMap<DateMesure, TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>> map = new TreeMap<DateMesure, TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>>( COMPARATOR_DATE_MESURE); for (TypeMesure typeMesure : typeMesureList) { Set<Mesure> mesureSet = typeMesure.getMesureSet(); // on récupère les numéros cast et numéros station si on les as Integer currentCast = null; Integer currentStation = null; // le code a été enlevé pour la lisibilité // il ne manipule pas l'objet map ni les mesure il ne touche qu'aux currentCast, currentStation et typeMesure for (Mesure mesure : mesureSet) { ParametrePhysique parametrePhysique = mesure .getParametrePhysique(); // le code important est ici ! TreeMap<ParametrePhysique, Mesure> treeMapStation = getLastSubMap( map, currentCast, currentStation, mesure); // enfin on stock le paramètre treeMapStation.put(parametrePhysique, mesure); } debugPrintMap(map, "Map for: " + typeMesure.toString()); } debugPrintMap(map, "First Map"); return map; }
Les comparator utilisés pour les TreeMap:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 /** * Retourne la sous map nécessaire au stockage de la mesure * * @param map la map global * @param currentCast le numéro cast courrant * @param currentStation le numéro station courrant * @param mesure la mesure à stocker (n'est pas stockée dans la map!) * @return la map dans laquelle on stock la donnée */ TreeMap<ParametrePhysique, Mesure> getLastSubMap( TreeMap<DateMesure, TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>> map, Integer currentCast, Integer currentStation, Mesure mesure) { DateMesure dateMesure = mesure.getDateMesure(); PositionMesure positionMesure = mesure.getPositionMesure(); ProfondeurMesure profondeurMesure = mesure.getProfondeurMesure(); // on crée la sous map pour la date si elle n'existe pas if (!map.containsKey(dateMesure)) { map.put( dateMesure, new TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>>( COMPARATOR_POSITION_MESURE)); } TreeMap<PositionMesure, TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>> treeMapDateMesure = map .get(dateMesure); if (!treeMapDateMesure.containsKey(positionMesure)) { treeMapDateMesure.put( positionMesure, new TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>>( COMPARATOR_PROFONDEUR_MESURE)); } TreeMap<ProfondeurMesure, TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>> treeMapPositionMesure = treeMapDateMesure .get(positionMesure); if (!treeMapPositionMesure.containsKey(profondeurMesure)) { treeMapPositionMesure.put( profondeurMesure, new TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>>( COMPARATOR_INTEGER)); } TreeMap<Integer, TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>> treeMapProfondeurMesure = treeMapPositionMesure .get(profondeurMesure); if (!treeMapProfondeurMesure.containsKey(currentCast)) { treeMapProfondeurMesure.put(currentCast, new TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>>( COMPARATOR_INTEGER)); } TreeMap<Integer, TreeMap<ParametrePhysique, Mesure>> treeMapCast = treeMapProfondeurMesure .get(currentCast); if (!treeMapCast.containsKey(currentStation)) { treeMapCast.put(currentStation, new TreeMap<ParametrePhysique, Mesure>(COMPARATOR_PARAM_PHY)); } TreeMap<ParametrePhysique, Mesure> treeMapStation = treeMapCast .get(currentStation); return treeMapStation; }
Les méthodes utilisées pour imprimer une map:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 private final class DateMesureComparator implements Comparator<DateMesure> { /** {@inheritDoc} */ @Override public int compare(DateMesure o1, DateMesure o2) { int result = o1.getDate().compareTo(o2.getDate()); if (result == 0) { // les valeurs sont identiques mais ce ne sont peut-être pas les // même dates int o1Id = o1.getId(); int o2Id = o2.getId(); if (o1Id < o2Id) { result = -1; } else if (o1Id > o2Id) { result = 1; } } return result; } } private final class ProfondeurMesureComparator implements Comparator<ProfondeurMesure> { /** {@inheritDoc} */ @Override public int compare(ProfondeurMesure o1, ProfondeurMesure o2) { float o1Prof = o1.getProfondeur(); float o2Prof = o2.getProfondeur(); int result = 0; if (o1Prof < o2Prof) { result = -1; } else if (o1Prof > o2Prof) { result = 1; } if (result == 0) { // les profondeur sont peut-être identique en valeur mais pas en // ID int o1Id = o1.getId(); int o2Id = o2.getId(); if (o1Id < o2Id) { result = -1; } else if (o1Id > o2Id) { result = 1; } } return result; } } private final class PositionMesureComparator implements Comparator<PositionMesure> { /** {@inheritDoc} */ @Override public int compare(PositionMesure o1, PositionMesure o2) { float o1Lat = o1.getLatitude(); float o1Long = o1.getLongitude(); float o2Lat = o2.getLatitude(); float o2Long = o2.getLongitude(); int result = 0; if (o1Lat == o2Lat) { if (o1Long < o2Long) { result = -1; } else if (o1Long > o2Long) { result = 1; } } else if (o1Lat < o2Lat) { result = -1; } else if (o1Lat > o2Lat) { result = 1; } if (result == 0) { int o1Id = o1.getId(); int o2Id = o2.getId(); if (o1Id < o2Id) { result = -1; } else if (o1Id > o2Id) { result = 1; } } return result; } } private final class IntegerComparator implements Comparator<Integer> { /** {@inheritDoc} */ @Override public int compare(Integer o1, Integer o2) { if (o1 == null && o2 == null) { return 0; } if (o1 == null && o2 != null) { return -1; } if (o1 != null && o2 == null) { return 1; } return o1.compareTo(o2); } } private final class ParametrePhysiqueComparator implements Comparator<ParametrePhysique> { /** {@inheritDoc} */ @Override public int compare(ParametrePhysique o1, ParametrePhysique o2) { // on compare les chaines de caractère des différents code return o1.getCodeRoscop().compareTo(o2.getCodeRoscop()); } } private final Comparator<DateMesure> COMPARATOR_DATE_MESURE = new DateMesureComparator(); private final Comparator<ProfondeurMesure> COMPARATOR_PROFONDEUR_MESURE = new ProfondeurMesureComparator(); private final Comparator<PositionMesure> COMPARATOR_POSITION_MESURE = new PositionMesureComparator(); private final Comparator<Integer> COMPARATOR_INTEGER = new IntegerComparator(); private final Comparator<ParametrePhysique> COMPARATOR_PARAM_PHY = new ParametrePhysiqueComparator();
La méthode utilisée pour le "toString" sur mes objets métiers.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 protected void debugPrintMap(Map map, String header) { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); File file = new File("D:\\testMap" + sdf.format(new Date())); try { DataOutputStream out = new DataOutputStream(new FileOutputStream( file)); out.writeBytes(header); out.writeBytes("\n"); debugPrintMap(map, out); out.flush(); out.close(); } catch (Exception e) { LOG.debug("aie..."); e.printStackTrace(); } } protected void debugPrintMap(Map map, DataOutputStream out2) throws IOException { debugPrintMap(map, out2, 0); } protected void debugPrintMap(Map map, DataOutputStream out2, int level) throws IOException { int nextLevel = level + 1; out2.writeBytes("{\n"); for (Object key : map.keySet()) { Object value = map.get(key); levelString(out2, level); if (key != null) { out2.writeBytes(key.toString()); } else { out2.writeBytes("null"); } out2.writeBytes(" : "); if (value instanceof Map) { debugPrintMap((Map) value, out2, nextLevel); } else { if (value != null) { out2.writeBytes(value.toString()); } else { out2.writeBytes("null"); } out2.writeBytes(",\n"); } } levelString(out2, level); out2.writeBytes("}\n"); } protected void levelString(DataOutputStream out2, int level) throws IOException { if (level != 0) { out2.writeBytes("\t"); levelString(out2, --level); } }
Id étant l'identifiant en base.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(this.getClass().getSimpleName()); sb.append("@"); sb.append(Integer.toHexString(hashCode())); sb.append("{"); sb.append("id : "); sb.append(id); sb.append("}"); return sb.toString(); }
Bon, ça fait peut-être un peu beaucoup de code, je vous l'accorde...
Mon problème est que lors de l'écriture, j'ai un NullPointerException qui apparait dans la première méthode (writeData). L'endroit est signalé par un commentaire ici.
Alors que dans la méthode getLastSubMap (qui construit la map de maps) je n'aie pas d'exception et je devrai si j'avais un éléments null.
J'ai fait des impressions de map avec ma fonction de debug, et comparé les sortie et j'ai effectivement des données null (mais jamais les mêmes et jamais certaines en écrasent d'autres).
Il est à noter que j'ai un nombre important de Mesure (~14 000 au max), mais que même en limitant ce nombre (~4 000) j'ai toujours le problème.
Si vous avez la moindre idée, je suis très preneur !!
PS: ci-joint les sortie text généré par debugPrintMap sur 2 essaie différents (vous pourrez voir le caractère aléatoire comme ça)
Partager