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-20

Firefox ESR と Firefox OS Simulator

CentOS 7 に収録されている Firefox は、延長サポート版 (ESR: Extended Support Release) になっています。

CentOS 7 がリリースされた当初は Firefox 24.5 が収録されていて、Firefox OS Simulator を試すことができませんでした。その後、24.8 までアップデートされましたが、Firefox OS Simulator が使えない状況は(もちろん)変わりませんでした。

CentOS はそもそも Linux の開発者向けのディストリビューションではなく、エンタープライズ向けの OS であるので、ブラウザに Firefox ESR が採用されているのはもっともな事で、Firefox OS Simulator をそのままでは利用できないのは暫くは仕方がないと諦めていました。

ところが、昨日の CentOS 7 のアップデートで Firefox はようやく次のバージョンの 31.1 へ移りました。

ということで、早速 Firefox OS Simulator を使ってみることに…。いつのまにか入手可能な最新の Firefox OS のバージョンは 2.2 になっていました。

Firefox OS 2.2 からではないのかもしれませんが、日本語がサポートされていました。画面構成もなんか変わっています。画面操作も全体的に横方向ははなく縦方向主体に変わったような…。

世の中は iPhone 6 で騒がれていますが、私は au から Firefox OS 搭載のスマートフォンが早く発売されないかと辛抱強く待っています。

関連記事

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

2014-08-31

あいらんど運営情報: あいらんど閉鎖について

1 年ぐらい前に、個人のサイトを Sitemix の Workshop Complex at bitWalk から、あいらんどの bitWalk's workshop へ引っ越したのですが、2014 年 8 月末をもって閉鎖するというアナウンスが出ていることに、お盆休み明けに気が付きました。なんだかあまり活用しないうちに閉鎖になってしまいました。

仕方がないので、今度は XREA.COM に bitWalk's workshop のサイトを準備しました。構成はこれから考えます。

参考サイト

2014-08-29

モジラ、3400円の格安スマホ投入へ―幹部インタビュー - WSJ

Firefox OS というと格安スマホの代名詞になりつつあるような気がしますが、兎に角、普及しないことには発展はありません。モジラは26日、インドの携帯電話販売会社インテックス・テクノロジーズ・インディアと共同で、格安スマホ「インテックス・クラウド FX (Intex Cloud FX)」を発売すると発表しました。

  1. モジラ、3400円の格安スマホ投入へ―幹部インタビュー - WSJ

インド訛りの英語ですが、参考まで。

2014-08-24

Red Hat Enterprise Linux 7がやってきた[起動処理編] - 第3回 systemdの基本操作:ITpro

Systemd が Fedora に導入されたのは 2011 年 5 月 24 日にリリースされ Fedora 15 の時ですから、先日リリースされた RHL 7 / Cent OS 7 に systemd が採用されたからと言って、自分にとって真新しいものはないはずです。しかし、マジメに systemd を勉強してこなかったので、引用サイト 1. を読み、自分の環境 (Cent OS 7) での使用例をまとめました。例に取り上げているサービスは httpd です。

systemctl コマンドで現在有効な Unit を一覧する場合

# systemctl --type=service --no-pager
UNIT                         LOAD   ACTIVE SUB     DESCRIPTION
abrt-ccpp.service            loaded active exited  Install ABRT coredump hook
abrt-oops.service            loaded active running ABRT kernel log watcher
abrt-xorg.service            loaded active running ABRT Xorg log watcher
abrtd.service                loaded active running ABRT Automated Bug Reporting 
...
(省略)
...
udisks2.service              loaded active running Disk Manager
upower.service               loaded active running Daemon for power management

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

73 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
# 

定義されているすべてのサービスを確認する場合

# systemctl list-unit-files --type=service --no-pager
UNIT FILE                                   STATE   
abrt-ccpp.service                           enabled
abrt-oops.service                           enabled
abrt-pstoreoops.service                     disabled
abrt-vmcore.service                         enabled 
...
(省略)
...
vmtoolsd.service                            enabled 
wacom-inputattach@.service                  static  
wpa_supplicant.service                      disabled

251 unit files listed.
# 

HTTP デーモンを起動する Unit である httpd.service について、自動起動を有効化/無効化する場合

# systemctl enable httpd.service
ln -s '/usr/lib/systemd/system/httpd.service' '/etc/systemd/system/multi-user.target.wants/httpd.service'
# systemctl disable httpd.service
rm '/etc/systemd/system/multi-user.target.wants/httpd.service'

システム起動後に手動で起動/停止/再起動する場合

# systemctl start httpd.service 
# systemctl stop httpd.service 
# systemctl restart httpd.service 

httpd.service」の稼働状態を表示する例

# systemctl status httpd.service
httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled)
   Active: active (running) since 月 2014-08-25 13:18:04 JST; 15s ago
  Process: 5654 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited, status=0/SUCCESS)
 Main PID: 5659 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─5659 /usr/sbin/httpd -DFOREGROUND
           ├─5660 /usr/libexec/nss_pcache 1277958 off /etc/httpd/alias
           ├─5661 /usr/sbin/httpd -DFOREGROUND
           ├─5662 /usr/sbin/httpd -DFOREGROUND
           ├─5663 /usr/sbin/httpd -DFOREGROUND
           ├─5664 /usr/sbin/httpd -DFOREGROUND
           ├─5665 /usr/sbin/httpd -DFOREGROUND
           └─5666 /usr/sbin/httpd -DFOREGROUND

 8月 25 13:18:03 localhost.localdomain httpd[5659]: AH00558: httpd: Could no...
 8月 25 13:18:04 localhost.localdomain systemd[1]: Started The Apache HTTP S...
Hint: Some lines were ellipsized, use -l to show in full.
# 

journald によるログの表示

# journalctl -u httpd.service -a --no-pager
-- Logs begin at 月 2014-08-25 12:30:25 JST, end at 月 2014-08-25 13:20:01 JST. --
 8月 25 12:31:14 localhost.localdomain systemd[1]: Starting The Apache HTTP Server...
 8月 25 12:31:15 localhost.localdomain httpd[1212]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using localhost.localdomain. Set the 'ServerName' directive globally to suppress this message
 8月 25 12:31:16 localhost.localdomain systemd[1]: Started The Apache HTTP Server.
 8月 25 13:15:48 localhost.localdomain systemd[1]: Started The Apache HTTP Server.
 8月 25 13:15:55 localhost.localdomain systemd[1]: Stopping The Apache HTTP Server...
...
(省略)
...

引用サイト

  1. Red Hat Enterprise Linux 7がやってきた[起動処理編] - 第3回 systemdの基本操作:ITpro