2012年12月26日水曜日

html5の数値入力欄

inputタグのtype属性をnumberにすると数値入力欄になります。

<input type="number" name="number" id="number">

ブラウザで確認すると以下の様な入力フォームが出力されます。





数値入力欄の値をJavaScriptでNumberとして取得することもできます。Numberとして取得したい場合は、valueAsNumberプロパティを通して値を取得します。

  (function() {
    var number = document.getElementById('number'),
        value;
    value = number.valueAsNumber;
    console.log(typeof value);
  })();

2012年12月21日金曜日

html5のrequired属性の背景色を変更

html5のクライアントバリデーションの必須属性(required属性)の背景色をjqueryを使用して変更する方法。

  (function ($) {
    $('input:required').each(function() {
      var $this = $(this);
      // 初期表示時の色設定
      changeColor($this);

      // チェンジイベントをトリガーとする色設定
      $this.change(function() {
        changeColor($this);
      });

      function changeColor(element) {
        var backgroundColor;
        if (element.val()) {
          // 値がある場合は背景色を白に
          backgroundColor = 'white';
        } else {
          // 値がない場合は背景色をピンクに
          backgroundColor = 'pink';
        }
        element.css({backgroundColor: backgroundColor});
      }
    });
  })(jQuery);

2012年12月11日火曜日

ORA-01704に、悩まされた時の対処方法

NCLOBへのインサート時に「ORA-01704: 文字列リテラルが長すぎます」が出た場合の対処方法。

下のコードのように、PL/SQLにして文字リテラルをCLOB型の変数に直接突っ込んであげるとエラーが回避できるみたい。
declare
  data nclob;
begin
  data := '長い文字列';
  insert into test values (data);
end;
/

2012年11月4日日曜日

CoffeeScriptで値の比較

JavaScriptで値の変換をするときは、型まで完全に一致していることを保証するために「===」や「!==」を使用します。
CoffeeScriptでは、JavaScriptで推奨されない(暗黙の型変換が行われるため)「==」と「!=」が、型まで完全に一致していることをチェックしてくれます。また、「==」と「!=」のエイリアスとして「is」と「isnt」があるので英文のように比較を行うこともできます。

サンプル

console.log(0 == 0) # true
console.log(0 is 0) # true

console.log(0 != 0)   # false
console.log(0 isnt 0) # false

userName = 'hoge fuga'
console.log(userName == 0) # false
console.log(userName is 0) # false
console.log(userName is 'hoge fuga') # true
console.log(userName is 'user name') # false
このコードがJavaScriptに変換されると、したのコードになります。
JavaScriptのコードは、「===」と「!==」になっています。
(function() {
  var userName;

  console.log(0 === 0);

  console.log(0 === 0);

  console.log(0 !== 0);

  console.log(0 !== 0);

  userName = 'hoge fuga';

  console.log(userName === 0);

  console.log(userName === 0);

  console.log(userName === 'hoge fuga');

  console.log(userName === 'user name');

}).call(this);

PL/SQLで開いたカーソルをJDBC経由でJavaに返す方法

PL/SQLで開いたカーソルをJDBC経由で受け取り、Java側で処理する方法。

OracleDataSource dataSource = new OracleDataSource();
dataSource.setURL("jdbc:oracle:thin:@localhost:1521:xe");
dataSource.setUser("hoge");
dataSource.setPassword("fuga");

try (Connection connection = dataSource.getConnection()) {
    // PL/SQLの定義。ref_curというref_cursorを開き、アウトパラメータ(? := ref_curの部分)に代入している。
    CallableStatement statement = connection.prepareCall(
            "declare "
                    + " ref_cur sys_refcursor;"
                    + " begin "
                    + " open ref_cur"
                    + " for ' select table_name from user_tables'; "
                    + " ? := ref_cur;"
                    + " end;"
    );

    // アウトパラメータの方をcursorと定義する
    statement.registerOutParameter(1, OracleTypes.CURSOR);
    statement.execute();

    // アウトパラメータをResultSetとして取得し、処理してあげる
    try (ResultSet resultSet = (ResultSet) statement.getObject(1)) {
        while (resultSet.next()) {
            System.out.println("resultSet.getString(\"table_name\") = " + resultSet.getString("table_name"));
        }
    }
}

2012年10月28日日曜日

[JavaScript]正規表現のプロパティ

JavaScriptで正規表現のプロパティから取得できる値のまとめ。

サンプルコート

    var p = /([a-z]+)([0-9]+)/i;

    // 現在の正規表現
    document.writeln('source = ' + p.source);
    // 文字列全体に対してマッチングするか
    document.writeln('global = ' + p.global);
    // 大文字小文字の区別
    document.writeln('ignoreCase = ' + p.ignoreCase);
    // 改行を行末と判断するか
    document.writeln('multiline = ' + p.multiline);

    // 静的なプロパティ
    var ret = 'abc123'.match(p);
    // 入力した値(abc123となる)
    document.writeln('RegExp.input = ' + RegExp.input);
    // グループ化した値の参照($ + グループ化の位置をしめす数字を指定する。)
    document.writeln('RegExp.$1 = ' + RegExp.$1);
    document.writeln('RegExp.$2 = ' + RegExp.$2);

結果

source = ([a-z]+)([0-9]+)
global = false
ignoreCase = true
multiline = false
RegExp.input = abc123
RegExp.$1 = abc
RegExp.$2 = 123

2012年10月18日木曜日

[ruby]ディレクトリ配下のファイルリストを取得

Dir. entriesを使う。

ディレクトリ配下の全ファイル一覧を取得

Dir.entries(".").each do |file| puts file end

結果

.
..
test.rb

一部ファイルの除外する場合

entriesの戻りの配列からdelete_ifで必要ないファイル名を削除する。
Dir.entries(".").delete_if do |file| file =~ /^\./ end.each do |file| puts file end

結果

test.rb

2012年10月7日日曜日

PL/SQLの Autonomous Transactions

AUTONOMOUS_TRANSACTIONプラグマを使用すると自律型のトランザクションを定義できます。
このトランザクションは、メイントランザクションと独立しているので、サブプロシージャないの処理を確実にコミットすることができます。
PL/SQLでログテーブルに書き込むときなどに使えるのではないでしょうか。

この無名PL/SQLは、innerサブプロシージャが自律型のトランザクションとなっています。
自律型トランザクション部分のtest1へのinsert処理は必ずコミットされます。
メイントランザクションではロールバックされるので、testへのinsertは取り消されます。
declare
  procedure inner
  is
    PRAGMA AUTONOMOUS_TRANSACTION;
  begin
    insert into test1 values ('1');
    commit;
  end;
begin
    insert into test values ('1');
    inner;
    rollback;
end;
/

実行前

test、test1ともテーブルは空です。
10:22:39 SQL> select * from test;

no rows selected

Elapsed: 00:00:00.00
10:27:56 SQL> select * from test1;

no rows selected

実行

10:27:43 SQL> r
  1  declare
  2    procedure inner
  3    is
  4  PRAGMA AUTONOMOUS_TRANSACTION;
  5    begin
  6  insert into test1 values ('1');
  7  commit;
  8    end;
  9  begin
 10  insert into test values ('1');
 11  inner;
 12  rollback;
 13* end;

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.04
10:28:07 SQL>

実行後

自律型トランザクションのtest1だけinsertされていることがわかる。
10:28:01 SQL> select * from test;

no rows selected

Elapsed: 00:00:00.00
10:28:21 SQL> select * from test1;

C
-
1

Elapsed: 00:00:00.00
10:28:25 SQL> 

2012年9月30日日曜日

PL/SQLで更新結果の取得

SQL%属性を使用して、更新有無や更新件数を取得できます。

下の例は、update文になっているけどdeleteやmergeなどでも同じように取得できます。
begin
  update account set name = '名前変更' where id = '00001';
  -- sql%foundを使用して更新有無を判断
  -- trueの場合は更新あり
  if (sql%found) then
    dbms_output.put_line('updated');
  else
    dbms_output.put_line('no updated');
  end if;
  -- sql%rowcountで更新件数を取得
  dbms_output.put_line(sql%rowcount);
end;

実行結果

updated
1

PL/SQL procedure successfully completed.

2012年9月22日土曜日

GroovyのInheritConstructorsアノテーション

クラスにInheritConstructorsアノテーションを付加すると、親クラスが実装しているコンストラクタをコンパイル時に追加してくれます。

Fugaは、引数を2つうけるコンストラクタを持っていないが「InheritConstructors」を設定しているので、親クラスのHogeが実装しているコンストラクタが追加されていることがわかる。

import groovy.transform.InheritConstructors

class Hoge {

  def hoge1
  def hoge2

  Hoge(hoge1, hoge2) {
    println "Hoge.Hoge"
    this.hoge1 = hoge1
    this.hoge2 = hoge2
  }

  @Override
  public String toString() {
    return "Hoge{" +
            "hoge1=" + hoge1 +
            ", hoge2=" + hoge2 +
            '}';
  }
}

@InheritConstructors
class Fuga extends Hoge {
}

def fuga = new Fuga("hoge1", "hoge2")
println "fuga = ${fuga}"

GroovyのEqualsAndHashCodeアノテーション

equalsとhashCodeを生成してくれるアノテーション

EqualsAndHashCodeを付加してクラスを宣言します。

import groovy.transform.EqualsAndHashCode

@EqualsAndHashCode
class Person {

  String name
  String address
  Date birthDay
  String mailAddress

}

2012年9月16日日曜日

GroovyのTupleConstructorアノテーション

TupleConstructorを付加すると、属性(フィールド)値を引数に取るコンストラクタが追加されます。
コンストラクタの引数の順番は、フィールドの宣言の順番となります。

TupleConstructorを付加してクラスを宣言します。
import groovy.transform.TupleConstructor

@TupleConstructor
class Person {
  String name
  String address
  String email
  Date birthDay
}

使い方は、フィールドの宣言順に値を設定するだけ。
なお、Groovy2.0の新機能のTypeCheckedアノテーション(コンパイル時に型チェックをしてくれるやつ)を付加すると、ちゃんとコンパイルエラーになります。
class Hoge {

  @TypeChecked
  public static void main(String[] args) {

    def person = new Person('name', 'address', 'mail@mail.com', new Date())
  }
}

2012年9月14日金曜日

GroovyのToStringアノテーション

クラスに「ToString」アノテーションを付加すると、コンパイル時にtoStringメソッドが生成されます。

デフォルトでは、すべてのフィールドがtoStringメソッドで文字列変換されますが、アノテーションの属性を設定することで除外設定などもできます。

2012年9月7日金曜日

Nio2でファイル属性

NIO2を使ってファイルの属性を取得する方法。

// 最後の更新日時
System.out.println("Files.getLastModifiedTime(path) = " + Files.getLastModifiedTime(path));
// ファイルサイズ
System.out.println("Files.size(path) = " + Files.size(path));
// 読み込み可能?
System.out.println("Files.isReadable(path) = " + Files.isReadable(path));
// 書き込み可能?
System.out.println("Files.isWritable(path) = " + Files.isWritable(path));
// シンボリックリンク?
System.out.println("Files.isSymbolicLink(path) = " + Files.isSymbolicLink(path));
// ディレクトリ
System.out.println("Files.isDirectory(path) = " + Files.isDirectory(path));
// 属性を纏めて取得
System.out.println("Files.readAttributes(path, \"*\") = " + Files.readAttributes(path, "*"));

2012年8月24日金曜日

NIO2を使ってファイルの作成

Files.createFileを使ってファイルの作成を行う。ファイル作成時にはアクセス権限も設定できたりする。

属性指定なしでファイル作成

Path path = Paths.get("test.txt")
Files.createFile(path)

umaskが022なので644でファイルが作られる。
sh-3.2$ umask
0022
sh-3.2$ ls -ln test.txt
-rw-r--r--  1 501  20  0  8 24 23:40 test.txt


アクセス権限(rwx------)を指定してファイル作成

FileAttribute<Set<PosixFilePermission>> attribute = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------"))
Path path = Paths.get("test.txt")
// 2番目の引数にFileAttributeを指定する。
Files.createFile(path, attribute)

