Skip to content

Custom registry metadata validator

bill edited this page Oct 17, 2018 · 4 revisions

Writing a custom Metadata validator for the Registry simulator

The Registry simulator can be configured with a custom metadata validator that is run on each Register transaction received by the simulator. The validator is written in Groovy, installed in the External Cache, and is registered in the configuration of the simulator.

A simple example of a validator is:

import gov.nist.toolkit.testengine.engine.validations.registry.AbstractServerValidater
import org.apache.axiom.om.*
import gov.nist.toolkit.registrymetadata.Metadata
import gov.nist.toolkit.errorrecording.ErrorRecorder

class FooFoo extends AbstractServerValidater {

   FooFoo(ErrorRecorder er) {
      super(er)
   }

   /*
    * metadata is the container holding all the metadata objects in the submission
    * er is the error log you should report to if an error is detected.
    *
    */
   @Override
   void run(Metadata metadata, ErrorRecorder er) {
      // every Register is declared to have an invalid code
	  er.err('No Code', 'Invalid code', null, null, null)
   }
}

The validator is a class that extends AbstractServerValidater. The class shown is FooFoo and it must be put in a file named FooFoo.groovy. The first method is the constructor which must be coded as shown with only the class named changed. The run method is where you put your validation logic. Errors are reported through the er.err() method.

Error reporting

The er.err() error reporting call has some built in flexibility. There are two variations on the call:

	void err(XdsErrorCode.Code code, String msg, String location, String severity, String resource)

or

	void err(String code, String msg, String location, String severity, String resource)

Where:

XdsErrorCode.Code code is one of a collection of predefined codes listed below.

String msg is an informative message.

String location indicates where in the message the problem occurred.

String severity is either "WARNING" or "ERROR" for basic error reporting. This parameter can take on other values which produce other kinds of output. More on that below.

String resource should be null.

The predefined codes are

XdsErrorCode.Code.NoCode
XdsErrorCode.Code.XDSMissingDocument
XdsErrorCode.Code.XDSMissingDocumentMetadata
XdsErrorCode.Code.XDSRegistryNotAvailable
XdsErrorCode.Code.XDSRegistryError
XdsErrorCode.Code.XDSRepositoryError
XdsErrorCode.Code.XDSRegistryDuplicateUniqueIdInMessage
XdsErrorCode.Code.XDSRepositoryDuplicateUniqueIdInMessage
XdsErrorCode.Code.XDSDuplicateUniqueIdInRegistry
XdsErrorCode.Code.XDSNonIdenticalHash
XdsErrorCode.Code.XDSRegistryBusy
XdsErrorCode.Code.XDSRepositoryBusy
XdsErrorCode.Code.XDSRegistryOutOfResources
XdsErrorCode.Code.XDSRepositoryOutOfResources
XdsErrorCode.Code.XDSRegistryMetadataError
XdsErrorCode.Code.XDSRepositoryMetadataError
XdsErrorCode.Code.XDSTooManyResults
XdsErrorCode.Code.XDSExtraMetadataNotSaved
XdsErrorCode.Code.XDSUnknownPatientId
XdsErrorCode.Code.XDSPatientIdDoesNotMatch
XdsErrorCode.Code.XDSUnknownStoredQuery
XdsErrorCode.Code.XDSStoredQueryMissingParam
XdsErrorCode.Code.XDSStoredQueryParamNumber
XdsErrorCode.Code.XDSRegistryDeprecatedDocumentError
XdsErrorCode.Code.XDSUnknownRepositoryId
XdsErrorCode.Code.XDSDocumentUniqueIdError
XdsErrorCode.Code.XDSPartialSuccess
XdsErrorCode.Code.XDSMetadataVersionError
XdsErrorCode.Code.XDSMetadataUpdateOperationError
XdsErrorCode.Code.XDSMetadataUpdateError
XdsErrorCode.Code.XDSMissingHomeCommunityId
XdsErrorCode.Code.XDSUnknownCommunity
XdsErrorCode.Code.XDSResultNotSinglePatient
XdsErrorCode.Code.XDSIRequestError
XdsErrorCode.Code.XDSIUnknownIdsUid
XdsErrorCode.Code.ReferencesExistException
XdsErrorCode.Code.XDSUnreferencedObjectException
XdsErrorCode.Code.UnresolvedReferenceException

