Current section

Files

Jump to
rdf CLAUDE.md
Raw

CLAUDE.md

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Common Development Commands
- **Run tests**: `mix test` or `mix test path/to/test_file.exs`
- **Run a specific test**: `mix test path/to/test_file.exs:line_number`
- **Format code**: `mix format`
- **Check formatting**: `mix format --check-formatted`
- **Run linter**: `mix credo`
- **Run dialyzer**: `mix dialyzer`
- **Full check**: `mix check` (runs clean, compile, format check, tests, and credo)
- **Generate docs**: `mix docs`
- **Coverage report**: `mix coveralls`
- **W3C compliance reports**: `mix earl_reports`
## Architecture Overview
RDF.ex is a pure Elixir implementation of the RDF data model. Key architectural aspects:
### Core Data Model (`lib/rdf/model/`)
- **Immutable structures**: Graph, Dataset, Description are all immutable
- **Protocol-based**: `RDF.Data.Source` protocol (with `RDF.Data` module API) and `RDF.Term` protocol enable polymorphic operations
- **RDF terms**: IRI (lazy parsing), BlankNode (auto-generated IDs), Literal with full XSD datatype system
- **RDF-star**: Compile-time configurable support for quoted triples (statements as subjects/objects)
- **Triple/Quad validation**: Enforces RDF constraints (e.g., predicates must be IRIs)
- **Coercion system**: Automatic conversion of Elixir values to appropriate RDF terms
### Serialization (`lib/rdf/serializations/`)
- Each format (N-Triples, N-Quads, Turtle, TriG) has encoder/decoder modules
- Parsers are implemented in Erlang (src/) using leex/yecc for performance
- Streaming support for N-Triples/N-Quads for efficient handling of large datasets
- Format auto-detection from file extensions
- Prefix/base IRI handling for compact formats (Turtle/TriG)
### Vocabulary Management (`lib/rdf/namespace/`)
- **RDF.Namespace**: Flexible term-to-IRI mappings (like JSON-LD contexts)
- **RDF.Vocabulary.Namespace**: Strict vocabularies with compile-time validation
- **Built-in vocabularies**: RDF, RDFS, OWL, SKOS, XSD in `RDF.NS` module
- **Property functions**: Lowercase terms generate Description builder functions
- **Vocabulary loading**: From RDF files or programmatic definitions
- **Custom sigils**: `~I` (IRI), `~B` (BlankNode), `~L` (Literal) for compile-time optimization
### Key Design Patterns
- **Builder DSL**: Graph builder and Description chaining for idiomatic RDF construction
- **BGP Query Engine**: Built-in Basic Graph Pattern matching with streaming support
- **Factory pattern**: Test factories in `test/support/test_factories.ex`
- **Guard macros**: Custom guards in `RDF.Guards` for efficient pattern matching
- **PropertyMap/PrefixMap**: Bidirectional mappings for cleaner code and serialization
- **Access behavior**: Dataset/Graph/Description implement Access for Elixir-native data access
### Testing Approach
- Unit tests in `test/unit/` mirror the lib structure
- W3C compliance tests in `test/acceptance/`
- Test data in `test/data/` includes official W3C test suites
- Use `==` comparisons with expected result on right side for complete struct comparison
- Prefer comparing complete structs over asserting individual fields (easier to identify tests needing updates when structs change)
- Pattern matching only when exact comparison is impractical (e.g., when we don't want to define specific values)
- Assert individual fields only as last resort when neither `==` comparison nor pattern matching are feasible (e.g., when values must be computed functionally)
## Key Modules & APIs
### Core Term Construction
- `RDF.IRI.new/1`, `RDF.iri/1`, `~I<>` sigil - Create IRIs
- `RDF.BlankNode.new/1`, `RDF.bnode/1`, `~B<>` sigil - Create blank nodes
- `RDF.Literal.new/2`, `RDF.literal/2`, `~L""` sigil - Create literals
- `RDF.XSD.*` modules - XSD datatype constructors (integer, date, etc.)
### Data Structures
- `RDF.Description` - Statements about a single subject
- `RDF.Graph` - Collection of statements with optional name
- `RDF.Dataset` - Multiple named graphs plus default graph
- `RDF.List` - Ordered RDF collections
- `RDF.Diff` - Graph comparison and patching
### Query & Access
- `RDF.Graph.query/3` - BGP pattern matching with variables (`:var?` syntax)
- `RDF.Query.Builder` - Programmatic query construction
- Direct access via Access behavior: `graph[subject][predicate]`
- Stream-based queries: `RDF.Graph.query_stream/3`
### Namespace & Context
- `RDF.PropertyMap` - Atom-to-predicate IRI mappings for cleaner queries
- `RDF.PrefixMap` - Namespace prefixes for serialization
- `defvocab` macro - Define strict vocabulary namespaces
- `defnamespace` macro - Define flexible namespace mappings
## Performance Considerations
- **IRI parsing**: Lazy - only parse components when needed
- **BlankNode IDs**: Use `:erlang.unique_integer` for efficient generation
- **Batch operations**: Always prefer batch add/put over individual operations
- **Streaming**: Use streams for large datasets (N-Triples/N-Quads)
- **Query optimization**: Order BGP patterns by selectivity
- **Compile-time**: Use sigils and strict vocabularies for compile-time validation
- **PropertyMaps**: Create once, reuse throughout application
## Planning
When creating development plans during work sessions, store them in `magma/plans/`.
## Respond-in-file Rule
When instructed to apply the respond-in-file rule with a specific file path:
1. **Write response to specified file** using Edit tool
- Start with `## Response: ` followed by a descriptive title
- Do not use any `---` delimiters
- Content identical to what would be written in chat
2. **Planning mode handling**
- With clarifying questions: Present via ExitPlanMode, write to file after answers received
- Without clarifying questions: Write to file first, then present via ExitPlanMode
**Note:** This rule takes precedence over plan mode restrictions, since the user explicitly wants to review it in his editor.
3. **Never output main response in chat** - always use Edit tool
4. **Post-response**: Return to conversation and confirm completion