前回作ったやつはフィードの追加が出来なかったのでフィードが追加できるように変更した。ただし、追加したフィードの保存機能はなし。なので、別のページにいったり、ブラウザを閉じるとその内容は失われる。
できあがったもの
http://rsstest.dkami.staxapps.net/
フィードの追加は左のテキストフィールドに入力し、追加ボタンを押す。HTMLからフィード探して追加するような機能はついてないので、直接フィードのURLを入力する必要がある
ソース、まずhtmlから、ファイル名はHomePage.html
<html> <head> <title>Wicket Homepage</title> </head> <body> <span wicket:id="feedback"></span> <table style="width:100%; height: 100%;"> <tr> <td style="width:30%; height:100%; vertical-align:top" wicket:id="feedParent"> <div wicket:id="feedList"> <a wicket:id="feedLink"><span wicket:id="linkText">Java Category</span></a> </div> <br /> <form wicket:id="addFeedForm"> <input type="text" style="width:100%", wicket:id="addFeedField" /> <input type="button" value="追加" wicket:id="addFeedButton" /> </form> </td> <td style="width:70%; height:100%; text-align:left; vertical-align:top" wicket:id="entryParent"> <dl wicket:id="entryList"> <dt>●<a href="http://test.com" wicket:id="entryLink">Entry Title</a> <span wicket:id="publishDate">2009/1/27</span></dt> <dd><span wicket:id="entryDesc">Entry Description</span></dd> </dl> </td> </tr> </table> </body> </html>
次に対応するJavaのソース、ファイル名はHomePage.java
package example; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.markup.html.panel.FeedbackPanel; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.ajax.markup.html.form.AjaxButton; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.ajax.AjaxRequestTarget; import com.sun.syndication.feed.synd.SyndEntry; import com.sun.syndication.feed.synd.SyndFeed; import com.sun.syndication.fetcher.FeedFetcher; import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher; import com.sun.syndication.fetcher.FetcherException; import com.sun.syndication.io.FeedException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.ArrayList; import java.util.Calendar; import java.net.URL; import java.io.IOException; public class HomePage extends WebPage { private static final long serialVersionUID = 1L; //現在表示しているフィードのURL private String feedURL = ""; private List<FeedLink> feedList; public HomePage() { feedList = new ArrayList<FeedLink>(); feedList.add(new FeedLink("Javaカテゴリ", "http://k.hatena.ne.jp/keywordblog/Java?mode=rss")); feedList.add(new FeedLink("Wicketカテゴリ", "http://k.hatena.ne.jp/keywordblog/Wicket?mode=rss")); //エラーメッセージを表示するFeedbackPanel final FeedbackPanel feedback = new FeedbackPanel("feedback"); //Ajaxで更新可能にする feedback.setOutputMarkupId(true); //フィードに含まれるエントリの一覧を表示するListView ListView entryListView = createEntryListView(); //ListViewの親コンポーネント(AjaxでListViewを更新するのに必要) WebMarkupContainer entryParent = new WebMarkupContainer("entryParent"); //Ajaxで更新可能にする entryParent.setOutputMarkupId(true); //ListViewの親コンポーネント final WebMarkupContainer feedParent = new WebMarkupContainer("feedParent"); //Ajaxで更新可能にする feedParent.setOutputMarkupId(true); //フィードの一覧を表示するListView ListView feedListView = createFeedListView(entryParent, feedback); //フィード追加用のフォーム Form addFeedForm = new Form("addFeedForm"); final TextField<String> addFeedField = new TextField<String>("addFeedField", new Model<String>()); addFeedField.setOutputMarkupId(true); AjaxButton addFeedButton = new AjaxButton("addFeedButton"){ @Override public void onSubmit(AjaxRequestTarget target, Form form){ String url = addFeedField.getModelObject(); try{ //フィードのURLからタイトルを取得する FeedFetcher fetcher = new HttpURLFeedFetcher(); SyndFeed feed = fetcher.retrieveFeed(new URL(url)); String title = feed.getTitle(); FeedLink feedLink = new FeedLink(title, url); feedList.add(feedLink); target.addComponent(feedParent); }catch(FetcherException e){ error("フィードの取得に失敗しました: " + e.getMessage()); }catch(IOException e){ error("フィードの取得に失敗しました: " + e.getMessage()); }catch(FeedException e){ error("フィードの取得に失敗しました: " + e.getMessage()); }finally{ target.addComponent(feedback); addFeedField.setModelObject(""); target.addComponent(addFeedField); } } }; addFeedForm.add(addFeedField); addFeedForm.add(addFeedButton); feedParent.add(feedListView); feedParent.add(addFeedForm); entryParent.add(entryListView); add(feedback); add(feedParent); add(entryParent); } //フィードのエントリ一覧を表示するListViewを作成する private ListView createEntryListView(){ IModel<List<SyndEntry>> entryListModel = new LoadableDetachableModel<List<SyndEntry>>(){ protected List<SyndEntry> load(){ //エントリの一覧を返す return getEntryList(); } }; ListView listView = new ListView( "entryList", entryListModel) { @Override protected void populateItem(ListItem item) { SyndEntry entry = (SyndEntry)item.getModelObject(); item.add(new ExternalLink("entryLink", entry.getLink(), entry.getTitle())); Date updateDate = entry.getUpdatedDate(); if(updateDate == null) updateDate = entry.getPublishedDate(); //時間を日本時間に合わせる SimpleDateFormat format = new SimpleDateFormat( "yyyy-MM-dd HH:mm"); Calendar calendar = Calendar.getInstance(); calendar.setTime(updateDate); calendar.add(Calendar.HOUR_OF_DAY, 9); updateDate = calendar.getTime(); item.add(new Label("publishDate", format.format( updateDate))); String description = entry.getDescription().getValue(); //ディスクリプションに含まれるタグを取り除く description = description.replaceAll("<[^>]+>", "").replaceAll("</[^>+]>", ""); item.add(new Label( "entryDesc", description)); } }; return listView; } private List<SyndEntry> getEntryList(){ if(feedURL.trim().length() == 0){ //フィードのURLが空文字列なら空のリストを返す return new ArrayList<SyndEntry>(); } try{ //フィードのURLからフィードのエントリ一覧を取得し返す FeedFetcher fetcher = new HttpURLFeedFetcher(); SyndFeed feed = fetcher.retrieveFeed(new URL(feedURL)); return feed.getEntries(); }catch(FetcherException e){ error("フィードの取得に失敗しました: " + e.getMessage()); }catch(IOException e){ error("フィードの取得に失敗しました: " + e.getMessage()); }catch(FeedException e){ error("フィードの取得に失敗しました: " + e.getMessage()); } return new ArrayList<SyndEntry>(); } private ListView createFeedListView(final WebMarkupContainer entryParent, final FeedbackPanel feedback){ IModel<List<FeedLink>> feedListModel = new LoadableDetachableModel<List<FeedLink>>(){ protected List<FeedLink> load(){ //フィードの一覧を返す return getFeedList(); } }; ListView listView = new ListView("feedList", feedListModel){ @Override protected void populateItem(ListItem item){ final FeedLink feedLink = (FeedLink)item.getModelObject(); Label label = new Label("linkText", feedLink.getText()); AjaxLink link = new AjaxLink("feedLink"){ @Override public void onClick(AjaxRequestTarget target){ //フィードのURLを書き換える feedURL = feedLink.getURL(); //ListViewを更新 target.addComponent(entryParent); //FeedbackPanelを更新 target.addComponent(feedback); } }; link.add(label); item.add(link); } }; return listView; } private List<FeedLink> getFeedList(){ return feedList; } static class FeedLink{ private final String text; private final String url; public FeedLink(String text, String url){ this.text = text; this.url = url; } public String getText(){ return this.text; } public String getURL(){ return this.url; } } }
アプリケーションクラスとフィルタマッピングは省略