IT戦記 このページをアンテナに追加 RSSフィード Twitter

2010-02-26

Effective Java 読書会 9 日目 「Enum の拡張とアノテーション」

はじめに

Effective Jav... - 告白 - はてなセリフ

今日読んだところ

160 ページ〜 174 ページ

前回はこちら

Effective Java 読書会 8 日目 「それ enum で出来るよ」 - IT戦記

enum継承できない

混乱するので、あまり出来ないほうがいいけどね!

オペコードのようなものは

インタフェースを切って enum継承してやれば拡張可能に出来るよ!

たとえば、 jythonバイトコード

package org.python.bytecode;

public interface Instruction {

    void accept(BytecodeVisitor visitor);
}

って感じのインタフェースを以下の enum で実装してる

package org.python.bytecode;

public enum BytecodeInstruction implements Instruction, RawInstruction {
    /** Marks the end of the byte code segment. */
    STOP_CODE(0, false, null, null) {

        /* ... */

        @Override
        public void accept(BytecodeVisitor visitor) {
            visitor.visitStop();
        }
    },

    /**
     * Remove the top stack element.
     *
     * Stack: element -> -
     */
    POP_TOP(1, false, null, null) {

        @Override
        public void accept(BytecodeVisitor visitor) {
            visitor.visitPop();
        }
    },

    /* ... */
}

なので、自分でオリジナルなバイトコードも追加できるということ

Class<T>#getEnumConstants

T.values と同じだけどインスタンスメソッドなので、型消去後も使える。

命名パターンは、ダメ

アノテーションを使おう、命名パターンだと書き間違えとかあるしね。

Override アノテーションは付ける

いろいろ便利

オーバーライドしたつもりが、シグネチャの違いでオーバーロードになっちゃってるときが結構ある。

@Override で解決さ!

マーカーインタフェースは便利

タイプアノテーションも便利だけど、場合によってはマーカーインタフェースもまだ使う

マーカーインタフェースが便利なのは以下のようなとき

  • メソッドがマーク付けしたクラスだけを受け取りたいとき
  • 永久的にこのマーカーを適用させたい場合

まとめ

なんか、あっさり目な内容でした。

あ、アノテーション愛が足りない><

次回はこちら

Effective Java 読書会 10 日目 「Java の基本テクニック集」 - IT戦記

ついったったーの情報をデータベースに突っ込む!

久々に Perl 書いた

#! /usr/bin/perl

use strict;
use warnings;
use utf8;

use DBI;
use HTTP::Date;
use Net::Twitter;
use File::Basename;
use Data::Dumper;
use Config::Pit;

my $config = pit_get('twitter.com');

my $dbh = DBI->connect('dbi:SQLite:twitter.db', '', '', { AutoCommit => 0 });
die DBI->errstr unless $dbh;
my $twitter = Net::Twitter->new( username => $config->{username}, password => $config->{password} );

my $limit = $twitter->rate_limit_status;
if ($limit->{remaining_hits} == 0) {
    while($limit->{reset_time_in_seconds} - time() > -10) {
        sleep(1);
        print "limit remaining time: " . ($limit->{reset_time_in_seconds} - time()) . " s \n";
    }
}

my $rv = $dbh->do('CREATE TABLE IF NOT EXISTS status (id INTEGER PRIMARY KEY, last_cursor INTEGER)');
die DBI->errstr unless $rv;
$rv = $dbh->do(q/
        CREATE TABLE IF NOT EXISTS user (
            id INTEGER PRIMARY KEY ON CONFLICT REPLACE,
            screen_name TEXT,
            name TEXT,
            created_at DATETIME,
            description TEXT,
            url TEXT,
            lang TEXT,
            location TEXT,
            profile_image_url TEXT,
            followers_count INTEGER,
            friends_count INTEGER,
            favourites_count INTEGER,
            statuses_count INTEGER,
            time_zone TEXT,
            utc_offset INTEGER,
            geo_enabled BOOLEAN,
            profile_background_image_url TEXT,
            profile_text_color INTEGER,
            profile_link_color INTEGER,
            profile_sidebar_fill_color INTEGER,
            profile_sidebar_border_color INTEGER,
            profile_background_color INTEGER,
            profile_background_tile INTEGER,
            notifications BOOLEAN,
            following BOOLEAN,
            protected BOOLEAN,
            verified BOOLEAN,
            contributors_enabled INTEGER,
            last_status_source TEXT,
            last_status_truncated INTEGER,
            last_status_favorited INTEGER,
            last_status_created_at DATETIME,
            last_status_text TEXT,
            last_status_in_reply_to_user_id INTEGER,
            last_status_id INTEGER,
            last_status_in_reply_to_status_id INTEGER,
            last_status_in_reply_to_screen_name TEXT
            )
            /);
            die DBI->errstr unless $rv;

            my $sth_save_status = $dbh->prepare(q/
                    INSERT OR REPLACE INTO status (
                        id, last_cursor
                        )
                    VALUES (1, ?)
                    /);
            die DBI->errstr unless $sth_save_status;
            my $sth_load_status = $dbh->prepare(q/
                    SELECT id, last_cursor FROM status WHERE id = 1
                    /);
            die DBI->errstr unless $sth_load_status;
            my $sth_insert_user = $dbh->prepare(q/
                    INSERT OR REPLACE INTO user (
                        id, screen_name, name, created_at, description, url, lang, location, profile_image_url, followers_count,
                        friends_count, favourites_count, statuses_count, time_zone, utc_offset, geo_enabled, profile_background_image_url,
                        profile_text_color, profile_link_color, profile_sidebar_fill_color, profile_sidebar_border_color, profile_background_color,
                        profile_background_tile, notifications, following, protected, verified, contributors_enabled, last_status_source,
                        last_status_truncated, last_status_favorited, last_status_created_at, last_status_text, last_status_in_reply_to_user_id,
                        last_status_id, last_status_in_reply_to_status_id, last_status_in_reply_to_screen_name
                        )
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                    /);
            die DBI->errstr unless $sth_insert_user;
            my $sth_check_user = $dbh->prepare(q/
                    SELECT id FROM user WHERE id = ?
                    /);
            die DBI->errstr unless $sth_check_user;

            my $followers;
            my $cursor = -1;
            $rv = $sth_load_status->execute;
            die $sth_load_status->errstr unless $rv;
            my $status_row = $sth_load_status->fetchrow_arrayref;
            if ($status_row) {
                my ($id, $last_cursor) = @$status_row;
                $cursor = $last_cursor;
                print "loaded $cursor\n";
            }

