Hatena::ブログ(Diary)

明日の鍵

2012-02-01

Javaの正規表現をテストするサイトを作ったよ

f:id:tomorrowkey:20120201225135p:image

作った

Java regex tester 
http://java-regex-tester.appspot.com/

Javaの正規表現を評価するサイトを作ったよ。


使ったライブラリとか

Slim3

https://sites.google.com/site/slim3appengine/

GAEだとslim3一択

jQuery: The Write Less, Do More, JavaScript Library

http://jquery.com/

jQueryないとjavascriptがめんどい

zClip :: jQuery ZeroClipboard

http://www.steamdev.com/zclip/

クリップボードにコピーするためのjQueryプラグイン

Adventures in Programming » Blog Archive » Toast Notifications Using jQuery

http://shawntabai.com/wp/2011/09/06/toast-notifications-using-jquery/

AndroidのToastライクな表示をするためのコード

Google Web Fonts

http://www.google.com/webfonts

Gudeaというフォントを使いました。

チェックボックスをつけて、コードをコピーするだけなんでとても簡単です。

見た目

がんばってCSS書いたけど、Bootstrap使ってかっこよくしたいなー。

あー、faviconださい。

あとは脱GAEしたい。

更新しました

  • 正規表現エラーだった場合にレスポンスが帰ってこない不具合を直しました
  • Bootstrap使いました
  • Matchesも表示するようにしました
  • Groupのハイライトを色分けしました

2012-02-05 20:45 追記

更新しました

  • Findがすべて抽出されないバグを修正しました

2012-02-07 08:49 追記

ソースを公開しました

tomorrowkey/RegularExpressionTester - GitHub 
https://github.com/tomorrowkey/RegularExpressionTester

いい加減ライセンスの表記をちゃんとしないとなー

2012-02-09 08:40 追記

2011-08-09

Google Spreadsheets Data APIを使う 参照編

**Google Spreadsheet Data APIとは

GoogleのサービスをプログラムからアクセスできるGoogle Data APIのGoogle SpreadsheetsにアクセスするためのAPI

Google Data API - Google Code 
http://code.google.com/intl/ja/apis/gdata/
Google スプレッドシートの API とツール - Google Code 
http://code.google.com/intl/ja/apis/spreadsheets/

Google Data APIサイトには各言語から簡単にアクセスするためのライブラリが公開されています。

Java JavaScript Python .NETなど

ライブラリのダウンロード

Google Data APIサイトからライブラリをダウンロードします。

Java用ライブラリはここからダウンロード

Downloads - gdata-java-client - Google Data Java Client Library - Google Project Hosting 
http://code.google.com/p/gdata-java-client/downloads/list

サンプル付きとソースコード付きの2つがあります。

ソースコード付きの gdata-src.java-1.45.0.zip をダウンロードします。

ライブラリのインポート

ダウンロードしたzipファイルを解凍し、jarファイルをビルドパスに追加します。

Google Spreadsheets Data APIにアクセスするためには以下のライブラリが必要です。

  • /gdata/java/lib/

gdata-core-1.0.jar

gdata-client-meta-1.0.jar

gdata-client-1.0.jar

gdata-media-1.0.jar

gdata-spreadsheet-meta-3.0.jar

gdata-spreadsheet-3.0.jar

gdata-docs-meta-3.0.jar

gdata-docs-3.0.jar

  • /gdata/java/deps/

google-collect-1.0-rc1.jar

認証

非公開のspreadsheetsにアクセスするためには認証をする必要があります。

認証方式にはOAuthとAuthStubとClientLoginがあります。

今回はデスクトップアプリケーション向けにClientLoginを使用します。

WebアプリケーションならばOAuthかAuthStubを使うべきです。

OAuthはここが参考になるかもしれません。*1

Google Data APIのOAUTHに挑戦 - 気楽なC#工房 
http://csfun.blog49.fc2.com/blog-entry-46.html
ClientLogin
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.util.AuthenticationException;

public class ClientLogin {

    private static final String APPLICATION_NAME = "tomorrowkey-" + ClientLogin.class.getSimpleName() + "-v1";

    public static void main(String[] args) {
        SpreadsheetService client = new SpreadsheetService(APPLICATION_NAME);
        String username = ArgumentUtil.getUsernameFromArgument(args);
        String password = ArgumentUtil.getPasswordFromArgument(args);
        try {
            client.setUserCredentials(username, password);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
    }
}

アプリケーション名(APPLICATION_NAME)は

[会社名]-[アプリケーション名]-[バージョン]

という命名規則に従って設定します。

この規則に従っていなくても動作はしますが…。

Google Spreadsheetにアクセスする場合は常にSpreadsheetServiceを使用します。

スプレッドシート一覧を取得する

自分のDocsに保存されているSpreadsheetsの名前を表示します。

ソースコード
import java.io.IOException;
import java.net.URL;
import java.util.List;

import com.google.gdata.client.spreadsheet.FeedURLFactory;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

public class PrintAllSpreadsheet {

