omnist-j API Reference¶
Looking for the complete, automatically generated Java API reference? See the Javadoc.
A curated overview of omnist-j's public API, verified directly against the underlying Java source declarations. See the Document Model and Schema Model chapters of spec.omnist.dev for the formal, language-agnostic definitions.
Package Index¶
dev.omnist.document: Document graph types (Document,Target,Node,Edge,Value,Scalar,Limits).dev.omnist.oml: Native OML reader and writer (OmlReader,OmlWriter,OmlParseException).dev.omnist.schema: OSD schema definition types (Schema,Record,Field,Cardinality,TargetType,OsdReader,OsdWriter,OsdParseException).dev.omnist.validation: Validation engine (Validator,ValidationResult,ValidationDiagnostic,Materializer).dev.omnist.algebra: Formal schema algebra operations (SchemaAlgebra,InferResult,AnyFallback,LintFinding).dev.omnist.codec: External format codecs (JsonCodec,YamlCodec,YamlLimits,TomlCodec,XmlCodec).
Document Model (dev.omnist.document)¶
Document¶
public sealed interface Document permits Node, Value
Root interface representing an Omnist Document (omnist-spec §2.2). A Document is either a Node or a Value.
Target¶
public sealed interface Target permits Node, Value
Target of a labeled Edge.
Node¶
public record Node(List<Edge> edges) implements Target, Document
Represents a node containing an ordered list of labeled edges.
Edge¶
public record Edge(String label, Target target)
Represents a labeled edge connecting a Node to a Target (Node or Value).
Value¶
public sealed interface Value extends Target, Document permits Scalar, Value.NullValue
Sealed interface representing a value in the Document model (Scalar or Value.NullValue).
- Value.NULL: public static final NullValue NULL = NullValue.INSTANCE;
- Value.NullValue: public record NullValue() implements Value
Scalar¶
public sealed interface Scalar extends Value
Sealed interface representing scalar values (omnist-spec §2.2.1). Permitted record variants:
1. Scalar.StringScalar(String value) — kind() = ScalarKind.STRING
2. Scalar.IntegerScalar(BigInteger value) — kind() = ScalarKind.INTEGER
3. Scalar.NumberScalar(double value) — kind() = ScalarKind.NUMBER
4. Scalar.BooleanScalar(boolean value) — kind() = ScalarKind.BOOLEAN
5. Scalar.DateScalar(LocalDate value) — kind() = ScalarKind.DATE
6. Scalar.TimeScalar(TimeValue value) — kind() = ScalarKind.TIME (TimeValue(LocalTime time, ZoneOffset offset))
7. Scalar.DateTimeScalar(DateTimeValue value) — kind() = ScalarKind.DATE_TIME (DateTimeValue(LocalDateTime dateTime, ZoneOffset offset))
Node node = new Node(List.of(
new Edge("title", new Scalar.StringScalar("Project"))
));
assertEquals("title", node.edges().get(0).label());
TimeValue¶
public record TimeValue(LocalTime time, ZoneOffset offset)
Represents a time of day with an optional UTC offset (omnist-spec §2.2.1).
- public String format() — Formats the time as a canonical ISO-8601 string (e.g. 12:30:00Z or 12:30:00+02:00).
DateTimeValue¶
public record DateTimeValue(LocalDateTime dateTime, ZoneOffset offset)
Represents a combined date and time with an optional UTC offset (omnist-spec §2.2.1).
- public String format() — Formats the date-time as a canonical ISO-8601 string (e.g. 2024-01-01T12:30:00Z).
TimeValue tv = TimeValue.of(java.time.LocalTime.of(12, 30, 0), java.time.ZoneOffset.UTC);
assertEquals("12:30Z", tv.format());
DateTimeValue dtv = DateTimeValue.of(java.time.LocalDateTime.of(2024, 1, 1, 12, 30, 0), java.time.ZoneOffset.UTC);
assertEquals("2024-01-01T12:30Z", dtv.format());
Limits¶
public record Limits(int maxDepth, int maxNodeCount, int maxIntegerDigits)
Guard parameters for parser recursion depth, node count, and integer digit limits. Default limits: maxDepth = 200, maxNodeCount = 1_000_000, maxIntegerDigits = 4300.
Limits limits = new Limits(2, 50, 100);
assertEquals(2, limits.maxDepth());
assertEquals(50, limits.maxNodeCount());
assertEquals(100, limits.maxIntegerDigits());
OML Reader & Writer (dev.omnist.oml)¶
OmlReader¶
public static Document read(String text)public static Document read(String text, Limits limits)
Parses OML text into a Document tree. Throws OmlParseException on invalid syntax or limit violations.
String oml = "name: \"Alice\"\nage: 30\n";
Document doc = OmlReader.read(oml);
assertTrue(doc instanceof Node);
Node root = (Node) doc;
assertEquals("name", root.edges().get(0).label());
Diagnostics. OmlParseException, OsdParseException and DocumentParseException (thrown by the
codecs) each carry a machine-readable getCode() and getPath() from the omnist-spec §8.3 taxonomy;
message text is for humans and is never a stable contract. The path follows §8.4 (E-11):
| Code family | getPath() |
|---|---|
parse.* (including parse.codec-syntax) |
a text position, line:col, 1-based |
document.*, format.* |
a Document path such as $ or $.order.items[2].sku |
schema.* |
a schema path such as Record.field, or $ for whole-schema cases |
SchemaException (an IllegalArgumentException) is thrown by the Schema, Record and Type.Ref
constructors for a programmatically built schema: schema.invalid-name at $ (S-8; the name is in the
message only) and schema.invalid-label at the record name (S-22; a field label with a lone surrogate).
OsdWriter throws WriteException with write.unsupported-value at the record name for a field with
max = 0 (OSD-16) or a label holding a C0 control character (OSD-14).
String-body errors (parse.control-character, parse.invalid-escape, parse.unterminated-string,
parse.unpaired-surrogate) report the position of the string's opening quote (E-23).
Leading byte-order mark. Every reader (OML, OSD, JSON, YAML, TOML, XML) strips exactly one leading
U+FEFF (D-15) and rejects a second one at 1:1 (D-21): parse.unexpected-token for OML and OSD,
parse.codec-syntax for the four codecs. A U+FEFF anywhere else is ordinary content. No writer ever emits
one. The rule lives in one place, dev.omnist.document.Bom.
OmlWriter¶
public static String write(Document doc)
Serializes a Document tree into canonical OML text format.
Document doc = OmlReader.read("name: \"Alice\"\nage: 30\n");
String oml = OmlWriter.write(doc);
assertTrue(oml.contains("name: \"Alice\""));
OSD Reader & Writer (dev.omnist.schema)¶
Schema¶
public record Schema(String root, Map<String, Record> records)
Record¶
public record Record(String name, List<Field> fields)
Field¶
public record Field(String label, Cardinality cardinality, TargetType targetType)
OsdReader¶
public static Schema read(String text)
Parses OSD schema text into a Schema. Throws OsdParseException on syntax errors.
String schemaText = "record Person {\n \"name\": string,\n \"age\": integer,\n}\nroot Person\n";
Schema schema = OsdReader.read(schemaText);
assertEquals("Person", schema.root());
OsdWriter¶
public static String write(Schema schema)
Serializes a Schema to canonical OSD text syntax.
String schemaText = "record Person {\n \"name\": string,\n \"age\": integer,\n}\nroot Person\n";
Schema schema = OsdReader.read(schemaText);
String written = OsdWriter.write(schema);
assertTrue(written.contains("record Person"));
Validation & Materialization (dev.omnist.validation)¶
ValidationResult¶
public record ValidationResult(boolean isValid, List<ValidationDiagnostic> diagnostics)
ValidationDiagnostic¶
public record ValidationDiagnostic(String path, String code, String message)
Validator¶
public static ValidationResult validate(Document doc, Schema schema)
Validates a Document against an OSD Schema.
Schema schema = OsdReader.read("record Person {\n \"name\": string,\n \"age\": integer,\n}\nroot Person\n");
Document validDoc = OmlReader.read("name: \"Bob\"\nage: 25\n");
ValidationResult res = Validator.validate(validDoc, schema);
assertTrue(res.isValid());
assertTrue(res.diagnostics().isEmpty());
Materializer¶
public static Document materialize(Document doc, Schema schema)
Upgrades scalar values (e.g. ISO-8601 strings to DateScalar / DateTimeScalar) per schema target types.
Schema schema = OsdReader.read("record Item {\n \"created\": date,\n}\nroot Item\n");
Document doc = OmlReader.read("created: \"2024-01-01\"\n");
Document materialized = Materializer.materialize(doc, schema);
assertNotNull(materialized);
Schema Algebra (dev.omnist.algebra)¶
SchemaAlgebra¶
satisfiableSet(Schema schema) -> Set<String>¶
Schema schema = OsdReader.read("record Root {\n \"id\": integer,\n}\nroot Root\n");
Set<String> set = SchemaAlgebra.satisfiableSet(schema);
assertTrue(set.contains("Root"));
isEmpty(Schema schema) -> boolean¶
Schema schema = OsdReader.read("record Root {\n \"id\": integer,\n}\nroot Root\n");
assertFalse(SchemaAlgebra.isEmpty(schema));
prune(Schema schema) -> Schema¶
Schema schema = OsdReader.read("record Root {\n \"id\": integer,\n}\nrecord Dead {\n \"x\": string,\n}\nroot Root\n");
Schema pruned = SchemaAlgebra.prune(schema);
assertFalse(pruned.records().containsKey("Dead"));
compatibleWith(Schema s1, Schema s2) -> boolean¶
Schema s1 = OsdReader.read("record Root {\n \"id\": integer,\n}\nroot Root\n");
Schema s2 = OsdReader.read("record Root {\n \"id\": integer,\n}\nroot Root\n");
assertTrue(SchemaAlgebra.compatibleWith(s1, s2));
equivalent(Schema s1, Schema s2) -> boolean¶
Schema s1 = OsdReader.read("record Root {\n \"id\": integer,\n}\nroot Root\n");
Schema s2 = OsdReader.read("record Root {\n \"id\": integer,\n}\nroot Root\n");
assertTrue(SchemaAlgebra.equivalent(s1, s2));
normalize(Schema schema) -> Schema¶
Schema schema = OsdReader.read("record Root {\n \"id\": integer,\n}\nroot Root\n");
Schema norm = SchemaAlgebra.normalize(schema);
assertNotNull(norm);
equivalenceClasses(Schema schema) -> List<List<String>>¶
Schema schema = OsdReader.read("record Root {\n \"id\": integer,\n}\nroot Root\n");
List<List<String>> classes = SchemaAlgebra.equivalenceClasses(schema);
assertFalse(classes.isEmpty());
extract(Schema schema, Set<String> fieldPaths) -> Schema¶
Schema schema = OsdReader.read("record Root {\n \"id\": integer,\n \"secret\" [0,1]: string,\n}\nroot Root\n");
Schema extracted = SchemaAlgebra.extract(schema, Set.of("id"));
assertNotNull(extracted);
lint(Schema schema) -> List<LintFinding>¶
public record LintFinding(String code, String severity, String location, String message)
Schema schema = OsdReader.read("record Root {\n \"id\": integer,\n}\nrecord Dead {\n \"x\": string,\n}\nroot Root\n");
List<LintFinding> findings = SchemaAlgebra.lint(schema);
assertEquals("lint.unreachable-record", findings.get(0).code());
infer(List<Document> samples) -> Schema¶
inferWithReport(List<Document> samples, String rootName, boolean allowAny) -> InferResult¶
public record InferResult(Schema schema, List<AnyFallback> fallbacks)
Document doc1 = OmlReader.read("id: 1\nname: \"A\"\n");
Document doc2 = OmlReader.read("id: 2\nname: \"B\"\n");
Schema inferred = SchemaAlgebra.infer(List.of(doc1, doc2));
assertTrue(inferred.records().containsKey("Root"));
InferResult res = SchemaAlgebra.inferWithReport(List.of(doc1, doc2), "Root", false);
assertNotNull(res.schema());
Format Codecs (dev.omnist.codec)¶
JsonCodec¶
public static Document read(String text)public static String write(Document doc)
YamlCodec¶
public static Document read(String text)(bounded by 2MBMAX_INPUT_LENGTHcap; alias limits at the reference defaults)public static Document readWithLimits(String text, YamlLimits limits)(the same, with the alias limits you choose)public static String write(Document doc)
YamlLimits¶
public record YamlLimits(int maxAliasExpansion, long maxExpandedSlots)
The two limits that bound what YAML anchors and aliases may expand to (omnist-spec §2.4.1). Defaults:
maxAliasExpansion = 50 (D-18, the expansion factor E = W / S of any mapping or sequence, root and inline merge
sources included; accepted at the limit, refused above it with document.limit.alias-expansion) and
maxExpandedSlots = 1_000_000 (D-22, the value slots W(root) of an input that contains an alias or a merge key;
refused above it with document.limit.expanded-size; an input with neither is exempt). Both are checked on
SnakeYAML's composed node graph before anything is constructed from it, in time linear in the input. An input that
crosses both reports document.limit.alias-expansion. A merge key whose value is not a mapping or a sequence of
mappings is parse.codec-syntax, and a self-referential anchor is document.limit.alias-expansion. Like Limits, the
constructor throws IllegalArgumentException for a value that is not positive; it also refuses
maxAliasExpansion above 10 000 and maxExpandedSlots above 10 000 000. A merge of a large block is not free: a
mapping that merges a k-key block and writes one key of its own has E of about (k + 2) / 3. See
limitations.md for the measured shapes.
String yaml = "base: &b {k1: 1, k2: 2, k3: 3, k4: 4, k5: 5, k6: 6, k7: 7, k8: 8}\n"
+ "job: {<<: *b, script: x}\n";
// E(job) = W / S = 10 / 3 = 3.33
Document doc = YamlCodec.readWithLimits(yaml, new YamlLimits(4, 1_000));
assertTrue(doc instanceof Node);
DocumentParseException tooBig = assertThrows(DocumentParseException.class,
() -> YamlCodec.readWithLimits(yaml, new YamlLimits(3, 1_000)));
assertEquals("document.limit.alias-expansion", tooBig.getCode());
assertEquals("$", tooBig.getPath());
// W(root) = 1 + 9 + 10 = 20 value slots
DocumentParseException tooLarge = assertThrows(DocumentParseException.class,
() -> YamlCodec.readWithLimits(yaml, new YamlLimits(4, 19)));
assertEquals("document.limit.expanded-size", tooLarge.getCode());
assertNotNull(YamlCodec.readWithLimits(yaml, new YamlLimits(4, 20)));
assertEquals(50, YamlLimits.DEFAULT.maxAliasExpansion());
assertEquals(1_000_000L, YamlLimits.DEFAULT.maxExpandedSlots());
TomlCodec¶
public static Document read(String text)(bounded by 2MBMAX_INPUT_LENGTHcap)public static String write(Document doc)
XmlCodec¶
public static Document read(String text)(secure XXE/DTD protection, bounded by 2MBMAX_INPUT_LENGTHcap)public static String write(Document doc)