Skip to content

Latest commit

 

History

History
148 lines (113 loc) · 6.6 KB

File metadata and controls

148 lines (113 loc) · 6.6 KB

JVM API

The surface of dev.disarm:disarm and dev.disarm:disarm-kotlin, and how it lines up with the names used in the other bindings. For install, the JDK floor and the bundled platforms, see Getting started.

This page covers what is specific to the JVM. Behaviour is language-neutral and lives once, in the concept and user-guide pages.

Two call styles

Disarm is a final class of static methods. disarm-kotlin adds top-level extension functions over the same native core, so the choice is a matter of which reads better in your codebase rather than which is capable.

Java Kotlin
entry point Disarm.transliterate(text) text.transliterate()
wide calls options builders default arguments
naming camelCase camelCase
package dev.disarm dev.disarm.kotlin for functions, dev.disarm for types

Kotlin's functions are top-level. There is no Disarm object to call them on, and getPipeline is a top-level function too.

import dev.disarm.TargetScript          // types
import dev.disarm.kotlin.*              // functions

What the JVM surface does not have

Measured against the 112 canonical operations in generated/parity.yaml, the JVM covers 65. Some of the remainder are deprecated aliases or Python-only conveniences and are not gaps at all. These are the ones that are:

absent what it is reach it with
escapeHtml, percentEncode output encoders your framework's encoder, which you should prefer anyway
stripLogInjection neutralize a log line canonicalize plus your own newline handling
decodeToUtf8, detectEncoding encoding recovery —
registerLang, registerReplacements runtime registration —
setEmojiProvider custom emoji naming —
isAscii a predicate text.chars().allMatch(c -> c < 128)

CVE Validation measures that canonicalize_strict and strip_obfuscation are the two presets that clear every row of the matrix, and recommends them on that basis. Both are on the JVM, as canonicalizeStrict and stripObfuscation; canonicalize misses the eclipsing mark in CVE-2017-7833.

The introspection lists are here too: listLangs, listProfiles and reverseLangs return what every other binding returns (#981), and each profile's Pipeline.purpose() says what it is for.

The figures and the table are gated. tests/test_jvm_api_page.py reads the coverage figure off the parity matrix, which has carried java and kotlin columns since #677, and fails if the table names a method that Disarm.java or the Kotlin functions declare.

Options builders

Four, all with the same shape: a static builder(), chained setters, and build().

TransliterateOptions.builder().scheme(Scheme.STRICT_ISO9).lang("ru").build();

SlugOptions.builder()
    .separator("_").lowercase(true).maxLength(64)
    .wordBoundary(true).saveOrder(true).stopwords(List.of("the"))
    .allowUnicode(false).lang("de")
    .build();

SanitizeFilenameOptions.builder()
    .separator("_").maxLength(255).platform(Platform.WINDOWS)
    .lang("de").preserveExtension(true)
    .build();

MlNormalizeOptions.builder().lang("de").emojiStyle("cldr").foldCase(false).build();

Kotlin passes the same values as named arguments and does not use the builders.

Types

type what it carries
AnomalyReport anomalous, kinds, findings, reason
Finding one anomaly: kind, token, start, end, detail, reason
HostnameAnalysis suspicious, canonical, scripts, mixedScript, hasConfusables, bidiConflict, bidiControl, hasInvisible, compatFold, crossLabelScript, labelScripts, wholeScriptConfusable, labelWholeScriptConfusable
KeyCollision key, values, indices
UnmappedConfusable, Untranslatable coverage residue
LangMeta, ScriptMeta, AutoLangInspection metadata
Lexicon, Pipeline native handles, AutoCloseable
TargetScript, NormalizationForm, DigitPolicy, Platform enums
Scheme nested in TransliterateOptions; Kotlin aliases it as Scheme

Name mapping

The other bindings use snake_case; the JVM uses camelCase. Everything else is the same name, with three exceptions worth knowing:

elsewhere JVM
is_suspicious_hostname → (bool, analysis) in Python isSuspiciousHostname → boolean, and analyzeHostname → HostnameAnalysis
has_anomalies(text) hasAnomalies(text, words) — no single-argument form
Disarm.canonicalize(...) in Java "...".canonicalize() in Kotlin

The hostname split is the one that catches people. Python returns the verdict and the analysis together; the JVM has a predicate and a separate analysis call, so asking for both means two calls or one call to analyzeHostname and reading .suspicious() off it.

Errors

DisarmException                    (extends RuntimeException)
└── DisarmInvalidArgumentException

Unchecked, so nothing forces a try. DisarmInvalidArgumentException is thrown for a value the library can name as wrong (an unknown profile, an unsupported scheme) and carries the offending value and the valid set in its message.

Signature stability (#588)

Every public Kotlin function with a default argument carries @JvmOverloads, so each default emits a real JVM method instead of a synthetic $default bridge. Without it, adding a default to a shipped function deletes an arity that existed, and callers who have not recompiled meet a NoSuchMethodError at run time.

JvmSignatureTest pins the arities in CI. See BINDINGS.md for why this is a guarantee rather than a style.

Disarm.skeletonKey(text[, digitPolicy]) · Disarm.editDistance(a, b) · Disarm.nearestMatch(value, candidates[, maxDistance])

skeletonKey is the TR39 identifier skeleton plus the two prototype classes disarm's table keeps apart (#650) — a spoof key, never for display; DigitPolicy.TR39 adds the digit half. editDistance is the Levenshtein distance in characters, and nearestMatch returns the closest candidate as a NearestMatch(value, distance) record or null beyond maxDistance (default 1) (#894). The six key builders — canonicalize, canonicalizeStrict, stripObfuscation, searchKey, sortKey, catalogKey — take a trailing DigitPolicy overload (#896), and Pipeline.withDigitPolicy(policy) returns a copy folding under it (#646). Kotlin exposes the same as extension functions with default arguments.