    private static final String APPLICATION_NAME = "tomorrowkey-" + PrintAllSpreadsheet.class.getSimpleName() + "-v1";

    public static final void main(String[] args) {
        String username = ArgumentUtil.getUsernameFromArgument(args);
        String password = ArgumentUtil.getPasswordFromArgument(args);
        PrintAllSpreadsheet printAllSpreadsheet = new PrintAllSpreadsheet();
        printAllSpreadsheet.start(username, password);
    }

    private SpreadsheetService client;

    private void start(String username, String password) {
        try {
            client = new SpreadsheetService(APPLICATION_NAME);
            client.setUserCredentials(username, password);

            URL url = FeedURLFactory.getDefault().getSpreadsheetsFeedUrl();
            SpreadsheetFeed feed = client.getFeed(url, SpreadsheetFeed.class);
            List<SpreadsheetEntry> spreadsheetEntryList = feed.getEntries();
            for (SpreadsheetEntry spreadsheetEntry : spreadsheetEntryList) {
                System.out.println(spreadsheetEntry.getTitle().getPlainText());
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }
    }
}
実行結果
TEST
投票シート
CharSettings作成シート
第2回Android温泉 会計
第2回Android温泉企画
第2回Android温泉参加者一覧
第2回Android温泉アンケート
集まれGDDのdeb仲間
デコ美統計
やることリスト
都道府県別DL数
デ部T申し込みフォーム
検索データ
ガソリン
北海道日程
北海道日程

スプレッドシート名で検索して取得する

ソースコード
import java.io.IOException;
import java.net.URL;
import java.util.List;

import com.google.gdata.client.spreadsheet.FeedURLFactory;
import com.google.gdata.client.spreadsheet.SpreadsheetQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

public class PrintSearhedSpreadsheet {

    private static final String APPLICATION_NAME = "tomorrowkey-" + PrintSearhedSpreadsheet.class.getSimpleName() + "-v1";

    public static final void main(String[] args) {
        String username = ArgumentUtil.getUsernameFromArgument(args);
        String password = ArgumentUtil.getPasswordFromArgument(args);
        PrintSearhedSpreadsheet printSearhedSpreadsheet = new PrintSearhedSpreadsheet();
        printSearhedSpreadsheet.start(username, password);
    }

    private SpreadsheetService client;

    private void start(String username, String password) {
        try {
            client = new SpreadsheetService(APPLICATION_NAME);
            client.setUserCredentials(username, password);

            URL url = FeedURLFactory.getDefault().getSpreadsheetsFeedUrl();
            SpreadsheetQuery query = new SpreadsheetQuery(url);
            query.setTitleQuery("android");
            SpreadsheetFeed feed = client.query(query, SpreadsheetFeed.class);
            List<SpreadsheetEntry> spreadsheetEntryList = feed.getEntries();
            for (SpreadsheetEntry spreadsheetEntry : spreadsheetEntryList) {
                System.out.println(spreadsheetEntry.getTitle().getPlainText());
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }

    }
}
実行結果
第2回Android温泉 会計
第2回Android温泉企画
第2回Android温泉参加者一覧
第2回Android温泉アンケート

大文字/小文字は識別されないようですね。

ワークシート一覧を取得する

テスト用の「TEST」という名前のSpreadsheetと作成しました。

f:id:tomorrowkey:20110809122458p:image

ソースコード

import java.io.IOException;
import java.net.URL;
import java.util.List;

import com.google.gdata.client.spreadsheet.FeedURLFactory;
import com.google.gdata.client.spreadsheet.SpreadsheetQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

public class PrintAllWorksheet {

    private static final String APPLICATION_NAME = "tomorrowkey-" + PrintAllWorksheet.class.getSimpleName() + "-v1";

    public static final void main(String[] args) {
        String username = ArgumentUtil.getUsernameFromArgument(args);
        String password = ArgumentUtil.getPasswordFromArgument(args);
        PrintAllWorksheet printAllWorksheet = new PrintAllWorksheet();
        printAllWorksheet.start(username, password);
    }

    private SpreadsheetService client;

