Flickr Atom Reader

 

スクリプト

FlickrAtomReader.fx

package net.javainthebox.flickr;

import javafx.ext.swing.SwingList;
import javafx.ext.swing.SwingListItem;
import javafx.ext.swing.SwingScrollPane;
import javafx.scene.Scene;
import javafx.stage.Stage;

// リストで表示する項目
var items: SwingListItem[];

var rssReader = AtomReader {
    url: "http://api.flickr.com/services/feeds/photos_public.gne?id=57085156@N00&lang=en-us&format=atom"
    
    onDone: function(infos: PhotoInfo[]) {
        // パースが終了したら、HTMLでリストの項目を表示する
        for (info in infos) {
            var item = SwingListItem {
                text: "<html><p>{info.title}</p><img src='{info.thumbnailUrl}' /></html>"
            }
            insert item into items;
        }
    }
}
rssReader.read();
 
Stage {
    title: "FlickrAtomReader"
    scene: Scene {
        width: 400
        height: 600
        content: [
            // リストをスクロールペインで表示する
            SwingScrollPane {
                width: 400
                height: 600
                
                view: SwingList {
                    items: bind items
                }
            }
        ]
    }
}

AtomReader.fx

package net.javainthebox.flickr;
 
import javafx.data.pull.Event;
import javafx.data.pull.PullParser;
import javafx.data.xml.QName;
import javafx.io.http.HttpRequest;
 
import java.io.InputStream;
import java.lang.Exception;
 
public class AtomReader {
    public-init var url: String;
 
    // 処理が終了した後にコールするコールバック関数
    public var onDone: function(:PhotoInfo[]): Void;
 
    // サムネイルのURLを取り出すための正規表現
    def pattern = java.util.regex.Pattern.compile("http://farm.*_m.jpg");
    
    public function read(): Void {
        var request = HttpRequest {
            location: url
 
            // 入力の解析はparse関数で行う
            onInput: parse
 
            // エラー処理
            onException: function(ex: Exception) {
                println("exception: {ex.getMessage()}");
            }
        };
        request.enqueue();
    }
 
    // Atomのパース
    function parse(stream: InputStream) {
        var infos: PhotoInfo[];
        var info: PhotoInfo;
        var inEntry: Boolean;
 
        var parser = PullParser {
            documentType: PullParser.XML;
            input: stream
            
            onEvent: function(event: Event) {
                if (event.type == PullParser.START_ELEMENT) {
                    if (event.qname.name == "entry") {
                        // <entry>の開始
                        // 新たなPhotoInfoオブジェクトを生成する
                        inEntry = true;
                        info = PhotoInfo {};
                    }
                }
                if (event.type == PullParser.END_ELEMENT) {
                    if (event.qname.name == "entry") {
                        // </entry>の場合
                        // 作成したPhotoInfoオブジェクトをシーケンスに追加
                        inEntry = false;
                        insert info into infos;
                    } else if (inEntry and event.qname.name == "title") {
                        // </title>の場合
                        // PhotoInfoオブジェクトのtitleを設定
                        info.title = event.text;
                    } else if (inEntry and event.qname.name == "content") {
                        // </content>の場合
                        // 正規表現を用いて、サムネイルのURLを取り出し、
                        // PhotoInfoオブジェクトのthumbnailUrlに設定
                        var matcher = pattern.matcher(event.text);
                        if (matcher.find()) {
                            var url = matcher.group();
                            info.thumbnailUrl = url.replaceAll("_m", "_t");
                        }
                    }
                }
            }
        }
        // パースの開始
        parser.parse();
        
        if (onDone != null) {
            // パースが終了したら、コールバック関数をコールする
            onDone(infos);
        }
        
        stream.close();
    }
}

PhotoInfo.fx

package net.javainthebox.flickr;
 
public class PhotoInfo {
    public var title: String;
    public var thumbnailUrl: String;
}