Apache James + Groovy でメール連携アプリケーション その4



今回はGroovyのスクリプトを考えてみます。

ISBN -> 書籍名に変換するよいwebapiが見当たらなかったので
自力で取得し、一度取得したものはDBにキャッシュするようにしました。

ちなみに、Groovy書くのは初めてです。

以下のスクリプトをappend.groovyとし、
/var/local/james/に保存します。

■append.groovy
import jp.dip.dkdc.james.*;
import java.sql.*;
import groovy.sql.Sql

//書籍情報クラス
class BookData {
    String bookTitle
    String author
    String publisher
    int count = 0
}

//全角・半角数値をとりあえずintへ変換
def toNumber(value){
    temp = 0
    for (int i = 0; i < value.length(); i++) {
        switch (value[i]) {
        case '1':
        case '1':
            temp = temp * 10 + 1
            break
        case '2':
        case '2':
            temp = temp * 10 + 2
            break
        case '3':
        case '3':
            temp = temp * 10 + 3
            break
        case '4':
        case '4':
            temp = temp * 10 + 4
            break
        case '5':
        case '5':
            temp = temp * 10 + 5
            break
        case '6':
        case '6':
            temp = temp * 10 + 6
            break
        case '7':
        case '7':
            temp = temp * 10 + 7
            break
        case '8':
        case '8':
            temp = temp * 10 + 8
            break
        case '9':
        case '9':
            temp = temp * 10 + 9
            break
        case '0':
        case '0':
            temp = temp * 10 + 0
            break

        }
    }
    return temp
}

//メールアドレスからユーザIDを取得
def getUserId(sql, user_address) {
    def user_count = sql.firstRow(
    "select count(*) as user_count from user_address where mail = '" + user_address + "'").user_count
    
    def user_id = 0
    
    if (user_count == 0) {
        user_id = sql.firstRow("select coalesce(max(id) + 1,1) as user_id from user_address").user_id
        
        def usert = sql.dataSet("user_address")
        usert.add(mail:user_address, id:user_id)
        
    } else {
        user_id = sql.firstRow("select id from user_address where mail = '" + user_address + "'").id
    }
    
    return user_id
}

//ISBNから書籍データ取得
def getBookData(isbn, sql) {

    //一旦DBを検索
    BookData book = getBookData4DB(isbn, sql)
    
    if (book == null) {
        //DBにデータがなければweb検索
        url_str = "http://bookweb.kinokuniya.co.jp/guest/cgi-bin/wshosea.cgi?W-ISBN=${isbn}"
    
        book = getBookData4URL(url_str)
        
        if (book.bookTitle != null) {
            //キャッシュにデータを追加
            def bookt = sql.dataSet("book_data")
            bookt.add(isbn:isbn, title:book.bookTitle ,count:book.count, author:book.author, publisher:book.publisher)
        } else {
            book = null
        }
    }
    
    return book
}

//DBのキャッシュを検索
def getBookData4DB(isbn, sql){
    
    def book_count = sql.firstRow("select count(*) as book_count from book_data where isbn = " + isbn).book_count
    
    if (book_count == 0) {
        return null
    }
    
    row = sql.firstRow("select * from book_data where isbn = " + isbn)
    
    BookData book = new BookData()
    
    book.bookTitle = row.title
    book.author = row.author
    book.publisher = row.publisher
    book.count = row.count
        
    return book
}

//webページから書籍名を取得
def getBookData4URL(url_str) {

    isHit = false
    hitAfter = 0

    BookData data = new BookData()

    def url = new URL(url_str)
    input=new BufferedReader(new InputStreamReader(url.openStream(), 'Shift_JIS'));
    
    while((s=input.readLine()) != null){
        if (s.contains('<span class="font16"><strong>')) {
            isHit = true
            //本の名前
            s = s - '<span class="font16"><strong>' - '</strong></span><br />'
            sp = s.tokenize('〈〉')
            data.bookTitle = sp[0]
            
            if (sp.size > 2) {
                data.count = toNumber(sp[1])
            }
        }
        
        if (s.contains('<h3 class="pro-bname">')) {
            return getBookData4URL('http://bookweb.kinokuniya.co.jp' + s.tokenize('"')[3])
        }
    
        if (isHit) {
            hitAfter++
        }
    
        if (hitAfter == 4) {
            //作者
            data.author = s.tokenize('<')[0].tokenize('>')[1]
        } else if (hitAfter == 5) {
            //出版社
            data.publisher = s.tokenize('<')[0].tokenize('>')[1]
            break
        }
    }
    return data
}

//返信内容取得
def bookComment(isbn, sql, user_id) {
    
    def comment = ""
    
    def book_count = sql.firstRow(
    "select count(*) as book_count from user_books where (isbn = " + isbn + ") and (id = " + user_id + ")"
    ).book_count
    
    if (book_count == 0) {
        def ubt = sql.dataSet("user_books")
        ubt.add(isbn:isbn, id:user_id)
        comment = "この本は持っていません。追加しました。\n"
    } else {
        comment = "この本は所持しています。\n"
    }
    
    return comment
}

//ISBNとしての妥当性検証
//といても、10もしくは13桁かのチェックのみ
def isISBN(value) {
    if (value == null) {
        return false
    }
    return ((value.length() == 10) || (value.length() == 13))
}

//ISBNから書籍名を解析
//また、このユーザがこの書籍を保持しているのか確認
def analize(isbn, sql, user_id) {

    result = ""

    if (isbn == null) {
        return result
    }

    if (isISBN(isbn)) {
        book = getBookData(isbn, sql)
    
        if (book == null) {
            result += isbn + ":書籍が特定できません。\n"
        } else {
            result += isbn + ":" + book.bookTitle
            if (book.count > 0) {
                result += "(" + book.count + ")"
            }
            result += "\n"
            
            //この本に対するコメントを付加
            result += bookComment(isbn, sql, user_id)
            
        }
    } else {
        result += isbn + ":ISBNの桁数が不正です\n"
    }
    
    return result
}


//Jamesから渡されたメールデータ
MailData data = (MailData)mail
//Jamesから渡されたコネクション
Connection con = (Connection)db

//groovy.sqlを生成
def sql = new Sql(con)

//メールアドレスからユーザID取得
def user_id = getUserId(sql, data.getSender())

BookData book = null;
resultBody = ""
//タイトル解析
resultBody += analize(data.getSubject(), sql, user_id)

//本体解析
if (data.getBody() != null) {
    line = data.getBody().replaceAll("\r", "")
    lines = line.tokenize("\n")

    for (int i = 0; i < lines.size; i++) {
        resultBody += analize(lines[i], sql, user_id)
    }
}

MailData result = new MailData()

result.setSubject("解析結果")
result.setBody(resultBody)
result.setSender(data.getSender())

return result


【参考URL】
http://kakutani.com/trans/ociweb/
http://www.jdocs.com/groovy/1.0.jsr06/groovy/sql/DataSet.html
http://groovy.codehaus.org/Database+features


もどる