    private void start(String username, String password) {
        try {
            client = new SpreadsheetService(APPLICATION_NAME);
            client.setUserCredentials(username, password);
            SpreadsheetEntry spreadsheet = getSpreadsheet("TEST");

            URL url = spreadsheet.getWorksheetFeedUrl();
            WorksheetFeed feed = client.getFeed(url, WorksheetFeed.class);
            List<WorksheetEntry> worksheetEntryList = feed.getEntries();
            for (WorksheetEntry worksheetEntry : worksheetEntryList) {
                System.out.println(worksheetEntry.getTitle().getPlainText());
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }

    }

    private SpreadsheetEntry getSpreadsheet(String spreadsheetName) throws IOException,
            ServiceException {
        URL url = FeedURLFactory.getDefault().getSpreadsheetsFeedUrl();
        SpreadsheetQuery query = new SpreadsheetQuery(url);
        query.setTitleQuery(spreadsheetName);
        SpreadsheetFeed feed = client.query(query, SpreadsheetFeed.class);
        List<SpreadsheetEntry> spreadsheetEntryList = feed.getEntries();
        if (spreadsheetEntryList.isEmpty()) {
            throw new RuntimeException("not found spreadsheet '" + spreadsheetName + "'");
        }
        return spreadsheetEntryList.get(0);
    }
}
実行結果
東京
品川
新宿

ワークシート名で検索して取得する

ソースコード
import java.io.IOException;
import java.net.URL;
import java.util.List;

import com.google.gdata.client.spreadsheet.FeedURLFactory;
import com.google.gdata.client.spreadsheet.SpreadsheetQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.client.spreadsheet.WorksheetQuery;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

public class PrintSearchedWorksheet {

    private static final String APPLICATION_NAME = "tomorrowkey-" + PrintSearchedWorksheet.class.getSimpleName() + "-v1";

    public static final void main(String[] args) {
        String username = ArgumentUtil.getUsernameFromArgument(args);
        String password = ArgumentUtil.getPasswordFromArgument(args);
        PrintSearchedWorksheet printAllWorksheet = new PrintSearchedWorksheet();
        printAllWorksheet.start(username, password);
    }

    private SpreadsheetService client;

    private void start(String username, String password) {
        try {
            client = new SpreadsheetService(APPLICATION_NAME);
            client.setUserCredentials(username, password);
            SpreadsheetEntry spreadsheet = getSpreadsheet("TEST");

            URL url = spreadsheet.getWorksheetFeedUrl();
            WorksheetQuery query = new WorksheetQuery(url);
            query.setTitleQuery("品川");
            WorksheetFeed feed = client.query(query, WorksheetFeed.class);
            List<WorksheetEntry> worksheetEntryList = feed.getEntries();
            for (WorksheetEntry worksheetEntry : worksheetEntryList) {
                System.out.println(worksheetEntry.getTitle().getPlainText());
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }
    }

    private SpreadsheetEntry getSpreadsheet(String spreadsheetName) throws IOException,
            ServiceException {
        URL url = FeedURLFactory.getDefault().getSpreadsheetsFeedUrl();
        SpreadsheetQuery query = new SpreadsheetQuery(url);
        query.setTitleQuery(spreadsheetName);
        SpreadsheetFeed feed = client.query(query, SpreadsheetFeed.class);
        List<SpreadsheetEntry> spreadsheetEntryList = feed.getEntries();
        if (spreadsheetEntryList.isEmpty()) {
            throw new RuntimeException("not found spreadsheet '" + spreadsheetName + "'");
        }
        return spreadsheetEntryList.get(0);
    }
}
実行結果
品川

ワークシートからリスト一覧を取得する

リストとは行のことであり、spreadsheetをデータベースのように扱う場合、レコードのようなイメージになります。

import java.io.IOException;
import java.net.URL;
import java.util.List;

import com.google.gdata.client.spreadsheet.FeedURLFactory;
import com.google.gdata.client.spreadsheet.SpreadsheetQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.client.spreadsheet.WorksheetQuery;
import com.google.gdata.data.spreadsheet.CustomElementCollection;
import com.google.gdata.data.spreadsheet.ListEntry;
import com.google.gdata.data.spreadsheet.ListFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

public class PrintAllList {

    private static final String APPLICATION_NAME = "tomorrowkey-" + PrintAllList.class.getSimpleName() + "-v1";

    public static final void main(String[] args) {
        String username = ArgumentUtil.getUsernameFromArgument(args);
        String password = ArgumentUtil.getPasswordFromArgument(args);
        PrintAllList printAllWorksheet = new PrintAllList();
        printAllWorksheet.start(username, password);
    }

    private SpreadsheetService client;