Reporting information that are not errors

Here are some calls that can be used to report other types of information back to the user.

sectionHeading(String msg)

Top level section heading that will appear in the log.

challenge(String msg)

externalChallenge(String msg)

Challenge and ExternalChallenge produce top level headings in the log.

detail(String msg)

Adds a detail message to the log.

report(String name, String found)

This produces a line

    name: found

in the log output.

Where does logging information go

Errors and warnings are reported in the RegistryResponse message returned from the Register transaction and in the simulator log.

All logging information described above goes into the log associated with the simulator and can be viewed through the New Simulator Logs tab - look in the [Log] inner tab.

Using the Metadata class

The Metadata class is the internal container for a metadata-based message like Register. It is built around the Axiom XML parser and the Axiom internal datatypes are used in calls and responses.

Here are some example calls:

Contains 2 DocumentEntries

    if (metadata.extrinsicObjects.size() != 2)
	    er.err(...)

Contains 1 Folder

    if (metadata.folders.size() != 1)
	    er.err(...)

DocumentEntry has confidentialityCode of Very Restricted

    @Override
    void run(Metadata metadata, ErrorRecorder er) {
        OMElement docEntry = metadata.extrinsicObjects[0]
        Iterator<OMElement> it = docEntry.getChildrenWithLocalName('Classification')
        boolean foundIt = false
        while (it.hasNext() && foundIt == false) {
            OMElement clas = (OMElement) it.next()
            if (clas.getAttributeValue(new QName('classificationScheme')) == 'urn:uuid:f4f85eac-e6cb-4883-b524-f2705394840f' &&
                    clas.getAttributeValue(new QName('nodeRepresentation')) == 'V')
                foundIt = true
        }
        if (!foundIt)
            er.err('No Code', 'Unacceptable Confidentiality code', null, null, null)
    }

Installing a validator

Validators are stored in the environment area of the External Cache. They are defined within an Environment and a TestSession. The directory holding validators on my system for the default Environment and the default TestKit is

    /home/bill/ExternalCache/environment/default/testkits/default/plugins/RegistryValidator

where

/home/bill/ExternalCache is the ExternalCache

environment holds all information for environments

default is the default environment

testkits is the collection of testkits defined for this environment

default is the TestKit for the default TestSession of the default environment

plugins is the plugins container

RegistryValidator holds the groovy code for all Registry validators

The above validator would be in this directory in a file FooFoo.groovy.

Most of this directory structure can be created automatically using the Create Testkit Structure function located in Toolkit Configuration.

These directories and files must be readable by the account in which Tomcat runs (the Tomcat that hosts Toolkit).

Installing a validator in a Registry simulator

Open the Simulators tool and edit the configuration (select simulator and click on the pencil icon below).

Fill in the Register Metadata Validator Class Name parameter with the class name of your validator. For the above example the name is FooFoo.

Save the configuration.

It will run when the next Register transaction is received.

Error reporting and issues with a validator

If a validator fails because of invalid code (bad variable name for example) here are some possible messages that will be returned and what they mean. These messages will appear in the RegistryResponse message.

Validation Fails - message did not meet the criteria

Error Code: message

Validator does not extend AbstractServerValidater

SOAP Fault: startup failed: /Users/bill/tmp/toolkit2a/environment/default/testkits/default/plugins/RegistryValidator/ConfCode.groovy: 18: Method 'run' from class 'ConfCode' does not override method from its superclass or interfaces but is annotated with @Override. @ line 18, column 5.

In this message the validator in question is ConfCode.groovy.

Code does not compile

SOAP Fault: startup failed: /Users/bill/tmp/toolkit2a/environment/default/testkits/default/plugins/RegistryValidator/ConfCode.groovy: 21: unexpected token: Iterator @ line 21, column 9. Iterator it = docEntry.getChildrenWithLocalName('Classification')

Unknown validator

SOAP Fault: Unknown validater ConfCode1 in default/default [/Users/bill/tmp/toolkit2a/environment/default/testkits/default/plugins/RegistryValidator, /Users/bill/Library/Caches/IntelliJIdea2018.1/gwt/develop.47685b4e/xdstools2.cf8becc6/run/www/toolkitx/testkit/plugins/RegistryValidator]

default/default shows the Environment/TestSession

The list is the search path through the available TestKits.

Clone this wiki locally