指定したアクセス権限でファイルが作られる。
sh-3.2$ ls -ltr test.txt
-rwx------  1 hove  staff  0  8 24 23:45 test.txt

2012年8月19日日曜日

NIO2で再帰的にファイルを扱う方法

Files.walkFileTreeメソッドを使用して、従来のjava.io.Fileを使う時よりも簡単にディレクトリを再帰的にたどってファイルを扱える。

下のコードだと、ディレクトリを再帰的にたどっていって、拡張子が「.groovy」の場合に標準出力にファイル名(フルパス)を出力しています。
import java.nio.file.*
import java.nio.file.attribute.BasicFileAttributes

def dir = Paths.get("../..")
Files.walkFileTree(dir, new FileVisitor());

class FileVisitor extends SimpleFileVisitor {
  @Override
  FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
    if (file.toString().endsWith(".groovy")) {
      println "groovyファイル:${file.toAbsolutePath().normalize()}"
    }
    return FileVisitResult.CONTINUE
  }
}

2012年8月18日土曜日

java.io.Fileとjava.nio.file.Pathの変換

File.toPathとPath.toFileを使う。

File file = new File('.')
// FileからPathへ
Path path = file.toPath()
// PathからFileへ
File toFile = path.toFile()

2012年8月16日木曜日

NIO2でglobを使ってファイル抽出

Files.newDirectoryStreamの第二引数にglobを指定する。


「*」を使用すると全ての文字
// すべてのファイルにマッチ
Files.newDirectoryStream(path, "*").each {
  println it.fileName
}

// sから始まるファイルにマッチ
Files.newDirectoryStream(path, "s*").each {
  println it.fileName
}

「?」は任意の1文字
// 拡張子をのぞいたファイル名が3文字
Files.newDirectoryStream(path, "???.groovy").each {
  println it.fileName
}

「[]」を使用すると[]の中で指定した文字
// 小文字から始まるファイル
Files.newDirectoryStream(path, "[a-z]*").each {
  println it.fileName
}

// mとnから始まるファイル
Files.newDirectoryStream(path, "[mn]*").each {
  println it.fileName
}

「{}」は、{}内に指定した値のいずれか(カンマ区切りで指定する。)
// 拡張子がjavaとgroovyのファイル
Files.newDirectoryStream(path, "*.{groovy,java}").each {
  println it.fileName
}

2012年8月5日日曜日

NIO2でファイルのコピー

Files#copyでコピーができる。

// コピー元
Path from = Paths.get("C:\\work\\test.txt");
// コピー先
Path to = Paths.get("C:\\work\\test2.txt");

// コピー
Files.copy(from, to);

2012年8月3日金曜日

無効になったPL/SQLのリコンパイル

テーブルの再作成などによって、無効化されたPL/SQLプログラムを抽出して再コンパイルする方法

USER_OBJECTS(場合によっては、ALLだったりする)から、STATUSがINVALIDのPL/SQLプログラムを抽出する。
ここで、抽出されたPL/SQLが無効化されているものなので、ALTER文(alter object_type object_name compile)でコンパイルしなおしてあげる。

以下のSQL文で抽出すると、ALTER文が生成されるので、コピペしてあげればリコンパイルができます。
SELECT 'ALTER ' || OBJECT_TYPE || ' ' || OBJECT_NAME || ' COMPILE;' FROM USER_OBJECTS WHERE STATUS = 'INVALID'

2012年7月22日日曜日

Project Euler-Problem22をgroovyで解いてみる

問題

http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2022

問題を解いたプログラム

1行にすべての値が書かれているとは思わなかった・・・
def alphaRange = 'A'..'Z'
def index = 0
println new File('names.txt').readLines().join(",").split(",").sort().inject(0) {result, line ->
  result + line.split(",").sort().inject(0) {lineTotal, element ->
    lineTotal + (element.inject(0) {elementTotal, chr ->
      elementTotal + alphaRange.indexOf(chr) + 1
    } * (++index))
  }
}

Java7のNIO2-Pathクラス

Java7のNIO2の勉強し始めたので、まずはPathクラスあたりを。

Path path = Paths.get("./test.txt");
System.out.println("path.toString() = " + path.toString());
System.out.println("path.getFileName() = " + path.getFileName());
// 不要な「.」や「\」なんかを取り除いてくれる。
System.out.println("path.normalize() = " + path.normalize());
// 絶対パスかどうか
System.out.println("path.isAbsolute() = " + path.isAbsolute());
// 絶対パスに変換
System.out.println("path.toAbsolutePath() = " + path.toAbsolutePath());
// 不要なものを取り除いて絶対パスに
System.out.println("path.normalize().toAbsolutePath() = " + path.normalize().toAbsolutePath());

実行結果
path.toString() = .\test.txt
path.getFileName() = test.txt
path.normalize() = test.txt
path.isAbsolute() = false
path.toAbsolutePath() = C:\work\test\.\test.txt
path.normalize().toAbsolutePath() = C:\work\test\test.txt

2012年7月21日土曜日

Project Euler-Problem21をgroovyで解いてみる

問題

d(n)をnの真の約数の和と定義する。(真の約数とはn以外の約数のことである。)
もし、d(a) = b かつ d(b) = a (a ≠ b)を満たすとき、aとbは友愛数(親和数)であるという。

例えば、220の約数は1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110なのでd(220) = 284である。
また、284の約数は1, 2, 4, 71, 142なのでd(284) = 220である。

それでは10000未満の友愛数の合計を求めよ。

問題を解いたプログラム

def getSumAliquot(def num) {
  (1..(num / 2)).findAll {num % it == 0}.sum()
}

println((1..<10000).sum {
  def aliquot = getSumAliquot(it)
  it != aliquot && it == getSumAliquot(aliquot) ? aliquot : 0
})

2012年7月16日月曜日

Project Euler-Problem19をgroovyで解いてみる

問題

次の情報が与えられている。

1900年1月1日は月曜日である。
9月、4月、6月、11月は30日まであり、2月を除く他の月は31日まである。
2月は28日まであるが、うるう年のときは29日である。
うるう年は西暦が4で割り切れる年に起こる。しかし、西暦が400で割り切れず100で割り切れる年はうるう年でない。
20世紀(1901年1月1日から2000年12月31日)で月の初めが日曜日になるのは何回あるか。

問題を解いたプログラム

def current = Calendar.getInstance()
current.set(1901, 1, 1)

def end = Calendar.getInstance()
end.set(2000, 12, 31)

int sundayCount = 0
while (current <= end) {
  if (current.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
    sundayCount++
  }
  current.set(Calendar.MONTH, current.get(Calendar.MONTH) + 1)
}
println "sundayCount = ${sundayCount}"

Project Euler-Problem20をgroovyで解いてみる

問題

n × (n - 1) × ... × 3 × 2 × 1 を n! と表す。

100! の各桁の数字の合計を求めよ。。

問題を解いたプログラム

Problem16と同じような構造です。
def ret = (new BigInteger(100)..new BigInteger(1)).inject(new BigInteger(1)) {num1, num2 ->
  num1.multiply(num2)
}.toString().collect{Integer.valueOf(it)}.sum()

println "ret = ${ret}"


解けない問題が増えてきた

2012年7月14日土曜日

Project Euler-Problem16をgroovyで解いてみる

問題

15 = 32768 であり、これの各数字の合計は 3 + 2 + 7 + 6 + 8 = 26 となる。

同様にして、21000 の各数字の合計を求めよ。

問題を解いたプログラム

クロージャがあるから簡単にかけてますが、JavaのAPIを使っているだけです。
import java.text.DecimalFormat

def format = new DecimalFormat("#")
println format.format(new BigInteger(2).pow(1000)).collect {Integer.valueOf(it)}.sum()

7/16:足し込むところを、collectionのsum関数を使うように変更。

2012年7月13日金曜日

[Oracle]pl/sqlの変数宣言

PL/SQLの変数宣言のまとめ

変数

declare
  -- 初期値なしで変数宣言
  v1 char(1);
  -- 初期値ありで変数宣言
  v2 varchar2(100) default 'ほげ';
  -- 他の変数の型で変数宣言
  v3 v2%type default 'ふが';
begin
  dbms_output.put_line(v1);
  dbms_output.put_line(v2);
  dbms_output.put_line(v3);
end;
/

定数

declare
  const_name constant varchar2(100) not null default '定数';
begin
  dbms_output.put_line(const_name);
end;
/

------------------------------
-- 実行結果
------------------------------
定数

PL/SQLプロシージャが正常に完了しました。

定数値を変更しようとすると例外が発生します。
-- 定数値を変更するステートメントを追加した場合
const_name := '書き換え';

------------------------------
-- 実行結果
------------------------------
行5でエラーが発生しました。:
ORA-06550: 行5、列3:
PLS-00363: 式CONST_NAMEは割当てターゲットとして使用できません。
ORA-06550: 行5、列3:
PL/SQL: Statement ignored

NULL不可変数

declare
  -- not nullを属性をつけることで、nullの代入がNGとなる。
  v1 char(1) not null default '1';
begin
  dbms_output.put_line(v1);
end;
/

procedureでnull不可の変数に「null」を代入しようとするとコンパイルエラーとなる
create or replace procedure hoge
is
  -- 初期値なしで変数宣言
  v1 char(1) not null default '1';
  v2 char(1);
begin
  v1 := null;
end;
/

LINE/COL ERROR
-------- -----------------------------------------------------------------
7/3      PL/SQL: Statement ignored
7/9      PLS-00382: 式の型が正しくありません。

procedureでnull不可の変数に別の変数の値を代入した場合、実行時エラーとなる
  1  create or replace procedure hoge
  2  is
  3    -- 初期値なしで変数宣言
  4    v1 char(1) not null default '1';
  5    v2 char(1);
  6  begin
  7    v1 := v2;
  8* end;
16:50:25 SQL> /

プロシージャが作成されました。

経過: 00:00:00.01
16:50:26 SQL> exec hoge
BEGIN hoge; END;

*
行1でエラーが発生しました。:
ORA-06502: PL/SQL: 数値または値のエラーが発生しました
ORA-06512: "HOGE", 行7
ORA-06512: 行1

2012年7月8日日曜日

[Oracle]PL/SQLでの数値計算はPLS_INTEGER(サブタイプ含む)を使用する

「PL/SQL言語リファレンス」によると、PL/SQLでの数値計算はNUMBERを使用するより、PLS_INTEGER(またはそのサブタイプ)を使用したほうが高速に処理できるようです。詳細は、以下のドキュメントに記述されています。

PLS_INTEGERおよびBINARY_INTEGERデータ型

また、上記のドキュメントによるとNULLが許容されずに計算時にオーバーフローが起こり得ない数値の場合には、PLS_INTEGERのサブタイプの「SIMPLE_INTEGER」を使用するほうがより高速なようです。

SIMPLE_INTEGERの詳細
PLS_INTEGERのSIMPLE_INTEGERサブタイプ

今まで、PLS_INTEGERを使うようにしてきたけど、用途によってはSIMPLE_INTEGERも検討しないと。

2012年6月24日日曜日

Project Euler-Problem14をgroovyで解いてみる

問題

正の整数に以下の式で繰り返し生成する数列を定義する。

n → n/2 (n が偶数)

n → 3n + 1 (n が奇数)

13からはじめるとこの数列は以下のようになる。

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
13から1まで10個の項になる。 この数列はどのような数字からはじめても最終的には 1 になると考えられているが、まだそのことは証明されていない(コラッツ問題)

さて、100万未満の数字の中でどの数字からはじめれば一番長い数列を生成するか。

注意: 数列の途中で100万以上になってもよい

問題を解いたプログラム

最初何も考えずに作ったら終わる気配が全くなく・・・。次にListで生成した数列自体をキャッシュしたが、全く意味がなく。最後に、Hashに生成した数列のサイズをキャッシュするように。これでなんとか処理が終わるようになった。
result = [:]

def next(long num) {
  num % 2 == 0 ? num / 2 : num * 3 + 1
}

def makeNumSeq(long num) {
  def count = 0
  long temp = num
  while (temp > 1) {
    temp = next(temp)
    def cacheCount = result[temp]
    if (cacheCount) {
      count += cacheCount
      break
    }
    count++
  }
  result[num] = count
}

(999999..1).each {it
  makeNumSeq(it)
}