    private void start(String username, String password) {
        try {
            client = new SpreadsheetService(APPLICATION_NAME);
            client.setUserCredentials(username, password);
            WorksheetEntry worksheet = getWorksheet("TEST", "東京");

            URL url = worksheet.getListFeedUrl();
            ListFeed feed = client.getFeed(url, ListFeed.class);
            List<ListEntry> listEntryList = feed.getEntries();
            for (ListEntry listEntry : listEntryList) {
                CustomElementCollection customElements = listEntry.getCustomElements();
                StringBuilder sb = new StringBuilder();
                sb.append("品目:").append(customElements.getValue("品目")).append(",");
                sb.append("価格:").append(customElements.getValue("価格")).append(",");
                sb.append("在庫:").append(customElements.getValue("在庫"));
                System.out.println(sb.toString());
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }

    }

    private WorksheetEntry getWorksheet(String spreadsheetName, String worksheetName)
            throws IOException, ServiceException {
        SpreadsheetEntry spreadsheet = getSpreadsheet(spreadsheetName);
        URL url = spreadsheet.getWorksheetFeedUrl();
        WorksheetQuery query = new WorksheetQuery(url);
        WorksheetFeed feed = client.query(query, WorksheetFeed.class);
        List<WorksheetEntry> worksheetEntryList = feed.getEntries();
        if (worksheetEntryList.isEmpty()) {
            throw new RuntimeException("not found worksheet '" + worksheetName + "' in '"
                    + spreadsheetName + "'");
        }
        return worksheetEntryList.get(0);
    }

    private SpreadsheetEntry getSpreadsheet(String spreadsheetName) throws IOException,
            ServiceException {
        URL url = FeedURLFactory.getDefault().getSpreadsheetsFeedUrl();
        SpreadsheetQuery query = new SpreadsheetQuery(url);
        query.setTitleQuery(spreadsheetName);
        SpreadsheetFeed feed = client.query(query, SpreadsheetFeed.class);
        List<SpreadsheetEntry> spreadsheetEntryList = feed.getEntries();
        if (spreadsheetEntryList.isEmpty()) {
            throw new RuntimeException("not found spreadsheet '" + spreadsheetName + "'");
        }
        return spreadsheetEntryList.get(0);
    }
}
実行結果
品目:りんご,価格:100,在庫:10
品目:みかん,価格:80,在庫:20
品目:もも,価格:160,在庫:3

ワークシートを検索してリストを取得する

ソースコード
import java.io.IOException;
import java.net.URL;
import java.util.List;

import com.google.gdata.client.spreadsheet.FeedURLFactory;
import com.google.gdata.client.spreadsheet.ListQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.client.spreadsheet.WorksheetQuery;
import com.google.gdata.data.spreadsheet.CustomElementCollection;
import com.google.gdata.data.spreadsheet.ListEntry;
import com.google.gdata.data.spreadsheet.ListFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

public class PrintSearchedList {

    private static final String APPLICATION_NAME = "tomorrowkey-"
            + PrintSearchedList.class.getSimpleName() + "-v1";

    public static final void main(String[] args) {
        String username = ArgumentUtil.getUsernameFromArgument(args);
        String password = ArgumentUtil.getPasswordFromArgument(args);
        PrintSearchedList printAllWorksheet = new PrintSearchedList();
        printAllWorksheet.start(username, password);
    }

    private SpreadsheetService client;

    private void start(String username, String password) {
        try {
            client = new SpreadsheetService(APPLICATION_NAME);
            client.setUserCredentials(username, password);
            WorksheetEntry worksheet = getWorksheet("TEST", "東京");

            URL url = worksheet.getListFeedUrl();
            ListQuery query = new ListQuery(url);
            query.setFullTextQuery("*ん");
            ListFeed feed = client.getFeed(query, ListFeed.class);
            List<ListEntry> listEntryList = feed.getEntries();
            for (ListEntry listEntry : listEntryList) {
                CustomElementCollection customElements = listEntry.getCustomElements();
                StringBuilder sb = new StringBuilder();
                sb.append("品目:").append(customElements.getValue("品目")).append(",");
                sb.append("価格:").append(customElements.getValue("価格")).append(",");
                sb.append("在庫:").append(customElements.getValue("在庫"));
                System.out.println(sb.toString());
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }

    }

    private WorksheetEntry getWorksheet(String spreadsheetName, String worksheetName)
            throws IOException, ServiceException {
        SpreadsheetEntry spreadsheet = getSpreadsheet(spreadsheetName);
        URL url = spreadsheet.getWorksheetFeedUrl();
        WorksheetQuery query = new WorksheetQuery(url);
        WorksheetFeed feed = client.query(query, WorksheetFeed.class);
        List<WorksheetEntry> worksheetEntryList = feed.getEntries();
        if (worksheetEntryList.isEmpty()) {
            throw new RuntimeException("not found worksheet '" + worksheetName + "' in '"
                    + spreadsheetName + "'");
        }
        return worksheetEntryList.get(0);
    }

    private SpreadsheetEntry getSpreadsheet(String spreadsheetName) throws IOException,
            ServiceException {
        URL url = FeedURLFactory.getDefault().getSpreadsheetsFeedUrl();
        SpreadsheetQuery query = new SpreadsheetQuery(url);
        query.setTitleQuery(spreadsheetName);
        SpreadsheetFeed feed = client.query(query, SpreadsheetFeed.class);
        List<SpreadsheetEntry> spreadsheetEntryList = feed.getEntries();
        if (spreadsheetEntryList.isEmpty()) {
            throw new RuntimeException("not found spreadsheet '" + spreadsheetName + "'");
        }
        return spreadsheetEntryList.get(0);
    }
}
実行結果
品目:みかん,価格:80,在庫:20

検索条件には完全一致はもちろん、"*"を使って簡単なあいまい検索もできるみたいです。

ワークシートからすべてのセルを取得する

ソースコード
import java.io.IOException;
import java.net.URL;
import java.util.List;

import com.google.gdata.client.spreadsheet.FeedURLFactory;
import com.google.gdata.client.spreadsheet.SpreadsheetQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.client.spreadsheet.WorksheetQuery;
import com.google.gdata.data.spreadsheet.CellEntry;
import com.google.gdata.data.spreadsheet.CellFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

public class PrintAllCell {

