IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

APIs Google Discussion :

Dévélopper une application de géolocalisation [Google Maps]


Sujet :

APIs Google

  1. #1
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 35
    Points : 17
    Points
    17
    Par défaut Dévélopper une application de géolocalisation
    Je souhaite développé une application de géolocalisation pour des équipements tels que les décodeurs histoire d'optimiser les interventions des techniciens chez les clients abonnés d'un Fournisseur d'Accès internet /Télévision Numérique & Téléphonie.
    Je suis novice dans le développement sur Google Maps API V3 et j'ai besoin des conseils pour démarrer mon projet ainsi que des Tutos qui pourront m'aider.

  2. #2
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    Bonjour,
    difficile de répondre juste comme cela!

    L'intégration d'un Map Google ne relève d'aucun exploit.
    FAQ API Google Maps

    La géolocalisation ce fait tout aussi simplement
    L'API geolocalisation en HTML5

    Pour le reste il s'agit de la gestion d'une base de données et de l'interrogation de celles ci.

    Mais pour commencer il suffit de bien définir son besoin

  3. #3
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 35
    Points : 17
    Points
    17
    Par défaut Afficher les marquers de différentes couleurs
    Bonsoir à tous J'ai avancé dans mon application de géolocalisation et elle est presque en phase terminale. Je devais attaquer une base de données de monitoring pour afficher l'état de mes équipements et leur emplacement sur la carte Google Maps. C'est à dire lorsque l'équipement est Up j'affiche le marqueur vert et lorsque l'équipement est Down j'affiche le marqueur Rouge. J'ai regardé un exemple sur google et on m'a conseillé ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     var customIcons = {
          restaurant: {
            icon: 'image1.png'
          },
          bar: {
            icon: 'image2.png'
          }
        };
    Mais la table avec laquelle je travaille dans ma base de données cet attribut est un entier donc l'attribut Status vaut 1 quand l'équipement est Up et 2 quand l'équipement est Down.
    Du coup j'ai transformé le code en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     var customIcons = {
          1: {
            icon: 'image1.png'
          },
          2: {
            icon: 'image2.png'
          }
        };
    Mais malheureusement il ne fonctionne pas. je voudrais savoir comment je peux appliquer cette structure avec des entiers et non des chaines de caractères.

  4. #4
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    Mais malheureusement il ne fonctionne pas. je voudrais savoir comment je peux appliquer cette structure avec des entiers et non des chaines de caractères.
    Ta deuxième syntaxe est tout à fait correcte seulement pour l'appel il faut faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    console.log( customIcons[2].icon);  // affiche image2.png
    Dans ton cas pourquoi ne pas plutôt passer par un Array si tu n'a pas plus de chose à mettre dans tes objets.

  5. #5
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 35
    Points : 17
    Points
    17
    Par défaut Google Maps API V3
    Merci pour l'aide mais je sais pas à quel niveau je suis sensé faire l'appel.
    Voici l'intégralité.
    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
     
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
        <title>Google Maps AJAX + mySQL/PHP Example</title>
        <script src="http://maps.google.com/maps/api/js?sensor=false"
                type="text/javascript"></script>
        <script type="text/javascript">
        //<![CDATA[
        // Je veux donc afficher le marker 4 quand l'attribut type vaut 1 et le marker 3 quand l'attribut type vaut 2
        var customIcons = {
          1: {
            icon: 'marker4.png',
          },
          2: {
            icon: 'marker3.png',
          }
        };
     
        function load() {
          var map = new google.maps.Map(document.getElementById("map"), {
            center: new google.maps.LatLng(47.6145, -122.3418),
            zoom: 13,
            mapTypeId: 'roadmap'
          });
          var infoWindow = new google.maps.InfoWindow;
     
          // Change this depending on the name of your PHP file
          downloadUrl("phpsqlajax_genxml2.php", function(data) {
            var xml = data.responseXML;
            var markers = xml.documentElement.getElementsByTagName("marker");
            for (var i = 0; i < markers.length; i++) {
              var name = markers[i].getAttribute("name");
              var address = markers[i].getAttribute("address");
              var type = markers[i].getAttribute("type");
              var point = new google.maps.LatLng(
                  parseFloat(markers[i].getAttribute("lat")),
                  parseFloat(markers[i].getAttribute("lng")));
              var html = "<b>" + name + "</b> <br/>" + address;
              var icon = customIcons[type] || {};
              var marker = new google.maps.Marker({
                map: map,
                position: point,
                icon: icon.icon,
                shadow: icon.shadow
              });
              bindInfoWindow(marker, map, infoWindow, html);
            }
          });
        }
     
        function bindInfoWindow(marker, map, infoWindow, html) {
          google.maps.event.addListener(marker, 'click', function() {
            infoWindow.setContent(html);
            infoWindow.open(map, marker);
          });
        }
     
        function downloadUrl(url, callback) {
          var request = window.ActiveXObject ?
              new ActiveXObject('Microsoft.XMLHTTP') :
              new XMLHttpRequest;
     
          request.onreadystatechange = function() {
            if (request.readyState == 4) {
              request.onreadystatechange = doNothing;
              callback(request, request.status);
            }
          };
     
          request.open('GET', url, true);
          request.send(null);
        }
     
        function doNothing() {}
     
        //]]>
      </script>
      </head>
     
      <body onload="load()">
        <div id="map" style="width: 100%; height: 100%"></div>
      </body>
    </html>
    C'est la page HTML qui lance la carte. j'ai un fichier php qui se charge de récupérer les informations dans la base de données et le parser en xml.

  6. #6
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    Dans ce que tu proposes je vois au moins une erreur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var marker = new google.maps.Marker({
        map: map,
        position: point,
        icon: icon.icon,
        shadow: icon.shadow   // icon.shadow N'EST PAS DEFINI
    });
    et une interrogation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    downloadUrl("phpsqlajax_genxml2.php", function(data) {
    var xml = data.responseXML;
    es tu sûr que data est au format XMLHttpRequest?

  7. #7
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 35
    Points : 17
    Points
    17
    Par défaut Google Maps API V3
    Oui Data est au format XMLHTTPRequest. Le problème est que j'ai regardé dans ma base de données j'ai prit un attribut qui est une chaine de caractères(Protocole) j'ai fait le test ça passe normalement les icônes rouges pour SNMP et vertes pour ICMP s'affichent normalement. c'est pourquoi je suis sûre que mon problème viens de ma structure javascript suivante.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    var customIcons = {
          1: {
            icon: 'green.png'
          },
          bar: {
            2: 'red.png'
          }
        };
    var icon = customIcons[Status] || {};
    Car avec l'attribut chaîne de caractère le code fonctionne à merveille.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    var customIcons = {
          SNMP: {
            icon: 'green.png'
          },
          ICMP: {
            icon: 'red.png'
          }
        };
    var icon = customIcons[Protocole] || {};
    Et c'est la table avec la chaine de caractère que je dois utilisé donc je sais plus comment faire.
    Aurez vous une solution.

  8. #8
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut !!!!
    Regarde bien les 2 structures que tu proposes, elles ne sont PAS IDENTIQUES !

  9. #9
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 35
    Points : 17
    Points
    17
    Par défaut Google Maps API V3
    je ne vois pas la différence elle est a quelle niveau. Mon problème est que cherche comment pouvoir utiliser les entiers avec ce type de structure pour pouvoir afficher 2 couleurs de maqueurs le vert lorsque le Status = 1 et le rouge lorsque Status = 2. est ce que c'est possible? Puisque avec les entiers ça passe normalement.

  10. #10
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    c'est le jeux des 7 erreurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    var customIcons = {
          1: {
            icon: 'green.png'
          },
          bar: {
            2: 'red.png'
          }
        };
    et il te faudra choisir entre status et protocole.

  11. #11
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 35
    Points : 17
    Points
    17
    Par défaut Google Maps API V3
    Oui C'est vrai dans ma base de données SQL Server la table que je manipule s'appelle dbo.nodes. Maintenant l'attribut que je dois utilisé c'est Status car c'est cette table qui me renseigne sur l'état propre des équipements monitoré. Status = 1 lorsque l'équipement est Up et Status = 2 lorsque l'équipement est Down.
    C'est pour cela que j'ai utilisé cette structure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     var customIcons = {
          1: {
            icon: 'Vert.png'
          },
          2: {
            icon: 'red.png'
          }
        };
    Mais elle ne fonctionne pas. pour voir si le code avait un problème j'ai donc prit pour les test l'attribut Protocole (Puisque l'attribut protocole ne résous pas mon problème je ne peux pas l'utiliser c'est juste pour tester) j'ai donc éssayé ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    var customIcons = {
          SNMP: {
            icon: 'Vert.png'
          },
          ICMP: {
            icon: 'red.png'
          }
        };
    Et je me suis rendu compte que cela fonctionnait bien les marqueurs changeait de couleur vert pour les équipements managé par le protocole SNMP et rouge pour ceux managés par le protocole ICMP. Mais ceci ne me sers absolument à rien.
    J'aimerais qu'on me corrige la structure avec les entiers 1 et 2 Car le code que vous m'avez proposé n'est pas adéquat.

  12. #12
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    Es tu sûr que les valeurs extraites sont 1 et 2 et qu'il n'y a pas de caractères parasites comme un espace après par exemple.

  13. #13
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 35
    Points : 17
    Points
    17
    Par défaut Google Maps API V3
    En effet voici une capture de la table Status comme vous voyez il y'a des équipements dont le Status vaut 1 ils sont Up et ceux dont le Status vaut 2 ils sont Down. Je voudrait donc que ma structure me permette d'afficher un marqueur de couleur différente selon la valeur de l'attribut Status. Le type de status dans la base est Status(char(20),null). Alors que l'attribut qui marchait bien mais qui n'est pas nécessaire est Protocol(nvarchar(50),null). C'est peut être à ce niveau que la différence ce joue mais je sait pas à quel niveau. J'attends vos suggestion. Merci
    Nom : Base de Données.PNG
Affichages : 3088
Taille : 56,6 Ko

  14. #14
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    Si tu ne sais pas à partir de TES donées générer TON fichier XML alors essaie de faire un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var type = parseInt (markers[i].getAttribute("type"));

  15. #15
    Membre à l'essai
    Inscrit en
    Janvier 2011
    Messages
    35
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 35
    Points : 17
    Points
    17
    Par défaut Google Maps API V3
    C'est parfait mon application fonctionne parfaitement. Il fallait faire le ParseInt sur la variable Status. Ma carte Google Maps s'affiche avec les marqueurs rouges lorsque l'équipement est Down (Status = Down) et vert lorsque l'équipement est Up (Status = Up). Je continue quand même à avancé et j'ai toujours besoin de vous car maintenant que les équipements sont représentés sur la carte je veux pouvoir tracer un itinéraire entre deux équipements. c'est à dire lorsque la carte est ouverte je veux choisir un bouton qui me dirait par exemple tracer un itinéraire et je pourrai dessiner l'itinéraire avec ma souris suivant les directions que je choisirais comme le fait par exemple Google Map Maker. J'ai fait des recherches pour savoir comment avoir le code de Google Map Maker ou comment avoir une documentation pour adapter certaines fonctionnalités de MapMaker à mon application. J'ai trouver ce code je l'ai étudié je ne sais pas si il résoudra mon problème mais je vous le présente quand même.
    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
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    654
    655
    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
    666
    667
    668
    669
    670
    671
    672
    673
    674
    675
    676
    677
    678
    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    691
    692
    693
    694
    695
    696
    697
    698
    699
    700
    701
    702
    703
    704
    705
    706
    707
    708
    709
    710
    711
    712
    713
    714
    715
    716
    717
    718
    719
    720
    721
    722
    723
    724
    725
    726
    727
    728
    729
    730
    731
    732
    733
    734
    735
    736
    737
    738
    739
    740
    741
    742
    743
    744
    745
    746
    747
    748
    749
    750
    751
    752
    753
    754
    755
    756
    757
    758
    759
    760
    761
    762
    763
    764
    765
    766
    767
    768
    769
    770
    771
    772
    773
    774
    775
    776
    777
    778
    779
    780
    781
    782
    783
    784
    785
    786
    787
    788
    789
    790
    791
    792
    793
    794
    795
    796
    797
    798
    799
    800
    801
    802
    803
    804
    805
    806
    807
    808
    809
    810
    811
    812
    813
    814
    815
    816
    817
    818
    819
    820
    821
    822
    823
    824
    825
    826
    827
    828
    829
    830
    831
    832
    833
    834
    835
    836
    837
    838
    839
    840
    841
    842
    843
    844
    845
    846
    847
    848
    849
    850
    851
    852
    853
    854
    855
    856
    857
    858
    859
    860
    861
    862
    863
    864
    865
    866
    867
    868
    869
    870
    871
    872
    873
    874
    875
    876
    877
    878
    879
    880
    881
    882
    883
    884
    885
    886
    887
    888
    889
    890
    891
    892
    893
    894
    895
    896
    897
    898
    899
    900
    901
    902
    903
    904
    905
    906
    907
    908
    909
    910
    911
    912
    913
    914
    915
    916
    917
    918
    919
    920
    921
    922
    923
    924
    925
    926
    927
    928
    929
    930
    931
    932
    933
    934
    935
    936
    937
    938
    939
    940
    941
    942
    943
    944
    945
    946
    947
    948
    949
    950
    951
    952
    953
    954
    955
    956
    957
    958
    959
    960
    961
    962
    963
    964
    965
    966
    967
    968
    969
    970
    971
    972
    973
    974
    975
    976
    977
    978
    979
    980
    981
    982
    983
    984
    985
    986
    987
    988
    989
    990
    991
    992
    993
    994
    995
    996
    997
    998
    999
    1000
    1001
    1002
    1003
    1004
    1005
    1006
    1007
    1008
    1009
    1010
    1011
    1012
    1013
    1014
    1015
    1016
    1017
    1018
    1019
    1020
    1021
    1022
    1023
    1024
    1025
    1026
    1027
    1028
    1029
    1030
    1031
    1032
    1033
    1034
    1035
    1036
    1037
    1038
    1039
    1040
    1041
    1042
    1043
    1044
    1045
    1046
    1047
    1048
    1049
    1050
    1051
    1052
    1053
    1054
    1055
    1056
    1057
    1058
    1059
    1060
    1061
    1062
    1063
    1064
    1065
    1066
    1067
    1068
    1069
    1070
    1071
    1072
    1073
    1074
    1075
    1076
    1077
    1078
    1079
    1080
    1081
    1082
    1083
    1084
    1085
    1086
    1087
    1088
    1089
    1090
    1091
    1092
    1093
    1094
    1095
    1096
    1097
    1098
    1099
    1100
    1101
    1102
    1103
    1104
    1105
    1106
    1107
    1108
    1109
    1110
    1111
    1112
    1113
    1114
    1115
    1116
    1117
    1118
    1119
     
    /*
     * Copyright (C) 2009 Google Inc.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     * http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
     
    package com.google.common.collect;
     
    import com.google.common.annotations.GwtCompatible;
    import com.google.common.annotations.GwtIncompatible;
    import com.google.common.base.FinalizableReferenceQueue;
    import com.google.common.base.FinalizableSoftReference;
    import com.google.common.base.FinalizableWeakReference;
    import com.google.common.base.Function;
    import com.google.common.collect.CustomConcurrentHashMap.ComputingStrategy;
    import com.google.common.collect.CustomConcurrentHashMap.Internals;
     
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.lang.ref.SoftReference;
    import java.lang.ref.WeakReference;
    import java.lang.reflect.Field;
    import java.util.Map;
    import java.util.TimerTask;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ConcurrentMap;
    import java.util.concurrent.TimeUnit;
     
    /**
     * A {@link ConcurrentMap} builder, providing any combination of these
     * features: {@linkplain SoftReference soft} or {@linkplain WeakReference
     * weak} keys, soft or weak values, timed expiration, and on-demand
     * computation of values. Usage example: <pre> {@code
     *
     *   ConcurrentMap<Key, Graph> graphs = new MapMaker()
     *       .concurrencyLevel(32)
     *       .softKeys()
     *       .weakValues()
     *       .expiration(30, TimeUnit.MINUTES)
     *       .makeComputingMap(
     *           new Function<Key, Graph>() {
     *             public Graph apply(Key key) {
     *               return createExpensiveGraph(key);
     *             }
     *           });}</pre>
     *
     * These features are all optional; {@code new MapMaker().makeMap()}
     * returns a valid concurrent map that behaves exactly like a
     * {@link ConcurrentHashMap}.
     *
     * The returned map is implemented as a hash table with similar performance
     * characteristics to {@link ConcurrentHashMap}. It supports all optional
     * operations of the {@code ConcurrentMap} interface. It does not permit
     * null keys or values. It is serializable; however, serializing a map that
     * uses soft or weak references can give unpredictable results.
     *
     * <p><b>Note:</b> by default, the returned map uses equality comparisons
     * (the {@link Object#equals(Object) equals} method) to determine equality
     * for keys or values. However, if {@link #weakKeys()} or {@link
     * #softKeys()} was specified, the map uses identity ({@code ==})
     * comparisons instead for keys. Likewise, if {@link #weakValues()} or
     * {@link #softValues()} was specified, the map uses identity comparisons
     * for values.
     *
     * <p>The returned map has <i>weakly consistent iteration</i>: an iterator
     * over one of the map's view collections may reflect some, all or none of
     * the changes made to the map after the iterator was created.
     *
     * <p>An entry whose key or value is reclaimed by the garbage collector
     * immediately disappears from the map. (If the default settings of strong
     * keys and strong values are used, this will never happen.) The client can
     * never observe a partially-reclaimed entry. Any {@link java.util.Map.Entry}
     * instance retrieved from the map's {@linkplain Map#entrySet() entry set}
     * is snapshot of that entry's state at the time of retrieval.
     *
     * <p>{@code new MapMaker().weakKeys().makeMap()} can almost always be
     * used as a drop-in replacement for {@link java.util.WeakHashMap}, adding
     * concurrency, asynchronous cleanup, identity-based equality for keys, and
     * great flexibility.
     *
     * @author Bob Lee
     * @author Kevin Bourrillion
     */
    @GwtCompatible(emulated = true)
    public final class MapMaker {
      private Strength keyStrength = Strength.STRONG;
      private Strength valueStrength = Strength.STRONG;
      private long expirationNanos = 0;
      private boolean useCustomMap;
      private final CustomConcurrentHashMap.Builder builder
          = new CustomConcurrentHashMap.Builder();
     
      /**
       * Constructs a new {@code MapMaker} instance with default settings,
       * including strong keys, strong values, and no automatic expiration.
       */
      public MapMaker() {}
     
      /**
       * Sets a custom initial capacity (defaults to 16). Resizing this or
       * any other kind of hash table is a relatively slow operation, so,
       * when possible, it is a good idea to provide estimates of expected
       * table sizes.
       *
       * @throws IllegalArgumentException if {@code initialCapacity} is
       *   negative
       * @throws IllegalStateException if an initial capacity was already set
       */
      public MapMaker initialCapacity(int initialCapacity) {
        builder.initialCapacity(initialCapacity);
        return this;
      }
     
      /**
       * Guides the allowed concurrency among update operations. Used as a
       * hint for internal sizing. The table is internally partitioned to try
       * to permit the indicated number of concurrent updates without
       * contention.  Because placement in hash tables is essentially random,
       * the actual concurrency will vary. Ideally, you should choose a value
       * to accommodate as many threads as will ever concurrently modify the
       * table. Using a significantly higher value than you need can waste
       * space and time, and a significantly lower value can lead to thread
       * contention. But overestimates and underestimates within an order of
       * magnitude do not usually have much noticeable impact. A value of one
       * is appropriate when it is known that only one thread will modify and
       * all others will only read. Defaults to 16.
       *
       * @throws IllegalArgumentException if {@code concurrencyLevel} is
       *     nonpositive
       * @throws IllegalStateException if a concurrency level was already set
       */
      @GwtIncompatible("java.util.concurrent.ConcurrentHashMap concurrencyLevel")
      public MapMaker concurrencyLevel(int concurrencyLevel) {
        builder.concurrencyLevel(concurrencyLevel);
        return this;
      }
     
      /**
       * Specifies that each key (not value) stored in the map should be
       * wrapped in a {@link WeakReference} (by default, strong references
       * are used).
       *
       * <p><b>Note:</b> the map will use identity ({@code ==}) comparison
       * to determine equality of weak keys, which may not behave as you expect.
       * For example, storing a key in the map and then attempting a lookup
       * using a different but {@link Object#equals(Object) equals}-equivalent
       * key will always fail.
       *
       * @throws IllegalStateException if the key strength was already set
       * @see WeakReference
       */
      @GwtIncompatible("java.lang.ref.WeakReference")
      public MapMaker weakKeys() {
        return setKeyStrength(Strength.WEAK);
      }
     
      /**
       * Specifies that each key (not value) stored in the map should be
       * wrapped in a {@link SoftReference} (by default, strong references
       * are used).
       *
       * <p><b>Note:</b> the map will use identity ({@code ==}) comparison
       * to determine equality of soft keys, which may not behave as you expect.
       * For example, storing a key in the map and then attempting a lookup
       * using a different but {@link Object#equals(Object) equals}-equivalent
       * key will always fail.
       *
       * @throws IllegalStateException if the key strength was already set
       * @see SoftReference
       */
      @GwtIncompatible("java.lang.ref.SoftReference")
      public MapMaker softKeys() {
        return setKeyStrength(Strength.SOFT);
      }
     
      private MapMaker setKeyStrength(Strength strength) {
        if (keyStrength != Strength.STRONG) {
          throw new IllegalStateException("Key strength was already set to "
              + keyStrength + ".");
        }
        keyStrength = strength;
        useCustomMap = true;
        return this;
      }
     
      /**
       * Specifies that each value (not key) stored in the map should be
       * wrapped in a {@link WeakReference} (by default, strong references
       * are used).
       *
       * <p>Weak values will be garbage collected once they are weakly
       * reachable. This makes them a poor candidate for caching; consider
       * {@link #softValues()} instead.
       *
       * <p><b>Note:</b> the map will use identity ({@code ==}) comparison
       * to determine equality of weak values. This will notably impact
       * the behavior of {@link Map#containsValue(Object) containsValue},
       * {@link ConcurrentMap#remove(Object, Object) remove(Object, Object)},
       * and {@link ConcurrentMap#replace(Object, Object, Object) replace(K, V, V)}.
       *
       * @throws IllegalStateException if the key strength was already set
       * @see WeakReference
       */
      @GwtIncompatible("java.lang.ref.WeakReference")
      public MapMaker weakValues() {
        return setValueStrength(Strength.WEAK);
      }
     
      /**
       * Specifies that each value (not key) stored in the map should be
       * wrapped in a {@link SoftReference} (by default, strong references
       * are used).
       *
       * <p>Soft values will be garbage collected in response to memory
       * demand, and in a least-recently-used manner. This makes them a
       * good candidate for caching.
       *
       * <p><b>Note:</b> the map will use identity ({@code ==}) comparison
       * to determine equality of soft values. This will notably impact
       * the behavior of {@link Map#containsValue(Object) containsValue},
       * {@link ConcurrentMap#remove(Object, Object) remove(Object, Object)},
       * and {@link ConcurrentMap#replace(Object, Object, Object) replace(K, V, V)}.
       *
       * @throws IllegalStateException if the value strength was already set
       * @see SoftReference
       */
      @GwtIncompatible("java.lang.ref.SoftReference")
      public MapMaker softValues() {
        return setValueStrength(Strength.SOFT);
      }
     
      private MapMaker setValueStrength(Strength strength) {
        if (valueStrength != Strength.STRONG) {
          throw new IllegalStateException("Value strength was already set to "
              + valueStrength + ".");
        }
        valueStrength = strength;
        useCustomMap = true;
        return this;
      }
     
      /**
       * Specifies that each entry should be automatically removed from the
       * map once a fixed duration has passed since the entry's creation.
       *
       * @param duration the length of time after an entry is created that it
       *     should be automatically removed
       * @param unit the unit that {@code duration} is expressed in
       * @throws IllegalArgumentException if {@code duration} is not positive
       * @throws IllegalStateException if the expiration time was already set
       */
      public MapMaker expiration(long duration, TimeUnit unit) {
        if (expirationNanos != 0) {
          throw new IllegalStateException("expiration time of "
              + expirationNanos + " ns was already set");
        }
        if (duration <= 0) {
          throw new IllegalArgumentException("invalid duration: " + duration);
        }
        this.expirationNanos = unit.toNanos(duration);
        useCustomMap = true;
        return this;
      }
     
      /**
       * Builds the final map, without on-demand computation of values. This method
       * does not alter the state of this {@code MapMaker} instance, so it can be
       * invoked again to create multiple independent maps.
       *
       * @param <K> the type of keys to be stored in the returned map
       * @param <V> the type of values to be stored in the returned map
       * @return a concurrent map having the requested features
       */
      public <K, V> ConcurrentMap<K, V> makeMap() {
        return useCustomMap
            ? new StrategyImpl<K, V>(this).map
            : new ConcurrentHashMap<K, V>(builder.getInitialCapacity(),
                0.75f, builder.getConcurrencyLevel());
      }
     
      /**
       * Builds a map that supports atomic, on-demand computation of values. {@link
       * Map#get} either returns an already-computed value for the given key,
       * atomically computes it using the supplied function, or, if another thread
       * is currently computing the value for this key, simply waits for that thread
       * to finish and returns its computed value. Note that the function may be
       * executed concurrently by multiple threads, but only for distinct keys.
       *
       * <p>If an entry's value has not finished computing yet, query methods
       * besides {@code get} return immediately as if an entry doesn't exist. In
       * other words, an entry isn't externally visible until the value's
       * computation completes.
       *
       * <p>{@link Map#get} on the returned map will never return {@code null}. It
       * may throw:
       *
       * <ul>
       * <li>{@link NullPointerException} if the key is null or the computing
       *     function returns null
       * <li>{@link ComputationException} if an exception was thrown by the
       *     computing function. If that exception is already of type {@link
       *     ComputationException}, it is propagated directly; otherwise it is
       *     wrapped.
       * </ul>
       *
       * <p><b>Note:</b> Callers of {@code get} <i>must</i> ensure that the key
       * argument is of type {@code K}. The {@code get} method accepts {@code
       * Object}, so the key type is not checked at compile time. Passing an object
       * of a type other than {@code K} can result in that object being unsafely
       * passed to the computing function as type {@code K}, and unsafely stored in
       * the map.
       *
       * <p>If {@link Map#put} is called before a computation completes, other
       * threads waiting on the computation will wake up and return the stored
       * value. When the computation completes, its new result will overwrite the
       * value that was put in the map manually.
       *
       * <p>This method does not alter the state of this {@code MapMaker} instance,
       * so it can be invoked again to create multiple independent maps.
       */
      public <K, V> ConcurrentMap<K, V> makeComputingMap(
          Function<? super K, ? extends V> computingFunction) {
        return new StrategyImpl<K, V>(this, computingFunction).map;
      }
     
      // Remainder of this file is private implementation details
     
      private enum Strength {
        WEAK {
          @Override boolean equal(Object a, Object b) {
            return a == b;
          }
          @Override int hash(Object o) {
            return System.identityHashCode(o);
          }
          @Override <K, V> ValueReference<K, V> referenceValue(
              ReferenceEntry<K, V> entry, V value) {
            return new WeakValueReference<K, V>(value, entry);
          }
          @Override <K, V> ReferenceEntry<K, V> newEntry(
              Internals<K, V, ReferenceEntry<K, V>> internals, K key,
              int hash, ReferenceEntry<K, V> next) {
            return (next == null)
                ? new WeakEntry<K, V>(internals, key, hash)
                : new LinkedWeakEntry<K, V>(internals, key, hash, next);
          }
          @Override <K, V> ReferenceEntry<K, V> copyEntry(
              K key, ReferenceEntry<K, V> original,
              ReferenceEntry<K, V> newNext) {
            WeakEntry<K, V> from = (WeakEntry<K, V>) original;
            return (newNext == null)
                ? new WeakEntry<K, V>(from.internals, key, from.hash)
                : new LinkedWeakEntry<K, V>(
                    from.internals, key, from.hash, newNext);
          }
        },
     
        SOFT {
          @Override boolean equal(Object a, Object b) {
            return a == b;
          }
          @Override int hash(Object o) {
            return System.identityHashCode(o);
          }
          @Override <K, V> ValueReference<K, V> referenceValue(
              ReferenceEntry<K, V> entry, V value) {
            return new SoftValueReference<K, V>(value, entry);
          }
          @Override <K, V> ReferenceEntry<K, V> newEntry(
              Internals<K, V, ReferenceEntry<K, V>> internals, K key,
              int hash, ReferenceEntry<K, V> next) {
            return (next == null)
                ? new SoftEntry<K, V>(internals, key, hash)
                : new LinkedSoftEntry<K, V>(internals, key, hash, next);
          }
          @Override <K, V> ReferenceEntry<K, V> copyEntry(
              K key, ReferenceEntry<K, V> original,
              ReferenceEntry<K, V> newNext) {
            SoftEntry<K, V> from = (SoftEntry<K, V>) original;
            return (newNext == null)
                ? new SoftEntry<K, V>(from.internals, key, from.hash)
                : new LinkedSoftEntry<K, V>(
                    from.internals, key, from.hash, newNext);
          }
        },
     
        STRONG {
          @Override boolean equal(Object a, Object b) {
            return a.equals(b);
          }
          @Override int hash(Object o) {
            return o.hashCode();
          }
          @Override <K, V> ValueReference<K, V> referenceValue(
              ReferenceEntry<K, V> entry, V value) {
            return new StrongValueReference<K, V>(value);
          }
          @Override <K, V> ReferenceEntry<K, V> newEntry(
              Internals<K, V, ReferenceEntry<K, V>> internals, K key,
              int hash, ReferenceEntry<K, V> next) {
            return (next == null)
                ? new StrongEntry<K, V>(internals, key, hash)
                : new LinkedStrongEntry<K, V>(
                    internals, key, hash, next);
          }
          @Override <K, V> ReferenceEntry<K, V> copyEntry(
              K key, ReferenceEntry<K, V> original,
              ReferenceEntry<K, V> newNext) {
            StrongEntry<K, V> from = (StrongEntry<K, V>) original;
            return (newNext == null)
                ? new StrongEntry<K, V>(from.internals, key, from.hash)
                : new LinkedStrongEntry<K, V>(
                    from.internals, key, from.hash, newNext);
          }
        };
     
        /**
         * Determines if two keys or values are equal according to this
         * strength strategy.
         */
        abstract boolean equal(Object a, Object b);
     
        /**
         * Hashes a key according to this strategy.
         */
        abstract int hash(Object o);
     
        /**
         * Creates a reference for the given value according to this value
         * strength.
         */
        abstract <K, V> ValueReference<K, V> referenceValue(
            ReferenceEntry<K, V> entry, V value);
     
        /**
         * Creates a new entry based on the current key strength.
         */
        abstract <K, V> ReferenceEntry<K, V> newEntry(
            Internals<K, V, ReferenceEntry<K, V>> internals, K key,
            int hash, ReferenceEntry<K, V> next);
     
        /**
         * Creates a new entry and copies the value and other state from an
         * existing entry.
         */
        abstract <K, V> ReferenceEntry<K, V> copyEntry(K key,
            ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext);
      }
     
      private static class StrategyImpl<K, V> implements Serializable,
          ComputingStrategy<K, V, ReferenceEntry<K, V>> {
        final Strength keyStrength;
        final Strength valueStrength;
        final ConcurrentMap<K, V> map;
        final long expirationNanos;
        Internals<K, V, ReferenceEntry<K, V>> internals;
     
        StrategyImpl(MapMaker maker) {
          this.keyStrength = maker.keyStrength;
          this.valueStrength = maker.valueStrength;
          this.expirationNanos = maker.expirationNanos;
     
          map = maker.builder.buildMap(this);
        }
     
        StrategyImpl(
            MapMaker maker, Function<? super K, ? extends V> computer) {
          this.keyStrength = maker.keyStrength;
          this.valueStrength = maker.valueStrength;
          this.expirationNanos = maker.expirationNanos;
     
          map = maker.builder.buildComputingMap(this, computer);
        }
     
        public void setValue(ReferenceEntry<K, V> entry, V value) {
          setValueReference(
              entry, valueStrength.referenceValue(entry, value));
          if (expirationNanos > 0) {
            scheduleRemoval(entry.getKey(), value);
          }
        }
     
        void scheduleRemoval(K key, V value) {
          /*
           * TODO: Keep weak reference to map, too. Build a priority
           * queue out of the entries themselves instead of creating a
           * task per entry. Then, we could have one recurring task per
           * map (which would clean the entire map and then reschedule
           * itself depending upon when the next expiration comes). We
           * also want to avoid removing an entry prematurely if the
           * entry was set to the same value again.
           */
          final WeakReference<K> keyReference = new WeakReference<K>(key);
          final WeakReference<V> valueReference = new WeakReference<V>(value);
          ExpirationTimer.instance.schedule(
              new TimerTask() {
                @Override public void run() {
                  K key = keyReference.get();
                  if (key != null) {
                    // Remove if the value is still the same.
                    map.remove(key, valueReference.get());
                  }
                }
              }, TimeUnit.NANOSECONDS.toMillis(expirationNanos));
        }
     
        public boolean equalKeys(K a, Object b) {
          return keyStrength.equal(a, b);
        }
     
        public boolean equalValues(V a, Object b) {
          return valueStrength.equal(a, b);
        }
     
        public int hashKey(Object key) {
          return keyStrength.hash(key);
        }
     
        public K getKey(ReferenceEntry<K, V> entry) {
          return entry.getKey();
        }
     
        public int getHash(ReferenceEntry<K, V> entry) {
          return entry.getHash();
        }
     
        public ReferenceEntry<K, V> newEntry(
            K key, int hash, ReferenceEntry<K, V> next) {
          return keyStrength.newEntry(internals, key, hash, next);
        }
     
        public ReferenceEntry<K, V> copyEntry(K key,
            ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
          ValueReference<K, V> valueReference = original.getValueReference();
          if (valueReference == COMPUTING) {
            ReferenceEntry<K, V> newEntry
                = newEntry(key, original.getHash(), newNext);
            newEntry.setValueReference(
                new FutureValueReference(original, newEntry));
            return newEntry;
          } else {
            ReferenceEntry<K, V> newEntry
                = newEntry(key, original.getHash(), newNext);
            newEntry.setValueReference(valueReference.copyFor(newEntry));
            return newEntry;
          }
        }
     
        /**
         * Waits for a computation to complete. Returns the result of the
         * computation or null if none was available.
         */
        public V waitForValue(ReferenceEntry<K, V> entry)
            throws InterruptedException {
          ValueReference<K, V> valueReference = entry.getValueReference();
          if (valueReference == COMPUTING) {
            synchronized (entry) {
              while ((valueReference = entry.getValueReference())
                  == COMPUTING) {
                entry.wait();
              }
            }
          }
          return valueReference.waitForValue();
        }
     
        /**
         * Used by CustomConcurrentHashMap to retrieve values. Returns null
         * instead of blocking or throwing an exception.
         */
        public V getValue(ReferenceEntry<K, V> entry) {
          ValueReference<K, V> valueReference = entry.getValueReference();
          return valueReference.get();
        }
     
        public V compute(K key, final ReferenceEntry<K, V> entry,
            Function<? super K, ? extends V> computer) {
          V value;
          try {
            value = computer.apply(key);
          } catch (ComputationException e) {
            // if computer has thrown a computation exception, propagate rather
            // than wrap
            setValueReference(entry,
                new ComputationExceptionReference<K, V>(e.getCause()));
            throw e;
          } catch (Throwable t) {
            setValueReference(
              entry, new ComputationExceptionReference<K, V>(t));
            throw new ComputationException(t);
          }
     
          if (value == null) {
            String message
                = computer + " returned null for key " + key + ".";
            setValueReference(
                entry, new NullOutputExceptionReference<K, V>(message));
            throw new NullOutputException(message);
          } else {
            setValue(entry, value);
          }
          return value;
        }
     
        /**
         * Sets the value reference on an entry and notifies waiting
         * threads.
         */
        void setValueReference(ReferenceEntry<K, V> entry,
            ValueReference<K, V> valueReference) {
          boolean notifyOthers = (entry.getValueReference() == COMPUTING);
          entry.setValueReference(valueReference);
          if (notifyOthers) {
            synchronized (entry) {
              entry.notifyAll();
            }
          }
        }
     
        /**
         * Points to an old entry where a value is being computed. Used to
         * support non-blocking copying of entries during table expansion,
         * removals, etc.
         */
        private class FutureValueReference implements ValueReference<K, V> {
          final ReferenceEntry<K, V> original;
          final ReferenceEntry<K, V> newEntry;
     
          FutureValueReference(
              ReferenceEntry<K, V> original, ReferenceEntry<K, V> newEntry) {
            this.original = original;
            this.newEntry = newEntry;
          }
     
          public V get() {
            boolean success = false;
            try {
              V value = original.getValueReference().get();
              success = true;
              return value;
            } finally {
              if (!success) {
                removeEntry();
              }
            }
          }
     
          public ValueReference<K, V> copyFor(ReferenceEntry<K, V> entry) {
            return new FutureValueReference(original, entry);
          }
     
          public V waitForValue() throws InterruptedException {
            boolean success = false;
            try {
              // assert that key != null
              V value = StrategyImpl.this.waitForValue(original);
              success = true;
              return value;
            } finally {
              if (!success) {
                removeEntry();
              }
            }
          }
     
          /**
           * Removes the entry in the event of an exception. Ideally,
           * we'd clean up as soon as the computation completes, but we
           * can't do that without keeping a reference to this entry from
           * the original.
           */
          void removeEntry() {
            internals.removeEntry(newEntry);
          }
        }
     
        public ReferenceEntry<K, V> getNext(
            ReferenceEntry<K, V> entry) {
          return entry.getNext();
        }
     
        public void setInternals(
            Internals<K, V, ReferenceEntry<K, V>> internals) {
          this.internals = internals;
        }
     
        private static final long serialVersionUID = 0;
     
        private void writeObject(ObjectOutputStream out)
            throws IOException {
          // Custom serialization code ensures that the key and value
          // strengths are written before the map. We'll need them to
          // deserialize the map entries.
          out.writeObject(keyStrength);
          out.writeObject(valueStrength);
          out.writeLong(expirationNanos);
     
          // TODO: It is possible for the strategy to try to use the map
          // or internals during deserialization, for example, if an
          // entry gets reclaimed. We could detect this case and queue up
          // removals to be flushed after we deserialize the map.
          out.writeObject(internals);
          out.writeObject(map);
        }
     
        /**
         * Fields used during deserialization. We use a nested class so we
         * don't load them until we need them. We need to use reflection to
         * set final fields outside of the constructor.
         */
        private static class Fields {
          static final Field keyStrength = findField("keyStrength");
          static final Field valueStrength = findField("valueStrength");
          static final Field expirationNanos = findField("expirationNanos");
          static final Field internals = findField("internals");
          static final Field map = findField("map");
     
          static Field findField(String name) {
            try {
              Field f = StrategyImpl.class.getDeclaredField(name);
              f.setAccessible(true);
              return f;
            } catch (NoSuchFieldException e) {
              throw new AssertionError(e);
            }
          }
        }
     
        private void readObject(ObjectInputStream in)
            throws IOException, ClassNotFoundException {
          try {
            Fields.keyStrength.set(this, in.readObject());
            Fields.valueStrength.set(this, in.readObject());
            Fields.expirationNanos.set(this, in.readLong());
            Fields.internals.set(this, in.readObject());
            Fields.map.set(this, in.readObject());
          } catch (IllegalAccessException e) {
            throw new AssertionError(e);
          }
        }
      }
     
      /** A reference to a value. */
      private interface ValueReference<K, V> {
        /**
         * Gets the value. Does not block or throw exceptions.
         */
        V get();
     
        /** Creates a copy of this reference for the given entry. */
        ValueReference<K, V> copyFor(ReferenceEntry<K, V> entry);
     
        /**
         * Waits for a value that may still be computing. Unlike get(),
         * this method can block (in the case of FutureValueReference) or
         * throw an exception.
         */
        V waitForValue() throws InterruptedException;
      }
     
      private static final ValueReference<Object, Object> COMPUTING
          = new ValueReference<Object, Object>() {
        public Object get() {
          return null;
        }
        public ValueReference<Object, Object> copyFor(
            ReferenceEntry<Object, Object> entry) {
          throw new AssertionError();
        }
        public Object waitForValue() {
          throw new AssertionError();
        }
      };
     
      /**
       * Singleton placeholder that indicates a value is being computed.
       */
      @SuppressWarnings("unchecked")
      // Safe because impl never uses a parameter or returns any non-null value
      private static <K, V> ValueReference<K, V> computing() {
        return (ValueReference<K, V>) COMPUTING;
      }
     
      /** Used to provide null output exceptions to other threads. */
      private static class NullOutputExceptionReference<K, V>
          implements ValueReference<K, V> {
        final String message;
        NullOutputExceptionReference(String message) {
          this.message = message;
        }
        public V get() {
          return null;
        }
        public ValueReference<K, V> copyFor(
            ReferenceEntry<K, V> entry) {
          return this;
        }
        public V waitForValue() {
          throw new NullOutputException(message);
        }
      }
     
      /** Used to provide computation exceptions to other threads. */
      private static class ComputationExceptionReference<K, V>
          implements ValueReference<K, V> {
        final Throwable t;
        ComputationExceptionReference(Throwable t) {
          this.t = t;
        }
        public V get() {
          return null;
        }
        public ValueReference<K, V> copyFor(
            ReferenceEntry<K, V> entry) {
          return this;
        }
        public V waitForValue() {
          throw new AsynchronousComputationException(t);
        }
      }
     
      /** Wrapper class ensures that queue isn't created until it's used. */
      private static class QueueHolder {
        static final FinalizableReferenceQueue queue
            = new FinalizableReferenceQueue();
      }
     
      /**
       * An entry in a reference map.
       */
      private interface ReferenceEntry<K, V> {
        /**
         * Gets the value reference from this entry.
         */
        ValueReference<K, V> getValueReference();
     
        /**
         * Sets the value reference for this entry.
         *
         * @param valueReference
         */
        void setValueReference(ValueReference<K, V> valueReference);
     
        /**
         * Removes this entry from the map if its value reference hasn't
         * changed.  Used to clean up after values. The value reference can
         * just call this method on the entry so it doesn't have to keep
         * its own reference to the map.
         */
        void valueReclaimed();
     
        /** Gets the next entry in the chain. */
        ReferenceEntry<K, V> getNext();
     
        /** Gets the entry's hash. */
        int getHash();
     
        /** Gets the key for this entry. */
        public K getKey();
      }
     
      /**
       * Used for strongly-referenced keys.
       */
      private static class StrongEntry<K, V> implements ReferenceEntry<K, V> {
        final K key;
     
        StrongEntry(Internals<K, V, ReferenceEntry<K, V>> internals, K key,
            int hash) {
          this.internals = internals;
          this.key = key;
          this.hash = hash;
        }
     
        public K getKey() {
          return this.key;
        }
     
        // The code below is exactly the same for each entry type.
     
        final Internals<K, V, ReferenceEntry<K, V>> internals;
        final int hash;
        volatile ValueReference<K, V> valueReference = computing();
     
        public ValueReference<K, V> getValueReference() {
          return valueReference;
        }
        public void setValueReference(
            ValueReference<K, V> valueReference) {
          this.valueReference = valueReference;
        }
        public void valueReclaimed() {
          internals.removeEntry(this, null);
        }
        public ReferenceEntry<K, V> getNext() {
          return null;
        }
        public int getHash() {
          return hash;
        }
      }
     
      private static class LinkedStrongEntry<K, V> extends StrongEntry<K, V> {
     
        LinkedStrongEntry(Internals<K, V, ReferenceEntry<K, V>> internals,
            K key, int hash, ReferenceEntry<K, V> next) {
          super(internals, key, hash);
          this.next = next;
        }
     
        final ReferenceEntry<K, V> next;
     
        @Override public ReferenceEntry<K, V> getNext() {
          return next;
        }
      }
     
      /**
       * Used for softly-referenced keys.
       */
      private static class SoftEntry<K, V> extends FinalizableSoftReference<K>
          implements ReferenceEntry<K, V> {
        SoftEntry(Internals<K, V, ReferenceEntry<K, V>> internals, K key,
            int hash) {
          super(key, QueueHolder.queue);
          this.internals = internals;
          this.hash = hash;
        }
     
        public K getKey() {
          return get();
        }
     
        public void finalizeReferent() {
          internals.removeEntry(this);
        }
     
        // The code below is exactly the same for each entry type.
     
        final Internals<K, V, ReferenceEntry<K, V>> internals;
        final int hash;
        volatile ValueReference<K, V> valueReference = computing();
     
        public ValueReference<K, V> getValueReference() {
          return valueReference;
        }
        public void setValueReference(
            ValueReference<K, V> valueReference) {
          this.valueReference = valueReference;
        }
        public void valueReclaimed() {
          internals.removeEntry(this, null);
        }
        public ReferenceEntry<K, V> getNext() {
          return null;
        }
        public int getHash() {
          return hash;
        }
      }
     
      private static class LinkedSoftEntry<K, V> extends SoftEntry<K, V> {
        LinkedSoftEntry(Internals<K, V, ReferenceEntry<K, V>> internals,
            K key, int hash, ReferenceEntry<K, V> next) {
          super(internals, key, hash);
          this.next = next;
        }
     
        final ReferenceEntry<K, V> next;
     
        @Override public ReferenceEntry<K, V> getNext() {
          return next;
        }
      }
     
      /**
       * Used for weakly-referenced keys.
       */
      private static class WeakEntry<K, V> extends FinalizableWeakReference<K>
          implements ReferenceEntry<K, V> {
        WeakEntry(Internals<K, V, ReferenceEntry<K, V>> internals, K key,
            int hash) {
          super(key, QueueHolder.queue);
          this.internals = internals;
          this.hash = hash;
        }
     
        public K getKey() {
          return get();
        }
     
        public void finalizeReferent() {
          internals.removeEntry(this);
        }
     
        // The code below is exactly the same for each entry type.
     
        final Internals<K, V, ReferenceEntry<K, V>> internals;
        final int hash;
        volatile ValueReference<K, V> valueReference = computing();
     
        public ValueReference<K, V> getValueReference() {
          return valueReference;
        }
        public void setValueReference(
            ValueReference<K, V> valueReference) {
          this.valueReference = valueReference;
        }
        public void valueReclaimed() {
          internals.removeEntry(this, null);
        }
        public ReferenceEntry<K, V> getNext() {
          return null;
        }
        public int getHash() {
          return hash;
        }
      }
     
      private static class LinkedWeakEntry<K, V> extends WeakEntry<K, V> {
        LinkedWeakEntry(Internals<K, V, ReferenceEntry<K, V>> internals,
            K key, int hash, ReferenceEntry<K, V> next) {
          super(internals, key, hash);
          this.next = next;
        }
     
        final ReferenceEntry<K, V> next;
     
        @Override public ReferenceEntry<K, V> getNext() {
          return next;
        }
      }
     
      /** References a weak value. */
      private static class WeakValueReference<K, V>
          extends FinalizableWeakReference<V>
          implements ValueReference<K, V> {
        final ReferenceEntry<K, V> entry;
     
        WeakValueReference(V referent, ReferenceEntry<K, V> entry) {
          super(referent, QueueHolder.queue);
          this.entry = entry;
        }
     
        public void finalizeReferent() {
          entry.valueReclaimed();
        }
     
        public ValueReference<K, V> copyFor(
            ReferenceEntry<K, V> entry) {
          return new WeakValueReference<K, V>(get(), entry);
        }
     
        public V waitForValue() {
          return get();
        }
      }
     
      /** References a soft value. */
      private static class SoftValueReference<K, V>
          extends FinalizableSoftReference<V>
          implements ValueReference<K, V> {
        final ReferenceEntry<K, V> entry;
     
        SoftValueReference(V referent, ReferenceEntry<K, V> entry) {
          super(referent, QueueHolder.queue);
          this.entry = entry;
        }
     
        public void finalizeReferent() {
          entry.valueReclaimed();
        }
     
        public ValueReference<K, V> copyFor(
            ReferenceEntry<K, V> entry) {
          return new SoftValueReference<K, V>(get(), entry);
        }
     
        public V waitForValue() {
          return get();
        }
      }
     
      /** References a strong value. */
      private static class StrongValueReference<K, V>
          implements ValueReference<K, V> {
        final V referent;
     
        StrongValueReference(V referent) {
          this.referent = referent;
        }
     
        public V get() {
          return referent;
        }
     
        public ValueReference<K, V> copyFor(
            ReferenceEntry<K, V> entry) {
          return this;
        }
     
        public V waitForValue() {
          return get();
        }
      }
    }
    Comment l'adapter si c'est le code de Map Maker Sinon pourrez vous m'aidez à résoudre mon problème? Aurez vous une autre alternative.

  16. #16
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    Afin de ne pas obscurcir cette discussion je te propose de passer celle ci en résolue puis d’en ouvrir une autre portant sur ton nouveau soucis.

    Je peux d'ores et déjà te dire 2 choses
    - le code que tu as déniché est du java et donc rien à voir avec javascript
    - regarde du coté de Création d'une Static Map à partir d'un itinéraire.

    On en reparle dans une autre discussion

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Intégration de google map dans une application de géolocalisation
    Par Safia_EL dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 25/03/2014, 08h41
  2. Développer une application de géolocalisation
    Par adam525 dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 22/09/2013, 11h03
  3. Intégration de Géolocalisation Google Maps dans une application Android
    Par af.zakaria dans le forum API standards et tierces
    Réponses: 3
    Dernier message: 01/01/2013, 22h01
  4. Conception UML d'une application de géolocalisation pour voyageur
    Par tunisdroid dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 16/10/2012, 12h28
  5. Réalisation d'une application de géolocalisation jEE
    Par azzabouines dans le forum Servlets/JSP
    Réponses: 0
    Dernier message: 25/05/2012, 13h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo