From f0d41c70a77f77e6d495a940a4f35ddddd91101c Mon Sep 17 00:00:00 2001 From: Nils Grunwald Date: Mon, 14 Jan 2013 16:01:19 +0100 Subject: [PATCH] switch to gavagai 0.3.0 and split the fetcher as a separate project --- README.md | 37 ++++++++------------ project.clj | 6 ++-- src/clj_rome/fetcher.clj | 66 ----------------------------------- src/clj_rome/reader.clj | 51 +++++++++++++++------------ test/clj_rome/test/reader.clj | 28 ++++++++------- 5 files changed, 62 insertions(+), 126 deletions(-) delete mode 100644 src/clj_rome/fetcher.clj diff --git a/README.md b/README.md index c5d9a5e..050b650 100644 --- a/README.md +++ b/README.md @@ -7,20 +7,27 @@ `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: @@ -28,7 +35,7 @@ Here are some exemples to give you an idea of what is in the feed and each entry (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. diff --git a/project.clj b/project.clj index 7614597..96a0fc1 100644 --- a/project.clj +++ b/project.clj @@ -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) diff --git a/src/clj_rome/fetcher.clj b/src/clj_rome/fetcher.clj deleted file mode 100644 index d0f7c8a..0000000 --- a/src/clj_rome/fetcher.clj +++ /dev/null @@ -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)) diff --git a/src/clj_rome/reader.clj b/src/clj_rome/reader.clj index a610e23..65a46f6 100644 --- a/src/clj_rome/reader.clj +++ b/src/clj_rome/reader.clj @@ -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 {}))) diff --git a/test/clj_rome/test/reader.clj b/test/clj_rome/test/reader.clj index 9c162a7..2be3463 100644 --- a/test/clj_rome/test/reader.clj +++ b/test/clj_rome/test/reader.clj @@ -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)))))