    private static final String APPLICATION_NAME = "tomorrowkey-"
            + PrintAllCell.class.getSimpleName() + "-v1";

    public static final void main(String[] args) {
        String username = ArgumentUtil.getUsernameFromArgument(args);
        String password = ArgumentUtil.getPasswordFromArgument(args);
        PrintAllCell printAllWorksheet = new PrintAllCell();
        printAllWorksheet.start(username, password);
    }

    private SpreadsheetService client;

    private void start(String username, String password) {
        try {
            client = new SpreadsheetService(APPLICATION_NAME);
            client.setUserCredentials(username, password);
            WorksheetEntry worksheet = getWorksheet("TEST", "東京");

            URL url = worksheet.getCellFeedUrl();
            CellFeed feed = client.getFeed(url, CellFeed.class);
            List<CellEntry> cellEntryList = feed.getEntries();
            for (CellEntry cellEntry : cellEntryList) {
                System.out.println(cellEntry.getCell().getValue());
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }
    }

    private WorksheetEntry getWorksheet(String spreadsheetName, String worksheetName)
            throws IOException, ServiceException {
        SpreadsheetEntry spreadsheet = getSpreadsheet(spreadsheetName);
        URL url = spreadsheet.getWorksheetFeedUrl();
        WorksheetQuery query = new WorksheetQuery(url);
        WorksheetFeed feed = client.query(query, WorksheetFeed.class);
        List<WorksheetEntry> worksheetEntryList = feed.getEntries();
        if (worksheetEntryList.isEmpty()) {
            throw new RuntimeException("not found worksheet '" + worksheetName + "' in '"
                    + spreadsheetName + "'");
        }
        return worksheetEntryList.get(0);
    }

    private SpreadsheetEntry getSpreadsheet(String spreadsheetName) throws IOException,
            ServiceException {
        URL url = FeedURLFactory.getDefault().getSpreadsheetsFeedUrl();
        SpreadsheetQuery query = new SpreadsheetQuery(url);
        query.setTitleQuery("TEST");
        SpreadsheetFeed feed = client.query(query, SpreadsheetFeed.class);
        List<SpreadsheetEntry> spreadsheetEntryList = feed.getEntries();
        if (spreadsheetEntryList.isEmpty()) {
            throw new RuntimeException("not found spreadsheet '" + spreadsheetName + "'");
        }
        return spreadsheetEntryList.get(0);
    }
}
実行結果
品目
価格
在庫
りんご
100
10
みかん
80
20
もも
160
3

ワークシートを検索してセルを取得する

ソースコード
import java.io.IOException;
import java.net.URL;
import java.util.List;

import com.google.gdata.client.spreadsheet.CellQuery;
import com.google.gdata.client.spreadsheet.FeedURLFactory;
import com.google.gdata.client.spreadsheet.SpreadsheetQuery;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.client.spreadsheet.WorksheetQuery;
import com.google.gdata.data.spreadsheet.CellEntry;
import com.google.gdata.data.spreadsheet.CellFeed;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.data.spreadsheet.WorksheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetFeed;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

public class PrintSearchedCell {

    private static final String APPLICATION_NAME = "tomorrowkey-"
            + PrintSearchedCell.class.getSimpleName() + "-v1";

    public static final void main(String[] args) {
        String username = ArgumentUtil.getUsernameFromArgument(args);
        String password = ArgumentUtil.getPasswordFromArgument(args);
        PrintSearchedCell printAllWorksheet = new PrintSearchedCell();
        printAllWorksheet.start(username, password);
    }

    private SpreadsheetService client;

