2014-09-29

【備忘録】CentOS 7 関連情報

7 月 7 日に CentOS 7 がリリースされて、3 ヶ月近く経ちました。インターネットで入手できる CentOS 7 の情報源をまとめてみました。

CentOS 7 x86_64 のインストール方法が丁寧に説明されています。

インストール方法だけでなく、各サーバの設定方法の情報もあります。特に、IaaS クラウドコンピューティングプロジェクトである OpenStack 2014.1 (Icehouse) に関する解説は重要かもしれません。

LAMP とは、OS である Linux、Web サーバである Apache HTTP Server、データベースである MySQL、スクリプト言語である Perl、PHP、Python を総称した頭文字から成る造語です。上記のサイトでは CentOS 7 上に Apache HTTP サーバの代わりに Nginx を、MySQL の代わりに MariaDB、そして PHP をインストールして WordPress が使えるようになるまでを解説しています。

Docker によるコンテナ管理に関する情報です。一部、CentOS 6.5 や RHL 7 の情報が混じっています。

 

2014-09-26

米RedHat、Bashへのコードインジェクション攻撃についてブログで解説:CodeZine

Bash にセキュリティホールが見つかったそうです (CVE-2014-6271, CVE-2014-7169)。

CentOS 7 でパッケージをアップデートしようとしたところ、bash があります。

# yum update
読み込んだプラグイン:fastestmirror, langpacks, priorities
Dropbox                                                  |  951 B     00:00     
adobe-linux-x86_64                                       |  951 B     00:00     
base                                                     | 3.6 kB     00:00     
centosplus                                               | 3.4 kB     00:00     
epel/x86_64/metalink                                     | 5.3 kB     00:00     
epel                                                     | 4.4 kB     00:00     
extras                                                   | 3.4 kB     00:00     
google-chrome                                            |  951 B     00:00     
rpmforge                                                 | 1.9 kB     00:00     
rpmfusion-free-updates                                   | 2.7 kB     00:00     
rpmfusion-nonfree-updates                                | 2.2 kB     00:00     
updates                                                  | 3.4 kB     00:00     
(1/3): centosplus/7/x86_64/primary_db                      | 2.1 MB   00:02     
...
省略
...
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ bash.x86_64 0:4.2.45-5.el7 を 更新
---> パッケージ bash.x86_64 0:4.2.45-5.el7_0.4 を アップデート
---> パッケージ crash.x86_64 0:7.0.2-6.el7 を 更新
---> パッケージ crash.x86_64 0:7.0.2-7.el7_0.1 を アップデート
...
省略
...
--> 依存性解決を終了しました。

依存性を解決しました

================================================================================
 Package                 アーキテクチャー
                                バージョン                     リポジトリー
                                                                           容量
================================================================================
更新します:
 bash                    x86_64 4.2.45-5.el7_0.4               updates    1.0 M
 crash                   x86_64 7.0.2-7.el7_0.1                updates    2.5 M
...
省略
...

トランザクションの要約
================================================================================
更新  15 パッケージ

総ダウンロード容量: 21 M
Is this ok [y/d/N]: y

とりあえず、アップデートして変更履歴を見てみることに。

$ rpm -q --changelog bash
* 木  9月 25 2014 Ondrej Oprala <ooprala@redhat.com> - 4.2.45-5.4
- CVE-2014-7169
  Resolves: #1146324

* 木  9月 25 2014 Ondrej Oprala <ooprala@redhat.com> - 4.2.45-5.3
- amend patch to match upstream's
  Related: #1146324

* 月  9月 15 2014 Ondrej Oprala <ooprala@redhat.com> - 4.2.45-5.2
- Fix-up the patch
  Related: #1141647

* 月  9月 15 2014 Ondrej Oprala <ooprala@redhat.com> - 4.2.45-5.1
- Check for fishy environment
  Resolves: #1141647
...
省略
...

CVE-2014-7169 を解決するパッチをあてたようですが、これで十分なのかな?

参考サイト

2014-09-23

NatTable(3)

