Tjek relevant overordnede dele er til stede i input (så validatorer ikke behøver blive negative, hvis de ikke er)Indhold:
På NSP deles i dag CDA dokumenter vha. en XDS infrastruktur. CDA dokumenter er et struktureret XML dokument, som følger en bestemt standard for kliniske dokumenter. Der findes forskellige typer af CDA dokumenter. Medcom har lavet de danske profileringer (Udgivelser), som dækker typerne:
Fælles for alle dokumenterne er en fælles CDA header, der indeholder metadata om dokumentet. Denne skal overholde Medcoms standard (XDS Metadata for Document Sharing. Danish profile). Ligesom data i headeren skal findes i Medcoms fælles liste over tilladet værdisæt (DK-IHE_Metadata-Common_Code_systems-Value_sets).
Dokumenter, som gemmes i XDS infrasktrukturen, registreres under deres metadata, og kan fremsøges ud fra disse igen. Det registerede metadata er underlagt samme standarder som CDA dokumenterne selv er, dvs. de skal overholde Medcoms standarder. For at gemme eller hente et dokument, anvendet et ITI kald. ITI kald er standardiserede SOAP services, der overholder IHE XDS specifikationen.
Et ITI kald opererer med begreberne SubmissionSet, DocumentEntry og Association, hvis indhold lægger sig op af dokumentets metadata. Disse skal derfor også overholde standarderne.
For yderligere detaljer og introduktion til dokumentdeling læs Dokumentdeling på NSP.
For at lette arbejdet med at overholde/validerere for standarderne, findes XdsValidation biblioteket. DROS komponenten gør brug af denne validering, for at sikre, at der ikke komme ugyldige data ind i XDS infrastrukturen. Anvendere af DROS kan selv implementere validering vha. af XdsValidation biblioteket, hvis man ønsker at finde "fejl" inden det faktisk kald udføres.
XdsValiderings biblioteket er under fortsat udvikling. Se afsnittet "Understøttede valideringsregler" for den nuværende implementering.
For at anvende XdsValidation biblioteket, skal man gøre brug af tredjepartsproduktet IPF Open eHealth Integration Platform, da interaktionen foregår vha. dette.
Da DROS som nævnt gør brug af XdsValidation, kan man her finde yderligere inspiration for implementering, hvis man som ekstern anvender ønsker at gøre brug af XDS validering. Dette dokument beskriver overordnet tilgængelighed af modulet samt anvendelse.
XdsValidation biblioteket kan overordnet validere følgende:
Biblioteket består af en række valideringsregler/klasser, som kan sættes sammen efter behov. Det er muligt at sætte en validering sammen, som en lang kæde, eller lave en træstruktur, sådan at visse valideringer, stopper for yderligere validering i specifikt område. Sidstnævnte kan f.eks. være, at hvis et dokument ikke er en kendt CDA type, så behøver man ikke validerere yderligere på dets metadata.
Figur: kæde- eller træstruktur
For at lette arbejdet med bibliotekt, findes der en default opsætning per område, som det anbefales at arbejde med (såkaldt factories). Se figuren "Validator overblik" i design og arkitekturdokumentet, for en overblik over disse. Hvordan disse factories anvendes er beskrevet i næste afsnit.
Hver valideringsregel er implementeret som en ud af fire typer (Navngivning samt hvilken klasse den extender, illustrerer dette dette). Disse er beskrevet i det efterfølgende.
En valideringsregel returnerer enten null (hvis den ikke forstår det input den modtager) eller et object ValidationResultSet. ValidationResultSet kan indholde en række fejl, hvis sådanne er fundet under valideringen.
En almindelig validering. Den består af en validering, samt mulighed for at angive "under-validatorerer" samt indikation af om disse "under-validatorer" skal køres, hvis dens egen validering fejler.
Man kan altså med denne validator gruppere en række valideringer, som man ønskes udført efter hinanden, baseret på validatorens eget udfald. Den almindelige validatorer returner så den fulde mængde af resultater/fejl fundet.
Et eksempel på sådan en validering er Apd2StartStopTimeValidator. Den tjekker på om ServiceStartTime på et aftaledokument er udfyldt, Den har ikke nogen "under-validatorer" i default opsætningen for ITI41 kaldet. Men på sigt kunne disse tilføjes, hvis der opstår behov for specifikke regler omkring StartTime valideringen, når den er udfyldt. Se følgende eksempel:
//nuværende eksempel på almindelig felt validering: Apd2StartStopTimeValidator apd2StartStopTimeValidator = new Apd2StartStopTimeValidator(); //fremtidigt eksempel med yderligere validering: Apd2StartStopTimeValidator apd2StartStopTimeValidator = new Apd2StartStopTimeValidator(false); Apd2StartStopTimeSpecifikValueValidator apd2StartStopTimeSpecifikValueValidator = new Apd2StartStopTimeSpecifikValueValidator(); apd2StartStopTimeValidator.appendValidator(apd2StartStopTimeSpecifikValueValidator); |
Det som kendetegner en almindelig validator er extension af klassen AbstractValidatorImpl.
Denne validator har lidt mere logik end en almindelig validator: Den kræver at mindst een af dens under-validatorer vil kendes ved det input den får, for at AtLeastOneValidatoren selv validerer noget ok.
Man kan altså med denne validator gruppere en række valideringer, og forvente at mindst een af dem vil kendes ved det input den får. Den/de "under-validering" som kendes ved input forventes så at udføre relevant validering.
Et eksempel på sådan en validering er CdaDocumentTypeValidator. Den er default konfigureret med en række "under-validatorer" der hver især kan håndtere en dokument type. Aktiveres CdaDocumentTypeValidator på et dokument, vil den "under-validator" der kendes ved dokumenttypen sørge for at validere specifikke regler for denne type. Kendes ingen af "under-validatorne" ved dokumentindholdet/typen, vil AtLeastOneValidatoren melde en fejl retur. Se følgende eksempel:
//validering hvor CdaDocumentTypeValidator forventer at ens af dens under-validatorer vil kendes ved input (dokumentet) CdaDocumentTypeValidator cdaDocumentTypeValidator = new CdaDocumentTypeValidator(); CdaDocumentApdV2ModelEnricher cdaDocumentApdV2ModelEnricher = new CdaDocumentApdV2ModelEnricher(); cdaDocumentTypeValidator.appendValidator(cdaDocumentApdV2ModelEnricher); CdaDocumentPhmrModelEnricher cdaDocumentPhmrModelEnricher = new CdaDocumentPhmrModelEnricher(); cdaDocumentTypeValidator.appendValidator(cdaDocumentPhmrModelEnricher); CdaDocumentQrdModelEnricher cdaDocumentQrdModelEnricher = new CdaDocumentQrdModelEnricher(); cdaDocumentTypeValidator.appendValidator(cdaDocumentQrdModelEnricher); |
Det som kendetegner en almindelig validator er extension af klassen AbstractAtLeastOneValidatorImpl.
Dette er ikke en egentlig validator. "Valideringen" består af udpakning af noget input.
Så en indirekte validering af, at input forståes og forbedring/berigelse af det data, der arbejdes på. Denne "berigelse" sættes på det indkomne objekt (deraf ModelEnricher) og senere validatorer kan så arbejde herpå.
Man kan på denne ModelEnricher også sættes "under-validatorer" på ligesom en almindelig validator.
Et eksempel på sådan en ModelEnricher er CdaDocumentApdV2ModelEnricher. Den er default konfigureret på CdaDocumentTypeValidator (se ovenfor for en AtLeastOneValidator) og modtager et CDA dokument, som den forsøger at pakke ud til et aftaledokument. Lykkedes dette kalder den sine "under-validatorer" som validerer aftale specikke regler.
//validering, hvor CdaDocumentApdV2ModelEnricher forventes at pakke input ud og forstå at det er et aftale dokument. CdaDocumentApdV2ModelEnricher cdaDocumentApdV2ModelEnricher = new CdaDocumentApdV2ModelEnricher(); Apd2StartStopTimeValidator apd2StartStopTimeValidator = new Apd2StartStopTimeValidator(); cdaDocumentApdV2ModelEnricher.appendValidator(apd2StartStopTimeValidator); Apd2AppointmentIdValidator apd2AppointmentIdValidator = new Apd2AppointmentIdValidator(); cdaDocumentApdV2ModelEnricher.appendValidator(apd2AppointmentIdValidator); Apd2CustodianIdValidator apd2CustodianIdValidator = new Apd2CustodianIdValidator(organisationCodeValidation); cdaDocumentApdV2ModelEnricher.appendValidator(apd2CustodianIdValidator); |
Det som kendetegner en almindelig validator er extension af klassen AbstractModelEnricherImpl.
Denne minder om en ModelEnricher, men adskiller sig ved, at den ikke modtager det fælles objekt XDSDocument som de andre validatorer arbejder med. Den modtager derimod en request type, som pakkes ud i et eller flere XDSDocument objekter, og Starter kører så sine under-validatorer på hver af disse objekter.
Alle valideringer starter derfor med en Starter validering og al anden validering bygges herpå. Se eksempelvis ProvideAndRegisterDocumentSetStarter for et fuldt eksempel.
//validering, hvor det hele initiers med en Starter validering til et iti 41 kald ProvideAndRegisterDocumentSetStarter provideAndRegisterDocumentSetStarter = new ProvideAndRegisterDocumentSetStarter(); |
Det som kendetegner en almindelig validator er extension af klassen AbstractStarterImpl.
Principperne for oprettelse af validerings regler og sammensætning i struktur er:
Alle ITI kalds default valideringer, som er konfigureret i XdsValidation biblioteket er sat op efter følgende struktur:
Hver ITI kald har sin kombination, da ikke alle elementer er til stede i de forskellige kald. F.eks, har et ITI 41 det eneste kald, som har et faktisk dokument, der kan valideres.
En grafisk præsentation af denne konfiguration af default validering kan ses i Design og arkitektur dokumentet.
For at gøre brug af xdsValidation skal følgende dependencies tilføjes til maven pom fil:
<dependency> <groupId>dk.nsp</groupId> <artifactId>validation-xds</artifactId> </dependency> |
Hvis man ikke allerede anvender IPF Open eHealth Integration Platform skal følgende dependency tilføjes
<dependency> <groupId>org.openehealth.ipf.commons</groupId> <artifactId>ipf-commons-ihe-xds</artifactId> <version>${openehealth.version}</version> </dependency> <!-- openehealth.version bør være samme version som XDSValidation anvender --> |
Følgende kode er taget fra DROS's validerings logik for ITI 41 kald.
// Fra klassen Iti41ValidationImpl metode validateAndTransform List<ErrorInfo> xdsValidationErrors = getXdsValidationErrors(provideAndRegisterDocumentSet, xdsValidatorFactory.buildIti41Validator(), xdsValidationLevel); // Fra klassen RegistryItiValidationImpl protected List<ErrorInfo> getXdsValidationErrors(ProvideAndRegisterDocumentSet request, ProvideAndRegisterDocumentSetStarter starter, XdsValidationLevel xdsValidationLevel) { return getXdsValidationErrors(() -> starter.validate(request), xdsValidationLevel); } private List<ErrorInfo> getXdsValidationErrors(Supplier<ValidationResultSet> validator, XdsValidationLevel xdsValidationLevel) { if(xdsValidationLevel == XdsValidationLevel.OFF) { return new ArrayList<>(); } List<ErrorInfo> errors = new ArrayList<>(); // Perform the validation ValidationResultSet resultSet = validator.get(); // Construct the result if(resultSet.hasErrors()) { // Based on the validation level, either return a warning or an error. Severity severity = getSeverity(xdsValidationLevel); for(ValidationError ve : resultSet.getErrors()) { ErrorInfo errorInfo = new ErrorInfo(ErrorCode.REGISTRY_METADATA_ERROR, ve.getErrorMessage(), severity, "", ""); errors.add(errorInfo); } } return errors; } |
Dvs ønsker man benytte default valideringen for ITI 41 kaldet gøres det ved at:
På samme måde kan man få valideret de øvrige kald, ved at vælge den rette Starter og sende requsted ind til den.
// Fra klassen Iti42ValidationImpl metode validateAndTransform List<ErrorInfo> xdsValidationErrors = getXdsValidationErrors(registerDocumentSet, xdsValidatorFactory.buildIti42Validator(), xdsValidationLevel); // Fra klassen RegistryItiValidationImpl protected List<ErrorInfo> getXdsValidationErrors(RegisterDocumentSet request, RegisterDocumentSetStarter starter, XdsValidationLevel xdsValidationLevel) { return getXdsValidationErrors(() -> starter.validate(request), xdsValidationLevel); //for getXdsValidationErrors se ovenfor } |
// Fra klassen Iti57ValidationImpl metode validateAndTransform List<ErrorInfo> xdsValidationErrors = getXdsValidationErrors(registerDocumentSet, xdsValidatorFactory.buildIti61Validator(), xdsValidationLevel); // Fra klassen RegistryItiValidationImpl protected List<ErrorInfo> getXdsValidationErrors(RegisterDocumentSet request, RegisterDocumentSetStarter starter, XdsValidationLevel xdsValidationLevel) { return getXdsValidationErrors(() -> starter.validate(request), xdsValidationLevel); //for getXdsValidationErrors se ovenfor } |
// Fra klassen Iti41ValidationImpl metode validateAndTransform List<ErrorInfo> xdsValidationErrors = getXdsValidationErrors(registerDocumentSet, xdsValidatorFactory.buildIti57Validator(), xdsValidationLevel); // Fra klassen RegistryItiValidationImpl protected List<ErrorInfo> getXdsValidationErrors(RegisterDocumentSet request, RegisterDocumentSetStarter starter, XdsValidationLevel xdsValidationLevel) { return getXdsValidationErrors(() -> starter.validate(request), xdsValidationLevel); //for getXdsValidationErrors se ovenfor } |
Se iøvrigt praktisk anvendelse i bibliotekets egne unit test. F.eks. CdaHeaderValidatorTest der viser CDA dokument validering og ProvideAndRegisterDocumentSetValidatorTest, der viser en række kald for iti-41.
De implementerede valideringsregler er lavet med udgangspunkt i Medcoms standarder og IHE XDS specifikationen.
De refereres som følger:
For nu er følgende valideringer implementeret:
(nedenstående beskrivelse stammer fra javadoc i mvn modul validation-xds og validation-codes. Anvend "mvn javadoc:javadoc -pl \!validation-cda-dependencies " for at generere i target/site folderne)
TODO factories
TODO f.eks starter, enricher og egentlige strukturer
Dette er hjælpevalideringer, som feltvalideringer gør brug af.
Klasse | Validering |
---|---|
CodedValueValidation |
|
ClassCodeValidation |
|
Klasse | Validering | ITI 41 default | ITI 42 default | ITI 61 default | ITI 57 default | Cda dokument |
---|---|---|---|---|---|---|
DocumentEntryClassCodeValidator |
| na | ||||
DocumentEntryAuthorInstitutionValidator |
| na | ||||
CdaHeaderAuthorInstitutionValidator |
| na | na | na | na | |
SubmissionSetAuthorInstitutionValidator |
| |||||