while (1) {
    last unless $cursor;
    eval {
        $followers = $twitter->followers({ cursor => $cursor });
        if (defined($followers)) {
            eval {
                for my $tweeter (@{$followers->{users}}) {
                    insert_user($tweeter);
                }
                my $rv = $sth_save_status->execute($followers->{next_cursor});
                die $sth_save_status->errstr unless $rv;
                $dbh->commit;
            };
            if ($@) {
                $dbh->rollback;
                die $@;
            }
        }
        else {
            print "current_cursor = " . $cursor . "!!!!\n";
            print "try again!!!!\n";
            print $twitter->http_message . "\n";
            if ($twitter->http_message eq 'Bad Request') {
                die $twitter->http_message;
            }
            $followers = { next_cursor => ($cursor - 100000000000000) }
        }
    };
    if ($@) {
        die $@;
    }
    $cursor = $followers->{next_cursor};
}

$cursor = -1;
while (1) {
    last unless $cursor;
    my $follower_ids;
    my $tweeter_id;
    eval {
        $follower_ids = $twitter->followers_ids({ cursor => $cursor });
        if (defined($follower_ids)) {
            for $tweeter_id (@{$follower_ids->{ids}}) {
                eval {
                    my $rv = $sth_check_user->execute($tweeter_id);
                    die $sth_check_user->errstr unless $rv;
                    my $tweeter_row = $sth_check_user->fetchrow_arrayref;
                    unless ($tweeter_row) {
                        my $tweeter = $twitter->show_user($tweeter_id);
                        if ($tweeter) {
                            insert_user($tweeter);
                        }
                        else {
                            print "id = $tweeter_id , message = " . $twitter->http_message . "\n";
                            if ($twitter->http_message eq 'Bad Request') {
                                die $twitter->http_message;
                            }
                        }
                    }
                    $dbh->commit;
                };
                if ($@) {
                    $dbh->rollback;
                    die $@;
                }
            }
        }
        else {
            print "current_cursor = " . $cursor . "!!!!\n";
            die $twitter->http_message;
        }
    };
    if ($@) {
        die $@;
    }
    $cursor = $follower_ids->{next_cursor};
}

sub insert_user {
    my $tweeter = shift;
    my $rv = $sth_insert_user->execute(
        $tweeter->{id},
        $tweeter->{screen_name},
        $tweeter->{name},
        create_iso_time($tweeter->{created_at}),
        $tweeter->{description},
        $tweeter->{url},
        $tweeter->{lang},
        $tweeter->{location},
        $tweeter->{profile_image_url},
        $tweeter->{followers_count},
        $tweeter->{friends_count},
        $tweeter->{favourites_count},
        $tweeter->{statuses_count},
        $tweeter->{time_zone},
        $tweeter->{utc_offset},
        $tweeter->{geo_enabled},
        $tweeter->{profile_background_image_url},
        $tweeter->{profile_text_color},
        $tweeter->{profile_link_color},
        $tweeter->{profile_sidebar_fill_color},
        $tweeter->{profile_sidebar_border_color},
        $tweeter->{profile_background_color},
        $tweeter->{profile_background_tile},
        $tweeter->{notifications},
        $tweeter->{following},
        $tweeter->{protected},
        $tweeter->{verified},
        $tweeter->{contributors_enabled},
        $tweeter->{status}->{source},
        $tweeter->{status}->{truncated},
        $tweeter->{status}->{favorited},
        create_iso_time($tweeter->{status}->{created_at}),
        $tweeter->{status}->{text},
        $tweeter->{status}->{in_reply_to_user_id},
        $tweeter->{status}->{id},
        $tweeter->{status}->{in_reply_to_status_id},
        $tweeter->{status}->{in_reply_to_screen_name},
    );
    die $sth_insert_user->errstr unless $rv;
    print "data insert " . $tweeter->{screen_name} . "\n";
}

sub create_iso_time {
    my $created_at = shift;
    if (defined $created_at) {
        $created_at =~ s/\+0000/UTC/;
        $created_at = HTTP::Date::time2iso(HTTP::Date::str2time($created_at));
    }
    else {
        $created_at = undef;
    }
    return $created_at;
}