NatTable(2) で比較的大きなサンプルを読み込むことができたので、これに勇気づけられ、まずは特定の集計に特化した集計用ツール (GUI) を作り始めました。

当初、Eclipse RCP に挑戦していたのですが、不慣れな為に調べることが山のようにあり、そこそこ動くようなレベルまで収束しません。やむなく現時点では Eclipse RCP を使うことを止めて、自己流のやりかたでそこそこ動作するものを作りました。機能的には 3 割程度の出来です。この集計ツールに求める機能の概略は次のとおりです。

  1. (あるシステムに)ユーザーアカウント別にログイン、ログアウトした時刻を記録したログのファイルを読み込む。
  2. 時刻単位でログインしていたユーザー数の集計をする。
  3. 時刻 対 ログインユーザー数の X-Y プロットを作成する。

この最初のステップをクリアしただけなのですが、スプレッドシート状の GUI (NatTable) を扱った意義は大きいです。

先月 8 月の夏休みとして確保した 10 日間でここまでは到達したかったので、ちょっと悔しいです。歳を取ると、若い時のような爆発的な集中力が出ないなぁとボヤキたくなります。いや、歳を言い訳にしてはいけませんね。一直線に突き進まない代わりに、細かいところを気にして回り道ばかりするのも、たぶん必要な気配りなんだということにしておきます。

デスクトップを GNOME から MATE へ切り替えて以来、使いやすくて目に馴染むウィンドウの外観を求めて、くるくる変わっていますが、そろそろこの辺で落ち着きそうです。

ちなみに、Windows 7 で動作させて場合は以下のような感じになりました。Windows を搭載した PC の CPU の方がコアは 4 つと倍なので、明らかに処理速度が早いのが悔しいのですが、Linux の方でもまあまあの処理速度で頑張っています。Excel のような細かな操作は不要だけど、大量のデータの集計をある一定の方法でさばきたい場合に、NatTable はとても力になってくれそうに思います。

今のところ自己満足に留まっていますが、ある程度 NatTable に慣れてくれば、汎用用途のツール作成にも手を出していき、ソースも公開できるようにしていきたいです。

2014-09-21

News & Trend - モバイル向けDBが活況、オラクルが製品を強化しNoSQLも進出:ITpro

NoSQL とは、Not only SQL という意味で、SQLを使用しないデータベースを指しています。たまたま、ネット上でニュースを見ていたら [1] の記事が目にとまり、Java SDK 2.0.0 って何だ?と思って読むと NoSQL のソフトウェア群の話だということが判ったのでした。ついてに、NoSQL に関する最近の話題をいくつかピックアップしました。

  1. Couchbase Java SDK 2.0.0 Beta 2 | Javalobby
  2. News & Trend - モバイル向けDBが活況、オラクルが製品を強化しNoSQLも進出:ITpro
  3. NoSQLを選ぶ理由 | Couchbase | Couchbase
  4. 米バショー・テクノロジーズ、高度なNoSQLのユーザビリティを実現する 「Riak Enterprise 2.0」を公開 - MSN産経ニュース
  5. Azure:新しいDocumentDB NoSQL Service、新しい検索サービス、新しいSQL AlwaysOn VMテンプレートなど (1/4):CodeZine
  6. EnterpriseDB、無償の「Postgres AWS」ツールを提供へ--NoSQL開発を容易に - ZDNet Japan
  7. NoSQLデータベースを試してみる:連載|gihyo.jp … 技術評論社
  8. 実用段階に入ったNoSQLをおさらい 「Cassandra」の概要と導入手順・基本設定 (1/6):CodeZine
  9. よくわかるNoSQL入門 - NoSQLがRDBMSより大規模データに向く理由:ITpro

Martin Fowler 氏の NoSQL に関する講演です(GOTO Aarhus 2013 Conference)。

2014-09-14

JRI, Java R Interface を試す

R で GUI が必要になる場合、Tcl/Tk を標準で利用できますが、一般的には R のスクリプト上で Tcl/Tk の GUI を定義することになります。簡単な GUI を必要とするアプリケーションであれば、このようなやり方で用をなす場合もありますが、メインのプログラミング環境が別にあって、数値計算をするときに R の機能を利用したい場合もあります。

