Add double-check for #610
This commit is contained in:
parent
e9a1069c9d
commit
6a5d0f95ae
|
@ -12,7 +12,7 @@ import java.lang.reflect.Method;
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@ -95,7 +95,7 @@ public class FhirContext {
|
||||||
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
private volatile RuntimeChildUndeclaredExtensionDefinition myRuntimeChildUndeclaredExtensionDefinition;
|
||||||
private IContextValidationSupport<?, ?, ?, ?, ?, ?> myValidationSupport;
|
private IContextValidationSupport<?, ?, ?, ?, ?, ?> myValidationSupport;
|
||||||
private final IFhirVersion myVersion;
|
private final IFhirVersion myVersion;
|
||||||
|
|
||||||
private Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> myVersionToNameToResourceType = Collections.emptyMap();
|
private Map<FhirVersionEnum, Map<String, Class<? extends IBaseResource>>> myVersionToNameToResourceType = Collections.emptyMap();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,7 +106,7 @@ public class FhirContext {
|
||||||
public FhirContext() {
|
public FhirContext() {
|
||||||
this(EMPTY_LIST);
|
this(EMPTY_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated It is recommended that you use one of the static initializer methods instead
|
* @deprecated It is recommended that you use one of the static initializer methods instead
|
||||||
* of this method, e.g. {@link #forDstu2()} or {@link #forDstu3()}
|
* of this method, e.g. {@link #forDstu2()} or {@link #forDstu3()}
|
||||||
|
@ -164,13 +164,14 @@ public class FhirContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theVersion == null) {
|
if (theVersion == null) {
|
||||||
ourLog.info("Creating new FhirContext with auto-detected version [{}]. It is recommended to explicitly select a version for future compatibility by invoking FhirContext.forDstuX()", myVersion.getVersion().name());
|
ourLog.info("Creating new FhirContext with auto-detected version [{}]. It is recommended to explicitly select a version for future compatibility by invoking FhirContext.forDstuX()",
|
||||||
|
myVersion.getVersion().name());
|
||||||
} else {
|
} else {
|
||||||
ourLog.info("Creating new FHIR context for FHIR version [{}]", myVersion.getVersion().name());
|
ourLog.info("Creating new FHIR context for FHIR version [{}]", myVersion.getVersion().name());
|
||||||
}
|
}
|
||||||
|
|
||||||
myResourceTypesToScan = theResourceTypes;
|
myResourceTypesToScan = theResourceTypes;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if we're running in Android mode and configure the context appropriately if so
|
* Check if we're running in Android mode and configure the context appropriately if so
|
||||||
*/
|
*/
|
||||||
|
@ -186,8 +187,7 @@ public class FhirContext {
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
ourLog.trace("Android mode not detected");
|
ourLog.trace("Android mode not detected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createUnknownResourceNameError(String theResourceName, FhirVersionEnum theVersion) {
|
private String createUnknownResourceNameError(String theResourceName, FhirVersionEnum theVersion) {
|
||||||
|
@ -266,7 +266,7 @@ public class FhirContext {
|
||||||
validateInitialized();
|
validateInitialized();
|
||||||
return Collections.unmodifiableCollection(myClassToElementDefinition.values());
|
return Collections.unmodifiableCollection(myClassToElementDefinition.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
* This feature is not yet in its final state and should be considered an internal part of HAPI for now - use with
|
||||||
* caution
|
* caution
|
||||||
|
@ -393,19 +393,19 @@ public class FhirContext {
|
||||||
return myIdToResourceDefinition.get(theId);
|
return myIdToResourceDefinition.get(theId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * Return an unmodifiable collection containing all known resource definitions
|
// * Return an unmodifiable collection containing all known resource definitions
|
||||||
// */
|
// */
|
||||||
// public Collection<RuntimeResourceDefinition> getResourceDefinitions() {
|
// public Collection<RuntimeResourceDefinition> getResourceDefinitions() {
|
||||||
//
|
//
|
||||||
// Set<Class<? extends IBase>> datatypes = Collections.emptySet();
|
// Set<Class<? extends IBase>> datatypes = Collections.emptySet();
|
||||||
// Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> existing = Collections.emptyMap();
|
// Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> existing = Collections.emptyMap();
|
||||||
// HashMap<String, Class<? extends IBaseResource>> types = new HashMap<String, Class<? extends IBaseResource>>();
|
// HashMap<String, Class<? extends IBaseResource>> types = new HashMap<String, Class<? extends IBaseResource>>();
|
||||||
// ModelScanner.scanVersionPropertyFile(datatypes, types, myVersion.getVersion(), existing);
|
// ModelScanner.scanVersionPropertyFile(datatypes, types, myVersion.getVersion(), existing);
|
||||||
// for (int next : types.)
|
// for (int next : types.)
|
||||||
//
|
//
|
||||||
// return Collections.unmodifiableCollection(myIdToResourceDefinition.values());
|
// return Collections.unmodifiableCollection(myIdToResourceDefinition.values());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the scanned runtime models. This is an advanced feature which is generally only needed for extending the
|
* Returns the scanned runtime models. This is an advanced feature which is generally only needed for extending the
|
||||||
|
@ -438,6 +438,7 @@ public class FhirContext {
|
||||||
* Returns the validation support module configured for this context, creating a default
|
* Returns the validation support module configured for this context, creating a default
|
||||||
* implementation if no module has been passed in via the {@link #setValidationSupport(IContextValidationSupport)}
|
* implementation if no module has been passed in via the {@link #setValidationSupport(IContextValidationSupport)}
|
||||||
* method
|
* method
|
||||||
|
*
|
||||||
* @see #setValidationSupport(IContextValidationSupport)
|
* @see #setValidationSupport(IContextValidationSupport)
|
||||||
*/
|
*/
|
||||||
public IContextValidationSupport<?, ?, ?, ?, ?, ?> getValidationSupport() {
|
public IContextValidationSupport<?, ?, ?, ?, ?, ?> getValidationSupport() {
|
||||||
|
@ -474,7 +475,7 @@ public class FhirContext {
|
||||||
/**
|
/**
|
||||||
* Creates a new FluentPath engine which can be used to exvaluate
|
* Creates a new FluentPath engine which can be used to exvaluate
|
||||||
* path expressions over FHIR resources. Note that this engine will use the
|
* path expressions over FHIR resources. Note that this engine will use the
|
||||||
* {@link IContextValidationSupport context validation support} module which is
|
* {@link IContextValidationSupport context validation support} module which is
|
||||||
* configured on the context at the time this method is called.
|
* configured on the context at the time this method is called.
|
||||||
* <p>
|
* <p>
|
||||||
* In other words, call {@link #setValidationSupport(IContextValidationSupport)} before
|
* In other words, call {@link #setValidationSupport(IContextValidationSupport)} before
|
||||||
|
@ -523,12 +524,12 @@ public class FhirContext {
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theClientType
|
* @param theClientType
|
||||||
* The client type, which is an interface type to be instantiated
|
* The client type, which is an interface type to be instantiated
|
||||||
* @param theServerBase
|
* @param theServerBase
|
||||||
* The URL of the base for the restful FHIR server to connect to
|
* The URL of the base for the restful FHIR server to connect to
|
||||||
* @return A newly created client
|
* @return A newly created client
|
||||||
* @throws ConfigurationException
|
* @throws ConfigurationException
|
||||||
* If the interface type is not an interface
|
* If the interface type is not an interface
|
||||||
*/
|
*/
|
||||||
public <T extends IRestfulClient> T newRestfulClient(Class<T> theClientType, String theServerBase) {
|
public <T extends IRestfulClient> T newRestfulClient(Class<T> theClientType, String theServerBase) {
|
||||||
return getRestfulClientFactory().newClient(theClientType, theServerBase);
|
return getRestfulClientFactory().newClient(theClientType, theServerBase);
|
||||||
|
@ -545,7 +546,7 @@ public class FhirContext {
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theServerBase
|
* @param theServerBase
|
||||||
* The URL of the base for the restful FHIR server to connect to
|
* The URL of the base for the restful FHIR server to connect to
|
||||||
*/
|
*/
|
||||||
public IGenericClient newRestfulGenericClient(String theServerBase) {
|
public IGenericClient newRestfulGenericClient(String theServerBase) {
|
||||||
return getRestfulClientFactory().newGenericClient(theServerBase);
|
return getRestfulClientFactory().newGenericClient(theServerBase);
|
||||||
|
@ -597,7 +598,7 @@ public class FhirContext {
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theType
|
* @param theType
|
||||||
* The custom type to add (must not be <code>null</code>)
|
* The custom type to add (must not be <code>null</code>)
|
||||||
*/
|
*/
|
||||||
public void registerCustomType(Class<? extends IBase> theType) {
|
public void registerCustomType(Class<? extends IBase> theType) {
|
||||||
Validate.notNull(theType, "theType must not be null");
|
Validate.notNull(theType, "theType must not be null");
|
||||||
|
@ -617,7 +618,7 @@ public class FhirContext {
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theTypes
|
* @param theTypes
|
||||||
* The custom types to add (must not be <code>null</code> or contain null elements in the collection)
|
* The custom types to add (must not be <code>null</code> or contain null elements in the collection)
|
||||||
*/
|
*/
|
||||||
public void registerCustomTypes(Collection<Class<? extends IBase>> theTypes) {
|
public void registerCustomTypes(Collection<Class<? extends IBase>> theTypes) {
|
||||||
Validate.notNull(theTypes, "theTypes must not be null");
|
Validate.notNull(theTypes, "theTypes must not be null");
|
||||||
|
@ -719,7 +720,7 @@ public class FhirContext {
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theAddProfileTagWhenEncoding
|
* @param theAddProfileTagWhenEncoding
|
||||||
* The add profile mode (must not be <code>null</code>)
|
* The add profile mode (must not be <code>null</code>)
|
||||||
*/
|
*/
|
||||||
public void setAddProfileTagWhenEncoding(AddProfileTagEnum theAddProfileTagWhenEncoding) {
|
public void setAddProfileTagWhenEncoding(AddProfileTagEnum theAddProfileTagWhenEncoding) {
|
||||||
Validate.notNull(theAddProfileTagWhenEncoding, "theAddProfileTagWhenEncoding must not be null");
|
Validate.notNull(theAddProfileTagWhenEncoding, "theAddProfileTagWhenEncoding must not be null");
|
||||||
|
@ -737,10 +738,10 @@ public class FhirContext {
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param theProfile
|
* @param theProfile
|
||||||
* The profile string, e.g. <code>"http://example.com/some_patient_profile"</code>. Must not be
|
* The profile string, e.g. <code>"http://example.com/some_patient_profile"</code>. Must not be
|
||||||
* <code>null</code> or empty.
|
* <code>null</code> or empty.
|
||||||
* @param theClass
|
* @param theClass
|
||||||
* The resource type, or <code>null</code> to clear any existing type
|
* The resource type, or <code>null</code> to clear any existing type
|
||||||
*/
|
*/
|
||||||
public void setDefaultTypeForProfile(String theProfile, Class<? extends IBaseResource> theClass) {
|
public void setDefaultTypeForProfile(String theProfile, Class<? extends IBaseResource> theClass) {
|
||||||
Validate.notBlank(theProfile, "theProfile must not be null or empty");
|
Validate.notBlank(theProfile, "theProfile must not be null or empty");
|
||||||
|
@ -767,7 +768,7 @@ public class FhirContext {
|
||||||
* Sets a parser error handler to use by default on all parsers
|
* Sets a parser error handler to use by default on all parsers
|
||||||
*
|
*
|
||||||
* @param theParserErrorHandler
|
* @param theParserErrorHandler
|
||||||
* The error handler
|
* The error handler
|
||||||
*/
|
*/
|
||||||
public void setParserErrorHandler(IParserErrorHandler theParserErrorHandler) {
|
public void setParserErrorHandler(IParserErrorHandler theParserErrorHandler) {
|
||||||
Validate.notNull(theParserErrorHandler, "theParserErrorHandler must not be null");
|
Validate.notNull(theParserErrorHandler, "theParserErrorHandler must not be null");
|
||||||
|
@ -777,8 +778,9 @@ public class FhirContext {
|
||||||
/**
|
/**
|
||||||
* Sets the parser options object which will be used to supply default
|
* Sets the parser options object which will be used to supply default
|
||||||
* options to newly created parsers
|
* options to newly created parsers
|
||||||
*
|
*
|
||||||
* @param theParserOptions The parser options object - Must not be <code>null</code>
|
* @param theParserOptions
|
||||||
|
* The parser options object - Must not be <code>null</code>
|
||||||
*/
|
*/
|
||||||
public void setParserOptions(ParserOptions theParserOptions) {
|
public void setParserOptions(ParserOptions theParserOptions) {
|
||||||
Validate.notNull(theParserOptions, "theParserOptions must not be null");
|
Validate.notNull(theParserOptions, "theParserOptions must not be null");
|
||||||
|
@ -823,7 +825,7 @@ public class FhirContext {
|
||||||
/**
|
/**
|
||||||
* Sets the validation support module to use for this context. The validation support module
|
* Sets the validation support module to use for this context. The validation support module
|
||||||
* is used to supply underlying infrastructure such as conformance resources (StructureDefinition, ValueSet, etc)
|
* is used to supply underlying infrastructure such as conformance resources (StructureDefinition, ValueSet, etc)
|
||||||
* as well as to provide terminology services to modules such as the validator and FluentPath executor
|
* as well as to provide terminology services to modules such as the validator and FluentPath executor
|
||||||
*/
|
*/
|
||||||
public void setValidationSupport(IContextValidationSupport<?, ?, ?, ?, ?, ?> theValidationSupport) {
|
public void setValidationSupport(IContextValidationSupport<?, ?, ?, ?, ?, ?> theValidationSupport) {
|
||||||
myValidationSupport = theValidationSupport;
|
myValidationSupport = theValidationSupport;
|
||||||
|
@ -841,9 +843,14 @@ public class FhirContext {
|
||||||
return resTypes;
|
return resTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void validateInitialized() {
|
private void validateInitialized() {
|
||||||
|
// See #610
|
||||||
if (!myInitialized) {
|
if (!myInitialized) {
|
||||||
scanResourceTypes(toElementList(myResourceTypesToScan));
|
synchronized (this) {
|
||||||
|
if (!myInitialized) {
|
||||||
|
scanResourceTypes(toElementList(myResourceTypesToScan));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class FhirContextDstu3Test {
|
||||||
public void testInitialisationThreadSafety() {
|
public void testInitialisationThreadSafety() {
|
||||||
final FhirContext ctx = FhirContext.forDstu3();
|
final FhirContext ctx = FhirContext.forDstu3();
|
||||||
|
|
||||||
final int numThreads = 4;
|
final int numThreads = 40;
|
||||||
final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>());
|
final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>());
|
||||||
final ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
|
final ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
|
||||||
try {
|
try {
|
||||||
|
@ -105,7 +105,9 @@ public class FhirContextDstu3Test {
|
||||||
threadsReady.countDown();
|
threadsReady.countDown();
|
||||||
try {
|
try {
|
||||||
threadsReady.await();
|
threadsReady.await();
|
||||||
ctx.getResourceDefinition("patient");
|
RuntimeResourceDefinition def = ctx.getResourceDefinition("patient");
|
||||||
|
ourLog.info(def.toString());
|
||||||
|
assertNotNull(def);
|
||||||
} catch(final Exception e) {
|
} catch(final Exception e) {
|
||||||
exceptions.add(e);
|
exceptions.add(e);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue