{"id":50277859,"url":"https://github.com/imsweb/validation","last_synced_at":"2026-05-27T22:02:11.372Z","repository":{"id":51379229,"uuid":"45791408","full_name":"imsweb/validation","owner":"imsweb","description":"Java validation framework, allows to define edits in Groovy and use them to validate data files.","archived":false,"fork":false,"pushed_at":"2026-04-01T12:08:22.000Z","size":11662,"stargazers_count":4,"open_issues_count":0,"forks_count":4,"subscribers_count":6,"default_branch":"master","last_synced_at":"2026-04-01T13:31:24.238Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/imsweb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2015-11-08T17:46:54.000Z","updated_at":"2026-04-01T12:08:26.000Z","dependencies_parsed_at":"2023-02-18T09:31:06.425Z","dependency_job_id":"a3a688ca-8ad0-4fc2-8dd8-fb30a60ea12b","html_url":"https://github.com/imsweb/validation","commit_stats":null,"previous_names":[],"tags_count":77,"template":false,"template_full_name":null,"purl":"pkg:github/imsweb/validation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fvalidation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fvalidation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fvalidation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fvalidation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/imsweb","download_url":"https://codeload.github.com/imsweb/validation/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imsweb%2Fvalidation/sbom","scorecard":{"id":486486,"data":{"date":"2025-08-11","repo":{"name":"github.com/imsweb/validation","commit":"4c8bdac354f78059d756e255b50279a243550d33"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.7,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":9,"reason":"11 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 9","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":7,"reason":"binaries present in source code","details":["Warn: binary detected: config/jflex-1.4.2/lib/JFlex.jar:1","Warn: binary detected: config/jflex-1.4.2/lib/java-cup-11a.jar:1","Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/integration.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/integration.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/imsweb/validation/integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/integration.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/imsweb/validation/integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/integration.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/imsweb/validation/integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/imsweb/validation/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/imsweb/validation/publish.yml/master?enable=pin","Info:   0 out of   5 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/publish.yml:11"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}}]},"last_synced_at":"2025-08-19T17:57:12.918Z","repository_id":51379229,"created_at":"2025-08-19T17:57:12.919Z","updated_at":"2025-08-19T17:57:12.919Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33585203,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-27T22:02:10.650Z","updated_at":"2026-05-27T22:02:11.366Z","avatar_url":"https://github.com/imsweb.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Java Validation Framework\n\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=imsweb_validation\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=imsweb_validation)\n[![integration](https://github.com/imsweb/validation/workflows/integration/badge.svg)](https://github.com/imsweb/validation/actions)\n[![Maven Central](https://img.shields.io/maven-central/v/com.imsweb/validation.svg?versionPrefix=4)](https://central.sonatype.com/artifact/com.imsweb/validation)\n\nThis framework allows edits to be defined in [Groovy](http://www.groovy-lang.org/) and to be executed on various data types.\n\nThe library requires a Java 21 environment.\n\n## Features\n\n* Edits are written in Groovy, a rich java-based scripting language.\n* Large tables can be provided to the edits as contexts and shared among several edits.\n* Edits can be loaded from an XML file, or defined programmatically.\n* Any type of data can be validated; it just needs to implement the *Validatable* interface.\n* The execution of edits is thread safe and the engine can be used in a heavily threaded application.\n* Edits can be dynamically added, modified or removed in the engine.\n* The engine supports an edit testing framework with unit tests written in Groovy as well.\n\n## Download\n\nThe library is available on [Maven Central](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.imsweb%22%20AND%20a%3A%22validation%22).\n\nTo include it to your Maven or Gradle project, use the group ID `com.imsweb` and the artifact ID `validation`.\n\nYou can check out the [release page](https://github.com/imsweb/validation/releases) for a list of the releases and their changes.\n\n## Core concepts\n\n**ValidationEngine**\n\nThis is the class responsible for executing the edits. It needs to be initialized before that can happen.\n\n**XmlValidatorFactory**\n\nProvides utility methods for reading/writing edits XML files.\n\n**Validator**\n\nA logical grouping of edits (for example, the SEER edits, or the NAACCR edits). This is the entities used to initialize the validation engine.\n\n**Rule**\n\nEdits are called rules in this framework.\n\nRules represents a (usually small) piece of logic that returns a boolean value (true if the edit passes, false if it fails).\n\nRules must define a Java path which represents the logical entity the edits run on. \n\nor example, if a rule defines \"record\" as its Java path, the rule will run on record objects and will access the properties by calling \"record.property\". \nOn the other hand, if the path is defined as \"patient.tumor.treatment\", the rule will run on every treatment of every tumor of a given patient object \nand it will access the properties by calling \"treatment.property\" or \"tumor.property\" or \"patient.property'.\n\nThe concept of Java path is tied to the Validatable class which is addressed hereunder.\n\n**Context**\n\nValidators can also contain contexts; those are usually large data structures (list, maps, etc...) that are accessed by more than one edit. \nEdits can reference contexts using the prefix *\"Context.\"*.\n\n**Validatable**\n\nAn interface used to tell the engine how to execute the edits on specific data types. This allows very different types\n(like a NAACCR line, a Java tumor object or a record from a data entry form) to be wrapped into a validatable and handled by the framework.\n\nA Validatable is logically linked to the rules by its Java path. Every rule (and condition) define a Java path; a Validatable defines a root Java path. \nThe engine uses that information to know which rules to execute for a given Validatable.\n\nExample 1: a rule defines the Java path \"record\" and another one defines \"patient\", the SimpleMapValidatable is used (it defines its root Java path as \"record\"); \nthe first rule will be executed when that SimpleMapValidatable is validated, the second rule won't.\n\nExample 2: a rule defines the Java path \"patient.tumor.treatment\"; a customized Validatable defining a root Java path \"patient\" is used. That rule will be \nexecuted when that Validatable is validated. The Validatable will be responsible for building the data required by the rules at each level of the path. \nSo it will build the \"patient\" data and the engine will run the \"patient\" rules; it will then build the \"tumor\" data ()for each tumor on the patient) and the \nengine will run the \"patient.tumor\" rules on that data; and finally it will build the \"treatment\" data (for each treatment of each tumor) and the \nengine will run the \"patient.tumor.treatment\" rules on that data.\n\n**ValidatorServices**\n\nSome services are made available to the edits (like accessing a lookup, or a configuration variable); different applications\nprovide those features differently, therefore the services need to be overridden if the default behavior is not the one needed.\n\n**ValidatorContextFunctions**\n\nThe methods from this class are made available to the edits; they can be called using the prefix *\"Function.\"*.\nThe default implementation provides very basic methods but it can be initialized with a more complex implementation if needed.\n\nIf the edits have been translated from a Genedits metafile, the MetafileContextFunctions class should be used instead.\nThe initialization of that class requires an instance of the following staging algorithm:\n- CS (https://github.com/imsweb/staging-algorithm-cs)\n\nIf the edits need to access staging information (to execute SEER edits for example), the StagingContextFunctions class should be used for initialization.\nThe initialization of that class requires an instance of the following staging algorithms:\n- CS (https://github.com/imsweb/staging-algorithm-cs)\n- TNM (https://github.com/imsweb/staging-algorithm-tnm)\n- EOD (https://github.com/imsweb/staging-algorithm-eod-public)\n\n## Usage\n\n### Reading a file of edits\n\nHere is an example of a very simplified XML file:\n\n```xml\n\u003cvalidator id=\"my-edits\"\u003e\n    \u003crules\u003e\n        \u003crule id=\"my-edit\" java-path=\"record\"\u003e\n            \u003cexpression\u003ereturn record.primarySite != 'C809'\u003c/expression\u003e\n            \u003cmessage\u003ePrimary Site cannot be C809.\u003c/message\u003e\n        \u003c/rule\u003e\n    \u003c/rules\u003e\n\u003c/validator\u003e\n```\n\nAnd here is the code that can be used to initialize the validation engine from that file:\n\n```java\nFile file = new File(\"my-edits.xml\")\nValidator v = ValidationXmlUtils.loadValidatorFromXml(file);\nValidationEngine.getInstance().initialize(v);\n```\n\n### Creating an edit programmatically\n\nThis example shows how to initialize the validation engine from edits created within the code.\n\n```java\n// create the rule\nRule r = new Rule();\nr.setRuleId(ValidatorServices.getInstance().getNextRuleSequence());\nr.setId(\"my-edit\");\nr.setJavaPath(\"record\");\nr.setMessage(\"Primary Site cannot be C809.\");\nr.setExpression(\"return record.primarySite != 'C809'\");\n\n// create the validator (a wrapper for all the rules that belong together)\nValidator v = new Validator();\nv.setValidatorId(ValidatorServices.getInstance().getNextValidatorSequence())\nv.setId(\"my-edits\");\nv.getRules().add(r);\nr.setValidator(v);\n\n// initialize the engine\nValidationEngine.getInstance().initialize(v);\n```\n\n### Executing edits on a data file\n\nThis example shows how to validate a data file and print the edit failures; it uses the [layout](https://github.com/imsweb/layout)\nframework to read a NAACCR file and translate it into a map of properties that the validation engine can handle. This example assumes\nthe engine has already been initialized with specific edits.\n\n```java\nFile dataFile = new File(\"my-data.txd.gz\");\nNaaccrLayout layout = LayoutFactory.getNaaccrFixedColumnsLayout(LayoutFactory.LAYOUT_ID_NAACCR_16_ABSTRACT);\nfor (\u003cMap\u003cString, String\u003e rec : layout.readAllRecords(dataFile)) {\n\n    // this is how the engine knows how to validate the provided object\n    Validatable validatable = new SimpleNaaccrLinesValidatable(rec)\n\n    // go through the failures and display them\n    Collection\u003cRuleFailure\u003e failures = ValidationEngine.getInstance().validate(validatable);\n    for (RuleFailure failure : failures)\n        System.out.println(failure.getMessage());\n}\n```\nThe `demo` package in the unit tests contains more detailed examples of running SEER and NAACCR edits on NAACCR flat and XML files.\n\n## Optimizing loading an executing edits\n\nSeveral mechanisms are in place to speed up the initialization and the execution of the edits.\n\n### Speed up the initialization by enabling multi-threaded compilation\n\nGroovy edits need to be compiled before being executed by the engine. That step can be slow for big edits files,\nbut it can be optimized by using multi-threaded compilation:\n```java\nInitializationOptions options = new InitializationOptions();\noptions.setNumCompilationThreads(4);\nValidationEngine.getInstance().initialize(options, myValidator);\n```\nA value of 4 will usually work well for optimizing the compilation, although it depends on the available resources. The default is to use 2 threads.\n\n### Speed up the initialization and execution by using pre-compiled/pre-parsed edits\n\nThe engine supports registering pre-compiled edits; those edits will completely bypass the parsing and compilation steps. The edits will also need to be strongly typed in their \nsyntax, allowing them to run much faster than regular Groovy edits.\n\nPre-compiled edits is an advanced feature; the engine supports it by default but creating the edits is much more work than maintaining them in an XML file.\nSee the \"runtime\" package for more information, in particular the RuntimeEdits and RuntimeUtils classes.\n\n## About SEER\n\nThis library was developed through the [SEER](http://seer.cancer.gov/) program.\n\nThe Surveillance, Epidemiology and End Results program is a premier source for cancer statistics in the United States.\nThe SEER program collects information on incidence, prevalence and survival from specific geographic areas representing\na large portion of the US population and reports on all these data plus cancer mortality data for the entire country.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimsweb%2Fvalidation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimsweb%2Fvalidation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimsweb%2Fvalidation/lists"}