今回は Java から R の利用を可能にする JRI について紹介します。

使用環境

使用している PC の環境は以下の通りです。

OS (Linux)
CentOS 7 (x86_64)
R パッケージ
R-core-3.1.1-3.el7.x86_64.rpm(CentOS 7 の RPM パッケージ)
Java の主要な開発環境
java-1.7.0-openjdk-1.7.0.65-2.5.1.2.el7_0.x86_64.rpm(CentOS 7 の RPM パッケージ)
java-1.7.0-openjdk-devel-1.7.0.65-2.5.1.2.el7_0.x86_64.rpm(CentOS 7 の RPM パッケージ)
Eclipse Standard 4.4 (eclipse-standard-luna-R-linux-gtk-x86_64.tar.gz)

JRI について

JRI, Java R Interface は R を Java から使用するためのインターフェイスです。JRI は単体で入手することもできますが、rJava というパッケージに JRI が含まれていますので、それを利用します。

rJava は、CentOS 7 の RPM パッケージとしては提供されていませんので、以下のように R を起動して、CRAN からソースをダウンロードして、それをコンパイルして利用します。したがって、上記 R と Java の開発環境の他に、C (gcc) による開発環境を利用できる必要があります。

$ R

R version 3.1.1 (2014-07-10) -- "Sock it to Me"
Copyright (C) 2014 The R Foundation for Statistical Computing
Platform: x86_64-redhat-linux-gnu (64-bit)

R は、自由なソフトウェアであり、「完全に無保証」です。 
 一定の条件に従えば、自由にこれを再配布することができます。 
 配布条件の詳細に関しては、'license()' あるいは 'licence()' と入力してください。 

R は多くの貢献者による共同プロジェクトです。 
 詳しくは 'contributors()' と入力してください。 
 また、R や R のパッケージを出版物で引用する際の形式については 
 'citation()' と入力してください。 

 'demo()' と入力すればデモをみることができます。 
 'help()' とすればオンラインヘルプが出ます。 
 'help.start()' で HTML ブラウザによるヘルプがみられます。 
 'q()' と入力すれば R を終了します。 

> install.packages("rJava", dependencies = TRUE)
Installing package into ‘/home/bitwalk/R/x86_64-redhat-linux-gnu-library/3.1’
(as ‘lib’ is unspecified)
 --- このセッションで使うために、CRAN のミラーサイトを選んでください --- 
CRAN mirror 

  1: 0-Cloud                        2: Argentina (La Plata)       
  3: Argentina (Mendoza)            4: Australia (Canberra)       
  5: Australia (Melbourne)          6: Austria                    
  7: Belgium                        8: Brazil (BA)                
...
(省略)
...
 95: USA (TN)                      96: USA (TX 1)                 
 97: USA (WA 1)                    98: USA (WA 2)                 
 99: Venezuela                    100: Vietnam                    


Selection: 50
 URL 'http://cran.ism.ac.jp/src/contrib/rJava_0.9-6.tar.gz' を試しています 
Content type 'application/x-gzip' length 567515 bytes (554 Kb)
 開かれた URL 
==================================================
downloaded 554 Kb

* installing *source* package ‘rJava’ ...
**  パッケージ ‘rJava’ の解凍および MD5 サムの検証に成功しました 
checking for gcc... gcc -m64 -std=gnu99
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
...
(省略)
...
installing via 'install.libs.R' to /home/bitwalk/R/x86_64-redhat-linux-gnu-library/3.1/rJava
** R
** inst
** preparing package for lazy loading
** help
*** installing help indices
  converting help for package ‘rJava’
    finding HTML links ...  完了 
    Exceptions                              html  
    J                                       html  
    accessOp                                html  
    aslist                                  html  
    clone                                   html  
    instanceof                              html  
    jarray                                  html  
    jarrayRef-class                         html  
    java-tools                              html  
    javaImport                              html  
    jcall                                   html  
    jcast                                   html  
    jcastToArray                            html  
    jcheck                                  html  
    jclassName                              html  
    jengine                                 html  
    jequals                                 html  
    jfield                                  html  
    jfloat-class                            html  
    jfloat                                  html  
    jinit                                   html  
    jmemprof                                html  
    jnew                                    html  
    jnull                                   html  
    jobjRef-class                           html  
    jpackage                                html  
    jrectRef-class                          html  
    jreflection                             html  
    jserialize                              html  
    jsimplify                               html  
    loader                                  html  
    new                                     html  
    rep                                     html  
    show                                    html  
    toJava                                  html  
    with                                    html  
