JDF and JMF Builder Modules
The jdf and jmf modules provide programmatic interfaces for building JDF (Job Definition Format) and JMF (Job Messaging Format) XML documents. These are industry-standard formats used in print production workflows for defining print jobs, managing device communication, and tracking production status.
Both modules use a dual return pattern where operations return both an updated builder and a reference to the created element, enabling hierarchical document construction.
JDF Builder Module (jdf)
The JDF builder creates job definition documents that describe print production workflows, resources, and specifications.
Core Functions
jdf.new(job_name, attrs, opts)
Creates a new JDF builder instance.
Parameters:
job_name(string): Descriptive name for the jobattrs(table): JDF root attributes (e.g.,{JobID = "BC-2025-001"}) - passnilor{}if noneopts(table): Builder options (e.g.,{validation_mode = "strict"}) - passnilor{}if none
Returns: builder - JDF builder userdata
local builder = jdf.new("Business Cards", {JobID = "BC-2025-001"}, {})jdf.from_graph(graph_data, opts)
Creates a JDF builder from existing graph data (e.g., from a parsed JDF document).
Parameters:
graph_data(table): Existing graph structureopts(table): Builder options - passnilor{}if none
Returns: builder - JDF builder userdata
Resource Functions
All resource functions return {builder, node_ref} where node_ref contains the created element's ID and can be used as a parent for other resources.
jdf.add_component(builder, parent_id, attrs)
Adds a component resource (sheets, final products, etc.).
local builder, component = jdf.add_component(builder, nil, {
ComponentType = "FinalProduct",
Amount = "1000",
ProductType = "BusinessCard"
})jdf.add_media(builder, parent_id, attrs)
Adds media resource (paper, film, plates, etc.).
local builder, media = jdf.add_media(builder, nil, {
MediaType = "Paper",
Dimension = "Letter",
Weight = "80"
})jdf.add_layout(builder, parent_id, attrs)
Adds layout resource defining page arrangement.
local builder, layout = jdf.add_layout(builder, component.id, {
Name = "10up_Layout",
SurfaceContentsBox = "0 0 890 510",
WorkStyle = "Simplex"
})jdf.add_customer_info(builder, parent_id, attrs)
Adds customer information.
local builder, customer = jdf.add_customer_info(builder, nil, {
CustomerID = "CUST123",
CustomerName = "Acme Corporation"
})jdf.add_resource(builder, parent_id, resource_type, attrs)
Adds a generic resource of any type.
local builder, resource = jdf.add_resource(builder, nil, "CustomResource", {
Name = "Special Resource"
})jdf.add_resource_link(builder, resource_id, usage, attrs)
Adds a resource link to connect resources.
local builder, link = jdf.add_resource_link(builder, resource.id, "Input", {
Usage = "Input"
})Additional Resource Functions
jdf.add_runlist(builder, parent_id, attrs)- Content to be printedjdf.add_colorpool(builder, parent_id, attrs)- Color definitionsjdf.add_node_info(builder, parent_id, attrs)- Node metadatajdf.add_device(builder, parent_id, attrs)- Device specifications
Intent Resources
Intent resources specify desired outcomes rather than specific implementations:
jdf.add_binding_intent(builder, parent_id, attrs)- Binding requirementsjdf.add_delivery_intent(builder, parent_id, attrs)- Delivery specificationsjdf.add_layout_intent(builder, parent_id, attrs)- Layout preferencesjdf.add_media_intent(builder, parent_id, attrs)- Media requirementsjdf.add_color_intent(builder, parent_id, attrs)- Color specifications
Audit Trail Functions
Track document creation and modification history:
jdf.add_created_audit(builder, attrs)
Adds a creation audit entry.
local builder, audit = jdf.add_created_audit(builder, {
Author = "System",
TimeStamp = "2025-09-23T10:00:00Z"
})jdf.add_modified_audit(builder, attrs)
Adds a modification audit entry.
local builder, audit = jdf.add_modified_audit(builder, {
Author = "User123",
TimeStamp = "2025-09-23T10:30:00Z"
})Validation and Management Functions
Advanced document management and validation:
jdf.validate(builder)
Validates the JDF document structure and content.
Returns: {ok, validation_result} or {false, error_message}
local ok, result = jdf.validate(builder)
if ok then
print("Validation passed:", result)
else
print("Validation failed:", result)
endjdf.get_resource(builder, resource_id)
Retrieves an existing resource by ID.
Returns: {true, resource_data} or {false, error_message}
local ok, resource = jdf.get_resource(builder, component.id)
if ok then
print("Resource found:", resource)
endjdf.update_resource(builder, resource_id, updates)
Updates an existing resource with new attributes.
Returns: {builder, updated_resource} or {false, error_message}
local builder, updated_component = jdf.update_resource(builder, component.id, {
Amount = "2000" -- Update quantity
})jdf.remove_resource(builder, resource_id)
Removes a resource from the document.
Returns: {builder} or {false, error_message}
local builder = jdf.remove_resource(builder, old_resource.id)Output Functions
jdf.render(builder, options)
Renders the JDF builder to XML string.
Parameters:
builder(userdata): JDF builder instanceoptions(table): Rendering options - passnilor{}if none
Returns: xml_string - Complete JDF XML document
local xml = jdf.render(builder, {})
-- Result: "<?xml version="1.0"?><JDF>...</JDF>"jdf.to_graph(builder)
Converts builder to graph representation for analysis or storage.
Parameters:
builder(userdata): JDF builder instance
Returns: graph_data - Graph structure
Complete JDF Example
-- Create job for business cards
local builder = jdf.new("Business Cards", {JobID = "BC-2025-001"}, {})
-- Add customer information
local builder, customer = jdf.add_customer_info(builder, nil, {
CustomerID = "CUST123",
CustomerName = "Acme Corporation"
})
-- Add final product component
local builder, product = jdf.add_component(builder, nil, {
ComponentType = "FinalProduct",
Amount = "1000",
ProductType = "BusinessCard",
Dimensions = "89 51"
})
-- Add paper media
local builder, media = jdf.add_media(builder, product.id, {
MediaType = "Paper",
Weight = "350",
Grade = "1"
})
-- Add layout with product as parent
local builder, layout = jdf.add_layout(builder, product.id, {
Name = "10up_Layout",
SurfaceContentsBox = "0 0 890 510",
WorkStyle = "Simplex"
})
-- Generate XML
local xml = jdf.render(builder, {})
print("Generated JDF:", xml)JMF Builder Module (jmf)
The JMF builder creates job messaging format documents for device communication, status reporting, and workflow management.
Core Functions
jmf.new(sender_id, attrs, opts)
Creates a new JMF builder instance.
Parameters:
sender_id(string): Identifier for the message senderattrs(table): JMF root attributes - passnilor{}if noneopts(table): Builder options - passnilor{}if none
Returns: builder - JMF builder userdata
local builder = jmf.new("Controller001", {}, {})Message Functions
All message functions return {builder, message_ref} where message_ref contains the created message's ID and metadata.
jmf.add_query(builder, query_type, attrs)
Adds a query message to request information.
local builder, query = jmf.add_query(builder, "Status", {
ID = "q001",
DeviceID = "Press001"
})jmf.add_response(builder, ref_id, attrs)
Adds a response message to a previous query.
local builder, response = jmf.add_response(builder, "q001", {
ReturnCode = "0",
DeviceStatus = "Idle"
})jmf.add_command(builder, command_type, attrs)
Adds a command message to control devices or workflows.
local builder, command = jmf.add_command(builder, "SubmitQueueEntry", {
QueueEntryID = "entry001",
Priority = "50"
})jmf.add_signal(builder, signal_type, attrs)
Adds a signal message for notifications and status updates.
local builder, signal = jmf.add_signal(builder, "Status", {
DeviceID = "Press001",
Status = "Running"
})jmf.add_acknowledge(builder, ref_id, attrs)
Adds an acknowledgment message.
local builder, ack = jmf.add_acknowledge(builder, "q001", {
ReturnCode = "0"
})Queue Management Functions
jmf.add_queue_status(builder, queue_id, status_attrs)
Adds queue status information.
local builder, queue_status = jmf.add_queue_status(builder, "MainQueue", {
Status = "Running",
QueueSize = "5"
})jmf.add_queue_entry(builder, queue_id, entry_attrs)
Adds a job entry to a queue.
local builder, entry = jmf.add_queue_entry(builder, "MainQueue", {
JobID = "Job001",
Priority = "50",
Status = "Waiting"
})jmf.update_queue_entry(builder, entry_id, attrs)
Updates an existing queue entry.
local builder, updated_entry = jmf.update_queue_entry(builder, entry.id, {
Status = "Running",
Progress = "25"
})Device Management Functions
jmf.add_device_info(builder, device_id, attrs)
Adds device information.
local builder, device_info = jmf.add_device_info(builder, "Press001", {
DeviceType = "DigitalPress",
Manufacturer = "ExampleCorp"
})jmf.add_device_status(builder, device_id, attrs)
Adds device status information.
local builder, device_status = jmf.add_device_status(builder, "Press001", {
Status = "Running",
Speed = "1000",
Counter = "12500"
})jmf.add_device_capability(builder, device_id, attrs)
Adds device capability information.
local builder, capability = jmf.add_device_capability(builder, "Press001", {
MediaType = "Paper",
ColorSpace = "CMYK",
Resolution = "2400"
})Subscription Functions
jmf.add_subscription(builder, url, attrs)
Adds a subscription for receiving notifications.
local builder, subscription = jmf.add_subscription(builder, "http://example.com/callback", {
Type = "Status",
RepeatTime = "10"
})jmf.add_filtered_subscription(builder, url, filters, attrs)
Adds a subscription with filters.
local builder, filtered_sub = jmf.add_filtered_subscription(builder,
"http://example.com/callback",
{{DeviceID = "Press001"}},
{Type = "Status"}
)jmf.add_recurring_subscription(builder, url, repeat_seconds, attrs)
Adds a subscription that repeats at regular intervals.
local builder, recurring_sub = jmf.add_recurring_subscription(builder,
"http://example.com/callback",
30, -- repeat every 30 seconds
{Type = "Status"}
)jmf.update_subscription(builder, subscription_id, updates)
Updates an existing subscription.
Returns: {builder, updated_subscription} or {false, error_message}
local builder, updated_sub = jmf.update_subscription(builder, subscription.id, {
RepeatTime = "60" -- Change interval to 60 seconds
})jmf.add_persistent_channel(builder, channel_attrs)
Adds a persistent communication channel.
local builder, channel = jmf.add_persistent_channel(builder, {
ChannelID = "persistent_001",
URL = "ws://example.com/websocket"
})jmf.remove_subscription(builder, subscription_id)
Removes an existing subscription.
Returns: {builder} or {false, error_message}
local builder = jmf.remove_subscription(builder, subscription.id)Advanced Queue Management Functions
jmf.add_queue_filter(builder, queue_id, filter_attrs)
Adds filtering criteria for queue entries.
local builder, filter = jmf.add_queue_filter(builder, "MainQueue", {
JobType = "BusinessCard",
Priority = "High"
})jmf.add_job_phase(builder, queue_entry_id, phase_attrs)
Adds phase information to a queue entry.
local builder, phase = jmf.add_job_phase(builder, entry.id, {
Phase = "Printing",
Status = "InProgress",
StartTime = "2025-09-23T10:00:00Z"
})jmf.add_preview(builder, parent_id, preview_attrs)
Adds preview information to messages.
local builder, preview = jmf.add_preview(builder, message.id, {
PreviewType = "Thumbnail",
URL = "http://example.com/preview.jpg"
})jmf.add_queue_container(builder, queue_id, queue_attrs)
Adds a queue container for organizing queues.
local builder, container = jmf.add_queue_container(builder, "PrintQueue", {
QueueType = "Production",
MaxEntries = "100"
})jmf.add_status_query_params(builder, query_id, params)
Adds parameters to status queries.
local builder, params = jmf.add_status_query_params(builder, query.id, {
DeviceDetails = "true",
IncludeQueue = "true"
})jmf.add_queue_submission_params(builder, command_id, params)
Adds parameters for queue submission commands.
local builder, params = jmf.add_queue_submission_params(builder, command.id, {
Priority = "50",
ActivationTime = "2025-09-23T10:00:00Z"
})Query Functions
jmf.add_resource_query(builder, resource_type, attrs)
Adds a query for specific resource types.
local builder, resource_query = jmf.add_resource_query(builder, "Media", {
ID = "rq001",
Scope = "Available"
})jmf.add_known_messages_query(builder, attrs)
Adds a query for known message types.
local builder, known_query = jmf.add_known_messages_query(builder, {
ID = "km001"
})Validation and Management Functions
jmf.validate(builder)
Validates the JMF message structure and content.
Returns: {ok, validation_result} or {false, error_message}
local ok, result = jmf.validate(builder)
if ok then
print("Validation passed:", result)
else
print("Validation failed:", result)
endjmf.get_message(builder, message_id)
Retrieves an existing message by ID.
Returns: {true, message_data} or {false, error_message}
local ok, message = jmf.get_message(builder, query.id)
if ok then
print("Message found:", message)
endjmf.update_message(builder, message_id, updates)
Updates an existing message with new attributes.
Returns: {builder, updated_message} or {false, error_message}
local builder, updated_query = jmf.update_message(builder, query.id, {
Priority = "High"
})Output Functions
jmf.render(builder, options)
Renders the JMF builder to XML string.
Parameters:
builder(userdata): JMF builder instanceoptions(table): Rendering options - passnilor{}if none
Returns: xml_string - Complete JMF XML document
local xml = jmf.render(builder, {})jmf.to_graph(builder)
Converts builder to graph representation.
Parameters:
builder(userdata): JMF builder instance
Returns: graph_data - Graph structure
Complete JMF Example
-- Create JMF message from controller
local builder = jmf.new("Controller001", {
TimeStamp = "2025-09-23T10:00:00Z"
}, {})
-- Query device status
local builder, status_query = jmf.add_query(builder, "Status", {
ID = "q001",
DeviceID = "Press001"
})
-- Add queue status
local builder, queue_status = jmf.add_queue_status(builder, "MainQueue", {
Status = "Running",
QueueSize = "3"
})
-- Add a job to queue
local builder, queue_entry = jmf.add_queue_entry(builder, "MainQueue", {
JobID = "BC-2025-001",
Priority = "50",
Status = "Waiting"
})
-- Generate XML
local xml = jmf.render(builder, {})
print("Generated JMF:", xml)Node and Message References
Both modules return reference objects that contain useful information:
JDF Node References
local builder, component = jdf.add_component(builder, nil, attrs)
-- Access reference properties
print("Component ID:", component.id) -- "COMP_20250923_001"
print("Component Type:", component.type) -- "Component"
print("Attributes:", component.attributes) -- Original attributes
-- Use as parent for other resources
local builder, layout = jdf.add_layout(builder, component.id, layout_attrs)JMF Message References
local builder, query = jmf.add_query(builder, "Status", attrs)
-- Access reference properties
print("Query ID:", query.id) -- "QUERY_20250923_001"
print("Message Type:", query.type) -- "Query"
print("Attributes:", query.attributes) -- Original attributes
-- Use for responses
local builder, response = jmf.add_response(builder, query.id, response_attrs)Error Handling
Both modules use consistent error handling patterns:
-- Functions return false and error message on failure
local ok, builder_or_error = jdf.new("Invalid Job", invalid_attrs)
if not ok then
error("Failed to create JDF builder: " .. builder_or_error)
end
-- Successful operations return the expected values
local builder, node_ref = jdf.add_component(builder, nil, valid_attrs)Integration with Print Production
These modules are particularly useful for:
- Job Template Generation: Create standardized JDF templates for common print jobs
- Device Communication: Generate JMF messages for printer status monitoring
- Workflow Automation: Build complex print production workflows programmatically
- Quality Control: Create JDF documents with specific quality parameters
- Production Reporting: Generate JMF status reports and notifications
Best Practices
- Hierarchical Structure: Use node references to build proper parent-child relationships
- Error Handling: Always check return values for error conditions
- Resource Organization: Group related resources under appropriate parent components
- Intent vs Implementation: Use intent resources when possible for flexibility
- Documentation: Include descriptive names and metadata in your documents
The JDF and JMF builder modules provide powerful tools for integrating with print production workflows while maintaining the flexibility and simplicity of Lua scripting.