println result.max {it.value}

2012年6月17日日曜日

[Oracle]PL/SQLでエラーハンドリング

PL/SQLのエラーハンドリングの纏め。

エラーハンドリング方法

エラーハンドリングは、EXCEPTIONブロックで行う。
補足する例外は、when句で指定することができて、名前付き例外を指定したりすることができる。
全ての例外を補足することを意味する「others」は、一番最後のwhen句のみに指定できる。
exception
  when no_data_found then      -- no_data_found例外の場合
    dbms_output.put_line('data not faound');
  when others then             -- 上記に該当しない場合
    dbms_output.put_line('other error');

複数のエラーで同一のエラー処理を行う必要がある場合には、下のようにwhen句で「or」でつないで複数の例外を指定すれば良い。
下の場合だと、no_data_foundかzero_divideが発生した場合に、このwhen句のブロック内のステートメントが実行される。
when no_data_found or zero_divide then

名前付き例外の宣言

名前付き例外として定義されていない例外は、PRAGMA EXCEPTION_INITを使用して名前付き例外を定義することができる。
declare
  hoge_error exception;
  pragma exception_init(hoge_error, -1843);
begin
  raise hoge_error;
exception
  when hoge_error then
    dbms_output.put_line('hoge_error');
    dbms_output.put_line(sqlerrm);
  when others then
    dbms_output.put_line('other error');
    dbms_output.put_line(sqlerrm);
end;
実行結果
hoge_errorが、when hoge_errorで補足できていることがわかる。また、ORA-01843とhoge_errorが紐付けられていることもわかる。
hoge_error
ORA-01843: not a valid month

PL/SQL procedure successfully completed.

名前付き例外を使わない場合は、othersで補足して分岐を書かなければならない。下のコードを見るとわかるけど、明らかに可読性が悪い。
when others then
  if sqlcode = -1843 then
    dbms_output.put_line('-1843');
    return;
  end if;

例外に対応するメッセージの取得

sqlerrmを使用すると、例外に対応するメッセージを取得できる。

sqlerrmは、exception句で使用すると発生した例外に対するメッセージを取得できる。また、任意のエラーコードを引数に指定すると、指定したコードに対するメッセージも取得することができる。

以下のプログラムで動きを見てみると。
declare
begin
  dbms_output.put_line(sqlerrm);     -- exceptionブロック意外でsqlerrmを使用
  dbms_output.put_line(sqlerrm(-1)); -- 一意制約のエラーコードを指定
  raise no_data_found;
exception
  when others then
    dbms_output.put_line(sqlerrm);   -- exceptionブロックで使用
end;

実行結果は、下のようになる。
ORA-0000: normal, successful completion     -- 正常を表すメッセージが取得できる。
ORA-00001: unique constraint (.) violated   -- 一意制約違反を表すメッセージ
ORA-01403: no data found                    -- exceptionブロックで補足した例外のメッセージ

Project Euler-Problem13をgroovyで解いてみる

問題

以下の50桁の数字100個の総和の上位10桁を求めよ。

37107287533902102798797998220837590246510135740250
46376937677490009712648124896970078050417018260538
74324986199524741059474233309513058123726617309629
91942213363574161572522430563301811072406154908250
23067588207539346171171980310421047513778063246676
89261670696623633820136378418383684178734361726757
28112879812849979408065481931592621691275889832738
44274228917432520321923589422876796487670272189318
47451445736001306439091167216856844588711603153276
70386486105843025439939619828917593665686757934951
62176457141856560629502157223196586755079324193331
64906352462741904929101432445813822663347944758178
92575867718337217661963751590579239728245598838407
58203565325359399008402633568948830189458628227828
80181199384826282014278194139940567587151170094390
35398664372827112653829987240784473053190104293586
86515506006295864861532075273371959191420517255829
71693888707715466499115593487603532921714970056938
54370070576826684624621495650076471787294438377604
53282654108756828443191190634694037855217779295145
36123272525000296071075082563815656710885258350721
45876576172410976447339110607218265236877223636045
17423706905851860660448207621209813287860733969412
81142660418086830619328460811191061556940512689692
51934325451728388641918047049293215058642563049483
62467221648435076201727918039944693004732956340691
15732444386908125794514089057706229429197107928209
55037687525678773091862540744969844508330393682126
18336384825330154686196124348767681297534375946515
80386287592878490201521685554828717201219257766954
78182833757993103614740356856449095527097864797581
16726320100436897842553539920931837441497806860984
48403098129077791799088218795327364475675590848030
87086987551392711854517078544161852424320693150332
59959406895756536782107074926966537676326235447210
69793950679652694742597709739166693763042633987085
41052684708299085211399427365734116182760315001271
65378607361501080857009149939512557028198746004375
35829035317434717326932123578154982629742552737307
94953759765105305946966067683156574377167401875275
88902802571733229619176668713819931811048770190271
25267680276078003013678680992525463401061632866526
36270218540497705585629946580636237993140746255962
24074486908231174977792365466257246923322810917141
91430288197103288597806669760892938638285025333403
34413065578016127815921815005561868836468420090470
23053081172816430487623791969842487255036638784583
11487696932154902810424020138335124462181441773470
63783299490636259666498587618221225225512486764533
67720186971698544312419572409913959008952310058822
95548255300263520781532296796249481641953868218774
76085327132285723110424803456124867697064507995236
37774242535411291684276865538926205024910326572967
23701913275725675285653248258265463092207058596522
29798860272258331913126375147341994889534765745501
18495701454879288984856827726077713721403798879715
38298203783031473527721580348144513491373226651381
34829543829199918180278916522431027392251122869539
40957953066405232632538044100059654939159879593635
29746152185502371307642255121183693803580388584903
41698116222072977186158236678424689157993532961922
62467957194401269043877107275048102390895523597457
23189706772547915061505504953922979530901129967519
86188088225875314529584099251203829009407770775672
11306739708304724483816533873502340845647058077308
82959174767140363198008187129011875491310547126581
97623331044818386269515456334926366572897563400500
42846280183517070527831839425882145521227251250327
55121603546981200581762165212827652751691296897789
32238195734329339946437501907836945765883352399886
75506164965184775180738168837861091527357929701337
62177842752192623401942399639168044983993173312731
32924185707147349566916674687634660915035914677504
99518671430235219628894890102423325116913619626622
73267460800591547471830798392868535206946944540724
76841822524674417161514036427982273348055556214818
97142617910342598647204516893989422179826088076852
87783646182799346313767754307809363333018982642090
10848802521674670883215120185883543223812876952786
71329612474782464538636993009049310363619763878039
62184073572399794223406235393808339651327408011116
66627891981488087797941876876144230030984490851411
60661826293682836764744779239180335110989069790714
85786944089552990653640447425576083659976645795096
66024396409905389607120198219976047599490197230297
64913982680032973156037120041377903785566085089252
16730939319872750275468906903707539413042652315011
94809377245048795150954100921645863754710598436791
78639167021187492431995700641917969777599028300699
15368713711936614952811305876380278410754449733078
40789923115535562561142322423255033685442488917353
44889911501440648020369068063960672322193204149535
41503128880339536053299340368006977710650566631954
81234880673210146739058568557934581403627822703280
82616570773948327592232845941706525094512325230608
22918802058777319719839450180888072429661980811197
77158542502016545090413245809786882778948721859617
72107838435069186155435662884062257473692284509516
20849603980134001723930671666823555245252804609722
53503534226472524250874054075591789781264330331690

問題を解いたプログラム

ヒアドキュメントを入力として、改行で分割した値を足し込んだ結果の上位10桁を取得してます。
input = """37107287533902102798797998220837590246510135740250
46376937677490009712648124896970078050417018260538
74324986199524741059474233309513058123726617309629
91942213363574161572522430563301811072406154908250
23067588207539346171171980310421047513778063246676
89261670696623633820136378418383684178734361726757
28112879812849979408065481931592621691275889832738
44274228917432520321923589422876796487670272189318
47451445736001306439091167216856844588711603153276
70386486105843025439939619828917593665686757934951
62176457141856560629502157223196586755079324193331
64906352462741904929101432445813822663347944758178
92575867718337217661963751590579239728245598838407
58203565325359399008402633568948830189458628227828
80181199384826282014278194139940567587151170094390
35398664372827112653829987240784473053190104293586
86515506006295864861532075273371959191420517255829
71693888707715466499115593487603532921714970056938
54370070576826684624621495650076471787294438377604
53282654108756828443191190634694037855217779295145
36123272525000296071075082563815656710885258350721
45876576172410976447339110607218265236877223636045
17423706905851860660448207621209813287860733969412
81142660418086830619328460811191061556940512689692
51934325451728388641918047049293215058642563049483
62467221648435076201727918039944693004732956340691
15732444386908125794514089057706229429197107928209
55037687525678773091862540744969844508330393682126
18336384825330154686196124348767681297534375946515
80386287592878490201521685554828717201219257766954
78182833757993103614740356856449095527097864797581
16726320100436897842553539920931837441497806860984
48403098129077791799088218795327364475675590848030
87086987551392711854517078544161852424320693150332
59959406895756536782107074926966537676326235447210
69793950679652694742597709739166693763042633987085
41052684708299085211399427365734116182760315001271
65378607361501080857009149939512557028198746004375
35829035317434717326932123578154982629742552737307
94953759765105305946966067683156574377167401875275
88902802571733229619176668713819931811048770190271
25267680276078003013678680992525463401061632866526
36270218540497705585629946580636237993140746255962
24074486908231174977792365466257246923322810917141
91430288197103288597806669760892938638285025333403
34413065578016127815921815005561868836468420090470
23053081172816430487623791969842487255036638784583
11487696932154902810424020138335124462181441773470
63783299490636259666498587618221225225512486764533
67720186971698544312419572409913959008952310058822
95548255300263520781532296796249481641953868218774
76085327132285723110424803456124867697064507995236
37774242535411291684276865538926205024910326572967
23701913275725675285653248258265463092207058596522
29798860272258331913126375147341994889534765745501
18495701454879288984856827726077713721403798879715
38298203783031473527721580348144513491373226651381
34829543829199918180278916522431027392251122869539
40957953066405232632538044100059654939159879593635
29746152185502371307642255121183693803580388584903
41698116222072977186158236678424689157993532961922
62467957194401269043877107275048102390895523597457
23189706772547915061505504953922979530901129967519
86188088225875314529584099251203829009407770775672
11306739708304724483816533873502340845647058077308
82959174767140363198008187129011875491310547126581
97623331044818386269515456334926366572897563400500
42846280183517070527831839425882145521227251250327
55121603546981200581762165212827652751691296897789
32238195734329339946437501907836945765883352399886
75506164965184775180738168837861091527357929701337
62177842752192623401942399639168044983993173312731
32924185707147349566916674687634660915035914677504
99518671430235219628894890102423325116913619626622
73267460800591547471830798392868535206946944540724
76841822524674417161514036427982273348055556214818
97142617910342598647204516893989422179826088076852
87783646182799346313767754307809363333018982642090
10848802521674670883215120185883543223812876952786
71329612474782464538636993009049310363619763878039
62184073572399794223406235393808339651327408011116
66627891981488087797941876876144230030984490851411
60661826293682836764744779239180335110989069790714
85786944089552990653640447425576083659976645795096
66024396409905389607120198219976047599490197230297
64913982680032973156037120041377903785566085089252
16730939319872750275468906903707539413042652315011
94809377245048795150954100921645863754710598436791
78639167021187492431995700641917969777599028300699
15368713711936614952811305876380278410754449733078
40789923115535562561142322423255033685442488917353
44889911501440648020369068063960672322193204149535
41503128880339536053299340368006977710650566631954
81234880673210146739058568557934581403627822703280
82616570773948327592232845941706525094512325230608
22918802058777319719839450180888072429661980811197
77158542502016545090413245809786882778948721859617
72107838435069186155435662884062257473692284509516
20849603980134001723930671666823555245252804609722
53503534226472524250874054075591789781264330331690"""

println input.split(/\n/).inject(0.0) {n1, n2 -> n1.add(new BigDecimal(n2))}.toString().substring(0, 10)

2012年6月10日日曜日

[Oracle]PL/SQLでエラー発生時にcallStackを取得する

