Permalink
Browse files

switch to gavagai 0.3.0 and split the fetcher as a separate project

  • Loading branch information...
ngrunwald committed Jan 14, 2013
1 parent 390b9eb commit f0d41c70a77f77e6d495a940a4f35ddddd91101c
Showing with 62 additions and 126 deletions.
  1. +15 −22 README.md
  2. +3 −3 project.clj
  3. +0 −66 src/clj_rome/fetcher.clj
  4. +29 −22 src/clj_rome/reader.clj
  5. +15 −13 test/clj_rome/test/reader.clj
View
@@ -7,28 +7,35 @@
`clj-rome` is available as a Maven artifact from
[Clojars](http://clojars.org/clj-rome):
```clojure
-[clj-rome "0.3.1"]
+[clj-rome "0.4.0"]
```
## Usage
```clojure
- ;; build-feed will automaticaly dispatch on an xml string, a filepath or an url
- (use 'clj-rome.reader)
- (def feed (build-feed "test/clj_rome/test/feeds/lacuisinededoria.xml"))
+;; build-feed will automaticaly dispatch on an xml string, a filepath, a reader or an url
+(use 'clj-rome.reader)
+(def feed (build-feed "test/clj_rome/test/feeds/lacuisinededoria.xml"))
```
The return value of `build-feed` is a lazy structure (see [lazymap](https://github.com/ngrunwald/lazymap)) recursively translated from Java to Clojure with [gavagai](https://github.com/ngrunwald/gavagai). It has keys corresponding to the Java getter methods. If you prefer plain greedy maps, you can use build-feed with an option map:
```clojure
- (def feed (build-feed "test/clj_rome/test/feeds/lacuisinededoria.xml" {:lazy? false}))
+(def feed (build-feed "test/clj_rome/test/feeds/lacuisinededoria.xml" {:lazy? false}))
+```
+
+There is also a `raw?` option to get the java SyndFeed object, if you need to modify it.
+
+```
+;; this is equivalent to build-feed with no option
+(convert-feed (build-feed "test/clj_rome/test/feeds/lacuisinededoria.xml"))
```
Here are some exemples to give you an idea of what is in the feed and each entry:
```clojure
(keys feed)
=> (:foreign-markup :published-date :entries :preserving-wire-feed?
:copyright :link :contributors :author :supported-feed-types
- :feed-type :image :language :title :uri :categories :original :modules
+ :feed-type :image :language :title :uri :categories :modules
:interface :links :encoding :authors :title-ex :description
:description-ex)
@@ -94,26 +101,12 @@ Here are some exemples to give you an idea of what is in the feed and each entry
:contents []}
```
- You can use the ROME fetcher to retrieve a feed from the web with caching and conditional GET handled for you:
-```clojure
- ;; creating a caching fetcher
- ;; type can be any of :hash-map, :linked-hash-map, :disk
- (use 'clj-rome.fetcher)
- (def fetcher (build-url-fetcher :disk "/tmp/cache"))
-
- ;; you can attach a listener to your fetcher
- (add-listener fetcher (fn [event] (println event)))
-
- ;; using the fetcher with a cache to fetch a feed
- (def feed
- (with-fetcher fetcher
- (retrieve-feed "http://www.atomenabled.org/atom.xml")))
-```
+If you need to use the wrapper for the ROME fetcher, it is packaged separately as `clj-rome-fetcher`. You can find it on [Github](https://github.com/ngrunwald/clj-rome-fetcher).
For more documentation on ROME, see the [ROME javadocs](http://www.jarvana.com/jarvana/view/net/java/dev/rome/rome/1.0.0/rome-1.0.0-javadoc.jar!/index.html).
## License
-Copyright (C) 2012 Nils Grunwald
+Copyright (C) 2012, 2013 Nils Grunwald
Distributed under the Eclipse Public License, the same as Clojure.
View
@@ -1,9 +1,9 @@
-(defproject clj-rome "0.3.2-SNAPSHOT"
+(defproject clj-rome "0.4.0-SNAPSHOT"
:description "A Clojure wrapper for the ROME feed parsing and manipulation library"
:url "https://github.com/ngrunwald/clj-rome"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.4.0"]
[net.java.dev.rome/rome "1.0.0"]
- [net.java.dev.rome/rome-fetcher "1.0.0"]
- [gavagai "0.2.1"]])
+ [gavagai "0.3.0"]]
+ :warn-on-reflection true)
View
@@ -1,66 +0,0 @@
-(ns clj-rome.fetcher
- (:import (com.sun.syndication.fetcher.impl HttpURLFeedFetcher DiskFeedInfoCache
- LinkedHashMapFeedInfoCache HashMapFeedInfoCache)
- (com.sun.syndication.fetcher FetcherListener)
- (java.net URL))
- (:require [clojure.java.io :as io]
- [gavagai.core :as gav]
- [clj-rome.reader :as r]))
-
-(def ^{:dynamic true} *fetcher*)
-
-(defn create-dir
- [path]
- (let [f (io/file path)]
- (.mkdirs f)
- (str f)))
-
-(defn build-feed-cache
- "builds a cache instance based on type:
- - :hash-map
- - :linked-hash-map
- - :disk path"
- [type & args]
- (case type
- :hash-map (HashMapFeedInfoCache.)
- :linked-hash-map (LinkedHashMapFeedInfoCache.)
- :disk (DiskFeedInfoCache. (create-dir (first args)))))
-
-(defn build-url-fetcher
- "builds an HttpURLFeedFetcher. Can take a cache type param
- (see build-feed-cache)"
- ([]
- (HttpURLFeedFetcher.))
- ([& args]
- (HttpURLFeedFetcher. (apply build-feed-cache args))))
-
-(defn retrieve-feed
- "retrieves a feed from a fetcher or the default one."
- ([fetcher url]
- (gav/translate (.retrieveFeed fetcher (URL. (str url))) {:nspace r/local-ns}))
- ([url]
- (retrieve-feed *fetcher* url)))
-
-(defn add-listener
- "adds a listener to the given fetcher object.
- Returns a FetcherListener object. Use it with
- remove-listener."
- ([fetcher cb]
- (let [listener (proxy [FetcherListener] []
- (fetcherEvent [event] (cb event)))]
- (.addFetcherEventListener fetcher listener)
- listener))
- ([cb]
- (add-listener *fetcher* cb)))
-
-(defn remove-listener
- "removes a listener from the given fetcher"
- ([fetcher listener]
- (.removeFetcherEventListener fetcher listener))
- ([listener]
- (remove-listener *fetcher* listener)))
-
-(defmacro with-fetcher
- [fetcher & body]
- `(binding [clj-rome.fetcher/*fetcher* ~fetcher]
- ~@body))
View
@@ -1,12 +1,10 @@
(ns clj-rome.reader
(:import (java.net URL)
(com.sun.syndication.io SyndFeedInput XmlReader)
- (java.io StringReader FileReader))
+ (java.io StringReader FileReader Reader))
(:require [clojure.string :as str]
[gavagai.core :as gav]))
-(def local-ns (find-ns 'clj-rome.reader))
-
(defprotocol Feedable
(make-reader [arg]))
@@ -25,29 +23,38 @@
(extend-type java.io.Reader
Feedable
- (make-reader
- [reader]
- reader))
+ (make-reader [reader] reader))
+
+(def feed-translator
+ (gav/register-converters
+ {:exclude [:class]}
+ [["com.sun.syndication.feed.synd.SyndFeedImpl"]
+ ["com.sun.syndication.feed.synd.SyndContentImpl"]
+ ["com.sun.syndication.feed.synd.SyndImageImpl"]
+ ["com.sun.syndication.feed.module.DCModuleImpl"]
+ ["com.sun.syndication.feed.module.DCSubjectImpl"]
+ ["com.sun.syndication.feed.module.SyModuleImpl"]
+ ["com.sun.syndication.feed.synd.SyndEntryImpl"]
+ ["com.sun.syndication.feed.synd.SyndLinkImpl"]
+ ["com.sun.syndication.feed.synd.SyndPersonImpl"]
+ ["com.sun.syndication.feed.synd.SyndEnclosureImpl"]
+ ["com.sun.syndication.feed.synd.SyndCategoryImpl"]]))
-(gav/register-converters
- ["com.sun.syndication.feed.synd.SyndFeedImpl" :exclude [:class] :add {:original identity}]
- ["com.sun.syndication.feed.synd.SyndContentImpl" :exclude [:class]]
- ["com.sun.syndication.feed.synd.SyndImageImpl" :exclude [:class]]
- ["com.sun.syndication.feed.module.DCModuleImpl" :exclude [:class]]
- ["com.sun.syndication.feed.module.DCSubjectImpl" :exclude [:class]]
- ["com.sun.syndication.feed.module.SyModuleImpl" :exclude [:class]]
- ["com.sun.syndication.feed.synd.SyndEntryImpl" :exclude [:class :source]]
- ["com.sun.syndication.feed.synd.SyndLinkImpl" :exclude [:class]]
- ["com.sun.syndication.feed.synd.SyndPersonImpl" :exclude [:class]]
- ["com.sun.syndication.feed.synd.SyndEnclosureImpl" :exclude [:class]]
- ["com.sun.syndication.feed.synd.SyndCategoryImpl" :exclude [:class]])
+(def convert-feed
+ "converts an object from ROME to its Clojure immutable translation"
+ (partial gav/translate feed-translator))
(defn build-feed
- "builds a SyndFeedImpl from an url, a filepath or a XML string"
- ([arg {:keys [lazy?] :as opts}]
+ "builds a SyndFeedImpl from an Url, a filepath, Reader or a XML string
+ It takes 2 options
+ :lazy? (set to false to get a realized map)
+ :raw? (set to true to get the raw java SyndFeed)"
+ ([arg {:keys [lazy? raw?] :as opts}]
(let
- [reader (make-reader arg)
+ [^Reader reader (make-reader arg)
feed (.build (SyndFeedInput.) reader)]
- (gav/translate feed (assoc opts :nspace local-ns))))
+ (if raw?
+ feed
+ (convert-feed feed opts))))
([arg]
(build-feed arg {})))
@@ -2,21 +2,23 @@
(:use [clj-rome.reader] :reload)
(:use [clojure.test]))
-(def feed (build-feed "test/clj_rome/test/feeds/lacuisinededoria.xml"))
+(let [feed-path "test/clj_rome/test/feeds/lacuisinededoria.xml"
+ feed (build-feed feed-path)]
+ (deftest options
+ (is (instance? lazymap.core.LazyPersistentMap feed))
+ (let [f2 (build-feed feed-path {:lazy? false})]
+ (is (instance? clojure.lang.PersistentHashMap f2)))
+ (let [raw-obj (build-feed feed-path {:raw? true})]
+ (is (not (map? raw-obj)))))
-(deftest lazyness
- (is (instance? lazymap.core.LazyPersistentMap feed))
- (let [f2 (build-feed "test/clj_rome/test/feeds/lacuisinededoria.xml" {:lazy? false})]
- (is (instance? clojure.lang.PersistentHashMap f2))))
+ (deftest test-feed-from-path
+ (is (= "rss_2.0" (:feed-type feed))))
-(deftest test-feed-from-path
- (is (= "rss_2.0" (:feed-type feed))))
+ (deftest test-feed-from-string
+ (is (= "rss_2.0" (:feed-type (build-feed (slurp feed-path))))))
-(deftest test-feed-from-string
- (is (= "rss_2.0" (:feed-type (build-feed (slurp "test/clj_rome/test/feeds/lacuisinededoria.xml"))))))
+ (def entry (first (:entries feed)))
-(def entry (first (:entries feed)))
-
-(deftest test-entry
- (is "Canard" (-> entry (:categories) (first) (:name))))
+ (deftest test-entry
+ (is "Canard" (-> entry (:categories) (first) (:name)))))

0 comments on commit f0d41c7

Please sign in to comment.