#lang racket/base
(require racket/class
(planet clements/sxml2:1)
"private/sxml.rkt")
(provide atom<%>
atom)
(define atom<%>
(interface ()
is-feed? get-sxml get-raw-sxml get-id get-title get-updated get-link get-raw-link get-entries get-raw-entries get-tag-value ))
(define atom%
(class* object% (atom<%>)
(init-field sxml)
(define root
(cond [(and (pair? sxml) (memq (car sxml) '(atom:feed atom:entry))) sxml]
[else (car* ((sxpath '((*or* atom:feed atom:entry))) sxml))]))
(unless root (error 'atom% "invalid Atom document: ~e" sxml))
(super-new)
(define/public (is-feed?)
(eq? 'atom:feed (sxml:element-name root)))
(define/public (get-sxml) root)
(define/public (get-raw-sxml) sxml)
(define/public (get-id)
(get1 'atom:get-id 'atom:id))
(define/public (get-title)
(get1 'atom:get-title 'atom:title))
(define/public (get-updated)
(get1 'atom:get-updated 'atom:updated))
(define/public (get-link rel [default not-given])
(let ([result ((sxpath `((atom:link (@ rel (equal? ,rel))) @ href *text*)) root)])
(cond [(pair? result) (car result)]
[else (do-default default (error 'atom:get-link "link ~s not found" rel))])))
(define/public (get-raw-link rel [default not-given])
(let ([result ((sxpath `((atom:link (@ rel (equal? ,rel))))) root)])
(cond [(pair? result) (car result)]
[else (do-default default (error 'atom:get-raw-link "link ~s not found" rel))])))
(define/public (get-entries)
(for/list ([entry (in-list (get-raw-entries))])
(new atom% (sxml entry))))
(define/public (get-raw-entries)
((sxpath '(atom:entry)) root))
(define/public (get-tag-value tag [default not-given])
(get1 'atom:get-tag-value tag default))
(define/private (get1 who tag [default not-given])
(let ([result ((sxpath `(,tag *text*)) root)])
(cond [(pair? result) (car result)]
[else (do-default default (error who "element `~a' not found" tag))])))
))
(define (car* x)
(and (pair? x) (car x)))
(define (atom sxml)
(new atom% (sxml sxml)))