DBMS_UTILITY.FORMAT_ERROR_BACKTRACEファンクションを使用すると、PL/SQLのEXCEPTIONブロックでエラー発生時のcallStackを取得できる。

下のコードでは、無名ブロック→hoge1→hoge2の順で呼び出していき、hoge2でエラーが発生します。
そのエラーを無名ブロックで補足して、「format_error_backtrace」を使用してcallStackeを表示するとエラー発生箇所までどのように呼び出されてきたかを確認できます。
11:08:43 SQL> r
  1  declare
  2    procedure hoge2 is
  3    begin
  4      raise no_data_found;
  5    end;
  6    procedure hoge1 is
  7    begin
  8      dbms_output.put_line('hoge1');
  9      hoge2;
 10    end;
 11  begin
 12    hoge1;
 13  exception
 14    when others
 15    then
 16       dbms_output.put_line(dbms_utility.format_error_backtrace); -- format_error_backtraceを使用して、callStackを表示する。
 17* end;
hoge1
ORA-06512: at line 4
ORA-06512: at line 9
ORA-06512: at line 12
PL/SQL procedure successfully completed.

2012年6月9日土曜日

Project Euler-Problem12をgroovyで解いてみる

問題

三角数の数列は自然数の和で表わされ、7番目の三角数は 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28 である。 三角数の最初の10項は

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
となる。

最初の7項について、その約数を列挙すると、以下のとおり。

 1: 1
 3: 1,3
 6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28

これから、7番目の三角数である28は、6個以上の約数をもつ最初の三角数であることが分る。
では、501 個以上の約数をもつ最初の三角数はいくらか。

問題を解いたプログラム

def getAliquot(def num) {
  def results = (1..Math.sqrt(num)).findResults {
    if (num % it == 0) {
      it
    }
  }
  results.size() * 2
}

def num = 1
def triangularNumbers = num
while (getAliquot(triangularNumbers) <= 500){
  num++
  triangularNumbers += num
}

println "num = ${triangularNumbers}"

2012年6月7日木曜日

[Oracle]PL/SQLのループでcontinue

Oracle11gから、ループ処理内でcontinueが使えるようになったようです。

例えば奇数の場合だけ処理を行うようなループは下のコードのようになります。
begin
  for i in 1 .. 10
  loop
    continue when mod(i, 2) = 0;  -- continueを使って偶数の場合は処理をスキップ
    dbms_output.put_line(i);
  end loop;
end;
/

処理結果を見ると奇数の場合だけ処理されていることがわかります。
23:14:04 SQL> /
1
3
5
7
9

2012年6月3日日曜日

[Oracle]PL/SQLのカーソルループ

取得したデータを単純に処理したい場合(取得結果のレコードをループの外で必要としない場合)は、カーソルループを使うと良い。
ほとんどのケースが、単純にいけるはずなのでこの実装のほうが良い気がする。

コードを見るとわかるが、カーソルのオープンやクローズ、ループの終了条件がないのがわかる。
begin
  for rec in (select col1 from test)   -- for文のin句にカーソルを指定する。ここで指定するカーソルは、事前に(declare)で定義したカーソルを指定することができる。
  loop
    dbms_output.put_line(rec.col1);
  end loop;
end;

2012年5月29日火曜日

Project Euler-Problem11をgroovyで解いてみる

問題

08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48

上の 20 × 20 の数字のなか、赤くマークされた数字の積は 26 × 63 × 78 × 14 = 1788696 となる。

上下左右斜めのいずれかの方向で連続する4つの数字の積のうち最大のものを求めよ。

問題を解いたプログラム

ベタベタな感じでしかとけません・・・。
def input = [
        [8, 02, 22, 97, 38, 15, 00, 40, 00, 75, 04, 05, 07, 78, 52, 12, 50, 77, 91, 8],
        [49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 04, 56, 62, 00],
        [81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 03, 49, 13, 36, 65],
        [52, 70, 95, 23, 04, 60, 11, 42, 69, 24, 68, 56, 01, 32, 56, 71, 37, 02, 36, 91],
        [22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80],
        [24, 47, 32, 60, 99, 03, 45, 02, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50],
        [32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70],
        [67, 26, 20, 68, 02, 62, 12, 20, 95, 63, 94, 39, 63, 8, 40, 91, 66, 49, 94, 21],
        [24, 55, 58, 05, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72],
        [21, 36, 23, 9, 75, 00, 76, 44, 20, 45, 35, 14, 00, 61, 33, 97, 34, 31, 33, 95],
        [78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 03, 80, 04, 62, 16, 14, 9, 53, 56, 92],
        [16, 39, 05, 42, 96, 35, 31, 47, 55, 58, 88, 24, 00, 17, 54, 24, 36, 29, 85, 57],
        [86, 56, 00, 48, 35, 71, 89, 07, 05, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58],
        [19, 80, 81, 68, 05, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 04, 89, 55, 40],
        [04, 52, 8, 83, 97, 35, 99, 16, 07, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66],
        [88, 36, 68, 87, 57, 62, 20, 72, 03, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69],
        [04, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 8, 46, 29, 32, 40, 62, 76, 36],
        [20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 04, 36, 16],
        [20, 73, 35, 29, 78, 31, 90, 01, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 05, 54],
        [01, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 01, 89, 19, 67, 48]]

def size = 20
def ret = (0..<size).findResults {row ->
  (0..<size).findResults {col ->
    [
            col < 17 ? (input[row][col..<col + 4]).inject(1) {n1, n2 -> n1 * n2} : 0,
            col < 17 && row < 17 ? [input[row][col], input[row + 1][col + 1], input[row + 2][col + 2], input[row + 3][col + 3]].inject(1) {n1, n2 -> n1 * n2} : 0,
            col >= 3 && row < 17 ? [input[row][col], input[row + 1][col - 1], input[row + 2][col - 2], input[row + 3][col - 3]].inject(1) {n1, n2 -> n1 * n2} : 0,
            row < 17 ? [input[row][col], input[row + 1][col], input[row + 2][col], input[row + 3][col]].inject(1) {n1, n2 -> n1 * n2} : 0
    ].max()
  }.max()
}.max()
println(ret)

2012年5月27日日曜日

Project Euler-Problem10をgroovyで解いてみる

問題

10以下の素数の和は2 + 3 + 5 + 7 = 17である.
200万以下の全ての素数の和を計算しなさい.

問題を解いたプログラム

処理時間はものすごくかかります。(3分弱かな)
import common.Prime

def prime = new Prime()
def sum = prime.primes(2000000).sum()
println "sum = ${sum}"

Primeクラスはのprimesはiteratorを返すようにしてます。
package common

class Prime {

  def primes(int max) {
    return new Iterator<Long>() {

      def primes = []

      boolean hasNext() {
        def start = primes ? primes.max() + 1 : 2
        def result = (start..max).findResult {
          if (isPriem(it)) {
            it
          }
        }
        if (result) {
          primes << result
          primes.last() < max
        } else {
          false
        }
      }

      Long next() {
        primes.last()
      }

      void remove() {
        throw new UnsupportedOperationException()
      }

      private def isPriem(int num) {
        if (num == 2) {
          true
        } else if (num % 2 == 0) {
          false
        } else {
          def sqrt = Math.sqrt(num).toInteger()
          primes.findResult(true) {
            if (it > sqrt) {
              true
            } else if (num % it == 0) {
              false
            }
          }
        }
      }
    };
  }
}

[Oracle]PL/SQLで範囲を指定してループ

昇順でループ

1から5までの範囲で昇順にループされます。
begin
    for i in 1 .. 5
    loop
        dbms_output.put_line(i);
    end loop;
end;

降順でループ

reverseキーワードを指定すると降順にループできます。
begin
    for i in reverse 1 .. 5
    loop
        dbms_output.put_line(i);
    end loop;
end;

ちなみに、降順でループさせたい時に範囲を「最大値 .. 最小値」と指定してもループ処理がおこなわれないのできをつける。

2012年5月14日月曜日

[Oracle]文字列のtrim

trim(rtrim,ltrim)の使い方。
-- スペースをtrim
select trim('  aa  ') from dual;

-- 指定した文字をtrim
-- bothを指定しているので、前後両方がtrim対象
select trim(both 'b' from 'bbaabb') from dual;

-- leadingを指定しているので、前方がtrim対象
select trim(leading 'b' from 'bbaabb') from dual;
-- leadingを使うならば、ltrimを使ったほうが良い
select ltrim('bbaabb', 'b') from dual;

-- trailingを指定しているので、後方がtrim対象
select trim(trailing 'b' from 'bbaabb') from dual;
-- trailingを使うならばrtrimを使ったほうが良い
select rtrim('bbaabb', 'b') from dual;

2012年5月13日日曜日

Project Euler-Problem9をgroovyで解いてみる

問題

ピタゴラスの三つ組(ピタゴラスの定理を満たす自然数)とはa<b<cで
a² + b² = c²
を満たす数の組である.

例えば, 3² + 4² = 9 + 16 = 25 = 5²である.

a + b + c = 1000となるピタゴラスの三つ組が一つだけ存在する. このa,b,cの積を計算しなさい.

問題を解いたプログラム

aとbをループでまわして、cは計算で求めてと単純な感じで。無駄にループしてない文そこまで遅くない。
def ret = (1..999).findResult { a->
  ((a + 1) .. 1000).findResult() {b ->
    def c = 1000 - a - b
    if (a * a + b * b == c * c) {
      a * b * c
    }
  }
}
println "ret = ${ret}"

[Groovy]booleanを返す式

Javaと比べて、オブジェクトの状態チェック(nullや空かなど)が簡単にできる。

//******************************************************************************
// 文字列
//******************************************************************************
assert !null      // nullはfalse
assert !''        // 空文字もfalse
assert 'a'        // 1文字以上あるとtrue
assert """
"""               // 改行があるからtrue

//******************************************************************************
// 数値
//******************************************************************************
assert !0         // 0はfalse
assert 0.1        // 非0はtrue
assert 1L         // 非0はtrue

//******************************************************************************
// コレクション系
//******************************************************************************
assert ![]        // 空のリストはfalse
assert ![:]       // 空のMapはfalse
assert [1]        // 要素があるのでtrue
assert [1:1]      // 要素があるのでtrue

//******************************************************************************
// オブジェクト
//******************************************************************************
assert new Object()           // null意外なのでtrue
assert !new Object() {        // asBooleanでfalseを返しているので、常にfalse
  boolean asBoolean() {false}
}

2012年5月12日土曜日

Project Euler-Problem8をgroovyで解いてみる

問題

以下の1000桁の数字から5つの連続する数字を取り出して その積を計算する。そのような積の中で最大のものの値はいくらか

73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450

EX 6桁の数123789なら、1*2*3*7*8と2*3*7*8*9の二通りとなり、後者の2*3*7*8*9=3024が最大の積となる。

問題を解いたプログラム

Iteratorで連続する5つの数字の積を返して、その最大値を求めてます。
String.metaClass.next = {int size ->
  def str = delegate.toString().replaceAll(/\r|\n/, "")
  if (size > str.size()) {
    return null
  }
  new Iterator<Integer>() {
    def result = []
    def pos = 0
    boolean hasNext() {
      pos < str.size()
    }
    Integer next() {
      if (result.isEmpty()) {
        (str[0..<size]).each {result << it.toInteger()}
        pos = 5
      } else {
        result.remove(0)
        pos <= str.size() ? result.add(str[pos++].toInteger()) : null
      }
      result.inject(1) {n1, n2 -> n1 * nn}
    }

    void remove() {
      throw new UnsupportedOperationException("unsupported remove.")
    }
  }
}
def input = """
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450
"""

println(input.next(5).inject(0) {max, n -> Math.max(max, n)})

[Oracle]LPADとRPAD

LPADもRPADも使い方は同じ。

第一引数

文字列

第二引数

桁数

第三引数(任意)

桁を揃えるために使う文字列。指定しなかった場合はスペースになる。

使用例

-- 左スペース埋めで10桁にする
select '[' || lpad('hoge', 10) || ']' from dual
-- 右スペース埋めで10桁にする
select '[' || rpad('hoge', 10) || ']' from dual