** building package indices
** testing if installed package can be loaded
* DONE (rJava)

 ダウンロードされたパッケージは、以下にあります 
  ‘/tmp/RtmpEdb1KU/downloaded_packages’ 
> 

コンパイルしたパッケージは、$HOME/R/x86_64-redhat-linux-gnu-library/3.1/ 以下にあります。

Eclipse の設定

まだ JRI を使いこなせていない状況ですので、参考サイト [1], [2] に掲載されているサンプルを参考にして次のようにしました。

List: SampleR.java
package jritest;

import org.rosuda.JRI.Rengine;
import org.rosuda.JRI.REXP;

public class SampleR {
    public static void main(String[] args) {
        Rengine engine = new Rengine(new String[] { "--no-save" }, false, null);
        engine.assign("a", new int[] { 36 });
        REXP result = engine.eval("sqrt(a)");
        System.out.println(result.asDouble());
        engine.end();
    }
}

Eclipse のプロジェクトのビルドバスの設定画面で、外部 JAR に、rJava のインストールでコンパイルされた、JRI.jar, JRIEngine.jar, REngine.jar を加えました。

メニューの Run → Run Configurations...で VM の引数にライブラリ libjri.so へのパスを指定します。このパスは実際、JRI.jar などと同じディレクトリです。

-Djava.library.path=./lib:/home/bitwalk/R/x86_64-redhat-linux-gnu-library/3.1/rJava/jri

サンプルの実行結果は、もちろん 6.0 です。もう少し使い込んで、機会があれば、より具体的なサンプルを紹介したいと考えています。

参考サイト

  1. RとJava - RjpWiki
  2. JavaからR言語を呼び出せる環境の構築 - Qiita
  3. Overview RoSuDA R packages API

2014-09-09

NatTable(2)

大きなファイルを読み込んでみたくて、前回のサンプルをベースに、むりやりファイルを読み込む処理を付け足して、大きめのサイズ(48MB 強)の HTML のテーブルを読み込ませてみました。

例に示した読み込むファイルの拡張子は、.xls になっていますが、中身は HTML です。ただし、読み込む形式が判っているので、汎用のパーサーを用いずに、一行ずつ読み込んで専用の処理をしています。このファイルはあるシステムが吐き出すログなのですが、詳細な説明は割愛します。

List: NatTableSample002.java
/*******************************************************************************
 * Copyright (c) 2012 Original authors and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Original authors and others - initial API and implementation
 ******************************************************************************/
// modified by Fuhito Suguri, 9-Sep-2014
package nattablesample;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

public class NatTableSample002 extends ApplicationWindow {
    private IDataProvider bodyDataProvider;
    private BodyLayerStack bodyLayer;

    private String[] propertyNames;
    private Map<String, String> propertyToLabels;

    public NatTableSample002() {
        super(null);
    }

    @Override
    protected Control createContents(Composite parent) {
        parent.setSize(400, 200);
        FillLayout layout = new FillLayout(SWT.HORIZONTAL | SWT.VERTICAL);

        // Body Layer
        bodyDataProvider = setupBodyDataProvider();
        bodyLayer = new BodyLayerStack(bodyDataProvider);

        // Column Layer
        DefaultColumnHeaderDataProvider colHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabels);
        ColumnHeaderLayerStack columnHeaderLayer = new ColumnHeaderLayerStack(colHeaderDataProvider);

