Merge pull request #615 from lschmierer/graphql_fixes
Fix GraphQLSchemaGenerator to produce valid GraphQL schemas
This commit is contained in:
commit
c8c96e13fd
|
@ -1,33 +1,33 @@
|
||||||
package org.hl7.fhir.r4.utils;
|
package org.hl7.fhir.r4.utils;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2011+, HL7, Inc.
|
Copyright (c) 2011+, HL7, Inc.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
list of conditions and the following disclaimer.
|
list of conditions and the following disclaimer.
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
this list of conditions and the following disclaimer in the documentation
|
this list of conditions and the following disclaimer in the documentation
|
||||||
and/or other materials provided with the distribution.
|
and/or other materials provided with the distribution.
|
||||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
* 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
|
endorse or promote products derived from this software without specific
|
||||||
prior written permission.
|
prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
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
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
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,
|
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
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,
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
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
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -65,6 +66,12 @@ public class GraphQLSchemaGenerator {
|
||||||
public enum FHIROperationType {READ, SEARCH, CREATE, UPDATE, DELETE};
|
public enum FHIROperationType {READ, SEARCH, CREATE, UPDATE, DELETE};
|
||||||
|
|
||||||
private static final String INNER_TYPE_NAME = "gql.type.name";
|
private static final String INNER_TYPE_NAME = "gql.type.name";
|
||||||
|
private static final Set<String> JSON_NUMBER_TYPES = new HashSet<String>() {{
|
||||||
|
add("decimal");
|
||||||
|
add("positiveInt");
|
||||||
|
add("unsignedInt");
|
||||||
|
}};
|
||||||
|
|
||||||
IWorkerContext context;
|
IWorkerContext context;
|
||||||
|
|
||||||
public GraphQLSchemaGenerator(IWorkerContext context) {
|
public GraphQLSchemaGenerator(IWorkerContext context) {
|
||||||
|
@ -106,7 +113,7 @@ public class GraphQLSchemaGenerator {
|
||||||
public void generateResource(OutputStream stream, StructureDefinition sd, List<SearchParameter> parameters, EnumSet<FHIROperationType> operations) throws IOException, FHIRException {
|
public void generateResource(OutputStream stream, StructureDefinition sd, List<SearchParameter> parameters, EnumSet<FHIROperationType> operations) throws IOException, FHIRException {
|
||||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
|
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
|
||||||
writer.write("# FHIR GraphQL Schema. Version "+Constants.VERSION+"\r\n\r\n");
|
writer.write("# FHIR GraphQL Schema. Version "+Constants.VERSION+"\r\n\r\n");
|
||||||
writer.write("# import the types from 'types.graphql'\r\n\r\n");
|
writer.write("# import * from 'types.graphql'\r\n\r\n");
|
||||||
generateType(writer, sd);
|
generateType(writer, sd);
|
||||||
if (operations.contains(FHIROperationType.READ))
|
if (operations.contains(FHIROperationType.READ))
|
||||||
generateIdAccess(writer, sd.getName());
|
generateIdAccess(writer, sd.getName());
|
||||||
|
@ -240,6 +247,11 @@ public class GraphQLSchemaGenerator {
|
||||||
writer.write("}\r\n");
|
writer.write("}\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");
|
||||||
|
writer.write("}\r\n");
|
||||||
|
writer.write("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateType(BufferedWriter writer, StructureDefinition sd) throws IOException {
|
private void generateType(BufferedWriter writer, StructureDefinition sd) throws IOException {
|
||||||
|
@ -319,10 +331,15 @@ public class GraphQLSchemaGenerator {
|
||||||
b.append(tail(child.getPath(), suffix));
|
b.append(tail(child.getPath(), suffix));
|
||||||
if (suffix)
|
if (suffix)
|
||||||
b.append(Utilities.capitalize(typeDetails.getWorkingCode()));
|
b.append(Utilities.capitalize(typeDetails.getWorkingCode()));
|
||||||
if (!child.getMax().equals("1"))
|
if (!child.getMax().equals("1")) {
|
||||||
b.append(": [ElementBase]\r\n");
|
b.append(": [ElementBase");
|
||||||
else
|
b.append(suffixS);
|
||||||
b.append(": ElementBase\r\n");
|
b.append("]\r\n");
|
||||||
|
} else {
|
||||||
|
b.append(": ElementBase");
|
||||||
|
b.append(suffixS);
|
||||||
|
b.append("\r\n");
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
b.append("\r\n");
|
b.append("\r\n");
|
||||||
} else {
|
} else {
|
||||||
|
@ -408,11 +425,15 @@ public class GraphQLSchemaGenerator {
|
||||||
|
|
||||||
private void generateSearchParamType(BufferedWriter writer, String name) throws IOException, FHIRException {
|
private void generateSearchParamType(BufferedWriter writer, String name) throws IOException, FHIRException {
|
||||||
String gqlName = getGqlname(name);
|
String gqlName = getGqlname(name);
|
||||||
if (gqlName.equals(name)) {
|
if (gqlName.equals("date")) {
|
||||||
writer.write("Scalar ");
|
writer.write("# Search Param ");
|
||||||
writer.write(name);
|
writer.write(name);
|
||||||
writer.write(" # JSON Format: String");
|
writer.write(": already defined as Primitive with JSON Format: string ");
|
||||||
} else {
|
} else if (gqlName.equals(name)) {
|
||||||
|
writer.write("scalar ");
|
||||||
|
writer.write(name);
|
||||||
|
writer.write(" # JSON Format: string");
|
||||||
|
} else {
|
||||||
writer.write("# Search Param ");
|
writer.write("# Search Param ");
|
||||||
writer.write(name);
|
writer.write(name);
|
||||||
writer.write(": use GraphQL Scalar type ");
|
writer.write(": use GraphQL Scalar type ");
|
||||||
|
@ -426,7 +447,12 @@ public class GraphQLSchemaGenerator {
|
||||||
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");
|
return ed.getType().get(0).getCodeElement().getExtensionString("http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type");
|
||||||
}
|
}
|
||||||
return "??";
|
// all primitives but JSON_NUMBER_TYPES are represented as JSON strings
|
||||||
|
if (JSON_NUMBER_TYPES.contains(sd.getName())) {
|
||||||
|
return "number";
|
||||||
|
} else {
|
||||||
|
return "string";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getGqlname(String name) {
|
private String getGqlname(String name) {
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
package org.hl7.fhir.r5.utils;
|
package org.hl7.fhir.r5.utils;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2011+, HL7, Inc.
|
Copyright (c) 2011+, HL7, Inc.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
list of conditions and the following disclaimer.
|
list of conditions and the following disclaimer.
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
this list of conditions and the following disclaimer in the documentation
|
this list of conditions and the following disclaimer in the documentation
|
||||||
and/or other materials provided with the distribution.
|
and/or other materials provided with the distribution.
|
||||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
* 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
|
endorse or promote products derived from this software without specific
|
||||||
prior written permission.
|
prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
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
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
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,
|
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
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,
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
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
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ import java.io.OutputStreamWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -50,7 +51,6 @@ import java.util.Set;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
import org.hl7.fhir.r5.model.Constants;
|
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||||
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
|
||||||
import org.hl7.fhir.r5.model.Enumerations.SearchParamType;
|
import org.hl7.fhir.r5.model.Enumerations.SearchParamType;
|
||||||
|
@ -65,6 +65,12 @@ public class GraphQLSchemaGenerator {
|
||||||
public enum FHIROperationType {READ, SEARCH, CREATE, UPDATE, DELETE};
|
public enum FHIROperationType {READ, SEARCH, CREATE, UPDATE, DELETE};
|
||||||
|
|
||||||
private static final String INNER_TYPE_NAME = "gql.type.name";
|
private static final String INNER_TYPE_NAME = "gql.type.name";
|
||||||
|
private static final Set<String> JSON_NUMBER_TYPES = new HashSet<String>() {{
|
||||||
|
add("decimal");
|
||||||
|
add("positiveInt");
|
||||||
|
add("unsignedInt");
|
||||||
|
}};
|
||||||
|
|
||||||
IWorkerContext context;
|
IWorkerContext context;
|
||||||
private ProfileUtilities profileUtilities;
|
private ProfileUtilities profileUtilities;
|
||||||
private String version;
|
private String version;
|
||||||
|
@ -110,7 +116,7 @@ public class GraphQLSchemaGenerator {
|
||||||
public void generateResource(OutputStream stream, StructureDefinition sd, List<SearchParameter> parameters, EnumSet<FHIROperationType> operations) throws IOException, FHIRException {
|
public void generateResource(OutputStream stream, StructureDefinition sd, List<SearchParameter> parameters, EnumSet<FHIROperationType> operations) throws IOException, FHIRException {
|
||||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
|
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream));
|
||||||
writer.write("# FHIR GraphQL Schema. Version "+version+"\r\n\r\n");
|
writer.write("# FHIR GraphQL Schema. Version "+version+"\r\n\r\n");
|
||||||
writer.write("# import the types from 'types.graphql'\r\n\r\n");
|
writer.write("# import * from 'types.graphql'\r\n\r\n");
|
||||||
generateType(writer, sd);
|
generateType(writer, sd);
|
||||||
if (operations.contains(FHIROperationType.READ))
|
if (operations.contains(FHIROperationType.READ))
|
||||||
generateIdAccess(writer, sd.getName());
|
generateIdAccess(writer, sd.getName());
|
||||||
|
@ -244,6 +250,11 @@ public class GraphQLSchemaGenerator {
|
||||||
writer.write("}\r\n");
|
writer.write("}\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");
|
||||||
|
writer.write("}\r\n");
|
||||||
|
writer.write("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateType(BufferedWriter writer, StructureDefinition sd) throws IOException {
|
private void generateType(BufferedWriter writer, StructureDefinition sd) throws IOException {
|
||||||
|
@ -323,10 +334,15 @@ public class GraphQLSchemaGenerator {
|
||||||
b.append(tail(child.getPath(), suffix));
|
b.append(tail(child.getPath(), suffix));
|
||||||
if (suffix)
|
if (suffix)
|
||||||
b.append(Utilities.capitalize(typeDetails.getWorkingCode()));
|
b.append(Utilities.capitalize(typeDetails.getWorkingCode()));
|
||||||
if (!child.getMax().equals("1"))
|
if (!child.getMax().equals("1")) {
|
||||||
b.append(": [ElementBase]\r\n");
|
b.append(": [ElementBase");
|
||||||
else
|
b.append(suffixS);
|
||||||
b.append(": ElementBase\r\n");
|
b.append("]\r\n");
|
||||||
|
} else {
|
||||||
|
b.append(": ElementBase");
|
||||||
|
b.append(suffixS);
|
||||||
|
b.append("\r\n");
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
b.append("\r\n");
|
b.append("\r\n");
|
||||||
} else {
|
} else {
|
||||||
|
@ -412,10 +428,14 @@ public class GraphQLSchemaGenerator {
|
||||||
|
|
||||||
private void generateSearchParamType(BufferedWriter writer, String name) throws IOException, FHIRException {
|
private void generateSearchParamType(BufferedWriter writer, String name) throws IOException, FHIRException {
|
||||||
String gqlName = getGqlname(name);
|
String gqlName = getGqlname(name);
|
||||||
if (gqlName.equals(name)) {
|
if (gqlName.equals("date")) {
|
||||||
writer.write("Scalar ");
|
writer.write("# Search Param ");
|
||||||
writer.write(name);
|
writer.write(name);
|
||||||
writer.write(" # JSON Format: String");
|
writer.write(": already defined as Primitive with JSON Format: string ");
|
||||||
|
} else if (gqlName.equals(name)) {
|
||||||
|
writer.write("scalar ");
|
||||||
|
writer.write(name);
|
||||||
|
writer.write(" # JSON Format: string");
|
||||||
} else {
|
} else {
|
||||||
writer.write("# Search Param ");
|
writer.write("# Search Param ");
|
||||||
writer.write(name);
|
writer.write(name);
|
||||||
|
@ -430,7 +450,12 @@ public class GraphQLSchemaGenerator {
|
||||||
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");
|
return ed.getType().get(0).getCodeElement().getExtensionString("http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type");
|
||||||
}
|
}
|
||||||
return "??";
|
// all primitives but JSON_NUMBER_TYPES are represented as JSON strings
|
||||||
|
if (JSON_NUMBER_TYPES.contains(sd.getName())) {
|
||||||
|
return "number";
|
||||||
|
} else {
|
||||||
|
return "string";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getGqlname(String name) {
|
private String getGqlname(String name) {
|
||||||
|
|
Loading…
Reference in New Issue