-- スペース以外を使用する場合は、3番目にその値を指定する。
select '[' || lpad('hoge', 10, '.') || ']' from dual
select '[' || lpad('hoge', 10, '.') || ']' from dual

-- 3番目には、2文字以上の値も指定できる。
-- この場合は、変換後の値は「abhoge」となる。(指定した値より長くなることなハイ)
select '[' || lpad('hoge', 6, 'abc') || ']' from dual

-- そもそも指定した文字が、サイズより小さい場合は切り捨てられる。
select '[' || lpad('hoge', 1, 'abc') || ']' from dual

2012年5月5日土曜日

Project Euler-Problem7をgroovyで解いてみる

問題

素数を小さい方から6つ並べると 2, 3, 5, 7, 11, 13 であり、6番目の素数は 13 である。

10001 番目の素数を求めよ。

問題を解いたプログラム

なんのひねりもないコードですが・・・
def primes = []
def num = 2;
while (primes.size() < 10001) {
  if (!primes.find {num % it == 0}) {
      primes << num
  }
  num++
}
println primes.last()

2012年5月4日金曜日

Groovyでカリー化

クロージャのcurryメソッドを使うとカリー化ができる。
def sum = {n1, n2 -> n1 + n2}
def curry = sum.curry(100)  // 最初のパラメータを100で固定してカリー化
println curry(100)  // 200
println curry(200)  // 300

Project Euler-Problem6をgroovyで解いてみる

問題

最初の10個の自然数について、その和の二乗と、二乗数の和は以下の通り。

1² + 2² + ... + 10² = 385
(1 + 2 + ... + 10)² = 3025
これらの数の差は 3025 - 385 = 2640 となる。

同様にして、最初の100個の自然数について和の二乗と二乗の和の差を求めよ。

問題を解いたプログラム

ありきたりな感じに、1から100までの和の二乗と、1から100までのそれぞれの二乗の和を求めてから差をもとめてるだけ。
def ret = (long) Math.pow((1..100).sum(), 2) - (1..100).inject(0) {n1, n2 -> n1 + (int) Math.pow(n2, 2) }
println "ret = $ret"

2012年5月2日水曜日

Project Euler-Problem5をgroovyで解いてみる

問題

2520 は 1 から 10 の数字の全ての整数で割り切れる数字であり、そのような数字の中では最小の値である。

では、1 から 20 までの整数全てで割り切れる数字の中で最小の値はいくらになるか。

問題を解いたプログラム

最小公倍数を求めていって、結果をだしいます。
流れとしては、下のような感じになっています。
1と2→2
2と3→6
6と3→6
6と4→12
〜省略〜
12252240と19→232792560
232792560と20→232792560

private int lcm(int n1, int n2) {
  def ret = n1
  while (ret % n2 != 0) {
    ret += n1
  }
  return ret
}
def ret = (1 .. 20).inject(1) {n1, n2 -> lcm(n1, n2) }
println "ret = $ret"

2012年4月30日月曜日

Project Euler-Problem4をgroovyで解いてみる

問題

左右どちらから読んでも同じ値になる数を回文数という。 2桁の数の積で表される回文数のうち、最大のものは 9009 = 91 × 99 である。

では、3桁の数の積で表される回文数のうち最大のものはいくらになるか。

答えを求めたコード

999から回文数を求めて、最も大きい数字を最後に取り出すだけの単純なコードです。
private Boolean isPalindrome(int num) {
  num.toString() == num.toString().reverse()
}

private Integer getMaxPalindrome(int num) {
  (num .. 100).findResult {
    if (isPalindrome(num * it)) {
      num * it
    }
  }
}
def ret = (999..100).collect {
  getMaxPalindrome(it)
}
println "{ret.max()} = ${ret.max()}"

2012年4月25日水曜日

Project Euler-Problem3をgroovyで解いてみる

問題内容

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?
和訳は・・・
13195 の素因数は 5、7、13、29 である。

600851475143 の素因数のうち最大のものを求めよ。

コード

単純に割り切れる値を求めて、その値が自分より小さい素数に含まれていないことをチェックしています。
def primes = []
(2..Math.sqrt(600851475143)).each {
  if (600851475143 % it == 0 && !(primes.find {prime -> it % prime == 0})) {
    primes << it
  }
}
println primes.max()

2012年4月22日日曜日

[groovy]正規表現パターンをコンパイルして使おう

正規表現パターンをコンパイルして使用する方法。
スラッシュでパターンを構築しても、単なる文字列なのでこれだと毎回コンパイルされるので、
コンパイルしてjava.util.regex.Patternにしてあげるのが良い。
def p = ~/\w/    // 正規表現文字列を「~」でコンパイルする
def s = /\w/

// 「~」でコンパイルしているのでPatternオブジェクトになる。
assert p instanceof java.util.regex.Pattern
// スラッシュで構築したパターンはStringオブジェクトのまま
assert s instanceof java.lang.String

2012年4月15日日曜日

[groovy]正規表現のパターン定義

パターン定義はjavaと同じ。
ただい、正規表現パターンの文字列を「"」ではなく「/」で定義すると余計なエスケープがいらなくなる。

assert "hoge." =~ /\./   // 余計なエスケープがいらない
assert "hoge." =~ "\\."    // 「\」のエスケープが必要

[groovy]Immutableなクラス

@ImmutableアノテーションをクラスにつけてあげるとImmutableなクラスが実現できる。

※Immutableアノテーションは、groovy.langパッケージにもあるけど、非推奨になっているのでgroovy.transformの方をしようする。

Immutableなクラスの例

import groovy.transform.Immutable

@Immutable
class Hoge {
  String hoge
  int num
}

Immutableなクラスを変更しようとするとどうなるか?

Hogeクラスをインスタンス化し、hogeプロパティを変更してみます。
def hoge = new Hoge(hoge: "hoge", num: 100)
hoge.hoge = "変更"

実行してみると、ReadOnlyPropertyExceptionが発生し、クラスの状態が変更できないことがわかります。
Caught: groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: hoge for class: goovy.immutable.Hoge
groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: hoge for class: goovy.immutable.Hoge
 at goovy.immutable.Hoge.setProperty(Hoge.groovy)
 at goovy.immutable.main.run(main.groovy:6)

==演算子

Immutableなクラスにしてあげると、「==」演算子をオーバライドしてくれます。

お試しコード。
def hoge = new Hoge(hoge: "hoge", num: 100)

// immutableなオブジェクトは、「==」をオーバライドしてくれるから、
// 同じあたいかどうかになる
assert hoge == new Hoge(hoge: "hoge", num: 100)
assert hoge != new Hoge(hoge: "hoge", num: 101)

def mutableHoge = new MutableHoge(hoge: "hoge", num : 100)
// mutableなオブジェクトは、==がオーバライドされないので同一インスタンスかの比較
assert mutableHoge != new MutableHoge(hoge: "hoge", num : 100)


ImmutableだとtoStringまで実装される

Immutableなクラスだと、toStringまで追加されるようです。

Immutableでないと、「hoge = goovy.immutable.Hoge@6c0089ab」な感じになりますが、Immutableだと「hoge = goovy.immutable.Hoge(hoge:hoge, num:100)」なります。


2012年4月12日木曜日

keytoolを使ってみた

keytoolを使用して、暗号化の鍵を生成してみよう。

※keytoolは、JAVA_HOME/bin配下にいます。

鍵を登録

keytoolの「-genseckey」を使用して暗号化の鍵を登録できます。 【ポイント】
  • storetypeには、「JCEKS」を指定する。
  • keyalgには、鍵を生成するためのアルゴリズムを指定する。
  • keysizeは、秘密鍵を生成する際には必須。今回は、AES暗号用の128ビットの鍵を生成している。
  • keystoreのファイル名。指定しない場合は、HOME/.keystoreとなる。
  • aliasには、鍵を識別するための任意の名前を指定する。 KeyStore#getKeyを使用して、鍵を取得する際に指定する名前となる。
  • storepassには、キーストアにアクセスするためのパスワードを設定する。
keytool -genseckey -storetype JCEKS -keyalg AES -keysize 128 -keystore ./.key -storepass password -alias key1 

上記コマンド実行後に、以下のメッセージが表示されます。 鍵ごとにパスワードを設定する場合には、新しいパスワードを入力します。 keysotreにアクセスする際に必要となるパスワードと同じにする場合には、なにも入力しなくて大丈夫です。
 の鍵パスワードを入力してください。 (キーストアのパスワードと同じ場合は RETURN を押してください): 

登録されている鍵をリスト表示

listを指定すると、登録されている鍵や証明書をリスト表示することが出来ます。

$ keytool -list -storepass password -keystore .key -storetype JCEKS

キーストアのタイプ: JCEKS キーストアのプロバイダ: SunJCE

キーストアには 2 エントリが含まれます。

key1, 2012/04/12, SecretKeyEntry, mykey, 2012/04/12, SecretKeyEntry, 

登録されている鍵を削除

deleteを指定すると登録されている鍵を削除できます。 deleteを実行後にlist表示してみると、鍵が上のlist表示の時から減っていることが分かります。
$ keytool -delete -alias mykey -keystore .key -storepass password -storetype JCEKS $ keytool -list -storepass password -keystore .key -storetype JCEKS

キーストアのタイプ: JCEKS キーストアのプロバイダ: SunJCE

キーストアには 1 エントリが含まれます。

key1, 2012/04/12, SecretKeyEntry, 

2012年4月5日木曜日

groovyの文字列操作

groovyの文字列操作。

基本的にJavaのStringにあるメソッドは使えるが、それが拡張されていて文字列をさらに扱いやすくなっている。

def str = 'Hello World.'

assert str.startsWith('Hello')

// 特定位置の文字を取得
assert str.charAt(0) == 'H'   // これは、java.lang.Stringのメソッド
assert str.getAt(0) == 'H'    // これは、groovyのメソッド
assert str[0] == 'H'

// 文字の存在チェック
assert str.contains("World")

// substring
assert str[0..4] == 'Hello'   // 0〜4文字目
assert str[0..<5] == 'Hello'  // 0〜4文字目
def range = (0..4)
assert str[range] == 'Hello'  // Rangeを指定してもOK

// 連結や除去
assert 'Hi' + str + '!' - 'Hello' - '.' == 'Hi World!'
assert "Hi${str}!" - 'Hello' - '.' == 'Hi World!'

// 文字数のカウント
assert str.count('l') == 3

// 整形
assert "100".padLeft(5, '0') == '00100'   // 先頭0埋め
assert "100".padLeft(5) == '  100'        // 先頭スペース埋め

// 増幅
assert "100" * 2 == '100100'

Project Euler-Problem 2をgroovyで解いてみる

問題はこちらを見てね。http://se-bikou.blogspot.jp/2012/03/project-euler-problem-2scala.html

単純にListに、フィボナッチ数列を詰めて行って、その値が400万を超えたらループを終えています。
で、求めた数列の中から偶数のものだけにフィルタかけて合計を求めてます。

def list = [0, 1]
while(list[-1] <= 4000000) {
  list << list[-2] + list[-1]
}
println "list.sum() = ${list.findAll{it % 2 == 0}.sum()}"

2012年3月31日土曜日

KotlinでJunit4系を使って自動テスト

githubみると、kotlinのテストはjunit3系(Testcaseを継承するやつ)でやっているので、
junit4系(アノテーションベースのやつ)での自動テストの実行方法を調べてみた。

テストコード

基本的にJavaでテストコード書く時と違いはない感じですね。
必要なアノテーションをimportしてあげて、メソッドの宣言時に指定してあげるだけです。
違いがあるとしたら、Javaとは異なりアノテーションを示す「@」は不要なとこですね。

あと、静的なメソッド作れないのでBeforeClassAfterClassを使っての、
テストクラスの初期処理と終了処理は実装できない感じです。(俺の知識が足りないだけかも?)

※junit4系でのテストコードの実装方法なので、ターゲットのコードは作ってません。
import org.junit.Before
import org.junit.After
import org.junit.Test

class SampleTest {

  Before fun setUp() {
    println("setUp")
  }

  After fun tearDown() {
    println("tearDown")
  }


  Test fun test1() {
    println("test1")
  }

  Test fun test2() {
    println("test2")
  }
}

実行結果