        // Row Layer
        DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);
        RowHeaderLayerStack rowHeaderLayer = new RowHeaderLayerStack(rowHeaderDataProvider);

        // Corner Layer
        DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(colHeaderDataProvider, rowHeaderDataProvider);
        CornerLayer cornerLayer = new CornerLayer(new DataLayer(cornerDataProvider), rowHeaderLayer, columnHeaderLayer);

        // Grid Layer
        GridLayer gridLayer = new GridLayer(bodyLayer, columnHeaderLayer, rowHeaderLayer, cornerLayer);

        NatTable natTable = new NatTable(parent, gridLayer);

        natTable.setLayout(layout);
        return natTable;
    }

    // setupBodyDataProvider
    private IDataProvider setupBodyDataProvider() {
        String fileName = "/home/bitwalk/ドキュメント/myExcel.xls";

        propertyToLabels = new HashMap<String, String>();
        propertyToLabels.put("lictype", "ライセンス タイプ");
        propertyToLabels.put("monthdate", "月の日");
        propertyToLabels.put("userid", "ユーザーID");
        propertyToLabels.put("site", "サイト");
        propertyToLabels.put("available", "アベイラビリティ");
        propertyToLabels.put("percentused", "パーセント使用");
        propertyToLabels.put("start", "開始");
        propertyToLabels.put("end", "終了");

        propertyNames = new String[] { "lictype", "monthdate", "userid", "site", "available", "percentused", "start", "end" };

        List<LicData> licUsage = new ArrayList<LicData>();
        try {
            File file = new File(fileName);

            if (checkBeforeReadfile(file)) {
                BufferedReader br = new BufferedReader(new FileReader(file));

                String str;
                String[] elem = new String[8];
                int counter = 0;

                while ((str = br.readLine()) != null) {
                    String line = str.trim();

                    if (line.length() == 0) {
                        continue;
                    }
                    if (line.equals("<tr>")) {
                        counter = 0;
                        continue;
                    }
                    if (line.equals("</tr>")) {
                        licUsage.add(new LicData(elem[0], elem[1], elem[2], elem[3], elem[4], elem[5], elem[6], elem[7]));
                        continue;
                    }
                    if (line.startsWith("<td>")) {
                        int lLength = line.length();
                        elem[counter] = new String(line.substring(4,
                                lLength - 5));
                        counter++;
                    }
                }

                br.close();
            } else {
                System.out.println("Can not find or can not open the file!");
            }
        } catch (FileNotFoundException e) {
            System.out.println(e);
        } catch (IOException e) {
            System.out.println(e);
        }

        return new ListDataProvider<LicData>(licUsage, new ReflectiveColumnPropertyAccessor<LicData>(propertyNames));
    }

    private static boolean checkBeforeReadfile(File file) {
        if (file.exists()) {
            if (file.isFile() && file.canRead()) {
                return true;
            }
        }
        return false;
    }

    // row structure of license usage data
    public class LicData {
        private String lictype;
        private String monthdate;
        private String userid;
        private String site;
        private String available;
        private String percentused;
        private String start;
        private String end;

        public LicData(String lictype, String monthdate, String userid,
                String site, String available, String percentused,
                String start, String end) {
            this.lictype = lictype;
            this.monthdate = monthdate;
            this.userid = userid;
            this.site = site;
            this.available = available;
            this.percentused = percentused;
            this.start = start;
            this.end = end;
        }

        public String getLictype() {
            return lictype;
        }

        public String getMonthdate() {
            return monthdate;
        }

        public String getUserid() {
            return userid;
        }

        public String getSite() {
            return site;
        }

        public String getAvailable() {
            return available;
        }

        public String getPercentused() {
            return percentused;
        }

        public String getStart() {
            return start;
        }

        public String getEnd() {
            return end;
        }

    }

    // class BodyLayerStack
    public class BodyLayerStack extends AbstractLayerTransform {
        private SelectionLayer selectionLayer;

        public BodyLayerStack(IDataProvider dataProvider) {
            DataLayer bodyDataLayer = new DataLayer(dataProvider);
            ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(bodyDataLayer);
            ColumnHideShowLayer columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
            selectionLayer = new SelectionLayer(columnHideShowLayer);
            ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
            setUnderlyingLayer(viewportLayer);
        }

        public SelectionLayer getSelectionLayer() {
            return selectionLayer;
        }
    }

    // class ColumnHeaderLayerStack
    public class ColumnHeaderLayerStack extends AbstractLayerTransform {
        public ColumnHeaderLayerStack(IDataProvider dataProvider) {
            DataLayer dataLayer = new DataLayer(dataProvider);
            ColumnHeaderLayer colHeaderLayer = new ColumnHeaderLayer(dataLayer, bodyLayer, bodyLayer.getSelectionLayer());
            setUnderlyingLayer(colHeaderLayer);
        }
    }

    // class RowHeaderLayerStack
    public class RowHeaderLayerStack extends AbstractLayerTransform {
        public RowHeaderLayerStack(IDataProvider dataProvider) {
            DataLayer dataLayer = new DataLayer(dataProvider, 100, 20);
            RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(dataLayer, bodyLayer, bodyLayer.getSelectionLayer());
            setUnderlyingLayer(rowHeaderLayer);
        }
    }

    public static void main(String[] args) {
        NatTableSample002 w = new NatTableSample002();
        w.setBlockOnOpen(true);
        w.open();
        Display.getCurrent().dispose();
    }
}