    private void start(String username, String password) {
        try {
            client = new SpreadsheetService(APPLICATION_NAME);
            client.setUserCredentials(username, password);
            WorksheetEntry worksheet = getWorksheet("TEST", "東京");

            URL url = worksheet.getCellFeedUrl();
            CellQuery query = new CellQuery(url);
            query.setFullTextQuery("*0");
            CellFeed feed = client.getFeed(query, CellFeed.class);
            List<CellEntry> cellEntryList = feed.getEntries();
            for (CellEntry cellEntry : cellEntryList) {
                System.out.println(cellEntry.getCell().getValue());
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        }
    }

    private WorksheetEntry getWorksheet(String spreadsheetName, String worksheetName)
            throws IOException, ServiceException {
        SpreadsheetEntry spreadsheet = getSpreadsheet(spreadsheetName);
        URL url = spreadsheet.getWorksheetFeedUrl();
        WorksheetQuery query = new WorksheetQuery(url);
        WorksheetFeed feed = client.query(query, WorksheetFeed.class);
        List<WorksheetEntry> worksheetEntryList = feed.getEntries();
        if (worksheetEntryList.isEmpty()) {
            throw new RuntimeException("not found worksheet '" + worksheetName + "' in '"
                    + spreadsheetName + "'");
        }
        return worksheetEntryList.get(0);
    }

    private SpreadsheetEntry getSpreadsheet(String spreadsheetName) throws IOException,
            ServiceException {
        URL url = FeedURLFactory.getDefault().getSpreadsheetsFeedUrl();
        SpreadsheetQuery query = new SpreadsheetQuery(url);
        query.setTitleQuery("TEST");
        SpreadsheetFeed feed = client.query(query, SpreadsheetFeed.class);
        List<SpreadsheetEntry> spreadsheetEntryList = feed.getEntries();
        if (spreadsheetEntryList.isEmpty()) {
            throw new RuntimeException("not found spreadsheet '" + spreadsheetName + "'");
        }
        return spreadsheetEntryList.get(0);
    }
}
実行結果
100
10
80
20
160

まとめ

1. FeedのURLを取得する

・Spreadsheet

→FeedURLFactory.getDefault().getSpreadsheetsFeedUrl();

・Worksheet

→SpreadsheetEntry#getWorksheetFeedUrl();

・List

→WorksheetEntry#getListFeedUrl();

Cell

→WorksheetEntry#getCellFeedUrl();

2. 検索する場合はQueryを作成する

・Spreadsheet

→SpreadsheetQuery

・Worksheet

→WorksheetQuery

・List

→ListQuery

・Cell

→CellQuery

3. URL/Queryを使い、Feedを作成する

・Spreadsheet

→SpreadsheetService#getFeed(#URL, SpreadsheetFeed.class);

→SpreadsheetService#getFeed(#SpreadsheetQuery, SpreadsheetFeed.class);

・Worksheet

→SpreadsheetService#getFeed(#URL, WorksheetFeed.class);

→SpreadsheetService#getFeed(#WorksheetQuery, WorksheetFeed.class);

・List

→SpreadsheetService#getFeed(#URL, ListFeed.class);

→SpreadsheetService#getFeed(#ListQuery, ListFeed.class);

・Cell

→SpreadsheetService#getFeed(#URL, CellFeed.class);

→SpreadsheetService#getFeed(#CellQuery, CellFeed.class);

4. List<Entry>を取得する

Feed#getEntries();

所感

同じようなコードをたくさん書いて疲れた、、。

とりあえず参照はこれだけあればできるはず。

他にRecordとTableってクラスがあるけど使ったことないなあ。

*1:試していません。いつかやりたいな

2011-02-12

Protocol Buffersを使う

ProtocolBuffers

protobuf - Project Hosting on Google Code

http://code.google.com/p/protobuf/

ProtocolBuffersはシリアライズライブラリです。

バージョン2.4.0aを使ってみます。

ダウンロード

http://code.google.com/p/protobuf/downloads/list

ここからダウンロード

ビルド

C++のところをビルド

$ ./configure
$ make
$ make check
$ sudo make install

jarつくる

cd java
mvn package

targetフォルダ内にprotobuf-java-2.4.0a.jarというファイルができていると思います

eclipseでプロジェクト作成

普通にjavaプロジェクトを作成

libsフォルダを作成し、中にprotobuf-java-2.4.0a.jarを入れてビルドパスに追加する

シリアライズ化するクラスの作成

ProtocolBuffersはシリアル化するクラスのprotoファイルを書く必要があります

Language Guide - Protocol Buffers - Google Code 
http://code.google.com/intl/ja/apis/protocolbuffers/docs/proto.html

このprotoファイルはIDLって言語で書くみたいです。

androidでserviceとの通信インターフェイスを定義するaidlファイルもIDLですね

インタフェース記述言語 - Wikipedia
http://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E8%A8%98%E8%BF%B0%E8%A8%80%E8%AA%9E
EmployeeTranslater.proto
package jp.tomorrowkey;

message Employee {
  required string name;
  required int32 age;
}

ファイル名とメッセージ名は違うやつにしないと怒られます

クラスに変換

プロジェクトルートで以下をコマンドする

protoc --java_out=src src/jp/tomorrowkey/EmployeeTranslater.proto

するとsrc/jp/tomorrowkeyにEmployeeTranslater.javaができあがります。

クラス変換を楽にするために

protoclipseというeclipse pluginがあります

これを使うとproto→javaの変換をjavaのビルドのタイミングで自動でやってくれます。

protoclipse - Project Hosting on Google Code 
http://code.google.com/p/protoclipse/

インストールが終わったらprotocの場所を設定したあとProtocolBuffersを使いたいプロジェクトで

右クリックして[Add Google ProtoBuf Compiler Nature]を選べば完了です。

Buildersの中にProtocolBuffersの変換する処理が追加されてると思います。

コードを書く

import com.google.protobuf.InvalidProtocolBufferException;

public class Main {
  public static void main(String[] args) {
    EmployeeTranslater.Employee.Builder builder = EmployeeTranslater.Employee.newBuilder();
    builder.setName("taro");
    builder.setAge(25);
    EmployeeTranslater.Employee src = builder.build();

    // シリアライズ
    byte[] buffer = src.toByteArray();

    // 表示してみる
    for (byte b : buffer) {
      System.out.print(Integer.toHexString(b & 0xFF) + " ");
    }
    System.out.println();

    // デシリアライズ
    EmployeeTranslater.Employee dst = null;
    try {
      dst = EmployeeTranslater.Employee.parseFrom(buffer);
    } catch (InvalidProtocolBufferException e) {
      dst = null;
    }

    // ちゃんと復元されたかな?
    if (dst != null) {
      System.out.println("name:" + dst.getName());
      System.out.println("age:" + dst.getAge());
    } else {
      System.out.println("dst is null");
    }
  }
}

実行

a 4 74 61 72 6f 10 19 
name:taro
age:25

やったー!シリアライズされたー!

MessagePack for Javaを使う

MessagePack

The MessagePack Project

http://msgpack.org/

MessagePackはシリアライズライブラリです。

バージョン0.5.1を使ってみます

ビルド

ビルドにはMavenが必要です。

ダウンロードしてパス通せば使えます。

Maven - Welcome to Apache Maven 
http://maven.apache.org/

あとはこれを打てばおっけー

$ git clone https://github.com/msgpack/msgpack.git
$ cd msgpack/java/
$ mvn package
$ mvn install

targetフォルダの中にmsgpack-0.5.1-devel.jarができてると思います

eclipseの設定

[環境設定][java][Build Path][Classpath Variables][New...]

$HOME/.m2/repository

を追加

eclipseでプロジェクト作成

普通にjavaプロジェクトを作成

libsフォルダを作成し、中にmsgpack-0.5.1-devel.jarを入れてビルドパスに追加する

.classpathを開き以下を追加する

<classpathentry kind="var" path="M2_REPO/javassist/javassist/3.12.1.GA/javassist-3.12.1.GA.jar"/>
<classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.13/log4j-1.2.13.jar"/>
<classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-api/1.4.3/slf4j-api-1.4.3.jar"/>
<classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-log4j12/1.4.3/slf4j-log4j12-1.4.3.jar"/>

コードを書く

import org.msgpack.MessagePack;
import org.msgpack.annotation.MessagePackMessage;

public class Main {