Javaと同じように、BeforeTestAfterが繰り返されているのがわかりますね。
setUp
test1
tearDown
setUp
test2
tearDown

2012年3月30日金曜日

[Oracle]ストアドファンクションの結果キャッシュ

ファンクションの結果キャッシュはOracle11gからの新機能で、この機能を使用すると同一のパラメータでストアドファンクションを呼び出した場合、2回目以降はキャッシュから結果を取り出してくれるので処理を高速化できる便利な機能。

細かい使い方は、マニュアルを見よう。

キャッシュを使った場合と使わなかった場合の性能差

実際にキャッシュを使った場合にどのぐらいパフォーマンス的に有利になるのかを測ってみました。

PL/SQLのコード

キャッシュを有効化するには、以下のようにファンクションの定義時に「RESULT_CACHE」キーワードを指定してあげるだけです。

処理的には、TEST_TABELEからパラメータで指定された値に紐付く「VAL」を取得して、返却するだけの簡単な処理になっています。
あと、ほんとに処理がスキップされて結果を返すかを確認するためにDBMS_OUTPUT.PUT_LINEでパラメータを出力してみてます。
CREATE OR REPLACE FUNCTION GET_VAL(key IN CHAR) RETURN CHAR RESULT_CACHE RELIES_ON (TEST_TABLE, HOGE)
AS
    val NVARCHAR2(100);
BEGIN
    DBMS_OUTPUT.PUT_LINE('param = ' || key);
    SELECT VAL INTO val
      FROM TEST_TABLE
     WHERE PK = key;
    RETURN val;
END;
/

テーブルの内容

PK   VAL
---- -----------
'01' 'あいうえお
'02' 'かきくけこ
'03' 'さしすせそ

sqlplusで2回連続で実行してみた

1回目の実行では、パラメータ情報が出力されているけど2回目は出力されていない。
どうやらキャッシュがちゃんと有効になっているっぽい。
19:52:02 SQL> exec :val := get_val('01');
param = 01

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.00
19:52:05 SQL> exec :val := get_val('01');

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.01

参照してるTEST_TABLEに変更加えた場合ってどう動くんだろう?といことで試してみた。
結果だけ見ると、参照テーブルに変更入るとキャッシュが無効化されて最新情報を取りに行くようですね。
20:00:19 SQL> exec :val := get_val('01');

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.00
20:00:23 SQL> update test_table set val = 'hoge' where pk = '01';

1行が更新されました。

経過: 00:00:00.00
20:00:29 SQL> commit;

コミットが完了しました。

経過: 00:00:00.00
20:00:31 SQL> exec :val := get_val('01');
param = 01

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.00

次は、関係ないテーブルに変更加えてみるとどうだろう。
結果、関係ないテーブルの変更はキャッシュに影響は与えないみたいなので想定通りの動き。
20:02:05 SQL> exec :val := get_val('01');

PL/SQLプロシージャが正常に完了しました。

経過: 00:00:00.00
20:08:17 SQL> update hoge set col1 = '1';

1行が更新されました。

経過: 00:00:00.00
20:08:21 SQL> commit;

コミットが完了しました。

経過: 00:00:00.00
20:08:24 SQL> exec :val := get_val('01');

PL/SQLプロシージャが正常に完了しました。

おわり。

2012年3月29日木曜日

TortoiseSVNをコマンドラインで使う

TortoiseSVNをコマンドラインで使う方法。
このコマンドをファイラと連携してあげれば、右クリックとかしなくてよいのでかなりいい感じになるはず。
(コマンドラインで使うだけなら、svnコマンドを使ってあげたほうが楽。)

コミット

TortoiseProc.exe /command:commit /path:[ファイルパス] /closeonend:1

※closeonendに「1」を指定してあげると、正常にコマンドが実行できた場合にはダイアログを閉じてくれます。
その他の設定値は、以下を参照。

0: ダイアログを自動的に閉じません。
1: エラーがなければ自動的に閉じます。
2: エラーや競合がなければ自動的に閉じます。
3: エラー、競合、マージがなければ自動的に閉じます。

ログの表示

TortoiseProc.exe /command:log /path:[ファイルパス]

更新

TortoiseProc.exe /command:update /path:[ファイルパス]

リポジトリブラウザの表示

TortoiseProc.exe /command:repobrowser /path:[ファイルパス]

※ファイルパスの部分は、ディレクトリに対するパスでも問題無いです。

2012年3月25日日曜日

Project Euler-Problem 2をkotlinで解いてみる

問題:http://se-bikou.blogspot.jp/2012/03/project-euler-problem-2scala.html

フィボナッチ数列をもつIterableなクラスを作って、偶数な値のみにフィルタして合計を求めてみてます。

import ext.sum
import java.util.Collection
import kotlin.util.arrayList

class Fibonacci(num : #(Int, Int), val end : Int) : Iterable {
  private var num : #(Int, Int) = num

  class InnerIterator() : Iterator {
    override val hasNext : Boolean
    get() = (num._1 + num._2) <= end

    override fun next() : Int {
      num = #(num._2, num._1 + num._2)
      return num._2
    }
  }
  override fun iterator() : Iterator {
    return InnerIterator()
  }
}

fun main(args : Array) {
  val sum = Fibonacci(#(0, 1), 4000000).filter({it % 2 == 0}).sum()
  println("sum = ${sum}")
}

2012年3月24日土曜日

JavaでAES暗号

KeyStoreで鍵を管理して、その鍵をつかって暗号化と復号化をするコード。


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;

public class Encryptor {

    /** エリアス名 */
    private static final String ALIAS_NAME = "aesKey";

    /** 暗号化キーを保存するファイル */
    private File keyFile;

    /** 認証用パスワード */
    private static final char[] KEY_PASSWORD = {'p', 'a', 's', 's', 'w', 'o',
            'r', 'd'};

    /** IV */
    private static final IvParameterSpec IV = new IvParameterSpec("1234567812345678".getBytes());

    /** keyStore */
    private KeyStore jceks;

    public static void main(
            String[] args) throws IOException {
        Encryptor encryptor = new Encryptor(new File(".keyFile"));
        
        /* 初期化(keyStoreをロード */
        encryptor.initialize();
        /* 鍵を保存 */
        encryptor.saveKey();
        /* 暗号化 */
        byte[] encrypt = encryptor.encrypt("これを暗号化するよ");
        /* 復号化 */
        byte[] decrypt = encryptor.decrypt(encrypt);
        System.out.println("new String(decrypt) = " + new String(decrypt));
    }

    public Encryptor(File keyFile) {
        this.keyFile = keyFile;
    }

    private void initialize() throws IOException {
        FileInputStream inputStream = null;
        if (keyFile.exists()) {
            inputStream = new FileInputStream(keyFile);
        }
        KeyStore jceks;
        try {
            jceks = KeyStore.getInstance("JCEKS");
            jceks.load(inputStream, KEY_PASSWORD);
        } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
            throw new IllegalStateException("failed to load key store.", e);
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
        this.jceks = jceks;
    }

    private byte[] encrypt(String text) {
        try {
            Key key = loadKey(ALIAS_NAME);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key, IV);
            return cipher.doFinal(text.getBytes());
        } catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
            throw new IllegalStateException("failed to encrypt.", e);
        }
    }

    private byte[] decrypt(byte[] encryptData) {
        try {
            Key key = loadKey(ALIAS_NAME);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, IV);
            return cipher.doFinal(encryptData);
        } catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
            throw new IllegalStateException("failed to encrypt.", e);
        }
    }

    private Key loadKey(String key) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException {
        return jceks.getKey(ALIAS_NAME, KEY_PASSWORD);
    }

    private void saveKey() throws IOException {
        try {
            if (!jceks.isKeyEntry(ALIAS_NAME)) {
                // 任意のキーを生成してkeyStoreにセット
                KeyGenerator aes = KeyGenerator.getInstance("AES");
                jceks.setKeyEntry(ALIAS_NAME, aes.generateKey(), KEY_PASSWORD, null);
            }

            // keyStoreファイルを保存
            try (FileOutputStream outputStream = new FileOutputStream(keyFile)) {
                jceks.store(outputStream, KEY_PASSWORD);
            }
        } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException e) {
            throw new IllegalStateException("failed to store key.", e);
        }
    }
}

[Oracle]データベース運用/保守 サンプルコード

オラクルさんが公開してくれている、データベース運用/保守 サンプルコードが以下のサイトから入手出来る。

http://otn.oracle.co.jp/sample_code/tech/dba/index.html

SafeVarargsアノテーション

総称型の可変長引数を持つメソッドのワーニングを抑制するためのjdk7から追加されたアノテーション。

例えば、以下のコードをコンパイルした場合、ワーニングとして「Hoge.javaの操作は、未チェックまたは安全ではありません。」が出力される。
public class Hoge {

    public static void main(String[] args) {
        Collection collection = hoge("1", "2");
    }

    public static  Collection hoge(T... elements) {
        return Arrays.asList(elements);
    }
}

このワーニングを抑制するために、「SafeVarargs」を対象のメソッドhogeに追加をしてあげるとよい。
ちなみに、このアノテーションはstaticかfainalなメソッドにしか設定できないので、非finalなインスタンスメソッドに設定すると、以下のようなコンパイルエラーが発生する。
エラー: SafeVarargs注釈が無効です。インスタンス・メソッドhoge(T...)はfinalではありません。
Tが型変数の場合:
メソッド hoge(T...)で宣言されているT extends Object

Project Euler-Problem 2をscalaで解いてみる

問題内容

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.


訳すと・・・

フィボナッチ数列の項は前の2つの項の和である。 最初の2項を 1, 2 とすれば、最初の10項は以下の通りである。

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
数列の項の値が400万を超えない範囲で、偶数値の項の総和を求めよ。

scalaのコード

fibo関数でフィボナッチ数列をListにつめていきます。400万を超えない範囲でとなっているので、400万を超えた時点でfibo関数から抜けます。
その結果のListから偶数でフィルタをかけて、sum関数で合計を求めて終わりです。
def fibo(n1: Int, n2: Int): List[Int] = {
  val n = n1 + n2
  if (n > 4000000) {
    Nil
  } else {
    n :: fibo(n2, n)
  }
}
val sum = fibo(0, 1).filter(_ % 2 == 0).sum
println("sum = " + sum)

2012年3月20日火曜日

最近読んだ本


Clean Coder プロフェッショナルプログラマへの道

この本は非常に面白かったです。自分がいかに社畜かを知れたのもよかったです。
何よりも、著者がIntelliJユーザと言うだけでもこの本は買いですね。




Jenkins実践入門

ciって何?ci導入してみたいんだけどって人は是非読んでみると良いです。
非常に分かりやすく書いてあるので、ci(jenkins)初心者にはかなりよいかと。




jQuery in Action

仕事でjQuery使うことになったのでとりあえず読んでみた。
jQueryの基本的な知識を得るには十分な本です。サンプルも豊富だし、セレクタやイベントハンドラを学習しやすくするための、サンプルコードがあるのもありがたい。

洋書なのがあれだけど、jQuery勉強したいなら読んでみるのもありかな。

2012年3月10日土曜日

[jQuery]拡張して関数を追加する方法

jQueryを拡張する方法。

拡張方法としては、jQueryのオブジェクトに関数を追加してあげるだけ。

jQueryオブジェクトが「$」となっているので、「$.関数名 = function(引数)」として定義してあげる。

(function ($) {
    $.showMessage = function(msg) {
        alert(msg);
    };

    console.log($.showMessage("メッセージ"));
})(jQuery);

Project Euler-Problem 1

Project Eulerなるものの存在を知ったので言語の勉強でつかってみた。

まずは、問題1をやってみた。

問題内容

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.

訳すとこんな感じ。

10未満の自然数のうち、3 もしくは 5 の倍数になっているものは 3, 5, 6, 9 の4つがあり、 これらの合計は 23 になる。
同じようにして、1,000 未満の 3 か 5 の倍数になっている数字の合計を求めよ。

解くために作ったプログラム

Scala

val ret = (0 to 999).filter(n =>{n % 5 == 0 || n % 3 == 0}).sum
println(ret)

Kotlin

Scalaと全く同じになるかなと思ったけど、sum関数がなかったので自作してみてます。
package p1

