diff --git a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/GraphQLEngine.java b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/GraphQLEngine.java
index 0127211c9..c78b9d409 100644
--- a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/GraphQLEngine.java
+++ b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/GraphQLEngine.java
@@ -1,33 +1,33 @@
package org.hl7.fhir.dstu3.utils;
-/*
- Copyright (c) 2011+, HL7, Inc.
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of HL7 nor the names of its contributors may be used to
- endorse or promote products derived from this software without specific
- prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-
- */
+/*
+ Copyright (c) 2011+, HL7, Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of HL7 nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ */
@@ -328,7 +328,7 @@ public class GraphQLEngine implements IGraphQLEngine {
return obj.primitiveValue() != "";
}
- private List filter(Resource context, Property prop, List arguments, List values, boolean extensionMode) throws FHIRException, EGraphQLException {
+ private List filter(Resource context, Property prop, String fieldName, List arguments, List values, boolean extensionMode) throws FHIRException, EGraphQLException {
List result = new ArrayList();
if (values.size() > 0) {
int count = Integer.MAX_VALUE;
@@ -353,10 +353,27 @@ public class GraphQLEngine implements IGraphQLEngine {
fp.append(" and "+arg.getName()+" = '"+vl.get(0).toString()+"'");
}
}
+
+ // Account for situations where the GraphQL expression selected e.g.
+ // effectiveDateTime but the field contains effectivePeriod
+ String propName = prop.getName();
+ List newValues = new ArrayList<>(values.size());
+ for (Base value : values) {
+ if (propName.endsWith("[x]")) {
+ String propNameShortened = propName.substring(0, propName.length() - 3);
+ if (fieldName.startsWith(propNameShortened) && fieldName.length() > propNameShortened.length()) {
+ if (!value.fhirType().equalsIgnoreCase(fieldName.substring(propNameShortened.length()))) {
+ continue;
+ }
+ }
+ }
+ newValues.add(value);
+ }
+
int i = 0;
int t = 0;
if (fp.length() == 0)
- for (Base v : values) {
+ for (Base v : newValues) {
if ((i >= offset) && passesExtensionMode(v, extensionMode)) {
result.add(v);
t++;
@@ -365,8 +382,8 @@ public class GraphQLEngine implements IGraphQLEngine {
}
i++;
} else {
- ExpressionNode node = fpe.parse(fp.toString().substring(5));
- for (Base v : values) {
+ ExpressionNode node = fpe.parse(fp.substring(5));
+ for (Base v : newValues) {
if ((i >= offset) && passesExtensionMode(v, extensionMode) && fpe.evaluateToBoolean(null, context, v, node)) {
result.add(v);
t++;
@@ -526,7 +543,7 @@ public class GraphQLEngine implements IGraphQLEngine {
if (!isPrimitive(prop.getTypeCode()) && sel.getField().getName().startsWith("_"))
throw new EGraphQLException("Unknown property "+sel.getField().getName()+" on "+source.fhirType());
- List vl = filter(context, prop, sel.getField().getArguments(), prop.getValues(), sel.getField().getName().startsWith("_"));
+ List vl = filter(context, prop, sel.getField().getName(), sel.getField().getArguments(), prop.getValues(), sel.getField().getName().startsWith("_"));
if (!vl.isEmpty())
processValues(context, sel, prop, target, vl, sel.getField().getName().startsWith("_"), inheritedList, suffix);
}
diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/GraphQLEngine.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/GraphQLEngine.java
index 4608583f9..db7230d8f 100644
--- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/GraphQLEngine.java
+++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/GraphQLEngine.java
@@ -1,33 +1,33 @@
package org.hl7.fhir.r4.utils;
-/*
- Copyright (c) 2011+, HL7, Inc.
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of HL7 nor the names of its contributors may be used to
- endorse or promote products derived from this software without specific
- prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-
- */
+/*
+ Copyright (c) 2011+, HL7, Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of HL7 nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ */
@@ -190,7 +190,7 @@ public class GraphQLEngine implements IGraphQLEngine {
return obj.primitiveValue() != "";
}
- private List filter(Resource context, Property prop, List arguments, List values, boolean extensionMode) throws FHIRException, EGraphQLException {
+ private List filter(Resource context, Property prop, String fieldName, List arguments, List values, boolean extensionMode) throws FHIRException, EGraphQLException {
List result = new ArrayList();
if (values.size() > 0) {
int count = Integer.MAX_VALUE;
@@ -215,10 +215,28 @@ public class GraphQLEngine implements IGraphQLEngine {
fp.append(" and " + arg.getName() + " = '" + vl.get(0).toString() + "'");
}
}
+
+ // Account for situations where the GraphQL expression selected e.g.
+ // effectiveDateTime but the field contains effectivePeriod
+ String propName = prop.getName();
+ List newValues = new ArrayList<>(values.size());
+ for (Base value : values) {
+ if (propName.endsWith("[x]")) {
+ String propNameShortened = propName.substring(0, propName.length() - 3);
+ if (fieldName.startsWith(propNameShortened) && fieldName.length() > propNameShortened.length()) {
+ if (!value.fhirType().equalsIgnoreCase(fieldName.substring(propNameShortened.length()))) {
+ continue;
+ }
+ }
+ }
+ newValues.add(value);
+ }
+
int i = 0;
int t = 0;
if (fp.length() == 0)
- for (Base v : values) {
+ for (Base v : newValues) {
+
if ((i >= offset) && passesExtensionMode(v, extensionMode)) {
result.add(v);
t++;
@@ -228,8 +246,8 @@ public class GraphQLEngine implements IGraphQLEngine {
i++;
}
else {
- ExpressionNode node = fpe.parse(fp.toString().substring(5));
- for (Base v : values) {
+ ExpressionNode node = fpe.parse(fp.substring(5));
+ for (Base v : newValues) {
if ((i >= offset) && passesExtensionMode(v, extensionMode) && fpe.evaluateToBoolean(null, context, v, node)) {
result.add(v);
t++;
@@ -389,7 +407,7 @@ public class GraphQLEngine implements IGraphQLEngine {
if (!isPrimitive(prop.getTypeCode()) && sel.getField().getName().startsWith("_"))
throw new EGraphQLException("Unknown property " + sel.getField().getName() + " on " + source.fhirType());
- List vl = filter(context, prop, sel.getField().getArguments(), prop.getValues(), sel.getField().getName().startsWith("_"));
+ List vl = filter(context, prop, sel.getField().getName(), sel.getField().getArguments(), prop.getValues(), sel.getField().getName().startsWith("_"));
if (!vl.isEmpty())
processValues(context, sel, prop, target, vl, sel.getField().getName().startsWith("_"), inheritedList, suffix);
}
diff --git a/org.hl7.fhir.r4/src/test/resources/graphql/manifest.xml b/org.hl7.fhir.r4/src/test/resources/graphql/manifest.xml
index ff1e6b27c..21af157f1 100644
--- a/org.hl7.fhir.r4/src/test/resources/graphql/manifest.xml
+++ b/org.hl7.fhir.r4/src/test/resources/graphql/manifest.xml
@@ -3,6 +3,7 @@
+
diff --git a/org.hl7.fhir.r4/src/test/resources/graphql/polymorphic-difftype.gql b/org.hl7.fhir.r4/src/test/resources/graphql/polymorphic-difftype.gql
new file mode 100644
index 000000000..4a0f9906f
--- /dev/null
+++ b/org.hl7.fhir.r4/src/test/resources/graphql/polymorphic-difftype.gql
@@ -0,0 +1,5 @@
+{
+ subject{reference}
+ valueQuantity {value unit}
+}
+
diff --git a/org.hl7.fhir.r4/src/test/resources/graphql/polymorphic-difftype.json b/org.hl7.fhir.r4/src/test/resources/graphql/polymorphic-difftype.json
new file mode 100644
index 000000000..f47cb5e74
--- /dev/null
+++ b/org.hl7.fhir.r4/src/test/resources/graphql/polymorphic-difftype.json
@@ -0,0 +1,6 @@
+{
+ "subject" : {
+ "reference" : "Patient/example"
+ },
+ "valueString": "FOO"
+}
\ No newline at end of file
diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/utils/GraphQLEngine.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/utils/GraphQLEngine.java
index 44bf6e92c..e419f3549 100644
--- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/utils/GraphQLEngine.java
+++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/utils/GraphQLEngine.java
@@ -7,34 +7,34 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-/*
- Copyright (c) 2011+, HL7, Inc.
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of HL7 nor the names of its contributors may be used to
- endorse or promote products derived from this software without specific
- prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-
- */
+/*
+ Copyright (c) 2011+, HL7, Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of HL7 nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ */
@@ -356,7 +356,7 @@ public class GraphQLEngine implements IGraphQLEngine {
return obj.primitiveValue() != "";
}
- private List filter(Resource context, Property prop, List arguments, List values, boolean extensionMode) throws FHIRException, EGraphQLException {
+ private List filter(Resource context, Property prop, String fieldName, List arguments, List values, boolean extensionMode) throws FHIRException, EGraphQLException {
List result = new ArrayList();
if (values.size() > 0) {
int count = Integer.MAX_VALUE;
@@ -381,10 +381,28 @@ public class GraphQLEngine implements IGraphQLEngine {
fp.append(" and "+arg.getName()+" = '"+vl.get(0).toString()+"'");
}
}
+
+
+ // Account for situations where the GraphQL expression selected e.g.
+ // effectiveDateTime but the field contains effectivePeriod
+ String propName = prop.getName();
+ List newValues = new ArrayList<>(values.size());
+ for (Base value : values) {
+ if (propName.endsWith("[x]")) {
+ String propNameShortened = propName.substring(0, propName.length() - 3);
+ if (fieldName.startsWith(propNameShortened) && fieldName.length() > propNameShortened.length()) {
+ if (!value.fhirType().equalsIgnoreCase(fieldName.substring(propNameShortened.length()))) {
+ continue;
+ }
+ }
+ }
+ newValues.add(value);
+ }
+
int i = 0;
int t = 0;
if (fp.length() == 0)
- for (Base v : values) {
+ for (Base v : newValues) {
if ((i >= offset) && passesExtensionMode(v, extensionMode)) {
result.add(v);
t++;
@@ -393,8 +411,8 @@ public class GraphQLEngine implements IGraphQLEngine {
}
i++;
} else {
- ExpressionNode node = fpe.parse(fp.toString().substring(5));
- for (Base v : values) {
+ ExpressionNode node = fpe.parse(fp.substring(5));
+ for (Base v : newValues) {
if ((i >= offset) && passesExtensionMode(v, extensionMode) && fpe.evaluateToBoolean(null, context, v, node)) {
result.add(v);
t++;
@@ -554,7 +572,7 @@ public class GraphQLEngine implements IGraphQLEngine {
if (!isPrimitive(prop.getTypeCode()) && sel.getField().getName().startsWith("_"))
throw new EGraphQLException("Unknown property "+sel.getField().getName()+" on "+source.fhirType());
- List vl = filter(context, prop, sel.getField().getArguments(), prop.getValues(), sel.getField().getName().startsWith("_"));
+ List vl = filter(context, prop, sel.getField().getName(), sel.getField().getArguments(), prop.getValues(), sel.getField().getName().startsWith("_"));
if (!vl.isEmpty())
processValues(context, sel, prop, target, vl, sel.getField().getName().startsWith("_"), inheritedList, suffix);
}
diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLEngine.java
index 769ebf5fd..9c95475bc 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLEngine.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLEngine.java
@@ -7,34 +7,34 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-/*
- Copyright (c) 2011+, HL7, Inc.
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of HL7 nor the names of its contributors may be used to
- endorse or promote products derived from this software without specific
- prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
-
- */
+/*
+ Copyright (c) 2011+, HL7, Inc.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of HL7 nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ */
@@ -356,7 +356,7 @@ public class GraphQLEngine implements IGraphQLEngine {
return obj.primitiveValue() != "";
}
- private List filter(Resource context, Property prop, List arguments, List values, boolean extensionMode) throws FHIRException, EGraphQLException {
+ private List filter(Resource context, Property prop, String fieldName, List arguments, List values, boolean extensionMode) throws FHIRException, EGraphQLException {
List result = new ArrayList();
if (values.size() > 0) {
int count = Integer.MAX_VALUE;
@@ -381,10 +381,27 @@ public class GraphQLEngine implements IGraphQLEngine {
fp.append(" and "+arg.getName()+" = '"+vl.get(0).toString()+"'");
}
}
+
+ // Account for situations where the GraphQL expression selected e.g.
+ // effectiveDateTime but the field contains effectivePeriod
+ String propName = prop.getName();
+ List newValues = new ArrayList<>(values.size());
+ for (Base value : values) {
+ if (propName.endsWith("[x]")) {
+ String propNameShortened = propName.substring(0, propName.length() - 3);
+ if (fieldName.startsWith(propNameShortened) && fieldName.length() > propNameShortened.length()) {
+ if (!value.fhirType().equalsIgnoreCase(fieldName.substring(propNameShortened.length()))) {
+ continue;
+ }
+ }
+ }
+ newValues.add(value);
+ }
+
int i = 0;
int t = 0;
if (fp.length() == 0)
- for (Base v : values) {
+ for (Base v : newValues) {
if ((i >= offset) && passesExtensionMode(v, extensionMode)) {
result.add(v);
t++;
@@ -393,8 +410,8 @@ public class GraphQLEngine implements IGraphQLEngine {
}
i++;
} else {
- ExpressionNode node = fpe.parse(fp.toString().substring(5));
- for (Base v : values) {
+ ExpressionNode node = fpe.parse(fp.substring(5));
+ for (Base v : newValues) {
if ((i >= offset) && passesExtensionMode(v, extensionMode) && fpe.evaluateToBoolean(null, context, v, node)) {
result.add(v);
t++;
@@ -554,7 +571,7 @@ public class GraphQLEngine implements IGraphQLEngine {
if (!isPrimitive(prop.getTypeCode()) && sel.getField().getName().startsWith("_"))
throw new EGraphQLException("Unknown property "+sel.getField().getName()+" on "+source.fhirType());
- List vl = filter(context, prop, sel.getField().getArguments(), prop.getValues(), sel.getField().getName().startsWith("_"));
+ List vl = filter(context, prop, sel.getField().getName(), sel.getField().getArguments(), prop.getValues(), sel.getField().getName().startsWith("_"));
if (!vl.isEmpty())
processValues(context, sel, prop, target, vl, sel.getField().getName().startsWith("_"), inheritedList, suffix);
}
diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLSchemaGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLSchemaGenerator.java
index 2bda2d70d..526960c88 100644
--- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLSchemaGenerator.java
+++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/GraphQLSchemaGenerator.java
@@ -30,24 +30,10 @@ package org.hl7.fhir.r5.utils;
*/
-
// todo:
// - generate sort order parameters
// - generate inherited search parameters
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.IWorkerContext;
@@ -60,33 +46,50 @@ import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.utilities.Utilities;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static java.util.Objects.requireNonNull;
+
public class GraphQLSchemaGenerator {
- public enum FHIROperationType {READ, SEARCH, CREATE, UPDATE, DELETE};
-
- private static final String INNER_TYPE_NAME = "gql.type.name";
private static final Set JSON_NUMBER_TYPES = new HashSet() {{
add("decimal");
add("positiveInt");
add("unsignedInt");
}};
-
+ private final ProfileUtilities profileUtilities;
+ private final String version;
IWorkerContext context;
- private ProfileUtilities profileUtilities;
- private String version;
-
public GraphQLSchemaGenerator(IWorkerContext context, String version) {
super();
this.context = context;
this.version = version;
- profileUtilities = new ProfileUtilities(context, null, null);
+ profileUtilities = new ProfileUtilities(context, null, null);
}
-
+
public void generateTypes(OutputStream stream) throws IOException, FHIRException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
-
- Map pl = new HashMap();
- Map tl = new HashMap();
+ generateTypes(writer);
+ writer.flush();
+ writer.close();
+ }
+
+ public void generateTypes(Writer writer) throws IOException {
+ Map pl = new HashMap<>();
+ Map tl = new HashMap<>();
+ Map existingTypeNames = new HashMap<>();
for (StructureDefinition sd : context.allStructures()) {
if (sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE && sd.getDerivation() == TypeDerivationRule.SPECIALIZATION) {
pl.put(sd.getName(), sd);
@@ -95,29 +98,39 @@ public class GraphQLSchemaGenerator {
tl.put(sd.getName(), sd);
}
}
- writer.write("# FHIR GraphQL Schema. Version "+version+"\r\n\r\n");
+ writer.write("# FHIR GraphQL Schema. Version " + version + "\r\n\r\n");
writer.write("# FHIR Defined Primitive types\r\n");
for (String n : sorted(pl.keySet()))
generatePrimitive(writer, pl.get(n));
writer.write("\r\n");
writer.write("# FHIR Defined Search Parameter Types\r\n");
for (SearchParamType dir : SearchParamType.values()) {
+ if (pl.containsKey(dir.toCode())) {
+ // Don't double create String and URI
+ continue;
+ }
if (dir != SearchParamType.NULL)
- generateSearchParamType(writer, dir.toCode());
+ generateSearchParamType(writer, dir.toCode());
}
writer.write("\r\n");
generateElementBase(writer);
for (String n : sorted(tl.keySet()))
- generateType(writer, tl.get(n));
- writer.flush();
- writer.close();
+ generateType(existingTypeNames, writer, tl.get(n));
}
public void generateResource(OutputStream stream, StructureDefinition sd, List parameters, EnumSet operations) throws IOException, FHIRException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
- writer.write("# FHIR GraphQL Schema. Version "+version+"\r\n\r\n");
+ generateResource(writer, sd, parameters, operations);
+ writer.flush();
+ writer.close();
+ }
+
+ public void generateResource(Writer writer, StructureDefinition sd, List parameters, EnumSet operations) throws IOException {
+ Map existingTypeNames = new HashMap<>();
+
+ writer.write("# FHIR GraphQL Schema. Version " + version + "\r\n\r\n");
writer.write("# import * from 'types.graphql'\r\n\r\n");
- generateType(writer, sd);
+ generateType(existingTypeNames, writer, sd);
if (operations.contains(FHIROperationType.READ))
generateIdAccess(writer, sd.getName());
if (operations.contains(FHIROperationType.SEARCH)) {
@@ -130,93 +143,90 @@ public class GraphQLSchemaGenerator {
generateUpdate(writer, sd.getName());
if (operations.contains(FHIROperationType.DELETE))
generateDelete(writer, sd.getName());
- writer.flush();
- writer.close();
}
- private void generateCreate(BufferedWriter writer, String name) throws IOException {
- writer.write("type "+name+"CreateType {\r\n");
- writer.write(" "+name+"Create(");
- param(writer, "resource", name+"Input", false, false);
- writer.write("): "+name+"Creation\r\n");
+ private void generateCreate(Writer writer, String name) throws IOException {
+ writer.write("type " + name + "CreateType {\r\n");
+ writer.write(" " + name + "Create(");
+ param(writer, "resource", name + "Input", false, false);
+ writer.write("): " + name + "Creation\r\n");
writer.write("}\r\n");
- writer.write("\r\n");
- writer.write("type "+name+"Creation {\r\n");
+ writer.write("\r\n");
+ writer.write("type " + name + "Creation {\r\n");
writer.write(" location: String\r\n");
- writer.write(" resource: "+name+"\r\n");
+ writer.write(" resource: " + name + "\r\n");
writer.write(" information: OperationOutcome\r\n");
writer.write("}\r\n");
- writer.write("\r\n");
+ writer.write("\r\n");
}
- private void generateUpdate(BufferedWriter writer, String name) throws IOException {
- writer.write("type "+name+"UpdateType {\r\n");
- writer.write(" "+name+"Update(");
+ private void generateUpdate(Writer writer, String name) throws IOException {
+ writer.write("type " + name + "UpdateType {\r\n");
+ writer.write(" " + name + "Update(");
param(writer, "id", "ID", false, false);
writer.write(", ");
- param(writer, "resource", name+"Input", false, false);
- writer.write("): "+name+"Update\r\n");
+ param(writer, "resource", name + "Input", false, false);
+ writer.write("): " + name + "Update\r\n");
writer.write("}\r\n");
- writer.write("\r\n");
- writer.write("type "+name+"Update {\r\n");
- writer.write(" resource: "+name+"\r\n");
+ writer.write("\r\n");
+ writer.write("type " + name + "Update {\r\n");
+ writer.write(" resource: " + name + "\r\n");
writer.write(" information: OperationOutcome\r\n");
writer.write("}\r\n");
- writer.write("\r\n");
+ writer.write("\r\n");
}
- private void generateDelete(BufferedWriter writer, String name) throws IOException {
- writer.write("type "+name+"DeleteType {\r\n");
- writer.write(" "+name+"Delete(");
+ private void generateDelete(Writer writer, String name) throws IOException {
+ writer.write("type " + name + "DeleteType {\r\n");
+ writer.write(" " + name + "Delete(");
param(writer, "id", "ID", false, false);
- writer.write("): "+name+"Delete\r\n");
+ writer.write("): " + name + "Delete\r\n");
writer.write("}\r\n");
- writer.write("\r\n");
- writer.write("type "+name+"Delete {\r\n");
+ writer.write("\r\n");
+ writer.write("type " + name + "Delete {\r\n");
writer.write(" information: OperationOutcome\r\n");
writer.write("}\r\n");
- writer.write("\r\n");
+ writer.write("\r\n");
}
- private void generateListAccess(BufferedWriter writer, List parameters, String name) throws IOException {
- writer.write("type "+name+"ListType {\r\n");
- writer.write(" "+name+"List(");
+ private void generateListAccess(Writer writer, List parameters, String name) throws IOException {
+ writer.write("type " + name + "ListType {\r\n");
+ writer.write(" ");
+ generateListAccessQuery(writer, parameters, name);
+ writer.write("}\r\n");
+ writer.write("\r\n");
+ }
+
+ public void generateListAccessQuery(Writer writer, List parameters, String name) throws IOException {
+ writer.write(name + "List(");
param(writer, "_filter", "String", false, false);
for (SearchParameter sp : parameters)
- param(writer, sp.getName().replace("-", "_"), getGqlname(sp.getType().toCode()), true, true);
+ param(writer, sp.getName().replace("-", "_"), getGqlname(requireNonNull(sp.getType().toCode())), true, true);
param(writer, "_sort", "String", false, true);
param(writer, "_count", "Int", false, true);
param(writer, "_cursor", "String", false, true);
- writer.write("): ["+name+"]\r\n");
- writer.write("}\r\n");
- writer.write("\r\n");
+ writer.write("): [" + name + "]\r\n");
}
- private void param(BufferedWriter writer, String name, String type, boolean list, boolean line) throws IOException {
+ private void param(Writer writer, String name, String type, boolean list, boolean line) throws IOException {
if (line)
writer.write("\r\n ");
writer.write(name);
writer.write(": ");
if (list)
writer.write("[");
- writer.write(type);
+ writer.write(type);
if (list)
writer.write("]");
}
- private void generateConnectionAccess(BufferedWriter writer, List parameters, String name) throws IOException {
- writer.write("type "+name+"ConnectionType {\r\n");
- writer.write(" "+name+"Conection(");
- param(writer, "_filter", "String", false, false);
- for (SearchParameter sp : parameters)
- param(writer, sp.getName().replace("-", "_"), getGqlname(sp.getType().toCode()), true, true);
- param(writer, "_sort", "String", false, true);
- param(writer, "_count", "Int", false, true);
- param(writer, "_cursor", "String", false, true);
- writer.write("): "+name+"Connection\r\n");
+ private void generateConnectionAccess(Writer writer, List parameters, String name) throws IOException {
+ writer.write("type " + name + "ConnectionType {\r\n");
+ writer.write(" ");
+ generateConnectionAccessQuery(writer, parameters, name);
writer.write("}\r\n");
- writer.write("\r\n");
- writer.write("type "+name+"Connection {\r\n");
+ writer.write("\r\n");
+ writer.write("type " + name + "Connection {\r\n");
writer.write(" count: Int\r\n");
writer.write(" offset: Int\r\n");
writer.write(" pagesize: Int\r\n");
@@ -224,32 +234,42 @@ public class GraphQLSchemaGenerator {
writer.write(" previous: ID\r\n");
writer.write(" next: ID\r\n");
writer.write(" last: ID\r\n");
- writer.write(" edges: ["+name+"Edge]\r\n");
+ writer.write(" edges: [" + name + "Edge]\r\n");
writer.write("}\r\n");
- writer.write("\r\n");
- writer.write("type "+name+"Edge {\r\n");
+ writer.write("\r\n");
+ writer.write("type " + name + "Edge {\r\n");
writer.write(" mode: String\r\n");
writer.write(" score: Float\r\n");
- writer.write(" resource: "+name+"\r\n");
+ writer.write(" resource: " + name + "\r\n");
writer.write("}\r\n");
- writer.write("\r\n");
+ writer.write("\r\n");
}
-
- private void generateIdAccess(BufferedWriter writer, String name) throws IOException {
- writer.write("type "+name+"ReadType {\r\n");
- writer.write(" "+name+"(id: ID!): "+name+"\r\n");
- writer.write("}\r\n");
- writer.write("\r\n");
+ public void generateConnectionAccessQuery(Writer writer, List parameters, String name) throws IOException {
+ writer.write(name + "Conection(");
+ param(writer, "_filter", "String", false, false);
+ for (SearchParameter sp : parameters)
+ param(writer, sp.getName().replace("-", "_"), getGqlname(requireNonNull(sp.getType().toCode())), true, true);
+ param(writer, "_sort", "String", false, true);
+ param(writer, "_count", "Int", false, true);
+ param(writer, "_cursor", "String", false, true);
+ writer.write("): " + name + "Connection\r\n");
}
- private void generateElementBase(BufferedWriter writer) throws IOException {
+ private void generateIdAccess(Writer writer, String name) throws IOException {
+ writer.write("type " + name + "ReadType {\r\n");
+ writer.write(" " + name + "(id: ID!): " + name + "\r\n");
+ writer.write("}\r\n");
+ writer.write("\r\n");
+ }
+
+ private void generateElementBase(Writer writer) throws IOException {
writer.write("type ElementBase {\r\n");
writer.write(" id: ID\r\n");
writer.write(" extension: [Extension]\r\n");
writer.write("}\r\n");
writer.write("\r\n");
-
+
writer.write("input ElementBaseInput {\r\n");
writer.write(" id : ID\r\n");
writer.write(" extension: [ExtensionInput]\r\n");
@@ -257,18 +277,18 @@ public class GraphQLSchemaGenerator {
writer.write("\r\n");
}
- private void generateType(BufferedWriter writer, StructureDefinition sd) throws IOException {
+ private void generateType(Map existingTypeNames, Writer writer, StructureDefinition sd) throws IOException {
if (sd.getAbstract())
return;
-
- List list = new ArrayList();
+
+ List list = new ArrayList<>();
StringBuilder b = new StringBuilder();
list.add(b);
b.append("type ");
b.append(sd.getName());
b.append(" {\r\n");
ElementDefinition ed = sd.getSnapshot().getElementFirstRep();
- generateProperties(list, b, sd.getName(), sd, ed, "type", "");
+ generateProperties(existingTypeNames, list, b, sd.getName(), sd, ed, "type", "");
b.append("}");
b.append("\r\n");
b.append("\r\n");
@@ -281,7 +301,7 @@ public class GraphQLSchemaGenerator {
b.append(sd.getName());
b.append("Input {\r\n");
ed = sd.getSnapshot().getElementFirstRep();
- generateProperties(list, b, sd.getName(), sd, ed, "input", "Input");
+ generateProperties(existingTypeNames, list, b, sd.getName(), sd, ed, "input", "Input");
b.append("}");
b.append("\r\n");
b.append("\r\n");
@@ -289,22 +309,22 @@ public class GraphQLSchemaGenerator {
writer.write(bs.toString());
}
- private void generateProperties(List list, StringBuilder b, String typeName, StructureDefinition sd, ElementDefinition ed, String mode, String suffix) throws IOException {
+ private void generateProperties(Map existingTypeNames, List list, StringBuilder b, String typeName, StructureDefinition sd, ElementDefinition ed, String mode, String suffix) throws IOException {
List children = profileUtilities.getChildList(sd, ed);
for (ElementDefinition child : children) {
if (child.hasContentReference()) {
- ElementDefinition ref = resolveContentReference(sd, child.getContentReference());
- generateProperty(list, b, typeName, sd, child, ref.getType().get(0), false, ref, mode, suffix);
+ ElementDefinition ref = resolveContentReference(sd, child.getContentReference());
+ generateProperty(existingTypeNames, list, b, typeName, sd, child, ref.getType().get(0), false, ref, mode, suffix);
} else if (child.getType().size() == 1) {
- generateProperty(list, b, typeName, sd, child, child.getType().get(0), false, null, mode, suffix);
+ generateProperty(existingTypeNames, list, b, typeName, sd, child, child.getType().get(0), false, null, mode, suffix);
} else {
- boolean ref = false;
+ boolean ref = false;
for (TypeRefComponent t : child.getType()) {
if (!t.hasTarget())
- generateProperty(list, b, typeName, sd, child, t, true, null, mode, suffix);
+ generateProperty(existingTypeNames, list, b, typeName, sd, child, t, true, null, mode, suffix);
else if (!ref) {
ref = true;
- generateProperty(list, b, typeName, sd, child, t, true, null, mode, suffix);
+ generateProperty(existingTypeNames, list, b, typeName, sd, child, t, true, null, mode, suffix);
}
}
}
@@ -317,12 +337,12 @@ public class GraphQLSchemaGenerator {
if (id.equals(ed.getId()))
return ed;
}
- throw new Error("Unable to find "+id);
+ throw new Error("Unable to find " + id);
}
- private void generateProperty(List list, StringBuilder b, String typeName, StructureDefinition sd, ElementDefinition child, TypeRefComponent typeDetails, boolean suffix, ElementDefinition cr, String mode, String suffixS) throws IOException {
+ private void generateProperty(Map existingTypeNames, List list, StringBuilder b, String typeName, StructureDefinition sd, ElementDefinition child, TypeRefComponent typeDetails, boolean suffix, ElementDefinition cr, String mode, String suffixS) throws IOException {
if (isPrimitive(typeDetails)) {
- String n = getGqlname(typeDetails.getWorkingCode());
+ String n = getGqlname(typeDetails.getWorkingCode());
b.append(" ");
b.append(tail(child.getPath(), suffix));
if (suffix)
@@ -334,15 +354,15 @@ public class GraphQLSchemaGenerator {
b.append(tail(child.getPath(), suffix));
if (suffix)
b.append(Utilities.capitalize(typeDetails.getWorkingCode()));
- if (!child.getMax().equals("1")) {
- b.append(": [ElementBase");
- b.append(suffixS);
- b.append("]\r\n");
- } else {
- b.append(": ElementBase");
- b.append(suffixS);
- b.append("\r\n");
- }
+ if (!child.getMax().equals("1")) {
+ b.append(": [ElementBase");
+ b.append(suffixS);
+ b.append("]\r\n");
+ } else {
+ b.append(": ElementBase");
+ b.append(suffixS);
+ b.append("\r\n");
+ }
} else
b.append("\r\n");
} else {
@@ -355,11 +375,11 @@ public class GraphQLSchemaGenerator {
b.append("[");
String type = typeDetails.getWorkingCode();
if (cr != null)
- b.append(generateInnerType(list, sd, typeName, cr, mode, suffixS));
+ b.append(generateInnerType(existingTypeNames, list, sd, typeName, cr, mode, suffixS));
else if (Utilities.existsInList(type, "Element", "BackboneElement"))
- b.append(generateInnerType(list, sd, typeName, child, mode, suffixS));
+ b.append(generateInnerType(existingTypeNames, list, sd, typeName, child, mode, suffixS));
else
- b.append(type+suffixS);
+ b.append(type).append(suffixS);
if (!child.getMax().equals("1"))
b.append("]");
if (child.getMin() != 0 && !suffix)
@@ -368,12 +388,15 @@ public class GraphQLSchemaGenerator {
}
}
- private String generateInnerType(List list, StructureDefinition sd, String name, ElementDefinition child, String mode, String suffix) throws IOException {
- if (child.hasUserData(INNER_TYPE_NAME+"."+mode))
- return child.getUserString(INNER_TYPE_NAME+"."+mode);
-
- String typeName = name+Utilities.capitalize(tail(child.getPath(), false));
- child.setUserData(INNER_TYPE_NAME+"."+mode, typeName);
+ private String generateInnerType(Map existingTypeNames, List list, StructureDefinition sd, String name, ElementDefinition child, String mode, String suffix) throws IOException {
+ String key = child.getName() + "." + mode;
+ if (existingTypeNames.containsKey(key)) {
+ return existingTypeNames.get(key);
+ }
+
+ String typeName = name + Utilities.capitalize(tail(child.getPath(), false)) + suffix;
+ existingTypeNames.put(key, typeName + suffix);
+
StringBuilder b = new StringBuilder();
list.add(b);
b.append(mode);
@@ -381,16 +404,16 @@ public class GraphQLSchemaGenerator {
b.append(typeName);
b.append(suffix);
b.append(" {\r\n");
- generateProperties(list, b, typeName, sd, child, mode, suffix);
+ generateProperties(existingTypeNames, list, b, typeName, sd, child, mode, suffix);
b.append("}");
b.append("\r\n");
b.append("\r\n");
- return typeName+suffix;
+ return typeName + suffix;
}
private String tail(String path, boolean suffix) {
if (suffix)
- path = path.substring(0, path.length()-3);
+ path = path.substring(0, path.length() - 3);
int i = path.lastIndexOf(".");
return i < 0 ? path : path.substring(i + 1);
}
@@ -404,20 +427,19 @@ public class GraphQLSchemaGenerator {
}
private List sorted(Set keys) {
- List sl = new ArrayList<>();
- sl.addAll(keys);
+ List sl = new ArrayList<>(keys);
Collections.sort(sl);
return sl;
}
- private void generatePrimitive(BufferedWriter writer, StructureDefinition sd) throws IOException, FHIRException {
+ private void generatePrimitive(Writer writer, StructureDefinition sd) throws IOException, FHIRException {
String gqlName = getGqlname(sd.getName());
- if (gqlName.equals(sd.getName())) {
+ if (gqlName.equals(sd.getName())) {
writer.write("scalar ");
writer.write(sd.getName());
writer.write(" # JSON Format: ");
writer.write(getJsonFormat(sd));
- } else {
+ } else {
writer.write("# Type ");
writer.write(sd.getName());
writer.write(": use GraphQL Scalar type ");
@@ -426,17 +448,17 @@ public class GraphQLSchemaGenerator {
writer.write("\r\n");
}
- private void generateSearchParamType(BufferedWriter writer, String name) throws IOException, FHIRException {
+ private void generateSearchParamType(Writer writer, String name) throws IOException, FHIRException {
String gqlName = getGqlname(name);
if (gqlName.equals("date")) {
writer.write("# Search Param ");
writer.write(name);
writer.write(": already defined as Primitive with JSON Format: string ");
- } else if (gqlName.equals(name)) {
+ } else if (gqlName.equals(name)) {
writer.write("scalar ");
writer.write(name);
writer.write(" # JSON Format: string");
- } else {
+ } else {
writer.write("# Search Param ");
writer.write(name);
writer.write(": use GraphQL Scalar type ");
@@ -444,10 +466,10 @@ public class GraphQLSchemaGenerator {
}
writer.write("\r\n");
}
-
+
private String getJsonFormat(StructureDefinition sd) throws FHIRException {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
- if (!ed.getType().isEmpty() && ed.getType().get(0).getCodeElement().hasExtension("http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type"))
+ if (!ed.getType().isEmpty() && ed.getType().get(0).getCodeElement().hasExtension("http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type"))
return ed.getType().get(0).getCodeElement().getExtensionString("http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type");
}
// all primitives but JSON_NUMBER_TYPES are represented as JSON strings
@@ -466,7 +488,9 @@ public class GraphQLSchemaGenerator {
if (name.equals("boolean"))
return "Boolean";
if (name.equals("id"))
- return "ID";
+ return "ID";
return name;
}
+
+ public enum FHIROperationType {READ, SEARCH, CREATE, UPDATE, DELETE}
}
\ No newline at end of file