From f4f57fd480b489637f63559ad82d0b76390bb2e5 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Sun, 4 Oct 2015 21:05:30 +0200 Subject: [PATCH] Make dependencies truly optionel + clean up / minimize android build both Phloc and Schematron was not truly optionel since they was referred from different files. So the references has been moved to a factory and ObjectUtil extended for some of the missing methods, where Schematron was used. Android pom file is cleaned so that all artifcates are build using the same base configuration and then schematron, phloc and some server components have been removed from artifact to minimize android artifacts. --- hapi-fhir-android/pom.xml | 227 ++++++++---------- .../java/ca/uhn/fhir/util/ObjectUtil.java | 14 ++ .../validation/BaseValidationContext.java | 5 +- .../ca/uhn/fhir/validation/FhirValidator.java | 23 +- .../fhir/validation/SchemaBaseValidator.java | 6 +- .../fhir/validation/ValidationContext.java | 9 +- .../schematron/SchematronProvider.java | 42 ++++ 7 files changed, 174 insertions(+), 152 deletions(-) create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/schematron/SchematronProvider.java diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml index adadb8915db..cb0c021d677 100644 --- a/hapi-fhir-android/pom.xml +++ b/hapi-fhir-android/pom.xml @@ -56,6 +56,12 @@ org.slf4j slf4j-android + + net.sourceforge.cobertura + cobertura + 2.1.1 + true + org.slf4j slf4j-api @@ -77,7 +83,7 @@ + + + + + javax.xml.stream + ca.uhn.fhir.repackage.javax.xml.stream + + + javax.json + ca.uhn.fhir.repackage.javax.json + + + + + + net.sourceforge.cobertura:cobertura + + net/sourceforge/cobertura/CoverageIgnore* + + + + + ca.uhn.hapi.fhir:hapi-fhir-base + + + ca/uhn/fhir/util/ITestingUiClientFactory + + ca/uhn/fhir/rest/server/Add* + ca/uhn/fhir/rest/server/Apache* + ca/uhn/fhir/rest/server/Bundle* + ca/uhn/fhir/rest/server/ETag* + ca/uhn/fhir/rest/server/Fifo* + ca/uhn/fhir/rest/server/Hard* + ca/uhn/fhir/rest/server/IBundle* + ca/uhn/fhir/rest/server/IDynamic* + ca/uhn/fhir/rest/server/Incoming* + ca/uhn/fhir/rest/server/IPaging* + ca/uhn/fhir/rest/server/IServerAdd* + ca/uhn/fhir/rest/server/Resource* + ca/uhn/fhir/rest/server/Rest* + ca/uhn/fhir/rest/server/Search* + ca/uhn/fhir/rest/server/Simple* + ca/uhn/fhir/rest/server/audit/** + ca/uhn/fhir/rest/server/interceptor/** + + ca/uhn/fhir/validation/schematron/SchematronBaseValidator* + + ca/uhn/fhir/narrative/*Thymeleaf* + + + + + - normal - package - - shade - - - true - true - true - - - ca.uhn.hapi.fhir:hapi-fhir-base - org.glassfish:javax.json - org.codehaus.woodstox:woodstox-core-asl - javax.xml.stream:stax-api - org.codehaus.woodstox:stax2-api - org.glassfish:javax.json - - - - - javax.xml.stream - ca.uhn.fhir.repackage.javax.xml.stream - - - javax.json - ca.uhn.fhir.repackage.javax.json - - - - - ca.uhn.hapi.fhir:hapi-fhir-base - - ca/uhn/fhir/util/ITestingUiClientFactory - ca/uhn/fhir/rest/server/** - **/*.java - - - ca/uhn/fhir/rest/server/exceptions/** - - - - - + shaded + package + + shade + + + dstu - package - - shade - + package + + shade + - true - true - true dstu - - ca.uhn.hapi.fhir:hapi-fhir-base ca.uhn.hapi.fhir:hapi-fhir-structures-dstu - org.glassfish:javax.json - org.codehaus.woodstox:woodstox-core-asl - javax.xml.stream:stax-api - - org.codehaus.woodstox:stax2-api - - - org.glassfish:javax.json - - - javax.xml.stream - ca.uhn.fhir.repackage.javax.xml.stream - - - javax.json - ca.uhn.fhir.repackage.javax.json - - - - ca.uhn.hapi.fhir:hapi-fhir-base - - ca/uhn/fhir/util/ITestingUiClientFactory - ca/uhn/fhir/rest/server/** - **/*.java - - - ca/uhn/fhir/rest/server/exceptions/** - - + ca.uhn.hapi.fhir:hapi-fhir-structures-dstu @@ -233,58 +236,22 @@ + dstu2 - package - - shade - + package + + shade + - true - true - true dstu2 - - ca.uhn.hapi.fhir:hapi-fhir-base ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2 - org.glassfish:javax.json - org.codehaus.woodstox:woodstox-core-asl - javax.xml.stream:stax-api - - org.codehaus.woodstox:stax2-api - - org.glassfish:javax.json - - - javax.xml.stream - ca.uhn.fhir.repackage.javax.xml.stream - - - javax.json - ca.uhn.fhir.repackage.javax.json - - - - ca.uhn.hapi.fhir:hapi-fhir-base - - ca/uhn/fhir/util/ITestingUiClientFactory - ca/uhn/fhir/rest/server/** - **/*.java - - - ca/uhn/fhir/rest/server/exceptions/** - - + ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2 diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ObjectUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ObjectUtil.java index 70413d258c3..b1b6bcd678b 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ObjectUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ObjectUtil.java @@ -1,5 +1,7 @@ package ca.uhn.fhir.util; +import org.apache.commons.lang3.StringUtils; + /* * #%L * HAPI FHIR - Core Library @@ -32,4 +34,16 @@ public class ObjectUtil { return object1.equals(object2); } + public static T requireNonNull(T obj, String message) { + if (obj == null) + throw new NullPointerException(message); + return obj; + } + + public static void requireNotEmpty(String str, String message) { + if (StringUtils.isBlank(str)) { + throw new IllegalArgumentException(message); + } + } + } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/BaseValidationContext.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/BaseValidationContext.java index cb0e7aabaae..9cf24acd05c 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/BaseValidationContext.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/BaseValidationContext.java @@ -23,9 +23,8 @@ package ca.uhn.fhir.validation; import java.util.ArrayList; import java.util.List; -import org.thymeleaf.util.Validate; - import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.util.ObjectUtil; abstract class BaseValidationContext implements IValidationContext { @@ -38,7 +37,7 @@ abstract class BaseValidationContext implements IValidationContext { @Override public void addValidationMessage(SingleValidationMessage theMessage) { - Validate.notNull(theMessage, "theMessage must not be null"); + ObjectUtil.requireNonNull(theMessage, "theMessage must not be null"); myMessages.add(theMessage); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/FhirValidator.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/FhirValidator.java index 1d03cf0d89a..a91e40e51db 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/FhirValidator.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/FhirValidator.java @@ -32,6 +32,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.util.OperationOutcomeUtil; +import ca.uhn.fhir.validation.schematron.SchematronProvider; /** * Resource validator, which checks resources for compliance against various validation schemes (schemas, schematrons, profiles, etc.) @@ -49,9 +50,6 @@ public class FhirValidator { private static final String I18N_KEY_NO_PHLOC_ERROR = FhirValidator.class.getName() + ".noPhlocError"; - private static final String I18N_KEY_NO_PHLOC_WARNING = FhirValidator.class.getName() + ".noPhlocWarningOnStartup"; - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirValidator.class); - private static volatile Boolean ourPhlocPresentOnClasspath; private final FhirContext myContext; private List myValidators = new ArrayList(); @@ -63,13 +61,7 @@ public class FhirValidator { myContext = theFhirContext; if (ourPhlocPresentOnClasspath == null) { - try { - Class.forName("com.phloc.schematron.ISchematronResource"); - ourPhlocPresentOnClasspath = true; - } catch (ClassNotFoundException e) { - ourLog.info(theFhirContext.getLocalizer().getMessage(I18N_KEY_NO_PHLOC_WARNING)); - ourPhlocPresentOnClasspath = false; - } + ourPhlocPresentOnClasspath = SchematronProvider.isScematronAvailable(theFhirContext); } } @@ -110,7 +102,12 @@ public class FhirValidator { * Should the validator validate the resource against the base schema (the schema provided with the FHIR distribution itself) */ public synchronized boolean isValidateAgainstStandardSchematron() { - return haveValidatorOfType(SchematronBaseValidator.class); + if (!ourPhlocPresentOnClasspath) { + return false; // No need to ask since we dont have Phloc. Also Class.forname will complain + // about missing phloc import. + } + Class cls = SchematronProvider.getSchematronValidatorClass(); + return haveValidatorOfType(cls); } /** @@ -147,7 +144,9 @@ public class FhirValidator { if (theValidateAgainstStandardSchematron && !ourPhlocPresentOnClasspath) { throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_KEY_NO_PHLOC_ERROR)); } - addOrRemoveValidator(theValidateAgainstStandardSchematron, SchematronBaseValidator.class, new SchematronBaseValidator(myContext)); + Class cls = SchematronProvider.getSchematronValidatorClass(); + IValidatorModule instance = SchematronProvider.getSchematronValidatorInstance(myContext); + addOrRemoveValidator(theValidateAgainstStandardSchematron, cls, instance); return this; } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java index 57d6fa7f34c..cebd80a4693 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SchemaBaseValidator.java @@ -53,7 +53,9 @@ import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; -class SchemaBaseValidator implements IValidatorModule { +public class SchemaBaseValidator implements IValidatorModule { + public static final String RESOURCES_JAR_NOTE = "Note that as of HAPI FHIR 1.2, DSTU2 validation files are kept in a separate JAR (hapi-fhir-validation-resources-XXX.jar) which must be added to your classpath. See the HAPI FHIR download page for more information."; + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SchemaBaseValidator.class); private static final Set SCHEMA_NAMES; @@ -129,7 +131,7 @@ class SchemaBaseValidator implements IValidatorModule { ourLog.debug("Going to load resource: {}", pathToBase); InputStream baseIs = FhirValidator.class.getResourceAsStream(pathToBase); if (baseIs == null) { - throw new InternalErrorException("Schema not found. " + SchematronBaseValidator.RESOURCES_JAR_NOTE); + throw new InternalErrorException("Schema not found. " + RESOURCES_JAR_NOTE); } baseIs = new BOMInputStream(baseIs, false); InputStreamReader baseReader = new InputStreamReader(baseIs, Charset.forName("UTF-8")); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationContext.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationContext.java index a7cdb87a951..843f676b553 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationContext.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationContext.java @@ -21,7 +21,6 @@ package ca.uhn.fhir.validation; */ import org.hl7.fhir.instance.model.api.IBaseResource; -import org.thymeleaf.util.Validate; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.Bundle; @@ -29,8 +28,9 @@ import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.rest.method.MethodUtil; import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import ca.uhn.fhir.util.ObjectUtil; -class ValidationContext extends BaseValidationContext implements IValidationContext { +public class ValidationContext extends BaseValidationContext implements IValidationContext { private final IEncoder myEncoder; private final T myResource; @@ -136,8 +136,8 @@ class ValidationContext extends BaseValidationContext implements IValidati } public static IValidationContext forText(final FhirContext theContext, final String theResourceBody) { - Validate.notNull(theContext, "theContext can not be null"); - Validate.notEmpty(theResourceBody, "theResourceBody can not be null or empty"); + ObjectUtil.requireNonNull(theContext, "theContext can not be null"); + ObjectUtil.requireNotEmpty(theResourceBody, "theResourceBody can not be null or empty"); return new BaseValidationContext(theContext) { private EncodingEnum myEncoding; @@ -169,5 +169,4 @@ class ValidationContext extends BaseValidationContext implements IValidati }; } - } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/schematron/SchematronProvider.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/schematron/SchematronProvider.java new file mode 100644 index 00000000000..a48abde04b1 --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/schematron/SchematronProvider.java @@ -0,0 +1,42 @@ +package ca.uhn.fhir.validation.schematron; + +import java.lang.reflect.Constructor; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.validation.FhirValidator; +import ca.uhn.fhir.validation.IValidatorModule; + +public class SchematronProvider { + + + private static final String I18N_KEY_NO_PHLOC_WARNING = FhirValidator.class.getName() + ".noPhlocWarningOnStartup"; + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirValidator.class); + + public static boolean isScematronAvailable(FhirContext theFhirContext) { + try { + Class.forName("com.phloc.schematron.ISchematronResource"); + return true; + } catch (ClassNotFoundException e) { + ourLog.info(theFhirContext.getLocalizer().getMessage(I18N_KEY_NO_PHLOC_WARNING)); + return false; + } + } + + public static Class getSchematronValidatorClass() { + try { + return (Class) Class.forName("ca.uhn.fhir.validation.schematron.SchematronBaseValidator"); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Cannot resolve schematron validator ", e); + } + } + + public static IValidatorModule getSchematronValidatorInstance(FhirContext myContext) { + try { + Class cls = getSchematronValidatorClass(); + Constructor constructor = cls.getConstructor(FhirContext.class); + return constructor.newInstance(myContext); + } catch (ReflectiveOperationException e) { + throw new IllegalStateException("Cannot construct schematron validator ", e); + } + } +}