  /**
   * シリアライズするクラス
   * MessagePackMessageアノテーションをつけるだけでおっけー
   */
  @MessagePackMessage
  public static class Employee {

    // publicなフィールドでないとシリアライズされない
    public String name;

    // publicなフィ(ry
    public int age;

    public Employee() {
      // デフォルトコンストラクタないと怒られます
    }

    public Employee(String name, int age) {
      this.name = name;
      this.age = age;
    }
  }

  public static void main(String[] args) {
    Employee src = new Employee("taro", 25);

    // シリアライズ
    byte[] buffer = MessagePack.pack(src);

    // 表示してみる
    for (byte b : buffer) {
      System.out.print(Integer.toHexString(b & 0xFF) + " ");
    }
    System.out.println();

    // デシリアライズ
    Employee dst = MessagePack.unpack(buffer, Employee.class);

    // ちゃんと復元されたかな?
    System.out.println("name:" + dst.name);
    System.out.println("age:" + dst.age);
  }
}

実行

92 a4 74 61 72 6f 19 
name:taro
age:25

やったー!シリアライズされたー!

2010-09-08

外部ライブラリのすゝめ

きっかけ

GoogleAppEngineとAndroidの開発をしていて、共通に使用するコードを外部ライブラリ化したかったんだけど

プロジェクトのプロパティから他のプロジェクトの参照という方法では

簡単にはjarファイルを任意の場所に置けない事が分かって*1

いろいろ試行錯誤してこれに落ち着きそうな感じです。

ant

antを使えばjavaのコンパイルや、jarファイル作成などマクロみたいに組むことができるんで

antのbuild.xmlを書きました。

ディレクトリ構成
root
 src
 bin
 build.xml
 xxx.jar

Eclipseで作成する普通のJavaプロジェクトで、build.xmlはプロジェクトの直下に置きます。

jarファイルはプロジェクト直下にできます。

ソース
  • build.xml
<?xml version="1.0" encoding="utf-8" ?>
<project name="xxx" default="deploy">

  <property name="jarname" location="./xxx.jar" />
  <property name="src" location="./src" />
  <property name="bin" location="./bin" />

  <target name="compile">
    <delete dir="${bin}/*" />
    <javac srcdir="${src}" destdir="${bin}" />
  </target>

  <target name="build">
    <delete file="${jarname}" />
    <jar jarfile="${jarname}">
      <fileset dir="${src}" />
      <fileset dir="${bin}" />
    </jar>
  </target>

  <target name="deploy" depends="build">
    <copy file="${jarname}" todir="./../gae_project/war/WEB-INF/lib" />
    <copy file="${jarname}" todir="./../android_project/assets" />
  </target>
</project>
使い方

主に変更する点

