From f0214399ca662d1090de0d0561fac0375978dfb1 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Thu, 13 Mar 2014 17:33:12 -0400 Subject: [PATCH] Lots of fixes and docs to tinder --- .../ca/uhn/fhir/context/ModelScanner.java | 50 +- .../model/{api => dstu/resource}/Binary.java | 3 +- .../uhn/fhir/model/primitive/BoundCodeDt.java | 2 +- hapi-fhir-base/src/site/site.xml | 1 + hapi-fhir-base/src/site/xdoc/doc_tinder.xml | 85 ++ hapi-fhir-structures-dstu/pom.xml | 1 + hapi-tinder-plugin/.classpath | 1 + hapi-tinder-plugin/pom.xml | 53 +- .../uhn/fhir/tinder/BaseStructureParser.java | 240 ++-- .../BaseStructureSpreadsheetParser.java | 11 +- .../DatatypeGeneratorUsingSpreadsheet.java | 9 + .../ca/uhn/fhir/tinder/ProfileParser.java | 43 +- .../ResourceGeneratorUsingSpreadsheet.java | 10 +- .../ca/uhn/fhir/tinder/TinderClientMojo.java | 21 +- .../uhn/fhir/tinder/TinderStructuresMojo.java | 138 ++- .../uhn/fhir/tinder/model/BaseRootType.java | 41 + .../java/ca/uhn/fhir/tinder/model/Child.java | 5 +- .../ca/uhn/fhir/tinder/model/Composite.java | 5 + .../ca/uhn/fhir/tinder/model/Resource.java | 37 +- .../fhir/tinder/model/SearchParameter.java | 4 +- .../ca/uhn/fhir/tinder/model/SimpleChild.java | 5 + .../src/main/resources/vm/client.vm | 7 +- .../src/main/resources/vm/dt_composite.vm | 7 +- .../src/main/resources/vm/resource.vm | 11 +- hapi-tinder-plugin/src/test/resources/tmp.txt | 484 ++++++++ hapi-tinder-test/.classpath | 1 + hapi-tinder-test/pom.xml | 58 + .../test/resources/profile/organization.xml | 579 ++++++++++ .../src/test/resources/profile/patient.xml | 1021 +++++++++++++++++ .../valueset/valueset-cgta-patientidpool.xml | 32 + .../valueset/valueset-cgta-provideridpool.xml | 26 + 31 files changed, 2766 insertions(+), 225 deletions(-) rename hapi-fhir-base/src/main/java/ca/uhn/fhir/model/{api => dstu/resource}/Binary.java (77%) create mode 100644 hapi-fhir-base/src/site/xdoc/doc_tinder.xml create mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/model/BaseRootType.java create mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/model/Composite.java create mode 100644 hapi-tinder-plugin/src/main/java/ca/uhn/fhir/tinder/model/SimpleChild.java create mode 100644 hapi-tinder-plugin/src/test/resources/tmp.txt create mode 100644 hapi-tinder-test/src/test/resources/profile/organization.xml create mode 100644 hapi-tinder-test/src/test/resources/profile/patient.xml create mode 100644 hapi-tinder-test/src/test/resources/valueset/valueset-cgta-patientidpool.xml create mode 100644 hapi-tinder-test/src/test/resources/valueset/valueset-cgta-provideridpool.xml diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java index aa1f6c43675..933824e5369 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java @@ -157,7 +157,8 @@ class ModelScanner { ResourceDef resourceDefinition = theClass.getAnnotation(ResourceDef.class); if (resourceDefinition != null) { if (!IResource.class.isAssignableFrom(theClass)) { - throw new ConfigurationException("Resource type contains a @" + ResourceDef.class.getSimpleName() + " annotation but does not implement " + IResource.class.getCanonicalName() + ": " + theClass.getCanonicalName()); + throw new ConfigurationException("Resource type contains a @" + ResourceDef.class.getSimpleName() + " annotation but does not implement " + IResource.class.getCanonicalName() + ": " + + theClass.getCanonicalName()); } @SuppressWarnings("unchecked") Class resClass = (Class) theClass; @@ -175,7 +176,8 @@ class ModelScanner { Class> resClass = (Class>) theClass; scanPrimitiveDatatype(resClass, datatypeDefinition); } else { - throw new ConfigurationException("Resource type contains a @" + DatatypeDef.class.getSimpleName() + " annotation but does not implement " + IDatatype.class.getCanonicalName() + ": " + theClass.getCanonicalName()); + throw new ConfigurationException("Resource type contains a @" + DatatypeDef.class.getSimpleName() + " annotation but does not implement " + IDatatype.class.getCanonicalName() + ": " + + theClass.getCanonicalName()); } } @@ -186,7 +188,8 @@ class ModelScanner { Class resClass = (Class) theClass; scanCodeTable(resClass, codeTableDefinition); } else { - throw new ConfigurationException("Type contains a @" + CodeTableDef.class.getSimpleName() + " annotation but does not implement " + ICodeEnum.class.getCanonicalName() + ": " + theClass.getCanonicalName()); + throw new ConfigurationException("Type contains a @" + CodeTableDef.class.getSimpleName() + " annotation but does not implement " + ICodeEnum.class.getCanonicalName() + ": " + + theClass.getCanonicalName()); } } @@ -197,7 +200,8 @@ class ModelScanner { Class blockClass = (Class) theClass; scanBlock(blockClass, blockDefinition); } else { - throw new ConfigurationException("Type contains a @" + Block.class.getSimpleName() + " annotation but does not implement " + IResourceBlock.class.getCanonicalName() + ": " + theClass.getCanonicalName()); + throw new ConfigurationException("Type contains a @" + Block.class.getSimpleName() + " annotation but does not implement " + IResourceBlock.class.getCanonicalName() + ": " + + theClass.getCanonicalName()); } } @@ -288,8 +292,8 @@ class ModelScanner { } @SuppressWarnings("unchecked") - private void scanCompositeElementForChildren(Class theClass, BaseRuntimeElementCompositeDefinition theDefinition, Set elementNames, TreeMap theOrderToElementDef, - TreeMap theOrderToExtensionDef) { + private void scanCompositeElementForChildren(Class theClass, BaseRuntimeElementCompositeDefinition theDefinition, Set elementNames, + TreeMap theOrderToElementDef, TreeMap theOrderToExtensionDef) { int baseElementOrder = theOrderToElementDef.isEmpty() ? 0 : theOrderToElementDef.lastEntry().getKey() + 1; for (Field next : theClass.getDeclaredFields()) { @@ -314,9 +318,7 @@ class ModelScanner { } /* - * Anything that's marked as unknown is given a new ID that is <0 so - * that it doesn't conflict wityh any given IDs and can be figured - * out later + * Anything that's marked as unknown is given a new ID that is <0 so that it doesn't conflict wityh any given IDs and can be figured out later */ while (order == Child.ORDER_UNKNOWN && orderMap.containsKey(order)) { order--; @@ -328,7 +330,8 @@ class ModelScanner { } if (orderMap.containsKey(order)) { - throw new ConfigurationException("Detected duplicate field order '" + childAnnotation.order() + "' for element named '" + elementName + "' in type '" + theClass.getCanonicalName() + "'"); + throw new ConfigurationException("Detected duplicate field order '" + childAnnotation.order() + "' for element named '" + elementName + "' in type '" + theClass.getCanonicalName() + + "'"); } if (elementNames.contains(elementName)) { @@ -352,7 +355,8 @@ class ModelScanner { * Child is an extension */ Class et = (Class) nextElementType; - RuntimeChildDeclaredExtensionDefinition def = new RuntimeChildDeclaredExtensionDefinition(next, childAnnotation, descriptionAnnotation, extensionAttr, elementName, extensionAttr.url(), et); + RuntimeChildDeclaredExtensionDefinition def = new RuntimeChildDeclaredExtensionDefinition(next, childAnnotation, descriptionAnnotation, extensionAttr, elementName, + extensionAttr.url(), et); orderMap.put(order, def); if (IElement.class.isAssignableFrom(nextElementType)) { addScanAlso((Class) nextElementType); @@ -374,8 +378,7 @@ class ModelScanner { } else if (IResourceBlock.class.isAssignableFrom(nextElementType)) { /* - * Child is a resource block (i.e. a sub-tag within a resource) - * TODO: do these have a better name according to HL7? + * Child is a resource block (i.e. a sub-tag within a resource) TODO: do these have a better name according to HL7? */ Class blockDef = (Class) nextElementType; @@ -407,7 +410,8 @@ class ModelScanner { CodeableConceptElement concept = next.getAnnotation(CodeableConceptElement.class); if (concept != null) { if (!ICodedDatatype.class.isAssignableFrom(nextDatatype)) { - throw new ConfigurationException("Field '" + elementName + "' in type '" + theClass.getCanonicalName() + "' is marked as @" + CodeableConceptElement.class.getCanonicalName() + " but type is not a subtype of " + ICodedDatatype.class.getName()); + throw new ConfigurationException("Field '" + elementName + "' in type '" + theClass.getCanonicalName() + "' is marked as @" + CodeableConceptElement.class.getCanonicalName() + + " but type is not a subtype of " + ICodedDatatype.class.getName()); } else { Class type = concept.type(); myScanAlsoCodeTable.add(type); @@ -457,19 +461,23 @@ class ModelScanner { if (myNameToResourceDefinitions.containsKey(resourceName)) { if (!myNameToResourceDefinitions.get(resourceName).getImplementingClass().equals(theClass)) { - throw new ConfigurationException("Detected duplicate element name '" + resourceName + "' in types '" + theClass.getCanonicalName() + "' and '" + myNameToResourceDefinitions.get(resourceName).getImplementingClass() + "'"); +// throw new ConfigurationException("Detected duplicate element name '" + resourceName + "' in types '" + theClass.getCanonicalName() + "' and '" +// + myNameToResourceDefinitions.get(resourceName).getImplementingClass() + "'"); + } else { + return resourceName; } - return resourceName; } String resourceId = resourceDefinition.id(); if (isBlank(resourceId)) { - throw new ConfigurationException("Resource type @" + ResourceDef.class.getSimpleName() + " annotation contains no resource ID: " + theClass.getCanonicalName()); + // throw new ConfigurationException("Resource type @" + ResourceDef.class.getSimpleName() + " annotation contains no resource ID: " + theClass.getCanonicalName()); + } else { + if (myIdToResourceDefinition.containsKey(resourceId)) { + throw new ConfigurationException("The following resource types have the same ID of '" + resourceId + "' - " + theClass.getCanonicalName() + " and " + + myIdToResourceDefinition.get(resourceId).getImplementingClass().getCanonicalName()); + } } - if (myIdToResourceDefinition.containsKey(resourceId)) { - throw new ConfigurationException("The following resource types have the same ID of '" + resourceId + "' - " + theClass.getCanonicalName() + " and " + myIdToResourceDefinition.get(resourceId).getImplementingClass().getCanonicalName()); - } - + RuntimeResourceDefinition resourceDef = new RuntimeResourceDefinition(theClass, resourceDefinition); myClassToElementDefinitions.put(theClass, resourceDef); myNameToResourceDefinitions.put(resourceName, resourceDef); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Binary.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/Binary.java similarity index 77% rename from hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Binary.java rename to hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/Binary.java index e55d65efaee..3b2479f76bf 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Binary.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/Binary.java @@ -1,5 +1,6 @@ -package ca.uhn.fhir.model.api; +package ca.uhn.fhir.model.dstu.resource; +import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.annotation.ResourceDef; @ResourceDef(name="Binary", profile="http://hl7.org/fhir/profiles/Binary", id="binary") diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BoundCodeDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BoundCodeDt.java index 8e6ab52f127..0aa8ffcc971 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BoundCodeDt.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BoundCodeDt.java @@ -3,7 +3,7 @@ package ca.uhn.fhir.model.primitive; import ca.uhn.fhir.model.api.IValueSetEnumBinder; import ca.uhn.fhir.model.api.annotation.DatatypeDef; -@DatatypeDef(name = "code") +@DatatypeDef(name = "boundCode") // note: this name is not real, it's a HAPI identifier- we should remove it public class BoundCodeDt> extends CodeDt { private IValueSetEnumBinder myBinder; diff --git a/hapi-fhir-base/src/site/site.xml b/hapi-fhir-base/src/site/site.xml index fb9cb12b614..25f8151e1f2 100644 --- a/hapi-fhir-base/src/site/site.xml +++ b/hapi-fhir-base/src/site/site.xml @@ -32,6 +32,7 @@ + diff --git a/hapi-fhir-base/src/site/xdoc/doc_tinder.xml b/hapi-fhir-base/src/site/xdoc/doc_tinder.xml new file mode 100644 index 00000000000..39dd068f23c --- /dev/null +++ b/hapi-fhir-base/src/site/xdoc/doc_tinder.xml @@ -0,0 +1,85 @@ + + + + + Tinder - HAPI FHIR + James Agnew + + + + +
+ + + + +

+ According to the FHIR specification, any conformant server + must be able to export a Conformance statement, which + indicates all of the resource types and potential operations + that the server supports. +

+ +

+ HAPI provides a Maven plugin called "Tinder" which is able to automatically + generate a client based on that conformance statement. +

+ +
+ +
+ +

+ The following example shows a simple Maven plugin which + builds a client for the Health Intersections reference + server. +

+ + + + ca.uhn.hapi.fhir + hapi-tinder-plugin + 1.0-SNAPSHOT + + + generate-structures + + ca.uhn.hitest.HiTest + http://fhir.healthintersections.com.au/open + true + + + + +]]> + +

+ This example will create a class called + ca.uhn.hitest.HiTest which has + methods to invoke the various server operations. +

+ +

+ It is then possible to use this client as simply as: +

+ + + +
+ + + +
diff --git a/hapi-fhir-structures-dstu/pom.xml b/hapi-fhir-structures-dstu/pom.xml index 97cfb79b9f1..fe3cdd86062 100644 --- a/hapi-fhir-structures-dstu/pom.xml +++ b/hapi-fhir-structures-dstu/pom.xml @@ -53,6 +53,7 @@ substance valueset + true diff --git a/hapi-tinder-plugin/.classpath b/hapi-tinder-plugin/.classpath index 7bbf0de5900..c967e1bd5c7 100644 --- a/hapi-tinder-plugin/.classpath +++ b/hapi-tinder-plugin/.classpath @@ -1,6 +1,7 @@ + diff --git a/hapi-tinder-plugin/pom.xml b/hapi-tinder-plugin/pom.xml index 79276d9ef6d..7d7fc85086d 100644 --- a/hapi-tinder-plugin/pom.xml +++ b/hapi-tinder-plugin/pom.xml @@ -46,7 +46,7 @@ commons-io 2.4 - + org.slf4j @@ -97,26 +97,43 @@ 3.1.1 + + + + org.apache.maven.plugins + maven-plugin-plugin + 3.2 + + + + report + + + + + + + - - org.apache.maven.plugins - maven-plugin-plugin - 3.2 - - - true - + + org.apache.maven.plugins + maven-plugin-plugin + 3.2 + + + true + - - - mojo-descriptor - - descriptor - - - - + + + mojo-descriptor + + descriptor + + + + + + + ca.uhn.hapi.fhir + hapi-tinder-plugin + 1.0-SNAPSHOT + + + custom-structs + + generate-structures + + + ca.uhn.test.customstructs + + src/test/resources/profile/patient.xml + src/test/resources/profile/organization.xml + + + src/test/resources/valueset/valueset-cgta-patientidpool.xml + src/test/resources/valueset/valueset-cgta-provideridpool.xml + + + + + generalstructs + + generate-structures + + + ca.uhn.test.realstructs + + patient + valueset + organization + device + location + practitioner + + true + + + + + diff --git a/hapi-tinder-test/src/test/resources/profile/organization.xml b/hapi-tinder-test/src/test/resources/profile/organization.xml new file mode 100644 index 00000000000..536f0e99486 --- /dev/null +++ b/hapi-tinder-test/src/test/resources/profile/organization.xml @@ -0,0 +1,579 @@ + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/hapi-tinder-test/src/test/resources/profile/patient.xml b/hapi-tinder-test/src/test/resources/profile/patient.xml new file mode 100644 index 00000000000..be4f2deeb97 --- /dev/null +++ b/hapi-tinder-test/src/test/resources/profile/patient.xml @@ -0,0 +1,1021 @@ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/hapi-tinder-test/src/test/resources/valueset/valueset-cgta-patientidpool.xml b/hapi-tinder-test/src/test/resources/valueset/valueset-cgta-patientidpool.xml new file mode 100644 index 00000000000..10095d6bacf --- /dev/null +++ b/hapi-tinder-test/src/test/resources/valueset/valueset-cgta-patientidpool.xml @@ -0,0 +1,32 @@ + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/hapi-tinder-test/src/test/resources/valueset/valueset-cgta-provideridpool.xml b/hapi-tinder-test/src/test/resources/valueset/valueset-cgta-provideridpool.xml new file mode 100644 index 00000000000..88d62cd058c --- /dev/null +++ b/hapi-tinder-test/src/test/resources/valueset/valueset-cgta-provideridpool.xml @@ -0,0 +1,26 @@ + + + +
+
+
+ + + + + + + + + + + + + + + + + + +
\ No newline at end of file