2017-03-25 1 views
0

Je suis confronté au problème suivant. Je suis en train de construire une fonction (macro) au-dessus du Hapi-fhir apiJava interop et clojure macros

function (macro) on topo of hapi-fhir api 
    (defmacro search-patient-resource 
    "This macro searches for a specified resource based on the 
    Patient Id" 
    [res id json?] 
    (let [tmp (symbol res)] 
    (if json? 
     `(. (. (. (. (. (. @restful-client search) (forResource ~(symbol res))) encodedJson) (where (. (. ~(resolve tmp) PATIENT) 
        (hasId (str ~id))))) (returnBundle Bundle)) execute) 
    ))) 

Cette macro fonctionne lorsqu'un faire quelque chose comme

(let [id 10465] 
(search-patient-resource "Observation" id true)) 
=>#object[ca.uhn.fhir.model.dstu2.resource.Bundle 0x520a3cc9 "Bundle[id=Bundle/9ca62ae1-82af-488f-a166-5b014f45886e]"] 

mais pas quand je fais

(let [id 10465 res "Observation"] 
(search-patient-resource "Observation" id true)) 
=> CompilerException java.lang.NullPointerException, compiling:(apycare_emrspp/hapi_fhir_helper.clj:122:1) 

Bien sûr, je ne peux pas écrire (symbole ~ res), car alors le lecteur évalue (symbole "Observation") à la compilation et je reçois

CompilerException java.lang.IllegalArgumentException: No matching method found: forResource for class ca.uhn.fhir.rest.client.GenericCl 
ient$SearchInternal, compiling:(apycare_emrspp/hapi_fhir_helper.clj:122:1) 

Aussi ne

(resolve (symbol ~res) 

ni

(resolve ~(symbol re) 
travail

.

Le code Java d'origine ressemble à ceci

FhirContext ctx = FhirContext.forDstu2(); 
String serverBase = "fhirtest.uhn.ca/baseDstu2"; 
IGenericClient client = ctx.newRestfulGenericClient(serverBase); 
Bundle results = client .search() .forResource(Observation.class) 
.where(Observation.PATIENT.hasId("1234")) 
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class) 
.execute(); 

Ce que je fais est essayer de faire l'appel avec

client 
.search() 
.forResource(another-resource.class) 
.where(another-resource.PATIENT.hasId(another-id)) 
.returnBundle(ca.uhn.fhir.model.dstu2.resource.Bundle.class) 
.execute(); 
+0

Je ne comprends pas pourquoi vous écrivez ceci comme une macro. Il semble que vous pourriez l'écrire comme une fonction et éviter le problème. –

+0

Comment ça? J'ai essayé de l'écrire comme une fonction, mais comment passer le nom de la méthode arbirtery sans se plaindre du compilateur clojure? Car instanse laisse dire que je veux passer [observation] pour appeler (.) L'observation des ressources). Si je le passe comme une chaîne, alors (.source (symbole "Observation"), ne fonctionnera pas à moins d'être développé à partir d'une liste par le biais de macros – Heefoo

+0

Veuillez clarifier la façon dont il est censé fonctionner. –

Répondre

0

Ok. Le problème auquel je faisais face était aussi dû au fait que je négligeais d'importer les symboles appropriés lorsque j'appelais le code d'un espace de noms différent. quand res = « ressources » dans le code ci-dessus puis

~(symbol "Resource") 

pourrait pas preperty résolu si je ne l'avais pas d'abord ajouter

(import '(ca.uhn.fhir.model.dstu2.resource.Resource)) 

Dans l'espace de noms ont été la macro a été appelé. Cela a fait fonctionner le code dans la plupart des cas. Pour le rendre pleinement fonctionnel que je devais changer

~(symbol "Resource") 

à (identité ~ (symbole "ressources"))

Ceci est la traduction correcte de

de java

Resource.class au code clojure

À la fin de la macro a pris la forme:

(defmacro search-patient-resource 
"This macro searches for a specified resource based on the 
    Patient Id" 
[res id json?] 
(let [tmp (symbol res)] 
    (if json? 
    `(. (. (. (. (. (. @restful-client search) 
        (forResource (identity ~(symbol res)))) 
        encodedJson) 
       (where 
       (. 
        (. ~(resolve tmp) PATIENT) 
        (hasId (~str ~id))))) 
      (returnBundle Bundle)) 
     execute) 
    `(. (. (. (. (. @restful-client search) 
        (forResource (identity ~(symbol res)))) 
       (where (. (. ~(symbol res) 
          PATIENT) 
         (hasId (str ~id))))) 
      (returnBundle Bundle)) 
     execute))))