実行例

79,446 行というのは、Excel で扱えない行数では決してありませんが、こんなに簡単に読み込めるんだということでオドロキです。もっとも読み込み速度が速いのは、単純にファイルの読み込み処理を特化しているせいなのでしょう。

定型のデータを読み込ませる場合は、このようなやり方で良いのですが、汎用目的に読み込むためにどうするのか、調べる必要があります。

参考サイト

  1. テキストファイルを読む - テキストファイルの入出力 - Java入門

2014-09-07

NatTable (1)

NatTable のサンプルを備忘録として掲載していきます。最初のうちは NatTable のサンプルを転用したものからはじめていきます。いまのところ、人様に対して詳細な解説を加えられるレベルまで理解が追いついていません。ひたすらサンプルを積み重ねて行きます。

Eclipse (LUNA 4.4.0 on CentOS 7) で使用したライブラリは以下の通りです。

今回は、NatTable のサンプル _001_Getting_Started.javaPerson.java をベースにしました。

List: NatTableSample001.java
/*******************************************************************************
 * Copyright (c) 2012 Original authors and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Original authors and others - initial API and implementation
 ******************************************************************************/
// modified by Fuhito Suguri, 7-Sep-2014
package nattablesample;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ReflectiveColumnPropertyAccessor;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
import org.eclipse.nebula.widgets.nattable.hideshow.ColumnHideShowLayer;
import org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.reorder.ColumnReorderLayer;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

public class NatTableSample001 extends ApplicationWindow {
    private IDataProvider bodyDataProvider;
    private String[] propertyNames;
    private BodyLayerStack bodyLayer;
    private Map<String, String> propertyToLabels;

    public NatTableSample001() {
        super(null);
    }