import java.util.Collection

fun Collection<Int<.sum():Int {
    var ret = 0
    for (item in this) {
        ret += item
    }
    return ret
}
fun main(args : Array<String>) {
    val result = (1..999).filter {it % 3 == 0 || it % 5 == 0}.sum()
    println("result = ${result}")
}

Java

いたって普通のコード。
package p1;

public class P1 {

    public static void main(String[] args) {
        int ret = 0;
        for (int i = 1; i <= 999; i++) {
            if (i % 3 ==0 || i % 5 == 0) {
                ret += i;
            }
        }
        System.out.println("ret = " + ret);
    }
}

javascript

とりあえず結果はあってる。
    var Num = function(s, e) {
        this.filter = function(func) {
            var arr = new Array();
            for (i = s; i <= e; i++) {
                if (func(i)) arr.push(i);
            }
            arr.sum = function() {
                var sum = 0;
                for (i = 0; i < this.length; i++) {
                    sum += this[i];
                }
                return sum;
            };
            return arr;
        }

    };

    var ret = new Num(1, 999).filter(function(val) {
        return val % 3 == 0 || val % 5 == 0;
    }).sum();
    document.write(ret);

groovy

def sum = (1..999).grep({it % 3 == 0 || it % 5 == 0}).sum()
println "sum = $sum"

2012年3月9日金曜日

Webエンジニアのためのデータベース技術入門

Webエンジニアのためのデータベース技術入門を購入。

mysql関連書籍をいくつか出している人が書いているので、良書な予感。


2012年3月8日木曜日

[jQuery]grep関数

jQueryのgrep関数を使って、配列の内容にフィルタかけてみたメモ。

grep関数の仕様

grep(array,callback,invert)

array    -> grepをかけたい配列オブジェクト
callback -> フィルタ条件をもつ関数オブジェクト。戻り値でbooleanを返したげる。
invert   -> これをtrueにしてあげると、callback関数の条件を逆にできる。(falseのものだけをフィルタする場合は、trueにするイメージ)

    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    (function ($) {
        // 5以下の要素のみを抽出
        var filter = $.grep(arr, function (value) {
            return value <= 5;
        });

        // 3つめのパラメータがtrueなので、6以上の要素のみが抽出される。
        var filter = $.grep(arr, function (value) {
            return value <= 5;
        }, true);

        // 以下のように正規表現も使えます。
        var ret = $.grep(["100", "200", "300"], function (value) {
            return value.match(/[12]00/);
        });
    })(jQuery);

2012年3月4日日曜日

[ruby on rails]IntelliJでscaffold

Intellijをつかってscaffoldingして、rakeコマンドでデータベースにテーブル作成して画面を動かしてみた。

1.scaffoldコマンドの実行


1.1.tool->Run Rails Generator...を選択



1.2.表示されたダイアログで、scaffoldコマンドを選択


1.3.scaffoldコマンドのModel名などを入力する画面が表示されるので、必要な値を入力してOKを選択

今回は、モデル名に「user」、フィールドに「userId」と「userName」を入力してみました。
このダイアログは、1つの入力エリアにscaffoldの引数をすべて入力しないといけないので正直使いづらい・・・



一応、こんな感じに型は補完してくれますがちょっと微妙

1.4.生成されたものを見てみよう

こんな感じにコントローラやモデルが出力されてます。ViewとHelperはコントローラ配下からたどれるようになっていて、モデルだけ分離されていますね。

2.次はテーブルを作ろう

scaffoldで自動生成が終わると、データベースのマイグレーションファイルが出力されるのでテーブル作ってあげよう。
今回、自動生成されたファイルはこんな感じ。
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :userId
      t.string :userName

      t.timestamps
    end
  end
end

2.1.データベースのマイグレーションをしよう

データベースのマイグレーションは、run->Resume Programからたどった先のrakeコマンドで行います。 まずは、Resume Programをメニューからたどっていきます。

2.2.debug実行用のダイアログが表示されるので、db:migrateを選択する。

このときに注意しないといけないのは、debug実行で実行しないこと。普通にクリックすると、debug実行になるのでshiftを押しながらクリックすること。

2.3.DataSourceウィンドウでテーブル出来たことを確認

3.画面動かしてみよう

画面でたっ!!簡単ですね。 画面の動かし方は、こちらを見てね。→IntelliJでruby on rails


jQueryを使うときは$の競合に気をつける

jQueryを使うときは、jQueryの別名参照の「$」を使用するけど、これの競合に注意しないといけないらしい。

例えば、こんなコードの用に「$」が既に定義されていた場合、$('body')はjQueryの呼び出しではなく、文字列変数の「$」を参照しているだけなので実行時にエラーになってしまう。(普通はこんなコードはないけど)

エラーの内容
Uncaught TypeError: Property '$' of object [object DOMWindow] is not a function

この競合を解決するために、jQueryを使うときは「$」を直接使うのではなく無名関数でwrapして使ってあげるのが一般的らしい。無名関数を使った場合は、こんな感じになるようだ。
これは、無名関数で引数を1つ(この場合は「$」)受け取っている。その引数には、最後のjQueryオブジェクトを渡してあげる。
あんまり理解出来なかったが、無名関数全体を括弧で囲んであげて、最後の「(jQuery)」部分でjQueryオブジェクトを引数に指定してあげてるようだ。

2012年2月29日水曜日

継続的デリバリー本を予約

リリースの仕組みとかってどんなプロジェクトでも悩まされたりするからポチッてみた。
内容は全くわからいけど、かなり期待して発売を待ってみる。



2012年2月25日土曜日

IntelliJでruby on rails

IntelliJでruby on railsのプロジェクト作る方法。
前提として、IntelliJはUltimate Editionを入れておかないとrubyプラグインが入れられないのでrailsの開発はできません。

rubyプラグインの入れ方は、http://se-bikou.blogspot.com/2011/03/intellijruby.htmlを参照

また、gemでrailsなどの必要なモジュールを事前にinstallしておかないとrailsのプロジェクト作れないので入れておきましょう。

1.プロジェクトを作成する
メニューから「New Project」を選択して、表示された「New Project」で「Create project from scratch」を選択して次へ。

「project files location」を入力して、「select type」でrubyを選択して次へ。
※project files locationを入力すると、Project名などは自動で入ってくれます。なので、任意のディレクトリを「project files location」に入力してあげればよいです。

Specify the Ruby SDKの画面が出てくるので、railsプロジェクトで使いたいrubyのバージョンのSDKを選択します。
RubyのSDKの設定がされていない場合は、ConfigureボタンからSDKの設定をしてあげます。

rubyのSDKは、下の画像の順に行っていきます。最後の「Ruby SDK」を選択するとファイルを選択するダイアログが開くのでrubyの実行モジュールを選択してあげます。

次の画面では、Ruby on Railsを選択してバージョンを選択してあげます。また、railsアプリケーションを作る必要があるので「Generate new Rails application」にチェックを入れます。


これでプロジェクトの作成は完了です。プロジェクトの作成が完了するとProject Viewがこんな感じになります。

2.コントローラを作って画面を表示してみよう
rails generateコマンドはguiで作業できるので、簡単にコントローラを作ることが出来ます。
まずは、「tool」メニューから「rails generate」を選択します。

「generator」メニューで「controller」を選択します。

Controller名を入力して、Actionを定義してあげます。今回はController名は「Test」、Actionは「index」のみにしています。

「Project view」の表示を「Rails」に変えてあげると、こんな感じに見やすくなります。Controllerもちゃんと出来てますね。

「Run」から開発用設定でWEBRickを起動してみましょう。

最後に画面が表示されることを確認しましょう。



[jQuery]fadeOutとfadeIn

fadeOutは対象の要素を隠してくれて、fadeInは表示してくれる。


fadeOutとfadeInの引数

1.speed
  速度を指定する。数値(ミリ秒)を指定した場合は、そのスピードで表示、非表示になります。
  文字列を指定した場合は、以下のどうさになります。ざっくり指定するにはこれですね。

  slow:ゆっくりと
  normal:普通
  fast:早く

  *この値を省略した場合は、「normal」な動作となります。
2.callback
  表示、非表示が完了したタイミングでコールバックされる関数。任意指定だから特に指定しなくても大丈夫。

下の例は、表示、非表示はゆっくりな動作を指定して、非表示にした場合にはボタンのラベルを「表示」にし、表示した場合には「閉じる」にしています。
<script type="text/javascript">
    $(function () {
        var button$ = $('input[type=button]');
        button$.toggle(
                function () {
                    $('div#hoge').fadeOut("slow", function() {
                        button$.val("表示");
                    });
                },
                function() {
                    $('div#hoge').fadeIn("slow", function() {
                        button$.val("閉じる");
                    });
                }
        )
    })
</script>

2012年2月23日木曜日

Kotlinの配列を色々触ってみた

Kotlinの配列を色々試してみた。

繰り返し処理

Scalaなどでもお馴染みのforcachforEachでぐるぐるまわします。
foreachforEachに指定する関数では、要素を「it」で参照できるみたいです。groovyちっくですね。
rubyのように、each_widh_indexみたいなので添字付きでぐるぐるまわすことはできないのかな。

var arr1 = array(1, 2, 3, 4)
arr1.forEach {println(it)}

配列の各要素を連結

おなじみのjoin関数を使って連結出来る。
// カンマで連結
arr.join(",")    // -> 1,2,3,4

// プレフィックス、サフィックスを指定して連結
arr.join(",", "<", ">")    // -> <1,2,3,4>

要素の中身全てが指定した条件を満たすかチェック

all関数を使用する。条件は、all関数の引数として指定してあげる。
// 全ての要素で条件をみたすことができない場合
var arr1 = array(1, 1, 1, 0)
arr1.all {it == 1}    // -> false

// 全ての要素で条件をみたすことが出来る場合
var arr2 = array(1, 1, 1, 1)
arr2.all {it == 1}    // -> true

// 文字列の場合
var str = array("1", "2", "3")
str.all {it <= "3"}    // -> true
str.all {it <= "2"}    // -> false

要素の中のどれか1つが指定した条件を満たすかチェック

any関数を使用するる。条件は、any関数の引数として指定してあげる。
// 要素ないに1つでも条件を満たす値がある場合
var arr1 = array(1, 0, 2, 0)
arr1.any {it == 1}    // -> true

// 要素ないの値が全て条件を満たさない場合
var arr2 = array("1", "2", "3")
arr2.any{it > "3"}    // -> false

要素の中で条件を満たす最初の値を取得する

他の言語でもお馴染みのfind関数を使います。使い方も他の言語と同じですね。
var arr1 = array(1, 0, 2, 0)
// 要素が見つかる場合
arr1.find {it == 0}    // -> 0
arr1.find {it == 2}    // -> 2

// 要素が見つからない場合
arr1.find {it == -1}    // -> null

要素の中で条件に一致したものを新しい配列で取得する

他の言語(Scala)でもお馴染みのfilter関数を使います。使い方も他の言語と同じですね。
var arr1 = array(1, 0, 2, 0)
arr1.filter {it % 2 == 0}    // -> [0, 2, 0]

var arr2 = array("1", "2", "3")
arr2.filter {it.length() == 1}    // -> ["1", "2", "3"]
// 条件に一致する要素が存在しない場合は、空の配列が戻ってきます。
arr2.filter {it.length() != 1}    // -> []

要素の中で条件に一致しないものを新しい配列で習得する

filterの逆ですね。これも他の言語(Scala)でもお馴染みのfilterNot関数を使います。使い方も他の言語と同じですね。
var arr1 = array(1, 0, 2, 0)
arr1.filterNot {it % 2 == 0}    // -> [1]

var arr2 = array("1", "2", "3")
arr2.filterNot {it.length() != 1}    // -> ["1", "2", "3"]
arr2.filterNot {it.length() == 1}    // -> []

各要素の値を変換して新しいCollectionを取得する。

ScalaにもあるflatMapを使ってあげるといけます。
引数の型パラメータと戻りの型パラメータが異なるから、flatMapに型パラメータ指定してあげないと動かなかった。
なんか間違ってるのかな?
ちなみに、arrayListやlinkedList関数は、「std.utilパッケージ」にあるのでimportしてあげないと使えないです。
// 各要素の値を2倍にする。
var arr1 = array(1, 2, 3)
arr1.flatMap<Int, Int> {(n) -> arrayList(n * 2)}    // -> [2, 4, 6]