  • projectエレメントのname属性
    • 別に必須じゃないから変更しなくてもいいんだけど、プロジェクト名を指定
  • property:jarnameのlocation
    • ./の後に、作成するjarファイルの名前に変更する
  • target:deployのcopyエレメント
    • todir属性の値を、jarファイルを配置するディレクトリパスに変更する。

当初はコンパイルも書いてたんですけど、eclipseさんが自動的にコンパイルしてくれるので

target:compileは使ってません。消しても構いません。

さらに

まだ手を抜くために、antの実行もショートカットで簡単にしてしまいます*2

  • プロジェクトで右クリック
  • Properties
  • Builders
  • Import...
  • Build.xmlを選択*3

これをやっておくとCommand+Bで(WindowsならCtrl+B?)勝手にコンパイルされて配置されます。

クリーンしたときも勝手にコンパイルされて配置されます。

プロジェクトを実行しようとしてもコンパイルされて配置されるかも。

androidの外部ライブラリを作る

androidSDKのAPIを使う外部ライブラリを作りたいなと思ったので、それも調べました。

ようはandroid.jarを参照ライブラリに追加すればいいですね。

とりあえずユーザライブラリにAndroid.jarを追加する

  • Eclipseの環境設定
  • java
  • Build Path
  • User Libraries
  • New...
  • 「Android 2.2」と入力
  • 「Android 2.2」を選択
  • Add JARs...
  • 「/Applications/android-sdk-mac_86/platforms/Android-8/android.jar」を選択*4

これはandroid 1.5からそれぞれのバージョンしておくといいかもしれませんね。

あとはライブラリプロジェクトの参照ライブラリに追加します。

  • プロジェクトで右クリック
  • Build Path
  • Add Libraries
  • User Library
  • 「Android 2.2」を選択

これでAndroidSDKのAPIを使ったライブラリを作ることができます。

最後に

ほぼ自己流でやってるんで、こういうところを改善した方がいいよ!ってあったら教えてください!

特にant歴は3時間くらいなんで、すげー怪しいです。

twitterでも!コメントででも!

*1:簡単な方法がありましたら教えてください。私のがんばりが消えてなくなります…

*2:毎回のビルド時間が長くなり、一長一短だったりするんで、導入はそれぞれで判断してください

*3:一度Antを手動で実行しないと表示されないかもしれません

*4:環境によって異なります

2010-03-02

JavaでSocket通信

これを使えば

"俺サーバ"も書けちゃうね!

ありがちだけどAndroidをタッチパッド代わりに使うアプリだって書けちゃう!

ソース

MyServer.java
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class MyServer extends Thread {

  private int serverPort;
  private int maxConnection;

  public MyServer(int serverPort, int maxConnection) {
    this.serverPort = serverPort;
    this.maxConnection = maxConnection;
  }

  @Override
  public void run() {
    ServerSocket serverSocket = null;
    Socket socket = null;

    try {
      serverSocket = new ServerSocket(serverPort, maxConnection);

      socket = serverSocket.accept();
      new ServerProcess(socket).start();

    } catch (IOException e) {
      e.printStackTrace();
      System.exit(1);
    } finally {
      if (serverSocket != null) {
        try {
          serverSocket.close();
        } catch (IOException e) {
          e.printStackTrace();
          System.exit(1);
        }
      }
    }
  }

  private class ServerProcess extends Thread {
    private Socket socket;

    public ServerProcess(Socket socket) {
      this.socket = socket;
    }

    @Override
    public void run() {
      InputStream stream = null;
      byte buffer[] = new byte[1024];
      int length;
      StringBuffer recvMessage = new StringBuffer();

      try {
        stream = socket.getInputStream();

        while (true) {
          length = stream.read(buffer);
          if (length > 0) {
            recvMessage.append(new String(buffer, 0, length));
          } else {
            break;
          }
        }

        System.out.println(recvMessage.toString());
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}
MyClient.java
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class MyClient {
  private String serverAddress;
  private int serverPort;

  public MyClient(String serverAddress, int serverPort) {
    this.serverAddress = serverAddress;
    this.serverPort = serverPort;
  }

  public boolean sendMessage(String message) {
    Socket socket = null;
    OutputStream stream = null;

    try {
      socket = new Socket(serverAddress, serverPort);
      stream = socket.getOutputStream();
      stream.write(message.getBytes());
      return true;
    } catch (IOException e) {
      e.printStackTrace();
      return false;
    } finally {
      try {
        if (socket != null) {
          socket.close();
        }
        if (stream != null) {
          stream.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}
Main.java
public class Main {
  public static void main(String[] args) {
    MyServer server = new MyServer(6001, 1);
    server.start();
    MyClient client = new MyClient("localhost", 6001);
    client.sendMessage("Hello Tomorrow!!");
  }
}

実行結果

Hello Tomorrow!!