    @Override
    protected Control createContents(Composite parent) {
        parent.setSize(400, 200);

        bodyDataProvider = setupBodyDataProvider();
        DefaultColumnHeaderDataProvider colHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabels);
        DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);

        bodyLayer = new BodyLayerStack(bodyDataProvider);
        ColumnHeaderLayerStack columnHeaderLayer = new ColumnHeaderLayerStack(colHeaderDataProvider);
        RowHeaderLayerStack rowHeaderLayer = new RowHeaderLayerStack(rowHeaderDataProvider);
        DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(colHeaderDataProvider, rowHeaderDataProvider);
        CornerLayer cornerLayer = new CornerLayer(new DataLayer(cornerDataProvider), rowHeaderLayer, columnHeaderLayer);

        GridLayer gridLayer = new GridLayer(bodyLayer, columnHeaderLayer, rowHeaderLayer, cornerLayer);
        NatTable natTable = new NatTable(parent, gridLayer);

        return natTable;
    }

    private IDataProvider setupBodyDataProvider() {
        final List<BoyName> people = Arrays.asList(
                new BoyName(1, "悠真", 0.73),
                new BoyName(2, "陽翔", 0.64),
                new BoyName(3, "蓮", 0.52),
                new BoyName(4, "大翔", 0.51),
                new BoyName(4, "湊", 0.51));

        propertyToLabels = new HashMap<String, String>();
        propertyToLabels.put("rank", "順位");
        propertyToLabels.put("name", "名前");
        propertyToLabels.put("ratio", "占率");

        propertyNames = new String[] { "rank", "name", "ratio" };
        return new ListDataProvider<BoyName>(people, new ReflectiveColumnPropertyAccessor<BoyName>(propertyNames));
    }

    public class BodyLayerStack extends AbstractLayerTransform {
        private SelectionLayer selectionLayer;

        public BodyLayerStack(IDataProvider dataProvider) {
            DataLayer bodyDataLayer = new DataLayer(dataProvider);
            ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(bodyDataLayer);
            ColumnHideShowLayer columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
            selectionLayer = new SelectionLayer(columnHideShowLayer);
            ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
            setUnderlyingLayer(viewportLayer);
        }

        public SelectionLayer getSelectionLayer() {
            return selectionLayer;
        }
    }

    public class ColumnHeaderLayerStack extends AbstractLayerTransform {
        public ColumnHeaderLayerStack(IDataProvider dataProvider) {
            DataLayer dataLayer = new DataLayer(dataProvider);
            ColumnHeaderLayer colHeaderLayer = new ColumnHeaderLayer(dataLayer, bodyLayer, bodyLayer.getSelectionLayer());
            setUnderlyingLayer(colHeaderLayer);
        }
    }

    public class RowHeaderLayerStack extends AbstractLayerTransform {
        public RowHeaderLayerStack(IDataProvider dataProvider) {
            DataLayer dataLayer = new DataLayer(dataProvider, 30, 20);
            RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(dataLayer, bodyLayer, bodyLayer.getSelectionLayer());
            setUnderlyingLayer(rowHeaderLayer);
        }
    }

    public class BoyName {
        private int rank;
        private String name;
        private double ratio;

        public BoyName(int rank, String name, double ratio) {
            this.rank = rank;
            this.name = name;
            this.ratio = ratio;
        }

        public int getRank() {
            return rank;
        }

        public String getName() {
            return name;
        }

        public double getRatio() {
            return ratio;
        }
    }

    public static void main(String[] args) {
        NatTableSample001 w = new NatTableSample001();
        w.setBlockOnOpen(true);
        w.open();
        Display.getCurrent().dispose();
    }
}

実行例

参考サイト

  1. 明治安田生命 | 名前ランキング2013 - 名前ベスト100 - 男の子

2014-09-06

JFace について

NatTable 1. は、大きなデータセットを扱うことが出来る SWT 2. の table/grid ウィジェットです。データ解析のアプリケーションを作るにあたって、まさに求めていたワークシート状ウィジェットを実現できるライブラリに巡り会えたと思い、先月の夏休みに使いこなせるようになろうと、まずは SWT によるプログラミングをなんとかおぼえました。

しかし、NatTable のサンプルは JFace 3. を利用していて、生半可な SWT の知識だけでは、残念ながらサンプルをベースにしても NatTable を満足に使いこなせるようになるには至りませんでした。

夏休み後も JFace について調べているなかで、古い記事ではありますが、以下の記事がとても判りやすかったので紹介します。

上記の記事は Windows 上でアプリケーションを動作させることを想定していましたが、トップディレクトリの指定を Linux に合うように書き替えただけで問題なく動作しました。

10 年以上前の記事をありがたがって読まなければならないということは、それだけ自分が時流から取り残されていることを認識しないわけにはいきません。でも、遅れていれば追いつけば良いのです。とにかくこれで、NatTable を使いこなす足掛かりができたように思います。

参考サイト

  1. Nebula NatTable
  2. SWT: The Standard Widget Toolkit
  3. JFace - Eclipsepedia