// 各要素先頭にstr =を加える。
var arr2 = array("1", "2", "3")
arr2.flatMap<String, String>{(s) -> linkedList("str = ${s}")}    // -> [str = 1, str = 2, str = 3]

2012年2月19日日曜日

[jQuery]イベントに応じて要素の表示、非表示を切り替える(アコーディオン)

jQueryを使用して、要素の表示と非表示を切り替えるには、toggleやslideToggle関数を使うと簡単に実現出来ます。

toggle関数は、引数を指定しないで呼び出してあげるとその要素の表示(show)と非表示(hide)を繰り返してくれます。
slideToggle関数を使うと、非表示にするときには徐々に消えていき、表示するときにはにょきにょきでてきます。

引数なしでtoggleとslideToggleを使ってみる

以下のhtmlをdiv部分をボタンクリックイベントで表示、表示を切り替えてみましょう。
<input type="button" value="表示・非表示切り替え" id="btn">

<div id="view">
この部分の表示、非表示を切り替えます。
</div>

toggle関数を使用すると、非常に簡単に表示、非表示を切り替えられますね。
$(function () {
    $('input#btn').click(function () {
        $('div#view').toggle();
    });
})

slideToggleもtoggleと使い方は基本的に同じ。
$(function () {
    $('input#btn').click(function () {
        $('div#view').slideToggle();
    });
})

表示、非表示の速度を変えてみる

toggleとslideToggleの引数には、ミリ秒と速度を示す文字列を指定出来ます。

ミリ秒を指定した場合は、その時間をかけて非表示になったり表示したりしてくれます。
文字列は、「Slow」、「Normal」、「Fast」の3種類が指定できまる。
以下のように、文字列通の動作をします。ミリ秒指定と比べるとかなりおおざっぱな感じですね。
* Slow:ゆっくりした動作
* Normal:普通の動作
* Fast:早い動作

使い方の例。この例だと2秒間かけて表示と非表示されます。
$(function () {
    $('input#btn').click(function () {
        $('div#view').slideToggle(2000);
    });
})

文字列指定の場合は、こんな感じです。
$(function () {
    $('input#btn').click(function () {
        $('div#view').toggle('fast');
    });
})

2012年2月18日土曜日

[Kotlin]安全なnull参照

Kotlinではxnull参照が型システムでコントロールされているので、NullPointerExceptionが発生することがないようです。

実際にサンプルコードで動作を確認してみよ。

例1:nullを許可しない変数

通常の変数宣言は、nullを許容しない変数となります。つまり、nullを代入することが出来ない変数なので、
Javaの実装でよくあるnullだったらどうしよう・・・という分岐が必要なくなります。

例えば、以下のコードはnullを許容しない変数にたいするnull代入となるためコンパイルエラーとなります。
var s:String
s = null

例2:nullを許可する変数

nullを許容する変数は、型の末尾に「?」を付加する必要があります。これにより、nullを変数に代入可能となります。
また、その変数を参照する際には、変数の末尾に「?」を付加して参照しないとコンパイルエラーになります。

このnull許可変数は、参照した際にnullの場合はnullが返却されるようになっています。JavaのようにNullPointerExceptionが発生することはないわけですね。

// 型の末尾に「?」を付加する。
var s:String? = "hoge"
val length = s?.length() // -> 4

// 変数がnullの場合に、参照を行うと戻り値もnullとなります。
s = null
val length2 = s?.length() // -> null

例3:Javaと同じようにNullPointerExceptionを送出したい場合

sure関数を使用すると、nullの場合にNullPointerExceptionが送出されます。
var s:String? = "1"
var length = s.sure().length()      // nullでは無いので、「1」が返却されます。

s = null;
length = s.sure().length()          // nullなのでNullPointerExceptionが送出されます。

実際に送出された例外のStackTraceです。
Exception in thread "main" jet.runtime.Intrinsics$JetNullPointerException
 at nullCheck.namespace.main(hoge.kt:21)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:601)
 at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

例4:Elvis operator(null値の判定で使用する)

nullの場合に、何か別の値を返す場合に使用するらしいです。

例えば、Javaで文字列の長さを返す際にその値がnullの場合は、-1を返すとする場合は、
以下のように三項演算子を使うと思います。
s != null ? s.length() : -1
これを、KotlinのElvis operatorで書くとこんな感じになります。
null意外の場合は、「:」の左側の式の結果(この場合だとlengthの結果)が返却され、nullの場合は「:」の右側の結果が返却されるようです。
b?.length() ?: -1

例5:安全なキャスト

安全にキャストを行うためには、「as?」を使用する必要があります。
「as?」を使用した場合、その型にキャストができない方の場合にはnullが返却されます。
「as」を使用した場合には、TypeCastExceptionが送出されます。

val s = "123";
var i1:Int = s as Int    // これは、TypeCastExceptionが送出されます。
var i2:Int? = s as? Int  // これは、nullが返却されます。


Collection系のオブジェクトから値を代入したときにその値がnullだった場合どんな動きをするんだ?
これは、コンパイル時にチェックするのは不可能だし、どんな動きをするんだろう?と思って調べてみました。

調べたときにつかったコード
val arr:Array<String?> = array(null)   // nullを許容するArray
val s:String = arr[0]                  // nullが代入出来る。
s.length()                             // ぬるぽではなく、TypeCastExceptionが発生

nullが代入されたnull不可変数を参照したら、まさかのTypeCastExceptionが発生しました。
これだったらNullPointerExceptionのが分かりやすいんじゃね?TypeCastExceptionじゃ原因特定出来る気がしない・・・。
この辺はこれから改善されていくかもしれませんが。

ScalaのOptionなるものがあったからこんどScalaのほうもちゃんと勉強してみよう。

2012年2月15日水曜日

[Kotlin]IntellijでKotlinしてみた。

Intellij用のKotlin pluginがでたので、Intellijに導入してみた。

現時点では、Intellij11.1のEAPにしか対応していないので、Intellij11.02ではなく11.1のEAPを導入しておく必要があります。

プロジェクトの作成手順などは、Kotlinのサイト(下のリンク先)の動画を参考にしたら割と簡単に出来ると思います。
http://confluence.jetbrains.net/display/Kotlin/Welcome

では、上の動画を参考にプロジェクトを作成して、Hello Worldを動かしてみましょう。

Kotlinプラグインと、ライブラリのダウンロード

プラグインとライブラリは、github(https://github.com/JetBrains/kotlin/downloads)からダウンロード出来ます。

ダウンロードしたプラグイン(解凍して出来たKotlinディレクトリ)は、Intellijのプラグインディレクトリにコピーします。

macの場合:~/Library/Application\ Support/IntelliJIdea11
Windowsの場合:USER_HOME/.IntelliJIdea11/config/plugins

ライブラリは、任意のディレクトリに解凍しておきます。

Javaプロジェクトの作成

new projectから新しいプロジェクトを作成します。Javaのプロジェクトとして作成してあげたらいいので、特に迷うことはないと思います。

Kotlinのソースコードファイルの生成

ソースコードディレクトリで右クリック→Newとすると、下の画像のようにKotlin Fileが選択出来るようになっています。
これが出てこないときは、プラグインがうまく適用出来ていないので、Settingsからpluginが適用出来ているか確認してみた方がよいでしょう。


Kotlin Fileを選択すると、下の画像のようにファイル名を入力するダイアログが表示されるので、
ファイル名を入力してOKとしてあげましょう。なお、ファイル名には拡張子を入力する必要はありません。


Kotlinライブラリの設定

初めてKotlinのソースファイルを作成すると、Kotlin Runtimeをセットアップしてねとのバーが表示されます。
下の画像のように、ライブラリパスを設定するダイアログに一番最初にダウンロードして解凍したKotlinライブラリのlibディレクトリのパスを設定してあげます。


Hello Worldを出力するコードの作成

http://confluence.jetbrains.net/display/Kotlin/Welcomeを参考にして作成します。

作成したソースはこんな感じですね。
fun main(args : Array<string>) {
    println("Hello World")
}

実行してみよう

右クリックで表示されるメニューからrun namespaceを選択して実行してみよう。
なお、packageを定義しているとrun パッケージ名とメニューに表示されます。

実行した結果、下の画像のようにコンソールにHello Worldが出力されたら実行成功です。


2012年1月29日日曜日

[jQuery]class属性の操作

jQueryを使用して、html要素のclass属性を操作する方法

class属性に、任意のクラスを追加

addClassメソッドを使用して、クラスを追加出来る。

以下の例では、input要素すべてに「className」というクラスを追加しています。
$(function () {
  $('input').addClass('className');
});

複数のクラスを追加したい場合には、スペースで区切って複数のクラス名を列挙してあげるとよい。
もしくは、addClass('class1').addClass('class2')のようにメソッドチェイン呼び出しにしてあげるとよい。
個人的には、後者の方が好み。いくつのクラスが追加されてるか分かるし、クラス名を単独になるから可読性高くなるし。


class属性から、任意のクラスを削除

removeClassメソッドを使用して、クラスを削除することが出来る。

基本的な使い方は、addClassと同じ。

以下の例では、input要素から「className」というクラスを削除しています。
$(function () {
  $('input').removeClass('className');
});

イベントを拾ってclassの有無を切り替える

イベントに応じて特定のクラスを削除したり、追加したりする方法。
例えば、input:textにフォーカスがあたっている場合、背景色を変更するクラスを追加して、フォーカスが外れた場合に削除したりする場合に使える。
addClassとremoveClassを組み合わせて使用したら出来るけど、toggleClassというメソッドが用意されているので、こちらを使った方が見通しがよくなる。

この例は、フォーカスがあたった場合と外れた場合に、changeTextColorファンクションを呼び出しています。
呼び出し先のメソッドでは、toggleClass('active')となっているので、「active」クラスがあればクラス属性から削除され、なければ追加されます。
$(function () {
  $('input:text').focusin(changeTextColor).focusout(changeTextColor);
});
function changeTextColor() {
  $(this).toggleClass('active');
}

指定されたクラスがclass属性にあるかチェック


hasClassメソッドを使用してテストできる。

$(function () {
  $('input').hasClass('className');
});

2012年1月21日土曜日

[jQuery]テーブルの行の背景色を交互に変更する方法

trのoddとevenでひろってきて、cssで背景色を変えることが出来る。
テーブルのレコードを表すtrタグと、奇数(odd)、偶数(even)番目を表すselectorを
組み合わせて使うことで割と簡単に実現出来る。

    $(function() {
        // trの中で奇数番目のものを対象にする
        $('tr:odd').css({
            backgroundColor:'#aaaaaa'
        });
        // trの中で偶数番目のものを対象にする
        $('tr:even').css({
            backgroundColor:'#ffffff'
        });
    });

2012年1月14日土曜日

[JavaScript]checkboxのチェックをクリアする

特定のdiv要素のボタンがクリックされたら、そのdiv要素内のcheckboxのチェックを外す方法。

jQueryを使うとこんな感じで出来るみたい。

2012年1月8日日曜日

[JavaScript]文字列のtrim

jQueryのtrim関数を使用してtrimできる。

// jQueryのtrim関数を使用してtrimする。
$.trim("trimしたい文字列");

2012年1月7日土曜日

JavaScript本格入門を読んだよ

JavaScriptを使う必要に迫られたので、読んでみた。
JavaScript書くなんてかなり久しぶりでちゃんと理解しとかないとと思い、Amazonレビューでも良さげそうだったこの本にしてみた感じです。



読んでみた感じは、内容はそんなこくないとは思うけど、図とかを使い端的に説明していて非常に分かりやすかったかなと思います。
ただ、サブタイトルにあるajaxやjqueryだったりの部分は、この本で学ぶのは期待しない方がよいと思います。
あくまでも、ajaxってなに?どんなことができるの?ってことを知れたり、jqueryを使うとどれぐらい簡単にajaxを実現出来るかを知れる程度だと思います。
(jqueryの専門書が出てる訳で、この本だけでjqueryも理解出来るって思う方が間違ってると思います。)